From 6b55adcdd9c735f310ed05ae5a7a53c92983c0af Mon Sep 17 00:00:00 2001 From: Regalis11 Date: Wed, 20 Jul 2022 18:47:07 +0300 Subject: [PATCH 01/11] v0.19.0.0 (unstable) --- .../ClientSource/CameraTransition.cs | 2 +- .../Characters/AI/EnemyAIController.cs | 5 + .../Characters/Animation/Ragdoll.cs | 91 +++-- .../ClientSource/Characters/Character.cs | 38 +- .../ClientSource/Characters/CharacterHUD.cs | 22 +- .../ClientSource/Characters/CharacterInfo.cs | 36 +- .../Characters/CharacterNetworking.cs | 37 +- .../Characters/Health/CharacterHealth.cs | 24 +- .../ClientSource/Characters/Limb.cs | 2 +- .../ClientSource/DebugConsole.cs | 63 +++- .../Events/EventActions/ConversationAction.cs | 4 +- .../ClientSource/GUI/CrewManagement.cs | 2 +- .../BarotraumaClient/ClientSource/GUI/GUI.cs | 27 +- .../ClientSource/GUI/GUIContextMenu.cs | 25 +- .../ClientSource/GUI/GUIDragHandle.cs | 75 ++++ .../ClientSource/GUI/GUIListBox.cs | 6 +- .../ClientSource/GUI/GUIMessageBox.cs | 3 +- .../ClientSource/GUI/HUDLayoutSettings.cs | 8 + .../ClientSource/GUI/TabMenu.cs | 235 ++++++------ .../ClientSource/GUI/UpgradeStore.cs | 24 +- .../BarotraumaClient/ClientSource/GameMain.cs | 10 +- .../ClientSource/GameSession/CrewManager.cs | 4 +- .../ClientSource/GameSession/GameMode.cs | 6 +- .../GameModes/MultiPlayerCampaign.cs | 21 +- .../GameModes/SinglePlayerCampaign.cs | 30 +- .../GameModes/Tutorials/CaptainTutorial.cs | 12 +- .../GameModes/Tutorials/DoctorTutorial.cs | 14 +- .../GameModes/Tutorials/EngineerTutorial.cs | 6 +- .../GameModes/Tutorials/MechanicTutorial.cs | 4 +- .../GameModes/Tutorials/OfficerTutorial.cs | 2 +- .../ClientSource/GameSession/GameSession.cs | 8 + .../ClientSource/GameSession/HintManager.cs | 26 +- .../ClientSource/Items/CharacterInventory.cs | 19 +- .../Items/Components/Holdable/IdCard.cs | 5 +- .../Items/Components/ItemComponent.cs | 25 +- .../Items/Components/ItemContainer.cs | 13 +- .../Components/Machines/Deconstructor.cs | 227 ++++++++++-- .../Items/Components/Machines/MiniMap.cs | 1 + .../Components/Machines/OutpostTerminal.cs | 2 +- .../Items/Components/Machines/Steering.cs | 8 +- .../Items/Components/Repairable.cs | 5 +- .../Components/Signal/ConnectionPanel.cs | 14 +- .../Items/Components/Signal/Wire.cs | 2 +- .../ClientSource/Items/Inventory.cs | 49 +-- .../ClientSource/Items/Item.cs | 15 +- .../ClientSource/Items/ItemInventory.cs | 5 +- .../ClientSource/Map/MapEntity.cs | 18 +- .../ClientSource/Networking/GameClient.cs | 6 +- .../Networking/Voip/VoipCapture.cs | 7 +- .../Networking/Voip/VoipClient.cs | 7 +- .../ClientSource/Particles/ParticleManager.cs | 6 +- .../ClientSource/PlayerInput.cs | 4 +- .../ClientSource/Screens/CampaignUI.cs | 186 ---------- .../CharacterEditor/CharacterEditorScreen.cs | 4 +- .../ClientSource/Screens/GameScreen.cs | 49 ++- .../ClientSource/Screens/MainMenuScreen.cs | 9 +- .../ClientSource/Screens/Screen.cs | 4 +- .../ClientSource/Screens/SubEditorScreen.cs | 67 ++-- .../ClientSource/Screens/TestScreen.cs | 57 +-- .../Serialization/SerializableEntityEditor.cs | 4 +- .../ClientSource/Settings/SettingsMenu.cs | 55 ++- .../ClientSource/Sounds/SoundManager.cs | 2 +- .../ClientSource/Sprite/Sprite.cs | 10 +- .../ClientSource/Steam/Lobby.cs | 4 +- .../WorkshopMenu/Mutable/InstalledTab.cs | 5 +- .../Steam/WorkshopMenu/Mutable/ItemList.cs | 3 + .../Mutable/MutableWorkshopMenu.cs | 6 +- .../Utils/LocalizationCSVtoXML.cs | 264 +++++++++----- .../BarotraumaClient/LinuxClient.csproj | 4 +- Barotrauma/BarotraumaClient/MacClient.csproj | 4 +- .../BarotraumaClient/WindowsClient.csproj | 4 +- .../BarotraumaServer/LinuxServer.csproj | 4 +- Barotrauma/BarotraumaServer/MacServer.csproj | 4 +- .../ServerSource/Characters/CharacterInfo.cs | 12 +- .../Characters/CharacterNetworking.cs | 11 +- .../Events/EventActions/ConversationAction.cs | 10 +- .../ServerSource/Events/EventManager.cs | 18 +- .../BarotraumaServer/ServerSource/GameMain.cs | 2 +- .../ServerSource/GameSession/Data/Wallet.cs | 11 + .../GameModes/MultiPlayerCampaign.cs | 21 +- .../ServerSource/Networking/Client.cs | 4 + .../ServerSource/Networking/GameServer.cs | 13 +- .../ServerSource/Networking/KarmaManager.cs | 4 +- .../ServerSource/Networking/RespawnManager.cs | 16 +- .../ServerSource/Networking/Voting.cs | 20 +- .../BarotraumaServer/ServerSource/Program.cs | 6 +- .../BarotraumaServer/WindowsServer.csproj | 4 +- .../ModLists/Release checklist mods.xml | 16 + .../Characters/AI/HumanAIController.cs | 8 +- .../Characters/AI/IndoorsSteeringManager.cs | 98 ++--- .../Characters/AI/NPCConversation.cs | 16 +- .../AI/Objectives/AIObjectiveCombat.cs | 17 + .../AI/Objectives/AIObjectiveGoTo.cs | 9 +- .../AI/Objectives/AIObjectiveIdle.cs | 9 +- .../AI/Objectives/AIObjectiveOperateItem.cs | 2 +- .../AI/Objectives/AIObjectiveRepairItem.cs | 10 +- .../AI/Objectives/AIObjectiveRepairItems.cs | 4 +- .../SharedSource/Characters/AI/PathFinder.cs | 66 +--- .../Characters/AI/SteeringPath.cs | 2 + .../Characters/Animation/AnimController.cs | 56 ++- .../Animation/HumanoidAnimController.cs | 83 +++-- .../Characters/Animation/Ragdoll.cs | 5 +- .../SharedSource/Characters/Character.cs | 342 +++++++++++------- .../Characters/CharacterEventData.cs | 9 + .../SharedSource/Characters/CharacterInfo.cs | 56 ++- .../Characters/CharacterNetworking.cs | 13 +- .../SharedSource/Characters/CorpsePrefab.cs | 2 +- .../Characters/Health/CharacterHealth.cs | 18 +- .../SharedSource/Characters/HumanPrefab.cs | 58 ++- .../SharedSource/Characters/Jobs/Job.cs | 11 +- .../SharedSource/Characters/Jobs/JobPrefab.cs | 2 +- .../SharedSource/Characters/Limb.cs | 11 + .../Characters/NPCPersonalityTrait.cs | 40 +- .../CharacterAbilityTandemFire.cs | 8 +- .../ContentFile/NPCPersonalityTraitsFile.cs | 12 + .../SharedSource/CoroutineManager.cs | 20 +- .../SharedSource/DebugConsole.cs | 53 ++- .../Events/EventActions/ConversationAction.cs | 12 +- .../Events/EventActions/SpawnAction.cs | 2 +- .../Events/EventActions/TriggerAction.cs | 5 +- .../SharedSource/Events/EventManager.cs | 119 +++--- .../SharedSource/Events/EventSet.cs | 26 +- .../Events/Missions/EscortMission.cs | 31 +- .../SharedSource/Events/Missions/Mission.cs | 2 +- .../Events/Missions/MonsterMission.cs | 26 +- .../SharedSource/Events/MonsterEvent.cs | 5 +- .../GameAnalytics/GameAnalyticsManager.cs | 21 +- .../SharedSource/GameSession/CargoManager.cs | 7 +- .../GameSession/Data/CampaignMetadata.cs | 21 +- .../GameSession/GameModes/CampaignMode.cs | 42 ++- .../SharedSource/GameSession/GameSession.cs | 2 +- .../GameSession/UpgradeManager.cs | 16 +- .../SharedSource/InputType.cs | 2 +- .../Items/Components/Holdable/Holdable.cs | 18 + .../Items/Components/Holdable/MeleeWeapon.cs | 18 +- .../Items/Components/Holdable/Pickable.cs | 6 +- .../Items/Components/Holdable/RepairTool.cs | 14 +- .../Items/Components/ItemContainer.cs | 16 +- .../SharedSource/Items/Components/Ladder.cs | 3 +- .../Items/Components/Machines/Controller.cs | 104 +++--- .../Components/Machines/Deconstructor.cs | 9 + .../Items/Components/Machines/Fabricator.cs | 14 +- .../Items/Components/Machines/Reactor.cs | 6 +- .../Items/Components/Machines/Steering.cs | 8 +- .../Items/Components/Power/PowerContainer.cs | 3 - .../Items/Components/Projectile.cs | 15 +- .../SharedSource/Items/Components/Quality.cs | 2 +- .../Items/Components/Repairable.cs | 6 +- .../Components/Signal/ConnectionPanel.cs | 15 +- .../Items/Components/Signal/Terminal.cs | 2 +- .../Items/Components/Signal/Wire.cs | 6 +- .../SharedSource/Items/Components/Turret.cs | 2 +- .../SharedSource/Items/Item.cs | 38 +- .../SharedSource/Map/Levels/Level.cs | 15 +- .../SharedSource/Map/Levels/LevelData.cs | 7 +- .../SharedSource/Map/Map/Map.cs | 7 +- .../SharedSource/Map/Outposts/NPCSet.cs | 2 +- .../Map/Outposts/OutpostGenerationParams.cs | 2 +- .../Map/Outposts/OutpostGenerator.cs | 6 +- .../SharedSource/Map/RoundEndCinematic.cs | 126 ------- .../SharedSource/Map/Submarine.cs | 8 - .../SharedSource/Map/SubmarineBody.cs | 14 +- .../SharedSource/Map/WayPoint.cs | 71 ++-- .../SharedSource/Networking/ServerSettings.cs | 7 + .../SharedSource/Screens/GameScreen.cs | 6 +- .../SharedSource/Screens/Screen.cs | 1 + .../SharedSource/Settings/GameSettings.cs | 27 +- .../StatusEffects/StatusEffect.cs | 84 ++++- Barotrauma/BarotraumaShared/changelog.txt | 107 +++++- .../BarotraumaShared/serversettings.xml | 2 +- 170 files changed, 2769 insertions(+), 1634 deletions(-) create mode 100644 Barotrauma/BarotraumaClient/ClientSource/GUI/GUIDragHandle.cs create mode 100644 Barotrauma/BarotraumaShared/ModLists/Release checklist mods.xml create mode 100644 Barotrauma/BarotraumaShared/SharedSource/ContentManagement/ContentFile/NPCPersonalityTraitsFile.cs delete mode 100644 Barotrauma/BarotraumaShared/SharedSource/Map/RoundEndCinematic.cs diff --git a/Barotrauma/BarotraumaClient/ClientSource/CameraTransition.cs b/Barotrauma/BarotraumaClient/ClientSource/CameraTransition.cs index 77339f0b1..ed7ff67d7 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/CameraTransition.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/CameraTransition.cs @@ -159,7 +159,7 @@ namespace Barotrauma GameMain.LightManager.LosEnabled = true; } #endif - timer += CoroutineManager.UnscaledDeltaTime; + timer += CoroutineManager.DeltaTime; yield return CoroutineStatus.Running; } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Characters/AI/EnemyAIController.cs b/Barotrauma/BarotraumaClient/ClientSource/Characters/AI/EnemyAIController.cs index bfb8b7202..c43d3f26b 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Characters/AI/EnemyAIController.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Characters/AI/EnemyAIController.cs @@ -73,6 +73,11 @@ namespace Barotrauma } GUI.DrawString(spriteBatch, pos - Vector2.UnitY * 80.0f, State.ToString(), stateColor, Color.Black); + if (State == AIState.Attack && selectedTargetingParams != null && selectedTargetingParams.AttackPattern == AttackPattern.Circle) + { + GUI.DrawString(spriteBatch, pos - Vector2.UnitY * 100.0f, CirclePhase.ToString(), stateColor, Color.Black); + } + if (LatchOntoAI != null && (State == AIState.Idle || LatchOntoAI.IsAttachedToSub)) { foreach (Joint attachJoint in LatchOntoAI.AttachJoints) diff --git a/Barotrauma/BarotraumaClient/ClientSource/Characters/Animation/Ragdoll.cs b/Barotrauma/BarotraumaClient/ClientSource/Characters/Animation/Ragdoll.cs index 5e315ee8f..dc50608c8 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Characters/Animation/Ragdoll.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Characters/Animation/Ragdoll.cs @@ -1,15 +1,14 @@ -using Barotrauma.Items.Components; +using Barotrauma.Extensions; +using Barotrauma.Items.Components; +using Barotrauma.Particles; using Barotrauma.SpriteDeformations; -using Barotrauma.Extensions; using FarseerPhysics; using FarseerPhysics.Dynamics; -using FarseerPhysics.Dynamics.Joints; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using System; -using System.Linq; using System.Collections.Generic; -using Barotrauma.Particles; +using System.Linq; namespace Barotrauma { @@ -55,21 +54,34 @@ namespace Barotrauma if (character.MemState[0].SelectedItem == null || character.MemState[0].SelectedItem.Removed) { - character.SelectedConstruction = null; + character.SelectedItem = null; } - else + else if (character.SelectedItem != character.MemState[0].SelectedItem) { - if (character.SelectedConstruction != character.MemState[0].SelectedItem) + foreach (var ic in character.MemState[0].SelectedItem.Components) { - foreach (var ic in character.MemState[0].SelectedItem.Components) + if (ic.CanBeSelected) { - if (ic.CanBeSelected) - { - ic.Select(character); - } + ic.Select(character); } } - character.SelectedConstruction = character.MemState[0].SelectedItem; + character.SelectedItem = character.MemState[0].SelectedItem; + } + + if (character.MemState[0].SelectedSecondaryItem == null || character.MemState[0].SelectedSecondaryItem.Removed) + { + character.SelectedSecondaryItem = null; + } + else if (character.SelectedSecondaryItem != character.MemState[0].SelectedSecondaryItem) + { + foreach (var ic in character.MemState[0].SelectedSecondaryItem.Components) + { + if (ic.CanBeSelected) + { + ic.Select(character); + } + } + character.SelectedSecondaryItem = character.MemState[0].SelectedSecondaryItem; } if (character.MemState[0].Animation == AnimController.Animation.CPR) @@ -201,15 +213,24 @@ namespace Barotrauma { if (serverPos.SelectedItem == null || serverPos.SelectedItem.Removed) { - character.SelectedConstruction = null; + character.SelectedItem = null; } - else if (serverPos.SelectedItem != null) + else if (character.SelectedItem != serverPos.SelectedItem) { - if (character.SelectedConstruction != serverPos.SelectedItem) - { - serverPos.SelectedItem.TryInteract(character, ignoreRequiredItems: true, forceSelectKey: true); - } - character.SelectedConstruction = serverPos.SelectedItem; + serverPos.SelectedItem.TryInteract(character, ignoreRequiredItems: true, forceSelectKey: true); + character.SelectedItem = serverPos.SelectedItem; + } + } + if (localPos.SelectedSecondaryItem != serverPos.SelectedSecondaryItem) + { + if (serverPos.SelectedSecondaryItem == null || serverPos.SelectedSecondaryItem.Removed) + { + character.SelectedSecondaryItem = null; + } + else if (character.SelectedSecondaryItem != serverPos.SelectedSecondaryItem) + { + serverPos.SelectedSecondaryItem.TryInteract(character, ignoreRequiredItems: true, forceSelectKey: true); + character.SelectedSecondaryItem = serverPos.SelectedSecondaryItem; } } @@ -496,12 +517,11 @@ namespace Barotrauma float maxDepth = 0.0f; float minDepth = 1.0f; float depthOffset = 0.0f; - var ladder = character.SelectedConstruction?.GetComponent(); - - if (ladder != null) + + if (character.SelectedSecondaryItem?.GetComponent() is Ladder ladder) { CalculateLimbDepths(); - if (character.WorldPosition.X < character.SelectedConstruction.WorldPosition.X) + if (character.WorldPosition.X < character.SelectedSecondaryItem.WorldPosition.X) { //at the left side of the ladder, needs to be drawn in front of the rungs if (maxDepth > ladder.BackgroundSpriteDepth) @@ -522,16 +542,21 @@ namespace Barotrauma else { CalculateLimbDepths(); - var controller = character.SelectedConstruction?.GetComponent(); - if (controller != null && controller.ControlCharacterPose && controller.User == character && controller.UserInCorrectPosition) + AdjustDepthOffset(character.SelectedItem); + AdjustDepthOffset(character.SelectedSecondaryItem); + + void AdjustDepthOffset(Item item) { - if (controller.Item.SpriteDepth <= maxDepth || controller.DrawUserBehind) + if (item?.GetComponent() is { ControlCharacterPose: true, UserInCorrectPosition: true } controller && controller.User == character) { - depthOffset = Math.Max(controller.Item.GetDrawDepth() + 0.0001f - minDepth, -minDepth); - } - else - { - depthOffset = Math.Max(controller.Item.GetDrawDepth() - 0.0001f - maxDepth, 0.0f); + if (controller.Item.SpriteDepth <= maxDepth || controller.DrawUserBehind) + { + depthOffset = Math.Max(controller.Item.GetDrawDepth() + 0.0001f - minDepth, -minDepth); + } + else + { + depthOffset = Math.Max(controller.Item.GetDrawDepth() - 0.0001f - maxDepth, 0.0f); + } } } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Characters/Character.cs b/Barotrauma/BarotraumaClient/ClientSource/Characters/Character.cs index 3c015ee76..99557594c 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Characters/Character.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Characters/Character.cs @@ -9,7 +9,6 @@ using Microsoft.Xna.Framework.Graphics; using System; using System.Collections.Generic; using System.Linq; -using System.Xml.Linq; using Barotrauma.Extensions; namespace Barotrauma @@ -323,8 +322,8 @@ namespace Barotrauma { cam.OffsetAmount = targetOffsetAmount = item.Prefab.OffsetOnSelected * item.OffsetOnSelectedMultiplier; } - else if (SelectedConstruction != null && ViewTarget == null && - SelectedConstruction.Components.Any(ic => ic?.GuiFrame != null && ic.ShouldDrawHUD(this))) + else if (SelectedItem != null && ViewTarget == null && + SelectedItem.Components.Any(ic => ic?.GuiFrame != null && ic.ShouldDrawHUD(this))) { cam.OffsetAmount = targetOffsetAmount = 0.0f; cursorPosition = @@ -368,21 +367,20 @@ namespace Barotrauma if (!GUI.InputBlockingMenuOpen) { - if (SelectedConstruction != null && - (SelectedConstruction.ActiveHUDs.Any(ic => ic.GuiFrame != null && HUD.CloseHUD(ic.GuiFrame.Rect)) || + if (SelectedItem != null && + (SelectedItem.ActiveHUDs.Any(ic => ic.GuiFrame != null && HUD.CloseHUD(ic.GuiFrame.Rect)) || ((ViewTarget as Item)?.Prefab.FocusOnSelected ?? false) && PlayerInput.KeyHit(Microsoft.Xna.Framework.Input.Keys.Escape))) { if (GameMain.Client != null) { - //emulate a Select input to get the character to deselect the item server-side - //keys[(int)InputType.Select].Hit = true; - keys[(int)InputType.Deselect].Hit = true; + //emulate a Deselect input to get the character to deselect the item server-side + EmulateInput(InputType.Deselect); } //reset focus to prevent us from accidentally interacting with another entity focusedItem = null; FocusedCharacter = null; findFocusedTimer = 0.2f; - SelectedConstruction = null; + SelectedItem = null; } } @@ -425,6 +423,11 @@ namespace Barotrauma } } } + + public void EmulateInput(InputType input) + { + keys[(int)input].Hit = true; + } partial void OnAttackedProjSpecific(Character attacker, AttackResult attackResult, float stun) { @@ -518,7 +521,7 @@ namespace Barotrauma //reduce the amount of aim assist if an item has been selected //= can't switch selection to another item without deselecting the current one first UNLESS the cursor is directly on the item //otherwise it would be too easy to accidentally switch the selected item when rewiring items - float aimAssistAmount = SelectedConstruction == null ? 100.0f * aimAssistModifier : 1.0f; + float aimAssistAmount = SelectedItem == null ? 100.0f * aimAssistModifier : 1.0f; Vector2 displayPosition = ConvertUnits.ToDisplayUnits(simPosition); @@ -623,12 +626,12 @@ namespace Barotrauma { if (this != controlled) { return false; } if (GameMain.GameSession?.Campaign != null && GameMain.GameSession.Campaign.ShowCampaignUI) { return true; } - var controller = SelectedConstruction?.GetComponent(); + var controller = SelectedItem?.GetComponent(); //lock if using a controller, except if we're also using a connection panel in the same item return - SelectedConstruction != null && + SelectedItem != null && controller?.User == this && controller.HideHUD && - SelectedConstruction?.GetComponent()?.User != this; + SelectedItem?.GetComponent()?.User != this; } @@ -900,7 +903,14 @@ namespace Barotrauma if (info != null) { LocalizedString name = Info.DisplayName; - if (controlled == null && name != Info.Name) { name += " " + TextManager.Get("Disguised"); } + if (controlled == null && name != Info.Name) + { + name += " " + TextManager.Get("Disguised"); + } + else if (Info.Title != null) + { + name += '\n' + Info.Title; + } Vector2 nameSize = GUIStyle.Font.MeasureString(name); Vector2 namePos = new Vector2(pos.X, pos.Y - 10.0f - (5.0f / cam.Zoom)) - nameSize * 0.5f / cam.Zoom; diff --git a/Barotrauma/BarotraumaClient/ClientSource/Characters/CharacterHUD.cs b/Barotrauma/BarotraumaClient/ClientSource/Characters/CharacterHUD.cs index 02e09c587..323184f04 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Characters/CharacterHUD.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Characters/CharacterHUD.cs @@ -108,7 +108,7 @@ namespace Barotrauma private static bool ShouldDrawInventory(Character character) { - var controller = character.SelectedConstruction?.GetComponent(); + var controller = character.SelectedItem?.GetComponent(); return character?.Inventory != null && @@ -417,13 +417,17 @@ namespace Barotrauma visibleRange = new Range(-100f, 500f); } + float dist = Vector2.Distance(character.WorldPosition, npc.WorldPosition); + float distFactor = 1.0f - MathUtils.InverseLerp(1000.0f, 3000.0f, dist); + float alpha = MathHelper.Lerp(0.3f, 1.0f, distFactor); GUI.DrawIndicator( spriteBatch, npc.WorldPosition, cam, visibleRange, iconStyle.GetDefaultSprite(), - iconStyle.Color); + iconStyle.Color * alpha, + label: npc.Info?.Title); } foreach (Item item in Item.ItemList) @@ -436,10 +440,10 @@ namespace Barotrauma } } - if (character.SelectedConstruction != null && - (character.CanInteractWith(character.SelectedConstruction) || Screen.Selected == GameMain.SubEditorScreen)) + if (character.SelectedItem != null && + (character.CanInteractWith(character.SelectedItem) || Screen.Selected == GameMain.SubEditorScreen)) { - character.SelectedConstruction.DrawHUD(spriteBatch, cam, character); + character.SelectedItem.DrawHUD(spriteBatch, cam, character); } if (character.Inventory != null) { @@ -561,9 +565,15 @@ namespace Barotrauma Color nameColor = character.FocusedCharacter.GetNameColor(); GUI.DrawString(spriteBatch, textPos, focusName, nameColor, Color.Black * 0.7f, 2, GUIStyle.SubHeadingFont, ForceUpperCase.No); - textPos.X += 10.0f * GUI.Scale; textPos.Y += GUIStyle.SubHeadingFont.MeasureString(focusName).Y; + if (character.FocusedCharacter.Info?.Title != null && !character.FocusedCharacter.Info.Title.IsNullOrEmpty()) + { + GUI.DrawString(spriteBatch, textPos, character.FocusedCharacter.Info.Title, nameColor, Color.Black * 0.7f, 2, GUIStyle.SubHeadingFont, ForceUpperCase.No); + textPos.Y += GUIStyle.SubHeadingFont.MeasureString(character.FocusedCharacter.Info.Title.Value).Y; + } + textPos.X += 10.0f * GUI.Scale; + if (!character.FocusedCharacter.IsIncapacitated && character.FocusedCharacter.IsPet) { GUI.DrawString(spriteBatch, textPos, GetCachedHudText("PlayHint", InputType.Use), diff --git a/Barotrauma/BarotraumaClient/ClientSource/Characters/CharacterInfo.cs b/Barotrauma/BarotraumaClient/ClientSource/Characters/CharacterInfo.cs index 305031f47..290746f93 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Characters/CharacterInfo.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Characters/CharacterInfo.cs @@ -102,7 +102,7 @@ namespace Barotrauma if (PersonalityTrait != null) { new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), headerTextArea.RectTransform), - TextManager.AddPunctuation(':', TextManager.Get("PersonalityTrait"), TextManager.Get("personalitytrait." + PersonalityTrait.Name.Replace(" ".ToIdentifier(), "".ToIdentifier()))), + TextManager.AddPunctuation(':', TextManager.Get("PersonalityTrait"), PersonalityTrait.DisplayName), font: font) { Padding = Vector4.Zero @@ -523,22 +523,20 @@ namespace Barotrauma Color facialHairColor = inc.ReadColorR8G8B8(); string ragdollFile = inc.ReadString(); - string jobIdentifier = inc.ReadString(); + uint jobIdentifier = inc.ReadUInt32(); int variant = inc.ReadByte(); JobPrefab jobPrefab = null; Dictionary skillLevels = new Dictionary(); - if (!string.IsNullOrEmpty(jobIdentifier)) - { - jobPrefab = JobPrefab.Get(jobIdentifier); - byte skillCount = inc.ReadByte(); - for (int i = 0; i < skillCount; i++) + if (jobIdentifier > 0) + { + jobPrefab = JobPrefab.Prefabs.Find(jp => jp.UintIdentifier == jobIdentifier); + foreach (SkillPrefab skillPrefab in jobPrefab.Skills.OrderBy(s => s.Identifier)) { - Identifier skillIdentifier = inc.ReadIdentifier(); float skillLevel = inc.ReadSingle(); - skillLevels.Add(skillIdentifier, skillLevel); - } - } + skillLevels.Add(skillPrefab.Identifier, skillLevel); + } + } // TODO: animations CharacterInfo ch = new CharacterInfo(speciesName, newName, originalName, jobPrefab, ragdollFile, variant) @@ -777,7 +775,21 @@ namespace Barotrauma createColorSelector($"Customization.{nameof(info.Head.SkinColor)}".ToIdentifier(), info.SkinColors, () => info.Head.SkinColor, (color) => info.Head.SkinColor = color); - +#if DEBUG + new GUIButton(new RectTransform(Vector2.One * 0.12f, + parentComponent.RectTransform, + anchor: Anchor.BottomRight, scaleBasis: ScaleBasis.Smallest) + { RelativeOffset = new Vector2(0.01f, 0.005f) }, style: "SaveButton", color: Color.Magenta) + { + ToolTip = "DEBUG ONLY: copy the character info XML to clipboard", + OnClicked = (button, o) => + { + XElement element = info.Save(null); + Clipboard.SetText(element.ToString()); + return false; + } + }; +#endif RandomizeButton = new GUIButton(new RectTransform(Vector2.One * 0.12f, parentComponent.RectTransform, anchor: Anchor.BottomRight, scaleBasis: ScaleBasis.Smallest) diff --git a/Barotrauma/BarotraumaClient/ClientSource/Characters/CharacterNetworking.cs b/Barotrauma/BarotraumaClient/ClientSource/Characters/CharacterNetworking.cs index 49a1eb6d8..49292f426 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Characters/CharacterNetworking.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Characters/CharacterNetworking.cs @@ -1,5 +1,4 @@ -using Barotrauma.Extensions; -using Barotrauma.Items.Components; +using Barotrauma.Items.Components; using Barotrauma.Networking; using Microsoft.Xna.Framework; using System; @@ -44,7 +43,8 @@ namespace Barotrauma LastNetworkUpdateID, AnimController.TargetDir, SelectedCharacter, - SelectedConstruction, + SelectedItem, + SelectedSecondaryItem, AnimController.Anim); memLocalState.Add(posInfo); @@ -219,15 +219,17 @@ namespace Barotrauma bool entitySelected = msg.ReadBoolean(); Character selectedCharacter = null; - Item selectedItem = null; + Item selectedItem = null, selectedSecondaryItem = null; AnimController.Animation animation = AnimController.Animation.None; if (entitySelected) { ushort characterID = msg.ReadUInt16(); ushort itemID = msg.ReadUInt16(); + ushort secondaryItemID = msg.ReadUInt16(); selectedCharacter = FindEntityByID(characterID) as Character; selectedItem = FindEntityByID(itemID) as Item; + selectedSecondaryItem = FindEntityByID(secondaryItemID) as Item; if (characterID != NullEntityID) { bool doingCpr = msg.ReadBoolean(); @@ -274,7 +276,7 @@ namespace Barotrauma pos, rotation, networkUpdateID, facingRight ? Direction.Right : Direction.Left, - selectedCharacter, selectedItem, animation); + selectedCharacter, selectedItem, selectedSecondaryItem, animation); while (index < memState.Count && NetIdUtils.IdMoreRecent(posInfo.ID, memState[index].ID)) index++; @@ -286,7 +288,7 @@ namespace Barotrauma pos, rotation, linearVelocity, angularVelocity, sendingTime, facingRight ? Direction.Right : Direction.Left, - selectedCharacter, selectedItem, animation); + selectedCharacter, selectedItem, selectedSecondaryItem, animation); while (index < memState.Count && posInfo.Timestamp > memState[index].Timestamp) index++; @@ -375,9 +377,15 @@ namespace Barotrauma if (attackLimbIndex == 255 || Removed) { break; } if (attackLimbIndex >= AnimController.Limbs.Length) { - string errorMsg = $"Received invalid {(eventType == EventType.SetAttackTarget ? "SetAttackTarget" : "ExecuteAttack")} message. Limb index out of bounds (character: {Name}, limb index: {attackLimbIndex}, limb count: {AnimController.Limbs.Length})"; - DebugConsole.ThrowError(errorMsg); - GameAnalyticsManager.AddErrorEventOnce("Character.ClientEventRead:AttackLimbOutOfBounds", GameAnalyticsManager.ErrorSeverity.Error, errorMsg); + //it's possible to get these errors when mid-round syncing, as the client may not + //yet know about afflictions that have given the character extra limbs (e.g. spineling genes) + //ignoring the error should be safe though, not executing the attack should not cause any further issues + if (!GameMain.Client.MidRoundSyncing) + { + string errorMsg = $"Received invalid {(eventType == EventType.SetAttackTarget ? "SetAttackTarget" : "ExecuteAttack")} message. Limb index out of bounds (character: {Name}, limb index: {attackLimbIndex}, limb count: {AnimController.Limbs.Length})"; + DebugConsole.ThrowError(errorMsg); + GameAnalyticsManager.AddErrorEventOnce("Character.ClientEventRead:AttackLimbOutOfBounds", GameAnalyticsManager.ErrorSeverity.Error, errorMsg); + } break; } Limb attackLimb = AnimController.Limbs[attackLimbIndex]; @@ -673,16 +681,17 @@ namespace Barotrauma AfflictionPrefab causeOfDeathAffliction = null; if (causeOfDeathType == CauseOfDeathType.Affliction) { - string afflictionName = msg.ReadString(); - if (!AfflictionPrefab.Prefabs.ContainsKey(afflictionName)) + uint afflictionId = msg.ReadUInt32(); + AfflictionPrefab afflictionPrefab = AfflictionPrefab.Prefabs.Find(p => p.UintIdentifier == afflictionId); + if (afflictionPrefab == null) { - string errorMsg = $"Error in CharacterNetworking.ReadStatus: affliction not found ({afflictionName})"; + string errorMsg = $"Error in CharacterNetworking.ReadStatus: affliction not found (id {afflictionId})"; causeOfDeathType = CauseOfDeathType.Unknown; - GameAnalyticsManager.AddErrorEventOnce("CharacterNetworking.ReadStatus:AfflictionIndexOutOfBounts", GameAnalyticsManager.ErrorSeverity.Error, errorMsg); + GameAnalyticsManager.AddErrorEventOnce("CharacterNetworking.ReadStatus:AfflictionNotFound", GameAnalyticsManager.ErrorSeverity.Error, errorMsg); } else { - causeOfDeathAffliction = AfflictionPrefab.Prefabs[afflictionName]; + causeOfDeathAffliction = afflictionPrefab; } } bool containsAfflictionData = msg.ReadBoolean(); diff --git a/Barotrauma/BarotraumaClient/ClientSource/Characters/Health/CharacterHealth.cs b/Barotrauma/BarotraumaClient/ClientSource/Characters/Health/CharacterHealth.cs index 48e87f489..19dbd141f 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Characters/Health/CharacterHealth.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Characters/Health/CharacterHealth.cs @@ -162,11 +162,7 @@ namespace Barotrauma openHealthWindow.characterName.Text = value.Character.Info.DisplayName; value.Character.Info.CheckDisguiseStatus(false); } - - if (Character.Controlled.SelectedConstruction != null && Character.Controlled.SelectedConstruction.GetComponent() == null) - { - Character.Controlled.SelectedConstruction = null; - } + Character.Controlled.SelectedItem = null; } HintManager.OnShowHealthInterface(); @@ -724,7 +720,7 @@ namespace Barotrauma //emulate a Health input to get the character to deselect the item server-side if (GameMain.Client != null) { - Character.Controlled.Keys[(int)InputType.Health].Hit = true; + Character.Controlled.EmulateInput(InputType.Health); } OpenHealthWindow = null; } @@ -2014,7 +2010,7 @@ namespace Barotrauma FaceTint = DefaultFaceTint; BodyTint = Color.TransparentBlack; - if (!(Character?.Params?.Health.ApplyAfflictionColors ?? false)) { return; } + if (!Character.Params.Health.ApplyAfflictionColors) { return; } foreach (KeyValuePair kvp in afflictions) { @@ -2031,15 +2027,21 @@ namespace Barotrauma foreach (Limb limb in Character.AnimController.Limbs) { if (limb.HealthIndex < 0 || limb.HealthIndex >= limbHealths.Count) { continue; } - limb.BurnOverlayStrength = 0.0f; limb.DamageOverlayStrength = 0.0f; foreach (KeyValuePair kvp in afflictions) { - if (kvp.Value != limbHealths[limb.HealthIndex]) { continue; } var affliction = kvp.Key; - limb.BurnOverlayStrength += affliction.Strength / Math.Min(affliction.Prefab.MaxStrength, 100) * affliction.Prefab.BurnOverlayAlpha; - limb.DamageOverlayStrength += affliction.Strength / Math.Min(affliction.Prefab.MaxStrength, 100) * affliction.Prefab.DamageOverlayAlpha; + float burnStrength = affliction.Strength / Math.Min(affliction.Prefab.MaxStrength, 100) * affliction.Prefab.BurnOverlayAlpha; + if (kvp.Value == limbHealths[limb.HealthIndex]) + { + limb.BurnOverlayStrength += burnStrength; + limb.DamageOverlayStrength += affliction.Strength / Math.Min(affliction.Prefab.MaxStrength, 100) * affliction.Prefab.DamageOverlayAlpha; + } + else + { + limb.BurnOverlayStrength += burnStrength / 2; + } } } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Characters/Limb.cs b/Barotrauma/BarotraumaClient/ClientSource/Characters/Limb.cs index 7fbcef8fe..4a8c36df7 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Characters/Limb.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Characters/Limb.cs @@ -481,7 +481,7 @@ namespace Barotrauma { ContentPath texturePath = character.Params.VariantFile?.Root?.GetAttributeContentPath("texture", character.Prefab.ContentPackage) - ?? ContentPath.FromRaw(character.Prefab.ContentPackage, spriteParams.GetTexturePath()); + ?? ContentPath.FromRaw(spriteParams.Element.ContentPackage ?? character.Prefab.ContentPackage, spriteParams.GetTexturePath()); path = GetSpritePath(texturePath); } else diff --git a/Barotrauma/BarotraumaClient/ClientSource/DebugConsole.cs b/Barotrauma/BarotraumaClient/ClientSource/DebugConsole.cs index 1bee53b41..2eee53707 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/DebugConsole.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/DebugConsole.cs @@ -1,21 +1,18 @@ -using Barotrauma.Items.Components; +using Barotrauma.ClientSource.Settings; +using Barotrauma.Extensions; +using Barotrauma.IO; +using Barotrauma.Items.Components; +using Barotrauma.MapCreatures.Behavior; using Barotrauma.Networking; +using Barotrauma.Steam; using Microsoft.Xna.Framework; -using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; using System; using System.Collections.Generic; -using Barotrauma.IO; +using System.Globalization; using System.Linq; using System.Text; using System.Xml.Linq; -using System.Globalization; -using FarseerPhysics; -using Barotrauma.Extensions; -using Barotrauma.Steam; -using System.Threading.Tasks; -using Barotrauma.ClientSource.Settings; -using Barotrauma.MapCreatures.Behavior; using static Barotrauma.FabricationRecipe; namespace Barotrauma @@ -1299,7 +1296,7 @@ namespace Barotrauma int? fabricationCost = null; int? deconstructProductCost = null; - var fabricationRecipe = fabricableItems.Find(f => f.TargetItem == itemPrefab); + var fabricationRecipe = fabricableItems.Find(f => f.TargetItem == itemPrefab && f.RequiredItems.Any()); if (fabricationRecipe != null) { foreach (var ingredient in fabricationRecipe.RequiredItems) @@ -1334,6 +1331,21 @@ namespace Barotrauma if (fabricationRecipe != null) { var ingredient = fabricationRecipe.RequiredItems.Find(r => r.ItemPrefabs.Contains(targetItem)); + + if (ingredient == null) + { + foreach (var requiredItem in fabricationRecipe.RequiredItems) + { + foreach (var itemPrefab2 in requiredItem.ItemPrefabs) + { + foreach (var recipe in itemPrefab2.FabricationRecipes.Values) + { + ingredient ??= recipe.RequiredItems.Find(r => r.ItemPrefabs.Contains(targetItem)); + } + } + } + } + if (ingredient == null) { NewMessage("Deconstructing \"" + itemPrefab.Name + "\" produces \"" + deconstructItem.ItemIdentifier + "\", which isn't required in the fabrication recipe of the item.", Color.Red); @@ -2077,7 +2089,17 @@ namespace Barotrauma var prefab = MapEntityPrefab.Find(null, args[0]); if (prefab != null) { - DebugConsole.NewMessage(prefab.Name + " " + prefab.Identifier + " " + prefab.GetType().ToString()); + NewMessage(prefab.Name + " " + prefab.Identifier + " " + prefab.GetType().ToString()); + } + })); + + commands.Add(new Command("copycharacterinfotoclipboard", "", (string[] args) => + { + if (Character.Controlled?.Info != null) + { + XElement element = Character.Controlled?.Info.Save(null); + Clipboard.SetText(element.ToString()); + DebugConsole.NewMessage($"Copied the characterinfo of {Character.Controlled.Name} to clipboard."); } })); @@ -2507,7 +2529,7 @@ namespace Barotrauma commands.Add(new Command("checkduplicates", "Checks the given language for duplicate translation keys and writes to file.", (string[] args) => { - if (args.Length != 1) return; + if (args.Length != 1) { return; } TextManager.CheckForDuplicates(args[0].ToIdentifier().ToLanguageIdentifier()); })); @@ -2517,9 +2539,20 @@ namespace Barotrauma NPCConversation.WriteToCSV(); })); - commands.Add(new Command("csvtoxml", "csvtoxml [language] -> Converts .csv localization files in Content/NPCConversations & Content/Texts to .xml for use in-game.", (string[] args) => + commands.Add(new Command("csvtoxml", "csvtoxml -> Converts .csv localization files Content/Texts/Texts.csv and Content/Texts/NPCConversations.csv to .xml for use in-game.", (string[] args) => { - LocalizationCSVtoXML.Convert(); + ShowQuestionPrompt("Do you want to save the text files to the project folder (../../../BarotraumaShared/Content/Texts/)? If not, they are saved in the current working directory. Y/N", + (option1) => + { + ShowQuestionPrompt("Do you want to convert the NPC conversations as well? Y/N", + (option2) => + { + LocalizationCSVtoXML.ConvertMasterLocalizationKit( + option1.ToLowerInvariant() == "y" ? "../../../BarotraumaShared/Content/Texts/" : "Content/Texts", + option1.ToLowerInvariant() == "y" ? "../../../BarotraumaShared/Content/NPCConversations/" : "Content/NPCConversations", + convertConversations: option2.ToLowerInvariant() == "y"); + }); + }); })); commands.Add(new Command("printproperties", "Goes through the currently collected property list for missing localizations and writes them to a file.", (string[] args) => diff --git a/Barotrauma/BarotraumaClient/ClientSource/Events/EventActions/ConversationAction.cs b/Barotrauma/BarotraumaClient/ClientSource/Events/EventActions/ConversationAction.cs index d9dd3a9cc..f216984a4 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Events/EventActions/ConversationAction.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Events/EventActions/ConversationAction.cs @@ -32,12 +32,12 @@ namespace Barotrauma private static bool shouldFadeToBlack; - private bool IsBlockedByAnotherConversation(IEnumerable _) + private bool IsBlockedByAnotherConversation(IEnumerable _, float duration) { return lastActiveAction != null && lastActiveAction.ParentEvent != ParentEvent && - Timing.TotalTime < lastActiveAction.lastActiveTime + BlockOtherConversationsDuration; + Timing.TotalTime < lastActiveAction.lastActiveTime + duration; } partial void ShowDialog(Character speaker, Character targetCharacter) diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/CrewManagement.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/CrewManagement.cs index 5760ecefd..c4ec84e16 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/CrewManagement.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/CrewManagement.cs @@ -528,7 +528,7 @@ namespace Barotrauma if (characterInfo.PersonalityTrait is NPCPersonalityTrait trait) { new GUITextBlock(new RectTransform(new Vector2(1.0f, blockHeight), infoLabelGroup.RectTransform), TextManager.Get("PersonalityTrait")); - new GUITextBlock(new RectTransform(new Vector2(1.0f, blockHeight), infoValueGroup.RectTransform), TextManager.Get("personalitytrait." + trait.Name.Replace(" ".ToIdentifier(), Identifier.Empty))); + new GUITextBlock(new RectTransform(new Vector2(1.0f, blockHeight), infoValueGroup.RectTransform), trait.DisplayName); } infoLabelGroup.Recalculate(); infoValueGroup.Recalculate(); diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUI.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUI.cs index 49f027c19..63021ce65 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUI.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUI.cs @@ -958,7 +958,7 @@ namespace Barotrauma // Wire cursors if (Character.Controlled != null) { - if (Character.Controlled.SelectedConstruction?.GetComponent() != null) + if (Character.Controlled.SelectedItem?.GetComponent() != null) { if (Connection.DraggingConnected != null) { @@ -1344,7 +1344,7 @@ namespace Barotrauma /// Should the indicator move based on the camera position? /// Override the distance-based alpha value with the specified alpha value public static void DrawIndicator(SpriteBatch spriteBatch, in Vector2 worldPosition, Camera cam, in Range visibleRange, Sprite sprite, in Color color, - bool createOffset = true, float scaleMultiplier = 1.0f, float? overrideAlpha = null) + bool createOffset = true, float scaleMultiplier = 1.0f, float? overrideAlpha = null, LocalizedString label = null) { Vector2 diff = worldPosition - cam.WorldViewCenter; float dist = diff.Length(); @@ -1394,10 +1394,6 @@ namespace Barotrauma angle = MathHelper.Lerp(originalAngle, angle, MathHelper.Clamp(((screenDist + 10f) - iconDiff.Length()) / 10f, 0f, 1f)); - /*Vector2 unclampedDiff = new Vector2( - (float)Math.Cos(angle) * screenDist, - (float)-Math.Sin(angle) * screenDist);*/ - iconDiff = new Vector2( (float)Math.Cos(angle) * Math.Min(GameMain.GraphicsWidth * 0.4f, screenDist), (float)-Math.Sin(angle) * Math.Min(GameMain.GraphicsHeight * 0.4f, screenDist)); @@ -1405,7 +1401,20 @@ namespace Barotrauma Vector2 iconPos = cam.WorldToScreen(cam.WorldViewCenter) + iconDiff; sprite.Draw(spriteBatch, iconPos, color * alpha, rotate: 0.0f, scale: symbolScale); - if (/*unclampedDiff.Length()*/ screenDist - 10 > iconDiff.Length()) + if (label != null) + { + float cursorDist = Vector2.Distance(PlayerInput.MousePosition, iconPos); + if (cursorDist < sprite.size.X * symbolScale) + { + Vector2 textSize = GUIStyle.Font.MeasureString(label); + Vector2 textPos = iconPos + new Vector2(sprite.size.X * symbolScale * 0.7f * Math.Sign(-iconDiff.X), -textSize.Y / 2); + if (iconDiff.X > 0) { textPos.X -= textSize.X; } + DrawString(spriteBatch, textPos + Vector2.One, label, Color.Black); + DrawString(spriteBatch, textPos, label, color); + } + } + + if (screenDist - 10 > iconDiff.Length()) { Vector2 normalizedDiff = Vector2.Normalize(targetScreenPos - iconPos); Vector2 arrowOffset = normalizedDiff * sprite.size.X * symbolScale * 0.7f; @@ -1465,9 +1474,9 @@ namespace Barotrauma depth); } - public static void DrawString(SpriteBatch sb, Vector2 pos, LocalizedString text, Color color, Color? backgroundColor = null, int backgroundPadding = 0, GUIFont font = null) + public static void DrawString(SpriteBatch sb, Vector2 pos, LocalizedString text, Color color, Color? backgroundColor = null, int backgroundPadding = 0, GUIFont font = null, ForceUpperCase forceUpperCase = ForceUpperCase.Inherit) { - DrawString(sb, pos, text.Value, color, backgroundColor, backgroundPadding, font); + DrawString(sb, pos, text.Value, color, backgroundColor, backgroundPadding, font, forceUpperCase); } public static void DrawString(SpriteBatch sb, Vector2 pos, string text, Color color, Color? backgroundColor = null, int backgroundPadding = 0, GUIFont font = null, ForceUpperCase forceUpperCase = ForceUpperCase.Inherit) diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIContextMenu.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIContextMenu.cs index 40eae2afa..3e9166fcd 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIContextMenu.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIContextMenu.cs @@ -62,7 +62,7 @@ namespace Barotrauma GUIFont headerFont = GUIStyle.SubHeadingFont; GUIFont font = GUIStyle.SmallFont; // font the context menu options use Vector4 padding = new Vector4(4), headerPadding = new Vector4(8); - int horizontalPadding = (int) (padding.X + padding.Z), verticalPadding = (int) (padding.Y + padding.W); + int horizontalPadding = (int)(padding.X + padding.Z), verticalPadding = (int)(padding.Y + padding.W); bool hasHeader = !header.IsNullOrWhiteSpace(); //---------------------------------------------------------------------------------- @@ -131,9 +131,15 @@ namespace Barotrauma optionElement.ToolTip = option.Tooltip; } - if (!option.IsEnabled) + //option doesn't do anything, make it a label + if (option.OnSelected == null) { - optionElement.TextColor *= 0.5f; + optionElement.TextAlignment = Alignment.BottomLeft; + optionElement.TextColor = optionElement.DisabledTextColor = GUIStyle.Green; + } + else if (!option.IsEnabled) + { + optionElement.TextColor *= 0.5f; } } @@ -146,7 +152,10 @@ namespace Barotrauma // Resize all children to the size of their text foreach (GUITextBlock block in children.Where(c => c is GUITextBlock).Cast()) { - block.RectTransform.NonScaledSize = new Point((int) (block.TextSize.X + (block.Padding.X + block.Padding.Z)), (int) (18 * GUI.Scale)); + bool isLabel = block.UserData is ContextMenuOption option && option.OnSelected == null; + block.RectTransform.NonScaledSize = new Point( + (int)(block.TextSize.X + (block.Padding.X + block.Padding.Z)), + (int)Math.Max(block.TextSize.Y * 1.2f, 18 * GUI.Scale)); } int largestWidth = children.Max(c => c.Rect.Width + horizontalPadding); @@ -155,7 +164,7 @@ namespace Barotrauma if (HeaderLabel != null) { RectTransform headerTransform = HeaderLabel.RectTransform; - headerTransform.MinSize = new Point((int) (HeaderLabel.TextSize.X + (headerPadding.X + headerPadding.Z)), headerTransform.NonScaledSize.Y); + headerTransform.MinSize = new Point((int)(HeaderLabel.TextSize.X + (headerPadding.X + headerPadding.Z)), headerTransform.NonScaledSize.Y); if (largestWidth < headerTransform.MinSize.X) { largestWidth = headerTransform.MinSize.X; @@ -171,7 +180,7 @@ namespace Barotrauma // the cropped size of the option list Point newSize = new Point(largestWidth, children.Sum(c => c.Rect.Height) + verticalPadding); // resize the menu itself taking into account the option menus relative Y size - RectTransform.NonScaledSize = new Point(newSize.X, (int) (newSize.Y / optionList.RectTransform.RelativeSize.Y)); + RectTransform.NonScaledSize = new Point(newSize.X, (int)(newSize.Y / optionList.RectTransform.RelativeSize.Y)); optionList.RectTransform.NonScaledSize = newSize; // move the context menu if it would go outside of screen @@ -227,8 +236,8 @@ namespace Barotrauma private Vector2 InflateSize(ref Point size, LocalizedString label, ScalableFont font) { Vector2 textSize = font.MeasureString(label); - size.X = Math.Max((int) Math.Ceiling(textSize.X), size.X); - size.Y += (int) Math.Ceiling(textSize.Y); + size.X = Math.Max((int)Math.Ceiling(textSize.X), size.X); + size.Y += (int)Math.Ceiling(textSize.Y); return textSize; } diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIDragHandle.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIDragHandle.cs new file mode 100644 index 000000000..b4987a87d --- /dev/null +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIDragHandle.cs @@ -0,0 +1,75 @@ +using Microsoft.Xna.Framework; +using System; + +namespace Barotrauma +{ + public class GUIDragHandle : GUIComponent + { + private readonly RectTransform elementToMove; + + private Vector2 dragStart; + private bool dragStarted; + + public Rectangle DragArea; + + public GUIDragHandle(RectTransform rectT, RectTransform elementToMove, string style = "GUIDragIndicator") + : base(style, rectT) + { + this.elementToMove = elementToMove; + DragArea = new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight); + } + + protected override void Update(float deltaTime) + { + if (!Visible) return; + base.Update(deltaTime); + Enabled = true; + if (dragStarted) + { + Point moveAmount = (PlayerInput.MousePosition - dragStart).ToPoint() - elementToMove.ScreenSpaceOffset; + Rectangle rect = elementToMove.Rect; + rect.Location += moveAmount; + + moveAmount.X += Math.Max(DragArea.X - rect.X, 0); + moveAmount.X -= Math.Max(rect.Right - DragArea.Right, 0); + moveAmount.Y += Math.Max(DragArea.Y - rect.Y, 0); + moveAmount.Y -= Math.Max(rect.Bottom - DragArea.Bottom, 0); + + if (moveAmount != Point.Zero) + { + elementToMove.ScreenSpaceOffset += moveAmount; + } + + if (!PlayerInput.PrimaryMouseButtonHeld()) + { + dragStarted = false; + } + } + else if (Rect.Contains(PlayerInput.MousePosition) && CanBeFocused && Enabled && GUI.IsMouseOn(this)) + { + State = Selected ? ComponentState.HoverSelected : ComponentState.Hover; + if (PlayerInput.PrimaryMouseButtonDown()) + { + dragStart = PlayerInput.MousePosition - elementToMove.ScreenSpaceOffset.ToVector2(); + dragStarted = true; + } + } + else + { + if (!ExternalHighlight) + { + State = Selected ? ComponentState.Selected : ComponentState.None; + } + else + { + State = ComponentState.Hover; + } + } + + foreach (GUIComponent child in Children) + { + child.State = State; + } + } + } +} diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIListBox.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIListBox.cs index 8e43f9c6f..579e492c2 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIListBox.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIListBox.cs @@ -49,7 +49,7 @@ namespace Barotrauma //scaling the bar linearly with the resolution tends to make them too large on large resolutions float desiredSize = 25.0f; float scaledSize = desiredSize * GUI.Scale; - return (int)((desiredSize + scaledSize) / 2.0f); + return (int)Math.Min((desiredSize + scaledSize) / 2.0f, Rect.Height / 3); } } @@ -73,6 +73,8 @@ namespace Barotrauma public bool HideChildrenOutsideFrame = true; + public bool ResizeContentToMakeSpaceForScrollBar = true; + private bool useGridLayout; private GUIComponent scrollToElement; @@ -419,7 +421,7 @@ namespace Barotrauma { dimensionsNeedsRecalculation = false; ContentBackground.RectTransform.Resize(Rect.Size); - bool reduceScrollbarSize = KeepSpaceForScrollBar ? ScrollBarEnabled : ScrollBarVisible; + bool reduceScrollbarSize = ResizeContentToMakeSpaceForScrollBar && (KeepSpaceForScrollBar ? ScrollBarEnabled : ScrollBarVisible); Point contentSize = reduceScrollbarSize ? CalculateFrameSize(ScrollBar.IsHorizontal, ScrollBarSize) : Rect.Size; Content.RectTransform.Resize(new Point((int)(contentSize.X - Padding.X - Padding.Z), (int)(contentSize.Y - Padding.Y - Padding.W))); if (!IsScrollBarOnDefaultSide) { Content.RectTransform.SetPosition(Anchor.BottomRight); } diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIMessageBox.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIMessageBox.cs index fb9756c54..8d8a563b4 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIMessageBox.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIMessageBox.cs @@ -471,6 +471,7 @@ namespace Barotrauma public void SetBackgroundIcon(Sprite icon) { if (icon == null) { return; } + if (icon == BackgroundIcon.Sprite) { return; } GUIImage newIcon = new GUIImage(new RectTransform(icon.size.ToPoint(), RectTransform), icon) { IgnoreLayoutGroups = true, @@ -593,7 +594,7 @@ namespace Barotrauma { newBackgroundIcon.SetAsFirstChild(); newBackgroundIcon.RectTransform.AbsoluteOffset = new Point(InnerFrame.Rect.Location.X - (int)(newBackgroundIcon.Rect.Size.X / 1.25f), (int)defaultPos.Y - newBackgroundIcon.Rect.Size.Y / 2); - newBackgroundIcon.Color = ToolBox.GradientLerp(iconState, Color.Transparent, Color.White); + newBackgroundIcon.Color = Color.Lerp(Color.Transparent, Color.White, iconState); if (newBackgroundIcon.Color.A == 255) { BackgroundIcon = newBackgroundIcon; diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/HUDLayoutSettings.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/HUDLayoutSettings.cs index 1c2e869b0..0552340d0 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/HUDLayoutSettings.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/HUDLayoutSettings.cs @@ -81,6 +81,11 @@ namespace Barotrauma get; private set; } + public static Rectangle ItemHUDArea + { + get; private set; + } + public static int Padding { get; private set; @@ -168,6 +173,8 @@ namespace Barotrauma // Height is based on text content VotingArea = new Rectangle(votingAreaX, votingAreaY, votingAreaWidth, 0); + + ItemHUDArea = new Rectangle(0, ButtonAreaTop.Bottom, GameMain.GraphicsWidth, GameMain.GraphicsHeight - ButtonAreaTop.Bottom - InventoryAreaLower.Height); } public static void Draw(SpriteBatch spriteBatch) @@ -181,6 +188,7 @@ namespace Barotrauma GUI.DrawRectangle(spriteBatch, InventoryAreaLower, Color.Yellow * 0.5f); GUI.DrawRectangle(spriteBatch, HealthWindowAreaLeft, Color.Red * 0.5f); GUI.DrawRectangle(spriteBatch, BottomRightInfoArea, Color.Green * 0.5f); + GUI.DrawRectangle(spriteBatch, ItemHUDArea, Color.Magenta * 0.3f); } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/TabMenu.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/TabMenu.cs index 6bd80ccc1..aded19429 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/TabMenu.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/TabMenu.cs @@ -403,7 +403,7 @@ namespace Barotrauma CreateSubmarineInfo(infoFrameHolder, Submarine.MainSub); break; case InfoFrameTab.Talents: - CreateTalentInfo(infoFrameHolder); + CreateCharacterInfo(infoFrameHolder); break; } } @@ -1803,161 +1803,121 @@ namespace Barotrauma { TalentTree.TalentTreeStageState.Highlighted, new Color(50,47,33,255) }, }.ToImmutableDictionary(); - private void CreateTalentInfo(GUIFrame infoFrame) + private void CreateCharacterInfo(GUIFrame infoFrame) { infoFrame.ClearChildren(); talentButtons.Clear(); talentCornerIcons.Clear(); - GUIFrame talentFrameBackground = new GUIFrame(new RectTransform(Vector2.One, infoFrame.RectTransform, Anchor.TopCenter), style: "GUIFrameListBox"); + GUIFrame background = new GUIFrame(new RectTransform(Vector2.One, infoFrame.RectTransform, Anchor.TopCenter), style: "GUIFrameListBox"); int padding = GUI.IntScale(15); - GUIFrame talentFrameContent = new GUIFrame(new RectTransform(new Point(talentFrameBackground.Rect.Width - padding, talentFrameBackground.Rect.Height - padding), infoFrame.RectTransform, Anchor.Center), style: null); + GUIFrame frame = new GUIFrame(new RectTransform(new Point(background.Rect.Width - padding, background.Rect.Height - padding), infoFrame.RectTransform, Anchor.Center), style: null); - GUIFrame paddedTalentFrame = new GUIFrame(new RectTransform(new Vector2(1f, 0.9f), talentFrameContent.RectTransform, Anchor.Center), style: null); - - GUIFrame talentFrameMain = new GUIFrame(new RectTransform(Vector2.One, paddedTalentFrame.RectTransform), style: null); + GUIFrame content = new GUIFrame(new RectTransform(new Vector2(0.98f), frame.RectTransform, Anchor.Center), style: null); GUIFrame characterSettingsFrame = null; GUILayoutGroup characterLayout = null; if (!(GameMain.NetworkMember is null)) { - characterSettingsFrame = new GUIFrame(new RectTransform(Vector2.One, talentFrameContent.RectTransform), style: null) { Visible = false }; + characterSettingsFrame = new GUIFrame(new RectTransform(Vector2.One, frame.RectTransform), style: null) { Visible = false }; characterLayout = new GUILayoutGroup(new RectTransform(Vector2.One, characterSettingsFrame.RectTransform)); GUIFrame containerFrame = new GUIFrame(new RectTransform(new Vector2(1f, 0.9f), characterLayout.RectTransform), style: null); GUIFrame playerFrame = new GUIFrame(new RectTransform(new Vector2(0.9f, 0.7f), containerFrame.RectTransform, Anchor.Center), style: null); GameMain.NetLobbyScreen.CreatePlayerFrame(playerFrame, alwaysAllowEditing: true, createPendingText: false); } - /*Character controlledCharacter = Character.Controlled; - if (controlledCharacter == null) { return; } - - if (controlledCharacter.Info is null) - { - DebugConsole.ThrowError("No character info found for talent UI"); - return; - }*/ - Character controlledCharacter = Character.Controlled; CharacterInfo info = controlledCharacter?.Info ?? GameMain.Client?.CharacterInfo; if (info == null) { return; } Job job = info.Job; - GUILayoutGroup talentFrameLayoutGroup = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 1.0f), talentFrameMain.RectTransform, anchor: Anchor.Center), childAnchor: Anchor.TopCenter) + GUILayoutGroup contentLayout = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 1.0f), content.RectTransform, anchor: Anchor.Center), childAnchor: Anchor.TopCenter) { - AbsoluteSpacing = GUI.IntScale(5) + AbsoluteSpacing = GUI.IntScale(10), + Stretch = true }; - GUILayoutGroup talentInfoLayoutGroup = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.25f), talentFrameLayoutGroup.RectTransform, Anchor.Center), isHorizontal: true); + GUILayoutGroup topLayout = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.3f), contentLayout.RectTransform, Anchor.Center), isHorizontal: true); - - new GUICustomComponent(new RectTransform(new Vector2(0.25f, 1f), talentInfoLayoutGroup.RectTransform), onDraw: (batch, component) => + new GUICustomComponent(new RectTransform(new Vector2(0.25f, 1f), topLayout.RectTransform), onDraw: (batch, component) => { float posY = component.Rect.Center.Y - component.Rect.Width / 2; info.DrawPortrait(batch, new Vector2(component.Rect.X, posY), Vector2.Zero, component.Rect.Width, false, false); }); - GUILayoutGroup nameLayout = new GUILayoutGroup(new RectTransform(new Vector2(0.3f, 1f), talentInfoLayoutGroup.RectTransform)) { RelativeSpacing = 0.05f }; + GUILayoutGroup nameLayout = new GUILayoutGroup(new RectTransform(new Vector2(0.3f, 1f), topLayout.RectTransform)) + { + AbsoluteSpacing = GUI.IntScale(5), + CanBeFocused = true + }; - Vector2 nameSize = GUIStyle.SubHeadingFont.MeasureString(info.Name); - GUITextBlock nameBlock = new GUITextBlock(new RectTransform(Vector2.One, nameLayout.RectTransform), info.Name, font: GUIStyle.SubHeadingFont); - nameBlock.RectTransform.NonScaledSize = nameSize.Pad(nameBlock.Padding).ToPoint(); + GUITextBlock nameBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), nameLayout.RectTransform), info.Name, font: GUIStyle.SubHeadingFont); if (!info.OmitJobInMenus) { nameBlock.TextColor = job.Prefab.UIColor; - Vector2 jobSize = GUIStyle.SmallFont.MeasureString(job.Name); - GUITextBlock jobBlock = new GUITextBlock(new RectTransform(Vector2.One, nameLayout.RectTransform), job.Name, font: GUIStyle.SmallFont) { TextColor = job.Prefab.UIColor }; - jobBlock.RectTransform.NonScaledSize = jobSize.Pad(jobBlock.Padding).ToPoint(); + 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"), TextManager.Get("personalitytrait." + info.PersonalityTrait.Name.Replace(" ", ""))); + 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(); - GUIFrame talentsOutsideTreeFrame = new GUIFrame(new RectTransform(new Vector2(1f, 0.35f), nameLayout.RectTransform, Anchor.BottomCenter), style: null); - - if (!(GameMain.NetworkMember is null)) + IEnumerable talentsOutsideTree = info.GetUnlockedTalentsOutsideTree().Select(e => TalentPrefab.TalentPrefabs.Find(c => c.Identifier == e)); + if (talentsOutsideTree.Count() > 0) { - GUIButton newCharacterBox = new GUIButton(new RectTransform(new Vector2(0.675f, 1f), talentsOutsideTreeFrame.RectTransform, Anchor.TopLeft), - text: GameMain.NetLobbyScreen.CampaignCharacterDiscarded ? TextManager.Get("settings") : TextManager.Get("createnew")) + //spacing + new GUIFrame(new RectTransform(new Vector2(1.0f, 0.05f), nameLayout.RectTransform), style: null); + + GUILayoutGroup extraTalentLayout = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.3f), nameLayout.RectTransform), childAnchor: Anchor.TopCenter); + + talentPointText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), extraTalentLayout.RectTransform, anchor: Anchor.Center), TextManager.Get("talentmenu.extratalents"), font: GUIStyle.SubHeadingFont); + talentPointText.RectTransform.MaxSize = new Point(int.MaxValue, (int)talentPointText.TextSize.Y); + + var extraTalentList = new GUIListBox(new RectTransform(new Vector2(0.9f, 0.8f), extraTalentLayout.RectTransform, anchor: Anchor.Center), isHorizontal: true) { - IgnoreLayoutGroups = true + AutoHideScrollBar = false, + ResizeContentToMakeSpaceForScrollBar = false }; - newCharacterBox.TextBlock.AutoScaleHorizontal = true; + extraTalentList.ScrollBar.RectTransform.SetPosition(Anchor.BottomCenter, Pivot.TopCenter); + extraTalentList.RectTransform.MinSize = new Point(0, GUI.IntScale(65)); + extraTalentLayout.Recalculate(); + extraTalentList.ForceLayoutRecalculation(); - newCharacterBox.OnClicked = (button, o) => + foreach (var extraTalent in talentsOutsideTree) { - if (!GameMain.NetLobbyScreen.CampaignCharacterDiscarded) + var img = new GUIImage(new RectTransform(new Point(extraTalentList.Content.Rect.Height), extraTalentList.Content.RectTransform), sprite: extraTalent.Icon, scaleToFit: true) { - GameMain.NetLobbyScreen.TryDiscardCampaignCharacter(() => - { - newCharacterBox.Text = TextManager.Get("settings"); - - if (pendingChangesFrame != null) - { - NetLobbyScreen.CreateChangesPendingFrame(pendingChangesFrame); - } - OpenMenu(); - }); - return true; - } - - OpenMenu(); - return true; - - void OpenMenu() - { - characterSettingsFrame!.Visible = true; - talentFrameMain.Visible = false; - } - }; - - if (!(characterLayout is null)) - { - GUILayoutGroup characterCloseButtonLayout = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.1f), characterLayout.RectTransform), childAnchor: Anchor.BottomRight); - new GUIButton(new RectTransform(new Vector2(0.4f, 1f), characterCloseButtonLayout.RectTransform), TextManager.Get("ApplySettingsButton")) //TODO: Is this text appropriate for this circumstance for all languages? - { - OnClicked = (button, o) => - { - GameMain.Client?.SendCharacterInfo(GameMain.Client.PendingName); - characterSettingsFrame!.Visible = false; - talentFrameMain.Visible = true; - return true; - } + ToolTip = RichString.Rich($"‖color:{Color.White.ToStringHex()}‖{extraTalent.DisplayName}‖color:end‖" + "\n\n" + extraTalent.Description), + Color = GUIStyle.Green }; + img.RectTransform.SizeChanged += () => + { + img.RectTransform.MaxSize = new Point(img.Rect.Height); + }; } } - IEnumerable talentsOutsideTree = info.GetUnlockedTalentsOutsideTree().Select(e => TalentPrefab.TalentPrefabs.Find(c => c.Identifier == e)); + GUILayoutGroup skillLayout = new GUILayoutGroup(new RectTransform(new Vector2(0.45f, 1f), topLayout.RectTransform), childAnchor: Anchor.TopRight) + { + AbsoluteSpacing = GUI.IntScale(5), + Stretch = true + }; - if (talentsOutsideTree.Count() > 0) - { - //TODO: replace with something more generic - GUIImage endocrineIcon = new GUIImage(new RectTransform(new Vector2(0.275f, 1f), talentsOutsideTreeFrame.RectTransform, anchor: Anchor.TopRight, scaleBasis: ScaleBasis.Normal), style: "EndocrineReminderIcon") - { - ToolTip = $"{TextManager.Get("afflictionname.endocrineboost")}\n\n{string.Join(", ", talentsOutsideTree.Select(e => e.DisplayName))}" - }; - } - - GUILayoutGroup skillLayout = new GUILayoutGroup(new RectTransform(new Vector2(0.45f, 1f), talentInfoLayoutGroup.RectTransform)) { Stretch = true }; - - LocalizedString skillString = TextManager.Get("skills"); - Vector2 skillSize = GUIStyle.SubHeadingFont.MeasureString(skillString); - GUITextBlock skillBlock = new GUITextBlock(new RectTransform(Vector2.One, skillLayout.RectTransform), skillString, font: GUIStyle.SubHeadingFont); - skillBlock.RectTransform.NonScaledSize = skillSize.Pad(skillBlock.Padding).ToPoint(); + GUITextBlock skillBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), skillLayout.RectTransform), TextManager.Get("skills"), font: GUIStyle.SubHeadingFont); skillListBox = new GUIListBox(new RectTransform(new Vector2(1f, 1f - skillBlock.RectTransform.RelativeSize.Y), skillLayout.RectTransform), style: null); - CreateTalentSkillList(controlledCharacter, info, skillListBox); + CreateSkillList(controlledCharacter, info, skillListBox); if (controlledCharacter != null) { if (!TalentTree.JobTalentTrees.TryGet(info.Job.Prefab.Identifier, out TalentTree talentTree)) { return; } - new GUIFrame(new RectTransform(new Vector2(1f, 1f), talentFrameLayoutGroup.RectTransform), style: "HorizontalLine"); + new GUIFrame(new RectTransform(new Vector2(1f, 1f), contentLayout.RectTransform), style: "HorizontalLine"); - GUIListBox talentTreeListBox = new GUIListBox(new RectTransform(new Vector2(1f, 0.7f), talentFrameLayoutGroup.RectTransform, Anchor.TopCenter), isHorizontal: true, style: null); + GUIListBox talentTreeListBox = new GUIListBox(new RectTransform(new Vector2(1f, 0.6f), contentLayout.RectTransform, Anchor.TopCenter), isHorizontal: true, style: null); selectedTalents = info.GetUnlockedTalentsInTree().ToList(); @@ -2008,10 +1968,9 @@ namespace Barotrauma }; GUIFrame croppedTalentFrame = new GUIFrame(new RectTransform(Vector2.One, talentFrame.RectTransform, anchor: Anchor.Center, scaleBasis: ScaleBasis.BothHeight), style: null); - GUIButton talentButton = new GUIButton(new RectTransform(Vector2.One, croppedTalentFrame.RectTransform, anchor: Anchor.Center), style: null) { - ToolTip = RichString.Rich(talent.DisplayName + "\n\n" + talent.Description), + ToolTip = RichString.Rich($"‖color:{Color.White.ToStringHex()}‖{talent.DisplayName}‖color:end‖" + "\n\n" + talent.Description), UserData = talent.Identifier, PressedColor = pressedColor, Enabled = controlledCharacter != null, @@ -2078,9 +2037,13 @@ namespace Barotrauma } GUITextBlock.AutoScaleAndNormalize(subTreeNames); - GUILayoutGroup talentBottomFrame = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.07f), talentFrameLayoutGroup.RectTransform, Anchor.TopCenter), isHorizontal: true) { RelativeSpacing = 0.01f }; + GUILayoutGroup bottomLayout = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.07f), contentLayout.RectTransform, Anchor.TopCenter), isHorizontal: true) + { + RelativeSpacing = 0.01f, + Stretch = true + }; - GUILayoutGroup experienceLayout = new GUILayoutGroup(new RectTransform(new Vector2(0.59f, 1f), talentBottomFrame.RectTransform)); + GUILayoutGroup experienceLayout = new GUILayoutGroup(new RectTransform(new Vector2(0.59f, 1f), bottomLayout.RectTransform)); GUIFrame experienceBarFrame = new GUIFrame(new RectTransform(new Vector2(1f, 0.5f), experienceLayout.RectTransform), style: null); experienceBar = new GUIProgressBar(new RectTransform(new Vector2(1f, 1f), experienceBarFrame.RectTransform, Anchor.CenterLeft), @@ -2097,30 +2060,84 @@ namespace Barotrauma talentPointText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), experienceLayout.RectTransform, anchor: Anchor.Center), "", font: GUIStyle.SubHeadingFont, textAlignment: Alignment.CenterRight) { AutoScaleVertical = true }; - talentResetButton = new GUIButton(new RectTransform(new Vector2(0.19f, 1f), talentBottomFrame.RectTransform), text: TextManager.Get("reset"), style: "GUIButtonFreeScale") + talentResetButton = new GUIButton(new RectTransform(new Vector2(0.19f, 1f), bottomLayout.RectTransform), text: TextManager.Get("reset"), style: "GUIButtonFreeScale") { OnClicked = ResetTalentSelection }; - talentApplyButton = new GUIButton(new RectTransform(new Vector2(0.19f, 1f), talentBottomFrame.RectTransform), text: TextManager.Get("applysettingsbutton"), style: "GUIButtonFreeScale") + talentApplyButton = new GUIButton(new RectTransform(new Vector2(0.19f, 1f), bottomLayout.RectTransform), text: TextManager.Get("applysettingsbutton"), style: "GUIButtonFreeScale") { OnClicked = ApplyTalentSelection, }; GUITextBlock.AutoScaleAndNormalize(talentResetButton.TextBlock, talentApplyButton.TextBlock); } + if (!(GameMain.NetworkMember is null)) + { + GUIButton newCharacterBox = new GUIButton(new RectTransform(new Vector2(0.5f, 0.2f), skillLayout.RectTransform, Anchor.BottomRight), + text: GameMain.NetLobbyScreen.CampaignCharacterDiscarded ? TextManager.Get("settings") : TextManager.Get("createnew"), style: "GUIButtonSmall") + { + IgnoreLayoutGroups = false + }; + newCharacterBox.TextBlock.AutoScaleHorizontal = true; + + newCharacterBox.OnClicked = (button, o) => + { + if (!GameMain.NetLobbyScreen.CampaignCharacterDiscarded) + { + GameMain.NetLobbyScreen.TryDiscardCampaignCharacter(() => + { + newCharacterBox.Text = TextManager.Get("settings"); + if (pendingChangesFrame != null) + { + NetLobbyScreen.CreateChangesPendingFrame(pendingChangesFrame); + } + OpenMenu(); + }); + return true; + } + + OpenMenu(); + return true; + + void OpenMenu() + { + characterSettingsFrame!.Visible = true; + content.Visible = false; + } + }; + + if (!(characterLayout is null)) + { + GUILayoutGroup characterCloseButtonLayout = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.1f), characterLayout.RectTransform), childAnchor: Anchor.BottomCenter); + new GUIButton(new RectTransform(new Vector2(0.4f, 1f), characterCloseButtonLayout.RectTransform), TextManager.Get("ApplySettingsButton")) //TODO: Is this text appropriate for this circumstance for all languages? + { + OnClicked = (button, o) => + { + GameMain.Client?.SendCharacterInfo(GameMain.Client.PendingName); + characterSettingsFrame!.Visible = false; + content.Visible = true; + return true; + } + }; + } + } + UpdateTalentInfo(); } - private void CreateTalentSkillList(Character character, CharacterInfo info, GUIListBox parent) + private void CreateSkillList(Character character, CharacterInfo info, GUIListBox parent) { parent.Content.ClearChildren(); List skillNames = new List(); foreach (Skill skill in info.Job.GetSkills()) { - GUILayoutGroup skillContainer = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.2f), parent.Content.RectTransform), isHorizontal: true) { CanBeFocused = false }; - - skillNames.Add(new GUITextBlock(new RectTransform(new Vector2(0.7f, 1f), skillContainer.RectTransform), TextManager.Get($"skillname.{skill.Identifier}").Fallback(skill.Identifier.Value))); - new GUITextBlock(new RectTransform(new Vector2(0.15f, 1.0f), skillContainer.RectTransform), Math.Floor(skill.Level).ToString("F0"), textAlignment: Alignment.CenterRight) { Padding = new Vector4(0, 0, 4, 0) }; + GUILayoutGroup skillContainer = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.0f), parent.Content.RectTransform), isHorizontal: true) { CanBeFocused = true }; + var skillName = new GUITextBlock(new RectTransform(new Vector2(0.7f, 0.0f), skillContainer.RectTransform), TextManager.Get($"skillname.{skill.Identifier}").Fallback(skill.Identifier.Value)); + skillNames.Add(skillName); + skillName.RectTransform.MinSize = new Point(0, skillName.Rect.Height); + skillContainer.RectTransform.MinSize = new Point(0, skillName.Rect.Height); + + new GUITextBlock(new RectTransform(new Vector2(0.15f, 1.0f), skillContainer.RectTransform), Math.Floor(skill.Level).ToString("F0"), textAlignment: Alignment.TopRight); float modifiedSkillLevel = character?.GetSkillLevel(skill.Identifier) ?? skill.Level; if (!MathUtils.NearlyEqual(MathF.Floor(modifiedSkillLevel), MathF.Floor(skill.Level))) @@ -2129,15 +2146,15 @@ namespace Barotrauma //TODO: if/when we upgrade to C# 9, do neater pattern matching here string stringColor = true switch { - true when skillChange > 0 => XMLExtensions.ColorToString(GUIStyle.Green), - true when skillChange < 0 => XMLExtensions.ColorToString(GUIStyle.Red), - _ => XMLExtensions.ColorToString(GUIStyle.TextColorNormal) + true when skillChange > 0 => XMLExtensions.ToStringHex(GUIStyle.Green), + true when skillChange < 0 => XMLExtensions.ToStringHex(GUIStyle.Red), + _ => XMLExtensions.ToStringHex(GUIStyle.TextColorNormal) }; RichString changeText = RichString.Rich($"(‖color:{stringColor}‖{(skillChange > 0 ? "+" : string.Empty) + skillChange}‖color:end‖)"); new GUITextBlock(new RectTransform(new Vector2(0.15f, 1.0f), skillContainer.RectTransform), changeText) { Padding = Vector4.Zero }; } - skillContainer.Recalculate(); + //skillContainer.Recalculate(); } parent.RecalculateChildren(); @@ -2216,7 +2233,7 @@ namespace Barotrauma talentButton.icon.HoverColor = hoverColor; } - CreateTalentSkillList(controlledCharacter, controlledCharacter.Info, skillListBox); + CreateSkillList(controlledCharacter, controlledCharacter.Info, skillListBox); } private void ApplyTalents(Character controlledCharacter) diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/UpgradeStore.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/UpgradeStore.cs index 4d5f3f806..7887ea6db 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/UpgradeStore.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/UpgradeStore.cs @@ -432,13 +432,21 @@ namespace Barotrauma }; Location location = Campaign.Map.CurrentLocation; - int hullRepairCost = location?.GetAdjustedMechanicalCost(CampaignMode.HullRepairCost) ?? CampaignMode.HullRepairCost; - int itemRepairCost = location?.GetAdjustedMechanicalCost(CampaignMode.ItemRepairCost) ?? CampaignMode.ItemRepairCost; - int shuttleRetrieveCost = location?.GetAdjustedMechanicalCost(CampaignMode.ShuttleReplaceCost) ?? CampaignMode.ShuttleReplaceCost; + + int hullRepairCost = Campaign.GetHullRepairCost(); + int itemRepairCost = Campaign.GetItemRepairCost(); + int shuttleRetrieveCost = CampaignMode.ShuttleReplaceCost; + if (location != null) + { + hullRepairCost = location.GetAdjustedMechanicalCost(hullRepairCost); + itemRepairCost = location.GetAdjustedMechanicalCost(itemRepairCost); + shuttleRetrieveCost = location.GetAdjustedMechanicalCost(shuttleRetrieveCost); + } CreateRepairEntry(currentStoreLayout.Content, TextManager.Get("repairallwalls"), "RepairHullButton", hullRepairCost, (button, o) => { - if (Campaign.PurchasedHullRepairs) + //cost is zero = nothing to repair + if (Campaign.PurchasedHullRepairs || hullRepairCost <= 0) { button.Enabled = false; return false; @@ -471,7 +479,7 @@ namespace Barotrauma return false; } return true; - }, Campaign.PurchasedHullRepairs || !HasPermission, isHovered => + }, Campaign.PurchasedHullRepairs || !HasPermission || hullRepairCost <= 0, isHovered => { highlightWalls = isHovered; return true; @@ -479,7 +487,8 @@ namespace Barotrauma CreateRepairEntry(currentStoreLayout.Content, TextManager.Get("repairallitems"), "RepairItemsButton", itemRepairCost, (button, o) => { - if (PlayerBalance >= itemRepairCost && !Campaign.PurchasedItemRepairs) + //cost is zero = nothing to repair + if (PlayerBalance >= itemRepairCost && !Campaign.PurchasedItemRepairs && itemRepairCost > 0) { LocalizedString body = TextManager.GetWithVariable("ItemRepairs.PurchasePromptBody", "[amount]", itemRepairCost.ToString()); currectConfirmation = EventEditorScreen.AskForConfirmation(TextManager.Get("Upgrades.PurchasePromptTitle"), body, () => @@ -505,9 +514,8 @@ namespace Barotrauma button.Enabled = false; return false; } - return true; - }, Campaign.PurchasedItemRepairs || !HasPermission, isHovered => + }, Campaign.PurchasedItemRepairs || !HasPermission || itemRepairCost <= 0, isHovered => { foreach (var (item, itemFrame) in itemPreviews) { diff --git a/Barotrauma/BarotraumaClient/ClientSource/GameMain.cs b/Barotrauma/BarotraumaClient/ClientSource/GameMain.cs index f3908eb62..f0930992a 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GameMain.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GameMain.cs @@ -814,7 +814,7 @@ namespace Barotrauma else if ((Character.Controlled == null || !itemHudActive()) && CharacterHealth.OpenHealthWindow == null && !CrewManager.IsCommandInterfaceOpen - && !(Screen.Selected is SubEditorScreen editor && !editor.WiringMode && Character.Controlled?.SelectedConstruction != null)) + && !(Screen.Selected is SubEditorScreen editor && !editor.WiringMode && Character.Controlled?.SelectedItem != null)) { // Otherwise toggle pausing, unless another window/interface is open. GUI.TogglePauseMenu(); @@ -822,9 +822,9 @@ namespace Barotrauma static bool itemHudActive() { - if (Character.Controlled?.SelectedConstruction == null) { return false; } + if (Character.Controlled?.SelectedItem == null) { return false; } return - Character.Controlled.SelectedConstruction.ActiveHUDs.Any(ic => ic.GuiFrame != null) || + Character.Controlled.SelectedItem.ActiveHUDs.Any(ic => ic.GuiFrame != null) || ((Character.Controlled.ViewTarget as Item)?.Prefab?.FocusOnSelected ?? false); } } @@ -919,7 +919,7 @@ namespace Barotrauma #endif } - CoroutineManager.Update((float)Timing.Step, Paused ? 0.0f : (float)Timing.Step); + CoroutineManager.Update(Paused, (float)Timing.Step); SteamManager.Update((float)Timing.Step); @@ -1098,7 +1098,7 @@ namespace Barotrauma GameAnalyticsManager.AddDesignEvent(eventId + "EventManager:CurrentIntensity", GameSession.EventManager.CurrentIntensity); foreach (var activeEvent in GameSession.EventManager.ActiveEvents) { - GameAnalyticsManager.AddDesignEvent(eventId + "EventManager:ActiveEvents:" + activeEvent.ToString()); + GameAnalyticsManager.AddDesignEvent(eventId + "EventManager:ActiveEvents:" + activeEvent.Prefab.Identifier); } GameSession.LogEndRoundStats(eventId); if (GameSession.GameMode is TutorialMode tutorialMode) diff --git a/Barotrauma/BarotraumaClient/ClientSource/GameSession/CrewManager.cs b/Barotrauma/BarotraumaClient/ClientSource/GameSession/CrewManager.cs index a4f756646..73ea45844 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GameSession/CrewManager.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GameSession/CrewManager.cs @@ -2412,7 +2412,7 @@ namespace Barotrauma float reactorOutput = -reactor.CurrPowerConsumption; // If player is not an engineer AND the reactor is not powered up AND nobody is using the reactor // --> Create shortcut node for "Operate Reactor" order's "Power Up" option - if (ShouldDelegateOrder("operatereactor") && reactorOutput < float.Epsilon && characters.None(c => c.SelectedConstruction == reactor.Item)) + if (ShouldDelegateOrder("operatereactor") && reactorOutput < float.Epsilon && characters.None(c => c.SelectedItem == reactor.Item)) { var orderPrefab = OrderPrefab.Prefabs["operatereactor"]; var order = new Order(orderPrefab, orderPrefab.Options[0], reactor.Item, reactor); @@ -2426,7 +2426,7 @@ namespace Barotrauma // If player is not a captain AND nobody is using the nav terminal AND the nav terminal is powered up // --> Create shortcut node for Steer order if (CanFitMoreNodes() && ShouldDelegateOrder("steer") && IsNonDuplicateOrderPrefab(OrderPrefab.Prefabs["steer"]) && - subItems.Find(i => i.HasTag("navterminal") && i.IsPlayerTeamInteractable) is Item nav && characters.None(c => c.SelectedConstruction == nav) && + subItems.Find(i => i.HasTag("navterminal") && i.IsPlayerTeamInteractable) is Item nav && characters.None(c => c.SelectedItem == nav) && nav.GetComponent() is Steering steering && steering.Voltage > steering.MinVoltage) { var order = new Order(OrderPrefab.Prefabs["steer"], steering.Item, steering); diff --git a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameMode.cs b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameMode.cs index 83b87c5ce..a3c45a280 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameMode.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameMode.cs @@ -3,8 +3,8 @@ namespace Barotrauma { partial class GameMode { - public virtual void Draw(SpriteBatch spriteBatch) - { - } + public virtual void HUDScaleChanged() { } + + public virtual void Draw(SpriteBatch spriteBatch) { } } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/MultiPlayerCampaign.cs b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/MultiPlayerCampaign.cs index c7d279a2d..a757aa34a 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/MultiPlayerCampaign.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/MultiPlayerCampaign.cs @@ -115,12 +115,16 @@ namespace Barotrauma partial void InitProjSpecific() { - var buttonContainer = new GUILayoutGroup(HUDLayoutSettings.ToRectTransform(HUDLayoutSettings.ButtonAreaTop, GUI.Canvas), - isHorizontal: true, childAnchor: Anchor.CenterRight) - { - CanBeFocused = false - }; + CreateButtons(); + } + public override void HUDScaleChanged() + { + CreateButtons(); + } + + private void CreateButtons() + { int buttonHeight = (int) (GUI.Scale * 40), buttonWidth = GUI.IntScale(450), buttonCenter = buttonHeight / 2, @@ -166,8 +170,6 @@ namespace Barotrauma }, UserData = "ReadyCheckButton" }; - - buttonContainer.Recalculate(); } private void InitCampaignUI() @@ -311,7 +313,7 @@ namespace Barotrauma if (prevControlled != null) { - prevControlled.SelectedConstruction = null; + prevControlled.SelectedItem = prevControlled.SelectedSecondaryItem = null; if (prevControlled.AIController != null) { prevControlled.AIController.Enabled = true; @@ -362,7 +364,7 @@ namespace Barotrauma float t = 0.0f; while (t < fadeOutDuration || endTransition.Running) { - t += CoroutineManager.UnscaledDeltaTime; + t += CoroutineManager.DeltaTime; overlayColor = Color.Lerp(Color.Transparent, Color.White, t / fadeOutDuration); yield return CoroutineStatus.Running; } @@ -469,7 +471,6 @@ namespace Barotrauma { base.End(transitionType); ForceMapUI = ShowCampaignUI = false; - UpgradeManager.CanUpgrade = true; // remove all event dialogue boxes GUIMessageBox.MessageBoxes.ForEachMod(mb => diff --git a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/SinglePlayerCampaign.cs b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/SinglePlayerCampaign.cs index fc3f8f71c..60814bd1c 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/SinglePlayerCampaign.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/SinglePlayerCampaign.cs @@ -169,10 +169,20 @@ namespace Barotrauma public static SinglePlayerCampaign Load(XElement element) => new SinglePlayerCampaign(element); private void InitUI() + { + CreateEndRoundButton(); + + campaignUIContainer = new GUIFrame(new RectTransform(Vector2.One, GUI.Canvas, Anchor.Center), style: "InnerGlow", color: Color.Black); + CampaignUI = new CampaignUI(this, campaignUIContainer) + { + StartRound = () => { TryEndRound(); } + }; + } + + private void CreateEndRoundButton() { int buttonHeight = (int)(GUI.Scale * 40); int buttonWidth = GUI.IntScale(450); - endRoundButton = new GUIButton(HUDLayoutSettings.ToRectTransform(new Rectangle((GameMain.GraphicsWidth / 2) - (buttonWidth / 2), HUDLayoutSettings.ButtonAreaTop.Center.Y - (buttonHeight / 2), buttonWidth, buttonHeight), GUI.Canvas), TextManager.Get("EndRound"), textAlignment: Alignment.Center, style: "EndRoundButton") { @@ -190,12 +200,11 @@ namespace Barotrauma return true; } }; + } - campaignUIContainer = new GUIFrame(new RectTransform(Vector2.One, GUI.Canvas, Anchor.Center), style: "InnerGlow", color: Color.Black); - CampaignUI = new CampaignUI(this, campaignUIContainer) - { - StartRound = () => { TryEndRound(); } - }; + public override void HUDScaleChanged() + { + CreateEndRoundButton(); } #endregion @@ -292,7 +301,7 @@ namespace Barotrauma yield return CoroutineStatus.Success; } overlayTextColor = Color.Lerp(Color.Transparent, Color.White, (timer - 1.0f) / fadeInDuration); - timer = Math.Min(timer + CoroutineManager.UnscaledDeltaTime, textDuration); + timer = Math.Min(timer + CoroutineManager.DeltaTime, textDuration); yield return CoroutineStatus.Running; } var outpost = GameMain.GameSession.Level.StartOutpost; @@ -320,7 +329,7 @@ namespace Barotrauma while (timer < fadeInDuration) { overlayColor = Color.Lerp(Color.LightGray, Color.Transparent, timer / fadeInDuration); - timer += CoroutineManager.UnscaledDeltaTime; + timer += CoroutineManager.DeltaTime; yield return CoroutineStatus.Running; } overlayColor = Color.Transparent; @@ -353,7 +362,7 @@ namespace Barotrauma if (prevControlled != null) { - prevControlled.SelectedConstruction = null; + prevControlled.SelectedItem = prevControlled.SelectedSecondaryItem = null; if (prevControlled.AIController != null) { prevControlled.AIController.Enabled = true; @@ -424,7 +433,7 @@ namespace Barotrauma float t = 0.0f; while (t < fadeOutDuration || endTransition.Running) { - t += CoroutineManager.UnscaledDeltaTime; + t += CoroutineManager.DeltaTime; overlayColor = Color.Lerp(Color.Transparent, Color.White, t / fadeOutDuration); yield return CoroutineStatus.Running; } @@ -436,6 +445,7 @@ namespace Barotrauma if (success) { GameMain.GameSession.SubmarineInfo = new SubmarineInfo(GameMain.GameSession.Submarine); + GameMain.GameSession.EventManager.RegisterEventHistory(); SaveUtil.SaveGame(GameMain.GameSession.SavePath); } else diff --git a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/CaptainTutorial.cs b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/CaptainTutorial.cs index 76cb87ce0..beb99fcb6 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/CaptainTutorial.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/CaptainTutorial.cs @@ -124,7 +124,7 @@ namespace Barotrauma.Tutorials captain_medicSpawnPos = Item.ItemList.Find(i => i.HasTag("captain_medicspawnpos")).WorldPosition; tutorial_submarineDoor = Item.ItemList.Find(i => i.HasTag("tutorial_submarinedoor")).GetComponent(); tutorial_submarineDoorLight = Item.ItemList.Find(i => i.HasTag("tutorial_submarinedoorlight")).GetComponent(); - var medicInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobOrJobPrefab: JobPrefab.Get("medicaldoctor")) + var medicInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobOrJobPrefab: JobPrefab.Get("medicaldoctor".ToIdentifier())) { TeamID = CharacterTeamType.Team1 }; @@ -148,21 +148,21 @@ namespace Barotrauma.Tutorials SetDoorAccess(tutorial_lockedDoor_1, null, false); SetDoorAccess(tutorial_lockedDoor_2, null, false); - var mechanicInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobOrJobPrefab: JobPrefab.Get("mechanic")) + var mechanicInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobOrJobPrefab: JobPrefab.Get("mechanic".ToIdentifier())) { TeamID = CharacterTeamType.Team1 }; captain_mechanic = Character.Create(mechanicInfo, WayPoint.GetRandom(SpawnType.Human, mechanicInfo.Job?.Prefab, Submarine.MainSub).WorldPosition, "mechanic"); captain_mechanic.GiveJobItems(); - var securityInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobOrJobPrefab: JobPrefab.Get("securityofficer")) + var securityInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobOrJobPrefab: JobPrefab.Get("securityofficer".ToIdentifier())) { TeamID = CharacterTeamType.Team1 }; captain_security = Character.Create(securityInfo, WayPoint.GetRandom(SpawnType.Human, securityInfo.Job?.Prefab, Submarine.MainSub).WorldPosition, "securityofficer"); captain_security.GiveJobItems(); - var engineerInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobOrJobPrefab: JobPrefab.Get("engineer")) + var engineerInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobOrJobPrefab: JobPrefab.Get("engineer".ToIdentifier())) { TeamID = CharacterTeamType.Team1 }; @@ -339,8 +339,8 @@ namespace Barotrauma.Tutorials private bool IsSelectedItem(Item item) { return - captain?.SelectedConstruction == item || - (captain?.SelectedConstruction?.linkedTo?.Contains(item) ?? false); + captain?.SelectedItem == item || + (captain?.SelectedItem?.linkedTo?.Contains(item) ?? false); } } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/DoctorTutorial.cs b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/DoctorTutorial.cs index 8d9ef63b1..442f36b07 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/DoctorTutorial.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/DoctorTutorial.cs @@ -119,7 +119,7 @@ namespace Barotrauma.Tutorials var patientHull2 = WayPoint.WayPointList.Find(wp => wp.IdCardDesc == "airlock").CurrentHull; medBay = WayPoint.WayPointList.Find(wp => wp.IdCardDesc == "medbay").CurrentHull; - var assistantInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobOrJobPrefab: JobPrefab.Get("assistant")) + var assistantInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobOrJobPrefab: JobPrefab.Get("assistant".ToIdentifier())) { TeamID = CharacterTeamType.Team1 }; @@ -130,7 +130,7 @@ namespace Barotrauma.Tutorials patient1.AddDamage(patient1.WorldPosition, new List() { new Affliction(AfflictionPrefab.Burn, 15.0f) }, stun: 0, playSound: false); patient1.AIController.Enabled = false; - assistantInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobOrJobPrefab: JobPrefab.Get("assistant")) + assistantInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobOrJobPrefab: JobPrefab.Get("assistant".ToIdentifier())) { TeamID = CharacterTeamType.Team1 }; @@ -139,7 +139,7 @@ namespace Barotrauma.Tutorials patient2.CanSpeak = false; patient2.AIController.Enabled = false; - var mechanicInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobOrJobPrefab: JobPrefab.Get("engineer")) + var mechanicInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobOrJobPrefab: JobPrefab.Get("engineer".ToIdentifier())) { TeamID = CharacterTeamType.Team1 }; @@ -148,13 +148,13 @@ namespace Barotrauma.Tutorials subPatient1.AddDamage(patient1.WorldPosition, new List() { new Affliction(AfflictionPrefab.Burn, 40.0f) }, stun: 0, playSound: false); subPatients.Add(subPatient1); - var securityInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobOrJobPrefab: JobPrefab.Get("securityofficer")); + var securityInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobOrJobPrefab: JobPrefab.Get("securityofficer".ToIdentifier())); var subPatient2 = Character.Create(securityInfo, WayPoint.GetRandom(SpawnType.Human, securityInfo.Job?.Prefab, Submarine.MainSub).WorldPosition, "3"); subPatient2.TeamID = CharacterTeamType.Team1; subPatient2.AddDamage(patient1.WorldPosition, new List() { new Affliction(AfflictionPrefab.InternalDamage, 40.0f) }, stun: 0, playSound: false); subPatients.Add(subPatient2); - var engineerInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobOrJobPrefab: JobPrefab.Get("engineer")) + var engineerInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobOrJobPrefab: JobPrefab.Get("engineer".ToIdentifier())) { TeamID = CharacterTeamType.Team1 }; @@ -262,7 +262,7 @@ namespace Barotrauma.Tutorials HighlightInventorySlot(doctor_suppliesCabinet.Inventory, i, highlightColor, .5f, .5f, 0f); } } - if (doctor.SelectedConstruction == doctor_suppliesCabinet.Item) + if (doctor.SelectedItem == doctor_suppliesCabinet.Item) { for (int i = 0; i < doctor.Inventory.Capacity; i++) { @@ -373,7 +373,7 @@ namespace Barotrauma.Tutorials HighlightInventorySlot(doctor_medBayCabinet.Inventory, i, highlightColor, .5f, .5f, 0f); } } - if (doctor.SelectedConstruction == doctor_medBayCabinet.Item) + if (doctor.SelectedItem == doctor_medBayCabinet.Item) { for (int i = 0; i < doctor.Inventory.Capacity; i++) { diff --git a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/EngineerTutorial.cs b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/EngineerTutorial.cs index b95fa6f31..3e30b7672 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/EngineerTutorial.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/EngineerTutorial.cs @@ -400,7 +400,7 @@ namespace Barotrauma.Tutorials wait -= 0.1f; engineer_reactor.AutoTemp = true; } while (wait > 0.0f); - engineer.SelectedConstruction = null; + engineer.SelectedItem = null; engineer_reactor.CanBeSelected = false; RemoveCompletedObjective(2); GameAnalyticsManager.AddDesignEvent("Tutorial:EngineerTutorial:Objective2"); @@ -513,7 +513,7 @@ namespace Barotrauma.Tutorials private bool IsSelectedItem(Item item) { - return engineer?.SelectedConstruction == item; + return engineer?.SelectedItem == item; } private IEnumerable ReactorOperatedProperly() @@ -568,7 +568,7 @@ namespace Barotrauma.Tutorials private void HandleJunctionBoxWiringHighlights() { - Item selected = engineer.SelectedConstruction; + Item selected = engineer.SelectedItem; if (!engineer.HasEquippedItem("screwdriver".ToIdentifier())) { diff --git a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/MechanicTutorial.cs b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/MechanicTutorial.cs index 06d05b708..e96dfc137 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/MechanicTutorial.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/MechanicTutorial.cs @@ -440,7 +440,7 @@ namespace Barotrauma.Tutorials bool gotSodium = false; do { - if (mechanic.SelectedConstruction == mechanic_craftingCabinet.Item) + if (mechanic.SelectedItem == mechanic_craftingCabinet.Item) { for (int i = 0; i < mechanic.Inventory.Capacity; i++) { @@ -702,7 +702,7 @@ namespace Barotrauma.Tutorials private bool IsSelectedItem(Item item) { - return mechanic?.SelectedConstruction == item; + return mechanic?.SelectedItem == item; } private bool WallHasDamagedSections(Structure wall) diff --git a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/OfficerTutorial.cs b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/OfficerTutorial.cs index dd0f49fe5..3cfb4551f 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/OfficerTutorial.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/OfficerTutorial.cs @@ -510,7 +510,7 @@ namespace Barotrauma.Tutorials private bool IsSelectedItem(Item item) { - return officer?.SelectedConstruction == item; + return officer?.SelectedItem == item; } private Character SpawnMonster(string speciesName, Vector2 pos) diff --git a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameSession.cs b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameSession.cs index 627f79236..dd566ee34 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameSession.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameSession.cs @@ -14,6 +14,7 @@ namespace Barotrauma public static bool IsTabMenuOpen => GameMain.GameSession?.tabMenu != null; public static TabMenu TabMenuInstance => GameMain.GameSession?.tabMenu; + private float prevHudScale; private TabMenu tabMenu; @@ -119,6 +120,7 @@ namespace Barotrauma return true; } }; + prevHudScale = GameSettings.CurrentConfig.Graphics.HUDScale; } public void AddToGUIUpdateList() @@ -178,6 +180,12 @@ namespace Barotrauma } } + public void HUDScaleChanged() + { + CreateTopLeftButtons(); + GameMode?.HUDScaleChanged(); + } + partial void UpdateProjSpecific(float deltaTime) { if (GUI.DisableHUD) { return; } diff --git a/Barotrauma/BarotraumaClient/ClientSource/GameSession/HintManager.cs b/Barotrauma/BarotraumaClient/ClientSource/GameSession/HintManager.cs index a7ee9cc4c..0dfc29ed7 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GameSession/HintManager.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GameSession/HintManager.cs @@ -112,19 +112,19 @@ namespace Barotrauma CheckReminders(); } - public static void OnSetSelectedConstruction(Character character, Item oldConstruction, Item newConstruction) + public static void OnSetSelectedItem(Character character, Item oldItem, Item newItem) { - if (oldConstruction == newConstruction) { return; } + if (oldItem == newItem) { return; } - if (Character.Controlled != null && Character.Controlled == character && oldConstruction != null && oldConstruction.GetComponent() == null) + if (Character.Controlled != null && Character.Controlled == character && oldItem != null && !oldItem.IsLadder) { TimeStoppedInteracting = Timing.TotalTime; } - if (newConstruction == null) { return; } - if (newConstruction.GetComponent() != null) { return; } - if (newConstruction.GetComponent() is ConnectionPanel cp && cp.User == character) { return; } - OnStartedInteracting(character, newConstruction); + if (newItem == null) { return; } + if (newItem.IsLadder) { return; } + if (newItem.GetComponent() is ConnectionPanel cp && cp.User == character) { return; } + OnStartedInteracting(character, newItem); } private static void OnStartedInteracting(Character character, Item item) @@ -177,10 +177,10 @@ namespace Barotrauma private static void CheckIsInteracting() { if (!CanDisplayHints()) { return; } - if (Character.Controlled?.SelectedConstruction == null) { return; } + if (Character.Controlled?.SelectedItem == null) { return; } - if (Character.Controlled.SelectedConstruction.GetComponent() is Reactor reactor && reactor.PowerOn && - Character.Controlled.SelectedConstruction.OwnInventory?.AllItems is IEnumerable containedItems && + if (Character.Controlled.SelectedItem.GetComponent() is Reactor reactor && reactor.PowerOn && + Character.Controlled.SelectedItem.OwnInventory?.AllItems is IEnumerable containedItems && containedItems.Count(i => i.HasTag("reactorfuel")) > 1) { if (DisplayHint("onisinteracting.reactorwithextrarods".ToIdentifier())) { return; } @@ -272,7 +272,7 @@ namespace Barotrauma if (!CanDisplayHints()) { return; } if (sonar == null || sonar.Removed) { return; } if (spottedCharacter == null || spottedCharacter.Removed || spottedCharacter.IsDead) { return; } - if (Character.Controlled.SelectedConstruction != sonar) { return; } + if (Character.Controlled.SelectedItem != sonar) { return; } if (HumanAIController.IsFriendly(Character.Controlled, spottedCharacter)) { return; } DisplayHint("onsonarspottedenemy".ToIdentifier()); } @@ -305,7 +305,7 @@ namespace Barotrauma { if (!CanDisplayHints()) { return; } if (character != Character.Controlled) { return; } - if (character.SelectedConstruction != null || character.FocusedItem != null) { return; } + if (character.HasSelectedAnyItem || character.FocusedItem != null) { return; } if (item == null || !item.IsShootable || !item.RequireAimToUse) { return; } if (TimeStoppedInteracting + 1 > Timing.TotalTime) { return; } if (GUI.MouseOn != null) { return; } @@ -317,7 +317,7 @@ namespace Barotrauma variables: new[] { ("[key]".ToIdentifier(), GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Aim)) }, onUpdate: () => { - if (character.SelectedConstruction == null && GUI.MouseOn == null && PlayerInput.KeyDown(InputType.Aim)) + if (character.SelectedItem == null && GUI.MouseOn == null && PlayerInput.KeyDown(InputType.Aim)) { ActiveHintMessageBox.Close(); } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/CharacterInventory.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/CharacterInventory.cs index 490516616..1645e1be1 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/CharacterInventory.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/CharacterInventory.cs @@ -562,7 +562,7 @@ namespace Barotrauma break; } //if putting an item to a container with a max stack size of 1, only put one item from the stack - if (quickUseAction == QuickUseAction.PutToContainer && (character.SelectedConstruction?.GetComponent()?.MaxStackSize ?? 0) <= 1) + if (quickUseAction == QuickUseAction.PutToContainer && (character.SelectedItem?.GetComponent()?.MaxStackSize ?? 0) <= 1) { break; } @@ -595,14 +595,14 @@ namespace Barotrauma if (rootInventory != null && rootInventory.Owner != Character.Controlled && - rootInventory.Owner != Character.Controlled.SelectedConstruction && + rootInventory.Owner != Character.Controlled.SelectedItem && rootInventory.Owner != Character.Controlled.SelectedCharacter) { //allow interacting if the container is linked to the item the character is interacting with if (!(rootContainer != null && rootContainer.DisplaySideBySideWhenLinked && - Character.Controlled.SelectedConstruction != null && - rootContainer.linkedTo.Contains(Character.Controlled.SelectedConstruction))) + Character.Controlled.SelectedItem != null && + rootContainer.linkedTo.Contains(Character.Controlled.SelectedItem))) { DraggingItems.Clear(); } @@ -756,7 +756,7 @@ namespace Barotrauma } else { - var selectedContainer = character.SelectedConstruction?.GetComponent(); + var selectedContainer = character.SelectedItem?.GetComponent(); if (selectedContainer != null && selectedContainer.Inventory != null && !selectedContainer.Inventory.Locked) @@ -775,7 +775,8 @@ namespace Barotrauma else { bool isEquippable = item.AllowedSlots.Any(s => s != InvSlotType.Any); - var selectedContainer = character.SelectedConstruction?.GetComponent(); + var selectedContainer = character.SelectedItem?.GetComponent(); + if (selectedContainer != null && selectedContainer.Inventory != null && !selectedContainer.Inventory.Locked && @@ -930,7 +931,7 @@ namespace Barotrauma } break; case QuickUseAction.PutToContainer: - var selectedContainer = character.SelectedConstruction?.GetComponent(); + var selectedContainer = character.SelectedItem?.GetComponent(); if (selectedContainer != null && selectedContainer.Inventory != null) { //player has selected the inventory of another item -> attempt to move the item there @@ -965,8 +966,8 @@ namespace Barotrauma } break; case QuickUseAction.PutToEquippedItem: - - foreach (Item heldItem in character.HeldItems) + //order by the condition of the contained item to prefer putting into the item with the emptiest ammo/battery/tank + foreach (Item heldItem in character.HeldItems.OrderBy(it => it.ContainedItems.FirstOrDefault()?.Condition ?? 0.0f)) { if (heldItem.OwnInventory == null) { continue; } //don't allow swapping if we're moving items into an item with 1 slot holding a stack of items diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Holdable/IdCard.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Holdable/IdCard.cs index bd2b6da47..e19b1dd82 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Holdable/IdCard.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Holdable/IdCard.cs @@ -23,11 +23,10 @@ namespace Barotrauma.Items.Components public void ExtractJobPrefab(IReadOnlyDictionary tags) { - if (!tags.TryGetValue("jobid".ToIdentifier(), out string jobId)) { return; } - + if (!tags.TryGetValue("jobid".ToIdentifier(), out string jobId)) { return; } if (!jobId.IsNullOrEmpty()) { - JobPrefab = JobPrefab.Get(jobId); + JobPrefab = JobPrefab.Get(jobId.ToIdentifier()); } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/ItemComponent.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/ItemComponent.cs index d331fc8a7..c60171bfe 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/ItemComponent.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/ItemComponent.cs @@ -522,13 +522,11 @@ namespace Barotrauma.Items.Components if (soundSelectionModes == null) soundSelectionModes = new Dictionary(); if (!soundSelectionModes.ContainsKey(type) || soundSelectionModes[type] == SoundSelectionMode.Random) { - SoundSelectionMode selectionMode = SoundSelectionMode.Random; - Enum.TryParse(subElement.GetAttributeString("selectionmode", "Random"), out selectionMode); + Enum.TryParse(subElement.GetAttributeString("selectionmode", "Random"), out SoundSelectionMode selectionMode); soundSelectionModes[type] = selectionMode; } - List soundList = null; - if (!sounds.TryGetValue(itemSound.Type, out soundList)) + if (!sounds.TryGetValue(itemSound.Type, out List soundList)) { soundList = new List(); sounds.Add(itemSound.Type, soundList); @@ -566,6 +564,9 @@ namespace Barotrauma.Items.Components } string style = GuiFrameSource.Attribute("style") == null ? null : GuiFrameSource.GetAttributeString("style", ""); GuiFrame = new GUIFrame(RectTransform.Load(GuiFrameSource, GUI.Canvas, Anchor.Center), style, color); + + TryCreateDragHandle(); + DefaultLayout = GUILayoutSettings.Load(GuiFrameSource); if (GuiFrame != null) { @@ -574,6 +575,22 @@ namespace Barotrauma.Items.Components GameMain.Instance.ResolutionChanged += OnResolutionChanged; } + protected void TryCreateDragHandle() + { + if (GuiFrame != null && GuiFrameSource.GetAttributeBool("draggable", true)) + { + var handle = new GUIDragHandle(new RectTransform(Vector2.One, GuiFrame.RectTransform, Anchor.Center), + GuiFrame.RectTransform, style: null) + { + DragArea = HUDLayoutSettings.ItemHUDArea + }; + + int iconHeight = GUIStyle.ItemFrameMargin.Y / 4; + new GUIImage(new RectTransform(new Point(GuiFrame.Rect.Width, iconHeight), handle.RectTransform, Anchor.TopCenter) { AbsoluteOffset = new Point(0, iconHeight / 2) }, + style: "GUIDragIndicatorHorizontal"); + } + } + /// /// Overload this method and implement. The method is automatically called when the resolution changes. /// diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/ItemContainer.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/ItemContainer.cs index b1d894203..5fe21e897 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/ItemContainer.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/ItemContainer.cs @@ -189,7 +189,7 @@ namespace Barotrauma.Items.Components onDraw: (SpriteBatch spriteBatch, GUICustomComponent component) => { Inventory.Draw(spriteBatch); }, onUpdate: null) { - CanBeFocused = false + CanBeFocused = true }; // Expand the frame vertically if it's too small to fit the text @@ -381,10 +381,15 @@ namespace Barotrauma.Items.Components guiCustomComponent.RectTransform.Parent = Inventory.RectTransform; } + if (item.ParentInventory?.Owner == character && character.SelectedItem == item) + { + character.SelectedItem = null; + } + //if the item is in the character's inventory, no need to update the item's inventory - //because the player can see it by hovering the cursor over the item - guiCustomComponent.Visible = item.ParentInventory?.Owner != character && DrawInventory; - if (!guiCustomComponent.Visible) { return; } + //because the player can see it by hovering the cursor over the item + guiCustomComponent.Visible = DrawInventory && item.ParentInventory?.Owner != character; + if (!guiCustomComponent.Visible) { return; } Inventory.Update(deltaTime, cam); } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Deconstructor.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Deconstructor.cs index 52c211c18..1eeedca4b 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Deconstructor.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Deconstructor.cs @@ -1,4 +1,5 @@ -using Barotrauma.Extensions; +using System.Collections.Generic; +using System.Collections.Immutable; using Barotrauma.Networking; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; @@ -15,6 +16,7 @@ namespace Barotrauma.Items.Components } private GUIButton activateButton; private GUIComponent inputInventoryHolder, outputInventoryHolder; + private GUIListBox outputDisplayListBox; private GUIComponent inSufficientPowerWarning; @@ -44,32 +46,43 @@ namespace Barotrauma.Items.Components protected override void CreateGUI() { - var paddedFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.90f, 0.80f), GuiFrame.RectTransform, Anchor.Center), childAnchor: Anchor.TopCenter) + var paddedFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.88f), GuiFrame.RectTransform, Anchor.Center), childAnchor: Anchor.TopCenter) { - Stretch = true, + Stretch = true, RelativeSpacing = 0.08f }; - new GUITextBlock(new RectTransform(new Vector2(1f, 0.07f), paddedFrame.RectTransform), item.Name, font: GUIStyle.SubHeadingFont) + new GUITextBlock(new RectTransform(new Vector2(1f, 0.07f), paddedFrame.RectTransform) { MinSize = new Point(0, GUI.IntScale(25)) }, item.Name, font: GUIStyle.SubHeadingFont) { TextAlignment = Alignment.Center, AutoScaleHorizontal = true }; - var topFrame = new GUIFrame(new RectTransform(new Vector2(1f, 0.5f), paddedFrame.RectTransform), style: null); - + var topFrame = new GUIFrame(new RectTransform(new Vector2(1f, 0.375f), paddedFrame.RectTransform), style: null); + // === INPUT LABEL === // - var inputLabelArea = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.15f), topFrame.RectTransform, Anchor.TopCenter), childAnchor: Anchor.CenterLeft, isHorizontal: true) - { - Stretch = true, - RelativeSpacing = 0.05f - }; - var inputLabel = new GUITextBlock(new RectTransform(Vector2.One, inputLabelArea.RectTransform), TextManager.Get("deconstructor.input", "uilabel.input"), font: GUIStyle.SubHeadingFont) { Padding = Vector4.Zero }; - inputLabel.RectTransform.Resize(new Point((int) inputLabel.Font.MeasureString(inputLabel.Text).X, inputLabel.RectTransform.Rect.Height)); - new GUIFrame(new RectTransform(Vector2.One, inputLabelArea.RectTransform), style: "HorizontalLine"); + var inputLabelArea = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.15f), topFrame.RectTransform, Anchor.TopCenter), childAnchor: Anchor.CenterLeft, isHorizontal: true); + + var queueLabelLayout = new GUILayoutGroup(new RectTransform(new Vector2(0.43f, 1f), inputLabelArea.RectTransform), childAnchor: Anchor.CenterLeft, isHorizontal: true) + { + Stretch = true, + RelativeSpacing = 0.05f + }; + var queueLabel = new GUITextBlock(new RectTransform(Vector2.One, queueLabelLayout.RectTransform), TextManager.Get("deconstructor.inputqueue"), font: GUIStyle.SubHeadingFont) { Padding = Vector4.Zero }; + queueLabel.RectTransform.Resize(new Point((int) queueLabel.Font.MeasureString(queueLabel.Text).X, queueLabel.RectTransform.Rect.Height)); + new GUIFrame(new RectTransform(Vector2.One, queueLabelLayout.RectTransform), style: "HorizontalLine"); + + var inputLabelLayout = new GUILayoutGroup(new RectTransform(new Vector2(0.57f, 1f), inputLabelArea.RectTransform), childAnchor: Anchor.CenterLeft, isHorizontal: true) + { + Stretch = true, + RelativeSpacing = 0.05f + }; + var inputLabel = new GUITextBlock(new RectTransform(Vector2.One, inputLabelLayout.RectTransform), TextManager.Get("deconstructor.input", "uilabel.input"), font: GUIStyle.SubHeadingFont) { Padding = Vector4.Zero }; + inputLabel.RectTransform.Resize(new Point((int) inputLabel.Font.MeasureString(inputLabel.Text).X, inputLabel.RectTransform.Rect.Height)); + new GUIFrame(new RectTransform(Vector2.One, inputLabelLayout.RectTransform), style: "HorizontalLine"); var inputArea = new GUILayoutGroup(new RectTransform(new Vector2(1f, 1f), topFrame.RectTransform, Anchor.CenterLeft), childAnchor: Anchor.BottomLeft, isHorizontal: true) { Stretch = true, RelativeSpacing = 0.05f }; - + // === INPUT SLOTS === // inputInventoryHolder = new GUIFrame(new RectTransform(new Vector2(0.7f, 1f), inputArea.RectTransform), style: null); new GUICustomComponent(new RectTransform(Vector2.One, inputInventoryHolder.RectTransform), DrawOverLay, null) { CanBeFocused = false }; @@ -92,8 +105,8 @@ namespace Barotrauma.Items.Components }; // === OUTPUT AREA === // - var bottomFrame = new GUIFrame(new RectTransform(new Vector2(1f, 0.5f), paddedFrame.RectTransform), style: null); - + var bottomFrame = new GUIFrame(new RectTransform(new Vector2(1f, 0.375f), paddedFrame.RectTransform), style: null); + // === OUTPUT LABEL === // var outputLabelArea = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.15f), bottomFrame.RectTransform, Anchor.TopCenter), childAnchor: Anchor.CenterLeft, isHorizontal: true) { @@ -104,10 +117,16 @@ namespace Barotrauma.Items.Components outputLabel.RectTransform.Resize(new Point((int) outputLabel.Font.MeasureString(outputLabel.Text).X, outputLabel.RectTransform.Rect.Height)); new GUIFrame(new RectTransform(Vector2.One, outputLabelArea.RectTransform), style: "HorizontalLine"); - var outputArea = new GUILayoutGroup(new RectTransform(new Vector2(1f, 1f), bottomFrame.RectTransform, Anchor.CenterLeft), childAnchor: Anchor.BottomLeft, isHorizontal: true) { Stretch = true, RelativeSpacing = 0.05f }; + var outputArea = new GUILayoutGroup(new RectTransform(new Vector2(1f, 1f), bottomFrame.RectTransform, Anchor.CenterLeft), childAnchor: Anchor.BottomLeft, isHorizontal: true) { Stretch = true, RelativeSpacing = 0.05f }; - // === OUTPUT SLOTS === // - outputInventoryHolder = new GUIFrame(new RectTransform(new Vector2(1f - InfoAreaWidth, 1f), outputArea.RectTransform, Anchor.CenterLeft), style: null); + // === OUTPUT SLOTS === // + outputInventoryHolder = new GUIFrame(new RectTransform(new Vector2(1f - InfoAreaWidth, 1f), outputArea.RectTransform, Anchor.CenterLeft), style: null); + + GUILayoutGroup outputDisplayLayout = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.25f), paddedFrame.RectTransform), childAnchor: Anchor.TopCenter); + GUILayoutGroup outDisplayTopGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.2f), outputDisplayLayout.RectTransform), isHorizontal: true); + GUITextBlock outDisplayBlock = new GUITextBlock(new RectTransform(Vector2.One, outDisplayTopGroup.RectTransform), TextManager.Get("deconstructor.output"), font: GUIStyle.SubHeadingFont) { Padding = Vector4.Zero }; + GUILayoutGroup outDisplayBottomGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.975f, 0.8f), outputDisplayLayout.RectTransform), isHorizontal: true); + outputDisplayListBox = new GUIListBox(new RectTransform(new Vector2(1f, 1f), outDisplayBottomGroup.RectTransform), isHorizontal: true, style: null); if (InfoAreaWidth >= 0.0f) { @@ -181,7 +200,7 @@ namespace Barotrauma.Items.Components { if (!(linkedTo is Item { DisplaySideBySideWhenLinked: true } linkedItem)) { continue; } if (!linkedItem.Components.Any()) { continue; } - + var itemContainer = linkedItem.GetComponent(); if (itemContainer?.GuiFrame == null || itemContainer.AllowUIOverlap) { continue; } @@ -195,6 +214,170 @@ namespace Barotrauma.Items.Components return base.Select(character); } + partial void OnItemSlotsChanged(ItemContainer container) + { + if (container.Inventory is null) { return; } + RefreshOutputDisplay(container.Inventory.AllItems.ToImmutableArray()); + } + + private void RefreshOutputDisplay(ImmutableArray items) + { + const string outputItemCountUserData = "OutputItemCount"; + const string questionMarkUserData = "UnknownItemOutput"; + + if (outputDisplayListBox is null || inputContainer.Inventory is null) { return; } + + Dictionary itemCounts = new Dictionary(); + Dictionary children = new Dictionary(); + + bool addQuestionMark = false; + + foreach (GUIComponent child in outputDisplayListBox.Content.Children) + { + if (child.UserData is Identifier it) + { + children.Add(it, child); + } + } + + if (outputDisplayListBox.Content.FindChild(questionMarkUserData) is { } foundChild) + { + outputDisplayListBox.RemoveChild(foundChild); + } + + foreach (Item it in items) + { + if (it.Prefab.RandomDeconstructionOutput) + { + addQuestionMark = true; + continue; + } + + foreach (DeconstructItem deconstructItem in it.Prefab.DeconstructItems) + { + RegisterItem(deconstructItem.ItemIdentifier); + } + + if (it.OwnInventory is { } inventory) + { + foreach (Item inventoryItems in inventory.AllItems) + { + RegisterItem(inventoryItems.Prefab.Identifier); + } + } + + void RegisterItem(Identifier identifier) + { + if (itemCounts.ContainsKey(identifier)) + { + itemCounts[identifier]++; + return; + } + + itemCounts.Add(identifier, 1); + } + } + + foreach (var (it, child) in children) + { + if (!itemCounts.ContainsKey(it)) + { + outputDisplayListBox.RemoveChild(child); + } + } + + foreach (var (it, amount) in itemCounts) + { + if (!children.TryGetValue(it, out GUIComponent child)) + { + child = CreateOutputDisplayItem(it, outputDisplayListBox.Content); + } + + if (child is null) { continue; } + UpdateOutputDisplayItemCount(child, amount); + } + + if (addQuestionMark) + { + CreateQuestionMark(outputDisplayListBox.Content); + } + + static void CreateQuestionMark(GUIComponent parent) + { + GUIFrame itemFrame = new GUIFrame(new RectTransform(new Vector2(0.1f, 1f), parent.RectTransform), style: null) + { + UserData = questionMarkUserData, + ToolTip = TextManager.Get("deconstructor.unknownitemsoutput") + }; + + GUIFrame questionMarkFrame = new GUIFrame(new RectTransform(Vector2.One, itemFrame.RectTransform, scaleBasis: ScaleBasis.Smallest, anchor: Anchor.Center), style: "GUIFrameListBox") + { + CanBeFocused = false, + }; + + // question mark text + new GUITextBlock(new RectTransform(Vector2.One, questionMarkFrame.RectTransform, anchor: Anchor.Center), text: "?", textAlignment: Alignment.Center, font: GUIStyle.LargeFont) + { + CanBeFocused = false + }; + } + + static GUIComponent CreateOutputDisplayItem(Identifier identifier, GUIComponent parent) + { + ItemPrefab prefab = ItemPrefab.Find(null, identifier); + if (prefab is null) { return null; } + + GUIFrame itemFrame = new GUIFrame(new RectTransform(new Vector2(0.1f, 1f), parent.RectTransform), style: null) + { + UserData = identifier, + ToolTip = GetTooltip(prefab) + }; + + Sprite icon = prefab.InventoryIcon ?? prefab.Sprite; + Color iconColor = prefab.InventoryIcon is null ? prefab.SpriteColor : prefab.InventoryIconColor; + + GUIImage itemIcon = new GUIImage(new RectTransform(Vector2.One, itemFrame.RectTransform, scaleBasis: ScaleBasis.Smallest, anchor: Anchor.Center), sprite: icon, scaleToFit: true) + { + Color = iconColor, + CanBeFocused = false + }; + + // item count text + new GUITextBlock(new RectTransform(new Vector2(0.5f, 0.5f), itemIcon.RectTransform, anchor: Anchor.BottomRight), "", font: GUIStyle.Font, textAlignment: Alignment.BottomRight) + { + UserData = outputItemCountUserData, + Shadow = true, + CanBeFocused = false, + Padding = Vector4.Zero, + TextColor = Color.White, + }; + + return itemFrame; + } + + static void UpdateOutputDisplayItemCount(GUIComponent component, int count) + { + if (!(component.FindChild(outputItemCountUserData, recursive: true) is GUITextBlock textBlock)) { return; } + + textBlock.Text = TextManager.GetWithVariable("campaignstore.quantity", "[amount]", count.ToString()); + } + + static RichString GetTooltip(ItemPrefab prefab) + { + LocalizedString toolTip = $"‖color:{Color.White.ToStringHex()}‖{prefab.Name}‖color:end‖"; + + LocalizedString description = prefab.Description; + if (!description.IsNullOrEmpty()) { toolTip += '\n' + description; } + + if (prefab.ContentPackage != GameMain.VanillaContent && prefab.ContentPackage != null) + { + toolTip += $"\n‖color:{Color.MediumPurple.ToStringHex()}‖{prefab.ContentPackage.Name}‖color:end‖"; + } + + return RichString.Rich(toolTip); + } + } + partial void OnItemLoadedProjSpecific() { inputContainer.AllowUIOverlap = true; @@ -208,7 +391,7 @@ namespace Barotrauma.Items.Components overlayComponent.RectTransform.SetAsLastChild(); if (!(inputContainer?.Inventory?.visualSlots is { } visualSlots)) { return; } - + if (DeconstructItemsSimultaneously) { for (int i = 0; i < InputContainer.Inventory.Capacity; i++) diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/MiniMap.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/MiniMap.cs index 371d3882b..5a917c369 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/MiniMap.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/MiniMap.cs @@ -246,6 +246,7 @@ namespace Barotrauma.Items.Components protected override void CreateGUI() { GuiFrame.ClearChildren(); + TryCreateDragHandle(); GuiFrame.RectTransform.RelativeOffset = new Vector2(0.05f, 0.0f); GuiFrame.CanBeFocused = true; diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/OutpostTerminal.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/OutpostTerminal.cs index 2798830ae..8c09ef322 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/OutpostTerminal.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/OutpostTerminal.cs @@ -25,7 +25,7 @@ namespace Barotrauma.Items.Components public override void Update(float deltaTime, Camera cam) { - if (Character.Controlled?.SelectedConstruction != item) + if (Character.Controlled?.SelectedItem != item) { IsActive = false; return; diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Steering.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Steering.cs index d85bca980..8eed52986 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Steering.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Steering.cs @@ -871,13 +871,11 @@ namespace Barotrauma.Items.Components posToMaintain = item.Submarine.WorldPosition; } MaintainPos = true; - if (userdata is Vector2) + if (userdata is Vector2 nudgeAmount) { - Sonar sonar = item.GetComponent(); - Vector2 nudgeAmount = (Vector2)userdata; - if (sonar != null) + if (item.GetComponent() is Sonar sonar) { - nudgeAmount *= sonar == null ? 500.0f : 500.0f / sonar.Zoom; + nudgeAmount *= 500.0f / sonar.Zoom; } PosToMaintain += nudgeAmount; } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Repairable.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Repairable.cs index 156e1afc1..20fc3437e 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Repairable.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Repairable.cs @@ -59,7 +59,7 @@ namespace Barotrauma.Items.Components public override bool ShouldDrawHUD(Character character) { if (item.HiddenInGame) { return false; } - if (!HasRequiredItems(character, false) || character.SelectedConstruction != item) { return false; } + if (!HasRequiredItems(character, false) || character.SelectedItem != item) { return false; } if (character.IsTraitor && item.ConditionPercentage > MinSabotageCondition) { return true; } float defaultMaxCondition = item.MaxCondition / item.MaxRepairConditionMultiplier; @@ -110,6 +110,7 @@ namespace Barotrauma.Items.Components if (GuiFrame != null) { GuiFrame.ClearChildren(); + TryCreateDragHandle(); CreateGUI(); } } @@ -265,7 +266,7 @@ namespace Barotrauma.Items.Components } } - if (CurrentFixer != null && CurrentFixer.SelectedConstruction == item) + if (CurrentFixer != null && CurrentFixer.SelectedItem == item) { if (repairSoundChannel == null || !repairSoundChannel.IsPlaying) { diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Signal/ConnectionPanel.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Signal/ConnectionPanel.cs index 541c54a63..c0d624511 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Signal/ConnectionPanel.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Signal/ConnectionPanel.cs @@ -33,10 +33,16 @@ namespace Barotrauma.Items.Components originalMaxSize = GuiFrame.RectTransform.MaxSize; originalRelativeSize = GuiFrame.RectTransform.RelativeSize; CheckForLabelOverlap(); - new GUICustomComponent(new RectTransform(Vector2.One, GuiFrame.RectTransform), DrawConnections, null) + var content = new GUICustomComponent(new RectTransform(Vector2.One, GuiFrame.RectTransform), DrawConnections, null) { UserData = this }; + content.RectTransform.SetAsFirstChild(); + + //prevents inputs from going through the GUICustomComponent to the drag handle + var blocker = new GUIFrame(new RectTransform(GuiFrame.Rect.Size - GUIStyle.ItemFrameMargin, GuiFrame.RectTransform, Anchor.Center) + { AbsoluteOffset = GUIStyle.ItemFrameOffset }, + style: null); } public void TriggerRewiringSound() @@ -62,7 +68,7 @@ namespace Barotrauma.Items.Components } rewireSoundTimer -= deltaTime; - if (user != null && user.SelectedConstruction == item && rewireSoundTimer > 0.0f) + if (user != null && user.SelectedItem == item && rewireSoundTimer > 0.0f) { if (rewireSoundChannel == null || !rewireSoundChannel.IsPlaying) { @@ -85,12 +91,12 @@ namespace Barotrauma.Items.Components public override bool ShouldDrawHUD(Character character) { - return character == Character.Controlled && character == user && character.SelectedConstruction == item; + return character == Character.Controlled && character == user && character.SelectedItem == item; } public override void UpdateHUD(Character character, float deltaTime, Camera cam) { - if (character != Character.Controlled || character != user || character.SelectedConstruction != item) { return; } + if (character != Character.Controlled || character != user || character.SelectedItem != item) { return; } if (HighlightedWire != null) { diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Signal/Wire.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Signal/Wire.cs index e0b3a75f0..4c1ac0f07 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Signal/Wire.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Signal/Wire.cs @@ -311,7 +311,7 @@ namespace Barotrauma.Items.Components Wire equippedWire = Character.Controlled.HeldItems.FirstOrDefault(it => it.GetComponent() != null)?.GetComponent(); if (equippedWire != null && GUI.MouseOn == null) { - if (PlayerInput.PrimaryMouseButtonClicked() && Character.Controlled.SelectedConstruction == null) + if (PlayerInput.PrimaryMouseButtonClicked() && Character.Controlled.SelectedItem == null) { equippedWire.Use(1.0f, Character.Controlled); } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Inventory.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Inventory.cs index d4ad96681..b64fda77a 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Inventory.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Inventory.cs @@ -364,7 +364,7 @@ namespace Barotrauma get { return Character.Controlled != null && - Character.Controlled.SelectedConstruction == null && + !Character.Controlled.HasSelectedAnyItem && CharacterHealth.OpenHealthWindow == null && DraggingItems.Any(); } @@ -924,9 +924,9 @@ namespace Barotrauma } } - if (Character.Controlled.SelectedConstruction != null) + if (Character.Controlled.SelectedItem != null) { - foreach (var ic in Character.Controlled.SelectedConstruction.ActiveHUDs) + foreach (var ic in Character.Controlled.SelectedItem.ActiveHUDs) { var itemContainer = ic as ItemContainer; if (itemContainer?.Inventory?.visualSlots == null) { continue; } @@ -1003,9 +1003,9 @@ namespace Barotrauma } } - if (character.SelectedConstruction != null) + if (character.SelectedItem != null) { - foreach (var ic in character.SelectedConstruction.ActiveHUDs) + foreach (var ic in character.SelectedItem.ActiveHUDs) { var itemContainer = ic as ItemContainer; if (itemContainer?.Inventory?.visualSlots == null) { continue; } @@ -1341,27 +1341,29 @@ namespace Barotrauma } else { - var rootOwner = (selectedSlot.ParentInventory?.Owner as Item)?.GetRootInventoryOwner(); - if (selectedSlot.ParentInventory?.Owner != Character.Controlled && - selectedSlot.ParentInventory?.Owner != Character.Controlled.SelectedCharacter && - selectedSlot.ParentInventory?.Owner != Character.Controlled.SelectedConstruction && - !(Character.Controlled.SelectedConstruction?.linkedTo.Contains(selectedSlot.ParentInventory?.Owner) ?? false) && - rootOwner != Character.Controlled && - rootOwner != Character.Controlled.SelectedCharacter && - rootOwner != Character.Controlled.SelectedConstruction && - !(Character.Controlled.SelectedConstruction?.linkedTo.Contains(rootOwner) ?? false)) + static bool OwnerInaccessible(Entity owner) => + owner != Character.Controlled && + owner != Character.Controlled.SelectedCharacter && + owner != Character.Controlled.SelectedItem && + (Character.Controlled.SelectedItem == null || !Character.Controlled.SelectedItem.linkedTo.Contains(owner)); + + Entity owner = selectedSlot.ParentInventory?.Owner; + Entity rootOwner = (owner as Item)?.GetRootInventoryOwner(); + if (OwnerInaccessible(owner) && (rootOwner == owner || OwnerInaccessible(rootOwner))) { return false; } - var parentItem = (selectedSlot?.ParentInventory?.Owner as Item) ?? selectedSlot?.Item; - if ((parentItem?.GetRootInventoryOwner() is Character ownerCharacter) && - ownerCharacter == Character.Controlled && - CharacterHealth.OpenHealthWindow?.Character != ownerCharacter && - ownerCharacter.Inventory.IsInLimbSlot(parentItem, InvSlotType.HealthInterface) && - Screen.Selected != GameMain.SubEditorScreen) + Item parentItem = (owner as Item) ?? selectedSlot?.Item; + if (parentItem?.GetRootInventoryOwner() is Character ownerCharacter) { - highlightedSubInventorySlots.RemoveWhere(s => s.Item == parentItem); - return false; + if (ownerCharacter == Character.Controlled && + CharacterHealth.OpenHealthWindow?.Character != ownerCharacter && + ownerCharacter.Inventory.IsInLimbSlot(parentItem, InvSlotType.HealthInterface) && + Screen.Selected != GameMain.SubEditorScreen) + { + highlightedSubInventorySlots.RemoveWhere(s => s.Item == parentItem); + return false; + } } } return true; @@ -1725,7 +1727,8 @@ namespace Barotrauma if (inventory != null && !inventory.Locked && Character.Controlled?.Inventory == inventory && - slot.InventoryKeyIndex != -1) + slot.InventoryKeyIndex != -1 && + slot.InventoryKeyIndex < GameSettings.CurrentConfig.InventoryKeyMap.Bindings.Length) { spriteBatch.Draw(slotHotkeySprite.Texture, rect.ScaleSize(1.15f), slotHotkeySprite.SourceRect, slotColor); GUI.DrawString(spriteBatch, rect.Location.ToVector2() + new Vector2((int)(4.25f * UIScale), (int)Math.Ceiling(-1.5f * UIScale)), GameSettings.CurrentConfig.InventoryKeyMap.Bindings[slot.InventoryKeyIndex].Name, Color.Black, font: GUIStyle.HotkeyFont); diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Item.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Item.cs index 32610f313..7431e8dda 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Item.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Item.cs @@ -982,7 +982,7 @@ namespace Barotrauma List elementsToMove = new List(); if (editingHUD != null && editingHUD.UserData == this && - ((HasInGameEditableProperties && Character.Controlled?.SelectedConstruction == this) || Screen.Selected == GameMain.SubEditorScreen)) + ((HasInGameEditableProperties && Character.Controlled?.SelectedItem == this) || Screen.Selected == GameMain.SubEditorScreen)) { elementsToMove.Add(editingHUD); } @@ -1042,7 +1042,7 @@ namespace Barotrauma public void UpdateHUD(Camera cam, Character character, float deltaTime) { bool editingHUDCreated = false; - if ((HasInGameEditableProperties && (character.SelectedConstruction == this || EditableWhenEquipped)) || + if ((HasInGameEditableProperties && (character.SelectedItem == this || EditableWhenEquipped)) || Screen.Selected == GameMain.SubEditorScreen) { GUIComponent prevEditingHUD = editingHUD; @@ -1126,7 +1126,7 @@ namespace Barotrauma foreach (Character otherCharacter in Character.CharacterList) { if (otherCharacter != character && - otherCharacter.SelectedConstruction == this) + otherCharacter.SelectedItem == this) { ItemInUseWarning.Visible = true; if (mergedHUDRect.Width > GameMain.GraphicsWidth / 2) { mergedHUDRect.Inflate(-GameMain.GraphicsWidth / 4, 0); } @@ -1145,7 +1145,7 @@ namespace Barotrauma public void DrawHUD(SpriteBatch spriteBatch, Camera cam, Character character) { - if (HasInGameEditableProperties && (character.SelectedConstruction == this || EditableWhenEquipped)) + if (HasInGameEditableProperties && (character.SelectedItem == this || EditableWhenEquipped)) { DrawEditing(spriteBatch, cam); } @@ -1215,6 +1215,7 @@ namespace Barotrauma if (ic.DisplayMsg.IsNullOrEmpty()) { continue; } if (!ic.CanBePicked && !ic.CanBeSelected) { continue; } if (ic is Holdable holdable && !holdable.CanBeDeattached()) { continue; } + if (ic is ConnectionPanel connectionPanel && !connectionPanel.CanRewire()) { continue; } Color color = Color.Gray; if (ic.HasRequiredItems(character, false)) @@ -1246,15 +1247,15 @@ namespace Barotrauma } else { - if (HasInGameEditableProperties && Character.Controlled != null && (Character.Controlled.SelectedConstruction == this || EditableWhenEquipped)) + if (HasInGameEditableProperties && Character.Controlled != null && (Character.Controlled.SelectedItem == this || EditableWhenEquipped)) { if (editingHUD != null && editingHUD.UserData == this) { editingHUD.AddToGUIUpdateList(); } } } - if (Character.Controlled != null && Character.Controlled.SelectedConstruction != this && GetComponent() == null) + if (Character.Controlled != null && Character.Controlled.SelectedItem != this && GetComponent() == null) { - if (Character.Controlled.SelectedConstruction?.GetComponent()?.TargetItem != this && + if (Character.Controlled.SelectedItem?.GetComponent()?.TargetItem != this && !Character.Controlled.HeldItems.Any(it => it.GetComponent()?.TargetItem == this)) { return; diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/ItemInventory.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/ItemInventory.cs index 20ab00f8a..35e6f8385 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/ItemInventory.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/ItemInventory.cs @@ -1,5 +1,4 @@ -using System; -using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using System.Linq; @@ -17,7 +16,7 @@ namespace Barotrauma { if (PlayerInput.KeyHit(InputType.Select)) { - Character.Controlled.SelectedConstruction = null; + Character.Controlled.SelectedItem = null; } }*/ } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Map/MapEntity.cs b/Barotrauma/BarotraumaClient/ClientSource/Map/MapEntity.cs index 0b0bec78b..b07a40828 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Map/MapEntity.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Map/MapEntity.cs @@ -232,8 +232,7 @@ namespace Barotrauma { foreach (MapEntity e in mapEntityList) { - if (!e.SelectableInEditor) continue; - + if (!e.SelectableInEditor) { continue; } if (e.IsMouseOn(position)) { int i = 0; @@ -243,9 +242,7 @@ namespace Barotrauma { i++; } - highlightedEntities.Insert(i, e); - if (i == 0) highLightedEntity = e; } } @@ -741,7 +738,14 @@ namespace Barotrauma /// public static void DrawSelecting(SpriteBatch spriteBatch, Camera cam) { - if (GUI.MouseOn != null) return; + if (Screen.Selected is SubEditorScreen subEditor) + { + if (subEditor.IsMouseOnEditorGUI()) { return; } + } + else if (GUI.MouseOn != null) + { + return; + } Vector2 position = PlayerInput.MousePosition; position = cam.ScreenToWorld(position); @@ -1093,6 +1097,10 @@ namespace Barotrauma resizeDirY = y; resizing = true; startMovingPos = Vector2.Zero; + foreach (var mapEntity in mapEntityList) + { + if (mapEntity != this) { mapEntity.isHighlighted = false; } + } } } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/GameClient.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/GameClient.cs index e5a4c4b0d..532928c46 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Networking/GameClient.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/GameClient.cs @@ -1202,6 +1202,8 @@ namespace Barotrauma.Networking connected = false; var prevContentPackages = clientPeer.ServerContentPackages; + //decrement lobby update ID to make sure we update the lobby when we reconnect + GameMain.NetLobbyScreen.LastUpdateID--; ConnectToServer(serverEndpoint, serverName); if (clientPeer != null) { @@ -3271,8 +3273,8 @@ namespace Barotrauma.Networking if (gameStarted && Screen.Selected == GameMain.GameScreen) { - var controller = Character.Controlled?.SelectedConstruction?.GetComponent(); - bool disableButtons = Character.Controlled != null && (controller != null && controller.HideHUD); + bool disableButtons = Character.Controlled?.SelectedItem?.GetComponent() is Controller c1 && c1.HideHUD || + Character.Controlled?.SelectedSecondaryItem?.GetComponent() is Controller c2 && c2.HideHUD; buttonContainer.Visible = !disableButtons; if (!GUI.DisableHUD && !GUI.DisableUpperHUD) diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/Voip/VoipCapture.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/Voip/VoipCapture.cs index f1c611704..db7a406c7 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Networking/Voip/VoipCapture.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/Voip/VoipCapture.cs @@ -227,10 +227,13 @@ namespace Barotrauma.Networking bool allowEnqueue = overrideSound != null; if (GameMain.WindowActive && SettingsMenu.Instance is null) { - bool pttDown = PlayerInput.KeyDown(InputType.Voice) && GUI.KeyboardDispatcher.Subscriber == null; + bool usingActiveMode = PlayerInput.KeyDown(InputType.Voice); + bool usingLocalMode = PlayerInput.KeyDown(InputType.LocalVoice); + bool usingRadioMode = PlayerInput.KeyDown(InputType.RadioVoice); + bool pttDown = (usingActiveMode || usingLocalMode || usingRadioMode) && GUI.KeyboardDispatcher.Subscriber == null; if (pttDown || captureTimer <= 0) { - ForceLocal = GameMain.ActiveChatMode == ChatMode.Local; + ForceLocal = (usingActiveMode && GameMain.ActiveChatMode == ChatMode.Local) || usingLocalMode; } if (GameSettings.CurrentConfig.Audio.VoiceSetting == VoiceMode.Activity) { diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/Voip/VoipClient.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/Voip/VoipClient.cs index 8ce374562..eabc6004a 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Networking/Voip/VoipClient.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/Voip/VoipClient.cs @@ -121,10 +121,9 @@ namespace Barotrauma.Networking { client.VoipSound.SetRange(ChatMessage.SpeakRange * 0.4f, ChatMessage.SpeakRange); } - if (messageType != ChatMessageType.Radio && Character.Controlled != null && !GameSettings.CurrentConfig.Audio.DisableVoiceChatFilters) - { - client.VoipSound.UseMuffleFilter = SoundPlayer.ShouldMuffleSound(Character.Controlled, client.Character.WorldPosition, ChatMessage.SpeakRange, client.Character.CurrentHull); - } + client.VoipSound.UseMuffleFilter = + messageType != ChatMessageType.Radio && Character.Controlled != null && !GameSettings.CurrentConfig.Audio.DisableVoiceChatFilters && + SoundPlayer.ShouldMuffleSound(Character.Controlled, client.Character.WorldPosition, ChatMessage.SpeakRange, client.Character.CurrentHull); } GameMain.NetLobbyScreen?.SetPlayerSpeaking(client); diff --git a/Barotrauma/BarotraumaClient/ClientSource/Particles/ParticleManager.cs b/Barotrauma/BarotraumaClient/ClientSource/Particles/ParticleManager.cs index 982106567..dfdd7342a 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Particles/ParticleManager.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Particles/ParticleManager.cs @@ -3,7 +3,6 @@ using Microsoft.Xna.Framework.Graphics; using System; using System.Collections.Generic; using System.Linq; -using System.Xml.Linq; namespace Barotrauma.Particles { @@ -217,6 +216,11 @@ namespace Barotrauma.Particles } } + public void ClearParticles() + { + particleCount = 0; + } + public void RemoveByPrefab(ParticlePrefab prefab) { if (particles == null) { return; } diff --git a/Barotrauma/BarotraumaClient/ClientSource/PlayerInput.cs b/Barotrauma/BarotraumaClient/ClientSource/PlayerInput.cs index 3aedb98d6..5b09b97aa 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/PlayerInput.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/PlayerInput.cs @@ -132,11 +132,11 @@ namespace Barotrauma } else if (a.MouseButton != MouseButton.None) { - return a.MouseButton == b.MouseButton; + return !(b is null) && a.MouseButton == b.MouseButton; } else { - return a.Key.Equals(b.Key); + return !(b is null) && a.Key.Equals(b.Key); } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Screens/CampaignUI.cs b/Barotrauma/BarotraumaClient/ClientSource/Screens/CampaignUI.cs index ba4d9eaa3..5fc6deb6c 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Screens/CampaignUI.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Screens/CampaignUI.cs @@ -27,8 +27,6 @@ namespace Barotrauma private bool hasMaxMissions; - private GUIButton repairHullsButton, replaceShuttlesButton, repairItemsButton; - private SubmarineSelection submarineSelection; private Location selectedLocation; @@ -101,170 +99,6 @@ namespace Barotrauma tabs[(int)CampaignMode.InteractionType.Store] = storeTab; Store = new Store(this, storeTab); - // repair tab ------------------------------------------------------------------------- - - tabs[(int)CampaignMode.InteractionType.Repair] = CreateDefaultTabContainer(container, new Vector2(0.7f)); - var repairFrame = new GUIFrame(new RectTransform(Vector2.One, GetTabContainer(CampaignMode.InteractionType.Repair).RectTransform, Anchor.TopLeft), color: Color.Black * 0.9f); - new GUIFrame(new RectTransform(new Vector2(1.25f, 1.25f), repairFrame.RectTransform, Anchor.Center), style: "OuterGlow", color: Color.Black * 0.7f) - { - UserData = "outerglow", - CanBeFocused = false - }; - - var repairContent = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.85f), repairFrame.RectTransform, Anchor.Center)) - { - RelativeSpacing = 0.05f, - Stretch = true - }; - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.2f), repairContent.RectTransform), "", font: GUIStyle.LargeFont) - { - TextGetter = GetMoney - }; - - // repair hulls ----------------------------------------------- - - var repairHullsHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.5f), repairContent.RectTransform), childAnchor: Anchor.TopRight) - { - RelativeSpacing = 0.05f, - Stretch = true - }; - new GUIImage(new RectTransform(new Vector2(0.3f, 1.0f), repairHullsHolder.RectTransform, Anchor.CenterLeft), "RepairHullButton") - { - IgnoreLayoutGroups = true, - CanBeFocused = false - }; - var repairHullsLabel = new GUITextBlock(new RectTransform(new Vector2(0.7f, 0.3f), repairHullsHolder.RectTransform), TextManager.Get("RepairAllWalls"), textAlignment: Alignment.Right, font: GUIStyle.SubHeadingFont) - { - ForceUpperCase = ForceUpperCase.Yes - }; - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.3f), repairHullsHolder.RectTransform), CampaignMode.HullRepairCost.ToString(), textAlignment: Alignment.Right, font: GUIStyle.SubHeadingFont); - repairHullsButton = new GUIButton(new RectTransform(new Vector2(0.4f, 0.3f), repairHullsHolder.RectTransform) { MinSize = new Point(140, 0) }, TextManager.Get("Repair")) - { - OnClicked = (btn, userdata) => - { - if (Campaign.PurchasedHullRepairs) - { - Campaign.Wallet.Refund(CampaignMode.HullRepairCost); - Campaign.PurchasedHullRepairs = false; - } - else - { - if (Campaign.TryPurchase(null, CampaignMode.HullRepairCost)) - { - GameAnalyticsManager.AddMoneySpentEvent(CampaignMode.HullRepairCost, GameAnalyticsManager.MoneySink.Service, "hullrepairs"); - Campaign.PurchasedHullRepairs = true; - } - } - GameMain.Client?.SendCampaignState(); - btn.GetChild().Selected = Campaign.PurchasedHullRepairs; - - return true; - } - }; - new GUITickBox(new RectTransform(new Vector2(0.65f), repairHullsButton.RectTransform, Anchor.CenterLeft) { AbsoluteOffset = new Point(10, 0) }, "") - { - CanBeFocused = false - }; - - // repair items ------------------------------------------- - - var repairItemsHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.5f), repairContent.RectTransform), childAnchor: Anchor.TopRight) - { - RelativeSpacing = 0.05f, - Stretch = true - }; - new GUIImage(new RectTransform(new Vector2(0.3f, 1.0f), repairItemsHolder.RectTransform, Anchor.CenterLeft), "RepairItemsButton") - { - IgnoreLayoutGroups = true, - CanBeFocused = false - }; - var repairItemsLabel = new GUITextBlock(new RectTransform(new Vector2(0.7f, 0.3f), repairItemsHolder.RectTransform), TextManager.Get("RepairAllItems"), textAlignment: Alignment.Right, font: GUIStyle.SubHeadingFont) - { - ForceUpperCase = ForceUpperCase.Yes - }; - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.3f), repairItemsHolder.RectTransform), CampaignMode.ItemRepairCost.ToString(), textAlignment: Alignment.Right, font: GUIStyle.SubHeadingFont); - repairItemsButton = new GUIButton(new RectTransform(new Vector2(0.4f, 0.3f), repairItemsHolder.RectTransform) { MinSize = new Point(140, 0) }, TextManager.Get("Repair")) - { - OnClicked = (btn, userdata) => - { - if (Campaign.PurchasedItemRepairs) - { - Campaign.Wallet.Refund(CampaignMode.ItemRepairCost); - Campaign.PurchasedItemRepairs = false; - } - else - { - if (Campaign.TryPurchase(null, CampaignMode.ItemRepairCost)) - { - GameAnalyticsManager.AddMoneySpentEvent(CampaignMode.ItemRepairCost, GameAnalyticsManager.MoneySink.Service, "devicerepairs"); - Campaign.PurchasedItemRepairs = true; - } - } - GameMain.Client?.SendCampaignState(); - btn.GetChild().Selected = Campaign.PurchasedItemRepairs; - - return true; - } - }; - new GUITickBox(new RectTransform(new Vector2(0.65f), repairItemsButton.RectTransform, Anchor.CenterLeft) { AbsoluteOffset = new Point(10, 0) }, "") - { - CanBeFocused = false - }; - - // replace lost shuttles ------------------------------------------- - - var replaceShuttlesHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.5f), repairContent.RectTransform), childAnchor: Anchor.TopRight) - { - RelativeSpacing = 0.05f, - Stretch = true - }; - new GUIImage(new RectTransform(new Vector2(0.3f, 1.0f), replaceShuttlesHolder.RectTransform, Anchor.CenterLeft), "ReplaceShuttlesButton") - { - IgnoreLayoutGroups = true, - CanBeFocused = false - }; - var replaceShuttlesLabel = new GUITextBlock(new RectTransform(new Vector2(0.7f, 0.3f), replaceShuttlesHolder.RectTransform), TextManager.Get("ReplaceLostShuttles"), textAlignment: Alignment.Right, font: GUIStyle.SubHeadingFont) - { - ForceUpperCase = ForceUpperCase.Yes - }; - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.3f), replaceShuttlesHolder.RectTransform), CampaignMode.ShuttleReplaceCost.ToString(), textAlignment: Alignment.Right, font: GUIStyle.SubHeadingFont); - replaceShuttlesButton = new GUIButton(new RectTransform(new Vector2(0.4f, 0.3f), replaceShuttlesHolder.RectTransform) { MinSize = new Point(140, 0) }, TextManager.Get("ReplaceShuttles")) - { - OnClicked = (btn, userdata) => - { - if (GameMain.GameSession?.SubmarineInfo != null && - GameMain.GameSession.SubmarineInfo.LeftBehindSubDockingPortOccupied) - { - new GUIMessageBox("", TextManager.Get("ReplaceShuttleDockingPortOccupied")); - return true; - } - - if (Campaign.PurchasedLostShuttles) - { - Campaign.Wallet.Refund(CampaignMode.ShuttleReplaceCost); - Campaign.PurchasedLostShuttles = false; - } - else - { - if (Campaign.TryPurchase(null, CampaignMode.ShuttleReplaceCost)) - { - GameAnalyticsManager.AddMoneySpentEvent(CampaignMode.ShuttleReplaceCost, GameAnalyticsManager.MoneySink.Service, "retrieveshuttle"); - Campaign.PurchasedLostShuttles = true; - } - } - GameMain.Client?.SendCampaignState(); - btn.GetChild().Selected = Campaign.PurchasedLostShuttles; - - return true; - } - }; - new GUITickBox(new RectTransform(new Vector2(0.65f), replaceShuttlesButton.RectTransform, Anchor.CenterLeft) { AbsoluteOffset = new Point(10, 0) }, "") - { - CanBeFocused = false - }; - GUITextBlock.AutoScaleAndNormalize(repairHullsLabel, repairItemsLabel, replaceShuttlesLabel); - GUITextBlock.AutoScaleAndNormalize(repairHullsButton.GetChild().TextBlock, repairItemsButton.GetChild().TextBlock, replaceShuttlesButton.GetChild().TextBlock); - // upgrade tab ------------------------------------------------------------------------- tabs[(int)CampaignMode.InteractionType.Upgrade] = new GUIFrame(new RectTransform(Vector2.One, container.RectTransform), color: Color.Black * 0.9f); @@ -701,26 +535,6 @@ namespace Barotrauma switch (selectedTab) { - case CampaignMode.InteractionType.Repair: - repairHullsButton.Enabled = - (Campaign.PurchasedHullRepairs || Campaign.Wallet.CanAfford(CampaignMode.HullRepairCost)); - repairHullsButton.GetChild().Selected = Campaign.PurchasedHullRepairs; - repairItemsButton.Enabled = - (Campaign.PurchasedItemRepairs || Campaign.Wallet.CanAfford(CampaignMode.ItemRepairCost)); - repairItemsButton.GetChild().Selected = Campaign.PurchasedItemRepairs; - - if (GameMain.GameSession?.SubmarineInfo == null || !GameMain.GameSession.SubmarineInfo.SubsLeftBehind) - { - replaceShuttlesButton.Enabled = false; - replaceShuttlesButton.GetChild().Selected = false; - } - else - { - replaceShuttlesButton.Enabled = - (Campaign.PurchasedLostShuttles || Campaign.Wallet.CanAfford(CampaignMode.ShuttleReplaceCost)); - replaceShuttlesButton.GetChild().Selected = Campaign.PurchasedLostShuttles; - } - break; case CampaignMode.InteractionType.Store: Store.SelectStore(storeIdentifier); break; diff --git a/Barotrauma/BarotraumaClient/ClientSource/Screens/CharacterEditor/CharacterEditorScreen.cs b/Barotrauma/BarotraumaClient/ClientSource/Screens/CharacterEditor/CharacterEditorScreen.cs index 11105e73a..668226715 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Screens/CharacterEditor/CharacterEditorScreen.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Screens/CharacterEditor/CharacterEditorScreen.cs @@ -2606,8 +2606,8 @@ namespace Barotrauma.CharacterEditor animationControls = new GUIFrame(new RectTransform(Vector2.One, centerArea.RectTransform), style: null) { CanBeFocused = false }; var layoutGroupAnimation = new GUILayoutGroup(new RectTransform(Vector2.One, animationControls.RectTransform), childAnchor: Anchor.TopLeft) { CanBeFocused = false }; var animationSelectionElement = new GUIFrame(new RectTransform(new Point(elementSize.X * 2 - (int)(5 * GUI.xScale), elementSize.Y), layoutGroupAnimation.RectTransform), style: null); - var animationSelectionText = new GUITextBlock(new RectTransform(new Point(elementSize.X, elementSize.Y), animationSelectionElement.RectTransform), GetCharacterEditorTranslation("SelectedAnimation") + ": ", Color.WhiteSmoke, textAlignment: Alignment.Center); - animSelection = new GUIDropDown(new RectTransform(new Point((int)(100 * GUI.xScale), elementSize.Y), animationSelectionElement.RectTransform, Anchor.TopRight), elementCount: 5); + var animationSelectionText = new GUITextBlock(new RectTransform(new Point(elementSize.X, elementSize.Y), animationSelectionElement.RectTransform), GetCharacterEditorTranslation("SelectedAnimation"), Color.WhiteSmoke, textAlignment: Alignment.CenterRight); + animSelection = new GUIDropDown(new RectTransform(new Point((int)(150 * GUI.xScale), elementSize.Y), animationSelectionElement.RectTransform, Anchor.Center, Pivot.CenterLeft), elementCount: 5); if (character.AnimController.CanWalk) { animSelection.AddItem(AnimationType.Walk.ToString(), AnimationType.Walk); diff --git a/Barotrauma/BarotraumaClient/ClientSource/Screens/GameScreen.cs b/Barotrauma/BarotraumaClient/ClientSource/Screens/GameScreen.cs index f3783a78a..90f0e3f1b 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Screens/GameScreen.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Screens/GameScreen.cs @@ -1,11 +1,10 @@ +using Barotrauma.Extensions; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Content; using Microsoft.Xna.Framework.Graphics; using System; -using FarseerPhysics; using System.Diagnostics; using System.Linq; -using Barotrauma.Extensions; namespace Barotrauma { @@ -79,21 +78,27 @@ namespace Barotrauma public override void AddToGUIUpdateList() { - if (Character.Controlled != null && Character.Controlled.SelectedConstruction != null && Character.Controlled.CanInteractWith(Character.Controlled.SelectedConstruction)) + if (Character.Controlled != null) { - Character.Controlled.SelectedConstruction.AddToGUIUpdateList(); - } - if (Character.Controlled?.Inventory != null) - { - foreach (Item item in Character.Controlled.Inventory.AllItems) + if (Character.Controlled.SelectedItem is { } selectedItem && Character.Controlled.CanInteractWith(selectedItem)) { - if (Character.Controlled.HasEquippedItem(item)) + selectedItem.AddToGUIUpdateList(); + } + if (Character.Controlled.SelectedSecondaryItem is { } selectedSecondaryItem && Character.Controlled.CanInteractWith(selectedSecondaryItem)) + { + selectedSecondaryItem.AddToGUIUpdateList(); + } + if (Character.Controlled.Inventory != null) + { + foreach (Item item in Character.Controlled.Inventory.AllItems) { - item.AddToGUIUpdateList(); + if (Character.Controlled.HasEquippedItem(item)) + { + item.AddToGUIUpdateList(); + } } } } - GameMain.GameSession?.AddToGUIUpdateList(); Character.AddAllToGUIUpdateList(); } @@ -260,11 +265,7 @@ namespace Barotrauma //Draw the rest of the structures, characters and front structures spriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.NonPremultiplied, null, DepthStencilState.None, null, null, cam.Transform); Submarine.DrawBack(spriteBatch, false, e => !(e is Structure) || e.SpriteDepth < 0.9f); - foreach (Character c in Character.CharacterList) - { - if (!c.IsVisible || c.AnimController.Limbs.Any(l => l.DeformSprite != null)) { continue; } - c.Draw(spriteBatch, Cam); - } + DrawCharacters(deformed: false, firstPass: true); spriteBatch.End(); sw.Stop(); @@ -272,11 +273,12 @@ namespace Barotrauma sw.Restart(); spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied, null, DepthStencilState.None, null, null, cam.Transform); - DrawDeformed(firstPass: true); - DrawDeformed(firstPass: false); + DrawCharacters(deformed: true, firstPass: true); + DrawCharacters(deformed: true, firstPass: false); + DrawCharacters(deformed: false, firstPass: false); spriteBatch.End(); - void DrawDeformed(bool firstPass) + void DrawCharacters(bool deformed, bool firstPass) { //backwards order to render the most recently spawned characters in front (characters spawned later have a larger sprite depth) for (int i = Character.CharacterList.Count - 1; i >= 0; i--) @@ -284,7 +286,14 @@ namespace Barotrauma Character c = Character.CharacterList[i]; if (!c.IsVisible) { continue; } if (c.Params.DrawLast == firstPass) { continue; } - if (c.AnimController.Limbs.All(l => l.DeformSprite == null)) { continue; } + if (deformed) + { + if (c.AnimController.Limbs.All(l => l.DeformSprite == null)) { continue; } + } + else + { + if (c.AnimController.Limbs.Any(l => l.DeformSprite != null)) { continue; } + } c.Draw(spriteBatch, Cam); } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Screens/MainMenuScreen.cs b/Barotrauma/BarotraumaClient/ClientSource/Screens/MainMenuScreen.cs index b61b535f0..303b9d94f 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Screens/MainMenuScreen.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Screens/MainMenuScreen.cs @@ -695,8 +695,13 @@ namespace Barotrauma gamesession.StartRound(fixedSeed ? "abcd" : ToolBox.RandomSeed(8), difficulty, levelGenerationParams); GameMain.GameScreen.Select(); // TODO: modding support - string[] jobIdentifiers = new string[] { "captain", "engineer", "mechanic", "securityofficer", "medicaldoctor" }; - foreach (string job in jobIdentifiers) + Identifier[] jobIdentifiers = new Identifier[] { + "captain".ToIdentifier(), + "engineer".ToIdentifier(), + "mechanic".ToIdentifier(), + "securityofficer".ToIdentifier(), + "medicaldoctor".ToIdentifier() }; + foreach (Identifier job in jobIdentifiers) { var jobPrefab = JobPrefab.Get(job); var variant = Rand.Range(0, jobPrefab.Variants); diff --git a/Barotrauma/BarotraumaClient/ClientSource/Screens/Screen.cs b/Barotrauma/BarotraumaClient/ClientSource/Screens/Screen.cs index 356b8878c..cdce5489e 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Screens/Screen.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Screens/Screen.cs @@ -55,9 +55,7 @@ namespace Barotrauma while (timer < duration) { GUI.ScreenOverlayColor = Color.Lerp(from, to, Math.Min(timer / duration, 1.0f)); - - timer += CoroutineManager.UnscaledDeltaTime; - + timer += CoroutineManager.DeltaTime; yield return CoroutineStatus.Running; } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Screens/SubEditorScreen.cs b/Barotrauma/BarotraumaClient/ClientSource/Screens/SubEditorScreen.cs index 66c404987..11ae9f941 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Screens/SubEditorScreen.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Screens/SubEditorScreen.cs @@ -813,8 +813,13 @@ namespace Barotrauma var itemCount = new GUITextBlock(new RectTransform(new Vector2(0.33f, 1.0f), itemCountText.RectTransform, Anchor.TopRight, Pivot.TopLeft), "", textAlignment: Alignment.CenterRight); itemCount.TextGetter = () => { - itemCount.TextColor = Item.ItemList.Count > MaxItems ? GUIStyle.Red : Color.Lerp(GUIStyle.Green, GUIStyle.Orange, Item.ItemList.Count / (float)MaxItems); - return Item.ItemList.Count.ToString(); + int count = Item.ItemList.Count; + if (dummyCharacter?.Inventory != null) + { + count -= dummyCharacter.Inventory.AllItems.Count(); + } + itemCount.TextColor = count > MaxItems ? GUIStyle.Red : Color.Lerp(GUIStyle.Green, GUIStyle.Orange, count / (float)MaxItems); + return count.ToString(); }; var structureCountText = new GUITextBlock(new RectTransform(new Vector2(0.75f, 0.0f), paddedEntityCountPanel.RectTransform), TextManager.Get("Structures"), @@ -1497,7 +1502,7 @@ namespace Barotrauma /// private static IEnumerable AutoSaveCoroutine() { - DateTime target = DateTime.Now.AddMinutes(GameSettings.CurrentConfig.AutoSaveIntervalSeconds); + DateTime target = DateTime.Now.AddSeconds(GameSettings.CurrentConfig.AutoSaveIntervalSeconds); DateTime tempTarget = DateTime.Now; bool wasPaused = false; @@ -1549,7 +1554,9 @@ namespace Barotrauma MapEntity.DeselectAll(); ClearUndoBuffer(); +#if !DEBUG DebugConsole.DeactivateCheats(); +#endif SetMode(Mode.Default); @@ -3337,23 +3344,21 @@ namespace Barotrauma { if (!(userData is XElement element)) { return; } - #warning TODO: revise +#warning TODO: revise string filePath = element.GetAttributeStringUnrestricted("file", ""); if (string.IsNullOrWhiteSpace(filePath)) { return; } var loadedSub = Submarine.Load(new SubmarineInfo(filePath), true); - // set the submarine file path to the "default" value - var unspecifiedFileName = TextManager.Get("UnspecifiedSubFileName"); - loadedSub.Info.FilePath = Path.Combine(ContentPackage.LocalModsDir, unspecifiedFileName.Value, $"{unspecifiedFileName}.sub"); - loadedSub.Info.Name = unspecifiedFileName.Value; try { - loadedSub.Info.Name = loadedSub.Info.SubmarineElement.GetAttributeString("name", loadedSub.Info.Name); + loadedSub.Info.Name = loadedSub.Info.SubmarineElement.GetAttributeString("name", loadedSub.Info.Name); } catch (Exception e) { DebugConsole.ThrowError("Failed to find a name for the submarine.", e); + var unspecifiedFileName = TextManager.Get("UnspecifiedSubFileName"); + loadedSub.Info.Name = unspecifiedFileName.Value; } MainSub = loadedSub; MainSub.SetPrevTransform(MainSub.Position); @@ -3726,7 +3731,6 @@ namespace Barotrauma } else { - List availableLayerOptions = new List { new ContextMenuOption("editor.layer.nolayer", true, onSelected: () => { MoveToLayer(null, targets); }) @@ -3769,7 +3773,8 @@ namespace Barotrauma { if (!me.Removed) { me.Remove(); } } - })); + }), + new ContextMenuOption(TextManager.Get("editortip.shiftforextraoptions") + '\n' + TextManager.Get("editortip.altforruler"), isEnabled: false, onSelected: null)); } } @@ -4257,7 +4262,7 @@ namespace Barotrauma MapEntity.SelectedList.Clear(); MapEntity.FilteredSelectedList.Clear(); MapEntity.SelectEntity(itemContainer); - dummyCharacter.SelectedConstruction = itemContainer; + dummyCharacter.SelectedItem = itemContainer; FilterEntities(entityFilterBox.Text); } @@ -4268,9 +4273,9 @@ namespace Barotrauma { if (dummyCharacter == null) { return; } //nothing to close -> return - if (DraggedItemPrefab == null && dummyCharacter?.SelectedConstruction == null && OpenedItem == null) { return; } + if (DraggedItemPrefab == null && dummyCharacter?.SelectedItem == null && OpenedItem == null) { return; } DraggedItemPrefab = null; - dummyCharacter.SelectedConstruction = null; + dummyCharacter.SelectedItem = null; OpenedItem?.Drop(dummyCharacter); OpenedItem?.SetTransform(oldItemPosition, 0f); OpenedItem = null; @@ -4347,9 +4352,9 @@ namespace Barotrauma } } - if (dummyCharacter?.SelectedConstruction != null) + if (dummyCharacter?.SelectedItem != null) { - var inv = dummyCharacter?.SelectedConstruction?.OwnInventory; + var inv = dummyCharacter?.SelectedItem?.OwnInventory; if (inv != null) { switch (obj) @@ -4779,9 +4784,9 @@ namespace Barotrauma if (dummyCharacter != null) { CharacterHUD.AddToGUIUpdateList(dummyCharacter); - if (dummyCharacter.SelectedConstruction != null) + if (dummyCharacter.SelectedItem != null) { - dummyCharacter.SelectedConstruction.AddToGUIUpdateList(); + dummyCharacter.SelectedItem.AddToGUIUpdateList(); } else if (WiringMode && MapEntity.SelectedList.FirstOrDefault() is Item item && item.GetComponent() != null) { @@ -4801,7 +4806,7 @@ namespace Barotrauma /// /// GUI.MouseOn doesn't get updated while holding primary mouse and we need it to /// - private bool IsMouseOnEditorGUI() + public bool IsMouseOnEditorGUI() { if (GUI.MouseOn == null) { return false; } @@ -5143,7 +5148,7 @@ namespace Barotrauma { if (dummyCharacter != null) { - if (dummyCharacter.SelectedConstruction == null) + if (dummyCharacter.SelectedItem == null) { foreach (var entity in MapEntity.mapEntityList) { @@ -5285,7 +5290,7 @@ namespace Barotrauma me.IsHighlighted = false; } - if (dummyCharacter.SelectedConstruction == null) + if (dummyCharacter.SelectedItem == null) { List wires = new List(); foreach (Item item in Item.ItemList) @@ -5308,8 +5313,8 @@ namespace Barotrauma }); } - if (dummyCharacter.SelectedConstruction == null || - dummyCharacter.SelectedConstruction.GetComponent() != null) + if (dummyCharacter.SelectedItem == null || + dummyCharacter.SelectedItem.GetComponent() != null) { if (WiringMode && PlayerInput.IsShiftDown()) { @@ -5341,7 +5346,7 @@ namespace Barotrauma TeleportDummyCharacter(oldItemPosition); } - if (WiringMode && dummyCharacter?.SelectedConstruction == null) + if (WiringMode && dummyCharacter?.SelectedItem == null) { TeleportDummyCharacter(FarseerPhysics.ConvertUnits.ToSimUnits(dummyCharacter.CursorPosition)); } @@ -5358,7 +5363,7 @@ namespace Barotrauma } // Deposit item from our "infinite stack" into inventory slots - var inv = dummyCharacter?.SelectedConstruction?.OwnInventory; + var inv = dummyCharacter?.SelectedItem?.OwnInventory; if (inv?.visualSlots != null && !PlayerInput.IsCtrlDown()) { var dragginMouse = MouseDragStart != Vector2.Zero && Vector2.Distance(PlayerInput.MousePosition, MouseDragStart) >= GUI.Scale * 20; @@ -5524,7 +5529,7 @@ namespace Barotrauma } if (!saveAssemblyFrame.Rect.Contains(PlayerInput.MousePosition) && !snapToGridFrame.Rect.Contains(PlayerInput.MousePosition) && - dummyCharacter?.SelectedConstruction == null && !WiringMode && GUI.MouseOn == null) + dummyCharacter?.SelectedItem == null && !WiringMode && GUI.MouseOn == null) { if (layerList is { Visible: true } && GUI.KeyboardDispatcher.Subscriber == layerList) { @@ -5549,7 +5554,7 @@ namespace Barotrauma if (!WiringMode) { - bool shouldCloseHud = dummyCharacter?.SelectedConstruction != null && HUD.CloseHUD(dummyCharacter.SelectedConstruction.Rect) && DraggedItemPrefab == null; + bool shouldCloseHud = dummyCharacter?.SelectedItem != null && HUD.CloseHUD(dummyCharacter.SelectedItem.Rect) && DraggedItemPrefab == null; if (MapEntityPrefab.Selected != null && GUI.MouseOn == null) { @@ -5565,7 +5570,7 @@ namespace Barotrauma } else { - if (dummyCharacter?.SelectedConstruction == null) + if (dummyCharacter?.SelectedItem == null) { CreateContextMenu(); } @@ -5622,11 +5627,11 @@ namespace Barotrauma wire?.Update((float)deltaTime, cam); } - if (dummyCharacter.SelectedConstruction != null) + if (dummyCharacter.SelectedItem != null) { - if (MapEntity.SelectedList.Contains(dummyCharacter.SelectedConstruction) || WiringMode) + if (MapEntity.SelectedList.Contains(dummyCharacter.SelectedItem) || WiringMode) { - dummyCharacter.SelectedConstruction?.UpdateHUD(cam, dummyCharacter, (float)deltaTime); + dummyCharacter.SelectedItem?.UpdateHUD(cam, dummyCharacter, (float)deltaTime); } else { diff --git a/Barotrauma/BarotraumaClient/ClientSource/Screens/TestScreen.cs b/Barotrauma/BarotraumaClient/ClientSource/Screens/TestScreen.cs index 3d95b1bbb..abfbb86e2 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Screens/TestScreen.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Screens/TestScreen.cs @@ -1,5 +1,4 @@ #nullable enable -using System; using System.Linq; using Barotrauma.Extensions; using Barotrauma.Items.Components; @@ -14,18 +13,14 @@ using Microsoft.Xna.Framework.Graphics; */ namespace Barotrauma { - class TestScreen : EditorScreen + internal sealed class TestScreen : EditorScreen { public override Camera Cam { get; } private Item? miniMapItem; - private Submarine? submarine; public static Character? dummyCharacter; public static Effect? BlueprintEffect; - private GUIFrame? container; - - private TabMenu? tabMenu; public TestScreen() { @@ -43,14 +38,11 @@ namespace Barotrauma return true; } }; - } public override void Select() { base.Select(); - container = new GUIFrame(new RectTransform(Vector2.One, GUI.Canvas, Anchor.Center), style: "InnerGlow", color: Color.Black); - var tab = new GUIFrame(new RectTransform(Vector2.One, container.RectTransform), color: Color.Black * 0.9f); if (dummyCharacter is { Removed: false }) { dummyCharacter?.Remove(); @@ -61,30 +53,50 @@ namespace Barotrauma dummyCharacter.Info.Name = "Galldren"; dummyCharacter.Inventory.CreateSlots(); + miniMapItem = new Item(ItemPrefab.Find(null, "deconstructor".ToIdentifier()), Vector2.Zero, null, 1337, false); + + foreach (ItemComponent component in miniMapItem.Components) + { + component.OnItemLoaded(); + } Character.Controlled = dummyCharacter; GameMain.World.ProcessChanges(); - tabMenu = new TabMenu(); } public override void AddToGUIUpdateList() { Frame.AddToGUIUpdateList(); - container?.AddToGUIUpdateList(); - tabMenu?.AddToGUIUpdateList(); - // CharacterHUD.AddToGUIUpdateList(dummyCharacter); - // dummyCharacter?.SelectedConstruction?.AddToGUIUpdateList(); + CharacterHUD.AddToGUIUpdateList(dummyCharacter); + dummyCharacter?.SelectedItem?.AddToGUIUpdateList(); } public override void Update(double deltaTime) { base.Update(deltaTime); - if (dummyCharacter is { } dummy) + if (dummyCharacter is { } dummy && miniMapItem is { } item) { + if (dummy.SelectedItem != item) + { + dummy.SelectedItem = item; + } + + dummy.SelectedItem?.UpdateHUD(Cam, dummy, (float)deltaTime); + Vector2 pos = FarseerPhysics.ConvertUnits.ToSimUnits(item.Position); + + foreach (Limb limb in dummy.AnimController.Limbs) + { + limb.body.SetTransform(pos, 0.0f); + } + + if (dummy.AnimController?.Collider is { } collider) + { + collider.SetTransform(pos, 0); + } + dummy.ControlLocalPlayer((float)deltaTime, Cam, false); dummy.Control((float)deltaTime, Cam); } - tabMenu?.Update((float)deltaTime); } public override void Draw(double deltaTime, GraphicsDevice graphics, SpriteBatch spriteBatch) @@ -93,12 +105,13 @@ namespace Barotrauma graphics.Clear(BackgroundColor); spriteBatch.Begin(SpriteSortMode.BackToFront, transformMatrix: Cam.Transform); - // miniMapItem?.Draw(spriteBatch, false); - // if (dummyCharacter is { } dummy) - // { - // dummyCharacter.DrawFront(spriteBatch, Cam); - // dummyCharacter.Draw(spriteBatch, Cam); - // } + miniMapItem?.Draw(spriteBatch, false); + if (dummyCharacter is { } dummy) + { + dummyCharacter.DrawFront(spriteBatch, Cam); + dummyCharacter.Draw(spriteBatch, Cam); + } + spriteBatch.End(); spriteBatch.Begin(SpriteSortMode.Deferred, samplerState: GUI.SamplerState); diff --git a/Barotrauma/BarotraumaClient/ClientSource/Serialization/SerializableEntityEditor.cs b/Barotrauma/BarotraumaClient/ClientSource/Serialization/SerializableEntityEditor.cs index 636331079..b7e2d7744 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Serialization/SerializableEntityEditor.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Serialization/SerializableEntityEditor.cs @@ -1448,7 +1448,9 @@ namespace Barotrauma var component = otherComponents[componentIndex]; Debug.Assert(component.GetType() == parentObject.GetType()); SafeAdd(component, property); - if (value is string stringValue && Enum.TryParse(property.PropertyType, stringValue, out var enumValue)) + if (value is string stringValue && + property.PropertyType.IsEnum && + Enum.TryParse(property.PropertyType, stringValue, out var enumValue)) { property.PropertyInfo.SetValue(component, enumValue); } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Settings/SettingsMenu.cs b/Barotrauma/BarotraumaClient/ClientSource/Settings/SettingsMenu.cs index 9cf545dc8..b11d5eaf1 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Settings/SettingsMenu.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Settings/SettingsMenu.cs @@ -26,7 +26,9 @@ namespace Barotrauma Gameplay, Mods } - + + public Tab CurrentTab { get; private set; } + private GameSettings.Config unsavedConfig; private readonly GUIFrame mainFrame; @@ -37,7 +39,13 @@ namespace Barotrauma public readonly WorkshopMenu WorkshopMenu; - private static readonly ImmutableHashSet LegacyInputTypes = new List() { InputType.Chat, InputType.RadioChat }.ToImmutableHashSet(); + private static readonly ImmutableHashSet LegacyInputTypes = new List() + { + InputType.Chat, + InputType.RadioChat, + InputType.LocalVoice, + InputType.RadioVoice, + }.ToImmutableHashSet(); public static SettingsMenu Create(RectTransform mainParent) { @@ -97,6 +105,7 @@ namespace Barotrauma public void SelectTab(Tab tab) { + CurrentTab = tab; SwitchContent(tabContents[tab].Content); tabber.Children.ForEach(c => { @@ -764,27 +773,35 @@ namespace Barotrauma private void CreateBottomButtons() { - GUIButton cancelButton = - new GUIButton(new RectTransform(new Vector2(1.0f, 1.0f), bottom.RectTransform), text: TextManager.Get("Cancel")) + new GUIButton(new RectTransform(new Vector2(1.0f, 1.0f), bottom.RectTransform), text: TextManager.Get("Cancel")) + { + OnClicked = (btn, obj) => { - OnClicked = (btn, obj) => - { - Close(); - return false; - } - }; - GUIButton applyButton = - new GUIButton(new RectTransform(new Vector2(1.0f, 1.0f), bottom.RectTransform), text: TextManager.Get("applysettingsbutton")) + Close(); + return false; + } + }; + new GUIButton(new RectTransform(new Vector2(1.0f, 1.0f), bottom.RectTransform), text: TextManager.Get("applysettingsbutton")) + { + OnClicked = (btn, obj) => { - OnClicked = (btn, obj) => + GameSettings.SetCurrentConfig(unsavedConfig); + if (WorkshopMenu is MutableWorkshopMenu mutableWorkshopMenu && + mutableWorkshopMenu.CurrentTab == MutableWorkshopMenu.Tab.InstalledMods) { - GameSettings.SetCurrentConfig(unsavedConfig); - if (WorkshopMenu is MutableWorkshopMenu mutableWorkshopMenu) { mutableWorkshopMenu.Apply(); } - GameSettings.SaveCurrentConfig(); - mainFrame.Flash(color: GUIStyle.Green); - return false; + mutableWorkshopMenu.Apply(); } - }; + GameSettings.SaveCurrentConfig(); + mainFrame.Flash(color: GUIStyle.Green); + return false; + }, + OnAddedToGUIUpdateList = (GUIComponent component) => + { + component.Enabled = + CurrentTab != Tab.Mods || + (WorkshopMenu is MutableWorkshopMenu mutableWorkshopMenu && mutableWorkshopMenu.CurrentTab == MutableWorkshopMenu.Tab.InstalledMods && !mutableWorkshopMenu.ViewingItemDetails); + } + }; } public void Close() diff --git a/Barotrauma/BarotraumaClient/ClientSource/Sounds/SoundManager.cs b/Barotrauma/BarotraumaClient/ClientSource/Sounds/SoundManager.cs index a2418f455..ec631166a 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Sounds/SoundManager.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Sounds/SoundManager.cs @@ -368,7 +368,7 @@ namespace Barotrauma.Sounds string filePath = overrideFilePath ?? element.GetAttributeContentPath("file")?.Value ?? ""; if (!File.Exists(filePath)) { - throw new System.IO.FileNotFoundException("Sound file \"" + filePath + "\" doesn't exist!"); + throw new System.IO.FileNotFoundException($"Sound file \"{filePath}\" doesn't exist! Content package \"{(element.ContentPackage?.Name ?? "Unknown")}\"."); } var newSound = new OggSound(this, filePath, stream, xElement: element); diff --git a/Barotrauma/BarotraumaClient/ClientSource/Sprite/Sprite.cs b/Barotrauma/BarotraumaClient/ClientSource/Sprite/Sprite.cs index d4e1648a3..1b1aae8c0 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Sprite/Sprite.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Sprite/Sprite.cs @@ -253,12 +253,18 @@ namespace Barotrauma if (flipHorizontal) { float diff = targetSize.X % (sourceRect.Width * scale.X); - flippedDrawOffset.X = (int)((sourceRect.Width * scale.X - diff) / scale.X); + flippedDrawOffset.X = (sourceRect.Width * scale.X - diff) / scale.X; + flippedDrawOffset.X = + MathUtils.NearlyEqual(flippedDrawOffset.X, MathF.Round(flippedDrawOffset.X)) ? + MathF.Round(flippedDrawOffset.X) : flippedDrawOffset.X; } if (flipVertical) { float diff = targetSize.Y % (sourceRect.Height * scale.Y); - flippedDrawOffset.Y = (int)((sourceRect.Height * scale.Y - diff) / scale.Y); + flippedDrawOffset.Y = (sourceRect.Height * scale.Y - diff) / scale.Y; + flippedDrawOffset.Y = + MathUtils.NearlyEqual(flippedDrawOffset.Y, MathF.Round(flippedDrawOffset.Y)) ? + MathF.Round(flippedDrawOffset.Y) : flippedDrawOffset.Y; } drawOffset += flippedDrawOffset; diff --git a/Barotrauma/BarotraumaClient/ClientSource/Steam/Lobby.cs b/Barotrauma/BarotraumaClient/ClientSource/Steam/Lobby.cs index 03760d937..1243e39d7 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Steam/Lobby.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Steam/Lobby.cs @@ -395,8 +395,8 @@ namespace Barotrauma.Steam if (rules.ContainsKey("allowspectating")) { serverInfo.AllowSpectating = rules["allowspectating"] == "True"; } if (rules.ContainsKey("allowrespawn")) { serverInfo.AllowRespawn = rules["allowrespawn"] == "True"; } if (rules.ContainsKey("voicechatenabled")) { serverInfo.VoipEnabled = rules["voicechatenabled"] == "True"; } - if (rules.ContainsKey("friendlyfireenabled")) { serverInfo.AllowRespawn = rules["friendlyfireenabled"] == "True"; } - if (rules.ContainsKey("karmaenabled")) { serverInfo.VoipEnabled = rules["karmaenabled"] == "True"; } + if (rules.ContainsKey("friendlyfireenabled")) { serverInfo.FriendlyFireEnabled = rules["friendlyfireenabled"] == "True"; } + if (rules.ContainsKey("karmaenabled")) { serverInfo.KarmaEnabled = rules["karmaenabled"] == "True"; } if (rules.ContainsKey("traitors")) { if (Enum.TryParse(rules["traitors"], out YesNoMaybe traitorsEnabled)) { serverInfo.TraitorsEnabled = traitorsEnabled; } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Steam/WorkshopMenu/Mutable/InstalledTab.cs b/Barotrauma/BarotraumaClient/ClientSource/Steam/WorkshopMenu/Mutable/InstalledTab.cs index 2e5953ae5..32482cc76 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Steam/WorkshopMenu/Mutable/InstalledTab.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Steam/WorkshopMenu/Mutable/InstalledTab.cs @@ -13,6 +13,8 @@ namespace Barotrauma.Steam { private CorePackage EnabledCorePackage => enabledCoreDropdown.SelectedData as CorePackage ?? throw new Exception("Valid core package not selected"); + public bool ViewingItemDetails { get; private set; } + private readonly GUIDropDown enabledCoreDropdown; private readonly GUIListBox enabledRegularModsList; private readonly GUIListBox disabledRegularModsList; @@ -167,7 +169,7 @@ namespace Barotrauma.Steam swapSoundType = null; } } - + private void CreateInstalledModsTab( out GUIDropDown enabledCoreDropdown, out GUIListBox enabledRegularModsList, @@ -523,6 +525,7 @@ namespace Barotrauma.Steam public void PopulateInstalledModLists(bool forceRefreshEnabled = false, bool refreshDisabled = true) { + ViewingItemDetails = false; bulkUpdateButton.Enabled = false; bulkUpdateButton.ToolTip = ""; ContentPackageManager.UpdateContentPackageList(); diff --git a/Barotrauma/BarotraumaClient/ClientSource/Steam/WorkshopMenu/Mutable/ItemList.cs b/Barotrauma/BarotraumaClient/ClientSource/Steam/WorkshopMenu/Mutable/ItemList.cs index e4e155950..351ebb833 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Steam/WorkshopMenu/Mutable/ItemList.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Steam/WorkshopMenu/Mutable/ItemList.cs @@ -283,6 +283,7 @@ namespace Barotrauma.Steam { CanBeFocused = false }; + unpublishedLayout.Recalculate(); } if (publishedGuiComponents.Any()) @@ -456,6 +457,7 @@ namespace Barotrauma.Steam { CreateSubscribeButton(workshopItem, new RectTransform(Vector2.One, itemLayout.RectTransform, scaleBasis: ScaleBasis.BothHeight), spriteScale: 0.4f); } + itemLayout.Recalculate(); } onFill?.Invoke(workshopItems); }); @@ -550,6 +552,7 @@ namespace Barotrauma.Steam private void PopulateFrameWithItemInfo(Steamworks.Ugc.Item workshopItem, GUIFrame parentFrame) { + ViewingItemDetails = true; taskCancelSrc = taskCancelSrc.IsCancellationRequested ? new CancellationTokenSource() : taskCancelSrc; var contentPackage diff --git a/Barotrauma/BarotraumaClient/ClientSource/Steam/WorkshopMenu/Mutable/MutableWorkshopMenu.cs b/Barotrauma/BarotraumaClient/ClientSource/Steam/WorkshopMenu/Mutable/MutableWorkshopMenu.cs index c8563eb3c..1a24d958e 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Steam/WorkshopMenu/Mutable/MutableWorkshopMenu.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Steam/WorkshopMenu/Mutable/MutableWorkshopMenu.cs @@ -1,12 +1,9 @@ #nullable enable using Barotrauma.Extensions; using Microsoft.Xna.Framework; -using System; using System.Collections.Generic; using System.Linq; using System.Threading; -using System.Threading.Tasks; -using ItemOrPackage = Barotrauma.Either; namespace Barotrauma.Steam { @@ -28,6 +25,8 @@ namespace Barotrauma.Steam ShowOnlySubs, ShowOnlyItemAssemblies } + + public Tab CurrentTab { get; private set; } private readonly GUILayoutGroup tabber; private readonly Dictionary tabContents; @@ -78,6 +77,7 @@ namespace Barotrauma.Steam public void SelectTab(Tab tab) { + CurrentTab = tab; SwitchContent(tabContents[tab].Content); tabber.Children.ForEach(c => { diff --git a/Barotrauma/BarotraumaClient/ClientSource/Utils/LocalizationCSVtoXML.cs b/Barotrauma/BarotraumaClient/ClientSource/Utils/LocalizationCSVtoXML.cs index b4662d858..f1fc1456d 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Utils/LocalizationCSVtoXML.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Utils/LocalizationCSVtoXML.cs @@ -1,30 +1,75 @@ #if DEBUG +using Barotrauma.IO; using System; using System.Collections.Generic; -using Barotrauma.IO; -using System.Text; -using System.Text.RegularExpressions; using System.Linq; -using System.Globalization; +using System.Text; namespace Barotrauma { class LocalizationCSVtoXML { - private static Regex csvSplit = new Regex("(?:^|,)(\"(?:[^\"])*\"|[^,]*)", RegexOptions.Compiled); // Handling commas inside data fields surrounded by "" - private static List conversationClosingIndent = new List(); - private static char[] separator = new char[1] { '|' }; + private static readonly List conversationClosingIndent = new List(); + private static readonly char[] separator = new char[1] { '|' }; private const string conversationsPath = "Content/NPCConversations"; private const string infoTextPath = "Content/Texts"; private const string xmlHeader = ""; - private static string[,] translatedLanguageNames = new string[13, 2] { { "English", "English" }, { "French", "Français" }, { "German", "Deutsch" }, + private static readonly string[,] translatedLanguageNames = new string[13, 2] { { "English", "English" }, { "French", "Français" }, { "German", "Deutsch" }, { "Russian", "Русский" }, { "Brazilian Portuguese", "Português brasileiro" }, { "Simplified Chinese", "中文(简体)" }, { "Traditional Chinese", "中文(繁體)" }, { "Castilian Spanish", "Castellano" }, { "Latinamerican Spanish", "Español Latinoamericano" }, { "Polish", "Polski" }, { "Turkish", "Türkçe" }, { "Japanese", "日本語" }, { "Korean", "한국어" } }; - public static void Convert() + public static void ConvertMasterLocalizationKit(string outputTextsDirectory, string outputConversationsDirectory, bool convertConversations) + { + string textFilePath = Path.Combine(infoTextPath, "Texts.csv"); + string conversationFilePath = Path.Combine(infoTextPath, "NPCConversations.csv"); + + Dictionary> xmlContent; + try + { + xmlContent = ConvertInfoTextToXML(File.ReadAllLines(textFilePath, Encoding.UTF8)); + } + catch (Exception e) + { + DebugConsole.ThrowError("InfoText Localization .csv to .xml conversion failed for: " + textFilePath, e); + return; + } + if (xmlContent == null) + { + DebugConsole.ThrowError("InfoText Localization .csv to .xml conversion failed for: " + textFilePath); + return; + } + foreach (string language in xmlContent.Keys) + { + string languageNoWhitespace = language.Replace(" ", ""); + string xmlFileFullPath = Path.Combine(outputTextsDirectory, $"{languageNoWhitespace}/{languageNoWhitespace}Vanilla.xml"); + File.WriteAllLines(xmlFileFullPath, xmlContent[language], Encoding.UTF8); + DebugConsole.NewMessage("InfoText localization .xml file successfully created at: " + xmlFileFullPath); + } + + if (convertConversations) + { + var conversationLinesAll = File.ReadAllLines(conversationFilePath, Encoding.UTF8); + foreach (string language in xmlContent.Keys) + { + List convXmlContent = ConvertConversationsToXML(conversationLinesAll, language); + if (convXmlContent == null) + { + DebugConsole.ThrowError("NPCConversation Localization .csv to .xml conversion failed for: " + language); + continue; + } + string languageNoWhitespace = language.Replace(" ", ""); + string xmlFileFullPath = Path.Combine(outputTextsDirectory, $"NpcConversations_{languageNoWhitespace}.xml"); + File.WriteAllLines(xmlFileFullPath, convXmlContent, Encoding.UTF8); + DebugConsole.NewMessage("Conversation localization .xml file successfully created at: " + xmlFileFullPath); + } + } + } + + [Obsolete] + public static void ConvertIndividualFiles() { if (GameSettings.CurrentConfig.Language != TextManager.DefaultLanguage) { @@ -89,8 +134,7 @@ namespace Barotrauma for (int j = 0; j < infoTextFiles.Count; j++) { - - List xmlContent = null; + List xmlContent; try { xmlContent = ConvertInfoTextToXML(File.ReadAllLines(infoTextFiles[j], Encoding.UTF8), language); @@ -121,6 +165,109 @@ namespace Barotrauma } } + private static Dictionary> ConvertInfoTextToXML(string[] csvContent) + { + Dictionary> xmlContentByLanguage = new Dictionary>(); + + //get all the languages from the header row + string headerRow = csvContent[0]; + var headerContent = headerRow.Split(separator); + for (int i = 0; i < headerContent.Length; i++) + { + string languageName = headerContent[i]; + if (languageName.Equals("tag", StringComparison.OrdinalIgnoreCase) || + languageName.Equals("comments", StringComparison.OrdinalIgnoreCase)) + { + continue; + } + string translatedName = GetTranslatedName(languageName); + bool nowhitespace = TextManager.IsCJK(translatedName); + List xmlContent = new List() + { + xmlHeader, + $"" + }; + xmlContentByLanguage.Add(headerContent[i], xmlContent); + } + + for (int row = 1; row < csvContent.Length; row++) // Start at one to ignore header + { + if (!xmlContentByLanguage.Values.All(values => values.Count == xmlContentByLanguage["English"].Count)) + { + throw new Exception($"Error while converting csv to xml: mismatching number of texts on line {row-1} ({csvContent[row - 1]}). Check that there's no extra newlines, separators or missing lines in the csv file."); + } + + if (csvContent[row].Length == 0) + { + AddToAllLanguages(string.Empty); + } + else + { + string[] split = csvContent[row].Split(separator); + + if (split.Length < xmlContentByLanguage.Count) + { + throw new Exception($"Error while converting csv to xml: not enough values on line {row} ({csvContent[row]}). Check that there's no extra newlines, separators or missing lines in the csv file."); + } + + if (split.Length > 1) // Localization data + { + //all values empty = an empty line + if (split.All(s => s.IsNullOrEmpty())) + { + AddToAllLanguages(string.Empty); + } + //value is empty in all languages + else if (!split[0].IsNullOrEmpty() && split.Skip(2).All(s => s.IsNullOrEmpty())) + { + //first line is all lower-case and contains dot, assume it's an empty value + if (split[0].Contains(".") && !split[0].Any(char.IsUpper)) + { + AddToAllLanguages($"<{split[0]}>"); + } + //otherwise assume it's a comment + else + { + AddToAllLanguages($""); + } + } + else + { + for (int j = 0; j < split.Length; j++) + { + string languageName = headerContent[j]; + if (languageName.Equals("tag", StringComparison.OrdinalIgnoreCase) || + languageName.Equals("comments", StringComparison.OrdinalIgnoreCase)) + { + continue; + } + split[j] = split[j].Replace(" & ", " & "); + xmlContentByLanguage[languageName].Add($"<{split[0]}>{split[j]}"); + } + } + } + else // A header/comment + { + AddToAllLanguages($""); + } + } + } + + AddToAllLanguages(string.Empty); + AddToAllLanguages(""); + + void AddToAllLanguages(string str) + { + foreach (var xmlContent in xmlContentByLanguage.Values) + { + xmlContent.Add(str); + } + } + + return xmlContentByLanguage; + } + + [Obsolete] private static List ConvertInfoTextToXML(string[] csvContent, string language) { List xmlContent = new List @@ -147,12 +294,6 @@ namespace Barotrauma if (split.Length >= 2) // Localization data { - if (split.Length > 2 && !split[0].All(char.IsLower)) // Invalid header in line with localization data - { - split[0] = split[1]; - split[1] = split[2]; - split[2] = string.Empty; - } split[1] = split[1].Replace(" & ", " & "); xmlContent.Add($"<{split[0]}>{split[1]}"); } @@ -186,68 +327,39 @@ namespace Barotrauma private static List ConvertConversationsToXML(string[] csvContent, string language) { - List xmlContent = new List(); - xmlContent.Add(xmlHeader); + List xmlContent = new List + { + xmlHeader + }; string translatedName = GetTranslatedName(language); bool nowhitespace = TextManager.IsCJK(translatedName); + int languageColumn = -1; + string[] headerSplit = csvContent[0].Split(separator); + for (int i = 0; i < headerSplit.Length; i++) + { + if (headerSplit[i] == language) + { + languageColumn = i; + break; + } + } + xmlContent.Add($""); - xmlContent.Add(string.Empty); - xmlContent.Add(""); - int traitStart = -1; - for (int i = 0; i < csvContent.Length; i++) - { - if (csvContent[i].StartsWith("Personality")) - { - traitStart = i + 1; - break; - } - } - - int conversationStart = -1; - for (int i = 0; i < csvContent.Length; i++) - { - if (csvContent[i].StartsWith("Generic")) - { - conversationStart = i; - break; - } - } - - if (traitStart == -1) - { - DebugConsole.ThrowError("Invalid formatting of NPCConversations, no traits found!"); - return null; - } - - //DebugConsole.NewMessage("Count: " + NPCPersonalityTrait.List.Count); - var traits = NPCPersonalityTrait.GetAll(language.ToLanguageIdentifier()).ToArray(); - for (int i = 0; i < traits.Length; i++) // Traits - { - //string[] split = SplitCSV(csvContent[traitStart + i].Trim(separator)); - string[] split = csvContent[traitStart + i].Split(separator); - xmlContent.Add( - $""); - } + int conversationStart = 1; xmlContent.Add(string.Empty); for (int i = conversationStart; i < csvContent.Length; i++) // Conversations { string[] split = csvContent[i].Split(separator); - int emptyFields = 0; - for (int j = 0; j < split.Length; j++) { - if (split[j] == string.Empty) emptyFields++; + if (split[j] == string.Empty) { emptyFields++; } } - if (emptyFields == split.Length) // Empty line with only commas, indicates the end of the previous conversation { HandleClosingElements(xmlContent, 0); @@ -260,10 +372,10 @@ namespace Barotrauma continue; } - string speaker = split[1]; - int depthIndex = int.Parse(split[2]); + string line = split[languageColumn].Replace("\"", ""); + string speaker = split[2]; + int depthIndex = int.Parse(split[3]); // 3 = original line - string line = split[3].Replace("\"", ""); string flags = split[4].Replace("\"", ""); string allowedJobs = split[5].Replace("\"", ""); string speakerTags = split[6].Replace("\"", ""); @@ -317,7 +429,7 @@ namespace Barotrauma xmlContent.Add(""); return xmlContent; - } + } private static void HandleClosingElements(List xmlContent, int targetDepth) { @@ -332,24 +444,6 @@ namespace Barotrauma } } - private static string[] SplitCSV(string input) // Splits the .csv with regex, leaving commas inside quotation marks intact - { - List list = new List(); - string curr = null; - foreach (Match match in csvSplit.Matches(input)) - { - curr = match.Value; - if (0 == curr.Length) - { - list.Add(""); - } - - list.Add(curr.TrimStart(separator)); - } - - return list.ToArray(); - } - private static string GetIndenting(int depthIndex) { string indenting = string.Empty; diff --git a/Barotrauma/BarotraumaClient/LinuxClient.csproj b/Barotrauma/BarotraumaClient/LinuxClient.csproj index 251b78f36..04e63b8ad 100644 --- a/Barotrauma/BarotraumaClient/LinuxClient.csproj +++ b/Barotrauma/BarotraumaClient/LinuxClient.csproj @@ -6,7 +6,7 @@ Barotrauma FakeFish, Undertow Games Barotrauma - 0.18.15.0 + 0.19.0.0 Copyright © FakeFish 2018-2022 AnyCPU;x64 Barotrauma @@ -65,7 +65,7 @@ - + diff --git a/Barotrauma/BarotraumaClient/MacClient.csproj b/Barotrauma/BarotraumaClient/MacClient.csproj index 065e6b693..0081ad967 100644 --- a/Barotrauma/BarotraumaClient/MacClient.csproj +++ b/Barotrauma/BarotraumaClient/MacClient.csproj @@ -6,7 +6,7 @@ Barotrauma FakeFish, Undertow Games Barotrauma - 0.18.15.0 + 0.19.0.0 Copyright © FakeFish 2018-2022 AnyCPU;x64 Barotrauma @@ -56,7 +56,7 @@ - + diff --git a/Barotrauma/BarotraumaClient/WindowsClient.csproj b/Barotrauma/BarotraumaClient/WindowsClient.csproj index f684f83ae..dfa092086 100644 --- a/Barotrauma/BarotraumaClient/WindowsClient.csproj +++ b/Barotrauma/BarotraumaClient/WindowsClient.csproj @@ -6,7 +6,7 @@ Barotrauma FakeFish, Undertow Games Barotrauma - 0.18.15.0 + 0.19.0.0 Copyright © FakeFish 2018-2022 AnyCPU;x64 Barotrauma @@ -62,7 +62,7 @@ - + diff --git a/Barotrauma/BarotraumaServer/LinuxServer.csproj b/Barotrauma/BarotraumaServer/LinuxServer.csproj index 868528655..cf881db47 100644 --- a/Barotrauma/BarotraumaServer/LinuxServer.csproj +++ b/Barotrauma/BarotraumaServer/LinuxServer.csproj @@ -6,7 +6,7 @@ Barotrauma FakeFish, Undertow Games Barotrauma Dedicated Server - 0.18.15.0 + 0.19.0.0 Copyright © FakeFish 2018-2022 AnyCPU;x64 DedicatedServer @@ -65,7 +65,7 @@ - + diff --git a/Barotrauma/BarotraumaServer/MacServer.csproj b/Barotrauma/BarotraumaServer/MacServer.csproj index 523a650c6..b7101a67b 100644 --- a/Barotrauma/BarotraumaServer/MacServer.csproj +++ b/Barotrauma/BarotraumaServer/MacServer.csproj @@ -6,7 +6,7 @@ Barotrauma FakeFish, Undertow Games Barotrauma Dedicated Server - 0.18.15.0 + 0.19.0.0 Copyright © FakeFish 2018-2022 AnyCPU;x64 DedicatedServer @@ -58,7 +58,7 @@ - + diff --git a/Barotrauma/BarotraumaServer/ServerSource/Characters/CharacterInfo.cs b/Barotrauma/BarotraumaServer/ServerSource/Characters/CharacterInfo.cs index 197c22a26..5dc354ccb 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Characters/CharacterInfo.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Characters/CharacterInfo.cs @@ -1,5 +1,4 @@ using Barotrauma.Networking; -using Microsoft.Xna.Framework; using System; using System.Collections.Generic; using System.Linq; @@ -66,19 +65,16 @@ namespace Barotrauma if (Job != null) { - msg.Write(Job.Prefab.Identifier); + msg.Write(Job.Prefab.UintIdentifier); msg.Write((byte)Job.Variant); - var skills = Job.GetSkills(); - msg.Write((byte)skills.Count()); - foreach (Skill skill in skills) + foreach (SkillPrefab skillPrefab in Job.Prefab.Skills.OrderBy(s => s.Identifier)) { - msg.Write(skill.Identifier); - msg.Write(skill.Level); + msg.Write(Job.GetSkill(skillPrefab.Identifier).Level); } } else { - msg.Write(""); + msg.Write((uint)0); msg.Write((byte)0); } diff --git a/Barotrauma/BarotraumaServer/ServerSource/Characters/CharacterNetworking.cs b/Barotrauma/BarotraumaServer/ServerSource/Characters/CharacterNetworking.cs index f896b27c5..65f10e4c2 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Characters/CharacterNetworking.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Characters/CharacterNetworking.cs @@ -359,11 +359,12 @@ namespace Barotrauma tempBuffer.Write(AnimController.Dir > 0.0f); } - if (SelectedCharacter != null || SelectedConstruction != null) + if (SelectedCharacter != null || HasSelectedAnyItem) { tempBuffer.Write(true); tempBuffer.Write(SelectedCharacter != null ? SelectedCharacter.ID : NullEntityID); - tempBuffer.Write(SelectedConstruction != null ? SelectedConstruction.ID : NullEntityID); + tempBuffer.Write(SelectedItem != null ? SelectedItem.ID : NullEntityID); + tempBuffer.Write(SelectedSecondaryItem != null ? SelectedSecondaryItem.ID : NullEntityID); if (SelectedCharacter != null) { tempBuffer.Write(AnimController.Anim == AnimController.Animation.CPR); @@ -424,8 +425,8 @@ namespace Barotrauma msg.Write(owner == c && owner.Character == this); msg.Write(owner != null && owner.Character == this && GameMain.Server.ConnectedClients.Contains(owner) ? owner.ID : (byte)0); break; - case CharacterStatusEventData _: - WriteStatus(msg); + case CharacterStatusEventData statusEventData: + WriteStatus(msg, statusEventData.ForceAfflictionData); break; case UpdateSkillsEventData _: if (Info?.Job == null) @@ -573,7 +574,7 @@ namespace Barotrauma msg.WriteRangedInteger((int)CauseOfDeath.Type, 0, Enum.GetValues(typeof(CauseOfDeathType)).Length - 1); if (CauseOfDeath.Type == CauseOfDeathType.Affliction) { - msg.Write(CauseOfDeath.Affliction.Identifier); + msg.Write(CauseOfDeath.Affliction.UintIdentifier); } msg.Write(forceAfflictionData); if (forceAfflictionData) diff --git a/Barotrauma/BarotraumaServer/ServerSource/Events/EventActions/ConversationAction.cs b/Barotrauma/BarotraumaServer/ServerSource/Events/EventActions/ConversationAction.cs index 718c588b9..0336b9ed0 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Events/EventActions/ConversationAction.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Events/EventActions/ConversationAction.cs @@ -58,7 +58,7 @@ namespace Barotrauma Reset(); } - private bool IsBlockedByAnotherConversation(IEnumerable targets) + private bool IsBlockedByAnotherConversation(IEnumerable targets, float duration) { foreach (Entity e in targets) { @@ -68,7 +68,7 @@ namespace Barotrauma { if (lastActiveAction.ContainsKey(targetClient) && lastActiveAction[targetClient].ParentEvent != ParentEvent && - Timing.TotalTime < lastActiveAction[targetClient].lastActiveTime + BlockOtherConversationsDuration) + Timing.TotalTime < lastActiveAction[targetClient].lastActiveTime + duration) { return true; } @@ -91,7 +91,7 @@ namespace Barotrauma { targetClients.Add(targetClient); lastActiveAction[targetClient] = this; - ServerWrite(speaker, targetClient); + ServerWrite(speaker, targetClient, interrupt); } } } @@ -105,14 +105,14 @@ namespace Barotrauma { targetClients.Add(c); lastActiveAction[c] = this; - ServerWrite(speaker, c); + ServerWrite(speaker, c, interrupt); } } } } } - private void ServerWrite(Character speaker, Client client) + public void ServerWrite(Character speaker, Client client, bool interrupt) { IWriteMessage outmsg = new WriteOnlyMessage(); outmsg.Write((byte)ServerPacketHeader.EVENTACTION); diff --git a/Barotrauma/BarotraumaServer/ServerSource/Events/EventManager.cs b/Barotrauma/BarotraumaServer/ServerSource/Events/EventManager.cs index 7446dfd5d..dfa4bc4c0 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Events/EventManager.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Events/EventManager.cs @@ -27,16 +27,24 @@ namespace Barotrauma #endif continue; } - - if (selectedOption == byte.MaxValue) + + if (convAction.SelectedOption > -1) { - convAction.IgnoreClient(sender, 3f); + //someone else already chose an option for this conversation: interrupt for this client + convAction.ServerWrite(convAction.speaker, sender, interrupt: true); } else { - convAction.SelectedOption = selectedOption; + if (selectedOption == byte.MaxValue) + { + convAction.IgnoreClient(sender, 3f); + } + else + { + convAction.SelectedOption = selectedOption; + } } - return; + return; } } } diff --git a/Barotrauma/BarotraumaServer/ServerSource/GameMain.cs b/Barotrauma/BarotraumaServer/ServerSource/GameMain.cs index 4af9addf0..42b514127 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/GameMain.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/GameMain.cs @@ -329,7 +329,7 @@ namespace Barotrauma if (Server == null) { break; } SteamManager.Update((float)Timing.Step); TaskPool.Update(); - CoroutineManager.Update((float)Timing.Step, (float)Timing.Step); + CoroutineManager.Update(paused: false, (float)Timing.Step); Timing.Accumulator -= Timing.Step; updateCount++; diff --git a/Barotrauma/BarotraumaServer/ServerSource/GameSession/Data/Wallet.cs b/Barotrauma/BarotraumaServer/ServerSource/GameSession/Data/Wallet.cs index 7c0767001..a4f06ea89 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/GameSession/Data/Wallet.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/GameSession/Data/Wallet.cs @@ -6,6 +6,8 @@ namespace Barotrauma { private readonly Queue transactions = new Queue(); + public bool ShouldForceUpdate; + partial void SettingsChanged(Option balanceChanged, Option rewardChanged) { transactions.Enqueue(new WalletChangedData @@ -15,6 +17,15 @@ namespace Barotrauma }); } + /// + /// Forces the server to sync the state of the wallet regardless if the balance/reward has changed + /// + public void ForceUpdate() + { + SettingsChanged(balanceChanged: Option.Some(0), rewardChanged: Option.None()); + ShouldForceUpdate = true; + } + public bool HasTransactions() => transactions.Count > 0; public NetWalletTransaction DequeueAndMergeTransactions(ushort id) diff --git a/Barotrauma/BarotraumaServer/ServerSource/GameSession/GameModes/MultiPlayerCampaign.cs b/Barotrauma/BarotraumaServer/ServerSource/GameSession/GameModes/MultiPlayerCampaign.cs index 6dbe8ff73..61caf6e9d 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/GameSession/GameModes/MultiPlayerCampaign.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/GameSession/GameModes/MultiPlayerCampaign.cs @@ -354,6 +354,7 @@ namespace Barotrauma LeaveUnconnectedSubs(leavingSub); NextLevel = newLevel; GameMain.GameSession.SubmarineInfo = new SubmarineInfo(GameMain.GameSession.Submarine); + GameMain.GameSession.EventManager.RegisterEventHistory(); SaveUtil.SaveGame(GameMain.GameSession.SavePath); } else @@ -530,8 +531,9 @@ namespace Barotrauma if (wallet.HasTransactions()) { NetWalletTransaction transaction = wallet.DequeueAndMergeTransactions(id); - if (transaction.ChangedData.BalanceChanged.IsNone() && transaction.ChangedData.RewardDistributionChanged.IsNone()) { continue; } + if (!wallet.ShouldForceUpdate && transaction.ChangedData.BalanceChanged.IsNone() && transaction.ChangedData.RewardDistributionChanged.IsNone()) { continue; } transactions.Add(transaction); + wallet.ShouldForceUpdate = false; } } @@ -790,11 +792,19 @@ namespace Barotrauma purchasedItemSwaps.Add(new PurchasedItemSwap(itemToRemove, itemToInstall)); } + int hullRepairCost = GetHullRepairCost(); + int itemRepairCost = GetItemRepairCost(); + int shuttleRetrieveCost = CampaignMode.ShuttleReplaceCost; Location location = Map.CurrentLocation; - int hullRepairCost = location?.GetAdjustedMechanicalCost(HullRepairCost) ?? HullRepairCost; - int itemRepairCost = location?.GetAdjustedMechanicalCost(ItemRepairCost) ?? ItemRepairCost; - int shuttleRetrieveCost = location?.GetAdjustedMechanicalCost(ShuttleReplaceCost) ?? ShuttleReplaceCost; + if (location != null) + { + hullRepairCost = location.GetAdjustedMechanicalCost(hullRepairCost); + itemRepairCost = location.GetAdjustedMechanicalCost(itemRepairCost); + shuttleRetrieveCost = location.GetAdjustedMechanicalCost(shuttleRetrieveCost); + } + Wallet personalWallet = GetWallet(sender); + personalWallet?.ForceUpdate(); if (purchasedHullRepairs != PurchasedHullRepairs) { @@ -875,6 +885,9 @@ namespace Barotrauma { foreach (var item in store.Value.ToList()) { + if (map?.CurrentLocation?.Stores == null || !map.CurrentLocation.Stores.ContainsKey(store.Key)) { continue; } + item.Quantity = Math.Min(map.CurrentLocation.Stores[store.Key].Stock.Find(s => s.ItemPrefab == item.ItemPrefab)?.Quantity ?? 0, item.Quantity); + if (item.Quantity <= 0) { continue; } CargoManager.ModifyItemQuantityInBuyCrate(store.Key, item.ItemPrefab, item.Quantity, sender); } } diff --git a/Barotrauma/BarotraumaServer/ServerSource/Networking/Client.cs b/Barotrauma/BarotraumaServer/ServerSource/Networking/Client.cs index fe720421c..f385efcde 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Networking/Client.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Networking/Client.cs @@ -62,6 +62,8 @@ namespace Barotrauma.Networking public float DeleteDisconnectedTimer; + public DateTime JoinTime; + private CharacterInfo characterInfo; public CharacterInfo CharacterInfo { @@ -114,6 +116,8 @@ namespace Barotrauma.Networking //initialize to infinity, gets set to a proper value when initializing midround syncing MidRoundSyncTimeOut = double.PositiveInfinity; + + JoinTime = DateTime.Now; } partial void DisposeProjSpecific() diff --git a/Barotrauma/BarotraumaServer/ServerSource/Networking/GameServer.cs b/Barotrauma/BarotraumaServer/ServerSource/Networking/GameServer.cs index e246d4549..74984923c 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Networking/GameServer.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Networking/GameServer.cs @@ -2081,7 +2081,7 @@ namespace Barotrauma.Networking float waitForResponseTimer = 5.0f; while (connectedClients.Any(c => !c.ReadyToStart) && waitForResponseTimer > 0.0f) { - waitForResponseTimer -= CoroutineManager.UnscaledDeltaTime; + waitForResponseTimer -= CoroutineManager.DeltaTime; yield return CoroutineStatus.Running; } @@ -2090,7 +2090,7 @@ namespace Barotrauma.Networking float waitForTransfersTimer = 20.0f; while (FileSender.ActiveTransfers.Count > 0 && waitForTransfersTimer > 0.0f) { - waitForTransfersTimer -= CoroutineManager.UnscaledDeltaTime; + waitForTransfersTimer -= CoroutineManager.DeltaTime; yield return CoroutineStatus.Running; } } @@ -3278,7 +3278,8 @@ namespace Barotrauma.Networking Client.UpdateKickVotes(connectedClients); - int minimumKickVotes = Math.Max(1, (int)(connectedClients.Count * serverSettings.KickVoteRequiredRatio)); + var kickVoteEligibleClients = connectedClients.Where(c => (DateTime.Now - c.JoinTime).TotalSeconds > ServerSettings.DisallowKickVoteTime); + int minimumKickVotes = Math.Max(2, (int)(kickVoteEligibleClients.Count() * serverSettings.KickVoteRequiredRatio)); var clientsToKick = connectedClients.FindAll(c => c.Connection != OwnerConnection && !c.HasPermission(ClientPermissions.Kick) && @@ -3581,14 +3582,14 @@ namespace Barotrauma.Networking List jobPreferences = new List(); int count = message.ReadByte(); - // TODO: modding support? for (int i = 0; i < Math.Min(count, 3); i++) { string jobIdentifier = message.ReadString(); int variant = message.ReadByte(); - if (JobPrefab.Prefabs.ContainsKey(jobIdentifier)) + if (JobPrefab.Prefabs.TryGet(jobIdentifier, out JobPrefab jobPrefab)) { - jobPreferences.Add(new JobVariant(JobPrefab.Prefabs[jobIdentifier], variant)); + if (jobPrefab.HiddenJob) { continue; } + jobPreferences.Add(new JobVariant(jobPrefab, variant)); } } diff --git a/Barotrauma/BarotraumaServer/ServerSource/Networking/KarmaManager.cs b/Barotrauma/BarotraumaServer/ServerSource/Networking/KarmaManager.cs index e86a858f5..e732ce117 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Networking/KarmaManager.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Networking/KarmaManager.cs @@ -188,9 +188,9 @@ namespace Barotrauma } } - if (client.Character?.Info?.Job.Prefab.Identifier == "captain" && client.Character.SelectedConstruction != null) + if (client.Character?.Info?.Job.Prefab.Identifier == "captain" && client.Character.SelectedItem != null) { - if (client.Character.SelectedConstruction.GetComponent() != null) + if (client.Character.SelectedItem.GetComponent() != null) { AdjustKarma(client.Character, SteerSubKarmaIncrease * deltaTime, "Steering the sub"); } diff --git a/Barotrauma/BarotraumaServer/ServerSource/Networking/RespawnManager.cs b/Barotrauma/BarotraumaServer/ServerSource/Networking/RespawnManager.cs index de685bebf..c65ba58d2 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Networking/RespawnManager.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Networking/RespawnManager.cs @@ -125,7 +125,7 @@ namespace Barotrauma.Networking return characterToRespawnCount >= GetMinCharactersToRespawn(); } - partial void UpdateWaiting(float deltaTime) + partial void UpdateWaiting(float _) { if (RespawnShuttle != null) { @@ -487,6 +487,20 @@ namespace Barotrauma.Networking { AutoItemPlacer.RegenerateLoot(RespawnShuttle, respawnContainer); } + + //try to put the items in containers in the shuttle + foreach (var respawnItem in respawnItems) + { + foreach (Item shuttleItem in RespawnShuttle.GetItems(alsoFromConnectedSubs: false)) + { + if (shuttleItem.NonInteractable || shuttleItem.NonPlayerTeamInteractable) { continue; } + var container = shuttleItem.GetComponent(); + if (container != null && container.Inventory.TryPutItem(respawnItem, user: null)) + { + break; + } + } + } } var characterData = campaign?.GetClientCharacterData(clients[i]); diff --git a/Barotrauma/BarotraumaServer/ServerSource/Networking/Voting.cs b/Barotrauma/BarotraumaServer/ServerSource/Networking/Voting.cs index 4724420b4..0ee0a0d73 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Networking/Voting.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Networking/Voting.cs @@ -254,15 +254,21 @@ namespace Barotrauma break; case VoteType.Kick: byte kickedClientID = inc.ReadByte(); - - Client kicked = GameMain.Server.ConnectedClients.Find(c => c.ID == kickedClientID); - if (kicked != null && kicked.Connection != GameMain.Server.OwnerConnection && !kicked.HasKickVoteFrom(sender)) + if ((DateTime.Now - sender.JoinTime).TotalSeconds > GameMain.Server.ServerSettings.DisallowKickVoteTime) { - kicked.AddKickVote(sender); - Client.UpdateKickVotes(GameMain.Server.ConnectedClients); - GameMain.Server.SendChatMessage($"ServerMessage.HasVotedToKick~[initiator]={sender.Name}~[target]={kicked.Name}", ChatMessageType.Server, null); - } + GameMain.Server.SendDirectChatMessage($"ServerMessage.kickvotedisallowed", sender); + } + else + { + Client kicked = GameMain.Server.ConnectedClients.Find(c => c.ID == kickedClientID); + if (kicked != null && kicked.Connection != GameMain.Server.OwnerConnection && !kicked.HasKickVoteFrom(sender)) + { + kicked.AddKickVote(sender); + Client.UpdateKickVotes(GameMain.Server.ConnectedClients); + GameMain.Server.SendChatMessage($"ServerMessage.HasVotedToKick~[initiator]={sender.Name}~[target]={kicked.Name}", ChatMessageType.Server, null); + } + } break; case VoteType.StartRound: bool ready = inc.ReadBoolean(); diff --git a/Barotrauma/BarotraumaServer/ServerSource/Program.cs b/Barotrauma/BarotraumaServer/ServerSource/Program.cs index c2fccb428..993323acb 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Program.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Program.cs @@ -55,6 +55,10 @@ namespace Barotrauma #if LINUX setLinuxEnv(); + AppDomain.CurrentDomain.ProcessExit += (s, e) => + { + GameMain.ShouldRun = false; + }; #endif Console.WriteLine("Barotrauma Dedicated Server " + GameMain.Version + " (" + AssemblyInfo.BuildString + ", branch " + AssemblyInfo.GitBranch + ", revision " + AssemblyInfo.GitRevision + ")"); @@ -93,7 +97,7 @@ namespace Barotrauma private static void CrashHandler(object sender, UnhandledExceptionEventArgs args) { - void swallowExceptions(Action action) + static void swallowExceptions(Action action) { try { diff --git a/Barotrauma/BarotraumaServer/WindowsServer.csproj b/Barotrauma/BarotraumaServer/WindowsServer.csproj index 43732773c..0b500d712 100644 --- a/Barotrauma/BarotraumaServer/WindowsServer.csproj +++ b/Barotrauma/BarotraumaServer/WindowsServer.csproj @@ -6,7 +6,7 @@ Barotrauma FakeFish, Undertow Games Barotrauma Dedicated Server - 0.18.15.0 + 0.19.0.0 Copyright © FakeFish 2018-2022 AnyCPU;x64 DedicatedServer @@ -60,7 +60,7 @@ - + diff --git a/Barotrauma/BarotraumaShared/ModLists/Release checklist mods.xml b/Barotrauma/BarotraumaShared/ModLists/Release checklist mods.xml new file mode 100644 index 000000000..8a2bef012 --- /dev/null +++ b/Barotrauma/BarotraumaShared/ModLists/Release checklist mods.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/HumanAIController.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/HumanAIController.cs index 6727b9637..62f664d39 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/HumanAIController.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/HumanAIController.cs @@ -511,9 +511,9 @@ namespace Barotrauma { newDir = Direction.Left; } - if (Character.SelectedConstruction != null) + if (Character.SelectedItem != null) { - Character.SelectedConstruction.SecondaryUse(deltaTime, Character); + Character.SelectedItem.SecondaryUse(deltaTime, Character); } } else if (AutoFaceMovement && Math.Abs(Character.AnimController.TargetMovement.X) > 0.1f && !Character.AnimController.InWater) @@ -2148,7 +2148,7 @@ namespace Barotrauma if (c.Removed) { continue; } if (c.TeamID != team) { continue; } if (c.IsIncapacitated) { continue; } - if (c.SelectedConstruction == target.Item) + if (c.SelectedItem == target.Item) { operatingCharacter = c; return true; @@ -2185,7 +2185,7 @@ namespace Barotrauma if (c.IsIncapacitated) { continue; } if (c.IsPlayer) { - if (c.SelectedConstruction == target.Item) + if (c.SelectedItem == target.Item) { // If the other character is player, don't try to operate other = c; diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/IndoorsSteeringManager.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/IndoorsSteeringManager.cs index 0c46fca5d..740c80b72 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/IndoorsSteeringManager.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/IndoorsSteeringManager.cs @@ -79,7 +79,8 @@ namespace Barotrauma { pathFinder = new PathFinder(WayPoint.WayPointList.FindAll(wp => wp.SpawnType == SpawnType.Path), true) { - GetNodePenalty = GetNodePenalty + GetNodePenalty = GetNodePenalty, + GetSingleNodePenalty = GetSingleNodePenalty }; this.canOpenDoors = canOpenDoors; @@ -360,7 +361,7 @@ namespace Barotrauma Ladder nextLadder = GetNextLadder(); var ladders = currentLadder ?? nextLadder; bool useLadders = canClimb && ladders != null && steering.LengthSquared() > 0.1f && (!isDiving || steering.Y > 1); - if (useLadders && character.SelectedConstruction != ladders.Item) + if (useLadders && character.SelectedSecondaryItem != ladders.Item) { if (character.CanInteractWith(ladders.Item)) { @@ -372,7 +373,7 @@ namespace Barotrauma // Try to select the previous ladder, unless it's already selected, unless the previous ladder is not adjacent to the current ladder. // The intention of this code is to prevent the bots from dropping from the "double ladders". var previousLadders = currentPath.PrevNode?.Ladders; - if (previousLadders != null && previousLadders != ladders && character.SelectedConstruction != previousLadders.Item && + if (previousLadders != null && previousLadders != ladders && character.SelectedSecondaryItem != previousLadders.Item && character.CanInteractWith(previousLadders.Item) && Math.Abs(previousLadders.Item.WorldPosition.X - ladders.Item.WorldPosition.X) < 5) { previousLadders.Item.TryInteract(character, forceSelectKey: true); @@ -382,8 +383,7 @@ namespace Barotrauma var collider = character.AnimController.Collider; if (character.IsClimbing && !useLadders) { - character.AnimController.Anim = AnimController.Animation.None; - character.SelectedConstruction = null; + character.StopClimbing(); } if (character.IsClimbing && useLadders) { @@ -402,15 +402,14 @@ namespace Barotrauma // We need some margin, because if a hatch has closed, it's possible that the height from floor is slightly negative. bool isAboveFloor = heightFromFloor > -0.1f; // If the next waypoint is horizontally far, we don't want to keep holding the ladders - if (isAboveFloor && (nextLadder == null || Math.Abs(currentPath.CurrentNode.WorldPosition.X - currentPath.NextNode.WorldPosition.X) > 50)) + if (isAboveFloor && !currentPath.IsAtEndNode && (nextLadder == null || Math.Abs(currentPath.CurrentNode.WorldPosition.X - currentPath.NextNode.WorldPosition.X) > 50)) { - character.AnimController.Anim = AnimController.Animation.None; - character.SelectedConstruction = null; + character.StopClimbing(); } else if (nextLadder != null && !nextLadderSameAsCurrent) { // Try to change the ladder (hatches between two submarines) - if (character.SelectedConstruction != nextLadder.Item && character.CanInteractWith(nextLadder.Item)) + if (character.SelectedSecondaryItem != nextLadder.Item && character.CanInteractWith(nextLadder.Item)) { if (nextLadder.Item.TryInteract(character, forceSelectKey: true)) { @@ -418,7 +417,7 @@ namespace Barotrauma } } } - if (isAboveFloor || nextLadderSameAsCurrent || nextLadder == null && Math.Abs(diff.Y) < 10) + if (!currentPath.IsAtEndNode && (isAboveFloor || nextLadderSameAsCurrent || nextLadder == null && Math.Abs(diff.Y) < 10)) { NextNode(!doorsChecked); } @@ -756,42 +755,8 @@ namespace Barotrauma private float? GetNodePenalty(PathNode node, PathNode nextNode) { if (character == null) { return 0.0f; } - if (nextNode.Waypoint.isObstructed) { return null; } - float penalty = 0.0f; - if (nextNode.Waypoint.ConnectedGap != null && nextNode.Waypoint.ConnectedGap.Open < 0.9f) - { - var door = nextNode.Waypoint.ConnectedDoor; - if (door == null) - { - penalty = 100.0f; - } - else - { - if (!CanAccessDoor(door, button => - { - // Ignore buttons that are on the wrong side of the door - if (door.IsHorizontal) - { - if (Math.Sign(button.Item.WorldPosition.Y - door.Item.WorldPosition.Y) != Math.Sign(character.WorldPosition.Y - door.Item.WorldPosition.Y)) - { - return false; - } - } - else - { - if (Math.Sign(button.Item.WorldPosition.X - door.Item.WorldPosition.X) != Math.Sign(character.WorldPosition.X - door.Item.WorldPosition.X)) - { - return false; - } - } - return true; - })) - { - return null; - } - } - } - + float? penalty = GetSingleNodePenalty(nextNode); + if (penalty == null) { return null; } bool nextNodeAboveWaterLevel = nextNode.Waypoint.CurrentHull != null && nextNode.Waypoint.CurrentHull.Surface < nextNode.Waypoint.Position.Y; //non-humanoids can't climb up ladders if (!(character.AnimController is HumanoidAnimController)) @@ -839,6 +804,47 @@ namespace Barotrauma return penalty; } + private float? GetSingleNodePenalty(PathNode node) + { + if (node.Waypoint.isObstructed) { return null; } + if (node.IsBlocked()) { return null; } + float penalty = 0.0f; + if (node.Waypoint.ConnectedGap != null && node.Waypoint.ConnectedGap.Open < 0.9f) + { + var door = node.Waypoint.ConnectedDoor; + if (door == null) + { + penalty = 100.0f; + } + else + { + if (!CanAccessDoor(door, button => + { + // Ignore buttons that are on the wrong side of the door + if (door.IsHorizontal) + { + if (Math.Sign(button.Item.WorldPosition.Y - door.Item.WorldPosition.Y) != Math.Sign(character.WorldPosition.Y - door.Item.WorldPosition.Y)) + { + return false; + } + } + else + { + if (Math.Sign(button.Item.WorldPosition.X - door.Item.WorldPosition.X) != Math.Sign(character.WorldPosition.X - door.Item.WorldPosition.X)) + { + return false; + } + } + return true; + })) + { + return null; + } + } + } + return penalty; + } + public static float smallRoomSize = 500; public void Wander(float deltaTime, float wallAvoidDistance = 150, bool stayStillInTightSpace = true) { diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/NPCConversation.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/NPCConversation.cs index 594ba9045..f3a2a9c39 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/NPCConversation.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/NPCConversation.cs @@ -14,13 +14,11 @@ namespace Barotrauma public readonly LanguageIdentifier Language; public readonly List Conversations; - public readonly Dictionary PersonalityTraits; public NPCConversationCollection(NPCConversationsFile file, ContentXElement element) : base(file, element.GetAttributeIdentifier("identifier", "")) { Language = element.GetAttributeIdentifier("language", "English").ToLanguageIdentifier(); Conversations = new List(); - PersonalityTraits = new Dictionary(); foreach (var subElement in element.Elements()) { Identifier elemName = new Identifier(subElement.Name.LocalName); @@ -28,11 +26,6 @@ namespace Barotrauma { Conversations.Add(new NPCConversation(subElement)); } - else if (elemName == "PersonalityTrait") - { - var personalityTrait = new NPCPersonalityTrait(subElement); - PersonalityTraits.Add(personalityTrait.Name, personalityTrait); - } } } @@ -361,10 +354,13 @@ namespace Barotrauma private static float GetConversationProbability(NPCConversation conversation) { - int index = previousConversations.IndexOf(conversation); - if (index < 0) return 10.0f; + //prefer choosing conversations with more flags (= for more specific situations) when possible + float baseProbability = MathF.Pow(conversation.Flags.Count + 1, 2); - return 1.0f - 1.0f / (index + 1); + int index = previousConversations.IndexOf(conversation); + if (index < 0) { return baseProbability * 10.0f; } + + return baseProbability + 1.0f - 1.0f / (index + 1); } #if DEBUG diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveCombat.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveCombat.cs index c3a21854d..34fed7024 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveCombat.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveCombat.cs @@ -512,6 +512,23 @@ namespace Barotrauma foreach (var weapon in weaponList) { float priority = weapon.CombatPriority; + if (weapon is RepairTool repairTool) + { + switch (repairTool.UsableIn) + { + case RepairTool.UseEnvironment.Air: + if (character.InWater) { continue; } + break; + case RepairTool.UseEnvironment.Water: + if (!character.InWater) { continue; } + break; + case RepairTool.UseEnvironment.None: + continue; + case RepairTool.UseEnvironment.Both: + default: + break; + } + } if (prioritizeMelee) { if (weapon is MeleeWeapon) diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveGoTo.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveGoTo.cs index 4bf65a912..640973cda 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveGoTo.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveGoTo.cs @@ -196,10 +196,7 @@ namespace Barotrauma character.AIController.SteeringManager.Reset(); return; } - if (!character.IsClimbing) - { - character.SelectedConstruction = null; - } + character.SelectedItem = null; if (Target is Entity e) { if (e.Removed) @@ -647,7 +644,7 @@ namespace Barotrauma { if (character.IsClimbing) { - if (SteeringManager == PathSteering && PathSteering.CurrentPath != null && !PathSteering.CurrentPath.Finished && PathSteering.IsCurrentNodeLadder) + if (SteeringManager == PathSteering && PathSteering.CurrentPath != null && !PathSteering.CurrentPath.Finished && PathSteering.IsCurrentNodeLadder && !PathSteering.CurrentPath.IsAtEndNode) { if (Target.WorldPosition.Y > character.WorldPosition.Y) { @@ -694,7 +691,7 @@ namespace Barotrauma { if (Target is Item item) { - if (!character.IsClimbing && character.CanInteractWith(item, out _, checkLinked: false)) { IsCompleted = true; } + if (character.CanInteractWith(item, out _, checkLinked: false)) { IsCompleted = true; } } else if (Target is Character targetCharacter) { diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveIdle.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveIdle.cs index 5b5665bf9..4d5fbb243 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveIdle.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveIdle.cs @@ -161,10 +161,7 @@ namespace Barotrauma character.DeselectCharacter(); } - if (!character.IsClimbing) - { - character.SelectedConstruction = null; - } + character.SelectedItem = null; CleanupItems(deltaTime); @@ -310,7 +307,7 @@ namespace Barotrauma if (character.AnimController.GetHeightFromFloor() < 0.1f) { character.AnimController.Anim = AnimController.Animation.None; - character.SelectedConstruction = null; + character.SelectedSecondaryItem = null; } return; } @@ -375,7 +372,7 @@ namespace Barotrauma } chairCheckTimer -= deltaTime; - if (chairCheckTimer <= 0.0f && character.SelectedConstruction == null) + if (chairCheckTimer <= 0.0f && character.SelectedSecondaryItem == null) { foreach (Item item in Item.ItemList) { diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveOperateItem.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveOperateItem.cs index f1bf0e45f..56a453007 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveOperateItem.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveOperateItem.cs @@ -205,7 +205,7 @@ namespace Barotrauma if (!character.IsClimbing && character.CanInteractWith(target.Item, out _, checkLinked: false)) { HumanAIController.FaceTarget(target.Item); - if (character.SelectedConstruction != target.Item) + if (character.SelectedItem != target.Item) { target.Item.TryInteract(character, forceSelectKey: true); } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveRepairItem.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveRepairItem.cs index ee2c985fb..78fc1a261 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveRepairItem.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveRepairItem.cs @@ -26,7 +26,7 @@ namespace Barotrauma private bool IsRepairing() => IsRepairing(character, Item); private readonly bool isPriority; - public static bool IsRepairing(Character character, Item item) => character.SelectedConstruction == item && item.Repairables.Any(r => r.CurrentFixer == character); + public static bool IsRepairing(Character character, Item item) => character.SelectedItem == item && item.Repairables.Any(r => r.CurrentFixer == character); public AIObjectiveRepairItem(Character character, Item item, AIObjectiveManager objectiveManager, float priorityModifier = 1, bool isPriority = false) : base(character, objectiveManager, priorityModifier) @@ -165,7 +165,7 @@ namespace Barotrauma return; } } - if (!character.IsClimbing && character.CanInteractWith(Item, out _, checkLinked: false)) + if (character.CanInteractWith(Item, out _, checkLinked: false)) { waitTimer += deltaTime; if (waitTimer < WaitTimeBeforeRepair) { return; } @@ -184,12 +184,12 @@ namespace Barotrauma } if (!Abandon) { - if (character.SelectedConstruction != Item) + if (character.SelectedItem != Item) { if (Item.TryInteract(character, ignoreRequiredItems: true, forceSelectKey: true) || Item.TryInteract(character, ignoreRequiredItems: true, forceUseKey: true)) { - character.SelectedConstruction = Item; + character.SelectedItem = Item; } else { @@ -232,8 +232,6 @@ namespace Barotrauma previousCondition = -1; var objective = new AIObjectiveGoTo(Item, character, objectiveManager) { - // Don't stop in ladders, because we can't interact with other items while holding the ladders. - endNodeFilter = node => node.Waypoint.Ladders == null, TargetName = Item.Name }; if (repairTool != null) diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveRepairItems.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveRepairItems.cs index 90578f6b9..c2539d899 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveRepairItems.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveRepairItems.cs @@ -67,7 +67,7 @@ namespace Barotrauma if (!ViableForRepair(item, character, HumanAIController)) { return false; }; if (!Objectives.ContainsKey(item)) { - if (item != character.SelectedConstruction) + if (item != character.SelectedItem) { if (NearlyFullCondition(item)) { return false; } } @@ -96,7 +96,7 @@ namespace Barotrauma protected override float TargetEvaluation() { - var selectedItem = character.SelectedConstruction; + var selectedItem = character.SelectedItem; if (selectedItem != null && AIObjectiveRepairItem.IsRepairing(character, selectedItem) && selectedItem.ConditionPercentage < 100) { // Don't stop fixing until completely done diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/PathFinder.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/PathFinder.cs index 3a8186c25..9e9398673 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/PathFinder.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/PathFinder.cs @@ -109,6 +109,8 @@ namespace Barotrauma { public delegate float? GetNodePenaltyHandler(PathNode node, PathNode prevNode); public GetNodePenaltyHandler GetNodePenalty; + public delegate float? GetSingleNodePenaltyHandler(PathNode node); + public GetSingleNodePenaltyHandler GetSingleNodePenalty; private readonly List nodes; private readonly bool isCharacter; @@ -282,8 +284,6 @@ namespace Barotrauma } //avoid stopping at a doorway if (node.Waypoint.ConnectedDoor != null) { node.TempDistance *= 10.0f; } - //avoid stopping at a ladder - if (node.Waypoint.Ladders != null) { node.TempDistance *= 10.0f; } } //optimization: node extremely far (> 100m / 800 m) from the end position, don't try to use it as an end node if (node.TempDistance > (InsideSubmarine ? 100.0f * 100.0f : 800.0f * 800.0f)) @@ -325,15 +325,24 @@ namespace Barotrauma #endif return new SteeringPath(true); } - var path = FindPath(startNode, endNode, nodeFilter, errorMsgStr, minGapSize); - return path; + return FindPath(startNode, endNode, nodeFilter, errorMsgStr, minGapSize); - bool IsWaypointVisible(PathNode node, Vector2 rayStart, bool checkVisibility = true) + bool IsValidStartNode(PathNode node) => IsValidNode(node, (isCharacter, start), startNodeFilter); + + bool IsValidEndNode(PathNode node) => IsValidNode(node, (isCharacter && checkVisibility, end), endNodeFilter); + + bool IsValidNode(PathNode node, (bool check, Vector2 start) visibilityCheck, Func extraFilter) { - //if searching for a path inside the sub, make sure the waypoint is visible - if (checkVisibility && isCharacter) + if (nodeFilter != null && !nodeFilter(node)) { return false; } + if (extraFilter != null && !extraFilter(node)) { return false; } + if (GetSingleNodePenalty != null && GetSingleNodePenalty(node) == null) { return false; } + if (node.Waypoint.ConnectedGap != null) { - var body = Submarine.PickBody(rayStart, node.TempPosition, + if (!CanFitThroughGap(node.Waypoint.ConnectedGap, minGapSize)) { return false; } + } + if (visibilityCheck.check) + { + var body = Submarine.PickBody(visibilityCheck.start, node.TempPosition, collisionCategory: Physics.CollisionWall | Physics.CollisionLevel | Physics.CollisionStairs); if (body != null) { @@ -344,36 +353,6 @@ namespace Barotrauma } return true; } - - bool IsValidStartNode(PathNode node) - { - if (nodeFilter != null && !nodeFilter(node)) { return false; } - if (startNodeFilter != null && !startNodeFilter(node)) { return false; } - if (node.Waypoint.isObstructed) { return false; } - // Always check the visibility for the start node - if (!IsWaypointVisible(node, start)) { return false; } - if (node.IsBlocked()) { return false; } - if (node.Waypoint.ConnectedGap != null) - { - if (!CanFitThroughGap(node.Waypoint.ConnectedGap, minGapSize)) { return false; } - } - return true; - } - - bool IsValidEndNode(PathNode node) - { - if (nodeFilter != null && !nodeFilter(node)) { return false; } - if (endNodeFilter != null && !endNodeFilter(node)) { return false; } - if (node.Waypoint.isObstructed) { return false; } - // Only check the visibility for the end node when allowed (fix leaks) - if (!IsWaypointVisible(node, end, checkVisibility: checkVisibility)) { return false; } - if (node.IsBlocked()) { return false; } - if (node.Waypoint.ConnectedGap != null) - { - if (!CanFitThroughGap(node.Waypoint.ConnectedGap, minGapSize)) { return false; } - } - return true; - } } private SteeringPath FindPath(PathNode start, PathNode end, Func filter = null, string errorMsgStr = "", float minGapSize = 0) @@ -402,15 +381,13 @@ namespace Barotrauma foreach (PathNode node in nodes) { if (node.state != 1 || node.F > dist) { continue; } - if (isCharacter && node.Waypoint.isObstructed) { continue; } if (filter != null && !filter(node)) { continue; } - if (node.IsBlocked()) { continue; } if (node.Waypoint.ConnectedGap != null) { if (!CanFitThroughGap(node.Waypoint.ConnectedGap, minGapSize)) { continue; } - } + } dist = node.F; - currNode = node; + currNode = node; } if (currNode == null || currNode == end) { break; } @@ -515,7 +492,4 @@ namespace Barotrauma private bool CanFitThroughGap(Gap gap, float minWidth) => gap.IsHorizontal ? gap.RectHeight > minWidth : gap.RectWidth > minWidth; } -} - - - +} \ No newline at end of file diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/SteeringPath.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/SteeringPath.cs index 24a3feb2b..eb7b56db4 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/SteeringPath.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/SteeringPath.cs @@ -115,6 +115,8 @@ namespace Barotrauma } } + public bool IsAtEndNode => currentIndex >= nodes.Count - 1; + public List Nodes { get { return nodes; } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/Animation/AnimController.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/Animation/AnimController.cs index 258eb4e33..928dd8e74 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/Animation/AnimController.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/Animation/AnimController.cs @@ -101,7 +101,7 @@ namespace Barotrauma { if (InWater || !CanWalk) { - return TargetMovement.LengthSquared() > MathUtils.Pow2(SwimSlowParams.MovementSpeed); + return TargetMovement.LengthSquared() > MathUtils.Pow2(SwimSlowParams.MovementSpeed + 0.0001f); } else { @@ -134,9 +134,12 @@ namespace Barotrauma } } - public enum Animation { None, Climbing, UsingConstruction, Struggle, CPR }; + public enum Animation { None, Climbing, UsingItem, Struggle, CPR, UsingItemWhileClimbing }; public Animation Anim; + public bool IsUsingItem => Anim == Animation.UsingItem || Anim == Animation.UsingItemWhileClimbing; + public bool IsClimbing => Anim == Animation.Climbing || Anim == Animation.UsingItemWhileClimbing; + public Vector2 AimSourceWorldPos { get @@ -280,7 +283,7 @@ namespace Barotrauma public void UpdateUseItem(bool allowMovement, Vector2 handWorldPos) { useItemTimer = 0.5f; - Anim = Animation.UsingConstruction; + StartUsingItem(); if (!allowMovement) { @@ -359,8 +362,13 @@ namespace Barotrauma Vector2 itemPos = aim ? aimPos : holdPos; - var controller = character.SelectedConstruction?.GetComponent(); + var controller = character.SelectedItem?.GetComponent(); bool usingController = controller != null && !controller.AllowAiming; + if (!usingController) + { + controller = character.SelectedSecondaryItem?.GetComponent(); + usingController = controller != null && !controller.AllowAiming; + } bool isClimbing = character.IsClimbing && Math.Abs(character.AnimController.TargetMovement.Y) > 0.01f; float itemAngle; Holdable holdable = item.GetComponent(); @@ -722,5 +730,45 @@ namespace Barotrauma CalculateArmLengths(); } } + + private void StartAnimation(Animation animation) + { + if (animation == Animation.UsingItem) + { + Anim = IsClimbing ? Animation.UsingItemWhileClimbing : Animation.UsingItem; + } + else if (animation == Animation.Climbing) + { + Anim = IsUsingItem ? Animation.UsingItemWhileClimbing : Animation.Climbing; + } + else + { + Anim = animation; + } + } + + private void StopAnimation(Animation animation) + { + if (animation == Animation.UsingItem) + { + Anim = IsClimbing ? Animation.Climbing : Animation.None; + } + else if (animation == Animation.Climbing) + { + Anim = IsUsingItem ? Animation.UsingItem : Animation.None; + } + else + { + Anim = Animation.None; + } + } + + public void StartUsingItem() => StartAnimation(Animation.UsingItem); + + public void StartClimbing() => StartAnimation(Animation.Climbing); + + public void StopUsingItem() => StopAnimation(Animation.UsingItem); + + public void StopClimbing() => StopAnimation(Animation.Climbing); } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/Animation/HumanoidAnimController.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/Animation/HumanoidAnimController.cs index 74f7ad622..e8c70509d 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/Animation/HumanoidAnimController.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/Animation/HumanoidAnimController.cs @@ -237,13 +237,14 @@ namespace Barotrauma public override void UpdateAnim(float deltaTime) { - if (Frozen) return; + if (Frozen) { return; } if (MainLimb == null) { return; } levitatingCollider = !IsHanging; ColliderIndex = Crouching && !swimming ? 1 : 0; - if (character.SelectedConstruction?.GetComponent()?.ControlCharacterPose ?? false || - character.SelectedConstruction?.GetComponent() != null || + if ((character.SelectedItem?.GetComponent()?.ControlCharacterPose ?? false) || + (character.SelectedSecondaryItem?.GetComponent()?.ControlCharacterPose ?? false) || + character.SelectedSecondaryItem?.GetComponent() != null || (ForceSelectAnimationType != AnimationType.Crouch && ForceSelectAnimationType != AnimationType.NotDefined)) { Crouching = false; @@ -354,12 +355,16 @@ namespace Barotrauma { ApplyTestPose(); } - else + else if (Anim != Animation.UsingItem) { - if (Anim != Animation.UsingConstruction) + if (Anim != Animation.UsingItemWhileClimbing) { ResetPullJoints(); } + else + { + ResetPullJoints(l => l.IsLowerBody); + } } if (SimplePhysicsEnabled) @@ -377,49 +382,53 @@ namespace Barotrauma switch (Anim) { case Animation.Climbing: + case Animation.UsingItemWhileClimbing: levitatingCollider = false; UpdateClimbing(); + UpdateUseItemTimer(); break; case Animation.CPR: UpdateCPR(deltaTime); break; - case Animation.UsingConstruction: + case Animation.UsingItem: default: - if (Anim == Animation.UsingConstruction) - { - useItemTimer -= deltaTime; - if (useItemTimer <= 0.0f) Anim = Animation.None; - } - + UpdateUseItemTimer(); swimmingStateLockTimer -= deltaTime; - if (forceStanding || character.AnimController.AnimationTestPose) { swimming = false; } - else + else if (swimming != inWater && swimmingStateLockTimer <= 0.0f) { //0.5 second delay for switching between swimming and walking //prevents rapid switches between swimming/walking if the water level is fluctuating around the minimum swimming depth - if (swimming != inWater && swimmingStateLockTimer <= 0.0f) - { - swimming = inWater; - swimmingStateLockTimer = 0.5f; - } + swimming = inWater; + swimmingStateLockTimer = 0.5f; } - if (swimming) { UpdateSwimming(); } - else + else if (character.SelectedItem == null || !(character.SelectedSecondaryItem?.GetComponent() is { } controller) || + !controller.ControlCharacterPose || !controller.UserInCorrectPosition) { UpdateStanding(); } - break; } + void UpdateUseItemTimer() + { + if (IsUsingItem) + { + useItemTimer -= deltaTime; + if (useItemTimer <= 0.0f) + { + StopUsingItem(); + } + } + } + if (Timing.TotalTime > LockFlippingUntil && TargetDir != dir && !IsStuck) { Flip(); @@ -841,7 +850,9 @@ namespace Barotrauma float targetSpeed = TargetMovement.Length(); if (targetSpeed > 0.1f && !character.IsRemotelyControlled && !Aiming) { - if (Anim != Animation.UsingConstruction && !(character.SelectedConstruction?.GetComponent()?.ControlCharacterPose ?? false)) + if (!IsUsingItem && + !(character.SelectedItem?.GetComponent()?.ControlCharacterPose ?? false) && + !(character.SelectedSecondaryItem?.GetComponent()?.ControlCharacterPose ?? false)) { if (rotation > 20 && rotation < 170) { @@ -1041,12 +1052,17 @@ namespace Barotrauma void UpdateClimbing() { - var ladder = character.SelectedConstruction?.GetComponent(); - if (ladder == null || character.IsIncapacitated) + var ladder = character.SelectedSecondaryItem?.GetComponent(); + if (character.IsIncapacitated) { Anim = Animation.None; return; } + else if (ladder == null) + { + StopClimbing(); + return; + } onGround = false; IgnorePlatforms = true; @@ -1209,15 +1225,21 @@ namespace Barotrauma { RotateHead(head); } + else if (Anim == Animation.UsingItemWhileClimbing && character.SelectedItem is { } selectedItem) + { + Vector2 diff = (selectedItem.WorldPosition - head.WorldPosition) * Dir; + float targetRotation = MathHelper.WrapAngle(MathUtils.VectorToAngle(diff) - MathHelper.PiOver4 * Dir); + head.body.SmoothRotate(targetRotation, force: WalkParams.HeadTorque); + } else { float movementMultiplier = targetMovement.Y < 0 ? 0 : 1; - head.body.SmoothRotate(MathHelper.PiOver4 * movementMultiplier * Dir, WalkParams.HeadTorque); + head.body.SmoothRotate(MathHelper.PiOver4 * movementMultiplier * Dir, force: WalkParams.HeadTorque); } - if (!ladder.Item.Prefab.Triggers.Any()) + if (ladder.Item.Prefab.Triggers.None()) { - character.SelectedConstruction = null; + character.SelectedSecondaryItem = null; return; } @@ -1247,8 +1269,7 @@ namespace Barotrauma if (!isClimbing) { - Anim = Animation.None; - character.SelectedConstruction = null; + character.StopClimbing(); IgnorePlatforms = false; } @@ -1487,7 +1508,7 @@ namespace Barotrauma target.AnimController.ResetPullJoints(); } - if (Anim == Animation.Climbing) + if (IsClimbing) { //cannot drag up ladders if the character is conscious if (target.AllowInput && (GameMain.NetworkMember == null || !GameMain.NetworkMember.IsClient)) diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/Animation/Ragdoll.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/Animation/Ragdoll.cs index bc2005a63..a0149777f 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/Animation/Ragdoll.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/Animation/Ragdoll.cs @@ -922,12 +922,13 @@ namespace Barotrauma { limb.MoveToPos(pos, amount, pullFromCenter); } - - public void ResetPullJoints() + + public void ResetPullJoints(Func condition = null) { for (int i = 0; i < Limbs.Length; i++) { if (Limbs[i] == null) { continue; } + if (condition != null && !condition(Limbs[i])) { continue; } Limbs[i].PullJointEnabled = false; } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/Character.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/Character.cs index 9a57f98a9..d6b95ac15 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/Character.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/Character.cs @@ -813,43 +813,65 @@ namespace Barotrauma get { return AnimController?.Collider?.LinearVelocity.Length() ?? 0.0f; } } - private Item _selectedConstruction; - public Item SelectedConstruction + private Item _selectedItem; + /// + /// The primary selected item. It can be any device that character interacts with. This excludes items like ladders and chairs which are assigned to . + /// + public Item SelectedItem { - get => _selectedConstruction; + get => _selectedItem; set { - var prevSelectedConstruction = _selectedConstruction; - _selectedConstruction = value; + var prevSelectedItem = _selectedItem; + _selectedItem = value; #if CLIENT - HintManager.OnSetSelectedConstruction(this, prevSelectedConstruction, _selectedConstruction); + HintManager.OnSetSelectedItem(this, prevSelectedItem, _selectedItem); if (Controlled == this) { - if (_selectedConstruction == null) + if (_selectedItem == null) { GameMain.GameSession?.CrewManager?.ResetCrewList(); } - else if (_selectedConstruction.GetComponent() == null) + else if (!_selectedItem.IsLadder) { GameMain.GameSession?.CrewManager?.AutoHideCrewList(); } } #endif - if (prevSelectedConstruction == null && _selectedConstruction != null) + if (prevSelectedItem != null && (_selectedItem == null || _selectedItem != prevSelectedItem) && itemSelectedTime > 0) + { + double selectedDuration = Timing.TotalTime - itemSelectedTime; + if (itemSelectedDurations.ContainsKey(prevSelectedItem.Prefab)) + { + itemSelectedDurations[prevSelectedItem.Prefab] += selectedDuration; + } + else + { + itemSelectedDurations.Add(prevSelectedItem.Prefab, selectedDuration); + } + itemSelectedTime = 0; + } + if (_selectedItem != null && (prevSelectedItem == null || prevSelectedItem != _selectedItem)) { itemSelectedTime = Timing.TotalTime; } - else if (prevSelectedConstruction != null && _selectedConstruction == null && itemSelectedTime > 0) - { - if (!itemSelectedDurations.ContainsKey(prevSelectedConstruction.Prefab)) - { - itemSelectedDurations.Add(prevSelectedConstruction.Prefab, 0); - } - itemSelectedDurations[prevSelectedConstruction.Prefab] += Timing.TotalTime - itemSelectedTime; - itemSelectedTime = 0; - } } } + /// + /// The secondary selected item. It's an item other than a device (see ), e.g. a ladder or a chair. + /// + public Item SelectedSecondaryItem { get; set; } + /// + /// Has the characters selected a primary or a secondary item? + /// + public bool HasSelectedAnyItem => SelectedItem != null || SelectedSecondaryItem != null; + /// + /// Is the item either the primary or the secondary selected item? + /// + /// + /// + public bool IsAnySelectedItem(Item item) => item == SelectedItem || item == SelectedSecondaryItem; + public bool HasSelectedAnotherSecondaryItem(Item item) => SelectedSecondaryItem != null && SelectedSecondaryItem != item; public Item FocusedItem { @@ -938,7 +960,7 @@ namespace Barotrauma { get { - return SelectedConstruction == null || SelectedConstruction.GetComponent() != null || (SelectedConstruction.GetComponent()?.AllowAiming ?? false); + return SelectedItem == null || (SelectedItem.GetComponent()?.AllowAiming ?? false); } } @@ -1481,8 +1503,20 @@ namespace Barotrauma public void GiveJobItems(WayPoint spawnPoint = null) { - if (info?.Job == null) { return; } - info.Job.GiveJobItems(this, spawnPoint); + if (info == null) { return; } + if (info.HumanPrefabIds != default) + { + var humanPrefab = NPCSet.Get(info.HumanPrefabIds.NpcSetIdentifier, info.HumanPrefabIds.NpcIdentifier); + if (humanPrefab == null) + { + DebugConsole.ThrowError($"Failed to give job items for the character \"{Name}\" - could not find human prefab with the id \"{info.HumanPrefabIds.NpcIdentifier}\" from \"{info.HumanPrefabIds.NpcSetIdentifier}\"."); + } + else if (humanPrefab.GiveItems(this, Submarine)) + { + return; + } + } + info.Job?.GiveJobItems(this, spawnPoint); } public void GiveIdCardTags(WayPoint spawnPoint, bool createNetworkEvent = false) @@ -1524,10 +1558,17 @@ namespace Barotrauma if (item?.GetComponent() is Wearable wearable && !Inventory.IsInLimbSlot(item, InvSlotType.Any)) { - if (wearable.SkillModifiers.TryGetValue(skillIdentifier, out float skillValue)) + foreach (var allowedSlot in wearable.AllowedSlots) { - skillLevel += skillValue; + if (allowedSlot == InvSlotType.Any) { continue; } + if (!Inventory.IsInLimbSlot(item, allowedSlot)) { continue; } + if (wearable.SkillModifiers.TryGetValue(skillIdentifier, out float skillValue)) + { + skillLevel += skillValue; + break; + } } + } } } @@ -1541,7 +1582,7 @@ namespace Barotrauma public Vector2? OverrideMovement { get; set; } public bool ForceRun { get; set; } - public bool IsClimbing => AnimController.Anim == AnimController.Animation.Climbing; + public bool IsClimbing => AnimController.IsClimbing; public Vector2 GetTargetMovement() { @@ -1771,6 +1812,11 @@ namespace Barotrauma return speed; } + /// + /// Values lower than this seem to cause constantious flipping when the mouse is near the player and the player is running, because the root collider moves after flipping. + /// + private const float cursorFollowMargin = 40; + public void Control(float deltaTime, Camera cam) { ViewTarget = null; @@ -1803,10 +1849,10 @@ namespace Barotrauma } if (!aiControlled && - AnimController.Anim != AnimController.Animation.UsingConstruction && + !AnimController.IsUsingItem && AnimController.Anim != AnimController.Animation.CPR && (GameMain.NetworkMember == null || !GameMain.NetworkMember.IsClient || Controlled == this) && - AnimController.OnGround && !AnimController.InWater) + (AnimController.OnGround || IsClimbing) && !AnimController.InWater) { if (dontFollowCursor) { @@ -1814,13 +1860,11 @@ namespace Barotrauma } else { - // Values lower than this seem to cause constantious flipping when the mouse is near the player and the player is running, because the root collider moves after flipping. - float followMargin = 40; - if (CursorPosition.X < AnimController.Collider.Position.X - followMargin) + if (CursorPosition.X < AnimController.Collider.Position.X - cursorFollowMargin) { AnimController.TargetDir = Direction.Left; } - else if (CursorPosition.X > AnimController.Collider.Position.X + followMargin) + else if (CursorPosition.X > AnimController.Collider.Position.X + cursorFollowMargin) { AnimController.TargetDir = Direction.Right; } @@ -1967,7 +2011,8 @@ namespace Barotrauma } } - if (SelectedConstruction == null || !SelectedConstruction.Prefab.DisableItemUsageWhenSelected) + bool CanUseItemsWhenSelected(Item item) => item == null || !item.Prefab.DisableItemUsageWhenSelected; + if (CanUseItemsWhenSelected(SelectedItem) && CanUseItemsWhenSelected(SelectedSecondaryItem)) { foreach (Item item in HeldItems) { @@ -1998,24 +2043,24 @@ namespace Barotrauma } } - if (SelectedConstruction != null) + if (SelectedItem != null) { - if (IsKeyDown(InputType.Aim) || !SelectedConstruction.RequireAimToSecondaryUse) + if (IsKeyDown(InputType.Aim) || !SelectedItem.RequireAimToSecondaryUse) { - SelectedConstruction.SecondaryUse(deltaTime, this); + SelectedItem.SecondaryUse(deltaTime, this); } - if (IsKeyDown(InputType.Use) && SelectedConstruction != null && !SelectedConstruction.IsShootable) + if (IsKeyDown(InputType.Use) && SelectedItem != null && !SelectedItem.IsShootable) { - if (!SelectedConstruction.RequireAimToUse || IsKeyDown(InputType.Aim)) + if (!SelectedItem.RequireAimToUse || IsKeyDown(InputType.Aim)) { - SelectedConstruction.Use(deltaTime, this); + SelectedItem.Use(deltaTime, this); } } - if (IsKeyDown(InputType.Shoot) && SelectedConstruction != null && SelectedConstruction.IsShootable) + if (IsKeyDown(InputType.Shoot) && SelectedItem != null && SelectedItem.IsShootable) { - if (!SelectedConstruction.RequireAimToUse || IsKeyDown(InputType.Aim)) + if (!SelectedItem.RequireAimToUse || IsKeyDown(InputType.Aim)) { - SelectedConstruction.Use(deltaTime, this); + SelectedItem.Use(deltaTime, this); } } } @@ -2351,15 +2396,15 @@ namespace Barotrauma //wires are interactable if the character has selected an item the wire is connected to, //and it's disconnected from the other end - if (wire.Connections[0]?.Item != null && SelectedConstruction == wire.Connections[0].Item) + if (wire.Connections[0]?.Item != null && SelectedItem == wire.Connections[0].Item) { return wire.Connections[1] == null; } - if (wire.Connections[1]?.Item != null && SelectedConstruction == wire.Connections[1].Item) + if (wire.Connections[1]?.Item != null && SelectedItem == wire.Connections[1].Item) { return wire.Connections[0] == null; } - if (SelectedConstruction?.GetComponent()?.DisconnectedWires.Contains(wire) ?? false) + if (SelectedItem?.GetComponent()?.DisconnectedWires.Contains(wire) ?? false) { return wire.Connections[0] == null && wire.Connections[1] == null; } @@ -2385,7 +2430,7 @@ namespace Barotrauma Pickable pickableComponent = item.GetComponent(); if (pickableComponent != null && pickableComponent.Picker != this && pickableComponent.Picker != null && !pickableComponent.Picker.IsDead) { return false; } - if (SelectedConstruction?.GetComponent()?.TargetItem == item) { return true; } + if (SelectedItem?.GetComponent()?.TargetItem == item) { return true; } //optimization: don't use HeldItems because it allocates memory and this method is executed very frequently var heldItem1 = Inventory?.GetItemInLimbSlot(InvSlotType.RightHand); if (heldItem1?.GetComponent()?.TargetItem == item) { return true; } @@ -2428,27 +2473,43 @@ namespace Barotrauma distanceToItem = Vector2.Distance(rectIntersectionPoint, playerDistanceCheckPosition); } - if (distanceToItem > item.InteractDistance && item.InteractDistance > 0.0f) { return false; } + float interactDistance = item.InteractDistance; + if ((SelectedSecondaryItem != null || item.IsSecondaryItem) && AnimController is HumanoidAnimController c) + { + // Use a distance slightly shorter than the arms length to keep the character in a comfortable pose + float armLength = 0.75f * ConvertUnits.ToDisplayUnits(c.ArmLength); + interactDistance = Math.Min(interactDistance, armLength); + } + if (distanceToItem > interactDistance && item.InteractDistance > 0.0f) { return false; } + + Vector2 itemPosition = item.SimPosition; + if (Submarine == null && item.Submarine != null) + { + //character is outside, item inside + itemPosition += item.Submarine.SimPosition; + } + else if (Submarine != null && item.Submarine == null) + { + //character is inside, item outside + itemPosition -= Submarine.SimPosition; + } + else if (Submarine != item.Submarine) + { + //character and the item are inside different subs + itemPosition += item.Submarine.SimPosition; + itemPosition -= Submarine.SimPosition; + } + + if (SelectedSecondaryItem != null && !item.IsSecondaryItem) + { + if (item.GetComponent() is { } controller && controller.Direction != 0 && controller.Direction != AnimController.Direction) { return false; } + float threshold = ConvertUnits.ToSimUnits(cursorFollowMargin); + if (AnimController.Direction == Direction.Left && SimPosition.X + threshold < itemPosition.X) { return false; } + if (AnimController.Direction == Direction.Right && SimPosition.X - threshold > itemPosition.X) { return false; } + } if (!item.Prefab.InteractThroughWalls && Screen.Selected != GameMain.SubEditorScreen && !insideTrigger) { - Vector2 itemPosition = item.SimPosition; - if (Submarine == null && item.Submarine != null) - { - //character is outside, item inside - itemPosition += item.Submarine.SimPosition; - } - else if (Submarine != null && item.Submarine == null) - { - //character is inside, item outside - itemPosition -= Submarine.SimPosition; - } - else if (Submarine != item.Submarine) - { - //character and the item are inside different subs - itemPosition += item.Submarine.SimPosition; - itemPosition -= Submarine.SimPosition; - } var body = Submarine.CheckVisibility(SimPosition, itemPosition, ignoreLevel: true); if (body != null && body.UserData as Item != item && (body.UserData as ItemComponent)?.Item != item && Submarine.LastPickedFixture?.UserData as Item != item) { @@ -2521,7 +2582,7 @@ namespace Barotrauma if (!CanInteract) { - SelectedConstruction = null; + SelectedItem = SelectedSecondaryItem = null; focusedItem = null; if (!AllowInput) { @@ -2570,8 +2631,8 @@ namespace Barotrauma AnimController.InWater : head.InWater; //climb ladders automatically when pressing up/down inside their trigger area - Ladder currentLadder = SelectedConstruction?.GetComponent(); - if ((SelectedConstruction == null || currentLadder != null) && + Ladder currentLadder = SelectedSecondaryItem?.GetComponent(); + if ((SelectedSecondaryItem == null || currentLadder != null) && !headInWater && Screen.Selected != GameMain.SubEditorScreen) { bool climbInput = IsKeyDown(InputType.Up) || IsKeyDown(InputType.Down); @@ -2613,7 +2674,7 @@ namespace Barotrauma { if (nearbyLadder.Select(this)) { - SelectedConstruction = nearbyLadder.Item; + SelectedSecondaryItem = nearbyLadder.Item; } } } @@ -2657,16 +2718,23 @@ namespace Barotrauma { FocusedCharacter.onCustomInteract(FocusedCharacter, this); } - else if (IsKeyHit(InputType.Deselect) && SelectedConstruction != null && SelectedConstruction.GetComponent() == null) + else if (IsKeyHit(InputType.Deselect) && SelectedItem != null) { - SelectedConstruction = null; + SelectedItem = null; #if CLIENT CharacterHealth.OpenHealthWindow = null; #endif } - else if (IsKeyHit(InputType.Health) && SelectedConstruction != null && SelectedConstruction.GetComponent() == null) + else if (IsKeyHit(InputType.Deselect) && SelectedSecondaryItem != null) { - SelectedConstruction = null; + SelectedSecondaryItem = null; +#if CLIENT + CharacterHealth.OpenHealthWindow = null; +#endif + } + else if (IsKeyHit(InputType.Health) && (SelectedItem != null || SelectedSecondaryItem != null)) + { + SelectedItem = SelectedSecondaryItem = null; } else if (focusedItem != null) { @@ -2901,7 +2969,7 @@ namespace Barotrauma { Stun = Math.Max(5.0f, Stun); AnimController.ResetPullJoints(); - SelectedConstruction = null; + SelectedItem = SelectedSecondaryItem = null; return; } @@ -2958,7 +3026,7 @@ namespace Barotrauma humanAnimController.Crouching = false; } AnimController.ResetPullJoints(); - SelectedConstruction = null; + SelectedItem = SelectedSecondaryItem = null; return; } @@ -2974,9 +3042,13 @@ namespace Barotrauma DoInteractionUpdate(deltaTime, mouseSimPos); } - if (SelectedConstruction != null && !CanInteractWith(SelectedConstruction)) + if (SelectedItem != null && !CanInteractWith(SelectedItem)) { - SelectedConstruction = null; + SelectedItem = null; + } + if (SelectedSecondaryItem != null && !CanInteractWith(SelectedSecondaryItem)) + { + SelectedSecondaryItem = null; } if (!IsDead) { LockHands = false; } @@ -3914,7 +3986,7 @@ namespace Barotrauma CharacterHealth.Stun = newStun; if (newStun > 0.0f) { - SelectedConstruction = null; + SelectedItem = SelectedSecondaryItem = null; } HealthUpdateInterval = 0.0f; } @@ -3930,77 +4002,79 @@ namespace Barotrauma CharacterHealth.ReduceAfflictionOnAllLimbs("damage".ToIdentifier(), eatingRegen * deltaTime); } } - if (!statusEffects.TryGetValue(actionType, out var statusEffectList)) { return; } - foreach (StatusEffect statusEffect in statusEffectList) + if (statusEffects.TryGetValue(actionType, out var statusEffectList)) { - if (statusEffect.type == ActionType.OnDamaged) + foreach (StatusEffect statusEffect in statusEffectList) { - if (!statusEffect.HasRequiredAfflictions(LastDamage)) { continue; } - if (statusEffect.OnlyPlayerTriggered) + if (statusEffect.type == ActionType.OnDamaged) { - if (LastAttacker == null || !LastAttacker.IsPlayer) + if (!statusEffect.HasRequiredAfflictions(LastDamage)) { continue; } + if (statusEffect.OnlyPlayerTriggered) { - continue; + if (LastAttacker == null || !LastAttacker.IsPlayer) + { + continue; + } } } - } - if (statusEffect.HasTargetType(StatusEffect.TargetType.NearbyItems) || - statusEffect.HasTargetType(StatusEffect.TargetType.NearbyCharacters)) - { - targets.Clear(); - targets.AddRange(statusEffect.GetNearbyTargets(WorldPosition, targets)); - statusEffect.Apply(actionType, deltaTime, this, targets); - } - else if (statusEffect.targetLimbs != null) - { - foreach (var limbType in statusEffect.targetLimbs) + if (statusEffect.HasTargetType(StatusEffect.TargetType.NearbyItems) || + statusEffect.HasTargetType(StatusEffect.TargetType.NearbyCharacters)) { - if (statusEffect.HasTargetType(StatusEffect.TargetType.AllLimbs)) + targets.Clear(); + targets.AddRange(statusEffect.GetNearbyTargets(WorldPosition, targets)); + statusEffect.Apply(actionType, deltaTime, this, targets); + } + else if (statusEffect.targetLimbs != null) + { + foreach (var limbType in statusEffect.targetLimbs) { - // Target all matching limbs - foreach (var limb in AnimController.Limbs) + if (statusEffect.HasTargetType(StatusEffect.TargetType.AllLimbs)) { - if (limb.IsSevered) { continue; } - if (limb.type == limbType) + // Target all matching limbs + foreach (var limb in AnimController.Limbs) + { + if (limb.IsSevered) { continue; } + if (limb.type == limbType) + { + statusEffect.sourceBody = limb.body; + statusEffect.Apply(actionType, deltaTime, this, limb); + } + } + } + else if (statusEffect.HasTargetType(StatusEffect.TargetType.Limb)) + { + // Target just the first matching limb + Limb limb = AnimController.GetLimb(limbType); + if (limb != null) + { + statusEffect.sourceBody = limb.body; + statusEffect.Apply(actionType, deltaTime, this, limb); + } + } + else if (statusEffect.HasTargetType(StatusEffect.TargetType.LastLimb)) + { + // Target just the last matching limb + Limb limb = AnimController.Limbs.LastOrDefault(l => l.type == limbType && !l.IsSevered && !l.Hidden); + if (limb != null) { statusEffect.sourceBody = limb.body; statusEffect.Apply(actionType, deltaTime, this, limb); } } } - else if (statusEffect.HasTargetType(StatusEffect.TargetType.Limb)) - { - // Target just the first matching limb - Limb limb = AnimController.GetLimb(limbType); - if (limb != null) - { - statusEffect.sourceBody = limb.body; - statusEffect.Apply(actionType, deltaTime, this, limb); - } - } - else if (statusEffect.HasTargetType(StatusEffect.TargetType.LastLimb)) - { - // Target just the last matching limb - Limb limb = AnimController.Limbs.LastOrDefault(l => l.type == limbType && !l.IsSevered && !l.Hidden); - if (limb != null) - { - statusEffect.sourceBody = limb.body; - statusEffect.Apply(actionType, deltaTime, this, limb); - } - } + } + if (statusEffect.HasTargetType(StatusEffect.TargetType.This) || statusEffect.HasTargetType(StatusEffect.TargetType.Character)) + { + statusEffect.Apply(actionType, deltaTime, this, this); } } - if (statusEffect.HasTargetType(StatusEffect.TargetType.This) || statusEffect.HasTargetType(StatusEffect.TargetType.Character)) + if (actionType != ActionType.OnDamaged && actionType != ActionType.OnSevered) { - statusEffect.Apply(actionType, deltaTime, this, this); - } - } - if (actionType != ActionType.OnDamaged && actionType != ActionType.OnSevered) - { - // OnDamaged is called only for the limb that is hit. - foreach (Limb limb in AnimController.Limbs) - { - limb.ApplyStatusEffects(actionType, deltaTime); + // OnDamaged is called only for the limb that is hit. + foreach (Limb limb in AnimController.Limbs) + { + limb.ApplyStatusEffects(actionType, deltaTime); + } } } //OnActive effects are handled by the afflictions themselves @@ -4075,10 +4149,12 @@ namespace Barotrauma return; } +#if SERVER if (GameMain.NetworkMember is { IsServer: true }) { - GameMain.NetworkMember.CreateEntityEvent(this, new CharacterStatusEventData()); + GameMain.NetworkMember.CreateEntityEvent(this, new CharacterStatusEventData(forceAfflictionData: true)); } +#endif isDead = true; @@ -4153,7 +4229,7 @@ namespace Barotrauma } } - SelectedConstruction = null; + SelectedItem = SelectedSecondaryItem = null; SelectedCharacter = null; AnimController.ResetPullJoints(); @@ -4896,6 +4972,12 @@ namespace Barotrauma /// Compares just the species name and the group, ignores teams. There's a more complex version found in HumanAIController.cs /// public static bool IsFriendly(Character me, Character other) => other.SpeciesName == me.SpeciesName || other.Params.CompareGroup(me.Params.Group); + + public void StopClimbing() + { + AnimController.StopClimbing(); + SelectedSecondaryItem = null; + } } class ActiveTeamChange diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/CharacterEventData.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/CharacterEventData.cs index 731461475..e8b58578b 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/CharacterEventData.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/CharacterEventData.cs @@ -54,6 +54,15 @@ namespace Barotrauma public struct CharacterStatusEventData : IEventData { public EventType EventType => EventType.Status; + +#if SERVER + public bool ForceAfflictionData; + + public CharacterStatusEventData(bool forceAfflictionData) + { + ForceAfflictionData = forceAfflictionData; + } +#endif } public struct TreatmentEventData : IEventData diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/CharacterInfo.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/CharacterInfo.cs index 1a9df1f90..aa44f780e 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/CharacterInfo.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/CharacterInfo.cs @@ -261,6 +261,10 @@ namespace Barotrauma public string Name; + public LocalizedString Title; + + public (Identifier NpcSetIdentifier, Identifier NpcIdentifier) HumanPrefabIds; + public string DisplayName { get @@ -649,15 +653,12 @@ namespace Barotrauma { Name = name; } - else if (!npcIdentifier.IsEmpty && TextManager.Get("npctitle." + npcIdentifier) is { Loaded: true } npcTitle) - { - Name = npcTitle.Value; - } else { Name = GetRandomName(randSync); } - + + TryLoadNameAndTitle(npcIdentifier); SetPersonalityTrait(); Salary = CalculateSalary(); @@ -727,7 +728,7 @@ namespace Barotrauma } // Used for loading the data - public CharacterInfo(XElement infoElement) + public CharacterInfo(XElement infoElement, Identifier npcIdentifier = default) { ID = idCounter; idCounter++; @@ -774,6 +775,8 @@ namespace Barotrauma Head.FacialHairColor = infoElement.GetAttributeColor("facialhaircolor", Color.White); CheckColors(); + TryLoadNameAndTitle(npcIdentifier); + if (string.IsNullOrEmpty(Name)) { var nameElement = CharacterConfigElement.GetChildElement("names"); @@ -794,9 +797,21 @@ namespace Barotrauma ragdollFileName = infoElement.GetAttributeString("ragdoll", string.Empty); if (personalityName != Identifier.Empty) { - PersonalityTrait = NPCPersonalityTrait.Get(GameSettings.CurrentConfig.Language, personalityName); + if (NPCPersonalityTrait.Traits.TryGet(personalityName, out var trait) || + NPCPersonalityTrait.Traits.TryGet(personalityName.Replace(" ".ToIdentifier(), Identifier.Empty), out trait)) + { + PersonalityTrait = trait; + } + else + { + DebugConsole.ThrowError($"Error in CharacterInfo \"{OriginalName}\": could not find a personality trait with the identifier \"{personalityName}\"."); + } } + HumanPrefabIds = ( + element.GetAttributeIdentifier("npcsetid", Identifier.Empty), + element.GetAttributeIdentifier("npcid", Identifier.Empty)); + MissionsCompletedSinceDeath = infoElement.GetAttributeInt("missionscompletedsincedeath", 0); foreach (var subElement in infoElement.Elements()) @@ -838,6 +853,19 @@ namespace Barotrauma LoadHeadAttachments(); } + private void TryLoadNameAndTitle(Identifier npcIdentifier) + { + if (!npcIdentifier.IsEmpty) + { + Title = TextManager.Get("npctitle." + npcIdentifier); + string nameTag = "charactername." + npcIdentifier; + if (TextManager.ContainsTag(nameTag)) + { + Name = TextManager.Get(nameTag).Value; + } + } + } + private List hairs; public IReadOnlyList Hairs => hairs; private List beards; @@ -1292,9 +1320,16 @@ namespace Barotrauma new XAttribute("facialhaircolor", XMLExtensions.ColorToString(Head.FacialHairColor)), new XAttribute("startitemsgiven", StartItemsGiven), new XAttribute("ragdoll", ragdollFileName), - new XAttribute("personality", PersonalityTrait?.Name.Value ?? "")); + new XAttribute("personality", PersonalityTrait?.Identifier ?? Identifier.Empty)); // TODO: animations? + if (HumanPrefabIds != default) + { + charElement.Add( + new XAttribute("npcsetid", HumanPrefabIds.NpcSetIdentifier), + new XAttribute("npcid", HumanPrefabIds.NpcIdentifier)); + } + charElement.Add(new XAttribute("missionscompletedsincedeath", MissionsCompletedSinceDeath)); if (Character != null) @@ -1323,11 +1358,8 @@ namespace Barotrauma } } - - charElement.Add(savedStatElement); - - parentElement.Add(charElement); + parentElement?.Add(charElement); return charElement; } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/CharacterNetworking.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/CharacterNetworking.cs index 4f0068328..29250acfd 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/CharacterNetworking.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/CharacterNetworking.cs @@ -10,26 +10,27 @@ namespace Barotrauma public readonly Direction Direction; public readonly Character SelectedCharacter; - public readonly Item SelectedItem; + public readonly Item SelectedItem, SelectedSecondaryItem; public readonly AnimController.Animation Animation; - public CharacterStateInfo(Vector2 pos, float? rotation, Vector2 velocity, float? angularVelocity, float time, Direction dir, Character selectedCharacter, Item selectedItem, AnimController.Animation animation = AnimController.Animation.None) - : this(pos, rotation, velocity, angularVelocity, 0, time, dir, selectedCharacter, selectedItem, animation) + public CharacterStateInfo(Vector2 pos, float? rotation, Vector2 velocity, float? angularVelocity, float time, Direction dir, Character selectedCharacter, Item selectedItem, Item selectedSecondaryItem, AnimController.Animation animation = AnimController.Animation.None) + : this(pos, rotation, velocity, angularVelocity, 0, time, dir, selectedCharacter, selectedItem, selectedSecondaryItem, animation) { } - public CharacterStateInfo(Vector2 pos, float? rotation, UInt16 ID, Direction dir, Character selectedCharacter, Item selectedItem, AnimController.Animation animation = AnimController.Animation.None) - : this(pos, rotation, Vector2.Zero, 0.0f, ID, 0.0f, dir, selectedCharacter, selectedItem, animation) + public CharacterStateInfo(Vector2 pos, float? rotation, UInt16 ID, Direction dir, Character selectedCharacter, Item selectedItem, Item selectedSecondaryItem, AnimController.Animation animation = AnimController.Animation.None) + : this(pos, rotation, Vector2.Zero, 0.0f, ID, 0.0f, dir, selectedCharacter, selectedItem, selectedSecondaryItem, animation) { } - protected CharacterStateInfo(Vector2 pos, float? rotation, Vector2 velocity, float? angularVelocity, UInt16 ID, float time, Direction dir, Character selectedCharacter, Item selectedItem, AnimController.Animation animation = AnimController.Animation.None) + protected CharacterStateInfo(Vector2 pos, float? rotation, Vector2 velocity, float? angularVelocity, UInt16 ID, float time, Direction dir, Character selectedCharacter, Item selectedItem, Item selectedSecondaryItem, AnimController.Animation animation = AnimController.Animation.None) : base(pos, rotation, velocity, angularVelocity, ID, time) { Direction = dir; SelectedCharacter = selectedCharacter; SelectedItem = selectedItem; + SelectedSecondaryItem = selectedSecondaryItem; Animation = animation; } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/CorpsePrefab.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/CorpsePrefab.cs index 2b9602b33..ae592923a 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/CorpsePrefab.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/CorpsePrefab.cs @@ -46,7 +46,7 @@ namespace Barotrauma [Serialize(0, IsPropertySaveable.No)] public int MaxMoney { get; private set; } - public CorpsePrefab(ContentXElement element, CorpsesFile file) : base(element, file) { } + public CorpsePrefab(ContentXElement element, CorpsesFile file) : base(element, file, npcSetIdentifier: Identifier.Empty) { } public static CorpsePrefab Random(Rand.RandSync sync = Rand.RandSync.Unsynced) => Prefabs.GetRandom(sync); } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/Health/CharacterHealth.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/Health/CharacterHealth.cs index 2381b31cc..c159dfbe5 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/Health/CharacterHealth.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/Health/CharacterHealth.cs @@ -55,13 +55,27 @@ namespace Barotrauma if (vitalityMultipliers != null) { float multiplier = subElement.GetAttributeFloat("multiplier", 1.0f); - vitalityMultipliers.ForEach(i => VitalityMultipliers.Add(i, multiplier)); + foreach (var vitalityMultiplier in vitalityMultipliers) + { + VitalityMultipliers.Add(vitalityMultiplier, multiplier); + if (AfflictionPrefab.Prefabs.None(p => p.Identifier == vitalityMultiplier)) + { + DebugConsole.AddWarning($"Potentially incorrectly defined vitality multiplier in \"{characterHealth.Character.Name}\". Could not find any afflictions with the identifier \"{vitalityMultiplier}\". Did you mean to define the afflictions by type instead?"); + } + } } var vitalityTypeMultipliers = subElement.GetAttributeIdentifierArray("type", null) ?? subElement.GetAttributeIdentifierArray("types", null); if (vitalityTypeMultipliers != null) { float multiplier = subElement.GetAttributeFloat("multiplier", 1.0f); - vitalityTypeMultipliers.ForEach(i => VitalityTypeMultipliers.Add(i, multiplier)); + foreach (var vitalityTypeMultiplier in vitalityTypeMultipliers) + { + VitalityTypeMultipliers.Add(vitalityTypeMultiplier, multiplier); + if (AfflictionPrefab.Prefabs.None(p => p.AfflictionType == vitalityTypeMultiplier)) + { + DebugConsole.AddWarning($"Potentially incorrectly defined vitality multiplier in \"{characterHealth.Character.Name}\". Could not find any afflictions of the type \"{vitalityTypeMultiplier}\". Did you mean to define the afflictions by identifier instead?"); + } + } } if (vitalityMultipliers == null && VitalityTypeMultipliers == null) { diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/HumanPrefab.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/HumanPrefab.cs index 7e8a539ff..1e041438a 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/HumanPrefab.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/HumanPrefab.cs @@ -10,7 +10,7 @@ namespace Barotrauma class HumanPrefab : PrefabWithUintIdentifier { [Serialize("any", IsPropertySaveable.No)] - public string Job { get; protected set; } + public Identifier Job { get; protected set; } [Serialize(1f, IsPropertySaveable.No)] public float Commonness { get; protected set; } @@ -82,17 +82,19 @@ namespace Barotrauma public XElement Element { get; protected set; } - public readonly Dictionary ItemSets = new Dictionary(); - public readonly Dictionary CustomNPCSets = new Dictionary(); + public readonly List<(XElement element, float commonness)> ItemSets = new List<(XElement element, float commonness)>(); + public readonly List<(XElement element, float commonness)> CustomCharacterInfos = new List<(XElement element, float commonness)>(); - public HumanPrefab(ContentXElement element, ContentFile file) : base(file, element.GetAttributeIdentifier("identifier", "")) + private readonly Identifier npcSetIdentifier; + + public HumanPrefab(ContentXElement element, ContentFile file, Identifier npcSetIdentifier) : base(file, element.GetAttributeIdentifier("identifier", "")) { SerializableProperty.DeserializeProperties(this, element); - Job = Job.ToLowerInvariant(); Element = element; - element.GetChildElements("itemset").ForEach(e => ItemSets.Add(e, e.GetAttributeFloat("commonness", 1))); - element.GetChildElements("character").ForEach(e => CustomNPCSets.Add(e, e.GetAttributeFloat("commonness", 1))); + element.GetChildElements("itemset").ForEach(e => ItemSets.Add((e, e.GetAttributeFloat("commonness", 1)))); + element.GetChildElements("character").ForEach(e => CustomCharacterInfos.Add((e, e.GetAttributeFloat("commonness", 1)))); PreferredOutpostModuleTypes = element.GetAttributeIdentifierArray("preferredoutpostmoduletypes", Array.Empty()); + this.npcSetIdentifier = npcSetIdentifier; } public IEnumerable GetModuleFlags() @@ -107,7 +109,7 @@ namespace Barotrauma public JobPrefab GetJobPrefab(Rand.RandSync randSync = Rand.RandSync.Unsynced, Func predicate = null) { - return Job != null && Job != "any" ? JobPrefab.Get(Job) : JobPrefab.Random(randSync, predicate); + return !Job.IsEmpty && Job != "any" ? JobPrefab.Get(Job) : JobPrefab.Random(randSync, predicate); } public void InitializeCharacter(Character npc, ISpatialEntity positionToStayIn = null) @@ -146,23 +148,43 @@ namespace Barotrauma } } - public void GiveItems(Character character, Submarine submarine, Rand.RandSync randSync = Rand.RandSync.Unsynced, bool createNetworkEvents = true) + public bool GiveItems(Character character, Submarine submarine, Rand.RandSync randSync = Rand.RandSync.Unsynced, bool createNetworkEvents = true) { - if (ItemSets == null || !ItemSets.Any()) { return; } - var spawnItems = ToolBox.SelectWeightedRandom(ItemSets.Keys.ToList(), ItemSets.Values.ToList(), randSync); + if (ItemSets == null || !ItemSets.Any()) { return false; } + var spawnItems = ToolBox.SelectWeightedRandom(ItemSets, it => it.commonness, randSync).element; if (spawnItems != null) { foreach (XElement itemElement in spawnItems.GetChildElements("item")) { - InitializeItem(character, itemElement, submarine, this, createNetworkEvents: createNetworkEvents); + int amount = itemElement.GetAttributeInt("amount", 1); + for (int i = 0; i < amount; i++) + { + InitializeItem(character, itemElement, submarine, this, createNetworkEvents: createNetworkEvents); + } } } + return true; } - public CharacterInfo GetCharacterInfo(Rand.RandSync randSync = Rand.RandSync.Unsynced) + /// + /// Creates a character info from the human prefab. If there are custom character infos defined, those are used, otherwise a randomized info is generated. + /// + /// + /// + public CharacterInfo CreateCharacterInfo(Rand.RandSync randSync = Rand.RandSync.Unsynced) { - var characterElement = ToolBox.SelectWeightedRandom(CustomNPCSets.Keys.ToList(), CustomNPCSets.Values.ToList(), randSync); - return characterElement != null ? new CharacterInfo(characterElement) : null; + var characterElement = ToolBox.SelectWeightedRandom(CustomCharacterInfos, info => info.commonness, randSync).element; + CharacterInfo characterInfo; + if (characterElement == null) + { + characterInfo= new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobOrJobPrefab: GetJobPrefab(randSync), npcIdentifier: Identifier); + } + else + { + characterInfo = new CharacterInfo(characterElement, Identifier); + } + characterInfo.HumanPrefabIds = (npcSetIdentifier, Identifier); + return characterInfo; } public static void InitializeItem(Character character, XElement itemElement, Submarine submarine, HumanPrefab humanPrefab, Item parentItem = null, bool createNetworkEvents = true) @@ -229,7 +251,11 @@ namespace Barotrauma parentItem?.Combine(item, user: null); foreach (XElement childItemElement in itemElement.Elements()) { - InitializeItem(character, childItemElement, submarine, humanPrefab, item, createNetworkEvents); + int amount = childItemElement.GetAttributeInt("amount", 1); + for (int i = 0; i < amount; i++) + { + InitializeItem(character, childItemElement, submarine, humanPrefab, item, createNetworkEvents); + } } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/Jobs/Job.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/Jobs/Job.cs index 615a33350..e1748b990 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/Jobs/Job.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/Jobs/Job.cs @@ -19,7 +19,7 @@ namespace Barotrauma public int Variant; - public Skill PrimarySkill { get; } + public Skill PrimarySkill { get; private set; } public Job(JobPrefab jobPrefab) : this(jobPrefab, randSync: Rand.RandSync.Unsynced, variant: 0) { } @@ -102,9 +102,14 @@ namespace Barotrauma public void OverrideSkills(Dictionary newSkills) { skills.Clear(); - foreach (var newSkill in newSkills) + foreach (var newSkillInfo in newSkills) { - skills.Add(newSkill.Key, new Skill(newSkill.Key, newSkill.Value)); + var newSkill = new Skill(newSkillInfo.Key, newSkillInfo.Value); + if (PrimarySkill != null && newSkill.Identifier == PrimarySkill.Identifier) + { + PrimarySkill = newSkill; + } + skills.Add(newSkillInfo.Key, newSkill); } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/Jobs/JobPrefab.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/Jobs/JobPrefab.cs index 8153bca07..b0df4f80d 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/Jobs/JobPrefab.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/Jobs/JobPrefab.cs @@ -79,7 +79,7 @@ namespace Barotrauma /// public static IReadOnlyDictionary ItemRepairPriorities => _itemRepairPriorities; - public static JobPrefab Get(string identifier) + public static JobPrefab Get(Identifier identifier) { if (Prefabs.ContainsKey(identifier)) { diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/Limb.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/Limb.cs index e958f391f..847ef13d1 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/Limb.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/Limb.cs @@ -303,6 +303,17 @@ namespace Barotrauma public Vector2 DebugTargetPos; public Vector2 DebugRefPos; + public bool IsLowerBody => + type == LimbType.LeftLeg || + type == LimbType.RightLeg || + type == LimbType.LeftFoot || + type == LimbType.RightFoot || + type == LimbType.Tail || + type == LimbType.Legs || + type == LimbType.RightThigh || + type == LimbType.LeftThigh || + type == LimbType.Waist; + public bool IsSevered { get { return isSevered; } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/NPCPersonalityTrait.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/NPCPersonalityTrait.cs index 292b58fc6..cc14d0fc6 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/NPCPersonalityTrait.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/NPCPersonalityTrait.cs @@ -5,9 +5,11 @@ using System.Xml.Linq; namespace Barotrauma { - class NPCPersonalityTrait + class NPCPersonalityTrait : PrefabWithUintIdentifier { - public readonly Identifier Name; + public readonly static PrefabCollection Traits = new PrefabCollection(); + + public readonly LocalizedString DisplayName; public readonly List AllowedDialogTags; @@ -17,43 +19,29 @@ namespace Barotrauma get { return commonness; } } - public static IEnumerable GetAll(LanguageIdentifier language) + public NPCPersonalityTrait(XElement element, NPCPersonalityTraitsFile file) + : base(file, element.GetAttributeIdentifier("identifier", element.GetAttributeIdentifier("name", Identifier.Empty))) { - if (language != TextManager.DefaultLanguage && !NPCConversationCollection.Collections.ContainsKey(language)) + string name = element.GetAttributeString("name", null); + if (name == null) { - DebugConsole.AddWarning($"Could not find NPC personality traits for the language \"{language}\". Using \"{TextManager.DefaultLanguage}\" instead.."); - language = TextManager.DefaultLanguage; + DisplayName = TextManager.Get("personalitytrait." + Identifier) + .Fallback(Identifier.ToString()); } - return NPCConversationCollection.Collections[language] - .SelectMany(cc => cc.PersonalityTraits.Values); - } - - public static NPCPersonalityTrait Get(LanguageIdentifier language, Identifier traitName) - { - if (language != TextManager.DefaultLanguage && !NPCConversationCollection.Collections.ContainsKey(language)) + else { - DebugConsole.AddWarning($"Could not find NPC personality traits for the language \"{language}\". Using \"{TextManager.DefaultLanguage}\" instead.."); - language = TextManager.DefaultLanguage; + DisplayName = name; } - return NPCConversationCollection.Collections[language] - .FirstOrDefault(cc => cc.PersonalityTraits.ContainsKey(traitName)) - .PersonalityTraits[traitName]; - } - - public NPCPersonalityTrait(XElement element) - { - Name = element.GetAttributeIdentifier("name", ""); AllowedDialogTags = new List(element.GetAttributeStringArray("alloweddialogtags", Array.Empty())); commonness = element.GetAttributeFloat("commonness", 1.0f); } public static NPCPersonalityTrait GetRandom(string seed) { - #warning TODO: implement NPCPersonality content type and revise this for determinism var rand = new MTRandom(ToolBox.StringToInt(seed)); - var list = GetAll(GameSettings.CurrentConfig.Language); - return ToolBox.SelectWeightedRandom(list, t => t.commonness, rand); + return ToolBox.SelectWeightedRandom(Traits.OrderBy(t => t.UintIdentifier), t => t.commonness, rand); } + public override void Dispose() { } } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/Talents/Abilities/CustomAbilities/CharacterAbilityTandemFire.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/Talents/Abilities/CustomAbilities/CharacterAbilityTandemFire.cs index 5bcac5e83..a534df7f5 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/Talents/Abilities/CustomAbilities/CharacterAbilityTandemFire.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/Talents/Abilities/CustomAbilities/CharacterAbilityTandemFire.cs @@ -17,7 +17,7 @@ namespace Barotrauma.Abilities protected override void ApplyEffect() { - if (Character.SelectedConstruction == null || !Character.SelectedConstruction.HasTag(tag)) { return; } + if (!SelectedItemHasTag(Character)) { return; } Character closestCharacter = null; float closestDistance = squaredMaxDistance; @@ -31,13 +31,17 @@ namespace Barotrauma.Abilities } } - if (closestCharacter?.SelectedConstruction == null || !closestCharacter.SelectedConstruction.HasTag(tag)) { return; } + if (!SelectedItemHasTag(closestCharacter)) { return; } if (closestDistance < squaredMaxDistance) { ApplyEffectSpecific(Character); ApplyEffectSpecific(closestCharacter); } + + bool SelectedItemHasTag(Character character) => + (character.SelectedItem != null && character.SelectedItem.HasTag(tag)) || + (character.SelectedSecondaryItem != null && character.SelectedSecondaryItem.HasTag(tag)); } } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/ContentManagement/ContentFile/NPCPersonalityTraitsFile.cs b/Barotrauma/BarotraumaShared/SharedSource/ContentManagement/ContentFile/NPCPersonalityTraitsFile.cs new file mode 100644 index 000000000..98ea05e9f --- /dev/null +++ b/Barotrauma/BarotraumaShared/SharedSource/ContentManagement/ContentFile/NPCPersonalityTraitsFile.cs @@ -0,0 +1,12 @@ +namespace Barotrauma +{ + sealed class NPCPersonalityTraitsFile : GenericPrefabFile + { + public NPCPersonalityTraitsFile(ContentPackage contentPackage, ContentPath path) : base(contentPackage, path) { } + + protected override bool MatchesSingular(Identifier identifier) => identifier == "personalitytrait"; + protected override bool MatchesPlural(Identifier identifier) => identifier == "personalitytraits"; + protected override PrefabCollection Prefabs => NPCPersonalityTrait.Traits; + protected override NPCPersonalityTrait CreatePrefab(ContentXElement element) => new NPCPersonalityTrait(element, this); + } +} diff --git a/Barotrauma/BarotraumaShared/SharedSource/CoroutineManager.cs b/Barotrauma/BarotraumaShared/SharedSource/CoroutineManager.cs index bdde120e8..8b3842223 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/CoroutineManager.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/CoroutineManager.cs @@ -84,7 +84,9 @@ namespace Barotrauma { static readonly List Coroutines = new List(); - public static float UnscaledDeltaTime, DeltaTime; + public static float DeltaTime { get; private set; } + + public static bool Paused { get; private set; } public static CoroutineHandle StartCoroutine(IEnumerable func, string name = "", bool useSeparateThread = false) { @@ -191,7 +193,7 @@ namespace Barotrauma if (current != null) { if (current.EndsCoroutine(handle) || handle.AbortRequested) { return true; } - if (!current.CheckFinished(UnscaledDeltaTime)) { return false; } + if (!current.CheckFinished(DeltaTime)) { return false; } } if (!handle.Coroutine.MoveNext()) { return true; } return false; @@ -204,7 +206,7 @@ namespace Barotrauma while (!handle.AbortRequested) { if (PerformCoroutineStep(handle)) { return; } - Thread.Sleep((int)(UnscaledDeltaTime * 1000)); + Thread.Sleep((int)(DeltaTime * 1000)); } } catch (ThreadAbortException) @@ -232,7 +234,7 @@ namespace Barotrauma { if (handle.Thread.ThreadState.HasFlag(ThreadState.Stopped)) { - if (handle.Exception!=null || handle.Coroutine.Current == CoroutineStatus.Failure) + if (handle.Exception != null || handle.Coroutine.Current == CoroutineStatus.Failure) { DebugConsole.ThrowError("Coroutine \"" + handle.Name + "\" has failed"); } @@ -254,9 +256,9 @@ namespace Barotrauma #endif } // Updating just means stepping through all the coroutines - public static void Update(float unscaledDeltaTime, float deltaTime) + public static void Update(bool paused, float deltaTime) { - UnscaledDeltaTime = unscaledDeltaTime; + Paused = paused; DeltaTime = deltaTime; List coroutineList; @@ -282,8 +284,8 @@ namespace Barotrauma { public readonly float TotalTime; - float timer; - bool ignorePause; + private float timer; + private readonly bool ignorePause; public WaitForSeconds(float time, bool ignorePause = true) { @@ -295,7 +297,7 @@ namespace Barotrauma public override bool CheckFinished(float deltaTime) { #if !SERVER - if (ignorePause || !GUI.PauseMenuOpen) + if (ignorePause || !CoroutineManager.Paused) { timer -= deltaTime; } diff --git a/Barotrauma/BarotraumaShared/SharedSource/DebugConsole.cs b/Barotrauma/BarotraumaShared/SharedSource/DebugConsole.cs index 0b4ac4c1d..a1954e4a8 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/DebugConsole.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/DebugConsole.cs @@ -798,7 +798,55 @@ namespace Barotrauma eventPrefabs.Select(prefab => prefab.Identifier).Distinct().Select(id => id.Value).ToArray() }; })); - + + commands.Add(new Command("unlockmission", "unlockmission [identifier/tag]: Unlocks a mission in a random adjacent level.", (string[] args) => + { + if (!(GameMain.GameSession?.GameMode is CampaignMode campaign)) + { + ThrowError("The unlockmission command is only usable in the campaign mode."); + return; + } + if (args.Length == 0) + { + ThrowError("Please enter the identifier or a tag of the mission you want to unlock."); + return; + } + var currentLocation = campaign.Map.CurrentLocation; + if (MissionPrefab.Prefabs.Any(p => p.Identifier == args[0])) + { + currentLocation.UnlockMissionByIdentifier(args[0].ToIdentifier()); + } + else + { + currentLocation.UnlockMissionByTag(args[0].ToIdentifier()); + } + if (campaign is MultiPlayerCampaign mpCampaign) + { + mpCampaign.IncrementLastUpdateIdForFlag(MultiPlayerCampaign.NetFlags.MapAndMissions); + } + }, isCheat: true, getValidArgs: () => + { + return new[] + { + MissionPrefab.Prefabs.Select(p => p.Identifier.ToString()).ToArray() + }; + })); + + commands.Add(new Command("setcampaignmetadata", "setcampaignmetadata [identifier] [value]: Sets the specified campaign metadata value.", (string[] args) => + { + if (!(GameMain.GameSession?.GameMode is CampaignMode campaign)) + { + ThrowError("The setcampaignmetadata command is only usable in the campaign mode."); + return; + } + if (args.Length < 2) + { + ThrowError("Please specify an identifier and a value."); + return; + } + SetDataAction.PerformOperation(campaign.CampaignMetadata, args[0].ToIdentifier(), args[1], SetDataAction.OperationType.Set); + }, isCheat: true)); + commands.Add(new Command("setskill", "setskill [all/identifier] [max/level] [character]: Set your skill level.", (string[] args) => { if (args.Length < 2) @@ -2532,9 +2580,12 @@ namespace Barotrauma #if CLIENT GameMain.DebugDraw = false; GameMain.LightManager.LightingEnabled = true; + Character.DebugDrawInteract = false; #endif Hull.EditWater = false; Hull.EditFire = false; + EnemyAIController.DisableEnemyAI = false; + HumanAIController.DisableCrewAI = false; } } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/ConversationAction.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/ConversationAction.cs index 27748f54d..a438db9a5 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/ConversationAction.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/ConversationAction.cs @@ -59,7 +59,11 @@ namespace Barotrauma [Serialize(false, IsPropertySaveable.Yes)] public bool ContinueConversation { get; set; } - private Character speaker; + public Character speaker + { + get; + private set; + } private AIObjective prevIdleObjective, prevGotoObjective; @@ -120,7 +124,7 @@ namespace Barotrauma #else foreach (Client c in GameMain.Server.ConnectedClients) { - if (c.InGame && c.Character != null) { ServerWrite(speaker, c); } + if (c.InGame && c.Character != null) { ServerWrite(speaker, c, interrupt); } } #endif ResetSpeaker(); @@ -331,9 +335,11 @@ namespace Barotrauma if (!TargetTag.IsEmpty) { targets = ParentEvent.GetTargets(TargetTag).Where(e => IsValidTarget(e)); - if (!targets.Any() || IsBlockedByAnotherConversation(targets)) { return; } + if (!targets.Any() || IsBlockedByAnotherConversation(targets, BlockOtherConversationsDuration)) { return; } } + if (targetCharacter != null && IsBlockedByAnotherConversation(targetCharacter.ToEnumerable(), 0.1f)) { return; } + if (speaker?.AIController is HumanAIController humanAI) { prevIdleObjective = humanAI.ObjectiveManager.GetObjective(); diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/SpawnAction.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/SpawnAction.cs index 70f6a7b61..5250521eb 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/SpawnAction.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/SpawnAction.cs @@ -118,7 +118,7 @@ namespace Barotrauma ISpatialEntity spawnPos = GetSpawnPos(); if (spawnPos != null) { - Entity.Spawner.AddCharacterToSpawnQueue(CharacterPrefab.HumanSpeciesName, OffsetSpawnPos(spawnPos.WorldPosition, 100.0f), humanPrefab.GetCharacterInfo(), onSpawn: newCharacter => + Entity.Spawner.AddCharacterToSpawnQueue(CharacterPrefab.HumanSpeciesName, OffsetSpawnPos(spawnPos.WorldPosition, 100.0f), humanPrefab.CreateCharacterInfo(), onSpawn: newCharacter => { if (newCharacter == null) { return; } newCharacter.HumanPrefab = humanPrefab; diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/TriggerAction.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/TriggerAction.cs index 09a689776..385dc13ae 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/TriggerAction.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/TriggerAction.cs @@ -157,8 +157,9 @@ namespace Barotrauma npcsOrItems.Add(item); } item.CampaignInteractionType = CampaignMode.InteractionType.Examine; - if (player.SelectedConstruction == item || - player.Inventory != null && player.Inventory.Contains(item) || + if (player.SelectedItem == item || + player.SelectedSecondaryItem == item || + (player.Inventory != null && player.Inventory.Contains(item)) || (player.FocusedItem == item && player.IsKeyHit(InputType.Use))) { Trigger(e1, e2); diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/EventManager.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/EventManager.cs index 63dd365ef..3fe4f0725 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Events/EventManager.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/EventManager.cs @@ -71,6 +71,10 @@ namespace Barotrauma private readonly List activeEvents = new List(); + private readonly HashSet finishedEvents = new HashSet(); + private readonly HashSet nonRepeatableEvents = new HashSet(); + + #if DEBUG && SERVER private DateTime nextIntensityLogTime; #endif @@ -169,54 +173,49 @@ namespace Barotrauma CreateEvents(additiveSet); } - if (level?.LevelData?.Type == LevelData.LevelType.Outpost) + if (level?.LevelData != null) { - //if the outpost is connected to a locked connection, create an event to unlock it - if (level.StartLocation?.Connections.Any(c => c.Locked && level.StartLocation.MapPosition.X < c.OtherLocation(level.StartLocation).MapPosition.X) ?? false) + if (level.LevelData.Type == LevelData.LevelType.Outpost) { - var unlockPathPrefabs = EventPrefab.Prefabs.Where(e => e.UnlockPathEvent); - var unlockPathPrefabsForBiome = unlockPathPrefabs.Where(e => - e.BiomeIdentifier.IsEmpty || - e.BiomeIdentifier == level.LevelData.Biome.Identifier); + //if the outpost is connected to a locked connection, create an event to unlock it + if (level.StartLocation?.Connections.Any(c => c.Locked && level.StartLocation.MapPosition.X < c.OtherLocation(level.StartLocation).MapPosition.X) ?? false) + { + var unlockPathPrefabs = EventPrefab.Prefabs.Where(e => e.UnlockPathEvent); + var unlockPathPrefabsForBiome = unlockPathPrefabs.Where(e => + e.BiomeIdentifier.IsEmpty || + e.BiomeIdentifier == level.LevelData.Biome.Identifier); - var unlockPathEventPrefab = unlockPathPrefabsForBiome.Any() ? - ToolBox.SelectWeightedRandom(unlockPathPrefabsForBiome, b => b.Commonness, rand) : - ToolBox.SelectWeightedRandom(unlockPathPrefabs, b => b.Commonness, rand); - if (unlockPathEventPrefab != null) - { - var newEvent = unlockPathEventPrefab.CreateInstance(); - newEvent.Init(); - ActiveEvents.Add(newEvent); - } - else - { - //if no event that unlocks the path can be found, unlock it automatically - level.StartLocation.Connections.ForEach(c => c.Locked = false); - } - } - - level.LevelData.EventHistory.AddRange(selectedEvents.Values.SelectMany(v => v).Select(e => e.Prefab).Where(e => !level.LevelData.EventHistory.Contains(e))); - if (level.LevelData.EventHistory.Count > MaxEventHistory) - { - level.LevelData.EventHistory.RemoveRange(0, level.LevelData.EventHistory.Count - MaxEventHistory); - } - AddChildEvents(initialEventSet); - void AddChildEvents(EventSet eventSet) - { - if (eventSet == null) { return; } - if (eventSet.OncePerOutpost) - { - foreach (EventPrefab ep in eventSet.EventPrefabs.SelectMany(e => e.EventPrefabs)) + var unlockPathEventPrefab = unlockPathPrefabsForBiome.Any() ? + ToolBox.SelectWeightedRandom(unlockPathPrefabsForBiome, b => b.Commonness, rand) : + ToolBox.SelectWeightedRandom(unlockPathPrefabs, b => b.Commonness, rand); + if (unlockPathEventPrefab != null) { - if (!level.LevelData.NonRepeatableEvents.Contains(ep)) - { - level.LevelData.NonRepeatableEvents.Add(ep); - } + var newEvent = unlockPathEventPrefab.CreateInstance(); + newEvent.Init(); + ActiveEvents.Add(newEvent); + } + else + { + //if no event that unlocks the path can be found, unlock it automatically + level.StartLocation.Connections.ForEach(c => c.Locked = false); } } - foreach (EventSet childSet in eventSet.ChildSets) + + AddChildEvents(initialEventSet); + void AddChildEvents(EventSet eventSet) { - AddChildEvents(childSet); + if (eventSet == null) { return; } + if (eventSet.OncePerOutpost) + { + foreach (EventPrefab ep in eventSet.EventPrefabs.SelectMany(e => e.EventPrefabs)) + { + nonRepeatableEvents.Add(ep); + } + } + foreach (EventSet childSet in eventSet.ChildSets) + { + AddChildEvents(childSet); + } } } } @@ -350,13 +349,33 @@ namespace Barotrauma selectedEvents.Clear(); activeEvents.Clear(); QueuedEvents.Clear(); + finishedEvents.Clear(); + nonRepeatableEvents.Clear(); preloadedSprites.ForEach(s => s.Remove()); preloadedSprites.Clear(); + pathFinder = null; } + /// + /// Registers the exhaustible events in the level as exhausted, and adds the current events to the event history + /// + public void RegisterEventHistory() + { + level.LevelData.EventsExhausted = true; + if (level?.LevelData != null && level.LevelData.Type == LevelData.LevelType.Outpost) + { + level.LevelData.EventHistory.AddRange(selectedEvents.Values.SelectMany(v => v).Select(e => e.Prefab).Where(e => !level.LevelData.EventHistory.Contains(e))); + if (level.LevelData.EventHistory.Count > MaxEventHistory) + { + level.LevelData.EventHistory.RemoveRange(0, level.LevelData.EventHistory.Count - MaxEventHistory); + } + level.LevelData.NonRepeatableEvents.AddRange(nonRepeatableEvents.Where(e => !level.LevelData.NonRepeatableEvents.Contains(e))); + } + } + public void SkipEventCooldown() { eventCoolDown = 0.0f; @@ -375,6 +394,8 @@ namespace Barotrauma selectedEvents.Remove(eventSet); if (level == null) { return; } if (level.LevelData.HasHuntingGrounds && eventSet.DisableInHuntingGrounds) { return; } + if (eventSet.Exhaustible && level.LevelData.EventsExhausted) { return; } + DebugConsole.NewMessage($"Loading event set {eventSet.Identifier}", Color.LightBlue, debugOnly: true); int applyCount = 1; @@ -427,7 +448,8 @@ namespace Barotrauma if (suitablePrefabSubsets.Any()) { var unusedEvents = suitablePrefabSubsets.ToList(); - for (int j = 0; j < eventSet.EventCount; j++) + int eventCount = eventSet.GetEventCount(level); + for (int j = 0; j < eventCount; j++) { if (unusedEvents.All(e => e.EventPrefabs.All(p => CalculateCommonness(p, e.Commonness) <= 0.0f))) { break; } EventSet.SubEventPrefab subEventPrefab = ToolBox.SelectWeightedRandom(unusedEvents, e => e.EventPrefabs.Max(p => CalculateCommonness(p, e.Commonness)), rand); @@ -706,7 +728,18 @@ namespace Barotrauma foreach (Event ev in activeEvents) { - if (!ev.IsFinished) { ev.Update(deltaTime); } + if (!ev.IsFinished) + { + ev.Update(deltaTime); + } + else if (!finishedEvents.Contains(ev)) + { + if (level?.LevelData != null && level.LevelData.Type == LevelData.LevelType.Outpost) + { + if (!level.LevelData.EventHistory.Contains(ev.Prefab)) { level.LevelData.EventHistory.Add(ev.Prefab); } + } + finishedEvents.Add(ev); + } } if (QueuedEvents.Count > 0) diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/EventSet.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/EventSet.cs index 3c2be4201..a8015d651 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Events/EventSet.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/EventSet.cs @@ -92,7 +92,13 @@ namespace Barotrauma public readonly bool ChooseRandom; - public readonly int EventCount = 1; + private readonly int eventCount = 1; + private readonly Dictionary overrideEventCount = new Dictionary(); + + /// + /// 'Exhaustible' sets won't appear in the same level until after one world step (~10 min, see Map.ProgressWorld) has passed. + /// + public readonly bool Exhaustible; public readonly float MinDistanceTraveled; public readonly float MinMissionTime; @@ -250,7 +256,8 @@ namespace Barotrauma MaxIntensity = Math.Max(element.GetAttributeFloat("maxintensity", 100.0f), MinIntensity); ChooseRandom = element.GetAttributeBool("chooserandom", false); - EventCount = element.GetAttributeInt("eventcount", 1); + eventCount = element.GetAttributeInt("eventcount", 1); + Exhaustible = element.GetAttributeBool("exhaustible", false); MinDistanceTraveled = element.GetAttributeFloat("mindistancetraveled", 0.0f); MinMissionTime = element.GetAttributeFloat("minmissiontime", 0.0f); @@ -288,6 +295,13 @@ namespace Barotrauma case "eventset": childSets.Add(new EventSet(subElement, file, this)); break; + case "overrideeventcount": + Identifier locationType = subElement.GetAttributeIdentifier("locationtype", ""); + if (!overrideEventCount.ContainsKey(locationType)) + { + overrideEventCount.Add(locationType, subElement.GetAttributeInt("eventcount", eventCount)); + } + break; default: //an element with just an identifier = reference to an event prefab if (!subElement.HasElements && subElement.Attributes().First().Name.ToString().Equals("identifier", StringComparison.OrdinalIgnoreCase)) @@ -332,6 +346,12 @@ namespace Barotrauma return OverrideCommonness.ContainsKey(key) ? OverrideCommonness[key] : DefaultCommonness; } + public int GetEventCount(Level level) + { + if (level?.StartLocation == null || !overrideEventCount.TryGetValue(level.StartLocation.Type.Identifier, out int count)) { return eventCount; } + return count; + } + public static List GetDebugStatistics(int simulatedRoundCount = 100, Func filter = null, bool fullLog = false) { List debugLines = new List(); @@ -358,7 +378,7 @@ namespace Barotrauma var unusedEvents = thisSet.EventPrefabs.ToList(); if (unusedEvents.Any()) { - for (int i = 0; i < thisSet.EventCount; i++) + for (int i = 0; i < thisSet.eventCount; i++) { var eventPrefab = ToolBox.SelectWeightedRandom(unusedEvents, unusedEvents.Select(e => e.Commonness).ToList(), Rand.RandSync.Unsynced); if (eventPrefab.EventPrefabs.Any(p => p != null)) diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/EscortMission.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/EscortMission.cs index a1434ba45..e94c4432c 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/EscortMission.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/EscortMission.cs @@ -95,37 +95,42 @@ namespace Barotrauma randSync = Rand.RandSync.Unsynced; } - //if any of the escortees have a job defined, try to use a spawnpoint designated for that job + List humanPrefabsToSpawn = new List(); foreach (XElement element in characterConfig.Elements()) { + int count = CalculateScalingEscortedCharacterCount(inMission: true); var humanPrefab = GetHumanPrefabFromElement(element); - if (humanPrefab == null || string.IsNullOrEmpty(humanPrefab.Job) || humanPrefab.Job.Equals("any", StringComparison.OrdinalIgnoreCase)) { continue; } + for (int i = 0; i < count; i++) + { + humanPrefabsToSpawn.Add(humanPrefab); + } + } - var jobPrefab = humanPrefab.GetJobPrefab(); + //if any of the escortees have a job defined, try to use a spawnpoint designated for that job + foreach (var humanPrefab in humanPrefabsToSpawn) + { + if (humanPrefab == null || humanPrefab.Job.IsEmpty || humanPrefab.Job == "any") { continue; } + var jobPrefab = humanPrefab.GetJobPrefab(randSync); if (jobPrefab != null) { var jobSpecificSpawnPos = WayPoint.GetRandom(SpawnType.Human, jobPrefab, Submarine.MainSub); - if (jobSpecificSpawnPos != null) + if (jobSpecificSpawnPos != null) { explicitStayInHullPos = jobSpecificSpawnPos; break; } } } - - foreach (XElement element in characterConfig.Elements()) + foreach (var humanPrefab in humanPrefabsToSpawn) { - int count = CalculateScalingEscortedCharacterCount(inMission: true); - for (int i = 0; i < count; i++) + Character spawnedCharacter = CreateHuman(humanPrefab, characters, characterItems, Submarine.MainSub, CharacterTeamType.FriendlyNPC, explicitStayInHullPos, humanPrefabRandSync: randSync); + if (spawnedCharacter.AIController is HumanAIController humanAI) { - Character spawnedCharacter = CreateHuman(GetHumanPrefabFromElement(element), characters, characterItems, Submarine.MainSub, CharacterTeamType.FriendlyNPC, explicitStayInHullPos, humanPrefabRandSync: randSync); - if (spawnedCharacter.AIController is HumanAIController humanAI) - { - humanAI.InitMentalStateManager(); - } + humanAI.InitMentalStateManager(); } } + if (terroristChance > 0f) { int terroristCount = (int)Math.Ceiling(terroristChance * Rand.Range(0.8f, 1.2f) * characters.Count); diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/Mission.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/Mission.cs index 4975202c3..e26735cc3 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/Mission.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/Mission.cs @@ -511,7 +511,7 @@ namespace Barotrauma protected Character CreateHuman(HumanPrefab humanPrefab, List characters, Dictionary> characterItems, Submarine submarine, CharacterTeamType teamType, ISpatialEntity positionToStayIn = null, Rand.RandSync humanPrefabRandSync = Rand.RandSync.ServerAndClient, bool giveTags = true) { - var characterInfo = humanPrefab.GetCharacterInfo(Rand.RandSync.ServerAndClient) ?? new CharacterInfo(CharacterPrefab.HumanSpeciesName, npcIdentifier: humanPrefab.Identifier, jobOrJobPrefab: humanPrefab.GetJobPrefab(humanPrefabRandSync), randSync: humanPrefabRandSync); + var characterInfo = humanPrefab.CreateCharacterInfo(Rand.RandSync.ServerAndClient); characterInfo.TeamID = teamType; if (positionToStayIn == null) diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/MonsterMission.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/MonsterMission.cs index f861c2d10..eb296dad9 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/MonsterMission.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/MonsterMission.cs @@ -2,21 +2,19 @@ using System.Collections.Generic; using System.Linq; using System; +using Barotrauma.Extensions; namespace Barotrauma { partial class MonsterMission : Mission { - //string = filename, point = min,max private readonly HashSet<(CharacterPrefab character, Point amountRange)> monsterPrefabs = new HashSet<(CharacterPrefab character, Point amountRange)>(); private readonly List monsters = new List(); private readonly List sonarPositions = new List(); - private readonly List tempSonarPositions = new List(); - private readonly float maxSonarMarkerDistance = 10000.0f; - private readonly Level.PositionType spawnPosType; + private Vector2? spawnPos = null; public override IEnumerable SonarPositions { @@ -114,7 +112,16 @@ namespace Barotrauma if (!IsClient) { - Level.Loaded.TryGetInterestingPosition(true, spawnPosType, Level.Loaded.Size.X * 0.3f, out Vector2 spawnPos); + float minDistBetweenMonsterMissions = 10000; + float mindDistFromSub = Level.Loaded.Size.X * 0.3f; + var monsterMissions = GameMain.GameSession.Missions.Select(e => e as MonsterMission).Where(m => m != null && m != this && m.spawnPos.HasValue); + if (!Level.Loaded.TryGetInterestingPosition(useSyncedRand: true, spawnPosType, mindDistFromSub, out Vector2 spawnPos, + filter: p => monsterMissions.None(m => Vector2.DistanceSquared(p.Position.ToVector2(), m.spawnPos.Value) < minDistBetweenMonsterMissions * minDistBetweenMonsterMissions), + suppressWarning: true)) + { + Level.Loaded.TryGetInterestingPosition(useSyncedRand: true, spawnPosType, mindDistFromSub, out spawnPos); + } + this.spawnPos = spawnPos; foreach (var (character, amountRange) in monsterPrefabs) { int amount = Rand.Range(amountRange.X, amountRange.Y + 1); @@ -123,9 +130,8 @@ namespace Barotrauma monsters.Add(Character.Create(character.Identifier, spawnPos, ToolBox.RandomSeed(8), createNetworkEvent: false)); } } - InitializeMonsters(monsters); - } + } } private void InitializeMonsters(IEnumerable monsters) @@ -181,7 +187,7 @@ namespace Barotrauma } if (monsters[i].Removed || monsters[i].IsDead) { continue; } - Vector2 diff = tempSonarPositions[i] - monsters[i].Position; + Vector2 diff = tempSonarPositions[i] - monsters[i].WorldPosition; float maxDist = maxSonarMarkerDistance; Submarine refSub = Character.Controlled?.Submarine ?? Submarine.MainSub; @@ -191,12 +197,12 @@ namespace Barotrauma float subDist = Vector2.Distance(refPos, tempSonarPositions[i]) / maxDist; maxDist = Math.Min(subDist * subDist * maxDist, maxDist); - maxDist = Math.Min(Vector2.Distance(refPos, monsters[i].Position), maxDist); + maxDist = Math.Min(Vector2.Distance(refPos, monsters[i].WorldPosition), maxDist); } if (diff.LengthSquared() > maxDist * maxDist) { - tempSonarPositions[i] = monsters[i].Position + Vector2.Normalize(diff) * maxDist; + tempSonarPositions[i] = monsters[i].WorldPosition + Vector2.Normalize(diff) * maxDist; } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/MonsterEvent.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/MonsterEvent.cs index c26b3f54b..8dae48c00 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Events/MonsterEvent.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/MonsterEvent.cs @@ -125,7 +125,8 @@ namespace Barotrauma var file = CharacterPrefab.FindBySpeciesName(SpeciesName)?.ContentFile; if (file == null) { - DebugConsole.ThrowError($"Failed to find config file for species \"{SpeciesName}\""); + DebugConsole.ThrowError($"Failed to find config file for species \"{SpeciesName}\". Content package: \"{prefab.ConfigElement?.ContentPackage?.Name ?? "unknown"}\"."); + disallowed = true; yield break; } else @@ -535,10 +536,10 @@ namespace Barotrauma Character createdCharacter = Character.Create(SpeciesName, pos, seed, characterInfo: null, isRemotePlayer: false, hasAi: true, createNetworkEvent: true, throwErrorIfNotFound: false); if (createdCharacter == null) { + DebugConsole.AddWarning($"Error in MonsterEvent: failed to spawn the character \"{SpeciesName}\". Content package: \"{prefab.ConfigElement?.ContentPackage?.Name ?? "unknown"}\"."); disallowed = true; return; } - var eventManager = GameMain.GameSession.EventManager; if (eventManager != null) { diff --git a/Barotrauma/BarotraumaShared/SharedSource/GameAnalytics/GameAnalyticsManager.cs b/Barotrauma/BarotraumaShared/SharedSource/GameAnalytics/GameAnalyticsManager.cs index ac9e379a4..9a0eddeed 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/GameAnalytics/GameAnalyticsManager.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/GameAnalytics/GameAnalyticsManager.cs @@ -342,6 +342,21 @@ namespace Barotrauma } private static Implementation? loadedImplementation; + private static void ValidateEventID(string eventID) + { +#if DEBUG + string[] parts = eventID.Split(':'); + if (parts.Length > 5) + { + DebugConsole.ThrowError($"Invalid GameAnalytics event id \"{eventID}\". Only 5 id parts allowed separated by ':'"); + } + if (parts.Any(p => p.Length > 32)) + { + DebugConsole.ThrowError($"Invalid GameAnalytics event id \"{eventID}\". Each id part separated by ':' must be 32 characters or less."); + } +#endif + } + public static void AddErrorEvent(ErrorSeverity errorSeverity, string message) { if (!SendUserStatistics) { return; } @@ -368,12 +383,14 @@ namespace Barotrauma public static void AddDesignEvent(string eventID) { if (!SendUserStatistics) { return; } + ValidateEventID(eventID); loadedImplementation?.AddDesignEvent(eventID); } public static void AddDesignEvent(string eventID, double value) { if (!SendUserStatistics) { return; } + ValidateEventID(eventID); loadedImplementation?.AddDesignEvent(eventID, value); } @@ -450,11 +467,11 @@ namespace Barotrauma SetConsent(Consent.Error); return; } + loadedImplementation?.SetEnabledInfoLog(true); + loadedImplementation?.SetEnabledVerboseLog(true); #if DEBUG try { - loadedImplementation?.SetEnabledInfoLog(true); - loadedImplementation?.SetEnabledVerboseLog(true); } catch (Exception e) { diff --git a/Barotrauma/BarotraumaShared/SharedSource/GameSession/CargoManager.cs b/Barotrauma/BarotraumaShared/SharedSource/GameSession/CargoManager.cs index c4d5be01a..cab2c43d6 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/GameSession/CargoManager.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/GameSession/CargoManager.cs @@ -302,6 +302,10 @@ namespace Barotrauma var itemsInStoreCrate = GetBuyCrateItems(storeIdentifier, create: true); foreach (PurchasedItem item in itemsToPurchase) { + // Exchange money + int itemValue = item.Quantity * buyValues[item.ItemPrefab]; + if (!campaign.TryPurchase(client, itemValue)) { continue; } + // Add to the purchased items var purchasedItem = itemsPurchasedFromStore.Find(pi => pi.ItemPrefab == item.ItemPrefab); if (purchasedItem != null) @@ -313,9 +317,6 @@ namespace Barotrauma purchasedItem = new PurchasedItem(item.ItemPrefab, item.Quantity, client); itemsPurchasedFromStore.Add(purchasedItem); } - // Exchange money - int itemValue = item.Quantity * buyValues[item.ItemPrefab]; - campaign.TryPurchase(client, itemValue); if (GameMain.IsSingleplayer) { GameAnalyticsManager.AddMoneySpentEvent(itemValue, GameAnalyticsManager.MoneySink.Store, item.ItemPrefab.Identifier.Value); diff --git a/Barotrauma/BarotraumaShared/SharedSource/GameSession/Data/CampaignMetadata.cs b/Barotrauma/BarotraumaShared/SharedSource/GameSession/Data/CampaignMetadata.cs index 1d88c39a6..06dc62593 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/GameSession/Data/CampaignMetadata.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/GameSession/Data/CampaignMetadata.cs @@ -96,20 +96,17 @@ namespace Barotrauma private object GetTypeOrDefault(Identifier identifier, Type type, object defaultValue) { object? value = GetValue(identifier); - - if (value == null) + if (value != null) { - SetValue(identifier, defaultValue); + if (value.GetType() == type) + { + return value; + } + else + { + DebugConsole.ThrowError($"Attempted to get value \"{identifier}\" as a {type} but the value is {value.GetType()}."); + } } - else if (value.GetType() == type) - { - return value; - } - else - { - DebugConsole.ThrowError($"Attempted to get value \"{identifier}\" as a {type} but the value is {value.GetType()}."); - } - return defaultValue; } diff --git a/Barotrauma/BarotraumaShared/SharedSource/GameSession/GameModes/CampaignMode.cs b/Barotrauma/BarotraumaShared/SharedSource/GameSession/GameModes/CampaignMode.cs index 7bf83c372..7e6bf9e6e 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/GameSession/GameModes/CampaignMode.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/GameSession/GameModes/CampaignMode.cs @@ -34,7 +34,7 @@ namespace Barotrauma public double TotalPlayTime; public int TotalPassedLevels; - public enum InteractionType { None, Talk, Examine, Map, Crew, Store, Repair, Upgrade, PurchaseSub, MedicalClinic, Cargo } + public enum InteractionType { None, Talk, Examine, Map, Crew, Store, Upgrade, PurchaseSub, MedicalClinic, Cargo } public static bool BlocksInteraction(InteractionType interactionType) { @@ -85,7 +85,9 @@ namespace Barotrauma public bool CheatsEnabled; - public const int HullRepairCost = 500, ItemRepairCost = 500, ShuttleReplaceCost = 1000; + public const float HullRepairCostPerDamage = 0.5f, ItemRepairCostPerRepairDuration = 1.0f; + public const int ShuttleReplaceCost = 1000; + public const int MaxHullRepairCost = 2000, MaxItemRepairCost = 2000; protected bool wasDocked; @@ -152,8 +154,9 @@ namespace Barotrauma { if (!(e.ChangedData.BalanceChanged is Some { Value: var changed })) { return; } - bool isGain = changed > 0; + if (changed != 0) { return; } + bool isGain = changed > 0; Color clr = isGain ? GUIStyle.Yellow : GUIStyle.Red; switch (e.Owner) @@ -260,6 +263,39 @@ namespace Barotrauma wasDocked = Level.Loaded.StartOutpost != null && connectedSubs.Contains(Level.Loaded.StartOutpost); } + public int GetHullRepairCost() + { + float totalDamage = 0; + foreach (Structure wall in Structure.WallList) + { + if (wall.Submarine == null || wall.Submarine.Info.Type != SubmarineType.Player) { continue; } + if (wall.Submarine == Submarine.MainSub || Submarine.MainSub.DockedTo.Contains(wall.Submarine)) + { + for (int i = 0; i < wall.SectionCount; i++) + { + totalDamage += wall.SectionDamage(i); + } + } + } + return (int)Math.Min(totalDamage * HullRepairCostPerDamage, MaxHullRepairCost); + } + + public int GetItemRepairCost() + { + float totalRepairDuration = 0.0f; + foreach (Item item in Item.ItemList) + { + if (item.Submarine == null || item.Submarine.Info.Type != SubmarineType.Player) { continue; } + if (item.Submarine == Submarine.MainSub || Submarine.MainSub.DockedTo.Contains(item.Submarine)) + { + var repairable = item.GetComponent(); + if (repairable == null) { continue; } + totalRepairDuration += repairable.FixDurationHighSkill * (1.0f - item.Condition / item.MaxCondition); + } + } + return (int)Math.Min(totalRepairDuration * ItemRepairCostPerRepairDuration, MaxItemRepairCost); + } + public void InitCampaignData() { Factions = new List(); diff --git a/Barotrauma/BarotraumaShared/SharedSource/GameSession/GameSession.cs b/Barotrauma/BarotraumaShared/SharedSource/GameSession/GameSession.cs index 68bfe6969..bb0dfda53 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/GameSession/GameSession.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/GameSession/GameSession.cs @@ -864,7 +864,7 @@ namespace Barotrauma double roundDuration = Timing.TotalTime - RoundStartTime; GameAnalyticsManager.AddProgressionEvent( success ? GameAnalyticsManager.ProgressionStatus.Complete : GameAnalyticsManager.ProgressionStatus.Fail, - GameMode?.Name?.Value ?? "none", + GameMode?.Preset.Identifier.Value ?? "none", roundDuration); string eventId = "EndRound:" + (GameMode?.Preset?.Identifier.Value ?? "none") + ":"; LogEndRoundStats(eventId); diff --git a/Barotrauma/BarotraumaShared/SharedSource/GameSession/UpgradeManager.cs b/Barotrauma/BarotraumaShared/SharedSource/GameSession/UpgradeManager.cs index b133e0228..59e15246d 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/GameSession/UpgradeManager.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/GameSession/UpgradeManager.cs @@ -60,16 +60,6 @@ namespace Barotrauma /// public const bool UpgradeAlsoConnectedSubs = true; - /// - /// Prevents the player from upgrading the submarine when we are switching to a new one. - /// - /// - /// In singleplayer we check if CampaignMode.PendingSubmarineSwitch is not null indicating we are switching submarines - /// but in multiplayer that value is not synced so we use this variable instead by setting it to false in - /// and then set it back to true when the round ends in - /// - public bool CanUpgrade = true; - /// /// This is used by the client in multiplayer, acts like a secondary PendingUpgrades list /// but is not affected by server messages. @@ -713,9 +703,9 @@ namespace Barotrauma public bool CanUpgradeSub() { - if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient) { return CanUpgrade; } - - return Campaign.PendingSubmarineSwitch == null; + return + Campaign.PendingSubmarineSwitch == null || + Campaign.PendingSubmarineSwitch.Name == Submarine.MainSub.Info.Name; } public void Save(XElement? parent) diff --git a/Barotrauma/BarotraumaShared/SharedSource/InputType.cs b/Barotrauma/BarotraumaShared/SharedSource/InputType.cs index 2b496a231..04c8c9239 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/InputType.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/InputType.cs @@ -12,7 +12,7 @@ namespace Barotrauma Ragdoll, Health, Grab, SelectNextCharacter, SelectPreviousCharacter, - Voice, + Voice, RadioVoice, LocalVoice, Deselect, Shoot, Command, diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Holdable/Holdable.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Holdable/Holdable.cs index 0fbda966d..8e49398a5 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Holdable/Holdable.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Holdable/Holdable.cs @@ -691,12 +691,30 @@ namespace Barotrauma.Items.Components { item.Drop(character); item.SetTransform(ConvertUnits.ToSimUnits(GetAttachPosition(character)), 0.0f, findNewHull: false); + //the light source won't get properly updated if lighting is disabled (even though the light sprite is still drawn when lighting is disabled) + //so let's ensure the light source is up-to-date + RefreshLightSources(item); } AttachToWall(); } return true; + + static void RefreshLightSources(Item item) + { + item.body?.UpdateDrawPosition(); + foreach (var light in item.GetComponents()) + { + light.SetLightSourceTransform(); + } + item.GetComponent()?.SetContainedItemPositions(); + foreach (var containedItem in item.ContainedItems) + { + RefreshLightSources(containedItem); + } + } } + public override bool SecondaryUse(float deltaTime, Character character = null) { return true; diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Holdable/MeleeWeapon.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Holdable/MeleeWeapon.cs index a321e27a2..74ef0f776 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Holdable/MeleeWeapon.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Holdable/MeleeWeapon.cs @@ -1,12 +1,10 @@ -using Barotrauma.Networking; -using FarseerPhysics; +using FarseerPhysics; using FarseerPhysics.Dynamics; using FarseerPhysics.Dynamics.Contacts; using Microsoft.Xna.Framework; using System; using System.Collections.Generic; using System.Linq; -using System.Xml.Linq; namespace Barotrauma.Items.Components { @@ -292,7 +290,6 @@ namespace Barotrauma.Items.Components item.body.PhysEnabled = false; } - private bool OnCollision(Fixture f1, Fixture f2, Contact contact) { if (User == null || User.Removed) @@ -419,7 +416,18 @@ namespace Barotrauma.Items.Components else if (target.UserData is Item targetItem && targetItem.Prefab.DamagedByMeleeWeapons && targetItem.Condition > 0) { if (targetItem.Removed) { return; } - Attack.DoDamage(User, targetItem, item.WorldPosition, 1.0f); + var attackResult = Attack.DoDamage(User, targetItem, item.WorldPosition, 1.0f); +#if CLIENT + if (attackResult.Damage > 0.0f) + { + Character.Controlled?.UpdateHUDProgressBar(targetItem, + targetItem.WorldPosition, + targetItem.Condition / targetItem.MaxCondition, + emptyColor: GUIStyle.HealthBarColorLow, + fullColor: GUIStyle.HealthBarColorHigh, + textTag: targetItem.Name); + } +#endif } else if (target.UserData is Holdable holdable && holdable.CanPush) { diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Holdable/Pickable.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Holdable/Pickable.cs index 5086b6899..61ab48fe9 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Holdable/Pickable.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Holdable/Pickable.cs @@ -169,7 +169,7 @@ namespace Barotrauma.Items.Components //attempting to pick does not select the item, so if it is selected at this point, another ItemComponent //must have been selected and we should not keep deattaching (happens when for example interacting with //an electrical component while holding both a screwdriver and a wrench). - if (picker.SelectedConstruction == item || + if (picker.IsAnySelectedItem(item)|| picker.IsKeyDown(InputType.Aim) || !picker.CanInteractWith(item) || item.Removed || item.ParentInventory != null) @@ -187,7 +187,7 @@ namespace Barotrauma.Items.Components !string.IsNullOrWhiteSpace(PickingMsg) ? PickingMsg : this is Door ? "progressbar.opening" : "progressbar.deattaching"); #endif - picker.AnimController.UpdateUseItem(true, item.WorldPosition + new Vector2(0.0f, 100.0f) * ((pickTimer / 10.0f) % 0.1f)); + picker.AnimController.UpdateUseItem(!picker.IsClimbing, item.WorldPosition + new Vector2(0.0f, 100.0f) * ((pickTimer / 10.0f) % 0.1f)); pickTimer += CoroutineManager.DeltaTime; yield return CoroutineStatus.Running; @@ -208,7 +208,7 @@ namespace Barotrauma.Items.Components { if (picker != null) { - picker.AnimController.Anim = AnimController.Animation.None; + picker.AnimController.StopUsingItem(); picker.PickingItem = null; } if (pickingCoroutine != null) diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Holdable/RepairTool.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Holdable/RepairTool.cs index f7b360dad..9986d7130 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Holdable/RepairTool.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Holdable/RepairTool.cs @@ -18,6 +18,7 @@ namespace Barotrauma.Items.Components }; private readonly HashSet fixableEntities; + private readonly HashSet nonFixableEntities; private Vector2 pickedPosition; private float activeTimer; @@ -135,6 +136,7 @@ namespace Barotrauma.Items.Components } fixableEntities = new HashSet(); + nonFixableEntities = new HashSet(); foreach (var subElement in element.Elements()) { switch (subElement.Name.ToString().ToLowerInvariant()) @@ -147,7 +149,16 @@ namespace Barotrauma.Items.Components } else { - fixableEntities.Add(subElement.GetAttributeIdentifier("identifier", "")); + foreach (Identifier id in subElement.GetAttributeIdentifierArray("identifier", Array.Empty())) + { + fixableEntities.Add(id); + } + } + break; + case "nonfixable": + foreach (Identifier id in subElement.GetAttributeIdentifierArray("identifier", Array.Empty())) + { + nonFixableEntities.Add(id); } break; } @@ -523,6 +534,7 @@ namespace Barotrauma.Items.Components if (sectionIndex < 0) { return false; } if (!fixableEntities.Contains("structure") && !fixableEntities.Contains(targetStructure.Prefab.Identifier)) { return true; } + if (nonFixableEntities.Contains(targetStructure.Prefab.Identifier) || nonFixableEntities.Any(t => targetStructure.Tags.Contains(t))) { return false; } ApplyStatusEffectsOnTarget(user, deltaTime, ActionType.OnUse, structure: targetStructure); FixStructureProjSpecific(user, deltaTime, targetStructure, sectionIndex); diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/ItemContainer.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/ItemContainer.cs index 0ea9d4cad..26b9713d6 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/ItemContainer.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/ItemContainer.cs @@ -49,6 +49,8 @@ namespace Barotrauma.Items.Components } } + public readonly NamedEvent OnContainedItemsChanged = new NamedEvent(); + private bool alwaysContainedItemsSpawned; public ItemInventory Inventory; @@ -347,6 +349,7 @@ namespace Barotrauma.Items.Components //no need to Update() if this item has no statuseffects and no physics body IsActive = activeContainedItems.Count > 0 || Inventory.AllItems.Any(it => it.body != null); + OnContainedItemsChanged.Invoke(this); } public override void Move(Vector2 amount, bool ignoreContacts = false) @@ -360,6 +363,7 @@ namespace Barotrauma.Items.Components //deactivate if the inventory is empty IsActive = activeContainedItems.Count > 0 || Inventory.AllItems.Any(it => it.body != null); + OnContainedItemsChanged.Invoke(this); } public bool CanBeContained(Item item) @@ -496,7 +500,7 @@ namespace Barotrauma.Items.Components return false; } } - if (AutoInteractWithContained && character.SelectedConstruction == null) + if (AutoInteractWithContained && character.SelectedItem == null) { foreach (Item contained in Inventory.AllItems) { @@ -510,7 +514,15 @@ namespace Barotrauma.Items.Components var abilityItem = new AbilityItemContainer(item); character.CheckTalents(AbilityEffectType.OnOpenItemContainer, abilityItem); - return base.Select(character); + if (item.ParentInventory?.Owner == character) + { + //can't select ItemContainers in the character's inventory (the inventory is drawn by hovering the cursor over the inventory slot, not as a GUIFrame) + return false; + } + else + { + return base.Select(character); + } } public override bool Pick(Character picker) diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Ladder.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Ladder.cs index c1cb4be89..4d0f92aed 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Ladder.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Ladder.cs @@ -19,8 +19,7 @@ namespace Barotrauma.Items.Components public override bool Select(Character character) { if (character == null || character.LockHands || character.Removed || !(character.AnimController is HumanoidAnimController)) return false; - - character.AnimController.Anim = AnimController.Animation.Climbing; + character.AnimController.StartClimbing(); return true; } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Controller.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Controller.cs index 84ad8903e..e11973068 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Controller.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Controller.cs @@ -36,6 +36,7 @@ namespace Barotrauma.Items.Components private readonly List limbPositions = new List(); private Direction dir; + public Direction Direction => dir; //the position where the user walks to when using the controller //(relative to the position of the item) @@ -128,6 +129,13 @@ namespace Barotrauma.Items.Components set; } + [Serialize(false, IsPropertySaveable.No, description: "If true, other items can be used simultaneously.")] + public bool IsSecondaryItem + { + get; + private set; + } + public Controller(Item item, ContentXElement element) : base(item, element) { @@ -150,7 +158,7 @@ namespace Barotrauma.Items.Components if (user == null || user.Removed - || user.SelectedConstruction != item + || !user.IsAnySelectedItem(item) || item.ParentInventory != null || !user.CanInteractWith(item) || (UsableIn == UseEnvironment.Water && !user.AnimController.InWater) @@ -165,7 +173,7 @@ namespace Barotrauma.Items.Components return; } - user.AnimController.Anim = AnimController.Animation.UsingConstruction; + user.AnimController.StartUsingItem(); if (userPos != Vector2.Zero) { @@ -186,32 +194,34 @@ namespace Barotrauma.Items.Components } else { - diff.Y = 0.0f; - if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient && user != Character.Controlled) + // Secondary items (like ladders or chairs) will control the character position over primary items + // Only control the character position if the character doesn't have another secondary item already controlling it + if (!user.HasSelectedAnotherSecondaryItem(Item)) { - if (Math.Abs(diff.X) > 20.0f) + diff.Y = 0.0f; + if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient && user != Character.Controlled) { - //wait for the character to walk to the correct position - return; + if (Math.Abs(diff.X) > 20.0f) + { + //wait for the character to walk to the correct position + return; + } + else if (Math.Abs(diff.X) > 0.1f) + { + //aim to keep the collider at the correct position once close enough + user.AnimController.Collider.LinearVelocity = new Vector2( + diff.X * 0.1f, + user.AnimController.Collider.LinearVelocity.Y); + } } - else if (Math.Abs(diff.X) > 0.1f) - { - //aim to keep the collider at the correct position once close enough - user.AnimController.Collider.LinearVelocity = new Vector2( - diff.X * 0.1f, - user.AnimController.Collider.LinearVelocity.Y); - } - } - else - { - if (Math.Abs(diff.X) > 10.0f) + else if (Math.Abs(diff.X) > 10.0f) { user.AnimController.TargetMovement = Vector2.Normalize(diff); user.AnimController.TargetDir = diff.X > 0.0f ? Direction.Right : Direction.Left; return; } + user.AnimController.TargetMovement = Vector2.Zero; } - user.AnimController.TargetMovement = Vector2.Zero; UserInCorrectPosition = true; } } @@ -220,9 +230,16 @@ namespace Barotrauma.Items.Components if (limbPositions.Count == 0) { return; } - user.AnimController.Anim = AnimController.Animation.UsingConstruction; + user.AnimController.StartUsingItem(); - user.AnimController.ResetPullJoints(); + if (user.SelectedItem != null) + { + user.AnimController.ResetPullJoints(l => l.IsLowerBody); + } + else + { + user.AnimController.ResetPullJoints(); + } if (dir != 0) { user.AnimController.TargetDir = dir; } @@ -230,7 +247,10 @@ namespace Barotrauma.Items.Components { Limb limb = user.AnimController.GetLimb(lb.LimbType); if (limb == null || !limb.body.Enabled) { continue; } - + // Don't move lower body limbs if there's another selected secondary item that should control them + if (limb.IsLowerBody && user.HasSelectedAnotherSecondaryItem(Item)) { continue; } + // Don't move hands if there's a selected primary item that should control them + if (!limb.IsLowerBody && Item == user.SelectedSecondaryItem && user.SelectedItem != null) { continue; } if (lb.AllowUsingLimb) { switch (lb.LimbType) @@ -247,12 +267,9 @@ namespace Barotrauma.Items.Components break; } } - limb.Disabled = true; - Vector2 worldPosition = new Vector2(item.WorldRect.X, item.WorldRect.Y) + lb.Position * item.Scale; Vector2 diff = worldPosition - limb.WorldPosition; - limb.PullJointEnabled = true; limb.PullJointWorldAnchorB = limb.SimPosition + ConvertUnits.ToSimUnits(diff); } @@ -266,9 +283,7 @@ namespace Barotrauma.Items.Components { return false; } - - if (user == null || user.Removed || - user.SelectedConstruction != item || !user.CanInteractWith(item)) + if (user == null || user.Removed || !user.IsAnySelectedItem(item) || !user.CanInteractWith(item)) { user = null; return false; @@ -290,46 +305,44 @@ namespace Barotrauma.Items.Components } lastUsed = Timing.TotalTime; - - ApplyStatusEffects(ActionType.OnUse, 1.0f, activator); - + ApplyStatusEffects(ActionType.OnUse, 1.0f, activator); return true; } public override bool SecondaryUse(float deltaTime, Character character = null) { - if (this.user != character) + if (user != character) { return false; } - - if (this.user == null || character.Removed || - this.user.SelectedConstruction != item || !character.CanInteractWith(item)) + if (user == null || character.Removed || !user.IsAnySelectedItem(item) || !character.CanInteractWith(item)) + { + user = null; + return false; + } + if (character == null) { - this.user = null; return false; } - if (character == null) return false; focusTarget = GetFocusTarget(); + if (focusTarget == null) { Vector2 centerPos = new Vector2(item.WorldRect.Center.X, item.WorldRect.Center.Y); - Vector2 offset = character.CursorWorldPosition - centerPos; offset.Y = -offset.Y; - targetRotation = MathUtils.WrapAngleTwoPi(MathUtils.VectorToAngle(offset)); return false; } character.ViewTarget = focusTarget; + #if CLIENT if (character == Character.Controlled && cam != null) { Lights.LightManager.ViewTarget = focusTarget; cam.TargetPos = focusTarget.WorldPosition; - cam.OffsetAmount = MathHelper.Lerp(cam.OffsetAmount, (focusTarget as Item).Prefab.OffsetOnSelected * focusTarget.OffsetOnSelectedMultiplier, deltaTime * 10.0f); HideHUDs(true); } @@ -338,16 +351,12 @@ namespace Barotrauma.Items.Components if (!character.IsRemotePlayer || character.ViewTarget == focusTarget) { Vector2 centerPos = new Vector2(focusTarget.WorldRect.Center.X, focusTarget.WorldRect.Center.Y); - - Turret turret = focusTarget.GetComponent(); - if (turret != null) + if (focusTarget.GetComponent() is { } turret) { centerPos = new Vector2(focusTarget.WorldRect.X + turret.TransformedBarrelPos.X, focusTarget.WorldRect.Y - turret.TransformedBarrelPos.Y); } - Vector2 offset = character.CursorWorldPosition - centerPos; offset.Y = -offset.Y; - targetRotation = MathUtils.WrapAngleTwoPi(MathUtils.VectorToAngle(offset)); } return true; @@ -425,9 +434,10 @@ namespace Barotrauma.Items.Components humanoidAnim.LockFlippingUntil = (float)Timing.TotalTime + 0.5f; } - if (character.SelectedConstruction == this.item) { character.SelectedConstruction = null; } + if (character.SelectedItem == item) { character.SelectedItem = null; } + if (character.SelectedSecondaryItem == item) { character.SelectedSecondaryItem = null; } - character.AnimController.Anim = AnimController.Animation.None; + character.AnimController.StopUsingItem(); if (character == Character.Controlled) { HideHUDs(false); diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Deconstructor.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Deconstructor.cs index c4f04b034..c119ceec5 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Deconstructor.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Deconstructor.cs @@ -3,6 +3,7 @@ using Barotrauma.Extensions; using Barotrauma.Networking; using System; using System.Collections.Generic; +using System.Collections.Immutable; using System.Linq; using System.Xml.Linq; @@ -62,11 +63,18 @@ namespace Barotrauma.Items.Components inputContainer = containers[0]; outputContainer = containers[1]; +#if CLIENT + Identifier eventIdentifier = new Identifier(nameof(Deconstructor)); + inputContainer.OnContainedItemsChanged.RegisterOverwriteExisting(eventIdentifier, OnItemSlotsChanged); +#endif + OnItemLoadedProjSpecific(); } partial void OnItemLoadedProjSpecific(); + partial void OnItemSlotsChanged(ItemContainer container); + public override void Update(float deltaTime, Camera cam) { MoveInputQueue(); @@ -281,6 +289,7 @@ 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; for (int i = 0; i < outputContainer.Capacity; i++) diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Fabricator.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Fabricator.cs index 1d48a1378..6c15619ce 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Fabricator.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Fabricator.cs @@ -556,8 +556,20 @@ namespace Barotrauma.Items.Components const int MaxCraftingSkill = 100; + //having a higher-than-100 skill (e.g. due to talents) gives +1 quality quality += fabricatedItem.RequiredSkills.All(s => user.GetSkillLevel(s.Identifier) >= MaxCraftingSkill) ? 1 : 0; - quality += FabricationDegreeOfSuccess(user, fabricatedItem.RequiredSkills) >= 0.5f ? 1 : 0; + foreach (var skill in fabricatedItem.RequiredSkills) + { + //+1 quality if the character's skill level is >20% from the min requirement towards max skill + //e.g. if the skill requirement is 10 -> 28 + //40 -> 52 + //90 -> 92 + float skillRequirement = MathHelper.Lerp(skill.Level, MaxCraftingSkill, 0.2f); + if (user.GetSkillLevel(skill.Identifier) > skillRequirement) + { + quality += 1; + } + } return quality; } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Reactor.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Reactor.cs index 4d9561116..f8191d796 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Reactor.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Reactor.cs @@ -226,7 +226,7 @@ namespace Barotrauma.Items.Components // (= bots turn autotemp back on when leaving the reactor) if (LastAIUser != null) { - if (LastAIUser.SelectedConstruction != item && LastAIUser.CanInteractWith(item)) + if (LastAIUser.SelectedItem != item && LastAIUser.CanInteractWith(item)) { AutoTemp = true; if (GameMain.NetworkMember?.IsServer ?? false) { unsentChanges = true; } @@ -505,7 +505,7 @@ namespace Barotrauma.Items.Components { fireTimer += MathHelper.Lerp(deltaTime * 2.0f, deltaTime, item.Condition / item.MaxCondition); #if SERVER - if (fireTimer > Math.Min(5.0f, FireDelay / 2) && blameOnBroken?.Character?.SelectedConstruction == item) + if (fireTimer > Math.Min(5.0f, FireDelay / 2) && blameOnBroken?.Character?.SelectedItem == item) { GameMain.Server.KarmaManager.OnReactorOverHeating(item, blameOnBroken.Character, deltaTime); } @@ -705,7 +705,7 @@ namespace Barotrauma.Items.Components { if (lastUser != null && lastUser != character && lastUser != LastAIUser) { - if (lastUser.SelectedConstruction == item && character.IsOnPlayerTeam) + if (lastUser.SelectedItem == item && character.IsOnPlayerTeam) { character.Speak(TextManager.Get("DialogReactorTaken").Value, null, 0.0f, "reactortaken".ToIdentifier(), 10.0f); } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Steering.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Steering.cs index a04b1eb25..fc32c5c30 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Steering.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Steering.cs @@ -301,7 +301,7 @@ namespace Barotrauma.Items.Components float userSkill = 0.0f; if (user != null && controlledSub != null && - (user.SelectedConstruction == item || item.linkedTo.Contains(user.SelectedConstruction))) + (user.SelectedItem == item || item.linkedTo.Contains(user.SelectedItem))) { userSkill = user.GetSkillLevel("helm") / 100.0f; } @@ -333,7 +333,7 @@ namespace Barotrauma.Items.Components { showIceSpireWarning = false; if (user != null && user.Info != null && - user.SelectedConstruction == item && + user.SelectedItem == item && controlledSub != null && controlledSub.Velocity.LengthSquared() > 0.01f) { IncreaseSkillLevel(user, deltaTime); @@ -389,7 +389,7 @@ namespace Barotrauma.Items.Components } // if our tactical AI pilot has left, revert back to maintaining position - if (navigateTactically && (user == null || user.SelectedConstruction != item)) + if (navigateTactically && (user == null || user.SelectedItem != item)) { navigateTactically = false; AIRamTimer = 0f; @@ -722,7 +722,7 @@ namespace Barotrauma.Items.Components character.AIController.SteeringManager.Reset(); if (objective.Override) { - if (user != character && user != null && user.SelectedConstruction == item && character.IsOnPlayerTeam) + if (user != character && user != null && user.SelectedItem == item && character.IsOnPlayerTeam) { character.Speak(TextManager.Get("DialogSteeringTaken").Value, null, 0.0f, "steeringtaken".ToIdentifier(), 10.0f); } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Power/PowerContainer.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Power/PowerContainer.cs index 46eac6dca..e23357700 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Power/PowerContainer.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Power/PowerContainer.cs @@ -117,9 +117,6 @@ namespace Barotrauma.Items.Components [Serialize(false, IsPropertySaveable.Yes, description: "If true, the recharge speed (and power consumption) of the device goes up exponentially as the recharge rate is increased.")] public bool ExponentialRechargeSpeed { get; set; } - [Editable(minValue: 0.0f, maxValue: 10.0f, decimals: 2), Serialize(0.5f, IsPropertySaveable.Yes)] - public float RechargeAdjustSpeed { get; set; } - private float efficiency; [Editable(minValue: 0.0f, maxValue: 1.0f, decimals: 2), Serialize(0.95f, IsPropertySaveable.Yes, description: "The amount of power you can get out of a item relative to the amount of power that's put into it.")] public float Efficiency diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Projectile.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Projectile.cs index 9c281f00d..a6fee0611 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Projectile.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Projectile.cs @@ -851,7 +851,7 @@ namespace Barotrauma.Items.Components } else if (target.Body.UserData is Limb limb) { - if (!FriendlyFire && User != null && limb.character.IsFriendly(User)) + if (!FriendlyFire && User != null && limb.character.IsFriendly(User) && HumanAIController.IsOnFriendlyTeam(limb.character, User)) { return false; } @@ -872,7 +872,18 @@ namespace Barotrauma.Items.Components if (targetItem.Removed) { return false; } if (Attack != null && targetItem.Prefab.DamagedByProjectiles && targetItem.Condition > 0) { - attackResult = Attack.DoDamage(User ?? Attacker, targetItem, item.WorldPosition, 1.0f); + attackResult = Attack.DoDamage(User ?? Attacker, targetItem, item.WorldPosition, 1.0f); +#if CLIENT + if (attackResult.Damage > 0.0f) + { + Character.Controlled?.UpdateHUDProgressBar(targetItem, + targetItem.WorldPosition, + targetItem.Condition / targetItem.MaxCondition, + emptyColor: GUIStyle.HealthBarColorLow, + fullColor: GUIStyle.HealthBarColorHigh, + textTag: targetItem.Name); + } +#endif } } else if (target.Body.UserData is IDamageable damageable) diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Quality.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Quality.cs index 0d3dd454c..bd2becdac 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Quality.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Quality.cs @@ -47,7 +47,7 @@ namespace Barotrauma.Items.Components private int qualityLevel; - [Editable, Serialize(0, IsPropertySaveable.Yes)] + [Editable(MinValueInt = 0, MaxValueInt = MaxQuality), Serialize(0, IsPropertySaveable.Yes)] public int QualityLevel { get { return qualityLevel; } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Repairable.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Repairable.cs index 7f8fc6789..b8a0436e3 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Repairable.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Repairable.cs @@ -343,7 +343,7 @@ namespace Barotrauma.Items.Components { CurrentFixer.CheckTalents(AbilityEffectType.OnStopTinkering); } - CurrentFixer.AnimController.Anim = AnimController.Animation.None; + CurrentFixer.AnimController.StopUsingItem(); CurrentFixer = null; currentRepairItem = null; currentFixerAction = FixActions.None; @@ -430,7 +430,7 @@ namespace Barotrauma.Items.Components if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient) { return; } - if (CurrentFixer != null && (CurrentFixer.SelectedConstruction != item || !CurrentFixer.CanInteractWith(item) || CurrentFixer.IsDead)) + if (CurrentFixer != null && (CurrentFixer.SelectedItem != item || !CurrentFixer.CanInteractWith(item) || CurrentFixer.IsDead)) { StopRepairing(CurrentFixer); return; @@ -502,7 +502,7 @@ namespace Barotrauma.Items.Components SteamAchievementManager.OnItemRepaired(item, CurrentFixer); CurrentFixer.CheckTalents(AbilityEffectType.OnRepairComplete); } - if (CurrentFixer?.SelectedConstruction == item) { CurrentFixer.SelectedConstruction = null; } + if (CurrentFixer?.SelectedItem == item) { CurrentFixer.SelectedItem = null; } deteriorationTimer = Rand.Range(MinDeteriorationDelay, MaxDeteriorationDelay); wasBroken = false; StopRepairing(CurrentFixer); diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/ConnectionPanel.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/ConnectionPanel.cs index 41a02b481..c5d847e8e 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/ConnectionPanel.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/ConnectionPanel.cs @@ -179,7 +179,7 @@ namespace Barotrauma.Items.Components { UpdateProjSpecific(deltaTime); - if (user == null || user.SelectedConstruction != item) + if (user == null || user.SelectedItem != item) { #if SERVER if (user != null) { item.CreateServerEvent(this); } @@ -196,7 +196,7 @@ namespace Barotrauma.Items.Components return; } - user.AnimController.UpdateUseItem(true, item.WorldPosition + new Vector2(0.0f, 100.0f) * (((float)Timing.TotalTime / 10.0f) % 0.1f)); + user.AnimController.UpdateUseItem(!user.IsClimbing, item.WorldPosition + new Vector2(0.0f, 100.0f) * (((float)Timing.TotalTime / 10.0f) % 0.1f)); } public override void UpdateBroken(float deltaTime, Camera cam) @@ -206,7 +206,7 @@ namespace Barotrauma.Items.Components partial void UpdateProjSpecific(float deltaTime); - public override bool Select(Character picker) + public bool CanRewire() { //attaching wires to items with a body is not allowed //(signal items remove their bodies when attached to a wall) @@ -214,6 +214,15 @@ namespace Barotrauma.Items.Components { return false; } + return true; + } + + public override bool Select(Character picker) + { + if (!CanRewire()) + { + return false; + } user = picker; #if SERVER diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/Terminal.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/Terminal.cs index 13409a48e..1d6188ebd 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/Terminal.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/Terminal.cs @@ -106,11 +106,11 @@ namespace Barotrauma.Items.Components { case "set_text": case "signal_in": + if (string.IsNullOrEmpty(signal.value)) { return; } if (signal.value.Length > MaxMessageLength) { signal.value = signal.value.Substring(0, MaxMessageLength); } - string inputSignal = signal.value.Replace("\\n", "\n"); ShowOnDisplay(inputSignal, addToHistory: true, TextColor); break; diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/Wire.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/Wire.cs index ec17bd33b..863210c6b 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/Wire.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/Wire.cs @@ -309,7 +309,7 @@ namespace Barotrauma.Items.Components if (nodes.Count == 0) { return; } Character user = item.ParentInventory?.Owner as Character; - editNodeDelay = (user?.SelectedConstruction == null) ? editNodeDelay - deltaTime : 0.5f; + editNodeDelay = (user?.SelectedItem == null) ? editNodeDelay - deltaTime : 0.5f; Submarine sub = item.Submarine; if (connections[0] != null && connections[0].Item.Submarine != null) { sub = connections[0].Item.Submarine; } @@ -369,7 +369,7 @@ namespace Barotrauma.Items.Components user.AnimController.Collider.ApplyForce(forceDir * user.Mass * 50.0f, maxVelocity: NetConfig.MaxPhysicsBodyVelocity * 0.5f); if (diff.LengthSquared() > 50.0f * 50.0f) { - user.AnimController.UpdateUseItem(true, user.WorldPosition + pullBackDir * Math.Min(150.0f, diff.Length())); + user.AnimController.UpdateUseItem(!user.IsClimbing, user.WorldPosition + pullBackDir * Math.Min(150.0f, diff.Length())); } if (GameMain.NetworkMember == null || GameMain.NetworkMember.IsServer) @@ -428,7 +428,7 @@ namespace Barotrauma.Items.Components public override bool Use(float deltaTime, Character character = null) { if (character == null || character != Character.Controlled) { return false; } - if (character.SelectedConstruction != null) { return false; } + if (character.HasSelectedAnyItem) { return false; } #if CLIENT if (Screen.Selected == GameMain.SubEditorScreen && !PlayerInput.PrimaryMouseButtonClicked()) { diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Turret.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Turret.cs index cf6c5cc42..a0b7b75be 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Turret.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Turret.cs @@ -525,7 +525,7 @@ namespace Barotrauma.Items.Components UpdateLightComponents(); } - private void UpdateLightComponents() + public void UpdateLightComponents() { if (lightComponents != null) { diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Item.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Item.cs index 02095120c..6137938e3 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Item.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Item.cs @@ -303,6 +303,10 @@ namespace Barotrauma { light.SetLightSourceTransform(); } + foreach (var turret in GetComponents()) + { + turret.UpdateLightComponents(); + } } #endif } @@ -458,7 +462,7 @@ namespace Barotrauma [Serialize(0.0f, IsPropertySaveable.No)] /// - /// Can be used by status effects or conditionals to modify the sound range + /// Can be used by status effects or conditionals to modify the sight range /// public new float SightRange { @@ -806,6 +810,10 @@ namespace Barotrauma } } + public bool IsLadder { get; } + + public bool IsSecondaryItem { get; } + public Item(ItemPrefab itemPrefab, Vector2 position, Submarine submarine, ushort id = Entity.NullEntityID, bool callOnItemLoaded = true) : this(new Rectangle( (int)(position.X - itemPrefab.Sprite.size.X / 2 * itemPrefab.Scale), @@ -1013,6 +1021,9 @@ namespace Barotrauma qualityComponent = GetComponent(); + IsLadder = GetComponent() != null; + IsSecondaryItem = IsLadder || GetComponent() is { IsSecondaryItem: true }; + InitProjSpecific(); if (callOnItemLoaded) @@ -2491,16 +2502,30 @@ namespace Barotrauma if (user != null) { - if (user.SelectedConstruction == this) + if (user.SelectedItem == this) { if (user.IsKeyHit(InputType.Select) || forceSelectKey) { - user.SelectedConstruction = null; + user.SelectedItem = null; + } + } + else if (user.SelectedSecondaryItem == this) + { + if (user.IsKeyHit(InputType.Select) || forceSelectKey) + { + user.SelectedSecondaryItem = null; } } else if (selected) { - user.SelectedConstruction = this; + if (IsSecondaryItem) + { + user.SelectedSecondaryItem = this; + } + else + { + user.SelectedItem = this; + } } } @@ -3245,7 +3270,7 @@ namespace Barotrauma relativeOrigin = MathUtils.RotatePoint(relativeOrigin, -item.RotationRad); Vector2 origin = new Vector2(rect.X + rect.Width / 2, rect.Y - rect.Height / 2) + relativeOrigin; - item.rect.Location -= (origin - oldOrigin).ToPoint(); + item.rect.Location -= ((origin - oldOrigin) * scaleRelativeToPrefab).ToPoint(); } if (item.PurchasedNewSwap && !string.IsNullOrEmpty(appliedSwap.SwappableItem?.SpawnWithId)) @@ -3433,7 +3458,8 @@ namespace Barotrauma foreach (Character character in Character.CharacterList) { - if (character.SelectedConstruction == this) { character.SelectedConstruction = null; } + if (character.SelectedItem == this) { character.SelectedItem = null; } + if (character.SelectedSecondaryItem == this) { character.SelectedSecondaryItem = null; } } Door door = GetComponent(); diff --git a/Barotrauma/BarotraumaShared/SharedSource/Map/Levels/Level.cs b/Barotrauma/BarotraumaShared/SharedSource/Map/Levels/Level.cs index 981ea9027..a6f3e2038 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Map/Levels/Level.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Map/Levels/Level.cs @@ -3128,14 +3128,14 @@ namespace Barotrauma return success; } - public bool TryGetInterestingPosition(bool useSyncedRand, PositionType positionType, float minDistFromSubs, out Vector2 position, Func filter = null) + public bool TryGetInterestingPosition(bool useSyncedRand, PositionType positionType, float minDistFromSubs, out Vector2 position, Func filter = null, bool suppressWarning = false) { - bool success = TryGetInterestingPosition(useSyncedRand, positionType, minDistFromSubs, out Point pos, Vector2.Zero, minDistFromPoint: 0, filter); + bool success = TryGetInterestingPosition(useSyncedRand, positionType, minDistFromSubs, out Point pos, Vector2.Zero, minDistFromPoint: 0, filter, suppressWarning); position = pos.ToVector2(); return success; } - public bool TryGetInterestingPosition(bool useSyncedRand, PositionType positionType, float minDistFromSubs, out Point position, Vector2 awayPoint, float minDistFromPoint = 0f, Func filter = null) + public bool TryGetInterestingPosition(bool useSyncedRand, PositionType positionType, float minDistFromSubs, out Point position, Vector2 awayPoint, float minDistFromPoint = 0f, Func filter = null, bool suppressWarning = false) { if (!PositionsOfInterest.Any()) { @@ -3155,11 +3155,14 @@ namespace Barotrauma } if (!suitablePositions.Any()) { - string errorMsg = "Could not find a suitable position of interest. (PositionType: " + positionType + ", minDistFromSubs: " + minDistFromSubs + ")\n" + Environment.StackTrace.CleanupStackTrace(); - GameAnalyticsManager.AddErrorEventOnce("Level.TryGetInterestingPosition:PositionTypeNotFound", GameAnalyticsManager.ErrorSeverity.Error, errorMsg); + if (!suppressWarning) + { + string errorMsg = "Could not find a suitable position of interest. (PositionType: " + positionType + ", minDistFromSubs: " + minDistFromSubs + ")\n" + Environment.StackTrace.CleanupStackTrace(); + GameAnalyticsManager.AddErrorEventOnce("Level.TryGetInterestingPosition:PositionTypeNotFound", GameAnalyticsManager.ErrorSeverity.Error, errorMsg); #if DEBUG - DebugConsole.ThrowError(errorMsg); + DebugConsole.ThrowError(errorMsg); #endif + } position = PositionsOfInterest[Rand.Int(PositionsOfInterest.Count, (useSyncedRand ? Rand.RandSync.ServerAndClient : Rand.RandSync.Unsynced))].Position; return false; } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Map/Levels/LevelData.cs b/Barotrauma/BarotraumaShared/SharedSource/Map/Levels/LevelData.cs index a6de99b67..340238aa7 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Map/Levels/LevelData.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Map/Levels/LevelData.cs @@ -57,6 +57,8 @@ namespace Barotrauma public readonly List EventHistory = new List(); public readonly List NonRepeatableEvents = new List(); + public bool EventsExhausted { get; set; } + public float CrushDepth { get @@ -130,6 +132,8 @@ namespace Barotrauma string[] nonRepeatablePrefabNames = element.GetAttributeStringArray("nonrepeatableevents", new string[] { }); NonRepeatableEvents.AddRange(EventPrefab.Prefabs.Where(p => nonRepeatablePrefabNames.Any(n => p.Identifier == n))); + + EventsExhausted = element.GetAttributeBool(nameof(EventsExhausted).ToLower(), false); } @@ -238,7 +242,8 @@ namespace Barotrauma new XAttribute("difficulty", Difficulty.ToString("G", CultureInfo.InvariantCulture)), new XAttribute("size", XMLExtensions.PointToString(Size)), new XAttribute("generationparams", GenerationParams.Identifier), - new XAttribute("initialdepth", InitialDepth)); + new XAttribute("initialdepth", InitialDepth), + new XAttribute(nameof(EventsExhausted).ToLower(), EventsExhausted)); if (HasBeaconStation) { diff --git a/Barotrauma/BarotraumaShared/SharedSource/Map/Map/Map.cs b/Barotrauma/BarotraumaShared/SharedSource/Map/Map/Map.cs index b09b2400a..a1086d71c 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Map/Map/Map.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Map/Map/Map.cs @@ -944,15 +944,20 @@ namespace Barotrauma { foreach (Location location in Locations) { + location.LevelData.EventsExhausted = false; if (location.Discovered) { - if (furthestDiscoveredLocation == null || + if (furthestDiscoveredLocation == null || location.MapPosition.X > furthestDiscoveredLocation.MapPosition.X) { furthestDiscoveredLocation = location; } } } + foreach (LocationConnection connection in Connections) + { + connection.LevelData.EventsExhausted = false; + } foreach (Location location in Locations) { diff --git a/Barotrauma/BarotraumaShared/SharedSource/Map/Outposts/NPCSet.cs b/Barotrauma/BarotraumaShared/SharedSource/Map/Outposts/NPCSet.cs index 48cce8bfc..965965805 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Map/Outposts/NPCSet.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Map/Outposts/NPCSet.cs @@ -19,7 +19,7 @@ namespace Barotrauma public NPCSet(ContentXElement element, NPCSetsFile file) : base(file, element.GetAttributeIdentifier("identifier", "")) { - Humans = element.Elements().Select(npcElement => new HumanPrefab(npcElement, file)).ToImmutableArray(); + Humans = element.Elements().Select(npcElement => new HumanPrefab(npcElement, file, Identifier)).ToImmutableArray(); } public static HumanPrefab? Get(Identifier setIdentifier, Identifier npcidentifier) diff --git a/Barotrauma/BarotraumaShared/SharedSource/Map/Outposts/OutpostGenerationParams.cs b/Barotrauma/BarotraumaShared/SharedSource/Map/Outposts/OutpostGenerationParams.cs index 4c65efaa3..6e9b95be9 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Map/Outposts/OutpostGenerationParams.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Map/Outposts/OutpostGenerationParams.cs @@ -203,7 +203,7 @@ namespace Barotrauma } else { - newCollection.Add(new HumanPrefab(npcElement, file)); + newCollection.Add(new HumanPrefab(npcElement, file, npcSetIdentifier: from)); } } humanPrefabCollections.Add(newCollection); diff --git a/Barotrauma/BarotraumaShared/SharedSource/Map/Outposts/OutpostGenerator.cs b/Barotrauma/BarotraumaShared/SharedSource/Map/Outposts/OutpostGenerator.cs index a0e5ceed6..30217e2a5 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Map/Outposts/OutpostGenerator.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Map/Outposts/OutpostGenerator.cs @@ -1426,7 +1426,7 @@ namespace Barotrauma static bool ShouldRemoveLinkedEntity(MapEntity e, bool doorInUse, PlacedModule module) { - if (e is Item it && it.GetComponent() != null) + if (e is Item it && it.IsLadder) { if (module.UsedGapPositions.HasFlag(OutpostModuleInfo.GapPosition.Top) || module.UsedGapPositions.HasFlag(OutpostModuleInfo.GapPosition.Bottom)) { @@ -1568,7 +1568,7 @@ namespace Barotrauma foreach (HumanPrefab humanPrefab in humanPrefabs) { if (humanPrefab is null) { continue; } - var characterInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobOrJobPrefab: humanPrefab.GetJobPrefab(Rand.RandSync.ServerAndClient), randSync: Rand.RandSync.ServerAndClient); + var characterInfo = humanPrefab.CreateCharacterInfo(Rand.RandSync.ServerAndClient); if (location != null && location.KilledCharacterIdentifiers.Contains(characterInfo.GetIdentifier())) { killedCharacters.Add(humanPrefab); @@ -1582,7 +1582,7 @@ namespace Barotrauma { for (int tries = 0; tries < 100; tries++) { - var characterInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobOrJobPrefab: killedCharacter.GetJobPrefab(Rand.RandSync.ServerAndClient), randSync: Rand.RandSync.ServerAndClient); + var characterInfo = killedCharacter.CreateCharacterInfo(Rand.RandSync.ServerAndClient); if (!location.KilledCharacterIdentifiers.Contains(characterInfo.GetIdentifier())) { selectedCharacters.Add((killedCharacter, characterInfo)); diff --git a/Barotrauma/BarotraumaShared/SharedSource/Map/RoundEndCinematic.cs b/Barotrauma/BarotraumaShared/SharedSource/Map/RoundEndCinematic.cs deleted file mode 100644 index 1fb8afbae..000000000 --- a/Barotrauma/BarotraumaShared/SharedSource/Map/RoundEndCinematic.cs +++ /dev/null @@ -1,126 +0,0 @@ -using Microsoft.Xna.Framework; -using System.Collections.Generic; -using System.Linq; - -namespace Barotrauma -{ - class RoundEndCinematic - { - public bool Running - { - get; - private set; - } - - public Camera AssignedCamera; - - private float duration; - - private CoroutineHandle updateCoroutine; - - public RoundEndCinematic(Submarine submarine, Camera cam, float duration = 10.0f) - : this(new List() { submarine }, cam, duration) - { - - } - - public RoundEndCinematic(List submarines, Camera cam, float duration) - { - if (!submarines.Any(s => s != null)) return; - - this.duration = duration; - AssignedCamera = cam; - - Running = true; - updateCoroutine = CoroutineManager.StartCoroutine(Update(submarines, cam)); - } - - public void Stop() - { - CoroutineManager.StopCoroutines(updateCoroutine); - Running = false; -#if CLIENT - GUI.ScreenOverlayColor = Color.TransparentBlack; -#endif - } - - private IEnumerable Update(List subs, Camera cam) - { - if (!subs.Any()) yield return CoroutineStatus.Success; - -#if CLIENT - Character.Controlled = null; - GameMain.LightManager.LosEnabled = false; -#endif - cam.TargetPos = Vector2.Zero; - - Level.Loaded.TopBarrier.Enabled = false; - - foreach (Character character in Character.CharacterList) - { - character.AnimController.Frozen = true; - foreach (Limb limb in character.AnimController.Limbs) - { - limb.body.PhysEnabled = false; - } - } - - cam.TargetPos = Vector2.Zero; - float timer = 0.0f; - float initialZoom = cam.Zoom; - Vector2 initialCameraPos = cam.Position; - - while (timer < duration) - { - if (Screen.Selected != GameMain.GameScreen) - { - yield return new WaitForSeconds(0.1f); - -#if CLIENT - GUI.ScreenOverlayColor = Color.TransparentBlack; -#endif - - Running = false; - yield return CoroutineStatus.Success; - } - - Vector2 minPos = new Vector2( - subs.Min(s => s.WorldPosition.X - s.Borders.Width / 2), - subs.Min(s => s.WorldPosition.Y - s.Borders.Height / 2)); - Vector2 maxPos = new Vector2( - subs.Min(s => s.WorldPosition.X + s.Borders.Width / 2), - subs.Min(s => s.WorldPosition.Y + s.Borders.Height / 2)); - Vector2 cameraPos = new Vector2( - MathHelper.SmoothStep(minPos.X, maxPos.X, timer / duration), - (minPos.Y + maxPos.Y) / 2.0f); - cam.Translate(cameraPos - cam.Position); - - foreach (Submarine sub in subs) - { - sub.PhysicsBody?.ResetDynamics(); - } - -#if CLIENT - cam.Zoom = MathHelper.SmoothStep(initialZoom, 0.5f, timer / duration); - if (timer / duration > 0.9f) - { - GUI.ScreenOverlayColor = Color.Lerp(Color.TransparentBlack, Color.Black, ((timer / duration) - 0.9f) * 10.0f); - } -#endif - timer += CoroutineManager.UnscaledDeltaTime; - - yield return CoroutineStatus.Running; - } - - Running = false; - - yield return new WaitForSeconds(0.1f); - -#if CLIENT - GUI.ScreenOverlayColor = Color.TransparentBlack; -#endif - - yield return CoroutineStatus.Success; - } - } -} diff --git a/Barotrauma/BarotraumaShared/SharedSource/Map/Submarine.cs b/Barotrauma/BarotraumaShared/SharedSource/Map/Submarine.cs index 4e6e22f7f..b5f2d85d0 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Map/Submarine.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Map/Submarine.cs @@ -986,14 +986,6 @@ namespace Barotrauma subBody.Body.ResetDynamics(); subBody.Body.Enabled = false; - foreach (MapEntity e in MapEntity.mapEntityList) - { - if (e.Submarine == this) - { - Spawner.AddEntityToRemoveQueue(e); - } - } - foreach (Character c in Character.CharacterList) { if (c.Submarine == this) diff --git a/Barotrauma/BarotraumaShared/SharedSource/Map/SubmarineBody.cs b/Barotrauma/BarotraumaShared/SharedSource/Map/SubmarineBody.cs index 673a6218b..ab8ea3922 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Map/SubmarineBody.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Map/SubmarineBody.cs @@ -1,8 +1,6 @@ using Barotrauma.Extensions; using Barotrauma.Items.Components; -using Barotrauma.Networking; using FarseerPhysics; -using FarseerPhysics.Collision; using FarseerPhysics.Common; using FarseerPhysics.Dynamics; using FarseerPhysics.Dynamics.Contacts; @@ -898,13 +896,15 @@ namespace Barotrauma } bool holdingOntoSomething = false; - if (c.SelectedConstruction != null) + if (c.SelectedSecondaryItem != null) { - holdingOntoSomething = - c.SelectedConstruction.GetComponent() != null || - (c.SelectedConstruction.GetComponent()?.LimbPositions.Any() ?? false); + holdingOntoSomething = c.SelectedSecondaryItem.IsLadder || + (c.SelectedSecondaryItem.GetComponent()?.LimbPositions.Any() ?? false); + } + if (!holdingOntoSomething && c.SelectedItem != null) + { + holdingOntoSomething = c.SelectedItem.GetComponent()?.LimbPositions.Any() ?? false; } - if (!holdingOntoSomething) { c.AnimController.Collider.ApplyLinearImpulse(c.AnimController.Collider.Mass * impulse, 10.0f); diff --git a/Barotrauma/BarotraumaShared/SharedSource/Map/WayPoint.cs b/Barotrauma/BarotraumaShared/SharedSource/Map/WayPoint.cs index 6972ac705..1a99f675a 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Map/WayPoint.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Map/WayPoint.cs @@ -19,7 +19,7 @@ namespace Barotrauma public static bool ShowWayPoints = true, ShowSpawnPoints = true; - public const float LadderWaypointInterval = 70.0f; + public const float LadderWaypointInterval = 55.0f; protected SpawnType spawnType; private string[] idCardTags; @@ -560,21 +560,22 @@ namespace Barotrauma stairPoints.ForEach(wp => wp.FindStairs()); } + // Ladders foreach (Item item in Item.ItemList) { var ladders = item.GetComponent(); if (ladders == null) { continue; } Vector2 bottomPoint = new Vector2(item.Rect.Center.X, item.Rect.Top - item.Rect.Height + 10); - List ladderPoints = new List + List<(WayPoint wp, bool connectHullPoints)> ladderPoints = new List<(WayPoint, bool)> { - new WayPoint(bottomPoint, SpawnType.Path, submarine), + (new WayPoint(bottomPoint, SpawnType.Path, submarine), true) }; List ignoredBodies = new List(); // Lowest point is only meaningful for hanging ladders inside the sub, but it shouldn't matter in other cases either. // Start point is where the bots normally grasp the ladder when they stand on ground. - WayPoint lowestPoint = ladderPoints[0]; + WayPoint lowestPoint = ladderPoints[0].wp; WayPoint prevPoint = lowestPoint; Vector2 prevPos = prevPoint.SimPosition; Body ground = Submarine.PickBody(lowestPoint.SimPosition, lowestPoint.SimPosition - Vector2.UnitY, ignoredBodies, @@ -589,7 +590,7 @@ namespace Barotrauma if (lowestPoint == null || Math.Abs(startPoint.Position.Y - startHeight) > 40 && Hull.FindHull(nextPos) != null) { startPoint = new WayPoint(nextPos, SpawnType.Path, submarine); - ladderPoints.Add(startPoint); + ladderPoints.Add((startPoint, true)); if (lowestPoint != null) { startPoint.ConnectTo(lowestPoint); @@ -613,18 +614,13 @@ namespace Barotrauma } else { - //no door, check for walls + //no door, check for platforms/walls pickedBody = Submarine.PickBody( ConvertUnits.ToSimUnits(new Vector2(startPoint.Position.X, y)), prevPos, ignoredBodies, null, false, (Fixture f) => f.Body.UserData is Structure); } - if (pickedBody == null) - { - prevPos = Submarine.LastPickedPosition; - continue; - } - else + if (pickedBody != null) { ignoredBodies.Add(pickedBody); } @@ -632,19 +628,29 @@ namespace Barotrauma if (pickedDoor != null) { WayPoint newPoint = new WayPoint(pickedDoor.Item.Position, SpawnType.Path, submarine); - ladderPoints.Add(newPoint); + ladderPoints.Add((newPoint, true)); newPoint.ConnectedGap = pickedDoor.LinkedGap; + // TODO: Prevent the waypoint below being too close to the door newPoint.ConnectTo(prevPoint); prevPoint = newPoint; prevPos = new Vector2(prevPos.X, ConvertUnits.ToSimUnits(pickedDoor.Item.Position.Y - pickedDoor.Item.Rect.Height)); + // Adjust y to prevent waypoints clamping up together + y = Math.Max(pickedDoor.Item.Position.Y, y); } else { - WayPoint newPoint = new WayPoint(ConvertUnits.ToDisplayUnits(Submarine.LastPickedPosition) + Vector2.UnitY * heightFromFloor, SpawnType.Path, submarine); - ladderPoints.Add(newPoint); + Vector2 pos = pickedBody == null ? new Vector2(startPoint.Position.X, y) : + ConvertUnits.ToDisplayUnits(Submarine.LastPickedPosition) + Vector2.UnitY * heightFromFloor; + WayPoint newPoint = new WayPoint(pos, SpawnType.Path, submarine); + ladderPoints.Add((newPoint, pickedBody != null)); newPoint.ConnectTo(prevPoint); prevPoint = newPoint; prevPos = ConvertUnits.ToSimUnits(newPoint.Position); + if (pickedBody != null) + { + // Adjust y to prevent waypoints clamping up together + y = Math.Max(newPoint.Position.Y, y); + } } } @@ -652,33 +658,30 @@ namespace Barotrauma if (prevPoint.rect.Y < item.Rect.Y - 40) { WayPoint wayPoint = new WayPoint(new Vector2(item.Rect.Center.X, item.Rect.Y - 1.0f), SpawnType.Path, submarine); - ladderPoints.Add(wayPoint); + ladderPoints.Add((wayPoint, true)); wayPoint.ConnectTo(prevPoint); } // Connect ladder waypoints to hull points at the right and left side - foreach (WayPoint ladderPoint in ladderPoints) + var ladderWaypoints = ladderPoints.Select(lp => lp.wp); + foreach (var ladderPoint in ladderPoints) { - ladderPoint.Ladders = ladders; - bool isHatch = ladderPoint.ConnectedGap != null && !ladderPoint.ConnectedGap.IsRoomToRoom; + var wp = ladderPoint.wp; + wp.Ladders = ladders; + if (!ladderPoint.connectHullPoints) { continue; } + bool isHatch = wp.ConnectedGap != null && !wp.ConnectedGap.IsRoomToRoom; for (int dir = -1; dir <= 1; dir += 2) { - WayPoint closest = null; - if (isHatch) - { - closest = ladderPoint.FindClosest(dir, horizontalSearch: true, new Vector2(500, 1000), ladderPoint.ConnectedGap?.ConnectedDoor?.Body.FarseerBody, filter: wp => wp.CurrentHull == null, ignored: ladderPoints); - } - else - { - closest = ladderPoint.FindClosest(dir, horizontalSearch: true, new Vector2(150, 100), ladderPoint.ConnectedGap?.ConnectedDoor?.Body.FarseerBody, ignored: ladderPoints); - } + WayPoint closest = isHatch ? + wp.FindClosest(dir, horizontalSearch: true, new Vector2(500, 1000), wp.ConnectedGap?.ConnectedDoor?.Body.FarseerBody, filter: wp => wp.CurrentHull == null, ignored: ladderWaypoints) : + wp.FindClosest(dir, horizontalSearch: true, new Vector2(150, 100), wp.ConnectedGap?.ConnectedDoor?.Body.FarseerBody, ignored: ladderWaypoints); if (closest == null) { continue; } - ladderPoint.ConnectTo(closest); + wp.ConnectTo(closest); } } } - // Another pass: connect cap and bottom points with other ladders when they are vertically adjacent to another (double ladders) + // Another ladder pass: connect cap and bottom points with other ladders when they are vertically adjacent to another (double ladders) foreach (Item item in Item.ItemList) { var ladders = item.GetComponent(); @@ -1035,12 +1038,10 @@ namespace Barotrauma w.tags = element.GetAttributeIdentifierArray("tags", Array.Empty()).ToHashSet(); - string jobIdentifier = element.GetAttributeString("job", "").ToLowerInvariant(); - if (!string.IsNullOrWhiteSpace(jobIdentifier)) + Identifier jobIdentifier = element.GetAttributeIdentifier("job", Identifier.Empty); + if (!jobIdentifier.IsEmpty) { - w.AssignedJob = - JobPrefab.Get(jobIdentifier) ?? - JobPrefab.Prefabs.Find(jp => jp.Name.Equals(jobIdentifier, StringComparison.OrdinalIgnoreCase)); + w.AssignedJob = JobPrefab.Get(jobIdentifier); } w.linkedToID = new List(); diff --git a/Barotrauma/BarotraumaShared/SharedSource/Networking/ServerSettings.cs b/Barotrauma/BarotraumaShared/SharedSource/Networking/ServerSettings.cs index bdafe7ea8..ec76db8e0 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Networking/ServerSettings.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Networking/ServerSettings.cs @@ -810,6 +810,13 @@ namespace Barotrauma.Networking private set; } + [Serialize(120.0f, IsPropertySaveable.Yes)] + public float DisallowKickVoteTime + { + get; + private set; + } + [Serialize(300.0f, IsPropertySaveable.Yes)] public float KillDisconnectedTime { diff --git a/Barotrauma/BarotraumaShared/SharedSource/Screens/GameScreen.cs b/Barotrauma/BarotraumaShared/SharedSource/Screens/GameScreen.cs index 36743762a..7b97635be 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Screens/GameScreen.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Screens/GameScreen.cs @@ -87,10 +87,12 @@ namespace Barotrauma GameSettings.SaveCurrentConfig(); GameMain.SoundManager.SetCategoryMuffle("default", false); GUI.ClearMessages(); +#if !DEBUG if (GameMain.GameSession?.GameMode is TestGameMode) { DebugConsole.DeactivateCheats(); } +#endif #endif } @@ -168,9 +170,9 @@ namespace Barotrauma if (Character.Controlled != null) { - if (Character.Controlled.SelectedConstruction != null && Character.Controlled.CanInteractWith(Character.Controlled.SelectedConstruction)) + if (Character.Controlled.SelectedItem != null && Character.Controlled.CanInteractWith(Character.Controlled.SelectedItem)) { - Character.Controlled.SelectedConstruction.UpdateHUD(cam, Character.Controlled, (float)deltaTime); + Character.Controlled.SelectedItem.UpdateHUD(cam, Character.Controlled, (float)deltaTime); } if (Character.Controlled.Inventory != null) { diff --git a/Barotrauma/BarotraumaShared/SharedSource/Screens/Screen.cs b/Barotrauma/BarotraumaShared/SharedSource/Screens/Screen.cs index 869d4ccff..86cce0a43 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Screens/Screen.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Screens/Screen.cs @@ -19,6 +19,7 @@ { Selected.Deselect(); #if CLIENT + GameMain.ParticleManager.ClearParticles(); GUIContextMenu.CurrentContextMenu = null; GUI.ClearCursorWait(); //make sure any textbox in the previously selected screen doesn't stay selected diff --git a/Barotrauma/BarotraumaShared/SharedSource/Settings/GameSettings.cs b/Barotrauma/BarotraumaShared/SharedSource/Settings/GameSettings.cs index d13c4975e..4fc3665d5 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Settings/GameSettings.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Settings/GameSettings.cs @@ -290,6 +290,8 @@ namespace Barotrauma { InputType.CrewOrders, Keys.C }, { InputType.Voice, Keys.V }, + { InputType.RadioVoice, Keys.None }, + { InputType.LocalVoice, Keys.None }, { InputType.ToggleChatMode, Keys.R }, { InputType.Command, MouseButton.MiddleMouse }, { InputType.PreviousFireMode, MouseButton.MouseWheelDown }, @@ -333,16 +335,15 @@ namespace Barotrauma } bool playerConfigContainsNewChatBinds = false; + bool playerConfigContainsRestoredVoipBinds = false; foreach (XElement element in elements) { foreach (XAttribute attribute in element.Attributes()) { if (Enum.TryParse(attribute.Name.LocalName, out InputType result)) { - if (!playerConfigContainsNewChatBinds) - { - playerConfigContainsNewChatBinds = result == InputType.ActiveChat; - } + playerConfigContainsNewChatBinds |= result == InputType.ActiveChat; + playerConfigContainsRestoredVoipBinds |= result == InputType.RadioVoice; bindings[result] = element.GetAttributeKeyOrMouse(attribute.Name.LocalName, bindings[result]); } } @@ -351,14 +352,15 @@ namespace Barotrauma // Clear the old chat binds for configs saved before the introduction of the new chat binds if (!playerConfigContainsNewChatBinds) { - if (bindings.ContainsKey(InputType.Chat)) - { - bindings[InputType.Chat] = Keys.None; - } - if (bindings.ContainsKey(InputType.RadioChat)) - { - bindings[InputType.RadioChat] = Keys.None; - } + bindings[InputType.Chat] = Keys.None; + bindings[InputType.RadioChat] = Keys.None; + } + + // Clear old VOIP binds to make sure we have no overlapping binds + if (!playerConfigContainsRestoredVoipBinds) + { + bindings[InputType.LocalVoice] = Keys.None; + bindings[InputType.RadioVoice] = Keys.None; } Bindings = bindings.ToImmutableDictionary(); @@ -511,6 +513,7 @@ namespace Barotrauma if (hudScaleChanged) { HUDLayoutSettings.CreateAreas(); + GameMain.GameSession?.HUDScaleChanged(); } GameMain.SoundManager?.ApplySettings(); diff --git a/Barotrauma/BarotraumaShared/SharedSource/StatusEffects/StatusEffect.cs b/Barotrauma/BarotraumaShared/SharedSource/StatusEffects/StatusEffect.cs index 3fae997c0..71b24e12a 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/StatusEffects/StatusEffect.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/StatusEffects/StatusEffect.cs @@ -264,12 +264,36 @@ namespace Barotrauma public string Name => $"Character Spawn Info ({SpeciesName})"; public Dictionary SerializableProperties { get; set; } + [Serialize(false, IsPropertySaveable.No)] + public bool TransferBuffs { get; private set; } + + [Serialize(false, IsPropertySaveable.No)] + public bool TransferAfflictions { get; private set; } + + [Serialize(false, IsPropertySaveable.No)] + public bool TransferInventory { get; private set; } + [Serialize("", IsPropertySaveable.No)] public Identifier SpeciesName { get; private set; } [Serialize(1, IsPropertySaveable.No)] public int Count { get; private set; } + [Serialize(0, IsPropertySaveable.No)] + public int Stun { get; private set; } + + [Serialize("", IsPropertySaveable.No)] + public Identifier AfflictionOnSpawn { get; private set; } + + [Serialize(1, IsPropertySaveable.No)] + public int AfflictionStrength { get; private set; } + + [Serialize(false, IsPropertySaveable.No)] + public bool TransferControl { get; private set; } + + [Serialize(false, IsPropertySaveable.No)] + public bool RemovePreviousCharacter { get; private set; } + [Serialize(0f, IsPropertySaveable.No)] public float Spread { get; private set; } @@ -1596,6 +1620,64 @@ namespace Barotrauma { SwarmBehavior.CreateSwarm(characters.Cast()); } + if (!characterSpawnInfo.AfflictionOnSpawn.IsEmpty) + { + if (!AfflictionPrefab.Prefabs.TryGet(characterSpawnInfo.AfflictionOnSpawn, out AfflictionPrefab afflictionPrefab)) + { + DebugConsole.NewMessage($"Could not apply an affliction to the spawned character(s). No affliction with the identifier \"{characterSpawnInfo.AfflictionOnSpawn}\" found.", Color.Red); + return; + } + newCharacter.CharacterHealth.ApplyAffliction(newCharacter.AnimController.MainLimb, afflictionPrefab.Instantiate(characterSpawnInfo.AfflictionStrength)); + } + if (characterSpawnInfo.Stun > 0) + { + newCharacter.SetStun(characterSpawnInfo.Stun); + } + foreach (var target in targets) + { + if (!(target is Character character)) { continue; } + if (characterSpawnInfo.TransferInventory && character.Inventory != null && newCharacter.Inventory != null) + { + if (character.Inventory.Capacity != newCharacter.Inventory.Capacity) { return; } + for (int i = 0; i < character.Inventory.Capacity && i < newCharacter.Inventory.Capacity; i++) + { + character.Inventory.GetItemsAt(i).ForEachMod(item => newCharacter.Inventory.TryPutItem(item, i, allowSwapping: true, allowCombine: false, user: null)); + } + } + if (characterSpawnInfo.TransferBuffs || characterSpawnInfo.TransferAfflictions) + { + foreach (Affliction affliction in character.CharacterHealth.GetAllAfflictions()) + { + if (!characterSpawnInfo.TransferAfflictions && characterSpawnInfo.TransferBuffs && affliction.Prefab.IsBuff) + { + newCharacter.CharacterHealth.ApplyAffliction(newCharacter.AnimController.MainLimb, affliction.Prefab.Instantiate(affliction.Strength)); + } + if (characterSpawnInfo.TransferAfflictions) + { + newCharacter.CharacterHealth.ApplyAffliction(newCharacter.AnimController.MainLimb, affliction.Prefab.Instantiate(affliction.Strength)); + } + } + } + if (i == characterSpawnInfo.Count) // Only perform the below actions if this is the last character being spawned. + { + if (characterSpawnInfo.TransferControl) + { +#if CLIENT + if (Character.Controlled == target) + { + Character.Controlled = newCharacter; + } +#elif SERVER + foreach (Client c in GameMain.Server.ConnectedClients) + { + if (c.Character != target) { continue; } + GameMain.Server.SetClientCharacter(c, newCharacter); + } +#endif + } + if (characterSpawnInfo.RemovePreviousCharacter) { Entity.Spawner?.AddEntityToRemoveQueue(character); } + } + } }); } } @@ -1897,7 +1979,7 @@ namespace Barotrauma { continue; } - element.Parent.ApplyToProperty(target, property, n, CoroutineManager.UnscaledDeltaTime); + element.Parent.ApplyToProperty(target, property, n, CoroutineManager.DeltaTime); } foreach (Affliction affliction in element.Parent.Afflictions) diff --git a/Barotrauma/BarotraumaShared/changelog.txt b/Barotrauma/BarotraumaShared/changelog.txt index 635a98b76..d3ba6592d 100644 --- a/Barotrauma/BarotraumaShared/changelog.txt +++ b/Barotrauma/BarotraumaShared/changelog.txt @@ -1,3 +1,108 @@ +--------------------------------------------------------------------------------------------------------- +v0.19.0.0 +--------------------------------------------------------------------------------------------------------- + +Changes: +- Device/item UIs can be moved around by dragging. +- Allow using devices while on a ladder or sitting on a chair. +- Readded the option to have separate push-to-talk binds for local and radio voice chat (by default not bind to anything). +- The deconstructor UI shows what the input items deconstruct to (particularly important now with the lossy deconstruction recipes - it can be risky to deconstruct something just to see what materials it gives out if that results in material loss). +- Wall and device repair costs in outposts are calculated based on the amount of damage in your sub, instead of always having a fixed price. +- Inflamed lung doesn't affect characters that don't need oxygen. +- Added swarm behavior for crawler husks. +- Added some more oomph to nuclear explosions. +- Adjust the alpha of the outpost service icons according to distance to make it easier to estimate where the NPC is at, show the title of the NPC when hovering the cursor over the icon. +- Added "unlockmission" console command. +- Added "setcampaignmetadata" console command (may be useful for modders creating custom scripted events for the campaign?). +- Changed how NPC "titles" work. Previously we defined "titles" for the pirates (e.g. "Pirate Lord" and such), and the title replaced the name of the NPC (which made their dialog a little awkward). Now we display both the name and the title over the character, and special outpost NPCs also have titles. +- Gave diving masks to most NPCs. +- Changed the burn overlay formula: now also the non-affected limbs get half of the effect, because it looks weird if there's a sharp contrast between the limbs. +- Restored the 3 shell railgun rack as a legacy option. +- Reworded the "respawn with penalty" prompt to make it less confusing: you always get a penalty to your skills when you die now, and Reaper's Tax is an "extra penalty" you get on top of that if you opt to respawn mid-round. The intention behind this is to incur a cost to respawning: it shouldn't be possible to get unlimited free reinforcements and supplies mid-round. +- Made SIGTERM close the linux server gracefully. +- Made respawn items (suits, scooters) spawn in the respawn shuttle's cabinets when possible. +- Show a healthbar on items (e.g. eggs and thalamus organs) when damaging them with handheld weapons (melee or ranged). + +Balance: +- "Mission cheesing" by repeatedly undocking and redocking to an outpost to reroll the mission events no longer works: new mission events don't reappear until one "world step" has passed (~10 minutes or traversing through one level). +- Balance pass on handheld weapons: adjusted reload times, damages, stun durations, recoil and ammo stack sizes. +- Reduced tools' structure damages (dual-wielded storage containers no longer chew through submarine walls in seconds). +- Increased heavy ruin wall health to make it less easy to cheese your way in to the artifact room in ruins. +- Made boomstick fire in bursts of 2 (similar to deadeye carbide) to prevent ridiculous fire rates with quick-reloading. +- Added EMP effect to nuclear depth charges for consistency. +- Changed how skill levels affect the quality of fabricated items. Previously having a skill level equal to or higher than the item's skill requirement would result in a good quality item, meaning that practically everyone could e.g. fabricate good quality oxygen tanks. Now your skill needs to be >20% from the minimum skill requirement towards 100, (e.g. if the item requires 20 skill to fabricate, 36 results in a higher quality item). +- Reduced PUCS's radiation resistance from 100% to 90%. Complete invulnerability to radiation has way too much potential for exploits and overpowered strategies. +- Adjusted supplies in pirate submarines. +- Turn some weapons' burn damage into explosion damage (wip). +- Terminal ignores empty signals. + +Multiplayer: +- Clients who've recently joined (by default 2 minutes) are not allowed to vote to kick others, and vote kicking someone always requires at least 2 votes. +- Fixed "missing entity" errors in a specific situation in multiplayer. Occurred when a respawn shuttle was enabled and loaded on the server (= i.e. in a non-outpost level), and a client disconnected and immediately reconnected. This would cause the client to deselect the respawn shuttle, and make them start the round without loading one, leading to the "missing entity" issues due to the shuttle only existing server-side. +- Fixes damage visuals not showing on characters who've died off-screen. +- Servers doent allow selecting hidden jobs (jobs only used by NPCs) as job preferences. +- Fixed ability to upgrade the sub when there's a switch pending in multiplayer. +- Fixed friendly fire and karma always showing up as disabled on dedicated servers in the server list. +- Fixed spineling spikes fired by a human with spineling genes not damaging any human characters (enemies in PvP, pirates in pirate missions) when friendly fire is disabled. +- Fixed "invalid ExecuteAttack message: limb index out of bounds" errors when you join a server where a character has fired spineling spikes with spineling genes mid-round. +- Fixed "entity not found" errors if a shuttle or submarine ends up absurdly deep in multiplayer (> 100 km). I don't even know how someone managed to pull this off. +- Fixed rapidly clicking on the mission giver with the Use input set to LMB sometimes not giving all the available missions. Happened because the conversation logic didn't check if there's another conversation active, causing the server to show a new conversation when clicking the NPC, without interrupting/continuing the previous conversation. +- Made shockjock event only show for the player triggering the event (making it visible for everyone works kind of weirdly, when the event involves talking to an NPC next to the character who triggered the event). +- Fixed outpost events getting stuck at the last ConversationAction if another client has finished the action. + +Submarines: +- Changed default reactor output from 10,000 kW to 5000 kW. +- Decreased Winterhalter reactor output, increased fuel consumption rate. +- Fixed some gap issues in Winterhalter. +- Fixed medics not having access to the toxin cabinet in Barsuk. +- Fixed medic, engineer and mechanic spawnpoints having no tags in Typhon. + +Fixes: +- Fixed fire, breach and intruder report icons not being shown to anyone. +- Fixed missing/unwired lighting in ResearchModule_02_Colony. +- Remove particles when switching screens (otherwise e.g. particles from the previous round are still in the level if you happen to be looking at the right spot). +- Thalamus or ice walls can't be welded. +- Quick-reloading tries to reload the item whose contained items have the lowest condition. In other words, if you've equipped 2 weapons, quick-reloading reloads the one with the least ammo instead of the one that's the first in your inventory. +- Fixed messed up dementonite and depleted fuel tool recipes. +- Fixed swapping a scaled turret/hardpoint causing the new one to be misplaced. +- Fixed inability to upgrade the sub or do maintenance if you buy and opt to switch to a new sub, and then go to the submarine switch terminal to cancel the switching. +- Fixed stolen items becoming non-stolen when deconstructed. +- Fixed ItemContainer UI popping up (with no visible inventory slot) when you pick one up. For example when you pick up a detonator from the floor. +- Fixed "[E] Rewire" hover text being shown on attachable items that haven't been attached to a wall (even though they can't be rewired until attached). +- Fixed trying to bind multiple console commands to the same key with the "binkey" command crashing the game. +- Fixed high-quality revolvers having no difference to normal-quality ones. They should get a 10% damage boost per quality level, but didn't due to incorrectly configured quality stats. +- Fixed multiple monster missions sometimes spawning the monsters close to each other, causing them to attack each other. +- Fix monsters sometimes using wrong animation parameters while idling (or moving slowly). +- Fixed nuclear depth decoy using the same sprite as the normal depth decoy. +- Fixed fractal guardian VitalityMultipliers being configured incorrectly (using the "type" attribute but with affliction identifiers instead of types). +- Fixed incorrectly sized thalamus wall colliders, added background sprites to the walls. +- Fixed "tried to overwrite a submarine that's not in a local package" error when loading and trying to save a submarine autosave file. +- Fixed location portraits sometimes not showing up in the mission tab. Happened when we initialized the mission tab before the portrait had been loaded. +- Fixed coilguns and chainguns not always playing the firing sound when fired. Happened because their audio clips were so long (albeit mostly silence) that firing the them continously lead to a ton of clips playing simultaneously, exhausting the available audio channels. +- Fixed monster missions' sonar marker being placed incorrectly if a monster ends up inside the sub, making it look as if the monster was far outside the level. This often made it look like the monster was moving away from the sub when trying to "approach it". +- Fixed security officer tutorial getting stuck if you equip the weapons and gear before the objective to do so appears. +- Fixed bandolier (and other items that give bonuses when worn) giving the bonuses when the item is held. +- Fixed mod texts being briefly misaligned when scrolling down the list of unpublished mods. +- Fixed light sprite rotation not getting refreshed when placing an attachable item on a wall when lighting has been disabled with console commands. +- Fixed supercapacitors showing 1% as the initial recharge rate because the recharge rate defaulted to 10. +- Fixed some ending options of the "good samaritan" outpost event not ending the event. +- Fixed random (non-mission) events disappearing from outposts when you save and quit. + +Submarine editor: +- Fixed crashing when trying to multi-edit a string value in the sub editor. +- Fixed dragged object becoming invisible if you bring the cursor over an UI element in the sub editor. +- Fixed screwdrivers and wires in your "inventory" being included in the total item count in the sub editor's wiring mode. +- Fixed entities that were below the cursor when starting to resize a structure staying highlighted during resizing. +- Fixed sub editor treating the autosave interval as minutes instead of seconds (saving every 300 minutes instead of 300 seconds). + +Modding: +- Made NPC personality traits a separate content type instead of defining them in the localization files. +- Fixed OnDeath status effects defined in afflictions not working. Did not affect any vanilla content. +- Fixed crash when controlling a character with more than 10 "Any" inventory slots. Did not affect any vanilla content. +- Fixed custom husk appendages' textures failing to load. +- Added new properties to StatusEffect's SpawnCharacter feature: Stun, AfflictionOnSpawn, AfflictionStrength, TransferControl, RemovePreviousCharacter, TransferBuffs, TransferAfflictions, TransferInventory. +- Fixed bots always choosing their "personality trait" from the first 6 even if more are modded in. + --------------------------------------------------------------------------------------------------------- v0.18.15.0 --------------------------------------------------------------------------------------------------------- @@ -41,12 +146,10 @@ Fixes: - Fixed non-player-team interactable items getting transferred on sub switch. - Fixed ballast flora root emitting particles when damaged client-side, even if it's already been destroyed. - Fixed recycle recipes for Piercing Ammunition Box and Pulse Tri-Laser Fuel Box. -- Fixed friendly fire and karma always showing up as disabled on dedicated servers in the server list. - Fixed some lights (e.g. vending machines, neon lights, holographics displays) looking different in the sub editor than they do in-game. - Fixed undocked shuttles remaining undocked if you save and start a new game with the same submarine during the same session. Restarting the game fixed the issue though. - Fixed sonar markers going crazy if the start and end locations have the same name + added some more variety to location names to prevent duplicate location names. - Fixed multiediting an ItemComponent modifying all the components of that type in all the selected items (e.g. when editing the 1st light component of a switch, all lights in all switches would be edited). -- Fixed spineling spikes fired by a human with spineling genes not damaging any human characters (enemies in PvP, pirates in pirate missions) when friendly fire is disabled. - Fixed melee weapons not damaging structures from outside. Modding: diff --git a/Barotrauma/BarotraumaShared/serversettings.xml b/Barotrauma/BarotraumaShared/serversettings.xml index 50ed25dac..482899fc2 100644 --- a/Barotrauma/BarotraumaShared/serversettings.xml +++ b/Barotrauma/BarotraumaShared/serversettings.xml @@ -11,7 +11,7 @@ autorestart="false" LevelDifficulty="20" AllowedRandomMissionTypes="Random,Salvage,Monster,Cargo,Combat" - AllowedClientNameChars="32-33,38-46,48-57,65-90,91-91,93-93,95-122,192-255,384-591,1024-1279,19968-21327,21329-40959,13312-19903,131072-173791,173824-178207,178208-183983,63744-64255,194560-195103" + AllowedClientNameChars="32-33,38-46,48-57,65-90,91-91,93-93,95-122,192-255,384-591,1024-1159,1162-1279,19968-21327,21329-40959,13312-19903,131072-173791,173824-178207,178208-183983,63744-64255,194560-195103" ServerMessage="" tickrate="20" randomizeseed="True" From 1219615d6445ba2d68a52d149c66da432cf7cd30 Mon Sep 17 00:00:00 2001 From: Juan Pablo Arce Date: Fri, 19 Aug 2022 13:59:08 -0300 Subject: [PATCH 02/11] Unstable v0.19.1.0 --- .../BarotraumaClient/ClientSource/Camera.cs | 2 +- .../ClientSource/Characters/CharacterHUD.cs | 13 +- .../Characters/CharacterNetworking.cs | 19 +- .../Characters/Health/CharacterHealth.cs | 16 +- .../ClientSource/DebugConsole.cs | 33 +- .../Events/EventActions/ConversationAction.cs | 53 +- .../ClientSource/GUI/CrewManagement.cs | 12 +- .../BarotraumaClient/ClientSource/GUI/GUI.cs | 4 +- .../ClientSource/GUI/GUIComponent.cs | 9 +- .../ClientSource/GUI/GUIDragHandle.cs | 84 ++- .../ClientSource/GUI/GUIMessageBox.cs | 4 +- .../ClientSource/GUI/GUITextBox.cs | 7 +- .../ClientSource/GUI/TabMenu.cs | 2 +- .../ClientSource/GUI/UpgradeStore.cs | 2 + .../ClientSource/GUI/VotingInterface.cs | 2 +- .../BarotraumaClient/ClientSource/GameMain.cs | 67 +- .../ClientSource/GameSession/CargoManager.cs | 4 +- .../ClientSource/GameSession/CrewManager.cs | 2 +- .../GameModes/SinglePlayerCampaign.cs | 6 +- .../ClientSource/GameSession/ReadyCheck.cs | 8 +- .../Items/Components/ItemComponent.cs | 59 +- .../Components/Machines/Deconstructor.cs | 9 +- .../Items/Components/Machines/Reactor.cs | 60 +- .../Items/Components/Repairable.cs | 2 +- .../Items/Components/Signal/Connection.cs | 1 + .../ClientSource/Items/Components/Turret.cs | 13 +- .../ClientSource/Items/Components/Wearable.cs | 2 +- .../ClientSource/Items/Inventory.cs | 33 +- .../ClientSource/Items/Item.cs | 57 +- .../ClientSource/Items/ItemPrefab.cs | 17 +- .../ClientSource/Map/Map/Map.cs | 4 +- .../ClientSource/Map/MapEntity.cs | 16 +- .../ClientSource/Map/MapEntityPrefab.cs | 4 +- .../ClientSource/Map/StructurePrefab.cs | 2 +- .../ClientSource/Media/Video.Internal.cs | 2 +- .../ClientSource/Media/Video.cs | 2 +- .../ClientSource/Networking/BanList.cs | 97 ++- .../ClientSource/Networking/ChatMessage.cs | 5 +- .../ClientSource/Networking/Client.cs | 4 +- .../Networking/FileTransfer/FileReceiver.cs | 6 +- .../ClientSource/Networking/GameClient.cs | 319 ++++----- .../ClientEntityEventManager.cs | 2 +- .../Networking/Primitives/Peers/ClientPeer.cs | 87 ++- .../Primitives/Peers/LidgrenClientPeer.cs | 54 +- .../Primitives/Peers/SteamP2PClientPeer.cs | 95 +-- .../Primitives/Peers/SteamP2POwnerPeer.cs | 97 ++- .../ClientSource/Networking/ServerInfo.cs | 122 ++-- .../ClientSource/Networking/ServerLog.cs | 21 +- .../ClientSource/Networking/ServerSettings.cs | 12 +- .../Networking/Voip/VoipCapture.cs | 4 +- .../ClientSource/Networking/Voting.cs | 44 +- .../ClientSource/Screens/LevelEditorScreen.cs | 13 +- .../ClientSource/Screens/MainMenuScreen.cs | 16 +- .../ClientSource/Screens/ModDownloadScreen.cs | 46 +- .../ClientSource/Screens/NetLobbyScreen.cs | 82 +-- .../ClientSource/Screens/ServerListScreen.cs | 294 +++----- .../ClientSource/Screens/SubEditorScreen.cs | 22 +- .../Serialization/SerializableEntityEditor.cs | 14 +- .../ClientSource/Sounds/OggSound.cs | 4 +- .../ClientSource/Sounds/Sound.cs | 2 +- .../ClientSource/Sounds/SoundBuffer.cs | 2 +- .../ClientSource/Sounds/SoundChannel.cs | 4 +- .../ClientSource/Sounds/SoundManager.cs | 2 +- .../ClientSource/Sounds/VideoSound.cs | 2 +- .../ClientSource/Sounds/VoipSound.cs | 2 +- .../StatusEffects/StatusEffect.cs | 8 +- .../ClientSource/Steam/BulkDownloader.cs | 6 +- .../ClientSource/Steam/Lobby.cs | 31 +- .../ClientSource/Steam/SteamManager.cs | 9 +- .../Steam/WorkshopMenu/Mutable/ItemList.cs | 13 +- .../Mutable/MutableWorkshopMenu.cs | 2 +- .../Steam/WorkshopMenu/Mutable/PublishTab.cs | 2 +- .../ClientSource/Utils/ConnectCommand.cs | 32 + .../ClientSource/Utils/RichTextData.cs | 20 + .../ClientSource/Utils/SpriteRecorder.cs | 2 +- .../ClientSource/Utils/ToolBox.cs | 22 +- .../BarotraumaClient/LinuxClient.csproj | 2 +- Barotrauma/BarotraumaClient/MacClient.csproj | 2 +- .../BarotraumaClient/WindowsClient.csproj | 2 +- .../BarotraumaServer/LinuxServer.csproj | 2 +- Barotrauma/BarotraumaServer/MacServer.csproj | 2 +- .../Characters/CharacterNetworking.cs | 7 +- .../ServerSource/DebugConsole.cs | 54 +- .../BarotraumaServer/ServerSource/GameMain.cs | 14 +- .../GameModes/CharacterCampaignData.cs | 31 +- .../GameModes/MultiPlayerCampaign.cs | 34 +- .../ServerSource/GameSession/ReadyCheck.cs | 12 +- .../Items/Components/Machines/Fabricator.cs | 4 +- .../ServerSource/Networking/BanList.cs | 244 ++----- .../ServerSource/Networking/ChatMessage.cs | 2 +- .../ServerSource/Networking/Client.cs | 6 +- .../ServerSource/Networking/GameServer.cs | 233 ++++--- .../Networking/OrderChatMessage.cs | 5 +- .../Peers/Server/LidgrenServerPeer.cs | 85 ++- .../Primitives/Peers/Server/ServerPeer.cs | 88 +-- .../Peers/Server/SteamP2PServerPeer.cs | 85 +-- .../ServerSource/Networking/RespawnManager.cs | 20 +- .../ServerSource/Networking/ServerSettings.cs | 108 +-- .../ServerSource/Networking/Voting.cs | 23 +- .../ServerSource/Steam/SteamManager.cs | 12 +- .../BarotraumaServer/WindowsServer.csproj | 2 +- .../Data/permissionpresets.xml | 2 +- .../Characters/AI/EnemyAIController.cs | 6 +- .../AI/Objectives/AIObjectiveGoTo.cs | 4 + .../Characters/Animation/Ragdoll.cs | 29 +- .../SharedSource/Characters/Attack.cs | 5 +- .../SharedSource/Characters/Character.cs | 57 +- .../SharedSource/Characters/CharacterInfo.cs | 5 + .../Health/Afflictions/Affliction.cs | 9 +- .../Health/Afflictions/AfflictionHusk.cs | 5 +- .../Health/Afflictions/AfflictionPrefab.cs | 19 +- .../Characters/Health/CharacterHealth.cs | 37 +- .../SharedSource/Characters/Limb.cs | 9 +- .../ContentFile/OtherFile.cs | 2 - .../ContentPackageManager.cs | 1 - .../SharedSource/DebugConsole.cs | 10 +- .../SharedSource/Events/EventManager.cs | 18 +- .../Events/Missions/BeaconMission.cs | 3 +- .../SharedSource/Events/MonsterEvent.cs | 67 +- .../Extensions/StringExtensions.cs | 2 +- .../GameAnalytics/GameAnalyticsManager.cs | 4 +- .../GameSession/GameModes/CampaignMode.cs | 17 +- .../GameModes/CharacterCampaignData.cs | 19 +- .../GameModes/MultiPlayerCampaign.cs | 6 +- .../Items/Components/ElectricalDischarger.cs | 2 +- .../Items/Components/Holdable/Holdable.cs | 7 +- .../Items/Components/Holdable/Pickable.cs | 43 +- .../Components/Machines/Deconstructor.cs | 9 +- .../Items/Components/Machines/Engine.cs | 2 +- .../Items/Components/Machines/Fabricator.cs | 12 +- .../Components/Machines/OxygenGenerator.cs | 3 +- .../Items/Components/Machines/Pump.cs | 2 +- .../Items/Components/Machines/Reactor.cs | 76 ++- .../Items/Components/Power/PowerContainer.cs | 2 +- .../Items/Components/Power/PowerTransfer.cs | 9 +- .../Items/Components/Power/Powered.cs | 5 + .../Items/Components/Projectile.cs | 29 +- .../Items/Components/Signal/Connection.cs | 33 +- .../Items/Components/Signal/LightComponent.cs | 11 +- .../SharedSource/Items/Components/Turret.cs | 63 +- .../SharedSource/Items/Item.cs | 58 +- .../SharedSource/Items/ItemPrefab.cs | 155 ++++- .../SharedSource/Map/Explosion.cs | 45 +- .../SharedSource/Map/Levels/Biome.cs | 6 +- .../Map/Levels/CaveGenerationParams.cs | 2 +- .../SharedSource/Map/Levels/Level.cs | 163 +++-- .../Map/Levels/LevelGenerationParams.cs | 4 +- .../SharedSource/Map/Map/Map.cs | 6 +- .../SharedSource/Map/SubmarineBody.cs | 14 +- .../SharedSource/NetStructBitField.cs | 168 +++++ .../SharedSource/Networking/BanList.cs | 41 +- .../SharedSource/Networking/Client.cs | 56 +- .../Networking/ClientPermissions.cs | 10 +- .../Networking/INetSerializableStruct.cs | 629 ++++++++++-------- .../SharedSource/Networking/NetworkMember.cs | 19 +- .../Primitives/AccountId/AccountId.cs | 24 + .../Primitives/AccountId/SteamId.cs | 121 ++++ .../Networking/Primitives/AccountInfo.cs | 50 ++ .../Networking/Primitives/Address/Address.cs | 26 + .../Primitives/Address/LidgrenAddress.cs | 69 ++ .../Primitives/Address/PipeAddress.cs | 22 + .../Primitives/Address/SteamP2PAddress.cs | 37 ++ .../Primitives/Address/UnknownAddress.cs | 16 + .../Primitives/Endpoint/Endpoint.cs | 33 + .../Primitives/Endpoint/LidgrenEndpoint.cs | 63 ++ .../Primitives/Endpoint/SteamP2PEndpoint.cs | 37 ++ .../Primitives/Message/IReadMessage.cs | 3 +- .../Primitives/Message/IWriteMessage.cs | 2 +- .../Networking/Primitives/Message/Message.cs | 27 +- .../NetworkConnection/LidgrenConnection.cs | 49 +- .../NetworkConnection/NetworkConnection.cs | 52 +- .../NetworkConnection/PipeConnection.cs | 32 +- .../NetworkConnection/SteamP2PConnection.cs | 20 +- .../SharedSource/Networking/RespawnManager.cs | 1 + .../SharedSource/Networking/ServerSettings.cs | 24 +- .../SharedSource/Networking/Voip/VoipQueue.cs | 6 +- .../SharedSource/Networking/Voting.cs | 4 +- .../SharedSource/Physics/Physics.cs | 4 +- .../SharedSource/Physics/PhysicsBody.cs | 4 +- .../Serialization/XMLExtensions.cs | 19 - .../StatusEffects/DelayedEffect.cs | 2 + .../StatusEffects/StatusEffect.cs | 142 ++-- .../SharedSource/Steam/SteamManager.cs | 39 +- .../SharedSource/Text/RichString.cs | 2 +- .../SharedSource/Utils/Either.cs | 51 +- .../SharedSource/Utils/Option/None.cs | 8 + .../SharedSource/Utils/Option/Option.cs | 28 +- .../SharedSource/Utils/Option/Some.cs | 8 + .../SharedSource/Utils/ReflectionUtils.cs | 48 +- .../SharedSource/Utils/SafeIO.cs | 2 + .../SharedSource/Utils/ToolBox.cs | 11 +- Barotrauma/BarotraumaShared/changelog.txt | 85 +++ 192 files changed, 3875 insertions(+), 2648 deletions(-) create mode 100644 Barotrauma/BarotraumaClient/ClientSource/Utils/ConnectCommand.cs create mode 100644 Barotrauma/BarotraumaClient/ClientSource/Utils/RichTextData.cs create mode 100644 Barotrauma/BarotraumaShared/SharedSource/NetStructBitField.cs create mode 100644 Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/AccountId/AccountId.cs create mode 100644 Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/AccountId/SteamId.cs create mode 100644 Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/AccountInfo.cs create mode 100644 Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/Address/Address.cs create mode 100644 Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/Address/LidgrenAddress.cs create mode 100644 Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/Address/PipeAddress.cs create mode 100644 Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/Address/SteamP2PAddress.cs create mode 100644 Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/Address/UnknownAddress.cs create mode 100644 Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/Endpoint/Endpoint.cs create mode 100644 Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/Endpoint/LidgrenEndpoint.cs create mode 100644 Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/Endpoint/SteamP2PEndpoint.cs diff --git a/Barotrauma/BarotraumaClient/ClientSource/Camera.cs b/Barotrauma/BarotraumaClient/ClientSource/Camera.cs index db7c27941..02ab56891 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Camera.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Camera.cs @@ -6,7 +6,7 @@ using System; namespace Barotrauma { - public class Camera : IDisposable + class Camera : IDisposable { public static bool FollowSub = true; diff --git a/Barotrauma/BarotraumaClient/ClientSource/Characters/CharacterHUD.cs b/Barotrauma/BarotraumaClient/ClientSource/Characters/CharacterHUD.cs index 323184f04..a605b41c6 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Characters/CharacterHUD.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Characters/CharacterHUD.cs @@ -173,8 +173,8 @@ namespace Barotrauma { if (character.Info != null && !character.ShouldLockHud() && character.SelectedCharacter == null && Screen.Selected != GameMain.SubEditorScreen) { - bool mouseOnPortrait = HUDLayoutSettings.BottomRightInfoArea.Contains(PlayerInput.MousePosition) && GUI.MouseOn == null; - if (mouseOnPortrait && PlayerInput.PrimaryMouseButtonClicked()) + bool mouseOnPortrait = MouseOnCharacterPortrait() && GUI.MouseOn == null; + if (mouseOnPortrait && PlayerInput.PrimaryMouseButtonClicked() && Inventory.DraggingItems.None()) { CharacterHealth.OpenHealthWindow = character.CharacterHealth; } @@ -491,7 +491,7 @@ namespace Barotrauma character.Info.DrawPortrait(spriteBatch, HUDLayoutSettings.PortraitArea.Location.ToVector2(), new Vector2(-12 * GUI.Scale, yOffset), targetWidth: HUDLayoutSettings.PortraitArea.Width, true, character.Info.IsDisguisedAsAnother); character.Info.DrawForeground(spriteBatch); } - mouseOnPortrait = HUDLayoutSettings.BottomRightInfoArea.Contains(PlayerInput.MousePosition) && !character.ShouldLockHud(); + mouseOnPortrait = MouseOnCharacterPortrait() && !character.ShouldLockHud(); if (mouseOnPortrait) { GUIStyle.UIGlow.Draw(spriteBatch, HUDLayoutSettings.BottomRightInfoArea, GUIStyle.Green * 0.5f); @@ -538,6 +538,13 @@ namespace Barotrauma } } + public static bool MouseOnCharacterPortrait() + { + if (Character.Controlled == null) { return false; } + if (CharacterHealth.OpenHealthWindow != null || Character.Controlled.SelectedCharacter != null) { return false; } + return HUDLayoutSettings.BottomRightInfoArea.Contains(PlayerInput.MousePosition); + } + private static void DrawCharacterHoverTexts(SpriteBatch spriteBatch, Camera cam, Character character) { var allItems = character.Inventory?.AllItems; diff --git a/Barotrauma/BarotraumaClient/ClientSource/Characters/CharacterNetworking.cs b/Barotrauma/BarotraumaClient/ClientSource/Characters/CharacterNetworking.cs index 49292f426..6f32c617c 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Characters/CharacterNetworking.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Characters/CharacterNetworking.cs @@ -175,6 +175,11 @@ namespace Barotrauma AnimController.Frozen = false; Enabled = true; + //if we start receiving position updates, it means the character's no longer disabled + if (DisabledByEvent && !Removed) + { + DisabledByEvent = false; + } UInt16 networkUpdateID = 0; if (msg.ReadBoolean()) @@ -534,6 +539,7 @@ namespace Barotrauma Vector2 position = new Vector2(inc.ReadSingle(), inc.ReadSingle()); bool enabled = inc.ReadBoolean(); + bool disabledByEvent = inc.ReadBoolean(); DebugConsole.Log("Received spawn data for " + speciesName); @@ -569,7 +575,7 @@ namespace Barotrauma CharacterInfo info = CharacterInfo.ClientRead(infoSpeciesName, inc); try { - character = Create(speciesName, position, seed, characterInfo: info, id: id, isRemotePlayer: ownerId > 0 && GameMain.Client.ID != ownerId, hasAi: hasAi); + character = Create(speciesName, position, seed, characterInfo: info, id: id, isRemotePlayer: ownerId > 0 && GameMain.Client.SessionId != ownerId, hasAi: hasAi); } catch (Exception e) { @@ -650,7 +656,7 @@ namespace Barotrauma GameMain.GameSession.CrewManager.AddCharacter(character); } - if (GameMain.Client.ID == ownerId) + if (GameMain.Client.SessionId == ownerId) { GameMain.Client.HasSpawned = true; GameMain.Client.Character = character; @@ -667,7 +673,14 @@ namespace Barotrauma } } - character.Enabled = Controlled == character || enabled; + if (disabledByEvent) + { + character.DisabledByEvent = true; + } + else + { + character.Enabled = Controlled == character || enabled; + } return character; } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Characters/Health/CharacterHealth.cs b/Barotrauma/BarotraumaClient/ClientSource/Characters/Health/CharacterHealth.cs index 19dbd141f..b5acfe2e8 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Characters/Health/CharacterHealth.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Characters/Health/CharacterHealth.cs @@ -1461,7 +1461,7 @@ namespace Barotrauma description.RectTransform.Resize(new Point(description.Rect.Width, (int)(description.TextSize.Y + 10))); - int vitalityDecrease = (int)affliction.GetVitalityDecrease(this); + int vitalityDecrease = (int)GetVitalityDecreaseWithVitalityMultipliers(affliction); if (vitalityDecrease == 0) { vitality.Visible = false; @@ -1503,7 +1503,7 @@ namespace Barotrauma foreach (Affliction affliction in afflictions) { - float afflictionVitalityDecrease = affliction.GetVitalityDecrease(this); + float afflictionVitalityDecrease = GetVitalityDecreaseWithVitalityMultipliers(affliction); Color afflictionEffectColor = Color.White; if (afflictionVitalityDecrease > 0.0f) { @@ -1586,7 +1586,7 @@ namespace Barotrauma affliction.Strength / affliction.Prefab.MaxStrength); var vitalityText = labelContainer.GetChildByUserData("vitality") as GUITextBlock; - int vitalityDecrease = (int)affliction.GetVitalityDecrease(this); + int vitalityDecrease = (int)GetVitalityDecreaseWithVitalityMultipliers(affliction); if (vitalityDecrease == 0) { vitalityText.Visible = false; @@ -1604,7 +1604,7 @@ namespace Barotrauma { //items can be dropped outside the health window if (!ignoreMousePos && - !healthWindow.Rect.Contains(PlayerInput.MousePosition) ) + !healthWindow.Rect.Contains(PlayerInput.MousePosition)) { return false; } @@ -1620,10 +1620,10 @@ namespace Barotrauma } } - Limb targetLimb = Character.AnimController.Limbs.FirstOrDefault(l => l.HealthIndex == selectedLimbIndex); - + Limb targetLimb = + Character.AnimController.Limbs.FirstOrDefault(l => l.HealthIndex == selectedLimbIndex) ?? + Character.AnimController.MainLimb; item.ApplyTreatment(Character.Controlled, Character, targetLimb); - return true; } private void UpdateLimbIndicators(float deltaTime, Rectangle drawArea) @@ -1686,7 +1686,7 @@ namespace Barotrauma if (!affliction.ShouldShowIcon(Character)) { continue; } if (!affliction.Prefab.IsBuff) { - negativeEffect += affliction.Strength; + negativeEffect += affliction.Strength * GetVitalityMultiplier(affliction, limbHealth); } else { diff --git a/Barotrauma/BarotraumaClient/ClientSource/DebugConsole.cs b/Barotrauma/BarotraumaClient/ClientSource/DebugConsole.cs index 2eee53707..22196a3e7 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/DebugConsole.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/DebugConsole.cs @@ -226,7 +226,7 @@ namespace Barotrauma return client.HasPermission(ClientPermissions.Kick); case "ban": case "banip": - case "banendpoint": + case "banaddress": return client.HasPermission(ClientPermissions.Ban); case "unban": case "unbanip": @@ -429,24 +429,6 @@ namespace Barotrauma } })); - commands.Add(new Command("startlidgrenclient", "", (string[] args) => - { - if (args.Length == 0) return; - - if (GameMain.Client == null) - { - GameMain.Client = new GameClient("Name", args[0], 0); - } - })); - - commands.Add(new Command("startsteamp2pclient", "", (string[] args) => - { - if (GameMain.Client == null) - { - GameMain.Client = new GameClient("Name", null, 76561198977850505); //this is juan's alt account, feel free to abuse this one - } - })); - commands.Add(new Command("enablecheats", "enablecheats: Enables cheat commands and disables Steam achievements during this play session.", (string[] args) => { CheatsEnabled = true; @@ -2849,7 +2831,7 @@ namespace Barotrauma ); AssignOnClientExecute( - "banendpoint|banip", + "banaddress|banip", (string[] args) => { if (GameMain.Client == null || args.Length == 0) return; @@ -2871,7 +2853,7 @@ namespace Barotrauma } GameMain.Client?.SendConsoleCommand( - "banendpoint " + + "banaddress " + args[0] + " " + (banDuration.HasValue ? banDuration.Value.TotalSeconds.ToString() : "0") + " " + reason); @@ -2884,13 +2866,16 @@ namespace Barotrauma { if (GameMain.Client == null || args.Length == 0) return; string clientName = string.Join(" ", args); - GameMain.Client.UnbanPlayer(clientName, ""); + GameMain.Client.UnbanPlayer(clientName); })); - commands.Add(new Command("unbanip", "unbanip [ip]: Unban a specific IP.", (string[] args) => + commands.Add(new Command("unbanaddress", "unbanaddress [endpoint]: Unban a specific endpoint.", (string[] args) => { if (GameMain.Client == null || args.Length == 0) return; - GameMain.Client.UnbanPlayer("", args[0]); + if (Endpoint.Parse(args[0]).TryUnwrap(out var endpoint)) + { + GameMain.Client.UnbanPlayer(endpoint); + } })); AssignOnClientExecute( diff --git a/Barotrauma/BarotraumaClient/ClientSource/Events/EventActions/ConversationAction.cs b/Barotrauma/BarotraumaClient/ClientSource/Events/EventActions/ConversationAction.cs index f216984a4..e8bddc5f7 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Events/EventActions/ConversationAction.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Events/EventActions/ConversationAction.cs @@ -63,33 +63,43 @@ namespace Barotrauma shouldFadeToBlack = fadeToBlack; + Sprite eventSprite = EventSet.GetEventSprite(spriteIdentifier); + if (lastMessageBox != null && !lastMessageBox.Closed && GUIMessageBox.MessageBoxes.Contains(lastMessageBox)) { - if (actionId != null && lastMessageBox.UserData is Pair userData) + if (eventSprite != null && lastMessageBox.BackgroundIcon == null) { - if (userData.Second == actionId) { return; } - lastMessageBox.UserData = new Pair("ConversationAction", actionId.Value); + //no background icon in the last message box: we need to create a new one + lastMessageBox.Close(); } - - GUIListBox conversationList = lastMessageBox.FindChild("conversationlist", true) as GUIListBox; - Debug.Assert(conversationList != null); - - // gray out the last text block - if (conversationList.Content.Children.LastOrDefault() is GUILayoutGroup lastElement) + else { - if (lastElement.FindChild("text", true) is GUITextBlock textLayout) + if (actionId != null && lastMessageBox.UserData is Pair userData) { - textLayout.OverrideTextColor(Color.DarkGray * 0.8f); + if (userData.Second == actionId) { return; } + lastMessageBox.UserData = new Pair("ConversationAction", actionId.Value); } + + GUIListBox conversationList = lastMessageBox.FindChild("conversationlist", true) as GUIListBox; + Debug.Assert(conversationList != null); + + // gray out the last text block + if (conversationList.Content.Children.LastOrDefault() is GUILayoutGroup lastElement) + { + if (lastElement.FindChild("text", true) is GUITextBlock textLayout) + { + textLayout.OverrideTextColor(Color.DarkGray * 0.8f); + } + } + + List extraButtons = CreateConversation(conversationList, text, speaker, options, string.IsNullOrWhiteSpace(spriteIdentifier)); + AssignActionsToButtons(extraButtons, lastMessageBox); + RecalculateLastMessage(conversationList, true); + + conversationList.ScrollToEnd(0.5f); + lastMessageBox.SetBackgroundIcon(eventSprite); + return; } - - List extraButtons = CreateConversation(conversationList, text, speaker, options, string.IsNullOrWhiteSpace(spriteIdentifier)); - AssignActionsToButtons(extraButtons, lastMessageBox); - RecalculateLastMessage(conversationList, true); - - conversationList.ScrollToEnd(0.5f); - lastMessageBox.SetBackgroundIcon(EventSet.GetEventSprite(spriteIdentifier)); - return; } var (relative, min) = GetSizes(dialogType); @@ -100,7 +110,10 @@ namespace Barotrauma { UserData = "ConversationAction" }; - + messageBox.OnAddedToGUIUpdateList += (GUIComponent component) => + { + if (!(Screen.Selected is GameScreen)) { messageBox.Close(); } + }; lastMessageBox = messageBox; messageBox.InnerFrame.ClearChildren(); diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/CrewManagement.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/CrewManagement.cs index c4ec84e16..80de95f63 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/CrewManagement.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/CrewManagement.cs @@ -128,10 +128,11 @@ namespace Barotrauma var sortGroup = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.04f), hireablesGroup.RectTransform), isHorizontal: true) { - RelativeSpacing = 0.015f + RelativeSpacing = 0.015f, + Stretch = true }; - new GUITextBlock(new RectTransform(new Vector2(0.15f, 1.0f), sortGroup.RectTransform), text: TextManager.Get("campaignstore.sortby")); - sortingDropDown = new GUIDropDown(new RectTransform(new Vector2(0.4f, 1.0f), sortGroup.RectTransform), elementCount: 5) + new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), sortGroup.RectTransform), text: TextManager.Get("campaignstore.sortby")); + sortingDropDown = new GUIDropDown(new RectTransform(new Vector2(0.5f, 1.0f), sortGroup.RectTransform), elementCount: 5) { OnSelected = (child, userData) => { @@ -193,19 +194,20 @@ namespace Barotrauma { RelativeSpacing = 0.01f }; - validateHiresButton = new GUIButton(new RectTransform(new Vector2(1.0f / 3.0f, 1.0f), group.RectTransform), text: TextManager.Get("campaigncrew.validate")) + validateHiresButton = new GUIButton(new RectTransform(new Vector2(0.4f, 1.0f), group.RectTransform), text: TextManager.Get("campaigncrew.validate")) { ClickSound = GUISoundType.ConfirmTransaction, ForceUpperCase = ForceUpperCase.Yes, OnClicked = (b, o) => ValidateHires(PendingHires, true) }; - clearAllButton = new GUIButton(new RectTransform(new Vector2(1.0f / 3.0f, 1.0f), group.RectTransform), text: TextManager.Get("campaignstore.clearall")) + clearAllButton = new GUIButton(new RectTransform(new Vector2(0.4f, 1.0f), group.RectTransform), text: TextManager.Get("campaignstore.clearall")) { ClickSound = GUISoundType.Cart, ForceUpperCase = ForceUpperCase.Yes, Enabled = HasPermission, OnClicked = (b, o) => RemoveAllPendingHires() }; + GUITextBlock.AutoScaleAndNormalize(validateHiresButton.TextBlock, clearAllButton.TextBlock); resolutionWhenCreated = new Point(GameMain.GraphicsWidth, GameMain.GraphicsHeight); } diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUI.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUI.cs index 63021ce65..4e4f7c94d 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUI.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUI.cs @@ -48,7 +48,7 @@ namespace Barotrauma WaitingBackground = 6, // Cursor + Hourglass } - public static class GUI + static class GUI { public static GUICanvas Canvas => GUICanvas.Instance; public static CursorState MouseCursor = CursorState.Default; @@ -981,7 +981,7 @@ namespace Barotrauma return editor.GetMouseCursorState(); // Portrait area during gameplay case GameScreen _ when !(Character.Controlled?.ShouldLockHud() ?? true): - if (HUDLayoutSettings.BottomRightInfoArea.Contains(PlayerInput.MousePosition) || CharacterHealth.IsMouseOnHealthBar()) + if (CharacterHUD.MouseOnCharacterPortrait() || CharacterHealth.IsMouseOnHealthBar()) { return CursorState.Hand; } diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIComponent.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIComponent.cs index dff86c500..61ddb8f50 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIComponent.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIComponent.cs @@ -806,6 +806,13 @@ namespace Barotrauma flashColor = (color == null) ? GUIStyle.Red : (Color)color; } + public void ImmediateFlash(Color? color = null) + { + flashTimer = MathHelper.Pi / 4.0f * 0.1f; + flashDuration = 1.0f *0.1f; + flashColor = (color == null) ? GUIStyle.Red : (Color)color; + } + public void FadeOut(float duration, bool removeAfter, float wait = 0.0f) { CoroutineManager.StartCoroutine(LerpAlpha(0.0f, duration, removeAfter, wait)); @@ -1156,7 +1163,7 @@ namespace Barotrauma try { #if USE_STEAM - Steam.SteamManager.OverlayCustomURL(url); + Steam.SteamManager.OverlayCustomUrl(url); #else ToolBox.OpenFileWithShell(url); #endif diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIDragHandle.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIDragHandle.cs index b4987a87d..678b3fb29 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIDragHandle.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIDragHandle.cs @@ -7,68 +7,88 @@ namespace Barotrauma { private readonly RectTransform elementToMove; + private Point originalOffset; + private Vector2 dragStart; private bool dragStarted; public Rectangle DragArea; + public Func ValidatePosition; + public GUIDragHandle(RectTransform rectT, RectTransform elementToMove, string style = "GUIDragIndicator") : base(style, rectT) { + enabled = true; this.elementToMove = elementToMove; DragArea = new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight); } protected override void Update(float deltaTime) { - if (!Visible) return; + if (!Visible) { return; } base.Update(deltaTime); - Enabled = true; - if (dragStarted) + + if (enabled) { - Point moveAmount = (PlayerInput.MousePosition - dragStart).ToPoint() - elementToMove.ScreenSpaceOffset; - Rectangle rect = elementToMove.Rect; - rect.Location += moveAmount; + if (dragStarted) + { + Point moveAmount = (PlayerInput.MousePosition - dragStart).ToPoint() - elementToMove.ScreenSpaceOffset; + Rectangle rect = elementToMove.Rect; + rect.Location += moveAmount; - moveAmount.X += Math.Max(DragArea.X - rect.X, 0); - moveAmount.X -= Math.Max(rect.Right - DragArea.Right, 0); - moveAmount.Y += Math.Max(DragArea.Y - rect.Y, 0); - moveAmount.Y -= Math.Max(rect.Bottom - DragArea.Bottom, 0); + moveAmount.X += Math.Max(DragArea.X - rect.X, 0); + moveAmount.X -= Math.Max(rect.Right - DragArea.Right, 0); + moveAmount.Y += Math.Max(DragArea.Y - rect.Y, 0); + moveAmount.Y -= Math.Max(rect.Bottom - DragArea.Bottom, 0); - if (moveAmount != Point.Zero) - { - elementToMove.ScreenSpaceOffset += moveAmount; - } + if (moveAmount != Point.Zero) + { + elementToMove.ScreenSpaceOffset += moveAmount; + } - if (!PlayerInput.PrimaryMouseButtonHeld()) - { - dragStarted = false; + bool isPositionValid = ValidatePosition == null || ValidatePosition.Invoke(elementToMove); + + if (!PlayerInput.PrimaryMouseButtonHeld()) + { + if (!isPositionValid) + { + elementToMove.ScreenSpaceOffset = originalOffset; + elementToMove.GUIComponent?.Flash(); + SoundPlayer.PlayUISound(GUISoundType.PickItemFail); + } + dragStarted = false; + } } - } - else if (Rect.Contains(PlayerInput.MousePosition) && CanBeFocused && Enabled && GUI.IsMouseOn(this)) - { - State = Selected ? ComponentState.HoverSelected : ComponentState.Hover; - if (PlayerInput.PrimaryMouseButtonDown()) + else if (Rect.Contains(PlayerInput.MousePosition) && CanBeFocused && Enabled && GUI.IsMouseOn(this) && !(GUI.MouseOn is GUIButton)) { - dragStart = PlayerInput.MousePosition - elementToMove.ScreenSpaceOffset.ToVector2(); - dragStarted = true; - } - } - else - { - if (!ExternalHighlight) - { - State = Selected ? ComponentState.Selected : ComponentState.None; + State = Selected ? ComponentState.HoverSelected : ComponentState.Hover; + if (PlayerInput.PrimaryMouseButtonDown()) + { + originalOffset = elementToMove.ScreenSpaceOffset; + dragStart = PlayerInput.MousePosition - elementToMove.ScreenSpaceOffset.ToVector2(); + dragStarted = true; + } } else { - State = ComponentState.Hover; + if (!ExternalHighlight) + { + State = Selected ? ComponentState.Selected : ComponentState.None; + } + else + { + State = ComponentState.Hover; + } } } foreach (GUIComponent child in Children) { + //allow buttons to handle their states themselves + if (child is GUIButton) { continue; } child.State = State; + child.Enabled = enabled; } } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIMessageBox.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIMessageBox.cs index 8d8a563b4..8936fb126 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIMessageBox.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIMessageBox.cs @@ -448,7 +448,7 @@ namespace Barotrauma { // Message box not of type GUIMessageBox is likely the round summary MessageBoxes[i].AddToGUIUpdateList(); - break; + if (!(MessageBoxes[i].UserData is RoundSummary)) { break; } } continue; } @@ -471,7 +471,7 @@ namespace Barotrauma public void SetBackgroundIcon(Sprite icon) { if (icon == null) { return; } - if (icon == BackgroundIcon.Sprite) { return; } + if (icon == BackgroundIcon?.Sprite) { return; } GUIImage newIcon = new GUIImage(new RectTransform(icon.size.ToPoint(), RectTransform), icon) { IgnoreLayoutGroups = true, diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUITextBox.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUITextBox.cs index 866214dd6..27a558c5c 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUITextBox.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUITextBox.cs @@ -402,7 +402,8 @@ namespace Barotrauma return; } - if (MouseRect.Contains(PlayerInput.MousePosition) && (GUI.MouseOn == null || (!(GUI.MouseOn is GUIButton) && GUI.IsMouseOn(this)))) + bool isMouseOn = MouseRect.Contains(PlayerInput.MousePosition) && (GUI.MouseOn == null || (!(GUI.MouseOn is GUIButton) && GUI.IsMouseOn(this))); + if (isMouseOn || isSelecting) { State = ComponentState.Hover; if (PlayerInput.PrimaryMouseButtonDown()) @@ -438,10 +439,6 @@ namespace Barotrauma isSelecting = false; State = ComponentState.None; } - if (!isSelecting) - { - isSelecting = PlayerInput.IsShiftDown(); - } if (mouseHeldInside && !PlayerInput.PrimaryMouseButtonHeld()) { diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/TabMenu.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/TabMenu.cs index aded19429..1e7d1cd03 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/TabMenu.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/TabMenu.cs @@ -631,7 +631,7 @@ namespace Barotrauma linkedGUIList = new List(); - List connectedClients = GameMain.Client.ConnectedClients; + var connectedClients = GameMain.Client.ConnectedClients; for (int i = 0; i < teamIDs.Count; i++) { diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/UpgradeStore.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/UpgradeStore.cs index 7887ea6db..fc4cc62f2 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/UpgradeStore.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/UpgradeStore.cs @@ -1313,6 +1313,8 @@ namespace Barotrauma Item[] entitiesOnSub = drawnSubmarine.GetItems(true).Where(i => drawnSubmarine.IsEntityFoundOnThisSub(i, true)).ToArray(); foreach (UpgradeCategory category in UpgradeCategory.Categories) { + //hide categories with no upgrades in them + if (UpgradePrefab.Prefabs.None(p => p.UpgradeCategories.Contains(category))) { continue; } if (entitiesOnSub.Any(item => category.CanBeApplied(item, null))) { yield return category; diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/VotingInterface.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/VotingInterface.cs index 7d83f6e99..6afb4c50f 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/VotingInterface.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/VotingInterface.cs @@ -66,7 +66,7 @@ namespace Barotrauma { currentVoteType = type; CreateVotingGUI(); - if (starter.ID == GameMain.Client.ID) { SetGUIToVotedState(2); } + if (starter.SessionId == GameMain.Client.SessionId) { SetGUIToVotedState(2); } VoteRunning = true; } diff --git a/Barotrauma/BarotraumaClient/ClientSource/GameMain.cs b/Barotrauma/BarotraumaClient/ClientSource/GameMain.cs index f0930992a..b1dcac1fe 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GameMain.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GameMain.cs @@ -109,9 +109,7 @@ namespace Barotrauma private readonly GameTime fixedTime; - public string ConnectName; - public string ConnectEndpoint; - public UInt64 ConnectLobby; + public Option ConnectCommand = Option.None(); private static SpriteBatch spriteBatch; @@ -232,20 +230,14 @@ namespace Barotrauma ConsoleArguments = args; - ConnectName = null; - ConnectEndpoint = null; - ConnectLobby = 0; - try { - ToolBox.ParseConnectCommand(ConsoleArguments, out ConnectName, out ConnectEndpoint, out ConnectLobby); + ConnectCommand = ToolBox.ParseConnectCommand(ConsoleArguments); } catch (IndexOutOfRangeException e) { DebugConsole.ThrowError($"Failed to parse console arguments ({string.Join(' ', ConsoleArguments)})", e); - ConnectName = null; - ConnectEndpoint = null; - ConnectLobby = 0; + ConnectCommand = Option.None(); } GUI.KeyboardDispatcher = new EventInput.KeyboardDispatcher(Window); @@ -595,7 +587,7 @@ namespace Barotrauma { try { - ToolBox.ParseConnectCommand(ToolBox.SplitCommand(connectCommand), out ConnectName, out ConnectEndpoint, out ConnectLobby); + ConnectCommand = ToolBox.ParseConnectCommand(ToolBox.SplitCommand(connectCommand)); } catch (IndexOutOfRangeException e) { @@ -604,12 +596,8 @@ namespace Barotrauma #else DebugConsole.Log($"Failed to parse a Steam friend's connect invitation command ({connectCommand})\n" + e.StackTrace.CleanupStackTrace()); #endif - ConnectName = null; - ConnectEndpoint = null; - ConnectLobby = 0; + ConnectCommand = Option.None(); } - - DebugConsole.NewMessage(ConnectName + ", " + ConnectEndpoint, Color.Yellow); } public void OnLobbyJoinRequested(Steamworks.Data.Lobby lobby, Steamworks.SteamId friendId) @@ -734,38 +722,29 @@ namespace Barotrauma } else if (HasLoaded) { - if (ConnectLobby != 0) + if (ConnectCommand is Some { Value: var connectCommand }) { if (Client != null) { - Client.Disconnect(); + Client.Quit(); Client = null; - - GameMain.MainMenuScreen.Select(); + MainMenuScreen.Select(); } - Steam.SteamManager.JoinLobby(ConnectLobby, true); - ConnectLobby = 0; - ConnectEndpoint = null; - ConnectName = null; - } - else if (!string.IsNullOrWhiteSpace(ConnectEndpoint)) - { - if (Client != null) + if (connectCommand.EndpointOrLobby.TryGet(out ulong lobbyId)) { - Client.Disconnect(); - Client = null; - - GameMain.MainMenuScreen.Select(); + SteamManager.JoinLobby(lobbyId, joinServer: true); } - UInt64 serverSteamId = SteamManager.SteamIDStringToUInt64(ConnectEndpoint); - Client = new GameClient(MultiplayerPreferences.Instance.PlayerName.FallbackNullOrEmpty(SteamManager.GetUsername()), - serverSteamId != 0 ? null : ConnectEndpoint, - serverSteamId, - string.IsNullOrWhiteSpace(ConnectName) ? ConnectEndpoint : ConnectName); - ConnectLobby = 0; - ConnectEndpoint = null; - ConnectName = null; + else if (connectCommand.EndpointOrLobby.TryGet(out ConnectCommand.NameAndEndpoint nameAndEndpoint) + && nameAndEndpoint is { ServerName: var serverName, Endpoint: var endpoint }) + { + Client = new GameClient(MultiplayerPreferences.Instance.PlayerName.FallbackNullOrEmpty(SteamManager.GetUsername()), + endpoint, + string.IsNullOrWhiteSpace(serverName) ? endpoint.StringRepresentation : serverName, + Option.None()); + } + + ConnectCommand = Option.None(); } SoundPlayer.Update((float)Timing.Step); @@ -1082,7 +1061,7 @@ namespace Barotrauma if (Client != null) { - Client.Disconnect(); + Client.Quit(); Client = null; } @@ -1162,7 +1141,7 @@ namespace Barotrauma UserData = "https://steamcommunity.com/app/602960/discussions/1/", OnClicked = (btn, userdata) => { - if (!SteamManager.OverlayCustomURL(userdata as string)) + if (!SteamManager.OverlayCustomUrl(userdata as string)) { ShowOpenUrlInWebBrowserPrompt(userdata as string); } @@ -1200,7 +1179,7 @@ namespace Barotrauma { exiting = true; DebugConsole.NewMessage("Exiting..."); - NetworkMember?.Disconnect(); + NetworkMember?.Quit(); SteamManager.ShutDown(); try diff --git a/Barotrauma/BarotraumaClient/ClientSource/GameSession/CargoManager.cs b/Barotrauma/BarotraumaClient/ClientSource/GameSession/CargoManager.cs index 07ed155ff..bbdde97f2 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GameSession/CargoManager.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GameSession/CargoManager.cs @@ -103,7 +103,7 @@ namespace Barotrauma { if (soldItem.ItemPrefab != soldEntity.ItemPrefab) { return false; } if (matchId && (soldEntity.Item == null || soldItem.ID != soldEntity.Item.ID)) { return false; } - if (soldItem.Origin == SoldItem.SellOrigin.Character && GameMain.Client != null && soldItem.SellerID != GameMain.Client.ID) { return false; } + if (soldItem.Origin == SoldItem.SellOrigin.Character && GameMain.Client != null && soldItem.SellerID != GameMain.Client.SessionId) { return false; } return true; } } @@ -143,7 +143,7 @@ namespace Barotrauma return; } bool canAddToRemoveQueue = campaign.IsSinglePlayer && Entity.Spawner != null; - byte sellerId = GameMain.Client?.ID ?? 0; + byte sellerId = GameMain.Client?.SessionId ?? 0; // Check all the prices before starting the transaction to make sure the modifiers stay the same for the whole transaction var sellValues = GetSellValuesAtCurrentLocation(storeIdentifier, itemsToSell.Select(i => i.ItemPrefab)); if (!(Location.GetStore(storeIdentifier) is { } store)) diff --git a/Barotrauma/BarotraumaClient/ClientSource/GameSession/CrewManager.cs b/Barotrauma/BarotraumaClient/ClientSource/GameSession/CrewManager.cs index 73ea45844..7614a8b8d 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GameSession/CrewManager.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GameSession/CrewManager.cs @@ -1390,7 +1390,7 @@ namespace Barotrauma } else { - CreateCommandUI(HUDLayoutSettings.BottomRightInfoArea.Contains(PlayerInput.MousePosition) ? Character.Controlled : GUI.MouseOn?.UserData as Character); + CreateCommandUI(CharacterHUD.MouseOnCharacterPortrait() ? Character.Controlled : GUI.MouseOn?.UserData as Character); } SoundPlayer.PlayUISound(GUISoundType.PopupMenu); clicklessSelectionActive = isOpeningClick = true; diff --git a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/SinglePlayerCampaign.cs b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/SinglePlayerCampaign.cs index 60814bd1c..06f1d24df 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/SinglePlayerCampaign.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/SinglePlayerCampaign.cs @@ -132,9 +132,9 @@ namespace Barotrauma }; } - PurchasedLostShuttles = element.GetAttributeBool("purchasedlostshuttles", false); - PurchasedHullRepairs = element.GetAttributeBool("purchasedhullrepairs", false); - PurchasedItemRepairs = element.GetAttributeBool("purchaseditemrepairs", false); + PurchasedLostShuttlesInLatestSave = element.GetAttributeBool("purchasedlostshuttles", false); + PurchasedHullRepairsInLatestSave = element.GetAttributeBool("purchasedhullrepairs", false); + PurchasedItemRepairsInLatestSave = element.GetAttributeBool("purchaseditemrepairs", false); CheatsEnabled = element.GetAttributeBool("cheatsenabled", false); if (CheatsEnabled) { diff --git a/Barotrauma/BarotraumaClient/ClientSource/GameSession/ReadyCheck.cs b/Barotrauma/BarotraumaClient/ClientSource/GameSession/ReadyCheck.cs index 4db03f290..1d1b488d3 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GameSession/ReadyCheck.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GameSession/ReadyCheck.cs @@ -83,7 +83,7 @@ namespace Barotrauma foreach (var (id, _) in Clients) { - Client? client = GameMain.Client.ConnectedClients.FirstOrDefault(c => c.ID == id); + Client? client = GameMain.Client.ConnectedClients.FirstOrDefault(c => c.SessionId == id); GUIFrame container = new GUIFrame(new RectTransform(new Vector2(1f, 0.15f), listBox.Content.RectTransform), style: "ListBoxElement") { UserData = id }; GUILayoutGroup frame = new GUILayoutGroup(new RectTransform(Vector2.One, container.RectTransform), isHorizontal: true) { Stretch = true }; @@ -93,7 +93,7 @@ namespace Barotrauma if (client == null) { - string list = GameMain.Client.ConnectedClients.Aggregate("Available clients:\n", (current, c) => current + $"{c.ID}: {c.Name}\n"); + string list = GameMain.Client.ConnectedClients.Aggregate("Available clients:\n", (current, c) => current + $"{c.SessionId}: {c.Name}\n"); DebugConsole.ThrowError($"Client ID {id} was reported in ready check but was not found.\n" + list.TrimEnd('\n')); } @@ -141,7 +141,7 @@ namespace Barotrauma { ReadyCheckState state = (ReadyCheckState) inc.ReadByte(); CrewManager? crewManager = GameMain.GameSession?.CrewManager; - List otherClients = GameMain.Client.ConnectedClients; + var otherClients = GameMain.Client.ConnectedClients; if (crewManager == null || otherClients == null) { if (state == ReadyCheckState.Start) @@ -165,7 +165,7 @@ namespace Barotrauma if (hasAuthor) { authorId = inc.ReadByte(); - isOwn = authorId == GameMain.Client.ID; + isOwn = authorId == GameMain.Client.SessionId; } ushort clientCount = inc.ReadUInt16(); diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/ItemComponent.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/ItemComponent.cs index c60171bfe..ebbc45e0b 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/ItemComponent.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/ItemComponent.cs @@ -148,6 +148,8 @@ namespace Barotrauma.Items.Components public GUIFrame GuiFrame { get; set; } + public bool LockGuiFramePosition; + [Serialize(false, IsPropertySaveable.No)] public bool AllowUIOverlap { @@ -586,8 +588,58 @@ namespace Barotrauma.Items.Components }; int iconHeight = GUIStyle.ItemFrameMargin.Y / 4; - new GUIImage(new RectTransform(new Point(GuiFrame.Rect.Width, iconHeight), handle.RectTransform, Anchor.TopCenter) { AbsoluteOffset = new Point(0, iconHeight / 2) }, + var dragIcon = new GUIImage(new RectTransform(new Point(GuiFrame.Rect.Width, iconHeight), handle.RectTransform, Anchor.TopCenter) { AbsoluteOffset = new Point(0, iconHeight / 2) }, style: "GUIDragIndicatorHorizontal"); + + handle.ValidatePosition = (RectTransform rectT) => + { + var activeHuds = Character.Controlled?.SelectedItem?.ActiveHUDs ?? item.ActiveHUDs; + foreach (ItemComponent ic in activeHuds) + { + if (ic == this || ic.GuiFrame == null || !ic.CanBeSelected) { continue; } + if (ic.GuiFrame.Rect.Width > GameMain.GraphicsWidth * 0.9f && ic.GuiFrame.Rect.Height > GameMain.GraphicsHeight * 0.9f) + { + //a full-screen GUIFrame (or at least close to one) - this component is doing something weird, + //an ItemContainer with no GUIFrame definition that positions itself in some other GUIFrame, some kind of an overlay? + // -> allow intersecting + continue; + } + if (dragIcon.Rect.Intersects(ic.GuiFrame.Rect)) + { + GuiFrame.ImmediateFlash(); + return false; + } + } + return true; + }; + + + int buttonHeight = (int)(GUIStyle.ItemFrameMargin.Y * 0.4f); + new GUIButton(new RectTransform(new Point(buttonHeight), handle.RectTransform, Anchor.TopLeft) { AbsoluteOffset = new Point(buttonHeight / 10) }, + style: "GUIButtonRefresh") + { + OnClicked = (btn, userdata) => + { + GUIContextMenu.CreateContextMenu( + new ContextMenuOption("item.resetuiposition", isEnabled: true, onSelected: () => + { + if (Character.Controlled?.SelectedItem != null && item != Character.Controlled.SelectedItem) + { + Character.Controlled.SelectedItem.ForceHUDLayoutUpdate(ignoreLocking: true); + } + else + { + item.ForceHUDLayoutUpdate(ignoreLocking: true); + } + }), + new ContextMenuOption(TextManager.Get(LockGuiFramePosition ? "item.unlockuiposition" : "item.lockuiposition"), isEnabled: true, onSelected: () => + { + LockGuiFramePosition = !LockGuiFramePosition; + handle.Enabled = !LockGuiFramePosition; + })); + return true; + } + }; } } @@ -648,6 +700,11 @@ namespace Barotrauma.Items.Components CreateGUI(); } OnResolutionChanged(); + item.ForceHUDLayoutUpdate(ignoreLocking: true); + if (GuiFrame != null && GuiFrame.GetChild() is GUIDragHandle dragHandle) + { + dragHandle.DragArea = HUDLayoutSettings.ItemHUDArea; + } } public virtual void AddTooltipInfo(ref LocalizedString name, ref LocalizedString description) { } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Deconstructor.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Deconstructor.cs index 1eeedca4b..1c4dfe80b 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Deconstructor.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Deconstructor.cs @@ -255,7 +255,7 @@ namespace Barotrauma.Items.Components foreach (DeconstructItem deconstructItem in it.Prefab.DeconstructItems) { - RegisterItem(deconstructItem.ItemIdentifier); + RegisterItem(deconstructItem.ItemIdentifier, deconstructItem.Amount); } if (it.OwnInventory is { } inventory) @@ -266,15 +266,14 @@ namespace Barotrauma.Items.Components } } - void RegisterItem(Identifier identifier) + void RegisterItem(Identifier identifier, int amount = 1) { if (itemCounts.ContainsKey(identifier)) { - itemCounts[identifier]++; + itemCounts[identifier] += amount; return; } - - itemCounts.Add(identifier, 1); + itemCounts.Add(identifier, amount); } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Reactor.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Reactor.cs index cfe675dbb..5e973af30 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Reactor.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Reactor.cs @@ -1,11 +1,11 @@ using Barotrauma.Extensions; using Barotrauma.Networking; +using Barotrauma.Sounds; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using System; using System.Collections.Generic; using System.Linq; -using System.Xml.Linq; namespace Barotrauma.Items.Components { @@ -40,6 +40,9 @@ namespace Barotrauma.Items.Components private Color outputColor = Color.Goldenrod; private Color loadColor = Color.LightSteelBlue; + private RoundSound temperatureBoostSoundUp, temperatureBoostSoundDown; + private GUIButton temperatureBoostUpButton, temperatureBoostDownButton; + public GUIScrollBar FissionRateScrollBar { get; private set; } public GUIScrollBar TurbineOutputScrollBar { get; private set; } @@ -76,6 +79,20 @@ namespace Barotrauma.Items.Components tempRangeIndicator = new Sprite(element.GetChildElement("temprangeindicator")?.GetChildElement("sprite")); graphLine = new Sprite(element.GetChildElement("graphline")?.GetChildElement("sprite")); + foreach (var subElement in element.Elements()) + { + string textureDir = GetTextureDirectory(subElement); + switch (subElement.Name.ToString().ToLowerInvariant()) + { + case "temperatureboostsoundup": + temperatureBoostSoundUp = RoundSound.Load(subElement, false); + break; + case "temperatureboostsounddown": + temperatureBoostSoundDown = RoundSound.Load(subElement, false); + break; + } + } + paddedFrame = new GUILayoutGroup(new RectTransform( GuiFrame.Rect.Size - GUIStyle.ItemFrameMargin, GuiFrame.RectTransform, Anchor.Center) { AbsoluteOffset = GUIStyle.ItemFrameOffset }, @@ -354,7 +371,46 @@ namespace Barotrauma.Items.Components new GUIFrame(new RectTransform(new Vector2(0.01f, 1.0f), bottomRightArea.RectTransform), style: "VerticalLine"); - new GUICustomComponent(new RectTransform(new Vector2(0.1f, 1), bottomRightArea.RectTransform, Anchor.Center), DrawTempMeter, null); + var temperatureArea = new GUILayoutGroup(new RectTransform(new Vector2(0.1f, 1), bottomRightArea.RectTransform, Anchor.Center), isHorizontal: false) + { + Stretch = true, + RelativeSpacing = 0.01f + }; + + temperatureBoostUpButton = new GUIButton(new RectTransform(Vector2.One, temperatureArea.RectTransform, scaleBasis: ScaleBasis.BothWidth), style: "GUIPlusButton") + { + ToolTip = TextManager.Get("reactor.temperatureboostup"), + OnClicked = (_, __) => + { + applyTemperatureBoost(TemperatureBoostAmount, temperatureBoostSoundUp); + return true; + } + }; + new GUICustomComponent(new RectTransform(Vector2.One, temperatureArea.RectTransform, Anchor.Center), DrawTempMeter, null); + + temperatureBoostDownButton = new GUIButton(new RectTransform(Vector2.One, temperatureArea.RectTransform, scaleBasis: ScaleBasis.BothWidth), style: "GUIMinusButton") + { + ToolTip = TextManager.Get("reactor.temperatureboostdown"), + OnClicked = (_, __) => + { + applyTemperatureBoost(-TemperatureBoostAmount, temperatureBoostSoundDown); + return true; + } + }; + + void applyTemperatureBoost(float amount, RoundSound sound) + { + temperatureBoost = amount; + if (sound != null) + { + SoundPlayer.PlaySound( + sound.Sound, + item.WorldPosition, + sound.Volume, + sound.Range, + hullGuess: item.CurrentHull); + } + } var graphArea = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 1.0f), bottomRightArea.RectTransform)) { diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Repairable.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Repairable.cs index 20fc3437e..c67963162 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Repairable.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Repairable.cs @@ -354,7 +354,7 @@ namespace Barotrauma.Items.Components tinkerButtonText : tinkeringText + new string('.', ((int)(Timing.TotalTime * 2.0f) % 3) + 1); - System.Diagnostics.Debug.Assert(GuiFrame.GetChild(0) is GUILayoutGroup, "Repair UI hierarchy has changed, could not find skill texts"); + //System.Diagnostics.Debug.Assert(GuiFrame.GetChild(0) is GUILayoutGroup, "Repair UI hierarchy has changed, could not find skill texts"); extraButtonContainer.Visible = SabotageButton.Visible || TinkerButton.Visible; extraButtonContainer.IgnoreLayoutGroups = !extraButtonContainer.Visible; diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Signal/Connection.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Signal/Connection.cs index 8d5d16766..fe6ba3270 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Signal/Connection.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Signal/Connection.cs @@ -317,6 +317,7 @@ namespace Barotrauma.Items.Components bool mouseOn = canDrag && + !(GUI.MouseOn is GUIDragHandle) && ((PlayerInput.MousePosition.X > Math.Min(start.X, end.X) && PlayerInput.MousePosition.X < Math.Max(start.X, end.X) && MathUtils.LineToPointDistanceSquared(start, end, PlayerInput.MousePosition) < 36) || diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Turret.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Turret.cs index 919eae413..03e4e2eff 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Turret.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Turret.cs @@ -5,9 +5,7 @@ using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using System; using System.Collections.Generic; -using Barotrauma.IO; using System.Linq; -using System.Xml.Linq; namespace Barotrauma.Items.Components { @@ -94,14 +92,6 @@ namespace Barotrauma.Items.Components private set; } - [Serialize(false, IsPropertySaveable.No, description: "Use firing offset for muzzleflash? This field shouldn't be needed but I'm using it for prototyping")] - public bool UseFiringOffsetForMuzzleFlash - { - get; - private set; - } - - public Vector2 DrawSize { get @@ -188,7 +178,7 @@ namespace Barotrauma.Items.Components recoilTimer /= 1 + user.GetStatValue(StatTypes.TurretAttackSpeed); } PlaySound(ActionType.OnUse); - Vector2 particlePos = GetRelativeFiringPosition(UseFiringOffsetForMuzzleFlash); + Vector2 particlePos = GetRelativeFiringPosition(); foreach (ParticleEmitter emitter in particleEmitters) { emitter.Emit(1.0f, particlePos, hullGuess: null, angle: -rotation, particleRotation: rotation); @@ -248,7 +238,6 @@ namespace Barotrauma.Items.Components { moveSoundChannel.FadeOutAndDispose(); moveSoundChannel = null; - } } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Wearable.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Wearable.cs index 8918490f2..4d4893e4e 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Wearable.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Wearable.cs @@ -26,7 +26,7 @@ namespace Barotrauma.Items.Components { foreach (DamageModifier damageModifier in damageModifiers) { - if (MathUtils.NearlyEqual(damageModifier.DamageMultiplier, 1f)) + if (MathUtils.NearlyEqual(damageModifier.DamageMultiplier * damageModifier.ProbabilityMultiplier, 1f)) { continue; } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Inventory.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Inventory.cs index b64fda77a..7858e3154 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Inventory.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Inventory.cs @@ -1147,15 +1147,16 @@ namespace Barotrauma { Character.Controlled.ClearInputs(); + bool mouseOnPortrait = CharacterHUD.MouseOnCharacterPortrait(); if (!DetermineMouseOnInventory(ignoreDraggedItem: true) && - CharacterHealth.OpenHealthWindow != null) + (CharacterHealth.OpenHealthWindow != null || mouseOnPortrait)) { bool dropSuccessful = false; foreach (Item item in DraggingItems) { var inventory = item.ParentInventory; var indices = inventory?.FindIndices(item); - dropSuccessful |= CharacterHealth.OpenHealthWindow.OnItemDropped(item, false); + dropSuccessful |= (CharacterHealth.OpenHealthWindow ?? Character.Controlled.CharacterHealth).OnItemDropped(item, ignoreMousePos: mouseOnPortrait); if (dropSuccessful) { if (indices != null && inventory.visualSlots != null) @@ -1167,7 +1168,6 @@ namespace Barotrauma } break; } - } if (dropSuccessful) { @@ -1444,7 +1444,10 @@ namespace Barotrauma float scale = Math.Min(Math.Min(iconSize / sprite.size.X, iconSize / sprite.size.Y), 1.5f); Vector2 itemPos = PlayerInput.MousePosition; - bool mouseOnHealthInterface = CharacterHealth.OpenHealthWindow != null && CharacterHealth.OpenHealthWindow.MouseOnElement && DraggingItems.Any(it => it.UseInHealthInterface); + bool mouseOnHealthInterface = + (CharacterHealth.OpenHealthWindow != null && CharacterHealth.OpenHealthWindow.MouseOnElement)|| + CharacterHUD.MouseOnCharacterPortrait(); + mouseOnHealthInterface = mouseOnHealthInterface && DraggingItems.Any(it => it.UseInHealthInterface); if ((GUI.MouseOn == null || mouseOnHealthInterface) && selectedSlot == null) { @@ -1453,13 +1456,25 @@ namespace Barotrauma Character.Controlled.FocusedItem != null ? TextManager.GetWithVariable("PutItemIn", "[itemname]", Character.Controlled.FocusedItem.Name, FormatCapitals.Yes) : TextManager.Get(Screen.Selected is SubEditorScreen editor && editor.EntityMenu.Rect.Contains(PlayerInput.MousePosition) ? "Delete" : "DropItem"); - int textWidth = (int)Math.Max(GUIStyle.Font.MeasureString(DraggingItems.First().Name).X, GUIStyle.SmallFont.MeasureString(toolTip).X); + + Vector2 nameSize = GUIStyle.Font.MeasureString(DraggingItems.First().Name); + Vector2 toolTipSize = GUIStyle.SmallFont.MeasureString(toolTip); + int textWidth = (int)Math.Max(nameSize.X, toolTipSize.X); int textSpacing = (int)(15 * GUI.Scale); - Point shadowBorders = (new Point(40, 10)).Multiply(GUI.Scale); + + Vector2 textPos = itemPos; + int textDir = textPos.X + textWidth * 1.5f > GameMain.GraphicsWidth ? -1 : 1; + int textOffset = textDir == 1 ? 0 : -1; + textPos += new Vector2((iconSize / 2 + textSpacing) * textDir, 0); + + Point shadowPadding = new Point(40, 20).Multiply(GUI.Scale); + Point shadowSize = new Point(iconSize + textWidth + textSpacing, iconSize) + shadowPadding.Multiply(2); + shadowSprite.Draw(spriteBatch, - new Rectangle(itemPos.ToPoint() - new Point(iconSize / 2) - shadowBorders, new Point(iconSize + textWidth + textSpacing, iconSize) + shadowBorders.Multiply(2)), Color.Black * 0.8f); - GUI.DrawString(spriteBatch, new Vector2(itemPos.X + iconSize / 2 + textSpacing, itemPos.Y - iconSize / 2), DraggingItems.First().Name, Color.White); - GUI.DrawString(spriteBatch, new Vector2(itemPos.X + iconSize / 2 + textSpacing, itemPos.Y), toolTip, + new Rectangle(itemPos.ToPoint() - new Point((iconSize / 2 - shadowPadding.X) * textDir - shadowSize.X * textOffset, iconSize / 2 + shadowPadding.Y), shadowSize), Color.Black * 0.8f); + + GUI.DrawString(spriteBatch, textPos + new Vector2(nameSize.X * textOffset, -iconSize / 2), DraggingItems.First().Name, Color.White); + GUI.DrawString(spriteBatch, textPos + new Vector2(toolTipSize.X * textOffset, 0), toolTip, color: Character.Controlled.FocusedItem == null && !mouseOnHealthInterface ? GUIStyle.Red : Color.LightGreen, font: GUIStyle.SmallFont); } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Item.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Item.cs index 7431e8dda..8547be8c6 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Item.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Item.cs @@ -569,6 +569,36 @@ namespace Barotrauma } } + partial void Splash() + { + if (body == null || CurrentHull == null) { return; } + //create a splash particle + float massFactor = MathHelper.Clamp(body.Mass, 0.5f, 20.0f); + for (int i = 0; i < MathHelper.Clamp(Math.Abs(body.LinearVelocity.Y), 1.0f, 10.0f); i++) + { + var splash = GameMain.ParticleManager.CreateParticle("watersplash", + new Vector2(WorldPosition.X, CurrentHull.WorldSurface), + new Vector2(0.0f, Math.Abs(-body.LinearVelocity.Y * massFactor)) + Rand.Vector(Math.Abs(body.LinearVelocity.Y * 10)), + Rand.Range(0.0f, MathHelper.TwoPi), CurrentHull); + if (splash != null) + { + splash.Size *= MathHelper.Clamp(Math.Abs(body.LinearVelocity.Y) * 0.1f * massFactor, 1.0f, 4.0f); + } + } + GameMain.ParticleManager.CreateParticle("bubbles", + new Vector2(WorldPosition.X, CurrentHull.WorldSurface), + body.LinearVelocity * massFactor, + 0.0f, CurrentHull); + + //create a wave + if (body.LinearVelocity.Y < 0.0f) + { + int n = (int)((Position.X - CurrentHull.Rect.X) / Hull.WaveWidth); + CurrentHull.WaveVel[n] += MathHelper.Clamp(body.LinearVelocity.Y * massFactor, -5.0f, 5.0f); + } + SoundPlayer.PlaySplashSound(WorldPosition, Math.Abs(body.LinearVelocity.Y) + Rand.Range(-10.0f, -5.0f)); + } + public void CheckNeedsSoundUpdate(ItemComponent ic) { if (ic.NeedsSoundUpdate()) @@ -976,7 +1006,7 @@ namespace Barotrauma /// /// Reposition currently active item interfaces to make sure they don't overlap with each other /// - private void SetHUDLayout() + private void SetHUDLayout(bool ignoreLocking = false) { //reset positions first List elementsToMove = new List(); @@ -991,6 +1021,7 @@ namespace Barotrauma foreach (ItemComponent ic in activeHUDs) { if (ic.GuiFrame == null || ic.AllowUIOverlap || ic.GetLinkUIToComponent() != null) { continue; } + if (!ignoreLocking && ic.LockGuiFramePosition) { continue; } //if the frame covers nearly all of the screen, don't trying to prevent overlaps because it'd fail anyway if (ic.GuiFrame.Rect.Width >= GameMain.GraphicsWidth * 0.9f && ic.GuiFrame.Rect.Height >= GameMain.GraphicsHeight * 0.9f) { continue; } ic.GuiFrame.RectTransform.ScreenSpaceOffset = Point.Zero; @@ -1015,11 +1046,7 @@ namespace Barotrauma disallowedAreas.Add(editor.ToggleEntityMenuButton.Rect); } - GUI.PreventElementOverlap(elementsToMove, disallowedAreas, - new Rectangle( - 0, 20, - GameMain.GraphicsWidth, - HUDLayoutSettings.InventoryTopY > 0 ? HUDLayoutSettings.InventoryTopY - 40 : GameMain.GraphicsHeight - 80)); + GUI.PreventElementOverlap(elementsToMove, disallowedAreas, clampArea: HUDLayoutSettings.ItemHUDArea); //System.Diagnostics.Debug.WriteLine("after: " + elementsToMove[0].Rect.ToString() + " " + elementsToMove[1].Rect.ToString()); foreach (ItemComponent ic in activeHUDs) @@ -1239,6 +1266,24 @@ namespace Barotrauma return texts; } + public void ForceHUDLayoutUpdate(bool ignoreLocking = false) + { + foreach (ItemComponent ic in activeHUDs) + { + if (ic.GuiFrame == null || !ic.CanBeSelected) { continue; } + ic.GuiFrame.RectTransform.ScreenSpaceOffset = Point.Zero; + if (ic.UseAlternativeLayout) + { + ic.AlternativeLayout?.ApplyTo(ic.GuiFrame.RectTransform); + } + else + { + ic.DefaultLayout?.ApplyTo(ic.GuiFrame.RectTransform); + } + } + SetHUDLayout(ignoreLocking); + } + public override void AddToGUIUpdateList(int order = 0) { if (Screen.Selected is SubEditorScreen) diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/ItemPrefab.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/ItemPrefab.cs index 864384257..cedbfbf72 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/ItemPrefab.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/ItemPrefab.cs @@ -252,7 +252,7 @@ namespace Barotrauma if (placePosition == Vector2.Zero) { - if (PlayerInput.PrimaryMouseButtonHeld()) placePosition = position; + if (PlayerInput.PrimaryMouseButtonHeld() && GUI.MouseOn == null) { placePosition = position; } } else { @@ -270,11 +270,10 @@ namespace Barotrauma item.SetTransform(ConvertUnits.ToSimUnits(Submarine.MainSub == null ? item.Position : item.Position - Submarine.MainSub.Position), 0.0f); item.FindHull(); - //selected = null; + SubEditorScreen.StoreCommand(new AddOrDeleteCommand(new List { item }, false)); + return; } - - position = placePosition; } } @@ -282,22 +281,12 @@ namespace Barotrauma { potentialContainer.IsHighlighted = true; } - - - //if (PlayerInput.GetMouseState.RightButton == ButtonState.Pressed) selected = null; - } public override void DrawPlacing(SpriteBatch spriteBatch, Camera cam) { Vector2 position = Submarine.MouseToWorldGrid(cam, Submarine.MainSub); - if (PlayerInput.SecondaryMouseButtonClicked()) - { - Selected = null; - return; - } - if (!ResizeHorizontal && !ResizeVertical) { Sprite.Draw(spriteBatch, new Vector2(position.X, -position.Y) + Sprite.size / 2.0f * Scale, SpriteColor, scale: Scale); diff --git a/Barotrauma/BarotraumaClient/ClientSource/Map/Map/Map.cs b/Barotrauma/BarotraumaClient/ClientSource/Map/Map/Map.cs index 25e6141c5..278e3a36c 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Map/Map/Map.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Map/Map/Map.cs @@ -666,7 +666,7 @@ namespace Barotrauma GUI.DrawRectangle(spriteBatch, new Rectangle((int)dPos.X, (int)dPos.Y, 256, 32), Color.White); } dPos.Y += 48; - GUI.DrawString(spriteBatch, dPos, $"Difficulty: {location.LevelData.Difficulty.FormatZeroDecimal()}", Color.White, Color.Black * 0.8f, 4, font: GUIStyle.SmallFont); + GUI.DrawString(spriteBatch, dPos, $"Difficulty: {location.LevelData.Difficulty.FormatSingleDecimal()}", Color.White, Color.Black * 0.8f, 4, font: GUIStyle.SmallFont); } } } @@ -981,7 +981,7 @@ namespace Barotrauma Vector2 center = rectCenter + (connection.CenterPos + viewOffset) * zoom; if (viewArea.Contains(center) && connection.Biome != null) { - GUI.DrawString(spriteBatch, center, (connection.LevelData?.GenerationParams?.Identifier ?? connection.Biome.Identifier) + " (" + (int)connection.Difficulty + ")", Color.White); + GUI.DrawString(spriteBatch, center, (connection.LevelData?.GenerationParams?.Identifier ?? connection.Biome.Identifier) + " (" + connection.Difficulty.FormatSingleDecimal() + ")", Color.White); } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Map/MapEntity.cs b/Barotrauma/BarotraumaClient/ClientSource/Map/MapEntity.cs index b07a40828..c7a818db0 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Map/MapEntity.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Map/MapEntity.cs @@ -21,6 +21,7 @@ namespace Barotrauma private static float keyDelay; public static Vector2 StartMovingPos => startMovingPos; + public static Vector2 SelectionPos => selectionPos; public event Action Resized; @@ -128,7 +129,9 @@ namespace Barotrauma return; } - if (GUI.MouseOn != null || !PlayerInput.MouseInsideWindow) + if (startMovingPos == Vector2.Zero + && selectionPos == Vector2.Zero + && (GUI.MouseOn != null || !PlayerInput.MouseInsideWindow)) { if (highlightedListBox == null || (GUI.MouseOn != highlightedListBox && !highlightedListBox.IsParentOf(GUI.MouseOn))) @@ -738,15 +741,6 @@ namespace Barotrauma /// public static void DrawSelecting(SpriteBatch spriteBatch, Camera cam) { - if (Screen.Selected is SubEditorScreen subEditor) - { - if (subEditor.IsMouseOnEditorGUI()) { return; } - } - else if (GUI.MouseOn != null) - { - return; - } - Vector2 position = PlayerInput.MousePosition; position = cam.ScreenToWorld(position); @@ -819,7 +813,7 @@ namespace Barotrauma selectionPos = Vector2.Zero; } } - if (selectionPos != null && selectionPos != Vector2.Zero) + if (selectionPos != Vector2.Zero) { var (sizeX, sizeY) = selectionSize; var (posX, posY) = selectionPos; diff --git a/Barotrauma/BarotraumaClient/ClientSource/Map/MapEntityPrefab.cs b/Barotrauma/BarotraumaClient/ClientSource/Map/MapEntityPrefab.cs index daf65126a..d70dc4087 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Map/MapEntityPrefab.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Map/MapEntityPrefab.cs @@ -21,7 +21,7 @@ namespace Barotrauma { Vector2 position = Submarine.MouseToWorldGrid(cam, Submarine.MainSub); - if (PlayerInput.PrimaryMouseButtonHeld()) placePosition = position; + if (PlayerInput.PrimaryMouseButtonHeld() && GUI.MouseOn == null) placePosition = position; } else { @@ -39,7 +39,7 @@ namespace Barotrauma newRect.Location -= MathUtils.ToPoint(Submarine.MainSub.Position); } - if (PlayerInput.PrimaryMouseButtonReleased()) + if (PlayerInput.PrimaryMouseButtonReleased() && GUI.MouseOn == null) { CreateInstance(newRect); placePosition = Vector2.Zero; diff --git a/Barotrauma/BarotraumaClient/ClientSource/Map/StructurePrefab.cs b/Barotrauma/BarotraumaClient/ClientSource/Map/StructurePrefab.cs index ee708d2ef..9ff0f0d9e 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Map/StructurePrefab.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Map/StructurePrefab.cs @@ -27,7 +27,7 @@ namespace Barotrauma if (placePosition == Vector2.Zero) { - if (PlayerInput.PrimaryMouseButtonHeld()) + if (PlayerInput.PrimaryMouseButtonClicked() && GUI.MouseOn == null) placePosition = Submarine.MouseToWorldGrid(cam, Submarine.MainSub); newRect.X = (int)position.X; diff --git a/Barotrauma/BarotraumaClient/ClientSource/Media/Video.Internal.cs b/Barotrauma/BarotraumaClient/ClientSource/Media/Video.Internal.cs index 6e6ef4ec2..56e1509e8 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Media/Video.Internal.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Media/Video.Internal.cs @@ -3,7 +3,7 @@ using System.Runtime.InteropServices; namespace Barotrauma.Media { - public partial class Video : IDisposable + partial class Video : IDisposable { private static class Internal { diff --git a/Barotrauma/BarotraumaClient/ClientSource/Media/Video.cs b/Barotrauma/BarotraumaClient/ClientSource/Media/Video.cs index eaf0966b8..e22d634c1 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Media/Video.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Media/Video.cs @@ -11,7 +11,7 @@ using Barotrauma.Sounds; namespace Barotrauma.Media { - public partial class Video : IDisposable + partial class Video : IDisposable { private static Internal.EventCallback VideoFrameCallback; private static Internal.EventCallback VideoAudioCallback; diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/BanList.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/BanList.cs index 1e112d1df..23afe3580 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Networking/BanList.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/BanList.cs @@ -1,28 +1,28 @@ -using Barotrauma.Steam; -using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework; using System; using System.Collections.Generic; using System.Linq; -using System.Text; namespace Barotrauma.Networking { partial class BannedPlayer { - public BannedPlayer(string name, UInt16 uniqueIdentifier, bool isRangeBan, string endPoint, ulong steamID, string reason, DateTime? expiration) + public BannedPlayer( + UInt32 uniqueIdentifier, + string name, + Either addressOrAccountId, + string reason, + DateTime? expiration) { this.Name = name; - this.EndPoint = endPoint; - this.SteamID = steamID; - ParseEndPointAsSteamId(); - this.IsRangeBan = isRangeBan; + this.AddressOrAccountId = addressOrAccountId; this.UniqueIdentifier = uniqueIdentifier; this.Reason = reason; this.ExpirationTime = expiration; } } - public partial class BanList + partial class BanList { private GUIComponent banFrame; @@ -31,8 +31,7 @@ namespace Barotrauma.Networking get { return banFrame; } } - public List localRemovedBans = new List(); - public List localRangeBans = new List(); + public List localRemovedBans = new List(); private void RecreateBanFrame() { @@ -71,28 +70,22 @@ namespace Barotrauma.Networking RelativeSpacing = 0.02f }; - string endPoint = bannedPlayer.EndPoint; - if (localRangeBans.Contains(bannedPlayer.UniqueIdentifier)) endPoint = ToRange(endPoint); - GUITextBlock textBlock = new GUITextBlock(new RectTransform(new Vector2(0.5f, 0.0f), topArea.RectTransform), - bannedPlayer.Name + " (" + endPoint + ")"); - textBlock.RectTransform.MinSize = new Point(textBlock.Rect.Width, 0); + var addressOrAccountId = bannedPlayer.AddressOrAccountId; + GUITextBlock textBlock = new GUITextBlock( + new RectTransform(new Vector2(0.5f, 1.0f), topArea.RectTransform), + bannedPlayer.Name + " (" + addressOrAccountId + ")") { CanBeFocused = true }; + textBlock.RectTransform.MinSize = new Point( + (int)textBlock.Font.MeasureString(textBlock.Text.SanitizedValue).X, 0); - if (bannedPlayer.EndPoint.IndexOf(".x") <= -1) - { - var rangeBanButton = new GUIButton(new RectTransform(new Vector2(0.25f, 0.4f), topArea.RectTransform), - TextManager.Get("BanRange"), style: "GUIButtonSmall") - { - UserData = bannedPlayer, - OnClicked = RangeBan - }; - } var removeButton = new GUIButton(new RectTransform(new Vector2(0.2f, 0.4f), topArea.RectTransform), TextManager.Get("BanListRemove"), style: "GUIButtonSmall") { UserData = bannedPlayer, OnClicked = RemoveBan }; - topArea.RectTransform.MinSize = new Point(0, (int)topArea.RectTransform.Children.Max(c => c.Rect.Height * 1.25f)); + topArea.RectTransform.MinSize = new Point(0, (int)(removeButton.Rect.Height * 1.25f)); + + topArea.ForceLayoutRecalculation(); new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedPlayerFrame.RectTransform), bannedPlayer.ExpirationTime == null ? @@ -127,19 +120,6 @@ namespace Barotrauma.Networking return true; } - - private bool RangeBan(GUIButton button, object obj) - { - BannedPlayer banned = obj as BannedPlayer; - if (banned == null) { return false; } - - localRangeBans.Add(banned.UniqueIdentifier); - RecreateBanFrame(); - - GameMain.Client?.ServerSettings?.ClientAdminWrite(ServerSettings.NetFlags.Properties); - - return true; - } public void ClientAdminRead(IReadMessage incMsg) { @@ -159,8 +139,7 @@ namespace Barotrauma.Networking for (int i = 0; i < (int)bannedPlayerCount; i++) { string name = incMsg.ReadString(); - UInt16 uniqueIdentifier = incMsg.ReadUInt16(); - bool isRangeBan = incMsg.ReadBoolean(); + UInt32 uniqueIdentifier = incMsg.ReadUInt32(); bool includesExpiration = incMsg.ReadBoolean(); incMsg.ReadPadBits(); @@ -173,19 +152,30 @@ namespace Barotrauma.Networking string reason = incMsg.ReadString(); - string endPoint = ""; - UInt64 steamID = 0; + Either addressOrAccountId; if (isOwner) { - endPoint = incMsg.ReadString(); - steamID = incMsg.ReadUInt64(); + bool isAddress = incMsg.ReadBoolean(); + incMsg.ReadPadBits(); + string str = incMsg.ReadString(); + if (isAddress && Address.Parse(str).TryUnwrap(out var address)) + { + addressOrAccountId = address; + } + else if (AccountId.Parse(str).TryUnwrap(out var accountId)) + { + addressOrAccountId = accountId; + } + else + { + continue; + } } else { - endPoint = "Endpoint concealed by host"; - steamID = 0; + addressOrAccountId = new UnknownAddress(); } - bannedPlayers.Add(new BannedPlayer(name, uniqueIdentifier, isRangeBan, endPoint, steamID, reason, expiration)); + bannedPlayers.Add(new BannedPlayer(uniqueIdentifier, name, addressOrAccountId, reason, expiration)); } if (banFrame != null) @@ -198,20 +188,13 @@ namespace Barotrauma.Networking public void ClientAdminWrite(IWriteMessage outMsg) { - outMsg.Write((UInt16)localRemovedBans.Count); - foreach (UInt16 uniqueId in localRemovedBans) - { - outMsg.Write(uniqueId); - } - - outMsg.Write((UInt16)localRangeBans.Count); - foreach (UInt16 uniqueId in localRangeBans) + outMsg.WriteVariableUInt32((UInt32)localRemovedBans.Count); + foreach (UInt32 uniqueId in localRemovedBans) { outMsg.Write(uniqueId); } localRemovedBans.Clear(); - localRangeBans.Clear(); } } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/ChatMessage.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/ChatMessage.cs index a020b263a..ec7909d75 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Networking/ChatMessage.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/ChatMessage.cs @@ -35,8 +35,9 @@ namespace Barotrauma.Networking bool hasSenderClient = msg.ReadBoolean(); if (hasSenderClient) { - UInt64 clientId = msg.ReadUInt64(); - senderClient = GameMain.Client.ConnectedClients.Find(c => c.SteamID == clientId || c.ID == clientId); + string userId = msg.ReadString(); + senderClient = GameMain.Client.ConnectedClients.Find(c + => c.SessionOrAccountIdMatches(userId)); if (senderClient != null) { senderName = senderClient.Name; } } bool hasSenderCharacter = msg.ReadBoolean(); diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/Client.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/Client.cs index f9348813e..480fa90cc 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Networking/Client.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/Client.cs @@ -72,8 +72,8 @@ namespace Barotrauma.Networking partial void InitProjSpecific() { VoipQueue = null; VoipSound = null; - if (ID == GameMain.Client.ID) return; - VoipQueue = new VoipQueue(ID, false, true); + if (SessionId == GameMain.Client.SessionId) { return; } + VoipQueue = new VoipQueue(SessionId, canSend: false, canReceive: true); GameMain.Client?.VoipClient?.RegisterQueue(VoipQueue); VoipSound = null; } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/FileTransfer/FileReceiver.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/FileTransfer/FileReceiver.cs index 1a0efc16c..59be7ad9e 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Networking/FileTransfer/FileReceiver.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/FileTransfer/FileReceiver.cs @@ -206,7 +206,7 @@ namespace Barotrauma.Networking case (byte)FileTransferMessageType.Initiate: { byte transferId = inc.ReadByte(); - var existingTransfer = activeTransfers.Find(t => t.Connection.EndpointMatches(t.Connection.EndPointString) && t.ID == transferId); + var existingTransfer = activeTransfers.Find(t => t.Connection.EndpointMatches(t.Connection.Endpoint) && t.ID == transferId); finishedTransfers.RemoveAll(t => t.transferId == transferId); byte fileType = inc.ReadByte(); //ushort chunkLen = inc.ReadUInt16(); @@ -329,7 +329,7 @@ namespace Barotrauma.Networking { byte transferId = inc.ReadByte(); - var activeTransfer = activeTransfers.Find(t => t.Connection.EndpointMatches(t.Connection.EndPointString) && t.ID == transferId); + var activeTransfer = activeTransfers.Find(t => t.Connection.EndpointMatches(t.Connection.Endpoint) && t.ID == transferId); if (activeTransfer == null) { //it's possible for the server to send some extra data @@ -406,7 +406,7 @@ namespace Barotrauma.Networking case (byte)FileTransferMessageType.Cancel: { byte transferId = inc.ReadByte(); - var matchingTransfer = activeTransfers.Find(t => t.Connection.EndpointMatches(t.Connection.EndPointString) && t.ID == transferId); + var matchingTransfer = activeTransfers.Find(t => t.Connection.EndpointMatches(t.Connection.Endpoint) && t.ID == transferId); if (matchingTransfer != null) { new GUIMessageBox("File transfer cancelled", "The server has cancelled the transfer of the file \"" + matchingTransfer.FileName + "\"."); diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/GameClient.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/GameClient.cs index 532928c46..9a04ff9e6 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Networking/GameClient.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/GameClient.cs @@ -1,18 +1,16 @@ -using Barotrauma.Items.Components; +using Barotrauma.Extensions; +using Barotrauma.IO; +using Barotrauma.Items.Components; using Barotrauma.Steam; using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Input; using System; using System.Collections.Generic; using System.Collections.Immutable; -using Barotrauma.IO; -using System.IO.Compression; using System.Linq; -using System.Text; using System.Threading; using System.Threading.Tasks; using System.Xml.Linq; -using Barotrauma.Extensions; -using Microsoft.Xna.Framework.Input; namespace Barotrauma.Networking { @@ -23,14 +21,9 @@ namespace Barotrauma.Networking get { return true; } } - private string name; - private UInt16 nameId = 0; - public string Name - { - get { return name; } - } + public string Name { get; private set; } public string PendingName = string.Empty; @@ -38,7 +31,7 @@ namespace Barotrauma.Networking { value = value.Replace(":", "").Replace(";", ""); if (string.IsNullOrEmpty(value)) { return; } - name = value; + Name = value; nameId++; } @@ -89,13 +82,11 @@ namespace Barotrauma.Networking public bool RoundStarting => roundInitStatus == RoundInitStatus.Starting || roundInitStatus == RoundInitStatus.WaitingForStartGameFinalize; - private byte myID; - private readonly List otherClients; public readonly List ServerSubmarines = new List(); - private string serverIP, serverName; + public string ServerName { get; private set; } private bool allowReconnect; private bool requiresPw; @@ -129,10 +120,7 @@ namespace Barotrauma.Networking public LocalizedString TraitorFirstObjective; public TraitorMissionPrefab TraitorMission = null; - public byte ID - { - get { return myID; } - } + public byte SessionId { get; private set; } public VoipClient VoipClient { @@ -140,7 +128,7 @@ namespace Barotrauma.Networking private set; } - public override List ConnectedClients + public override IReadOnlyList ConnectedClients { get { @@ -175,14 +163,10 @@ namespace Barotrauma.Networking set; } - private readonly object serverEndpoint; - private readonly int ownerKey; - private readonly bool steamP2POwner; + private readonly Endpoint serverEndpoint; + private readonly Option ownerKey; - public bool IsServerOwner - { - get { return ownerKey > 0 || steamP2POwner; } - } + public bool IsServerOwner => ownerKey.IsSome(); internal readonly struct PermissionChangedEvent { @@ -198,11 +182,10 @@ namespace Barotrauma.Networking public readonly NamedEvent OnPermissionChanged = new NamedEvent(); - public GameClient(string newName, string ip, UInt64 steamId, string serverName = null, int ownerKey = 0, bool steamP2POwner = false) + public GameClient(string newName, Endpoint endpoint, string serverName, Option ownerKey) { //TODO: gui stuff should probably not be here? this.ownerKey = ownerKey; - this.steamP2POwner = steamP2POwner; roundInitStatus = RoundInitStatus.NotStarted; @@ -280,7 +263,7 @@ namespace Barotrauma.Networking fileReceiver.OnFinished += OnFileReceived; fileReceiver.OnTransferFailed += OnTransferFailed; - characterInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, name, null) + characterInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, Name, originalName: null) { Job = null }; @@ -290,15 +273,8 @@ namespace Barotrauma.Networking serverSettings = new ServerSettings(this, "Server", 0, 0, 0, false, false); Voting = new Voting(); - if (steamId == 0) - { - serverEndpoint = ip; - } - else - { - serverEndpoint = steamId; - } - ConnectToServer(serverEndpoint, serverName); + serverEndpoint = endpoint; + InitiateServerJoin(serverName); //ServerLog = new ServerLog(""); @@ -306,7 +282,7 @@ namespace Barotrauma.Networking GameMain.ResetNetLobbyScreen(); } - private void ConnectToServer(object endpoint, string hostName) + private void InitiateServerJoin(string hostName) { LastClientListUpdateID = 0; @@ -315,7 +291,7 @@ namespace Barotrauma.Networking GameMain.NetLobbyScreen.RemovePlayer(c); c.Dispose(); } - ConnectedClients.Clear(); + otherClients.Clear(); chatBox.InputBox.Enabled = false; if (GameMain.NetLobbyScreen?.ChatInput != null) @@ -323,102 +299,48 @@ namespace Barotrauma.Networking GameMain.NetLobbyScreen.ChatInput.Enabled = false; } - serverName = hostName; + ServerName = hostName; myCharacter = Character.Controlled; ChatMessage.LastID = 0; clientPeer?.Close(); - clientPeer = null; - object translatedEndpoint = null; - if (endpoint is string hostIP) - { - int port; - string[] address = hostIP.Split(':'); - if (address.Length == 1) - { - serverIP = hostIP; - port = NetConfig.DefaultPort; - } - else - { - serverIP = string.Join(":", address.Take(address.Length - 1)); - if (!int.TryParse(address[address.Length - 1], out port)) - { - DebugConsole.ThrowError("Invalid port: " + address[address.Length - 1] + "!"); - port = NetConfig.DefaultPort; - } - } - - clientPeer = new LidgrenClientPeer(Name); - - System.Net.IPEndPoint IPEndPoint = null; - try - { - IPEndPoint = new System.Net.IPEndPoint(Lidgren.Network.NetUtility.Resolve(serverIP), port); - } - catch - { - new GUIMessageBox(TextManager.Get("CouldNotConnectToServer"), - TextManager.GetWithVariables("InvalidIPAddress", ("[serverip]", serverIP), ("[port]", port.ToString()))); - return; - } - - translatedEndpoint = IPEndPoint; - } - else if (endpoint is UInt64) - { - if (steamP2POwner) - { - clientPeer = new SteamP2POwnerPeer(Name); - } - else - { - clientPeer = new SteamP2PClientPeer(Name); - } - - translatedEndpoint = endpoint; - } - clientPeer.OnDisconnect = OnDisconnect; - clientPeer.OnDisconnectMessageReceived = HandleDisconnectMessage; - clientPeer.OnInitializationComplete = OnConnectionInitializationComplete; - clientPeer.OnRequestPassword = (int salt, int retries) => - { - if (pwRetries != retries) - { - wrongPassword = retries > 0; - requiresPw = true; - } - pwRetries = retries; - }; - clientPeer.OnMessageReceived = ReadDataMessage; - - // Connect client, to endpoint previously requested from user - try - { - clientPeer.Start(translatedEndpoint, ownerKey); - } - catch (Exception e) - { - DebugConsole.ThrowError("Couldn't connect to " + endpoint.ToString() + ". Error message: " + e.Message); - Disconnect(); - chatBox.InputBox.Enabled = true; - if (GameMain.NetLobbyScreen?.ChatInput != null) - { - GameMain.NetLobbyScreen.ChatInput.Enabled = true; - } - GameMain.ServerListScreen.Select(); - return; - } + clientPeer = CreateNetPeer(); + clientPeer.Start(); updateInterval = new TimeSpan(0, 0, 0, 0, 150); CoroutineManager.StartCoroutine(WaitForStartingInfo(), "WaitForStartingInfo"); } + private ClientPeer CreateNetPeer() + { + Networking.ClientPeer.Callbacks callbacks = new ClientPeer.Callbacks( + ReadDataMessage, + OnClientPeerDisconnect, + HandleDisconnectMessage, + (int salt, int retries) => + { + if (pwRetries != retries) + { + wrongPassword = retries > 0; + requiresPw = true; + } + pwRetries = retries; + }, + OnConnectionInitializationComplete); + return serverEndpoint switch + { + LidgrenEndpoint lidgrenEndpoint => new LidgrenClientPeer(lidgrenEndpoint, callbacks, ownerKey), + SteamP2PEndpoint _ when ownerKey is Some { Value: var key } => new SteamP2POwnerPeer(callbacks, key), + SteamP2PEndpoint steamP2PServerEndpoint when ownerKey.IsNone() => new SteamP2PClientPeer(steamP2PServerEndpoint, callbacks), + _ => throw new ArgumentOutOfRangeException() + }; + } + private bool ReturnToPreviousMenu(GUIButton button, object obj) { - Disconnect(); + Quit(); Submarine.Unload(); GameMain.Client = null; @@ -442,7 +364,7 @@ namespace Barotrauma.Networking { ChildServerRelay.ShutDown(); connectCancelled = true; - Disconnect(); + Quit(); } private bool wrongPassword; @@ -467,14 +389,13 @@ namespace Barotrauma.Networking { if (reconnectBox == null && waitInServerQueueBox == null) { - string serverDisplayName = serverName; - if (string.IsNullOrEmpty(serverDisplayName)) { serverDisplayName = serverIP; } + string serverDisplayName = ServerName; if (string.IsNullOrEmpty(serverDisplayName) && clientPeer?.ServerConnection is SteamP2PConnection steamConnection) { - serverDisplayName = steamConnection.SteamID.ToString(); - if (SteamManager.IsInitialized) + if (SteamManager.IsInitialized && steamConnection.AccountInfo.AccountId.TryUnwrap(out var accountId) && accountId is SteamId steamId) { - string steamUserName = Steamworks.SteamFriends.GetFriendPersonaName(steamConnection.SteamID); + serverDisplayName = steamId.ToString(); + string steamUserName = Steamworks.SteamFriends.GetFriendPersonaName(steamId.Value); if (!string.IsNullOrEmpty(steamUserName) && steamUserName != "[unknown]") { serverDisplayName = steamUserName; @@ -604,7 +525,7 @@ namespace Barotrauma.Networking { if (VoipCapture.Instance.LastEnqueueAudio > DateTime.Now - new TimeSpan(0, 0, 0, 0, milliseconds: 100)) { - var myClient = ConnectedClients.Find(c => c.ID == ID); + var myClient = ConnectedClients.Find(c => c.SessionId == SessionId); if (Screen.Selected == GameMain.NetLobbyScreen) { GameMain.NetLobbyScreen.SetPlayerSpeaking(myClient); @@ -645,7 +566,7 @@ namespace Barotrauma.Networking GameAnalyticsManager.AddErrorEventOnce("GameClient.Update:CheckServerMessagesException" + e.TargetSite.ToString(), GameAnalyticsManager.ErrorSeverity.Error, errorMsg); DebugConsole.ThrowError("Error while reading a message from server.", e); new GUIMessageBox(TextManager.Get("Error"), TextManager.GetWithVariables("MessageReadError", ("[message]", e.Message), ("[targetsite]", e.TargetSite.ToString()))); - Disconnect(); + Quit(); GameMain.ServerListScreen.Select(); return; } @@ -688,7 +609,7 @@ namespace Barotrauma.Networking { if (ChildServerRelay.Process?.HasExited ?? true) { - Disconnect(); + Quit(); if (!GUIMessageBox.MessageBoxes.Any(mb => (mb as GUIMessageBox)?.Text?.Text == ChildServerRelay.CrashMessage)) { var msgBox = new GUIMessageBox(TextManager.Get("ConnectionLost"), ChildServerRelay.CrashMessage); @@ -769,7 +690,7 @@ namespace Barotrauma.Networking { byte clientId = inc.ReadByte(); UInt16 clientPing = inc.ReadUInt16(); - Client client = ConnectedClients.Find(c => c.ID == clientId); + Client client = ConnectedClients.Find(c => c.SessionId == clientId); if (client != null) { client.Ping = clientPing; @@ -1079,16 +1000,15 @@ namespace Barotrauma.Networking roundInitStatus = RoundInitStatus.Started; } - - private void OnDisconnect(bool disableReconnect) + /// + /// Fires when the ClientPeer gets disconnected from the server. Does not necessarily mean the client is shutting down, we may still be able to reconnect. + /// + private void OnClientPeerDisconnect(bool disableReconnect) { CoroutineManager.StopCoroutines("WaitForStartingInfo"); reconnectBox?.Close(); reconnectBox = null; - GameMain.ModDownloadScreen.Reset(); - ContentPackageManager.EnabledPackages.Restore(); - GUI.ClearCursorWait(); if (disableReconnect) { allowReconnect = false; } @@ -1125,7 +1045,6 @@ namespace Barotrauma.Networking if (disconnectReason != DisconnectReason.Banned && disconnectReason != DisconnectReason.ServerShutdown && disconnectReason != DisconnectReason.TooManyFailedLogins && - disconnectReason != DisconnectReason.NotOnWhitelist && disconnectReason != DisconnectReason.MissingContentPackage && disconnectReason != DisconnectReason.InvalidVersion) { @@ -1197,14 +1116,16 @@ namespace Barotrauma.Networking reconnectBox?.Close(); reconnectBox = new GUIMessageBox( TextManager.Get("ConnectionLost"), msg, - new LocalizedString[] { TextManager.Get("Cancel") }); - reconnectBox.Buttons[0].OnClicked += (btn, userdata) => { CancelConnect(); return true; }; + new LocalizedString[] { TextManager.Get("Cancel") }) + { + DisplayInLoadingScreens = true + }; + reconnectBox.Buttons[0].OnClicked += ReturnToPreviousMenu; connected = false; - var prevContentPackages = clientPeer.ServerContentPackages; //decrement lobby update ID to make sure we update the lobby when we reconnect GameMain.NetLobbyScreen.LastUpdateID--; - ConnectToServer(serverEndpoint, serverName); + InitiateServerJoin(ServerName); if (clientPeer != null) { //restore the previous list of content packages so we can reconnect immediately without having to recheck that the packages match @@ -1243,12 +1164,18 @@ namespace Barotrauma.Networking if (msg == Lidgren.Network.NetConnection.NoResponseMessage) { //display a generic "could not connect" popup if the message is Lidgren's "failed to establish connection" - var msgBox = new GUIMessageBox(TextManager.Get("ConnectionFailed"), TextManager.Get(allowReconnect ? "ConnectionLost" : "CouldNotConnectToServer")); + var msgBox = new GUIMessageBox(TextManager.Get("ConnectionFailed"), TextManager.Get(allowReconnect ? "ConnectionLost" : "CouldNotConnectToServer")) + { + DisplayInLoadingScreens = true + }; msgBox.Buttons[0].OnClicked += ReturnToPreviousMenu; } else { - var msgBox = new GUIMessageBox(TextManager.Get(allowReconnect ? "ConnectionLost" : "CouldNotConnectToServer"), msg); + var msgBox = new GUIMessageBox(TextManager.Get(allowReconnect ? "ConnectionLost" : "CouldNotConnectToServer"), msg) + { + DisplayInLoadingScreens = true + }; msgBox.Buttons[0].OnClicked += ReturnToPreviousMenu; } @@ -1266,8 +1193,8 @@ namespace Barotrauma.Networking if (SteamManager.IsInitialized) { Steamworks.SteamFriends.ClearRichPresence(); - Steamworks.SteamFriends.SetRichPresence("status", "Playing on " + serverName); - Steamworks.SteamFriends.SetRichPresence("connect", "-connect \"" + serverName.Replace("\"", "\\\"") + "\" " + serverEndpoint); + Steamworks.SteamFriends.SetRichPresence("status", "Playing on " + ServerName); + Steamworks.SteamFriends.SetRichPresence("connect", "-connect \"" + ServerName.Replace("\"", "\\\"") + "\" " + serverEndpoint); } canStart = true; @@ -1275,7 +1202,7 @@ namespace Barotrauma.Networking VoipClient = new VoipClient(this, clientPeer); - if (Screen.Selected != GameMain.GameScreen) + if (Screen.Selected != GameMain.GameScreen && !(Screen.Selected is RoundSummaryScreen)) { GameMain.ModDownloadScreen.Select(); } @@ -1312,7 +1239,7 @@ namespace Barotrauma.Networking { if (!CoroutineManager.IsCoroutineRunning("WaitForStartingInfo")) { - ConnectToServer(serverEndpoint, serverName); + InitiateServerJoin(ServerName); yield return new WaitForSeconds(5.0f); } yield return new WaitForSeconds(0.5f); @@ -1383,15 +1310,15 @@ namespace Barotrauma.Networking private void ReadPermissions(IReadMessage inc) { List permittedConsoleCommands = new List(); - byte clientID = inc.ReadByte(); + byte clientId = inc.ReadByte(); ClientPermissions permissions = ClientPermissions.None; List permittedCommands = new List(); Client.ReadPermissions(inc, out permissions, out permittedCommands); - Client targetClient = ConnectedClients.Find(c => c.ID == clientID); + Client targetClient = ConnectedClients.Find(c => c.SessionId == clientId); targetClient?.SetPermissions(permissions, permittedCommands); - if (clientID == myID) + if (clientId == SessionId) { SetMyPermissions(permissions, permittedCommands.Select(command => command.names[0])); } @@ -1923,7 +1850,7 @@ namespace Barotrauma.Networking private void ReadInitialUpdate(IReadMessage inc) { - myID = inc.ReadByte(); + SessionId = inc.ReadByte(); UInt16 subListCount = inc.ReadUInt16(); ServerSubmarines.Clear(); @@ -1983,22 +1910,22 @@ namespace Barotrauma.Networking foreach (TempClient tc in tempClients) { //see if the client already exists - var existingClient = ConnectedClients.Find(c => c.ID == tc.ID && c.Name == tc.Name); + var existingClient = ConnectedClients.Find(c => c.SessionId == tc.SessionId && c.Name == tc.Name); if (existingClient == null) //if not, create it { - existingClient = new Client(tc.Name, tc.ID) + existingClient = new Client(tc.Name, tc.SessionId) { - SteamID = tc.SteamID, + AccountInfo = tc.AccountInfo, Muted = tc.Muted, InGame = tc.InGame, AllowKicking = tc.AllowKicking, IsOwner = tc.IsOwner }; - ConnectedClients.Add(existingClient); + otherClients.Add(existingClient); refreshCampaignUI = true; GameMain.NetLobbyScreen.AddPlayer(existingClient); } - existingClient.NameID = tc.NameID; + existingClient.NameId = tc.NameId; existingClient.PreferredJob = tc.PreferredJob; existingClient.PreferredTeam = tc.PreferredTeam; existingClient.Character = null; @@ -2009,22 +1936,22 @@ namespace Barotrauma.Networking existingClient.AllowKicking = tc.AllowKicking; existingClient.IsDownloading = tc.IsDownloading; GameMain.NetLobbyScreen.SetPlayerNameAndJobPreference(existingClient); - if (Screen.Selected != GameMain.NetLobbyScreen && tc.CharacterID > 0) + if (Screen.Selected != GameMain.NetLobbyScreen && tc.CharacterId > 0) { - existingClient.CharacterID = tc.CharacterID; + existingClient.CharacterID = tc.CharacterId; } - if (existingClient.ID == myID) + if (existingClient.SessionId == SessionId) { existingClient.SetPermissions(permissions, permittedConsoleCommands); - if (!NetIdUtils.IdMoreRecent(nameId, tc.NameID)) + if (!NetIdUtils.IdMoreRecent(nameId, tc.NameId)) { - name = tc.Name; - nameId = tc.NameID; + Name = tc.Name; + nameId = tc.NameId; } if (GameMain.NetLobbyScreen.CharacterNameBox != null && !GameMain.NetLobbyScreen.CharacterNameBox.Selected) { - GameMain.NetLobbyScreen.CharacterNameBox.Text = name; + GameMain.NetLobbyScreen.CharacterNameBox.Text = Name; } } currentClients.Add(existingClient); @@ -2035,14 +1962,14 @@ namespace Barotrauma.Networking if (!currentClients.Contains(ConnectedClients[i])) { GameMain.NetLobbyScreen.RemovePlayer(ConnectedClients[i]); - ConnectedClients[i].Dispose(); - ConnectedClients.RemoveAt(i); + otherClients[i].Dispose(); + otherClients.RemoveAt(i); refreshCampaignUI = true; } } foreach (Client client in ConnectedClients) { - int index = previouslyConnectedClients.FindIndex(c => c.ID == client.ID); + int index = previouslyConnectedClients.FindIndex(c => c.SessionId == client.SessionId); if (index < 0) { if (previouslyConnectedClients.Count > 100) @@ -2405,7 +2332,7 @@ namespace Barotrauma.Networking outmsg.Write(ChatMessage.LastID); outmsg.Write(LastClientListUpdateID); outmsg.Write(nameId); - outmsg.Write(name); + outmsg.Write(Name); var jobPreferences = GameMain.NetLobbyScreen.JobPreferences; if (jobPreferences.Count > 0) { @@ -2519,7 +2446,7 @@ namespace Barotrauma.Networking if (clientPeer?.ServerConnection == null) { return; } ChatMessage chatMessage = ChatMessage.Create( - gameStarted && myCharacter != null ? myCharacter.Name : name, + gameStarted && myCharacter != null ? myCharacter.Name : Name, message, type, gameStarted && myCharacter != null ? myCharacter : null); @@ -2761,7 +2688,7 @@ namespace Barotrauma.Networking return false; } - public override void Disconnect() + public override void Quit() { allowReconnect = false; @@ -2770,6 +2697,9 @@ namespace Barotrauma.Networking SteamManager.LeaveLobby(); } + GameMain.ModDownloadScreen.Reset(); + ContentPackageManager.EnabledPackages.Restore(); + CampaignMode.StartRoundCancellationToken?.Cancel(); clientPeer?.Close(); @@ -2864,7 +2794,7 @@ namespace Barotrauma.Networking public void VoteForKick(Client votedClient) { if (votedClient == null) { return; } - votedClient.AddKickVote(ConnectedClients.FirstOrDefault(c => c.ID == myID)); + votedClient.AddKickVote(ConnectedClients.FirstOrDefault(c => c.SessionId == SessionId)); Vote(VoteType.Kick, votedClient); } @@ -2918,26 +2848,35 @@ namespace Barotrauma.Networking clientPeer.Send(msg, DeliveryMethod.Reliable); } - public override void BanPlayer(string kickedName, string reason, bool range = false, TimeSpan? duration = null) + public override void BanPlayer(string kickedName, string reason, TimeSpan? duration = null) { IWriteMessage msg = new WriteOnlyMessage(); msg.Write((byte)ClientPacketHeader.SERVER_COMMAND); msg.Write((UInt16)ClientPermissions.Ban); msg.Write(kickedName); msg.Write(reason); - msg.Write(range); msg.Write(duration.HasValue ? duration.Value.TotalSeconds : 0.0); //0 = permaban clientPeer.Send(msg, DeliveryMethod.Reliable); } - public override void UnbanPlayer(string playerName, string playerIP) + public override void UnbanPlayer(string playerName) { IWriteMessage msg = new WriteOnlyMessage(); msg.Write((byte)ClientPacketHeader.SERVER_COMMAND); msg.Write((UInt16)ClientPermissions.Unban); - msg.Write(string.IsNullOrEmpty(playerName) ? "" : playerName); - msg.Write(string.IsNullOrEmpty(playerIP) ? "" : playerIP); + msg.Write(true); msg.WritePadBits(); + msg.Write(playerName); + clientPeer.Send(msg, DeliveryMethod.Reliable); + } + + public override void UnbanPlayer(Endpoint endpoint) + { + IWriteMessage msg = new WriteOnlyMessage(); + msg.Write((byte)ClientPacketHeader.SERVER_COMMAND); + msg.Write((UInt16)ClientPermissions.Unban); + msg.Write(false); msg.WritePadBits(); + msg.Write(endpoint.StringRepresentation); clientPeer.Send(msg, DeliveryMethod.Reliable); } @@ -3470,7 +3409,7 @@ namespace Barotrauma.Networking public virtual bool SelectCrewClient(Client client, GUIComponent frame) { - if (client == null || client.ID == ID) { return false; } + if (client == null || client.SessionId == SessionId) { return false; } CreateSelectionRelatedButtons(client, frame); return true; } @@ -3543,12 +3482,12 @@ namespace Barotrauma.Networking }; if (GameMain.NetworkMember.ConnectedClients != null) { - kickVoteButton.Enabled = !client.HasKickVoteFromID(myID); + kickVoteButton.Enabled = !client.HasKickVoteFromSessionId(SessionId); } } } - public void CreateKickReasonPrompt(string clientName, bool ban, bool rangeBan = false) + public void CreateKickReasonPrompt(string clientName, bool ban) { var banReasonPrompt = new GUIMessageBox( TextManager.Get(ban ? "BanReasonPrompt" : "KickReasonPrompt"), @@ -3609,11 +3548,11 @@ namespace Barotrauma.Networking if (!permaBanTickBox.Selected) { TimeSpan banDuration = new TimeSpan(durationInputDays.IntValue, durationInputHours.IntValue, 0, 0); - BanPlayer(clientName, banReasonBox.Text, ban, banDuration); + BanPlayer(clientName, banReasonBox.Text, banDuration); } else { - BanPlayer(clientName, banReasonBox.Text, range: rangeBan); + BanPlayer(clientName, banReasonBox.Text); } } else @@ -3626,7 +3565,7 @@ namespace Barotrauma.Networking banReasonPrompt.Buttons[1].OnClicked += banReasonPrompt.Close; } - public void ReportError(ClientNetError error, UInt16 expectedID = 0, UInt16 eventID = 0, UInt16 entityID = 0) + public void ReportError(ClientNetError error, UInt16 expectedId = 0, UInt16 eventId = 0, UInt16 entityId = 0) { IWriteMessage outMsg = new WriteOnlyMessage(); outMsg.Write((byte)ClientPacketHeader.ERROR); @@ -3634,12 +3573,12 @@ namespace Barotrauma.Networking switch (error) { case ClientNetError.MISSING_EVENT: - outMsg.Write(expectedID); - outMsg.Write(eventID); + outMsg.Write(expectedId); + outMsg.Write(eventId); break; case ClientNetError.MISSING_ENTITY: - outMsg.Write(eventID); - outMsg.Write(entityID); + outMsg.Write(eventId); + outMsg.Write(entityId); outMsg.Write((byte)Submarine.Loaded.Count); foreach (Submarine sub in Submarine.Loaded) { @@ -3651,7 +3590,7 @@ namespace Barotrauma.Networking if (!eventErrorWritten) { - WriteEventErrorData(error, expectedID, eventID, entityID); + WriteEventErrorData(error, expectedId, eventId, entityId); eventErrorWritten = true; } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/NetEntityEvent/ClientEntityEventManager.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/NetEntityEvent/ClientEntityEventManager.cs index 50486ace0..929701014 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Networking/NetEntityEvent/ClientEntityEventManager.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/NetEntityEvent/ClientEntityEventManager.cs @@ -203,7 +203,7 @@ namespace Barotrauma.Networking DebugConsole.NewMessage( "Received msg " + thisEventID + ", entity " + entityID + " not found", GUIStyle.Red); - GameMain.Client.ReportError(ClientNetError.MISSING_ENTITY, eventID: thisEventID, entityID: entityID); + GameMain.Client.ReportError(ClientNetError.MISSING_ENTITY, eventId: thisEventID, entityId: entityID); return false; } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/Primitives/Peers/ClientPeer.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/Primitives/Peers/ClientPeer.cs index f39baaaec..b7aa17ec1 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Networking/Primitives/Peers/ClientPeer.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/Primitives/Peers/ClientPeer.cs @@ -1,11 +1,9 @@ -using Barotrauma.Extensions; +#nullable enable using Barotrauma.Steam; using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; -using System.Reflection; -using System.Text; namespace Barotrauma.Networking { @@ -18,7 +16,7 @@ namespace Barotrauma.Networking public readonly UInt64 WorkshopId; public readonly DateTime InstallTime; - public RegularPackage RegularPackage + public RegularPackage? RegularPackage { get { @@ -26,7 +24,7 @@ namespace Barotrauma.Networking } } - public CorePackage CorePackage + public CorePackage? CorePackage { get { @@ -34,8 +32,8 @@ namespace Barotrauma.Networking } } - public ContentPackage ContentPackage - => (ContentPackage)RegularPackage ?? CorePackage; + public ContentPackage? ContentPackage + => (ContentPackage?)RegularPackage ?? CorePackage; public string GetPackageStr() @@ -58,21 +56,44 @@ namespace Barotrauma.Networking public delegate void DisconnectMessageCallback(string message); public delegate void PasswordCallback(int salt, int retries); public delegate void InitializationCompleteCallback(); + + [Obsolete("TODO: delete in nr3-layer-1-2-cleanup")] + public readonly struct Callbacks + { + public readonly MessageCallback OnMessageReceived; + public readonly DisconnectCallback OnDisconnect; + public readonly DisconnectMessageCallback OnDisconnectMessageReceived; + public readonly PasswordCallback OnRequestPassword; + public readonly InitializationCompleteCallback OnInitializationComplete; + + public Callbacks(MessageCallback onMessageReceived, DisconnectCallback onDisconnect, DisconnectMessageCallback onDisconnectMessageReceived, PasswordCallback onRequestPassword, InitializationCompleteCallback onInitializationComplete) + { + OnMessageReceived = onMessageReceived; + OnDisconnect = onDisconnect; + OnDisconnectMessageReceived = onDisconnectMessageReceived; + OnRequestPassword = onRequestPassword; + OnInitializationComplete = onInitializationComplete; + } + } + + protected readonly Callbacks callbacks; + + public readonly Endpoint ServerEndpoint; + public NetworkConnection? ServerConnection { get; protected set; } + + protected readonly bool isOwner; + protected readonly Option ownerKey; + + public ClientPeer(Endpoint serverEndpoint, Callbacks callbacks, Option ownerKey) + { + ServerEndpoint = serverEndpoint; + this.callbacks = callbacks; + this.ownerKey = ownerKey; + isOwner = ownerKey.IsSome(); + } - public MessageCallback OnMessageReceived; - public DisconnectCallback OnDisconnect; - public DisconnectMessageCallback OnDisconnectMessageReceived; - public PasswordCallback OnRequestPassword; - public InitializationCompleteCallback OnInitializationComplete; - - public string Name; - - public string Version { get; protected set; } - - public NetworkConnection ServerConnection { get; protected set; } - - public abstract void Start(object endPoint, int ownerKey); - public abstract void Close(string msg = null, bool disableReconnect = false); + public abstract void Start(); + public abstract void Close(string? msg = null, bool disableReconnect = false); public abstract void Update(float deltaTime); public abstract void Send(IWriteMessage msg, DeliveryMethod deliveryMethod, bool compressPastThreshold = true); public abstract void SendPassword(string password); @@ -80,10 +101,9 @@ namespace Barotrauma.Networking protected abstract void SendMsgInternal(DeliveryMethod deliveryMethod, IWriteMessage msg); protected ConnectionInitialization initializationStep; - protected bool contentPackageOrderReceived; - protected int ownerKey = 0; + public bool ContentPackageOrderReceived { get; protected set; } protected int passwordSalt; - protected Steamworks.AuthTicket steamAuthTicket; + protected Steamworks.AuthTicket? steamAuthTicket; protected void ReadConnectionInitializationStep(IReadMessage inc) { ConnectionInitialization step = (ConnectionInitialization)inc.ReadByte(); @@ -97,9 +117,9 @@ namespace Barotrauma.Networking outMsg = new WriteOnlyMessage(); outMsg.Write((byte)PacketHeader.IsConnectionInitializationStep); outMsg.Write((byte)ConnectionInitialization.SteamTicketAndVersion); - outMsg.Write(Name); - outMsg.Write(ownerKey); - outMsg.Write(SteamManager.GetSteamID()); + outMsg.Write(GameMain.Client.Name); + outMsg.Write(ownerKey.Fallback(0)); + outMsg.Write(SteamManager.GetSteamId().Select(steamId => steamId.Value).Fallback(0)); if (steamAuthTicket == null) { outMsg.Write((UInt16)0); @@ -122,8 +142,6 @@ namespace Barotrauma.Networking outMsg.Write((byte)PacketHeader.IsConnectionInitializationStep); outMsg.Write((byte)ConnectionInitialization.ContentPackageOrder); - string serverName = inc.ReadString(); - UInt32 packageCount = inc.ReadVariableUInt32(); List serverPackages = new List(); for (int i = 0; i < packageCount; i++) @@ -139,9 +157,16 @@ namespace Barotrauma.Networking serverPackages.Add(pkg); } - if (!contentPackageOrderReceived) + if (!ContentPackageOrderReceived) { ServerContentPackages = serverPackages.ToImmutableArray(); + if (serverPackages.Count == 0) + { + string errorMsg = "Error in ContentPackageOrder message: list of content packages enabled on the server was empty."; + GameAnalyticsManager.AddErrorEventOnce("ClientPeer.ReadConnectionInitializationStep:NoContentPackages", GameAnalyticsManager.ErrorSeverity.Error, errorMsg); + DebugConsole.ThrowError(errorMsg); + } + ContentPackageOrderReceived = true; SendMsgInternal(DeliveryMethod.Reliable, outMsg); } break; @@ -158,7 +183,7 @@ namespace Barotrauma.Networking { retries = inc.ReadInt32(); } - OnRequestPassword?.Invoke(passwordSalt, retries); + callbacks.OnRequestPassword.Invoke(passwordSalt, retries); break; } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/Primitives/Peers/LidgrenClientPeer.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/Primitives/Peers/LidgrenClientPeer.cs index ed3738964..80e5a7f65 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Networking/Primitives/Peers/LidgrenClientPeer.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/Primitives/Peers/LidgrenClientPeer.cs @@ -1,10 +1,8 @@ -using System; -using System.Collections.Generic; -using System.Net; -using System.Text; +using Barotrauma.Steam; using Lidgren.Network; -using Barotrauma.Steam; -using System.Linq; +using System; +using System.Collections.Generic; +using System.Text; namespace Barotrauma.Networking { @@ -16,39 +14,42 @@ namespace Barotrauma.Networking List incomingLidgrenMessages; - public LidgrenClientPeer(string name) + private LidgrenEndpoint lidgrenEndpoint + => ServerConnection is LidgrenConnection { Endpoint: LidgrenEndpoint result } + ? result + : throw new InvalidOperationException(); + + public LidgrenClientPeer(LidgrenEndpoint endpoint, Callbacks callbacks, Option ownerKey) : base(endpoint, callbacks, ownerKey) { ServerConnection = null; - Name = name; - netClient = null; isActive = false; } - public override void Start(object endPoint, int ownerKey) + public override void Start() { if (isActive) { return; } - this.ownerKey = ownerKey; - - contentPackageOrderReceived = false; + ContentPackageOrderReceived = false; netPeerConfiguration = new NetPeerConfiguration("barotrauma") { UseDualModeSockets = GameSettings.CurrentConfig.UseDualModeSockets }; - netPeerConfiguration.DisableMessageType(NetIncomingMessageType.DebugMessage | NetIncomingMessageType.WarningMessage | NetIncomingMessageType.Receipt - | NetIncomingMessageType.ErrorMessage | NetIncomingMessageType.Error); + netPeerConfiguration.DisableMessageType( + NetIncomingMessageType.DebugMessage + | NetIncomingMessageType.WarningMessage + | NetIncomingMessageType.Receipt + | NetIncomingMessageType.ErrorMessage + | NetIncomingMessageType.Error); netClient = new NetClient(netPeerConfiguration); if (SteamManager.IsInitialized) { steamAuthTicket = SteamManager.GetAuthSessionTicket(); - //TODO: wait for GetAuthSessionTicketResponse_t - if (steamAuthTicket == null) { throw new Exception("GetAuthSessionTicket returned null"); @@ -59,7 +60,7 @@ namespace Barotrauma.Networking initializationStep = ConnectionInitialization.SteamTicketAndVersion; - if (!(endPoint is IPEndPoint ipEndPoint)) + if (!(ServerEndpoint is LidgrenEndpoint lidgrenEndpoint)) { throw new InvalidCastException("endPoint is not IPEndPoint"); } @@ -69,7 +70,10 @@ namespace Barotrauma.Networking } netClient.Start(); - ServerConnection = new LidgrenConnection("Server", netClient.Connect(ipEndPoint), 0) + + var netConnection = netClient.Connect(lidgrenEndpoint.NetEndpoint); + + ServerConnection = new LidgrenConnection(netConnection) { Status = NetworkConnectionStatus.Connected }; @@ -81,7 +85,7 @@ namespace Barotrauma.Networking { if (!isActive) { return; } - if (ownerKey != 0 && (ChildServerRelay.Process?.HasExited ?? true)) + if (isOwner && !(ChildServerRelay.Process is { HasExited: false })) { Close(); var msgBox = new GUIMessageBox(TextManager.Get("ConnectionLost"), ChildServerRelay.CrashMessage); @@ -97,7 +101,7 @@ namespace Barotrauma.Networking foreach (NetIncomingMessage inc in incomingLidgrenMessages) { - if (inc.SenderConnection != (ServerConnection as LidgrenConnection).NetConnection) { continue; } + if (!inc.SenderConnection.RemoteEndPoint.Equals(lidgrenEndpoint.NetEndpoint)) { continue; } switch (inc.MessageType) { @@ -125,12 +129,12 @@ namespace Barotrauma.Networking { if (initializationStep != ConnectionInitialization.Success) { - OnInitializationComplete?.Invoke(); + callbacks.OnInitializationComplete.Invoke(); initializationStep = ConnectionInitialization.Success; } UInt16 length = inc.ReadUInt16(); IReadMessage msg = new ReadOnlyMessage(inc.Data, packetHeader.IsCompressed(), inc.PositionInBytes, length, ServerConnection); - OnMessageReceived?.Invoke(msg); + callbacks.OnMessageReceived.Invoke(msg); } } @@ -144,7 +148,7 @@ namespace Barotrauma.Networking case NetConnectionStatus.Disconnected: string disconnectMsg = inc.ReadString(); Close(disconnectMsg); - OnDisconnectMessageReceived?.Invoke(disconnectMsg); + callbacks.OnDisconnectMessageReceived.Invoke(disconnectMsg); break; } } @@ -176,7 +180,7 @@ namespace Barotrauma.Networking netClient.Shutdown(msg ?? TextManager.Get("Disconnecting").Value); netClient = null; steamAuthTicket?.Cancel(); steamAuthTicket = null; - OnDisconnect?.Invoke(disableReconnect); + callbacks.OnDisconnect.Invoke(disableReconnect); } public override void Send(IWriteMessage msg, DeliveryMethod deliveryMethod, bool compressPastThreshold = true) diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/Primitives/Peers/SteamP2PClientPeer.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/Primitives/Peers/SteamP2PClientPeer.cs index 6e097aabf..c4c30ce12 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Networking/Primitives/Peers/SteamP2PClientPeer.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/Primitives/Peers/SteamP2PClientPeer.cs @@ -1,17 +1,16 @@ -using System; +using Barotrauma.Steam; +using System; using System.Collections.Generic; -using System.Text; using System.Linq; -using Barotrauma.Steam; +using System.Text; using System.Threading; -using Barotrauma.Items.Components; namespace Barotrauma.Networking { class SteamP2PClientPeer : ClientPeer { private bool isActive; - private UInt64 hostSteamId; + private readonly SteamId hostSteamId; private double timeout; private double heartbeatTimer; private double connectionStatusTimer; @@ -21,18 +20,23 @@ namespace Barotrauma.Networking private List incomingInitializationMessages; private List incomingDataMessages; - public SteamP2PClientPeer(string name) + public SteamP2PClientPeer(SteamP2PEndpoint endpoint, Callbacks callbacks) : base(endpoint, callbacks, Option.None()) { ServerConnection = null; - Name = name; - isActive = false; + + if (!(ServerEndpoint is SteamP2PEndpoint steamIdEndpoint)) + { + throw new InvalidCastException("endPoint is not SteamId"); + } + + hostSteamId = steamIdEndpoint.SteamId; } - public override void Start(object endPoint, int ownerKey) + public override void Start() { - contentPackageOrderReceived = false; + ContentPackageOrderReceived = false; steamAuthTicket = SteamManager.GetAuthSessionTicket(); //TODO: wait for GetAuthSessionTicketResponse_t @@ -42,21 +46,14 @@ namespace Barotrauma.Networking throw new Exception("GetAuthSessionTicket returned null"); } - if (!(endPoint is UInt64 steamIdEndpoint)) - { - throw new InvalidCastException("endPoint is not UInt64"); - } - - hostSteamId = steamIdEndpoint; - Steamworks.SteamNetworking.ResetActions(); Steamworks.SteamNetworking.OnP2PSessionRequest = OnIncomingConnection; Steamworks.SteamNetworking.OnP2PConnectionFailed = OnConnectionFailed; Steamworks.SteamNetworking.AllowP2PPacketRelay(true); - ServerConnection = new SteamP2PConnection("Server", hostSteamId); - ServerConnection.SetOwnerSteamIDIfUnknown(hostSteamId); + ServerConnection = new SteamP2PConnection(hostSteamId); + ServerConnection.SetAccountInfo(new AccountInfo(hostSteamId)); incomingInitializationMessages = new List(); incomingDataMessages = new List(); @@ -66,7 +63,7 @@ namespace Barotrauma.Networking outMsg.Write((byte)PacketHeader.IsConnectionInitializationStep); outMsg.Write((byte)ConnectionInitialization.ConnectionStarted); - Steamworks.SteamNetworking.SendP2PPacket(hostSteamId, outMsg.Buffer, outMsg.LengthBytes, 0, Steamworks.P2PSend.Reliable); + Steamworks.SteamNetworking.SendP2PPacket(hostSteamId.Value, outMsg.Buffer, outMsg.LengthBytes, 0, Steamworks.P2PSend.Reliable); sentBytes += outMsg.LengthBytes; initializationStep = ConnectionInitialization.SteamTicketAndVersion; @@ -81,7 +78,7 @@ namespace Barotrauma.Networking private void OnIncomingConnection(Steamworks.SteamId steamId) { if (!isActive) { return; } - if (steamId == hostSteamId) + if (steamId == hostSteamId.Value) { Steamworks.SteamNetworking.AcceptP2PSessionWithUser(steamId); } @@ -90,23 +87,23 @@ namespace Barotrauma.Networking initializationStep != ConnectionInitialization.Success) { DebugConsole.ThrowError($"Connection from incorrect SteamID was rejected: "+ - $"expected {SteamManager.SteamIDUInt64ToString(hostSteamId)}," + - $"got {SteamManager.SteamIDUInt64ToString(steamId)}"); + $"expected {hostSteamId}," + + $"got {new SteamId(steamId)}"); } } private void OnConnectionFailed(Steamworks.SteamId steamId, Steamworks.P2PSessionError error) { if (!isActive) { return; } - if (steamId != hostSteamId) { return; } + if (steamId != hostSteamId.Value) { return; } Close($"SteamP2P connection failed: {error}"); - OnDisconnectMessageReceived?.Invoke($"{DisconnectReason.SteamP2PError}/SteamP2P connection failed: {error}"); + callbacks.OnDisconnectMessageReceived.Invoke($"{DisconnectReason.SteamP2PError}/SteamP2P connection failed: {error}"); } private void OnP2PData(ulong steamId, byte[] data, int dataLength) { if (!isActive) { return; } - if (steamId != hostSteamId) { return; } + if (steamId != hostSteamId.Value) { return; } timeout = Screen.Selected == GameMain.GameScreen ? NetworkConnection.TimeoutThresholdInGame : @@ -138,7 +135,7 @@ namespace Barotrauma.Networking IReadMessage inc = new ReadOnlyMessage(data, false, 1, dataLength - 1, ServerConnection); string msg = inc.ReadString(); Close(msg); - OnDisconnectMessageReceived?.Invoke(msg); + callbacks.OnDisconnectMessageReceived.Invoke(msg); } else { @@ -166,18 +163,18 @@ namespace Barotrauma.Networking connectionStatusTimer -= deltaTime; if (connectionStatusTimer <= 0.0) { - var state = Steamworks.SteamNetworking.GetP2PSessionState(hostSteamId); + var state = Steamworks.SteamNetworking.GetP2PSessionState(hostSteamId.Value); if (state == null) { Close("SteamP2P connection could not be established"); - OnDisconnectMessageReceived?.Invoke(DisconnectReason.SteamP2PError.ToString()); + callbacks.OnDisconnectMessageReceived.Invoke(DisconnectReason.SteamP2PError.ToString()); } else { if (state?.P2PSessionError != Steamworks.P2PSessionError.None) { Close($"SteamP2P error code: {state?.P2PSessionError}"); - OnDisconnectMessageReceived?.Invoke($"{DisconnectReason.SteamP2PError}/SteamP2P error code: {state?.P2PSessionError}"); + callbacks.OnDisconnectMessageReceived.Invoke($"{DisconnectReason.SteamP2PError}/SteamP2P error code: {state?.P2PSessionError}"); } } connectionStatusTimer = 1.0f; @@ -204,7 +201,7 @@ namespace Barotrauma.Networking outMsg.Write((byte)DeliveryMethod.Unreliable); outMsg.Write((byte)PacketHeader.IsHeartbeatMessage); - Steamworks.SteamNetworking.SendP2PPacket(hostSteamId, outMsg.Buffer, outMsg.LengthBytes, 0, Steamworks.P2PSend.Unreliable); + Steamworks.SteamNetworking.SendP2PPacket(hostSteamId.Value, outMsg.Buffer, outMsg.LengthBytes, 0, Steamworks.P2PSend.Unreliable); sentBytes += outMsg.LengthBytes; heartbeatTimer = 5.0; @@ -213,7 +210,7 @@ namespace Barotrauma.Networking if (timeout < 0.0) { Close("Timed out"); - OnDisconnectMessageReceived?.Invoke(DisconnectReason.SteamP2PTimeOut.ToString()); + callbacks.OnDisconnectMessageReceived.Invoke(DisconnectReason.SteamP2PTimeOut.ToString()); return; } @@ -221,7 +218,22 @@ namespace Barotrauma.Networking { if (incomingDataMessages.Count > 0) { - OnInitializationComplete?.Invoke(); + var incomingMessage = incomingDataMessages.First(); + byte incomingHeader = incomingMessage.LengthBytes > 0 ? incomingMessage.PeekByte() : (byte)0; + if (ContentPackageOrderReceived) + { +#warning: TODO: do not allow completing initialization until content package order has been received? + string errorMsg = $"Error during connection initialization: completed initialization before receiving content package order. Incoming header: {incomingHeader}"; + GameAnalyticsManager.AddErrorEventOnce("SteamP2PClientPeer.OnInitializationComplete:ContentPackageOrderNotReceived", GameAnalyticsManager.ErrorSeverity.Error, errorMsg); + DebugConsole.ThrowError(errorMsg); + } + if (ServerContentPackages.Length == 0) + { + string errorMsg = $"Error during connection initialization: list of content packages enabled on the server was empty when completing initialization. Incoming header: {incomingHeader}"; + GameAnalyticsManager.AddErrorEventOnce("SteamP2PClientPeer.OnInitializationComplete:NoContentPackages", GameAnalyticsManager.ErrorSeverity.Error, errorMsg); + DebugConsole.ThrowError(errorMsg); + } + callbacks.OnInitializationComplete.Invoke(); initializationStep = ConnectionInitialization.Success; } else @@ -237,7 +249,7 @@ namespace Barotrauma.Networking { foreach (IReadMessage inc in incomingDataMessages) { - OnMessageReceived?.Invoke(inc); + callbacks.OnMessageReceived.Invoke(inc); } } @@ -303,7 +315,7 @@ namespace Barotrauma.Networking private void Send(byte[] buf, int length, Steamworks.P2PSend sendType) { - bool successSend = Steamworks.SteamNetworking.SendP2PPacket(hostSteamId, buf, length + 4, 0, sendType); + bool successSend = Steamworks.SteamNetworking.SendP2PPacket(hostSteamId.Value, buf, length + 4, 0, sendType); sentBytes += length + 4; if (!successSend) { @@ -311,7 +323,7 @@ namespace Barotrauma.Networking { DebugConsole.Log("WARNING: message couldn't be sent unreliably, forcing reliable send (" + length.ToString() + " bytes)"); sendType = Steamworks.P2PSend.Reliable; - successSend = Steamworks.SteamNetworking.SendP2PPacket(hostSteamId, buf, length + 4, 0, sendType); + successSend = Steamworks.SteamNetworking.SendP2PPacket(hostSteamId.Value, buf, length + 4, 0, sendType); sentBytes += length + 4; } if (!successSend) @@ -335,7 +347,7 @@ namespace Barotrauma.Networking outMsg.Write(saltedPw, 0, saltedPw.Length); heartbeatTimer = 5.0; - Steamworks.SteamNetworking.SendP2PPacket(hostSteamId, outMsg.Buffer, outMsg.LengthBytes, 0, Steamworks.P2PSend.Reliable); + Steamworks.SteamNetworking.SendP2PPacket(hostSteamId.Value, outMsg.Buffer, outMsg.LengthBytes, 0, Steamworks.P2PSend.Reliable); sentBytes += outMsg.LengthBytes; } @@ -354,7 +366,7 @@ namespace Barotrauma.Networking try { - Steamworks.SteamNetworking.SendP2PPacket(hostSteamId, outMsg.Buffer, outMsg.LengthBytes, 0, Steamworks.P2PSend.Reliable); + Steamworks.SteamNetworking.SendP2PPacket(hostSteamId.Value, outMsg.Buffer, outMsg.LengthBytes, 0, Steamworks.P2PSend.Reliable); sentBytes += outMsg.LengthBytes; } catch (Exception e) @@ -365,12 +377,11 @@ namespace Barotrauma.Networking Thread.Sleep(100); Steamworks.SteamNetworking.ResetActions(); - Steamworks.SteamNetworking.CloseP2PSessionWithUser(hostSteamId); + Steamworks.SteamNetworking.CloseP2PSessionWithUser(hostSteamId.Value); steamAuthTicket?.Cancel(); steamAuthTicket = null; - hostSteamId = 0; - OnDisconnect?.Invoke(disableReconnect); + callbacks.OnDisconnect.Invoke(disableReconnect); } protected override void SendMsgInternal(DeliveryMethod deliveryMethod, IWriteMessage msg) @@ -394,7 +405,7 @@ namespace Barotrauma.Networking msgToSend.Write(msg.Buffer, 0, msg.LengthBytes); heartbeatTimer = 5.0; - Steamworks.SteamNetworking.SendP2PPacket(hostSteamId, msgToSend.Buffer, msgToSend.LengthBytes, 0, sendType); + Steamworks.SteamNetworking.SendP2PPacket(hostSteamId.Value, msgToSend.Buffer, msgToSend.LengthBytes, 0, sendType); sentBytes += msg.LengthBytes; } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/Primitives/Peers/SteamP2POwnerPeer.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/Primitives/Peers/SteamP2POwnerPeer.cs index 2f5c2f480..0f6641332 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Networking/Primitives/Peers/SteamP2POwnerPeer.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/Primitives/Peers/SteamP2POwnerPeer.cs @@ -1,7 +1,7 @@ -using Barotrauma.Steam; +using Barotrauma.Extensions; +using Barotrauma.Steam; using System; using System.Collections.Generic; -using System.Linq; using System.Threading; namespace Barotrauma.Networking @@ -10,20 +10,20 @@ namespace Barotrauma.Networking { private bool isActive; - private readonly UInt64 selfSteamID; - private UInt64 ownerKey64 => unchecked((UInt64)ownerKey); + private readonly SteamId selfSteamID; + private UInt64 ownerKey64 => unchecked((UInt64)ownerKey.Fallback(0)); - private UInt64 ReadSteamId(IReadMessage inc) - => inc.ReadUInt64() ^ ownerKey64; - private void WriteSteamId(IWriteMessage msg, UInt64 val) - => msg.Write(val ^ ownerKey64); + private SteamId ReadSteamId(IReadMessage inc) + => new SteamId(inc.ReadUInt64() ^ ownerKey64); + private void WriteSteamId(IWriteMessage msg, SteamId val) + => msg.Write(val.Value ^ ownerKey64); private long sentBytes, receivedBytes; class RemotePeer { - public UInt64 SteamID; - public UInt64 OwnerSteamID; + public SteamId SteamId; + public Option OwnerSteamId; public double? DisconnectTime; public bool Authenticating; public bool Authenticated; @@ -33,12 +33,12 @@ namespace Barotrauma.Networking public DeliveryMethod DeliveryMethod; public IWriteMessage Message; } - public List UnauthedMessages; + public readonly List UnauthedMessages; - public RemotePeer(UInt64 steamId) + public RemotePeer(SteamId steamId) { - SteamID = steamId; - OwnerSteamID = 0; + SteamId = steamId; + OwnerSteamId = Option.None(); DisconnectTime = null; Authenticating = false; Authenticated = false; @@ -49,27 +49,27 @@ namespace Barotrauma.Networking } List remotePeers; - public SteamP2POwnerPeer(string name) + public SteamP2POwnerPeer(Callbacks callbacks, int ownerKey) : base(new PipeEndpoint(), callbacks, Option.Some(ownerKey)) { ServerConnection = null; - Name = name; - isActive = false; - selfSteamID = Steam.SteamManager.GetSteamID(); + selfSteamID = SteamManager.GetSteamId().TryUnwrap(out var steamId) + ? steamId + : throw new InvalidOperationException("Steamworks not initialized"); } - public override void Start(object endPoint, int ownerKey) + public override void Start() { if (isActive) { return; } - this.ownerKey = ownerKey; - initializationStep = ConnectionInitialization.SteamTicketAndVersion; - ServerConnection = new PipeConnection(selfSteamID); - ServerConnection.Status = NetworkConnectionStatus.Connected; + ServerConnection = new PipeConnection(selfSteamID) + { + Status = NetworkConnectionStatus.Connected + }; remotePeers = new List(); @@ -82,10 +82,10 @@ namespace Barotrauma.Networking isActive = true; } - private void OnAuthChange(Steamworks.SteamId steamID, Steamworks.SteamId ownerID, Steamworks.AuthResponse status) + private void OnAuthChange(Steamworks.SteamId steamId, Steamworks.SteamId ownerId, Steamworks.AuthResponse status) { - RemotePeer remotePeer = remotePeers.Find(p => p.SteamID == steamID); - DebugConsole.Log(steamID + " validation: " + status + ", " + (remotePeer != null)); + RemotePeer remotePeer = remotePeers.Find(p => p.SteamId.Value == steamId); + DebugConsole.Log(steamId + " validation: " + status + ", " + (remotePeer != null)); if (remotePeer == null) { return; } @@ -100,7 +100,7 @@ namespace Barotrauma.Networking if (status == Steamworks.AuthResponse.OK) { - remotePeer.OwnerSteamID = ownerID; + remotePeer.OwnerSteamId = Option.Some(new SteamId(ownerId)); remotePeer.Authenticated = true; remotePeer.Authenticating = false; foreach (var msg in remotePeer.UnauthedMessages) @@ -111,7 +111,7 @@ namespace Barotrauma.Networking //known now int prevBitPosition = msg.Message.BitPosition; msg.Message.BitPosition = sizeof(ulong) * 8; - WriteSteamId(msg.Message, ownerID); + WriteSteamId(msg.Message, new SteamId(ownerId)); msg.Message.BitPosition = prevBitPosition; byte[] msgToSend = (byte[])msg.Message.Buffer.Clone(); Array.Resize(ref msgToSend, msg.Message.LengthBytes); @@ -130,34 +130,33 @@ namespace Barotrauma.Networking { if (!isActive) { return; } - if (!remotePeers.Any(p => p.SteamID == steamId)) + if (remotePeers.None(p => p.SteamId.Value == steamId)) { - remotePeers.Add(new RemotePeer(steamId)); + remotePeers.Add(new RemotePeer(new SteamId(steamId))); } Steamworks.SteamNetworking.AcceptP2PSessionWithUser(steamId); //accept all connections, the server will figure things out later } - private void OnP2PData(ulong steamId, byte[] data, int dataLength, int channel) + private void OnP2PData(ulong steamId, byte[] data, int dataLength, int _) { if (!isActive) { return; } - RemotePeer remotePeer = remotePeers.Find(p => p.SteamID == steamId); - if (remotePeer == null || remotePeer.DisconnectTime != null) - { - return; - } + RemotePeer remotePeer = remotePeers.Find(p => p.SteamId.Value == steamId); + if (remotePeer == null) { return; } + if (remotePeer.DisconnectTime != null) { return; } IWriteMessage outMsg = new WriteOnlyMessage(); - WriteSteamId(outMsg, steamId); - WriteSteamId(outMsg, remotePeer.OwnerSteamID); + var steamUserId = new SteamId(steamId); + WriteSteamId(outMsg, steamUserId); + WriteSteamId(outMsg, remotePeer.OwnerSteamId.Fallback(steamUserId)); outMsg.Write(data, 1, dataLength - 1); DeliveryMethod deliveryMethod = (DeliveryMethod)data[0]; PacketHeader packetHeader = (PacketHeader)data[1]; - if (!remotePeer.Authenticated & !remotePeer.Authenticating && packetHeader.IsConnectionInitializationStep()) + if (!remotePeer.Authenticated && !remotePeer.Authenticating && packetHeader.IsConnectionInitializationStep()) { remotePeer.DisconnectTime = null; @@ -240,7 +239,7 @@ namespace Barotrauma.Networking { if (!isActive) { return; } - UInt64 recipientSteamId = ReadSteamId(inc); + SteamId recipientSteamId = ReadSteamId(inc); DeliveryMethod deliveryMethod = (DeliveryMethod)inc.ReadByte(); int p2pDataStart = inc.BytePosition; @@ -255,7 +254,7 @@ namespace Barotrauma.Networking return; } - RemotePeer peer = remotePeers.Find(p => p.SteamID == recipientSteamId); + RemotePeer peer = remotePeers.Find(p => p.SteamId == recipientSteamId); if (peer == null) { return; } @@ -314,7 +313,7 @@ namespace Barotrauma.Networking sendType = Steamworks.P2PSend.Reliable; } - bool successSend = Steamworks.SteamNetworking.SendP2PPacket(recipientSteamId, p2pData, p2pData.Length, 0, sendType); + bool successSend = Steamworks.SteamNetworking.SendP2PPacket(recipientSteamId.Value, p2pData, p2pData.Length, 0, sendType); sentBytes += p2pData.Length; if (!successSend) @@ -323,7 +322,7 @@ namespace Barotrauma.Networking { DebugConsole.Log("WARNING: message couldn't be sent unreliably, forcing reliable send (" + p2pData.Length.ToString() + " bytes)"); sendType = Steamworks.P2PSend.Reliable; - successSend = Steamworks.SteamNetworking.SendP2PPacket(recipientSteamId, p2pData, p2pData.Length, 0, sendType); + successSend = Steamworks.SteamNetworking.SendP2PPacket(recipientSteamId.Value, p2pData, p2pData.Length, 0, sendType); sentBytes += p2pData.Length; } if (!successSend) @@ -354,7 +353,7 @@ namespace Barotrauma.Networking WriteSteamId(outMsg, selfSteamID); WriteSteamId(outMsg, selfSteamID); outMsg.Write((byte)(PacketHeader.IsConnectionInitializationStep)); - outMsg.Write(Name); + outMsg.Write(GameMain.Client.Name); byte[] msgToSend = (byte[])outMsg.Buffer.Clone(); Array.Resize(ref msgToSend, outMsg.LengthBytes); @@ -365,12 +364,12 @@ namespace Barotrauma.Networking { if (initializationStep != ConnectionInitialization.Success) { - OnInitializationComplete?.Invoke(); + callbacks.OnInitializationComplete.Invoke(); initializationStep = ConnectionInitialization.Success; } UInt16 length = inc.ReadUInt16(); IReadMessage msg = new ReadOnlyMessage(inc.Buffer, packetHeader.IsCompressed(), inc.BytePosition, length, ServerConnection); - OnMessageReceived?.Invoke(msg); + callbacks.OnMessageReceived.Invoke(msg); return; } @@ -390,7 +389,7 @@ namespace Barotrauma.Networking outMsg.Write((byte)(PacketHeader.IsServerMessage | PacketHeader.IsDisconnectMessage)); outMsg.Write(msg); - Steamworks.SteamNetworking.SendP2PPacket(peer.SteamID, outMsg.Buffer, outMsg.LengthBytes, 0, Steamworks.P2PSend.Reliable); + Steamworks.SteamNetworking.SendP2PPacket(peer.SteamId.Value, outMsg.Buffer, outMsg.LengthBytes, 0, Steamworks.P2PSend.Reliable); sentBytes += outMsg.LengthBytes; } else @@ -401,7 +400,7 @@ namespace Barotrauma.Networking private void ClosePeerSession(RemotePeer peer) { - Steamworks.SteamNetworking.CloseP2PSessionWithUser(peer.SteamID); + Steamworks.SteamNetworking.CloseP2PSessionWithUser(peer.SteamId.Value); remotePeers.Remove(peer); } @@ -430,7 +429,7 @@ namespace Barotrauma.Networking ChildServerRelay.ClosePipes(); - OnDisconnect?.Invoke(disableReconnect); + callbacks.OnDisconnect.Invoke(disableReconnect); SteamManager.LeaveLobby(); Steamworks.SteamNetworking.ResetActions(); diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerInfo.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerInfo.cs index 797343808..acfa28618 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerInfo.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerInfo.cs @@ -3,7 +3,6 @@ using Microsoft.Xna.Framework; using System; using System.Collections.Generic; using System.Linq; -using System.Net; using System.Threading.Tasks; using System.Xml.Linq; @@ -11,13 +10,14 @@ namespace Barotrauma.Networking { class ServerInfo { - public string IP; - public string Port; - public string QueryPort; - - public Steamworks.Data.NetPingLocation? PingLocation; + public Endpoint Endpoint; + + #region TODO: genericize + public int QueryPort; public UInt64 LobbyID; - public UInt64 OwnerID; + public Steamworks.Data.NetPingLocation? PingLocation; + #endregion + public bool OwnerVerified; private string serverName; @@ -42,7 +42,7 @@ namespace Barotrauma.Networking //null value means that the value isn't known (the server may be using //an old version of the game that didn't report these values or the FetchRules query to Steam may not have finished yet) - public bool? UsingWhiteList; + // TODO: death to Nullable!!!! public SelectionMode? ModeSelectionMode; public SelectionMode? SubSelectionMode; public bool? AllowSpectating; @@ -140,7 +140,7 @@ namespace Barotrauma.Networking } var serverType = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), frame.RectTransform), - TextManager.Get((OwnerID != 0 || LobbyID != 0) ? "SteamP2PServer" : "DedicatedServer"), + Endpoint.ServerTypeString, textAlignment: Alignment.TopLeft) { CanBeFocused = false @@ -248,20 +248,6 @@ namespace Barotrauma.Networking else voipEnabledTickBox.Selected = VoipEnabled.Value;*/ - var usingWhiteList = new GUITickBox(new RectTransform(new Vector2(1, elementHeight), content.RectTransform), TextManager.Get("ServerListUsingWhitelist")) - { - CanBeFocused = false - }; - if (!UsingWhiteList.HasValue) - new GUITextBlock(new RectTransform(new Vector2(0.8f, 0.8f), usingWhiteList.Box.RectTransform, Anchor.Center), "?", textAlignment: Alignment.Center); - else - usingWhiteList.Selected = UsingWhiteList.Value; - - content.RectTransform.SizeChanged += () => - { - GUITextBlock.AutoScaleAndNormalize(allowSpectating.TextBlock, allowRespawn.TextBlock, usingWhiteList.TextBlock); - }; - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), content.RectTransform), TextManager.Get("ServerListContentPackages"), textAlignment: Alignment.Center, font: GUIStyle.SubHeadingFont); @@ -350,34 +336,27 @@ namespace Barotrauma.Networking public static ServerInfo FromXElement(XElement element) { - ServerInfo info = new ServerInfo() + string endpointStr + = element.GetAttributeString("Endpoint", null) + ?? element.GetAttributeString("OwnerID", null) + ?? $"{element.GetAttributeString("IP", "")}:{element.GetAttributeInt("Port", 0)}"; + + if (!(Endpoint.Parse(endpointStr).TryUnwrap(out var endpoint))) { return null; } + + ServerInfo info = new ServerInfo { ServerName = element.GetAttributeString("ServerName", ""), ServerMessage = element.GetAttributeString("ServerMessage", ""), - IP = element.GetAttributeString("IP", ""), - Port = element.GetAttributeString("Port", ""), - QueryPort = element.GetAttributeString("QueryPort", ""), - OwnerID = element.GetAttributeSteamID("OwnerID",0) + Endpoint = endpoint, + QueryPort = element.GetAttributeInt("QueryPort", 0), + GameMode = element.GetAttributeIdentifier("GameMode", Identifier.Empty), + GameVersion = element.GetAttributeString("GameVersion", ""), + MaxPlayers = Math.Min(element.GetAttributeInt("MaxPlayers", 0), NetConfig.MaxPlayers), + HasPassword = element.GetAttributeBool("HasPassword", false), + RespondedToSteamQuery = null }; - info.RespondedToSteamQuery = null; - - info.GameMode = element.GetAttributeIdentifier("GameMode", Identifier.Empty); - info.GameVersion = element.GetAttributeString("GameVersion", ""); - - int maxPlayersElement = element.GetAttributeInt("MaxPlayers", 0); - - if (maxPlayersElement > NetConfig.MaxPlayers) - { - /*DebugConsole.IsOpen = true; - DebugConsole.NewMessage($"Setting the maximum amount of players to {maxPlayersElement} failed due to exceeding the limit of {NetConfig.MaxPlayers} players per server. Using the maximum of {NetConfig.MaxPlayers} instead.", Color.Red);*/ - maxPlayersElement = NetConfig.MaxPlayers; - } - - info.MaxPlayers = maxPlayersElement; - if (Enum.TryParse(element.GetAttributeString("PlayStyle", ""), out PlayStyle playStyleTemp)) { info.PlayStyle = playStyleTemp; } - if (bool.TryParse(element.GetAttributeString("UsingWhiteList", ""), out bool whitelistTemp)) { info.UsingWhiteList = whitelistTemp; } if (Enum.TryParse(element.GetAttributeString("TraitorsEnabled", ""), out YesNoMaybe traitorsTemp)) { info.TraitorsEnabled = traitorsTemp; } if (Enum.TryParse(element.GetAttributeString("SubSelectionMode", ""), out SelectionMode subSelectionTemp)) { info.SubSelectionMode = subSelectionTemp; } if (Enum.TryParse(element.GetAttributeString("ModeSelectionMode", ""), out SelectionMode modeSelectionTemp)) { info.ModeSelectionMode = modeSelectionTemp; } @@ -385,8 +364,6 @@ namespace Barotrauma.Networking if (bool.TryParse(element.GetAttributeString("KarmaEnabled", ""), out bool karmaTemp)) { info.KarmaEnabled = karmaTemp; } if (bool.TryParse(element.GetAttributeString("FriendlyFireEnabled", ""), out bool friendlyFireTemp)) { info.FriendlyFireEnabled = friendlyFireTemp; } - info.HasPassword = element.GetAttributeBool("HasPassword", false); - return info; } @@ -394,9 +371,9 @@ namespace Barotrauma.Networking { if (!SteamManager.IsInitialized) { return; } - if (int.TryParse(QueryPort, out int parsedPort) && IPAddress.TryParse(IP, out IPAddress parsedIP)) + if (QueryPort != 0 && Endpoint is LidgrenEndpoint { NetEndpoint: { Address: var ipAddress } }) { - if (MatchmakingPingResponse?.QueryActive ?? false) + if (MatchmakingPingResponse is { QueryActive: true }) { MatchmakingPingResponse.Cancel(); } @@ -433,14 +410,11 @@ namespace Barotrauma.Networking RespondedToSteamQuery = false; }); - MatchmakingPingResponse.HQueryPing(parsedIP, parsedPort); + MatchmakingPingResponse.HQueryPing(ipAddress, QueryPort); } - else if (OwnerID != 0) + else if (Endpoint is SteamP2PEndpoint { SteamId: var ownerId }) { - if (SteamFriend == null) - { - SteamFriend = new Steamworks.Friend(OwnerID); - } + SteamFriend ??= new Steamworks.Friend(ownerId.Value); if (LobbyID == 0) { TaskPool.Add("RequestSteamP2POwnerInfo", SteamFriend?.RequestInfoAsync(), @@ -474,20 +448,15 @@ namespace Barotrauma.Networking bool.TryParse(lobby.GetData("haspassword"), out bool hasPassword); int.TryParse(lobby.GetData("playercount"), out int currPlayers); int.TryParse(lobby.GetData("maxplayernum"), out int maxPlayers); - UInt64 ownerId = SteamManager.SteamIDStringToUInt64(lobby.GetData("lobbyowner")); - - if (OwnerID != ownerId) { return; } + + if (!SteamId.Parse(lobby.GetData("lobbyowner")).TryUnwrap(out var ownerId)) { return; } + if (!(Endpoint is SteamP2PEndpoint { SteamId: var id }) || id != ownerId) { return; } ServerName = lobby.GetData("name"); - IP = ""; - Port = ""; - QueryPort = ""; PlayerCount = currPlayers; MaxPlayers = maxPlayers; HasPassword = hasPassword; RespondedToSteamQuery = true; - LobbyID = lobby.Id; - OwnerID = ownerId; PingChecked = false; OwnerVerified = true; @@ -496,7 +465,7 @@ namespace Barotrauma.Networking public XElement ToXElement() { - if (OwnerID == 0 && string.IsNullOrEmpty(Port)) + if (Endpoint is null) { return null; //can't save this one since it's not set up correctly } @@ -505,22 +474,12 @@ namespace Barotrauma.Networking element.SetAttributeValue("ServerName", ServerName); element.SetAttributeValue("ServerMessage", ServerMessage); - if (OwnerID == 0) - { - element.SetAttributeValue("IP", IP); - element.SetAttributeValue("Port", Port); - element.SetAttributeValue("QueryPort", QueryPort); - } - else - { - element.SetAttributeValue("OwnerID", SteamManager.SteamIDUInt64ToString(OwnerID)); - } + element.SetAttributeValue("Endpoint", Endpoint.ToString()); element.SetAttributeValue("GameMode", GameMode); element.SetAttributeValue("GameVersion", GameVersion ?? ""); element.SetAttributeValue("MaxPlayers", MaxPlayers); if (PlayStyle.HasValue) { element.SetAttributeValue("PlayStyle", PlayStyle.Value.ToString()); } - if (UsingWhiteList.HasValue) { element.SetAttributeValue("UsingWhiteList", UsingWhiteList.Value.ToString()); } if (TraitorsEnabled.HasValue) { element.SetAttributeValue("TraitorsEnabled", TraitorsEnabled.Value.ToString()); } if (SubSelectionMode.HasValue) { element.SetAttributeValue("SubSelectionMode", SubSelectionMode.Value.ToString()); } if (ModeSelectionMode.HasValue) { element.SetAttributeValue("ModeSelectionMode", ModeSelectionMode.Value.ToString()); } @@ -540,14 +499,19 @@ namespace Barotrauma.Networking public bool Equals(ServerInfo other) { return - other.OwnerID == OwnerID && - (other.LobbyID == LobbyID || other.LobbyID == 0 || LobbyID == 0) && - ((OwnerID == 0) ? (other.IP == IP && other.Port == Port) : true); + other.Endpoint == Endpoint && + (other.LobbyID == LobbyID || other.LobbyID == 0 || LobbyID == 0); } + /// + /// This class is trash, so punish its use by making it horribly inefficient in hashsets + /// Doing anything else here would make it cause even more bugs + /// + public override int GetHashCode() => 0; + public bool MatchesByEndpoint(ServerInfo other) { - return OwnerID == other.OwnerID && (OwnerID != 0 ? true : (IP == other.IP && Port == other.Port)); + return other.Endpoint == Endpoint; } } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerLog.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerLog.cs index 19a9ba612..e0476a625 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerLog.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerLog.cs @@ -1,9 +1,9 @@ -using Microsoft.Xna.Framework; +using Barotrauma.Extensions; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; using System; using System.Collections.Generic; using System.Linq; -using Microsoft.Xna.Framework.Graphics; -using Barotrauma.Extensions; namespace Barotrauma.Networking { @@ -196,11 +196,7 @@ namespace Barotrauma.Networking { foreach (var data in richString.RichTextData.Value) { - if (!UInt64.TryParse(data.Metadata, out ulong id)) { return; } - Client client = GameMain.Client.ConnectedClients.Find(c => c.SteamID == id) - ?? GameMain.Client.ConnectedClients.Find(c => c.ID == id) - ?? GameMain.Client.PreviouslyConnectedClients.FirstOrDefault(c => c.SteamID == id) - ?? GameMain.Client.PreviouslyConnectedClients.FirstOrDefault(c => c.ID == id); + Client client = data.ExtractClient(); if (client != null && client.Karma < 40.0f) { textContainer = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.0f), listBox.Content.RectTransform), @@ -258,11 +254,8 @@ namespace Barotrauma.Networking foreach (GUIComponent child in listBox.Content.Children) { - var textBlock = child as GUITextBlock; - if (textBlock == null) continue; - + if (!(child is GUITextBlock textBlock)) { continue; } child.Visible = true; - if (msgTypeHidden[(int)((LogMessage)child.UserData).Type]) { child.Visible = false; @@ -287,10 +280,10 @@ namespace Barotrauma.Networking listBox.Content.RectTransform.ReverseChildren(); } - public bool ClearFilter(GUIComponent button, object obj) + public bool ClearFilter(GUIComponent button, object _) { var searchBox = button.UserData as GUITextBox; - if (searchBox != null) searchBox.Text = ""; + if (searchBox != null) { searchBox.Text = ""; } msgFilter = ""; FilterMessages(); diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerSettings.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerSettings.cs index f03d7b099..26cc5098c 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerSettings.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerSettings.cs @@ -121,7 +121,6 @@ namespace Barotrauma.Networking ReadMonsterEnabled(incMsg); BanList.ClientAdminRead(incMsg); - Whitelist.ClientAdminRead(incMsg); } public void ClientRead(IReadMessage incMsg) @@ -225,7 +224,6 @@ namespace Barotrauma.Networking outMsg.Write(changedMonsterSettings); outMsg.WritePadBits(); if (changedMonsterSettings) WriteMonsterEnabled(outMsg, tempMonsterEnabled); BanList.ClientAdminWrite(outMsg); - Whitelist.ClientAdminWrite(outMsg); } if (dataToSend.HasFlag(NetFlags.HiddenSubs)) @@ -273,8 +271,7 @@ namespace Barotrauma.Networking General, Rounds, Antigriefing, - Banlist, - Whitelist + Banlist } private NetPropertyData GetPropertyData(string name) @@ -949,13 +946,6 @@ namespace Barotrauma.Networking //-------------------------------------------------------------------------------- BanList.CreateBanFrame(settingsTabs[(int)SettingsTab.Banlist]); - - //-------------------------------------------------------------------------------- - // whitelist - //-------------------------------------------------------------------------------- - - Whitelist.CreateWhiteListFrame(settingsTabs[(int)SettingsTab.Whitelist]); - Whitelist.localEnabled = Whitelist.Enabled; } private void CreateLabeledSlider(GUIComponent parent, string labelTag, out GUIScrollBar slider, out GUITextBlock label) diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/Voip/VoipCapture.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/Voip/VoipCapture.cs index db7a406c7..617e7d40f 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Networking/Voip/VoipCapture.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/Voip/VoipCapture.cs @@ -53,7 +53,7 @@ namespace Barotrauma.Networking { get { - return GameMain.Client?.ID ?? 0; + return GameMain.Client?.SessionId ?? 0; } protected set { @@ -82,7 +82,7 @@ namespace Barotrauma.Networking } } - private VoipCapture(string deviceName) : base(GameMain.Client?.ID ?? 0, true, false) + private VoipCapture(string deviceName) : base(GameMain.Client?.SessionId ?? 0, true, false) { Disconnected = false; diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/Voting.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/Voting.cs index 90382e7c9..38c935426 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Networking/Voting.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/Voting.cs @@ -2,6 +2,7 @@ using Microsoft.Xna.Framework; using System.Collections.Generic; using System.Linq; +using Barotrauma.Extensions; namespace Barotrauma { @@ -54,7 +55,7 @@ namespace Barotrauma voteCountMax[voteType] = value; } - public void UpdateVoteTexts(List clients, VoteType voteType) + public void UpdateVoteTexts(IEnumerable clients, VoteType voteType) { switch (voteType) { @@ -92,7 +93,7 @@ namespace Barotrauma private void SetVoteText(GUIListBox listBox, object userData, int votes) { - if (userData == null) return; + if (userData == null) { return; } foreach (GUIComponent comp in listBox.Content.Children) { if (comp.UserData != userData) { continue; } @@ -136,7 +137,7 @@ namespace Barotrauma case VoteType.Kick: if (!(data is Client votedClient)) { return; } - msg.Write(votedClient.ID); + msg.Write(votedClient.SessionId); break; case VoteType.StartRound: if (!(data is bool)) { return; } @@ -233,21 +234,22 @@ namespace Barotrauma DebugConsole.ThrowError("Failed to cast vote type \"" + voteTypeByte + "\"", e); } - byte yesClientCount = inc.ReadByte(); - for (int i = 0; i < yesClientCount; i++) + int readVote(int value) { - byte clientID = inc.ReadByte(); - var matchingClient = GameMain.NetworkMember.ConnectedClients.Find(c => c.ID == clientID); - matchingClient?.SetVote(voteType, 2); - } + byte clientCount = inc.ReadByte(); + for (int i = 0; i < clientCount; i++) + { + byte clientId = inc.ReadByte(); + var matchingClient = GameMain.NetworkMember.ConnectedClients.Find(c => c.SessionId == clientId); + matchingClient?.SetVote(voteType, value); + } - byte noClientCount = inc.ReadByte(); - for (int i = 0; i < noClientCount; i++) - { - byte clientID = inc.ReadByte(); - var matchingClient = GameMain.NetworkMember.ConnectedClients.Find(c => c.ID == clientID); - matchingClient?.SetVote(voteType, 1); + return clientCount; } + + int yesClientCount = readVote(value: 2); + int noClientCount = readVote(value: 1); + byte maxClientCount = inc.ReadByte(); SetVoteCountYes(voteType, yesClientCount); @@ -258,10 +260,10 @@ namespace Barotrauma { case VoteState.Started: byte starterID = inc.ReadByte(); - Client starterClient = GameMain.NetworkMember.ConnectedClients.Find(c => c.ID == starterID); + Client starterClient = GameMain.NetworkMember.ConnectedClients.Find(c => c.SessionId == starterID); float timeOut = inc.ReadByte(); - Client myClient = GameMain.NetworkMember.ConnectedClients.Find(c => c.ID == GameMain.Client.ID); + Client myClient = GameMain.NetworkMember.ConnectedClients.Find(c => c.SessionId == GameMain.Client.SessionId); if (myClient == null || !myClient.InGame) { return; } switch (voteType) @@ -284,8 +286,8 @@ namespace Barotrauma byte toClientId = inc.ReadByte(); int transferAmount = inc.ReadInt32(); - Client fromClient = GameMain.NetworkMember.ConnectedClients.Find(c => c.ID == fromClientId); - Client toClient = GameMain.NetworkMember.ConnectedClients.Find(c => c.ID == toClientId); + Client fromClient = GameMain.NetworkMember.ConnectedClients.Find(c => c.SessionId == fromClientId); + Client toClient = GameMain.NetworkMember.ConnectedClients.Find(c => c.SessionId == toClientId); GameMain.Client.ShowMoneyTransferVoteInterface(starterClient, fromClient, transferAmount, toClient, timeOut); break; } @@ -343,8 +345,8 @@ namespace Barotrauma byte readyClientCount = inc.ReadByte(); for (int i = 0; i < readyClientCount; i++) { - byte clientID = inc.ReadByte(); - var matchingClient = GameMain.NetworkMember.ConnectedClients.Find(c => c.ID == clientID); + byte clientId = inc.ReadByte(); + var matchingClient = GameMain.NetworkMember.ConnectedClients.Find(c => c.SessionId == clientId); matchingClient?.SetVote(VoteType.StartRound, true); } UpdateVoteTexts(GameMain.NetworkMember.ConnectedClients, VoteType.StartRound); diff --git a/Barotrauma/BarotraumaClient/ClientSource/Screens/LevelEditorScreen.cs b/Barotrauma/BarotraumaClient/ClientSource/Screens/LevelEditorScreen.cs index 3d026e56a..4537be4ac 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Screens/LevelEditorScreen.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Screens/LevelEditorScreen.cs @@ -810,7 +810,7 @@ namespace Barotrauma GUI.DrawString(spriteBatch, pos, interestingPos.PositionType.ToString(), Color.White, font: GUIStyle.LargeFont); } - // TODO: Improve this temporary level editor debug solution (or remove it) + // TODO: Improve this temporary level editor debug solution foreach (var pathPoint in Level.Loaded.PathPoints) { Vector2 pathPointPos = new Vector2(pathPoint.Position.X, -pathPoint.Position.Y); @@ -833,6 +833,17 @@ namespace Barotrauma GUI.DrawString(spriteBatch, pathPointPos, "Path Point\n" + pathPoint.Id, color, font: GUIStyle.LargeFont); } + foreach (var location in Level.Loaded.AbyssResources) + { + if (location.Resources == null) { continue; } + foreach (var resource in location.Resources) + { + Vector2 resourcePos = new Vector2(resource.Position.X, -resource.Position.Y); + spriteBatch.DrawCircle(resourcePos, 100, 6, Color.DarkGreen * 0.5f, thickness: (int)(2 / Cam.Zoom)); + GUI.DrawString(spriteBatch, resourcePos, resource.Name, Color.DarkGreen, font: GUIStyle.LargeFont); + } + } + /*for (int i = 0; i < Level.Loaded.distanceField.Count; i++) { GUI.DrawRectangle(spriteBatch, diff --git a/Barotrauma/BarotraumaClient/ClientSource/Screens/MainMenuScreen.cs b/Barotrauma/BarotraumaClient/ClientSource/Screens/MainMenuScreen.cs index 303b9d94f..fa017d9c0 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Screens/MainMenuScreen.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Screens/MainMenuScreen.cs @@ -390,7 +390,7 @@ namespace Barotrauma SelectTab(tb, userdata); GameMain.Client = new GameClient(MultiplayerPreferences.Instance.PlayerName.FallbackNullOrEmpty(SteamManager.GetUsername()), - IPAddress.Loopback.ToString(), 0, "localhost", 0, false); + new LidgrenEndpoint(IPAddress.Loopback, NetConfig.DefaultPort), "localhost", Option.None()); return true; } @@ -489,7 +489,7 @@ namespace Barotrauma if (GameMain.Client != null) { - GameMain.Client.Disconnect(); + GameMain.Client.Quit(); GameMain.Client = null; } @@ -834,9 +834,9 @@ namespace Barotrauma arguments += " -nopassword"; } - if (Steam.SteamManager.GetSteamID() != 0) + if (SteamManager.GetSteamId().TryUnwrap(out var steamId1)) { - arguments += " -steamid " + Steam.SteamManager.GetSteamID(); + arguments += " -steamid " + steamId1.Value; } int ownerKey = Math.Max(CryptoRandom.Instance.Next(), 1); arguments += " -ownerkey " + ownerKey; @@ -865,8 +865,12 @@ namespace Barotrauma Thread.Sleep(1000); //wait until the server is ready before connecting GameMain.Client = new GameClient(MultiplayerPreferences.Instance.PlayerName.FallbackNullOrEmpty( - SteamManager.GetUsername().FallbackNullOrEmpty(name)), - System.Net.IPAddress.Loopback.ToString(), Steam.SteamManager.GetSteamID(), name, ownerKey, true); + SteamManager.GetUsername().FallbackNullOrEmpty(name)), + SteamManager.GetSteamId().TryUnwrap(out var steamId) + ? new SteamP2PEndpoint(steamId) + : (Endpoint)new LidgrenEndpoint(IPAddress.Loopback, NetConfig.DefaultPort), + name, + Option.Some(ownerKey)); } catch (Exception e) { diff --git a/Barotrauma/BarotraumaClient/ClientSource/Screens/ModDownloadScreen.cs b/Barotrauma/BarotraumaClient/ClientSource/Screens/ModDownloadScreen.cs index 537124f37..599aa2c60 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Screens/ModDownloadScreen.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Screens/ModDownloadScreen.cs @@ -68,12 +68,28 @@ namespace Barotrauma { OnClicked = (guiButton, o) => { - GameMain.Client?.Disconnect(); + GameMain.Client?.Quit(); GameMain.MainMenuScreen.Select(); return false; } }; - + + if (!GameMain.Client.IsServerOwner) + { + if (GameMain.Client.ClientPeer.ServerContentPackages.Length == 0) + { + string errorMsg = $"Error in ModDownloadScreen: the list of mods the server has enabled was empty. Content package list received: {GameMain.Client.ClientPeer.ContentPackageOrderReceived}"; + GameAnalyticsManager.AddErrorEventOnce("ModDownloadScreen.Select:NoContentPackages", GameAnalyticsManager.ErrorSeverity.Error, errorMsg); + throw new InvalidOperationException(errorMsg); + } + if (GameMain.Client.ClientPeer.ServerContentPackages.None(p => p.CorePackage != null)) + { + string errorMsg = $"Error in ModDownloadScreen: no core packages in the list of mods the server has enabled. Content package list received: {GameMain.Client.ClientPeer.ContentPackageOrderReceived}"; + GameAnalyticsManager.AddErrorEventOnce("ModDownloadScreen.Select:NoCorePackage", GameAnalyticsManager.ErrorSeverity.Error, errorMsg); + throw new InvalidOperationException(errorMsg); + } + } + var missingPackages = GameMain.Client.ClientPeer.ServerContentPackages .Where(sp => sp.ContentPackage is null).ToArray(); if (!missingPackages.Any()) @@ -84,11 +100,14 @@ namespace Barotrauma ContentPackageManager.EnabledPackages.SetCore( GameMain.Client.ClientPeer.ServerContentPackages .Select(p => p.CorePackage) - .First(p => p != null)); - ContentPackageManager.EnabledPackages.SetRegular( + .OfType().First()); + List regularPackages = GameMain.Client.ClientPeer.ServerContentPackages .Select(p => p.RegularPackage) - .Where(p => p != null).ToArray()); + .OfType().ToList(); + //keep enabled client-side-only mods enabled + regularPackages.AddRange(ContentPackageManager.EnabledPackages.Regular.Where(p => !p.HasMultiplayerSyncedContent)); + ContentPackageManager.EnabledPackages.SetRegular(regularPackages); } GameMain.NetLobbyScreen.Select(); return; @@ -153,7 +172,7 @@ namespace Barotrauma buttonContainerSpacing(0.2f); button(TextManager.Get("No"), () => { - GameMain.Client?.Disconnect(); + GameMain.Client?.Quit(); GameMain.MainMenuScreen.Select(); }); buttonContainerSpacing(0.1f); @@ -173,10 +192,10 @@ namespace Barotrauma if (GameMain.Client != null) { BulkDownloader.SubscribeToServerMods(missingIds, - rejoinEndpoint: GameMain.Client.ClientPeer.ServerConnection.EndPointString, - rejoinLobby: SteamManager.CurrentLobbyID, - rejoinServerName: GameMain.NetLobbyScreen.ServerName.Text); - GameMain.Client.Disconnect(); + new ConnectCommand( + serverName: GameMain.Client.ServerName, + endpoint: GameMain.Client.ClientPeer.ServerEndpoint)); + GameMain.Client.Quit(); } GameMain.MainMenuScreen.Select(); }, width: 0.7f); @@ -275,19 +294,22 @@ namespace Barotrauma ?? serverPackages.FirstOrDefault(p => p.CorePackage != null) ?.CorePackage ?? throw new Exception($"Failed to find core package to enable"); - RegularPackage[] regularPackages + List regularPackages = serverPackages.Where(p => p.CorePackage is null) .Select(p => p.RegularPackage ?? downloadedPackages.FirstOrDefault(d => d is RegularPackage && d.Hash.Equals(p.Hash)) ?? throw new Exception($"Could not find regular package \"{p.Name}\"")) .Cast() - .ToArray(); + .ToList(); foreach (var regularPackage in regularPackages) { DebugConsole.NewMessage($"Enabling \"{regularPackage.Name}\" ({regularPackage.Dir})", Color.Lime); } + //keep enabled client-side-only mods enabled + regularPackages.AddRange(ContentPackageManager.EnabledPackages.Regular.Where(p => !p.HasMultiplayerSyncedContent)); + ContentPackageManager.EnabledPackages.BackUp(); ContentPackageManager.EnabledPackages.SetCore(corePackage); ContentPackageManager.EnabledPackages.SetRegular(regularPackages); diff --git a/Barotrauma/BarotraumaClient/ClientSource/Screens/NetLobbyScreen.cs b/Barotrauma/BarotraumaClient/ClientSource/Screens/NetLobbyScreen.cs index 4bf99f6d8..7321d64d6 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Screens/NetLobbyScreen.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Screens/NetLobbyScreen.cs @@ -1529,14 +1529,13 @@ namespace Barotrauma while (i < MultiplayerPreferences.Instance.JobPreferences.Count) { var jobPreference = MultiplayerPreferences.Instance.JobPreferences[i]; - if (!JobPrefab.Prefabs.ContainsKey(jobPreference.JobIdentifier)) + if (!JobPrefab.Prefabs.TryGet(jobPreference.JobIdentifier, out JobPrefab prefab) || prefab.HiddenJob) { MultiplayerPreferences.Instance.JobPreferences.RemoveAt(i); continue; } // The old job variant system used one-based indexing // so let's make sure no one get to pick a variant which doesn't exist - var prefab = JobPrefab.Prefabs[jobPreference.JobIdentifier]; var variant = Math.Min(jobPreference.Variant, prefab.Variants - 1); jobPrefab = new JobVariant(prefab, variant); break; @@ -2160,15 +2159,8 @@ namespace Barotrauma if (child != null) { PlayerList.RemoveChild(child); } } - private Client ExtractClientFromClickableArea(GUITextBlock.ClickableArea area) - { - if (!UInt64.TryParse(area.Data.Metadata, out UInt64 id)) { return null; } - Client client = GameMain.Client.ConnectedClients.Find(c => c.SteamID == id) - ?? GameMain.Client.ConnectedClients.Find(c => c.ID == id) - ?? GameMain.Client.PreviouslyConnectedClients.FirstOrDefault(c => c.SteamID == id) - ?? GameMain.Client.PreviouslyConnectedClients.FirstOrDefault(c => c.ID == id); - return client; - } + public static Client ExtractClientFromClickableArea(GUITextBlock.ClickableArea area) + => area.Data.ExtractClient(); public void SelectPlayer(GUITextBlock component, GUITextBlock.ClickableArea area) { @@ -2188,29 +2180,35 @@ namespace Barotrauma public static void CreateModerationContextMenu(Client client) { if (GUIContextMenu.CurrentContextMenu != null) { return; } - if (GameMain.IsSingleplayer || client == null || ((!GameMain.Client?.PreviouslyConnectedClients?.Contains(client)) ?? true)) { return; } - bool hasSteam = client.SteamID > 0 && SteamManager.IsInitialized, - canKick = GameMain.Client.HasPermission(ClientPermissions.Kick), - canBan = GameMain.Client.HasPermission(ClientPermissions.Ban) && client.AllowKicking, - canPromo = GameMain.Client.HasPermission(ClientPermissions.ManagePermissions); + if (GameMain.IsSingleplayer || client == null) { return; } + if (!(GameMain.Client is { PreviouslyConnectedClients: var previouslyConnectedClients }) + || !previouslyConnectedClients.Contains(client)) { return; } + + bool hasAccountId = client.AccountId.IsSome(); + bool canKick = GameMain.Client.HasPermission(ClientPermissions.Kick); + bool canBan = GameMain.Client.HasPermission(ClientPermissions.Ban) && client.AllowKicking; + bool canManagePermissions = GameMain.Client.HasPermission(ClientPermissions.ManagePermissions); // Disable options if we are targeting ourselves - if (client.ID == GameMain.Client?.ID) + if (client.SessionId == GameMain.Client.SessionId) { - canKick = canBan = canPromo = false; + canKick = canBan = canManagePermissions = false; } - List options = new List + List options = new List(); + + if (client.AccountId.TryUnwrap(out var accountId) && accountId is SteamId steamId) { - new ContextMenuOption("ViewSteamProfile", isEnabled: hasSteam, onSelected: delegate - { - Steamworks.SteamFriends.OpenWebOverlay($"https://steamcommunity.com/profiles/{client.SteamID}"); - }), - new ContextMenuOption("ModerationMenu.ManagePlayer", isEnabled: true, onSelected: delegate + options.Add(new ContextMenuOption("ViewSteamProfile", isEnabled: hasAccountId, onSelected: () => + { + SteamManager.OverlayProfile(steamId); + })); + } + + options.Add(new ContextMenuOption("ModerationMenu.ManagePlayer", isEnabled: true, onSelected: () => { GameMain.NetLobbyScreen?.SelectPlayer(client); - }) - }; + })); // Creates sub context menu options for all the ranks List rankOptions = new List(); @@ -2236,18 +2234,18 @@ namespace Barotrauma }) { Tooltip = rank.Description }); } - options.Add(new ContextMenuOption("Rank", isEnabled: canPromo, options: rankOptions.ToArray())); + options.Add(new ContextMenuOption("Rank", isEnabled: canManagePermissions, options: rankOptions.ToArray())); Color clientColor = client.Character?.Info?.Job.Prefab.UIColor ?? Color.White; if (GameMain.Client.ConnectedClients.Contains(client)) { - options.Add(new ContextMenuOption(client.MutedLocally ? "Unmute" : "Mute", isEnabled: client.ID != GameMain.Client?.ID, onSelected: delegate + options.Add(new ContextMenuOption(client.MutedLocally ? "Unmute" : "Mute", isEnabled: client.SessionId != GameMain.Client.SessionId, onSelected: delegate { client.MutedLocally = !client.MutedLocally; })); - bool kickEnabled = client.ID != GameMain.Client?.ID && client.AllowKicking; + bool kickEnabled = client.SessionId != GameMain.Client.SessionId && client.AllowKicking; // if the user can kick create a kick option else create the votekick option ContextMenuOption kickOption; @@ -2281,7 +2279,7 @@ namespace Barotrauma public bool SelectPlayer(Client selectedClient) { - bool myClient = selectedClient.ID == GameMain.Client.ID; + bool myClient = selectedClient.SessionId == GameMain.Client.SessionId; bool hasManagePermissions = GameMain.Client.HasPermission(ClientPermissions.ManagePermissions); PlayerFrame = new GUIButton(new RectTransform(Vector2.One, GUI.Canvas, Anchor.Center), style: null) @@ -2510,14 +2508,6 @@ namespace Barotrauma }; banButton.OnClicked = (bt, userdata) => { BanPlayer(selectedClient); return true; }; banButton.OnClicked += ClosePlayerFrame; - - var rangebanButton = new GUIButton(new RectTransform(new Vector2(0.34f, 1.0f), buttonAreaTop.RectTransform), - TextManager.Get("BanRange")) - { - UserData = selectedClient - }; - rangebanButton.OnClicked = (bt, userdata) => { BanPlayerRange(selectedClient); return true; }; - rangebanButton.OnClicked += ClosePlayerFrame; } if (GameMain.Client != null && GameMain.Client.ConnectedClients.Contains(selectedClient)) @@ -2528,7 +2518,7 @@ namespace Barotrauma var kickVoteButton = new GUIButton(new RectTransform(new Vector2(0.34f, 1.0f), buttonAreaLower.RectTransform), TextManager.Get("VoteToKick")) { - Enabled = !selectedClient.HasKickVoteFromID(GameMain.Client.ID), + Enabled = !selectedClient.HasKickVoteFromSessionId(GameMain.Client.SessionId), OnClicked = (btn, userdata) => { GameMain.Client.VoteForKick(selectedClient); btn.Enabled = false; return true; }, UserData = selectedClient }; @@ -2560,7 +2550,7 @@ namespace Barotrauma } } - if (selectedClient.SteamID != 0 && Steam.SteamManager.IsInitialized) + if (selectedClient.AccountId.TryUnwrap(out var accountId) && accountId is SteamId steamId && Steam.SteamManager.IsInitialized) { var viewSteamProfileButton = new GUIButton(new RectTransform(new Vector2(0.3f, 1.0f), headerContainer.RectTransform, Anchor.TopCenter) { MaxSize = new Point(int.MaxValue, (int)(40 * GUI.Scale)) }, TextManager.Get("ViewSteamProfile")) @@ -2570,7 +2560,7 @@ namespace Barotrauma viewSteamProfileButton.TextBlock.AutoScaleHorizontal = true; viewSteamProfileButton.OnClicked = (bt, userdata) => { - SteamManager.OverlayCustomURL("https://steamcommunity.com/profiles/" + selectedClient.SteamID.ToString()); + SteamManager.OverlayProfile(steamId); return true; }; } @@ -2628,13 +2618,7 @@ namespace Barotrauma public void BanPlayer(Client client) { if (GameMain.NetworkMember == null || client == null) { return; } - GameMain.Client.CreateKickReasonPrompt(client.Name, ban: true, rangeBan: false); - } - - public void BanPlayerRange(Client client) - { - if (GameMain.NetworkMember == null || client == null) { return; } - GameMain.Client.CreateKickReasonPrompt(client.Name, ban: true, rangeBan: true); + GameMain.Client.CreateKickReasonPrompt(client.Name, ban: true); } public override void AddToGUIUpdateList() @@ -2679,7 +2663,7 @@ namespace Barotrauma if (child.FindChild(c => c.UserData is Pair pair && pair.First == "soundicon") is GUIImage soundIcon) { double voipAmplitude = 0.0f; - if (client.ID != GameMain.Client.ID) + if (client.SessionId != GameMain.Client.SessionId) { voipAmplitude = client.VoipSound?.CurrentAmplitude ?? 0.0f; } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Screens/ServerListScreen.cs b/Barotrauma/BarotraumaClient/ClientSource/Screens/ServerListScreen.cs index 49bed19f7..984cb5cbb 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Screens/ServerListScreen.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Screens/ServerListScreen.cs @@ -53,21 +53,19 @@ namespace Barotrauma private class FriendInfo { - public UInt64 SteamID; + public UInt64 SteamId; public string Name; public Sprite Sprite; public LocalizedString StatusText; public bool PlayingThisGame; public bool PlayingAnotherGame; - public string ConnectName; - public string ConnectEndpoint; - public UInt64 ConnectLobby; + public Option ConnectCommand = Option.None(); public bool InServer { get { - return PlayingThisGame && !StatusText.IsNullOrWhiteSpace() && (!string.IsNullOrWhiteSpace(ConnectEndpoint) || ConnectLobby != 0); + return PlayingThisGame && !StatusText.IsNullOrWhiteSpace() && ConnectCommand.IsSome(); } } } @@ -81,7 +79,7 @@ namespace Barotrauma private List favoriteServers; private List recentServers; - private readonly Dictionary activePings = new Dictionary(); + private readonly Dictionary activePings = new Dictionary(); private enum ServerListTab { @@ -153,7 +151,6 @@ namespace Barotrauma private GUITickBox filterIncompatible; private GUITickBox filterFull; private GUITickBox filterEmpty; - private GUITickBox filterWhitelisted; private Dictionary ternaryFilters; private Dictionary filterTickBoxes; private Dictionary playStyleTickBoxes; @@ -405,7 +402,6 @@ namespace Barotrauma filterIncompatible = addTickBox("FilterIncompatibleServers".ToIdentifier()); filterFull = addTickBox("FilterFullServers".ToIdentifier()); filterEmpty = addTickBox("FilterEmptyServers".ToIdentifier()); - filterWhitelisted = addTickBox("FilterWhitelistedServers".ToIdentifier()); filterOffensive = addTickBox("FilterOffensiveServers".ToIdentifier()); // Filter Tags @@ -608,14 +604,14 @@ namespace Barotrauma { if (selectedServer != null) { - if (!string.IsNullOrWhiteSpace(selectedServer.IP) && !string.IsNullOrWhiteSpace(selectedServer.Port) && int.TryParse(selectedServer.Port, out _)) - { - JoinServer(selectedServer.IP + ":" + selectedServer.Port, selectedServer.ServerName); - } - else if (selectedServer.LobbyID != 0) + if (selectedServer.LobbyID != 0) { Steam.SteamManager.JoinLobby(selectedServer.LobbyID, true); } + else if (selectedServer.Endpoint != null) + { + JoinServer(selectedServer.Endpoint, selectedServer.ServerName); + } else { new GUIMessageBox("", TextManager.Get("ServerOffline")); @@ -753,20 +749,11 @@ namespace Barotrauma doc.SaveSafe(file); } - public ServerInfo UpdateServerInfoWithServerSettings(NetworkConnection endpoint, ServerSettings serverSettings) + public ServerInfo UpdateServerInfoWithServerSettings(NetworkConnection connection, ServerSettings serverSettings) { - UInt64 steamId = 0; - string ip = ""; string port = ""; - if (endpoint is SteamP2PConnection steamP2PConnection) { steamId = steamP2PConnection.SteamID; } - else if (endpoint is LidgrenConnection lidgrenConnection) - { - ip = lidgrenConnection.IPString; - port = lidgrenConnection.Port.ToString(); - } - bool isInfoNew = false; ServerInfo info = serverList.Content.FindChild(d => (d.UserData is ServerInfo serverInfo) && - (steamId != 0 ? steamId == serverInfo.OwnerID : (ip == serverInfo.IP && port == serverInfo.Port)))?.UserData as ServerInfo; + serverInfo.Endpoint == connection.Endpoint)?.UserData as ServerInfo; if (info == null) { isInfoNew = true; @@ -775,17 +762,14 @@ namespace Barotrauma info.ServerName = serverSettings.ServerName; info.ServerMessage = serverSettings.ServerMessageText; - info.OwnerID = steamId; + info.Endpoint = connection.Endpoint; info.LobbyID = SteamManager.CurrentLobbyID; - info.IP = ip; - info.Port = port; info.GameMode = GameMain.NetLobbyScreen.SelectedMode?.Identifier ?? Identifier.Empty; info.GameStarted = Screen.Selected != GameMain.NetLobbyScreen; info.GameVersion = GameMain.Version.ToString(); info.MaxPlayers = serverSettings.MaxPlayers; info.PlayStyle = serverSettings.PlayStyle; info.RespondedToSteamQuery = true; - info.UsingWhiteList = serverSettings.Whitelist.Enabled; info.TraitorsEnabled = serverSettings.TraitorsEnabled; info.SubSelectionMode = serverSettings.SubSelectionMode; info.ModeSelectionMode = serverSettings.ModeSelectionMode; @@ -807,10 +791,9 @@ namespace Barotrauma public void AddToRecentServers(ServerInfo info) { - if (!string.IsNullOrEmpty(info.IP)) + if (info.Endpoint is LidgrenEndpoint { NetEndpoint: { Address: var ip } } && IPAddress.IsLoopback(ip)) { - //don't add localhost to recent servers - if (IPAddress.TryParse(info.IP, out IPAddress ip) && IPAddress.IsLoopback(ip)) { return; } + return; } info.Recent = true; @@ -870,8 +853,7 @@ namespace Barotrauma private void SortList(string sortBy, bool toggle) { - GUIButton button = labelHolder.GetChildByUserData(sortBy) as GUIButton; - if (button == null) { return; } + if (!(labelHolder.GetChildByUserData(sortBy) is GUIButton button)) { return; } sortedBy = sortBy; @@ -985,7 +967,7 @@ namespace Barotrauma if (GameMain.Client != null) { - GameMain.Client.Disconnect(); + GameMain.Client.Quit(); GameMain.Client = null; } @@ -1060,14 +1042,13 @@ namespace Barotrauma (!filterIncompatible.Selected || !incompatible) && (!filterFull.Selected || serverInfo.PlayerCount < serverInfo.MaxPlayers) && (!filterEmpty.Selected || serverInfo.PlayerCount > 0) && - (!filterWhitelisted.Selected || serverInfo.UsingWhiteList == true) && (!filterOffensive.Selected || !ForbiddenWordFilter.IsForbidden(serverInfo.ServerName)) && karmaFilterPassed && friendlyFireFilterPassed && traitorsFilterPassed && voipFilterPassed && moddedFilterPassed && - ((selectedTab == ServerListTab.All && (serverInfo.LobbyID != 0 || !string.IsNullOrWhiteSpace(serverInfo.Port))) || + ((selectedTab == ServerListTab.All && (serverInfo.LobbyID != 0 || serverInfo.Endpoint != null)) || (selectedTab == ServerListTab.Recent && serverInfo.Recent) || (selectedTab == ServerListTab.Favorites && serverInfo.Favorite)); } @@ -1105,7 +1086,7 @@ namespace Barotrauma serverList.UpdateScrollBarSize(); } - private Queue pendingQueries = new Queue(); + private readonly Queue pendingQueries = new Queue(); int activeQueries = 0; private void QueueInfoQuery(ServerInfo info) { @@ -1152,46 +1133,22 @@ namespace Barotrauma okButton.Enabled = false; okButton.OnClicked = (btn, userdata) => { - JoinServer(endpointBox.Text, ""); + if (!(Endpoint.Parse(endpointBox.Text).TryUnwrap(out var endpoint))) { return false; } + JoinServer(endpoint, ""); msgBox.Close(); - return true; + return false; }; var favoriteButton = msgBox.Buttons[1]; favoriteButton.Enabled = false; favoriteButton.OnClicked = (button, userdata) => { - UInt64 steamId = SteamManager.SteamIDStringToUInt64(endpointBox.Text); - string ip = ""; int port = 0; - if (steamId == 0) - { - string hostIP = endpointBox.Text; + if (!(Endpoint.Parse(endpointBox.Text).TryUnwrap(out var endpoint))) { return false; } - string[] address = hostIP.Split(':'); - if (address.Length == 1) - { - ip = hostIP; - port = NetConfig.DefaultPort; - } - else - { - ip = string.Join(":", address.Take(address.Length - 1)); - if (!int.TryParse(address[address.Length - 1], out port)) - { - DebugConsole.ThrowError("Invalid port: " + address[address.Length - 1] + "!"); - port = NetConfig.DefaultPort; - } - } - } - - //TODO: add a better way to get the query port, right now we're just assuming that it'll always be the default ServerInfo serverInfo = new ServerInfo() { ServerName = "Server", - OwnerID = steamId, - IP = ip, - Port = port.ToString(), - QueryPort = NetConfig.DefaultQueryPort.ToString(), + Endpoint = endpoint, GameVersion = GameMain.Version.ToString(), PlayStyle = null }; @@ -1231,37 +1188,25 @@ namespace Barotrauma private bool JoinFriend(GUIButton button, object userdata) { - FriendInfo info = userdata as FriendInfo; + if (!(userdata is FriendInfo { InServer: true } info)) { return false; } - if (info.InServer) - { - if (info.ConnectLobby != 0) - { - GameMain.Instance.ConnectLobby = info.ConnectLobby; - GameMain.Instance.ConnectEndpoint = null; - GameMain.Instance.ConnectName = null; - } - else - { - GameMain.Instance.ConnectLobby = 0; - GameMain.Instance.ConnectEndpoint = info.ConnectEndpoint; - GameMain.Instance.ConnectName = info.ConnectName; - } - } + GameMain.Instance.ConnectCommand = info.ConnectCommand; return false; } private bool OpenFriendPopup(GUIButton button, object userdata) { - FriendInfo info = userdata as FriendInfo; + if (!(userdata is FriendInfo { InServer: true } info)) { return false; } - if (info.InServer) + if (info.InServer + && info.ConnectCommand is Some { Value: { EndpointOrLobby: var endpointOrLobby } } + && endpointOrLobby.TryGet(out ConnectCommand.NameAndEndpoint nameAndEndpoint)) { - int framePadding = 5; + const int framePadding = 5; friendPopup = new GUIFrame(new RectTransform(Vector2.One, GUI.Canvas)); - var serverNameText = new GUITextBlock(new RectTransform(new Vector2(0.7f, 1.0f), friendPopup.RectTransform, Anchor.CenterLeft), info.ConnectName ?? "[Unnamed]"); + var serverNameText = new GUITextBlock(new RectTransform(new Vector2(0.7f, 1.0f), friendPopup.RectTransform, Anchor.CenterLeft), nameAndEndpoint.ServerName ?? "[Unnamed]"); serverNameText.RectTransform.AbsoluteOffset = new Point(framePadding, 0); var joinButton = new GUIButton(new RectTransform(new Vector2(0.3f, 1.0f), friendPopup.RectTransform, Anchor.CenterRight), TextManager.Get("ServerListJoin")) @@ -1349,7 +1294,7 @@ namespace Barotrauma for (int i = friendsList.Count - 1; i >= 0; i--) { var friend = friendsList[i]; - if (!friends.Any(g => g.Id == friend.SteamID && g.IsOnline)) + if (!friends.Any(g => g.Id == friend.SteamId && g.IsOnline)) { friend.Sprite?.Remove(); friendsList.RemoveAt(i); @@ -1360,12 +1305,12 @@ namespace Barotrauma { if (!friend.IsOnline) { continue; } - FriendInfo info = friendsList.Find(f => f.SteamID == friend.Id); + FriendInfo info = friendsList.Find(f => f.SteamId == friend.Id); if (info == null) { info = new FriendInfo() { - SteamID = friend.Id + SteamId = friend.Id }; friendsList.Insert(0, info); } @@ -1425,9 +1370,7 @@ namespace Barotrauma info.Name = friend.Name; - info.ConnectName = null; - info.ConnectEndpoint = null; - info.ConnectLobby = 0; + info.ConnectCommand = Option.None(); info.PlayingThisGame = friend.IsPlayingThisGame; info.PlayingAnotherGame = friend.GameInfo.HasValue; @@ -1439,7 +1382,7 @@ namespace Barotrauma try { - ToolBox.ParseConnectCommand(ToolBox.SplitCommand(connectCommand), out info.ConnectName, out info.ConnectEndpoint, out info.ConnectLobby); + info.ConnectCommand = ToolBox.ParseConnectCommand(ToolBox.SplitCommand(connectCommand)); } catch (IndexOutOfRangeException e) { @@ -1448,9 +1391,7 @@ namespace Barotrauma #else DebugConsole.Log($"Failed to parse a Steam friend's connect command ({connectCommand})\n" + e.StackTrace.CleanupStackTrace()); #endif - info.ConnectName = null; - info.ConnectEndpoint = null; - info.ConnectLobby = 0; + info.ConnectCommand = Option.None(); } } else @@ -1650,86 +1591,16 @@ namespace Barotrauma yield return CoroutineStatus.Success; } - private void UpdateServerList(string masterServerData) - { - serverList.ClearChildren(); - - if (masterServerData.Substring(0, 5).Equals("error", StringComparison.OrdinalIgnoreCase)) - { - DebugConsole.ThrowError("Error while connecting to master server (" + masterServerData + ")!"); - return; - } - - string[] lines = masterServerData.Split('\n'); - List serverInfos = new List(); - for (int i = 0; i < lines.Length; i++) - { - string[] arguments = lines[i].Split('|'); - if (arguments.Length < 3) continue; - - string ip = arguments[0]; - string port = arguments[1]; - string serverName = arguments[2]; - bool gameStarted = arguments.Length > 3 && arguments[3] == "1"; - string currPlayersStr = arguments.Length > 4 ? arguments[4] : ""; - string maxPlayersStr = arguments.Length > 5 ? arguments[5] : ""; - bool hasPassWord = arguments.Length > 6 && arguments[6] == "1"; - string gameVersion = arguments.Length > 7 ? arguments[7] : ""; - string contentPackageNames = arguments.Length > 8 ? arguments[8] : ""; - string contentPackageHashes = arguments.Length > 9 ? arguments[9] : ""; - - int.TryParse(currPlayersStr, out int playerCount); - int.TryParse(maxPlayersStr, out int maxPlayers); - - var serverInfo = new ServerInfo() - { - IP = ip, - Port = port, - ServerName = serverName, - GameStarted = gameStarted, - PlayerCount = playerCount, - MaxPlayers = maxPlayers, - HasPassword = hasPassWord, - GameVersion = gameVersion, - OwnerVerified = true - }; - foreach (string contentPackageName in contentPackageNames.Split(',')) - { - if (string.IsNullOrEmpty(contentPackageName)) continue; - serverInfo.ContentPackageNames.Add(contentPackageName); - } - foreach (string contentPackageHash in contentPackageHashes.Split(',')) - { - if (string.IsNullOrEmpty(contentPackageHash)) continue; - serverInfo.ContentPackageHashes.Add(contentPackageHash); - } - - serverInfos.Add(serverInfo); - } - - serverList.Content.ClearChildren(); - if (serverInfos.Count() == 0) - { - new GUITextBlock(new RectTransform(new Vector2(1.0f, 1.0f), serverList.Content.RectTransform), - TextManager.Get("NoServers"), textAlignment: Alignment.Center) - { - CanBeFocused = false - }; - return; - } - foreach (ServerInfo serverInfo in serverInfos) - { - AddToServerList(serverInfo); - } - } - + private GUIComponent FindFrameMatchingServerInfo(ServerInfo serverInfo) + => serverList.Content.FindChild(d => + d.UserData is ServerInfo info + && (info.LobbyID == 0 || info.LobbyID == serverInfo.LobbyID) + && info.OwnerVerified + && serverInfo.Endpoint == info.Endpoint); + private void AddToServerList(ServerInfo serverInfo) { - var serverFrame = serverList.Content.FindChild(d => (d.UserData is ServerInfo info) && - (info.LobbyID == serverInfo.LobbyID || - (info.LobbyID == 0 && info.OwnerID == serverInfo.OwnerID && - serverInfo.OwnerVerified)) && - (serverInfo.OwnerID != 0 ? true : (info.IP == serverInfo.IP && info.Port == serverInfo.Port))); + var serverFrame = FindFrameMatchingServerInfo(serverInfo); if (serverFrame == null) { @@ -1763,8 +1634,10 @@ namespace Barotrauma if (serverInfo.OwnerVerified) { - var childrenToRemove = serverList.Content.FindChildren(c => (c.UserData is ServerInfo info) && info != serverInfo && - (serverInfo.OwnerID != 0 ? info.OwnerID == serverInfo.OwnerID : info.IP == serverInfo.IP)).ToList(); + var childrenToRemove = serverList.Content.FindChildren(c => + c.UserData is ServerInfo info + && !ReferenceEquals(info, serverInfo) + && serverInfo.Endpoint == info.Endpoint).ToList(); foreach (var child in childrenToRemove) { serverList.Content.RemoveChild(child); @@ -1779,11 +1652,7 @@ namespace Barotrauma private void UpdateServerInfo(ServerInfo serverInfo) { - var serverFrame = serverList.Content.FindChild(d => (d.UserData is ServerInfo info) && - (info.LobbyID == serverInfo.LobbyID || - (info.LobbyID == 0 && info.OwnerID == serverInfo.OwnerID && - serverInfo.OwnerVerified)) && - (serverInfo.OwnerID != 0 ? true : (info.IP == serverInfo.IP && info.Port == serverInfo.Port))); + var serverFrame = FindFrameMatchingServerInfo(serverInfo); if (serverFrame == null) return; var serverContent = serverFrame.Children.First() as GUILayoutGroup; @@ -1806,11 +1675,10 @@ namespace Barotrauma }; var serverName = new GUITextBlock(new RectTransform(new Vector2(columnRelativeWidth[2] * 1.1f, 1.0f), serverContent.RectTransform), -#if !DEBUG - serverInfo.ServerName, -#else - ((serverInfo.OwnerID != 0 || serverInfo.LobbyID != 0) ? "[STEAMP2P] " : "[LIDGREN] ") + serverInfo.ServerName, +#if DEBUG + (serverInfo.Endpoint is SteamP2PEndpoint ? "[STEAMP2P] " : "[LIDGREN] ") + #endif + serverInfo.ServerName, style: "GUIServerListTextBox"); serverName.UserData = serverName.Text; serverName.RectTransform.SizeChanged += () => @@ -1850,7 +1718,7 @@ namespace Barotrauma serverPingText.Text = serverInfo.Ping > -1 ? serverInfo.Ping.ToString() : "?"; serverPingText.TextColor = GetPingTextColor(serverInfo.Ping); } - else if (!string.IsNullOrEmpty(serverInfo.IP)) + else if (serverInfo.Endpoint is LidgrenEndpoint lidgrenEndpoint) { try { @@ -1866,7 +1734,7 @@ namespace Barotrauma CoroutineManager.StartCoroutine(EstimateLobbyPing(serverInfo, serverPingText), "EstimateLobbyPing"); } - if (serverInfo.LobbyID == 0 && (string.IsNullOrWhiteSpace(serverInfo.IP) || string.IsNullOrWhiteSpace(serverInfo.Port))) + if (serverInfo.LobbyID == 0) { LocalizedString toolTip = TextManager.Get("ServerOffline"); serverContent.Children.ForEach(c => c.ToolTip = toolTip); @@ -1930,7 +1798,7 @@ namespace Barotrauma LocalizedString toolTip = ""; for (int i = 0; i < serverInfo.ContentPackageNames.Count; i++) { - if (!ContentPackageManager.EnabledPackages.All.Any(contentPackage => contentPackage.Hash.StringRepresentation == serverInfo.ContentPackageHashes[i])) + if (ContentPackageManager.EnabledPackages.All.None(contentPackage => contentPackage.Hash.StringRepresentation == serverInfo.ContentPackageHashes[i])) { if (toolTip != "") { toolTip += "\n"; } toolTip += TextManager.GetWithVariable("ServerListIncompatibleContentPackageWorkshopAvailable", "[contentpackage]", serverInfo.ContentPackageNames[i]); @@ -1995,7 +1863,7 @@ namespace Barotrauma masterServerResponded = true; } - private bool JoinServer(string endpoint, string serverName) + private bool JoinServer(Endpoint endpoint, string serverName) { if (string.IsNullOrWhiteSpace(ClientNameBox.Text)) { @@ -2013,17 +1881,13 @@ namespace Barotrauma return true; } - private IEnumerable ConnectToServer(string endpoint, string serverName) + private IEnumerable ConnectToServer(Endpoint endpoint, string serverName) { - string serverIP = null; - UInt64 serverSteamID = SteamManager.SteamIDStringToUInt64(endpoint); - if (serverSteamID == 0) { serverIP = endpoint; } - #if !DEBUG try { #endif - GameMain.Client = new GameClient(MultiplayerPreferences.Instance.PlayerName.FallbackNullOrEmpty(SteamManager.GetUsername()), serverIP, serverSteamID, serverName); + GameMain.Client = new GameClient(MultiplayerPreferences.Instance.PlayerName.FallbackNullOrEmpty(SteamManager.GetUsername()), endpoint, serverName, Option.None()); #if !DEBUG } catch (Exception e) @@ -2035,31 +1899,32 @@ namespace Barotrauma yield return CoroutineStatus.Success; } - public void GetServerPing(ServerInfo serverInfo, GUITextBlock serverPingText) + private void GetServerPing(ServerInfo serverInfo, GUITextBlock serverPingText) { if (CoroutineManager.IsCoroutineRunning("ConnectToServer")) { return; } - + if (!(serverInfo.Endpoint is LidgrenEndpoint { NetEndpoint: { Address: var address } })) { return; } + lock (activePings) { - if (activePings.ContainsKey(serverInfo.IP)) { return; } - activePings.Add(serverInfo.IP, activePings.Any() ? activePings.Values.Max()+1 : 0); + if (activePings.ContainsKey(address)) { return; } + activePings.Add(address, activePings.Any() ? activePings.Values.Max()+1 : 0); } serverInfo.PingChecked = false; serverInfo.Ping = -1; - TaskPool.Add($"PingServerAsync ({serverInfo?.IP ?? "NULL"})", PingServerAsync(serverInfo.IP, 1000), + TaskPool.Add($"PingServerAsync ({address})", PingServerAsync(address, 1000), new Tuple(serverInfo, serverPingText), (rtt, obj) => { - var info = obj.Item1; - var text = obj.Item2; - rtt.TryGetResult(out info.Ping); info.PingChecked = true; + var (info, text) = obj; + if (!rtt.TryGetResult(out info.Ping)) { info.Ping = -1; } + info.PingChecked = true; text.TextColor = GetPingTextColor(info.Ping); text.Text = info.Ping > -1 ? info.Ping.ToString() : "?"; lock (activePings) { - activePings.Remove(info.IP); + activePings.Remove(address); } }); } @@ -2070,7 +1935,7 @@ namespace Barotrauma return ToolBox.GradientLerp(ping / 200.0f, GUIStyle.Green, GUIStyle.Orange, GUIStyle.Red); } - public async Task PingServerAsync(string ip, int timeOut) + public async Task PingServerAsync(IPAddress ipAddress, int timeOut) { await Task.Yield(); bool shouldGo = false; @@ -2078,29 +1943,22 @@ namespace Barotrauma { lock (activePings) { - shouldGo = activePings.Count(kvp => kvp.Value < activePings[ip]) < 25; + shouldGo = activePings.Count(kvp => kvp.Value < activePings[ipAddress]) < 25; } await Task.Delay(25); } - if (string.IsNullOrWhiteSpace(ip)) - { - return -1; - } - long rtt = -1; - IPAddress address = null; - IPAddress.TryParse(ip, out address); - if (address != null) + if (ipAddress != null) { //don't attempt to ping if the address is IPv6 and it's not supported - if (address.AddressFamily != AddressFamily.InterNetworkV6 || Socket.OSSupportsIPv6) + if (ipAddress.AddressFamily != AddressFamily.InterNetworkV6 || Socket.OSSupportsIPv6) { Ping ping = new Ping(); byte[] buffer = new byte[32]; try { - PingReply pingReply = ping.Send(address, timeOut, buffer, new PingOptions(128, true)); + PingReply pingReply = ping.Send(ipAddress, timeOut, buffer, new PingOptions(128, true)); if (pingReply != null) { @@ -2117,9 +1975,9 @@ namespace Barotrauma } catch (Exception ex) { - GameAnalyticsManager.AddErrorEventOnce("ServerListScreen.PingServer:PingException" + ip, GameAnalyticsManager.ErrorSeverity.Warning, "Failed to ping a server - " + (ex?.InnerException?.Message ?? ex.Message)); + GameAnalyticsManager.AddErrorEventOnce("ServerListScreen.PingServer:PingException" + ipAddress, GameAnalyticsManager.ErrorSeverity.Warning, "Failed to ping a server - " + (ex?.InnerException?.Message ?? ex.Message)); #if DEBUG - DebugConsole.NewMessage("Failed to ping a server (" + ip + ") - " + (ex?.InnerException?.Message ?? ex.Message), Color.Red); + DebugConsole.NewMessage("Failed to ping a server (" + ipAddress + ") - " + (ex?.InnerException?.Message ?? ex.Message), Color.Red); #endif } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Screens/SubEditorScreen.cs b/Barotrauma/BarotraumaClient/ClientSource/Screens/SubEditorScreen.cs index 11ae9f941..96e66ded3 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Screens/SubEditorScreen.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Screens/SubEditorScreen.cs @@ -149,7 +149,7 @@ namespace Barotrauma private GUIDropDown linkedSubBox; private static GUIComponent autoSaveLabel; - private static int maxAutoSaves => GameSettings.CurrentConfig.MaxAutoSaves; + private static int MaxAutoSaves => GameSettings.CurrentConfig.MaxAutoSaves; public static readonly object ItemAddMutex = new object(), ItemRemoveMutex = new object(); @@ -228,6 +228,8 @@ namespace Barotrauma private static bool isAutoSaving; + private KeyOrMouse toggleEntityListBind; + public override Camera Cam => cam; public static XDocument AutoSaveInfo; @@ -926,7 +928,6 @@ namespace Barotrauma toggleEntityMenuButton = new GUIButton(new RectTransform(new Vector2(0.15f, 0.08f), EntityMenu.RectTransform, Anchor.TopCenter, Pivot.BottomCenter) { MinSize = new Point(0, 15) }, style: "UIToggleButtonVertical") { - ToolTip = RichString.Rich($"{TextManager.Get("EntityMenuToggleTooltip")}\n‖color:125,125,125‖{GameSettings.CurrentConfig.KeyMap.Bindings[InputType.ToggleInventory].Name}‖color:end‖"), OnClicked = (btn, userdata) => { entityMenuOpen = !entityMenuOpen; @@ -1645,7 +1646,7 @@ namespace Barotrauma if (AutoSaveInfo?.Root == null || MainSub?.Info == null) { return; } int saveCount = AutoSaveInfo.Root.Elements().Count(); - while (AutoSaveInfo.Root.Elements().Count() > maxAutoSaves) + while (AutoSaveInfo.Root.Elements().Count() > MaxAutoSaves) { XElement min = AutoSaveInfo.Root.Elements().OrderBy(element => element.GetAttributeUInt64("time", 0)).FirstOrDefault(); #warning TODO: revise @@ -5192,6 +5193,11 @@ namespace Barotrauma } } + if (toggleEntityListBind != GameSettings.CurrentConfig.KeyMap.Bindings[InputType.ToggleInventory]) + { + toggleEntityMenuButton.ToolTip = RichString.Rich($"{TextManager.Get("EntityMenuToggleTooltip")}\n‖color:125,125,125‖{GameSettings.CurrentConfig.KeyMap.Bindings[InputType.ToggleInventory].Name}‖color:end‖"); + toggleEntityListBind = GameSettings.CurrentConfig.KeyMap.Bindings[InputType.ToggleInventory]; + } if (GameSettings.CurrentConfig.KeyMap.Bindings[InputType.ToggleInventory].IsHit() && mode == Mode.Default) { toggleEntityMenuButton.OnClicked?.Invoke(toggleEntityMenuButton, toggleEntityMenuButton.UserData); @@ -5528,8 +5534,10 @@ namespace Barotrauma MouseDragStart = Vector2.Zero; } - if (!saveAssemblyFrame.Rect.Contains(PlayerInput.MousePosition) && !snapToGridFrame.Rect.Contains(PlayerInput.MousePosition) && - dummyCharacter?.SelectedItem == null && !WiringMode && GUI.MouseOn == null) + if (!saveAssemblyFrame.Rect.Contains(PlayerInput.MousePosition) + && !snapToGridFrame.Rect.Contains(PlayerInput.MousePosition) + && dummyCharacter?.SelectedItem == null && !WiringMode + && (GUI.MouseOn == null || MapEntity.SelectedAny || MapEntity.SelectionPos != Vector2.Zero)) { if (layerList is { Visible: true } && GUI.KeyboardDispatcher.Subscriber == layerList) { @@ -5556,7 +5564,7 @@ namespace Barotrauma { bool shouldCloseHud = dummyCharacter?.SelectedItem != null && HUD.CloseHUD(dummyCharacter.SelectedItem.Rect) && DraggedItemPrefab == null; - if (MapEntityPrefab.Selected != null && GUI.MouseOn == null) + if (MapEntityPrefab.Selected != null) { MapEntityPrefab.Selected.UpdatePlacing(cam); } @@ -5708,7 +5716,7 @@ namespace Barotrauma spriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.NonPremultiplied, transformMatrix: cam.Transform); Submarine.DrawFront(spriteBatch, editing: true, e => !IsSubcategoryHidden(e.Prefab?.Subcategory)); - if (!WiringMode && !IsMouseOnEditorGUI()) + if (!WiringMode) { MapEntityPrefab.Selected?.DrawPlacing(spriteBatch, cam); MapEntity.DrawSelecting(spriteBatch, cam); diff --git a/Barotrauma/BarotraumaClient/ClientSource/Serialization/SerializableEntityEditor.cs b/Barotrauma/BarotraumaClient/ClientSource/Serialization/SerializableEntityEditor.cs index b7e2d7744..3040f674e 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Serialization/SerializableEntityEditor.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Serialization/SerializableEntityEditor.cs @@ -382,10 +382,9 @@ namespace Barotrauma LocalizedString toolTip = TextManager.Get($"sp.{propertyTag}.description"); if (toolTip.IsNullOrEmpty()) { - toolTip = TextManager.Get($"{propertyTag}.description", $"sp.{fallbackTag}.description"); + toolTip = TextManager.Get($"{propertyTag}.description", $"sp.{fallbackTag}.description"); } - - if (toolTip == null) + if (toolTip.IsNullOrEmpty()) { toolTip = property.GetAttribute().Description; } @@ -700,9 +699,12 @@ namespace Barotrauma List prevSelected = MapEntity.SelectedList.ToList(); //reselect the entities that were selected during editing //otherwise multi-editing won't work when we deselect the entities with unapplied changes in the textbox - foreach (var entity in editedEntities) - { - MapEntity.SelectedList.Add(entity); + if (editedEntities.Count > 1) + { + foreach (var entity in editedEntities) + { + MapEntity.SelectedList.Add(entity); + } } if (SetPropertyValue(property, entity, textBox.Text)) { diff --git a/Barotrauma/BarotraumaClient/ClientSource/Sounds/OggSound.cs b/Barotrauma/BarotraumaClient/ClientSource/Sounds/OggSound.cs index 7249c9972..20f85f5e4 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Sounds/OggSound.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Sounds/OggSound.cs @@ -6,7 +6,7 @@ using System.Xml.Linq; namespace Barotrauma.Sounds { - public class OggSound : Sound + class OggSound : Sound { private VorbisReader reader; @@ -49,7 +49,7 @@ namespace Barotrauma.Sounds { if (!muffleFilters.TryGetValue(sampleRate, out BiQuad filter)) { - filter = new LowpassFilter(sampleRate, 800); + filter = new LowpassFilter(sampleRate, 1600); muffleFilters.Add(sampleRate, filter); } filter.Process(buffer); diff --git a/Barotrauma/BarotraumaClient/ClientSource/Sounds/Sound.cs b/Barotrauma/BarotraumaClient/ClientSource/Sounds/Sound.cs index fbcca4b32..3f4918c57 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Sounds/Sound.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Sounds/Sound.cs @@ -6,7 +6,7 @@ using System.Xml.Linq; namespace Barotrauma.Sounds { - public abstract class Sound : IDisposable + abstract class Sound : IDisposable { protected bool disposed; public bool Disposed diff --git a/Barotrauma/BarotraumaClient/ClientSource/Sounds/SoundBuffer.cs b/Barotrauma/BarotraumaClient/ClientSource/Sounds/SoundBuffer.cs index 79e00f0f1..cacd1121a 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Sounds/SoundBuffer.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Sounds/SoundBuffer.cs @@ -7,7 +7,7 @@ using System.Text; namespace Barotrauma.Sounds { - public class SoundBuffers : IDisposable + class SoundBuffers : IDisposable { private static readonly HashSet bufferPool = new HashSet(); #if OSX diff --git a/Barotrauma/BarotraumaClient/ClientSource/Sounds/SoundChannel.cs b/Barotrauma/BarotraumaClient/ClientSource/Sounds/SoundChannel.cs index 41675864d..bacb39916 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Sounds/SoundChannel.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Sounds/SoundChannel.cs @@ -7,7 +7,7 @@ using System.Diagnostics; namespace Barotrauma.Sounds { - public class SoundSourcePool : IDisposable + class SoundSourcePool : IDisposable { public uint[] ALSources { @@ -80,7 +80,7 @@ namespace Barotrauma.Sounds } } - public class SoundChannel : IDisposable + class SoundChannel : IDisposable { private const int STREAM_BUFFER_SIZE = 8820; private short[] streamShortBuffer; diff --git a/Barotrauma/BarotraumaClient/ClientSource/Sounds/SoundManager.cs b/Barotrauma/BarotraumaClient/ClientSource/Sounds/SoundManager.cs index ec631166a..8cfa4a8f7 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Sounds/SoundManager.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Sounds/SoundManager.cs @@ -9,7 +9,7 @@ using Barotrauma.IO; namespace Barotrauma.Sounds { - public class SoundManager : IDisposable + class SoundManager : IDisposable { public const int SOURCE_COUNT = 32; diff --git a/Barotrauma/BarotraumaClient/ClientSource/Sounds/VideoSound.cs b/Barotrauma/BarotraumaClient/ClientSource/Sounds/VideoSound.cs index 42422aefa..f462abe24 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Sounds/VideoSound.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Sounds/VideoSound.cs @@ -11,7 +11,7 @@ using Barotrauma.Media; namespace Barotrauma.Sounds { - public class VideoSound : Sound + class VideoSound : Sound { private readonly object mutex; private Queue sampleQueue; diff --git a/Barotrauma/BarotraumaClient/ClientSource/Sounds/VoipSound.cs b/Barotrauma/BarotraumaClient/ClientSource/Sounds/VoipSound.cs index 92394a518..7c52cd028 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Sounds/VoipSound.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Sounds/VoipSound.cs @@ -8,7 +8,7 @@ using System.Collections.Generic; namespace Barotrauma.Sounds { - public class VoipSound : Sound + class VoipSound : Sound { public override SoundManager.SourcePoolIndex SourcePoolIndex { diff --git a/Barotrauma/BarotraumaClient/ClientSource/StatusEffects/StatusEffect.cs b/Barotrauma/BarotraumaClient/ClientSource/StatusEffects/StatusEffect.cs index cd908d386..82f0bc176 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/StatusEffects/StatusEffect.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/StatusEffects/StatusEffect.cs @@ -1,11 +1,9 @@ -using System; -using System.Collections.Generic; -using System.Text; +using Barotrauma.Items.Components; using Barotrauma.Particles; using Barotrauma.Sounds; using Microsoft.Xna.Framework; -using System.Xml.Linq; -using Barotrauma.Items.Components; +using System; +using System.Collections.Generic; using System.Linq; namespace Barotrauma diff --git a/Barotrauma/BarotraumaClient/ClientSource/Steam/BulkDownloader.cs b/Barotrauma/BarotraumaClient/ClientSource/Steam/BulkDownloader.cs index ddac26c05..4a25ebe63 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Steam/BulkDownloader.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Steam/BulkDownloader.cs @@ -37,7 +37,7 @@ namespace Barotrauma.Steam }); } - internal static void SubscribeToServerMods(IEnumerable missingIds, string rejoinEndpoint, ulong rejoinLobby, string rejoinServerName) + internal static void SubscribeToServerMods(IEnumerable missingIds, ConnectCommand rejoinCommand) { CloseAllMessageBoxes(); GUIMessageBox msgBox = new GUIMessageBox(headerText: "", text: TextManager.Get("PreparingWorkshopDownloads"), @@ -59,9 +59,7 @@ namespace Barotrauma.Steam InitiateDownloads(items, onComplete: () => { ContentPackageManager.UpdateContentPackageList(); - GameMain.Instance.ConnectEndpoint = rejoinEndpoint; - GameMain.Instance.ConnectLobby = rejoinLobby; - GameMain.Instance.ConnectName = rejoinServerName; + GameMain.Instance.ConnectCommand = Option.Some(rejoinCommand); }); }); } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Steam/Lobby.cs b/Barotrauma/BarotraumaClient/ClientSource/Steam/Lobby.cs index 1243e39d7..7701c1469 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Steam/Lobby.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Steam/Lobby.cs @@ -92,7 +92,9 @@ namespace Barotrauma.Steam //currentLobby?.SetData("hostipaddress", lobbyIP); string pingLocation = Steamworks.SteamNetworkingUtils.LocalPingLocation?.ToString(); currentLobby?.SetData("pinglocation", pingLocation ?? ""); - currentLobby?.SetData("lobbyowner", SteamIDUInt64ToString(GetSteamID())); + currentLobby?.SetData("lobbyowner", GetSteamId().TryUnwrap(out var steamId) + ? steamId.StringRepresentation + : throw new InvalidOperationException("Steamworks not initialized")); currentLobby?.SetData("haspassword", serverSettings.HasPassword.ToString()); currentLobby?.SetData("message", serverSettings.ServerMessageText); @@ -101,7 +103,6 @@ namespace Barotrauma.Steam currentLobby?.SetData("contentpackage", string.Join(",", contentPackages.Select(cp => cp.Name))); currentLobby?.SetData("contentpackagehash", string.Join(",", contentPackages.Select(cp => cp.Hash.StringRepresentation))); currentLobby?.SetData("contentpackageid", string.Join(",", contentPackages.Select(cp => cp.SteamWorkshopId))); - currentLobby?.SetData("usingwhitelist", (serverSettings.Whitelist != null && serverSettings.Whitelist.Enabled).ToString()); currentLobby?.SetData("modeselectionmode", serverSettings.ModeSelectionMode.ToString()); currentLobby?.SetData("subselectionmode", serverSettings.SubSelectionMode.ToString()); currentLobby?.SetData("voicechatenabled", serverSettings.VoiceChatEnabled.ToString()); @@ -144,9 +145,10 @@ namespace Barotrauma.Steam lobbyID = (currentLobby?.Id).Value; if (joinServer) { - GameMain.Instance.ConnectLobby = 0; - GameMain.Instance.ConnectName = currentLobby?.GetData("servername"); - GameMain.Instance.ConnectEndpoint = SteamIDUInt64ToString((currentLobby?.Owner.Id).Value); + GameMain.Instance.ConnectCommand = Option.Some( + new ConnectCommand( + currentLobby?.GetData("servername") ?? "Server", + new SteamP2PEndpoint(new SteamId(currentLobby?.Owner.Id ?? 0)))); } }); } @@ -189,14 +191,16 @@ namespace Barotrauma.Steam { if (string.IsNullOrEmpty(lobby.GetData("name"))) { continue; } - ServerInfo serverInfo = new ServerInfo(); - serverInfo.ServerName = lobby.GetData("name"); - serverInfo.OwnerID = SteamIDStringToUInt64(lobby.GetData("lobbyowner")); - serverInfo.LobbyID = lobby.Id; + ServerInfo serverInfo = new ServerInfo + { + ServerName = lobby.GetData("name"), + Endpoint = new SteamP2PEndpoint(SteamId.Parse(lobby.GetData("lobbyowner")).Fallback(default(SteamId))), + LobbyID = lobby.Id, + RespondedToSteamQuery = true + }; bool.TryParse(lobby.GetData("haspassword"), out serverInfo.HasPassword); serverInfo.PlayerCount = int.TryParse(lobby.GetData("playercount"), out int playerCount) ? playerCount : 0; serverInfo.MaxPlayers = int.TryParse(lobby.GetData("maxplayernum"), out int maxPlayers) ? maxPlayers : 1; - serverInfo.RespondedToSteamQuery = true; AssignLobbyDataToServerInfo(lobby, serverInfo); @@ -215,8 +219,7 @@ namespace Barotrauma.Steam { ServerName = info.Name, HasPassword = info.Passworded, - IP = info.Address.ToString(), - Port = info.ConnectionPort.ToString(), + Endpoint = new LidgrenEndpoint(info.Address, info.ConnectionPort), PlayerCount = info.Players, MaxPlayers = info.MaxPlayers, RespondedToSteamQuery = responsive @@ -316,7 +319,6 @@ namespace Barotrauma.Steam serverInfo.ContentPackageWorkshopIds.AddRange(WorkshopUrlsToIds(workshopUrls)); } - serverInfo.UsingWhiteList = getLobbyBool("usingwhitelist"); if (Enum.TryParse(lobby.GetData("modeselectionmode"), out SelectionMode selectionMode)) { serverInfo.ModeSelectionMode = selectionMode; } if (Enum.TryParse(lobby.GetData("subselectionmode"), out selectionMode)) { serverInfo.SubSelectionMode = selectionMode; } @@ -365,7 +367,7 @@ namespace Barotrauma.Steam if (rules.ContainsKey("playercount")) { - if (int.TryParse(rules["playercount"], out int playerCount)) serverInfo.PlayerCount = playerCount; + if (int.TryParse(rules["playercount"], out int playerCount)) { serverInfo.PlayerCount = playerCount; } } serverInfo.ContentPackageNames.Clear(); @@ -383,7 +385,6 @@ namespace Barotrauma.Steam serverInfo.ContentPackageWorkshopIds.AddRange(WorkshopUrlsToIds(workshopUrls)); } - if (rules.ContainsKey("usingwhitelist")) { serverInfo.UsingWhiteList = rules["usingwhitelist"] == "True"; } if (rules.ContainsKey("modeselectionmode")) { if (Enum.TryParse(rules["modeselectionmode"], out SelectionMode selectionMode)) { serverInfo.ModeSelectionMode = selectionMode; } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Steam/SteamManager.cs b/Barotrauma/BarotraumaClient/ClientSource/Steam/SteamManager.cs index e99288885..66463fe83 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Steam/SteamManager.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Steam/SteamManager.cs @@ -28,7 +28,7 @@ namespace Barotrauma.Steam if (IsInitialized) { DebugConsole.NewMessage( - $"Logged in as {GetUsername()} (SteamID {SteamIDUInt64ToString(GetSteamID())})"); + $"Logged in as {GetUsername()} (SteamID {(GetSteamId().TryUnwrap(out var steamId) ? steamId.ToString() : "[NULL]")})"); popularTags.Clear(); int i = 0; @@ -129,7 +129,7 @@ namespace Barotrauma.Steam } - public static bool OverlayCustomURL(string url) + public static bool OverlayCustomUrl(string url) { if (!IsInitialized || !Steamworks.SteamClient.IsValid) { @@ -139,5 +139,10 @@ namespace Barotrauma.Steam Steamworks.SteamFriends.OpenWebOverlay(url); return true; } + + public static void OverlayProfile(SteamId steamId) + { + OverlayCustomUrl($"https://steamcommunity.com/profiles/{steamId.Value}"); + } } } \ No newline at end of file diff --git a/Barotrauma/BarotraumaClient/ClientSource/Steam/WorkshopMenu/Mutable/ItemList.cs b/Barotrauma/BarotraumaClient/ClientSource/Steam/WorkshopMenu/Mutable/ItemList.cs index 351ebb833..0d401f95a 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Steam/WorkshopMenu/Mutable/ItemList.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Steam/WorkshopMenu/Mutable/ItemList.cs @@ -126,7 +126,7 @@ namespace Barotrauma.Steam { OnClicked = (button, o) => { - SteamManager.OverlayCustomURL(workshopItem.Url); + SteamManager.OverlayCustomUrl(workshopItem.Url); return false; } }; @@ -234,7 +234,7 @@ namespace Barotrauma.Steam int indexOfUserDataInPublishedItemsArray(object userData) => publishedItems.IndexOf(t - => t.WorkshopItem.Id == ((Steamworks.Ugc.Item)(userData as ItemOrPackage)).Id); + => t.WorkshopItem.Id == ((Steamworks.Ugc.Item)(userData as ItemOrPackage)!).Id); //Take the existing GUI items that are in the list and sort to match the order of publishedItems var publishedGuiComponents = selfModsList.Content.Children.OrderBy(c => indexOfUserDataInPublishedItemsArray(c.UserData)).ToArray(); @@ -582,7 +582,7 @@ namespace Barotrauma.Steam SelectedTextColor = GUIStyle.TextColorNormal, OnClicked = (button, o) => { - SteamManager.OverlayCustomURL( + SteamManager.OverlayCustomUrl( $"https://steamcommunity.com/profiles/{author.Id}/myworkshopfiles/?appid={SteamManager.AppID}"); return false; } @@ -639,9 +639,10 @@ namespace Barotrauma.Steam new RectTransform(Vector2.Zero, reinstallButton.RectTransform), onUpdate: (f, component) => { - reinstallButton.Visible = workshopItem.IsSubscribed || workshopItem.Owner.Id == SteamManager.GetSteamID(); - reinstallButton.Enabled = !workshopItem.IsDownloading && !workshopItem.IsDownloadPending && - !SteamManager.Workshop.IsInstalling(workshopItem); + reinstallButton.Visible = workshopItem.IsSubscribed + || workshopItem.Owner.Id == SteamManager.GetSteamId().Select(steamId => steamId.Value).Fallback(0); + reinstallButton.Enabled = !workshopItem.IsDownloading && !workshopItem.IsDownloadPending + && !SteamManager.Workshop.IsInstalling(workshopItem); reinstallSprite.Color = reinstallButton.Enabled ? reinstallSprite.Style.Color diff --git a/Barotrauma/BarotraumaClient/ClientSource/Steam/WorkshopMenu/Mutable/MutableWorkshopMenu.cs b/Barotrauma/BarotraumaClient/ClientSource/Steam/WorkshopMenu/Mutable/MutableWorkshopMenu.cs index 1a24d958e..c9cbd489d 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Steam/WorkshopMenu/Mutable/MutableWorkshopMenu.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Steam/WorkshopMenu/Mutable/MutableWorkshopMenu.cs @@ -137,7 +137,7 @@ namespace Barotrauma.Steam { OnClicked = (button, o) => { - SteamManager.OverlayCustomURL($"https://steamcommunity.com/app/{SteamManager.AppID}/workshop/"); + SteamManager.OverlayCustomUrl($"https://steamcommunity.com/app/{SteamManager.AppID}/workshop/"); return false; } }; diff --git a/Barotrauma/BarotraumaClient/ClientSource/Steam/WorkshopMenu/Mutable/PublishTab.cs b/Barotrauma/BarotraumaClient/ClientSource/Steam/WorkshopMenu/Mutable/PublishTab.cs index 136290f81..6d6cc04ed 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Steam/WorkshopMenu/Mutable/PublishTab.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Steam/WorkshopMenu/Mutable/PublishTab.cs @@ -546,7 +546,7 @@ namespace Barotrauma.Steam if (result.Value.NeedsWorkshopAgreement) { - SteamManager.OverlayCustomURL(resultItem.Url); + SteamManager.OverlayCustomUrl(resultItem.Url); } new GUIMessageBox(string.Empty, TextManager.GetWithVariable("workshopitempublished", "[itemname]", localPackage.Name)); } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Utils/ConnectCommand.cs b/Barotrauma/BarotraumaClient/ClientSource/Utils/ConnectCommand.cs new file mode 100644 index 000000000..fb86070c6 --- /dev/null +++ b/Barotrauma/BarotraumaClient/ClientSource/Utils/ConnectCommand.cs @@ -0,0 +1,32 @@ +#nullable enable +using Barotrauma.Networking; + +namespace Barotrauma +{ + readonly struct ConnectCommand + { + public readonly struct NameAndEndpoint + { + public readonly string ServerName; + public readonly Endpoint Endpoint; + + public NameAndEndpoint(string serverName, Endpoint endpoint) + { + ServerName = serverName; + Endpoint = endpoint; + } + } + + public readonly Either EndpointOrLobby; + + public ConnectCommand(string serverName, Endpoint endpoint) + { + EndpointOrLobby = new NameAndEndpoint(serverName, endpoint); + } + + public ConnectCommand(ulong lobbyId) + { + EndpointOrLobby = lobbyId; + } + } +} diff --git a/Barotrauma/BarotraumaClient/ClientSource/Utils/RichTextData.cs b/Barotrauma/BarotraumaClient/ClientSource/Utils/RichTextData.cs new file mode 100644 index 000000000..19ce051e9 --- /dev/null +++ b/Barotrauma/BarotraumaClient/ClientSource/Utils/RichTextData.cs @@ -0,0 +1,20 @@ +using System; +using System.Linq; +using Barotrauma.Networking; + +namespace Barotrauma +{ + static class RichTextDataExtensions + { + public static Client ExtractClient(this RichTextData data) + { + bool isInt = UInt64.TryParse(data.Metadata, out ulong uintId); + Option accountId = AccountId.Parse(data.Metadata); + Client client = GameMain.Client.ConnectedClients.Find(c => accountId.IsSome() && accountId == c.AccountId) + ?? GameMain.Client.ConnectedClients.Find(c => isInt && c.SessionId == uintId) + ?? GameMain.Client.PreviouslyConnectedClients.FirstOrDefault(c => accountId.IsSome() && accountId == c.AccountId) + ?? GameMain.Client.PreviouslyConnectedClients.FirstOrDefault(c => isInt && c.SessionId == uintId); + return client; + } + } +} \ No newline at end of file diff --git a/Barotrauma/BarotraumaClient/ClientSource/Utils/SpriteRecorder.cs b/Barotrauma/BarotraumaClient/ClientSource/Utils/SpriteRecorder.cs index 6fdfc7098..43ba00158 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Utils/SpriteRecorder.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Utils/SpriteRecorder.cs @@ -7,7 +7,7 @@ using System.Text; namespace Barotrauma { - public class SpriteRecorder : ISpriteBatch, IDisposable + class SpriteRecorder : ISpriteBatch, IDisposable { private struct Command { diff --git a/Barotrauma/BarotraumaClient/ClientSource/Utils/ToolBox.cs b/Barotrauma/BarotraumaClient/ClientSource/Utils/ToolBox.cs index c11566a30..3d193471b 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Utils/ToolBox.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Utils/ToolBox.cs @@ -4,11 +4,12 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; using System.Linq; +using Barotrauma.Networking; using Color = Microsoft.Xna.Framework.Color; namespace Barotrauma { - public static partial class ToolBox + static partial class ToolBox { /// /// Checks if point is inside of a polygon @@ -450,21 +451,26 @@ namespace Barotrauma public static string WrapText(string text, float lineLength, ScalableFont font, float textScale = 1.0f) => font.WrapText(text, lineLength / textScale); - public static void ParseConnectCommand(string[] args, out string name, out string endpoint, out UInt64 lobbyId) + public static Option ParseConnectCommand(string[] args) { - name = null; endpoint = null; lobbyId = 0; - if (args == null || args.Length < 2) { return; } + if (args == null || args.Length < 2) { return Option.None(); } if (args[0].Equals("-connect", StringComparison.OrdinalIgnoreCase)) { - if (args.Length < 3) { return; } - name = args[1]; - endpoint = args[2]; + if (args.Length < 3) { return Option.None(); } + if (!(Endpoint.Parse(args[2]).TryUnwrap(out var endpoint))) { return Option.None(); } + return Option.Some( + new ConnectCommand( + serverName: args[1], + endpoint: endpoint)); } else if (args[0].Equals("+connect_lobby", StringComparison.OrdinalIgnoreCase)) { - UInt64.TryParse(args[1], out lobbyId); + return UInt64.TryParse(args[1], out var lobbyId) + ? Option.Some(new ConnectCommand(lobbyId)) + : Option.None(); } + return Option.None(); } public static bool VersionNewerIgnoreRevision(Version a, Version b) diff --git a/Barotrauma/BarotraumaClient/LinuxClient.csproj b/Barotrauma/BarotraumaClient/LinuxClient.csproj index 04e63b8ad..560289dd2 100644 --- a/Barotrauma/BarotraumaClient/LinuxClient.csproj +++ b/Barotrauma/BarotraumaClient/LinuxClient.csproj @@ -6,7 +6,7 @@ Barotrauma FakeFish, Undertow Games Barotrauma - 0.19.0.0 + 0.19.1.0 Copyright © FakeFish 2018-2022 AnyCPU;x64 Barotrauma diff --git a/Barotrauma/BarotraumaClient/MacClient.csproj b/Barotrauma/BarotraumaClient/MacClient.csproj index 0081ad967..4e6d3e5a8 100644 --- a/Barotrauma/BarotraumaClient/MacClient.csproj +++ b/Barotrauma/BarotraumaClient/MacClient.csproj @@ -6,7 +6,7 @@ Barotrauma FakeFish, Undertow Games Barotrauma - 0.19.0.0 + 0.19.1.0 Copyright © FakeFish 2018-2022 AnyCPU;x64 Barotrauma diff --git a/Barotrauma/BarotraumaClient/WindowsClient.csproj b/Barotrauma/BarotraumaClient/WindowsClient.csproj index dfa092086..54cc0ce82 100644 --- a/Barotrauma/BarotraumaClient/WindowsClient.csproj +++ b/Barotrauma/BarotraumaClient/WindowsClient.csproj @@ -6,7 +6,7 @@ Barotrauma FakeFish, Undertow Games Barotrauma - 0.19.0.0 + 0.19.1.0 Copyright © FakeFish 2018-2022 AnyCPU;x64 Barotrauma diff --git a/Barotrauma/BarotraumaServer/LinuxServer.csproj b/Barotrauma/BarotraumaServer/LinuxServer.csproj index cf881db47..83cba5533 100644 --- a/Barotrauma/BarotraumaServer/LinuxServer.csproj +++ b/Barotrauma/BarotraumaServer/LinuxServer.csproj @@ -6,7 +6,7 @@ Barotrauma FakeFish, Undertow Games Barotrauma Dedicated Server - 0.19.0.0 + 0.19.1.0 Copyright © FakeFish 2018-2022 AnyCPU;x64 DedicatedServer diff --git a/Barotrauma/BarotraumaServer/MacServer.csproj b/Barotrauma/BarotraumaServer/MacServer.csproj index b7101a67b..36a90f48b 100644 --- a/Barotrauma/BarotraumaServer/MacServer.csproj +++ b/Barotrauma/BarotraumaServer/MacServer.csproj @@ -6,7 +6,7 @@ Barotrauma FakeFish, Undertow Games Barotrauma Dedicated Server - 0.19.0.0 + 0.19.1.0 Copyright © FakeFish 2018-2022 AnyCPU;x64 DedicatedServer diff --git a/Barotrauma/BarotraumaServer/ServerSource/Characters/CharacterNetworking.cs b/Barotrauma/BarotraumaServer/ServerSource/Characters/CharacterNetworking.cs index 65f10e4c2..37dd065db 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Characters/CharacterNetworking.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Characters/CharacterNetworking.cs @@ -8,7 +8,7 @@ namespace Barotrauma { partial class Character { - public string OwnerClientEndPoint; + public Endpoint OwnerClientEndpoint; public string OwnerClientName; public bool ClientDisconnected; public float KillDisconnectedTimer; @@ -423,7 +423,7 @@ namespace Barotrauma case ControlEventData controlEventData: Client owner = controlEventData.Owner; msg.Write(owner == c && owner.Character == this); - msg.Write(owner != null && owner.Character == this && GameMain.Server.ConnectedClients.Contains(owner) ? owner.ID : (byte)0); + msg.Write(owner != null && owner.Character == this && GameMain.Server.ConnectedClients.Contains(owner) ? owner.SessionId : (byte)0); break; case CharacterStatusEventData statusEventData: WriteStatus(msg, statusEventData.ForceAfflictionData); @@ -632,6 +632,7 @@ namespace Barotrauma } msg.Write(Enabled); + msg.Write(DisabledByEvent); //character with no characterinfo (e.g. some monster) if (Info == null) @@ -644,7 +645,7 @@ namespace Barotrauma if (ownerClient != null) { msg.Write(true); - msg.Write(ownerClient.ID); + msg.Write(ownerClient.SessionId); } else if (GameMain.Server.Character == this) { diff --git a/Barotrauma/BarotraumaServer/ServerSource/DebugConsole.cs b/Barotrauma/BarotraumaServer/ServerSource/DebugConsole.cs index 58cb3e0ee..6c3a29f56 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/DebugConsole.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/DebugConsole.cs @@ -7,6 +7,7 @@ using System.Diagnostics; using System.Globalization; using System.Linq; using System.Text; +using Barotrauma.Steam; namespace Barotrauma { @@ -299,10 +300,16 @@ namespace Barotrauma Client client = GameMain.Server.ConnectedClients.Find(c => Homoglyphs.Compare(c.Name, arg)); if (int.TryParse(arg, out int id)) { - client ??= GameMain.Server.ConnectedClients.Find(c => c.ID == id); + client ??= GameMain.Server.ConnectedClients.Find(c => c.SessionId == id); + } + if (Endpoint.Parse(arg).TryUnwrap(out var endpoint)) + { + client ??= GameMain.Server.ConnectedClients.Find(c => c.EndpointMatches(endpoint)); + } + if (AccountId.Parse(arg).TryUnwrap(out var argAccountId)) + { + client ??= GameMain.Server.ConnectedClients.Find(c => c.AccountId.ValueEquals(argAccountId)); } - client ??= GameMain.Server.ConnectedClients.Find(c => c.EndpointMatches(arg)); - client ??= GameMain.Server.ConnectedClients.Find(c => c.SteamID == Steam.SteamManager.SteamIDStringToUInt64(arg)); return client; } @@ -872,7 +879,7 @@ namespace Barotrauma NewMessage("***************", Color.Cyan); foreach (Client c in GameMain.Server.ConnectedClients) { - NewMessage("- " + c.ID.ToString() + ": " + c.Name + (c.Character != null ? " playing " + c.Character.LogName : "") + ", " + c.Karma, Color.Cyan); + NewMessage("- " + c.SessionId.ToString() + ": " + c.Name + (c.Character != null ? " playing " + c.Character.LogName : "") + ", " + c.Karma, Color.Cyan); } NewMessage("***************", Color.Cyan); }); @@ -881,7 +888,7 @@ namespace Barotrauma GameMain.Server.SendConsoleMessage("***************", client); foreach (Client c in GameMain.Server.ConnectedClients) { - GameMain.Server.SendConsoleMessage("- " + c.ID.ToString() + ": " + c.Name + (c.Character != null ? " playing " + c.Character.LogName : "") + ", " + c.Karma, client); + GameMain.Server.SendConsoleMessage("- " + c.SessionId.ToString() + ": " + c.Name + (c.Character != null ? " playing " + c.Character.LogName : "") + ", " + c.Karma, client); } GameMain.Server.SendConsoleMessage("***************", client); }); @@ -904,10 +911,12 @@ namespace Barotrauma client); }); - AssignOnExecute("banendpoint", (string[] args) => + AssignOnExecute("banaddress", (string[] args) => { if (GameMain.Server == null || args.Length == 0) return; + if (!(Endpoint.Parse(args[0]).TryUnwrap(out var endpoint))) { return; } + ShowQuestionPrompt("Reason for banning the endpoint \"" + args[0] + "\"? (c to cancel)", (reason) => { if (reason == "c" || reason == "C") { return; } @@ -925,16 +934,16 @@ namespace Barotrauma banDuration = parsedBanDuration; } - var clients = GameMain.Server.ConnectedClients.FindAll(c => c.EndpointMatches(args[0])); + var clients = GameMain.Server.ConnectedClients.Where(c => c.EndpointMatches(endpoint)).ToList(); if (clients.Count == 0) { - GameMain.Server.ServerSettings.BanList.BanPlayer("Unnamed", args[0], reason, banDuration); + GameMain.Server.ServerSettings.BanList.BanPlayer("Unnamed", endpoint, reason, banDuration); } else { foreach (Client cl in clients) { - GameMain.Server.BanClient(cl, reason, false, banDuration); + GameMain.Server.BanClient(cl, reason, banDuration); } } }); @@ -1036,7 +1045,8 @@ namespace Barotrauma NewMessage("***************", Color.Cyan); foreach (Client c in GameMain.Server.ConnectedClients) { - NewMessage("- " + c.ID.ToString() + ": " + c.Name + (c.Character != null ? " playing " + c.Character.LogName : "") + ", " + c.Connection.EndPointString + $", ping {c.Ping} ms", Color.Cyan); + NewMessage( + $"- {c.SessionId}: {c.Name}{(c.Character != null ? " playing " + c.Character.LogName : "")}, {c.Connection.Endpoint.StringRepresentation}, {c.Connection.AccountInfo.AccountId}, ping {c.Ping} ms", Color.Cyan); } NewMessage("***************", Color.Cyan); })); @@ -1045,7 +1055,7 @@ namespace Barotrauma GameMain.Server.SendConsoleMessage("***************", client, Color.Cyan); foreach (Client c in GameMain.Server.ConnectedClients) { - GameMain.Server.SendConsoleMessage("- " + c.ID.ToString() + ": " + c.Name + ", " + c.Connection.EndPointString + $", ping {c.Ping} ms", client, Color.Cyan); + GameMain.Server.SendConsoleMessage("- " + c.SessionId.ToString() + ": " + c.Name + ", " + c.Connection.Endpoint.StringRepresentation + $", ping {c.Ping} ms", client, Color.Cyan); } GameMain.Server.SendConsoleMessage("***************", client, Color.Cyan); }); @@ -1496,11 +1506,12 @@ namespace Barotrauma ); AssignOnClientRequestExecute( - "banendpoint|banip", + "banaddress|banip", (Client client, Vector2 cursorPos, string[] args) => { - if (args.Length < 1) return; - var clients = GameMain.Server.ConnectedClients.FindAll(c => c.EndpointMatches(args[0])); + if (args.Length < 1) { return; } + if (!(Endpoint.Parse(args[0]).TryUnwrap(out var endpoint))) { return; } + var clients = GameMain.Server.ConnectedClients.Where(c => c.EndpointMatches(endpoint)).ToList(); TimeSpan? duration = null; if (args.Length > 1) { @@ -1519,13 +1530,13 @@ namespace Barotrauma if (clients.Count == 0) { - GameMain.Server.ServerSettings.BanList.BanPlayer("Unnamed", args[0], reason, duration); + GameMain.Server.ServerSettings.BanList.BanPlayer("Unnamed", endpoint, reason, duration); } else { foreach (Client cl in clients) { - GameMain.Server.BanClient(cl, reason, false, duration); + GameMain.Server.BanClient(cl, reason, duration); } } } @@ -1535,7 +1546,7 @@ namespace Barotrauma { if (GameMain.Server == null || args.Length == 0) return; string clientName = string.Join(" ", args); - GameMain.Server.UnbanPlayer(clientName, ""); + GameMain.Server.UnbanPlayer(clientName); }, () => { @@ -1546,17 +1557,20 @@ namespace Barotrauma }; })); - commands.Add(new Command("unbanip", "unbanip [ip]: Unban a specific IP.", (string[] args) => + commands.Add(new Command("unbanaddress", "unbanaddress [endpoint]: Unban a specific endpoint.", (string[] args) => { if (GameMain.Server == null || args.Length == 0) return; - GameMain.Server.UnbanPlayer("", args[0]); + if (Endpoint.Parse(args[0]).TryUnwrap(out var endpoint)) + { + GameMain.Server.UnbanPlayer(endpoint); + } }, () => { if (GameMain.Server == null) return null; return new string[][] { - GameMain.Server.ServerSettings.BanList.BannedEndPoints.ToArray() + GameMain.Server.ServerSettings.BanList.BannedAddresses.Select(ep => ep.ToString()).ToArray() }; })); diff --git a/Barotrauma/BarotraumaServer/ServerSource/GameMain.cs b/Barotrauma/BarotraumaServer/ServerSource/GameMain.cs index 42b514127..be7481ad2 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/GameMain.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/GameMain.cs @@ -151,9 +151,9 @@ namespace Barotrauma string password = ""; bool enableUpnp = false; - int maxPlayers = 10; - int? ownerKey = null; - UInt64 steamId = 0; + int maxPlayers = 10; + Option ownerKey = Option.None(); + Option steamId = Option.None(); XDocument doc = XMLExtensions.TryLoadXml(ServerSettings.SettingsFile); if (doc?.Root == null) @@ -169,7 +169,7 @@ namespace Barotrauma password = doc.Root.GetAttributeString("password", ""); enableUpnp = doc.Root.GetAttributeBool("enableupnp", false); maxPlayers = doc.Root.GetAttributeInt("maxplayers", 10); - ownerKey = null; + ownerKey = Option.None(); } #if DEBUG @@ -218,12 +218,12 @@ namespace Barotrauma case "-ownerkey": if (int.TryParse(CommandLineArgs[i + 1], out int key)) { - ownerKey = key; + ownerKey = Option.Some(key); } i++; break; case "-steamid": - UInt64.TryParse(CommandLineArgs[i + 1], out steamId); + steamId = SteamId.Parse(CommandLineArgs[i + 1]); i++; break; case "-pipes": @@ -274,7 +274,7 @@ namespace Barotrauma public void CloseServer() { - Server?.Disconnect(); + Server?.Quit(); ShouldRun = false; Server = null; } diff --git a/Barotrauma/BarotraumaServer/ServerSource/GameSession/GameModes/CharacterCampaignData.cs b/Barotrauma/BarotraumaServer/ServerSource/GameSession/GameModes/CharacterCampaignData.cs index 671dedf34..e81939b28 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/GameSession/GameModes/CharacterCampaignData.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/GameSession/GameModes/CharacterCampaignData.cs @@ -15,8 +15,8 @@ namespace Barotrauma public CharacterCampaignData(Client client) { Name = client.Name; - ClientEndPoint = client.Connection.EndPointString; - SteamID = client.SteamID; + ClientAddress = client.Connection.Endpoint.Address; + AccountId = client.AccountId; CharacterInfo = client.CharacterInfo; healthData = new XElement("health"); @@ -55,13 +55,13 @@ namespace Barotrauma public CharacterCampaignData(XElement element) { Name = element.GetAttributeString("name", "Unnamed"); - ClientEndPoint = element.GetAttributeString("endpoint", null) ?? element.GetAttributeString("ip", ""); - string steamID = element.GetAttributeString("steamid", ""); - if (!string.IsNullOrEmpty(steamID)) - { - ulong.TryParse(steamID, out ulong parsedID); - SteamID = parsedID; - } + string clientEndPointStr = element.GetAttributeString("address", null) + ?? element.GetAttributeString("endpoint", null) + ?? element.GetAttributeString("ip", ""); + ClientAddress = Address.Parse(clientEndPointStr).Fallback(new UnknownAddress()); + string accountIdStr = element.GetAttributeString("accountid", null) + ?? element.GetAttributeString("steamid", ""); + AccountId = Networking.AccountId.Parse(accountIdStr); foreach (XElement subElement in element.Elements()) { @@ -89,19 +89,20 @@ namespace Barotrauma public bool MatchesClient(Client client) { - if (SteamID > 0) + if (AccountId.TryUnwrap(out var accountId) + && client.AccountId.TryUnwrap(out var clientId)) { - return SteamID == client.SteamID; + return accountId == clientId; } else { - return ClientEndPoint == client.Connection.EndPointString; + return ClientAddress == client.Connection.Endpoint.Address; } } public bool IsDuplicate(CharacterCampaignData other) { - return other.SteamID == SteamID && other.ClientEndPoint == ClientEndPoint; + return AccountId == other.AccountId && other.ClientAddress == ClientAddress; } public void SpawnInventoryItems(Character character, Inventory inventory) @@ -136,8 +137,8 @@ namespace Barotrauma { XElement element = new XElement("CharacterCampaignData", new XAttribute("name", Name), - new XAttribute("endpoint", ClientEndPoint), - new XAttribute("steamid", SteamID)); + new XAttribute("address", ClientAddress), + new XAttribute("accountid", AccountId.TryUnwrap(out var accountId) ? accountId.StringRepresentation : "")); CharacterInfo?.Save(element); if (itemData != null) { element.Add(itemData); } diff --git a/Barotrauma/BarotraumaServer/ServerSource/GameSession/GameModes/MultiPlayerCampaign.cs b/Barotrauma/BarotraumaServer/ServerSource/GameSession/GameModes/MultiPlayerCampaign.cs index 61caf6e9d..e9d0dfbe0 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/GameSession/GameModes/MultiPlayerCampaign.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/GameSession/GameModes/MultiPlayerCampaign.cs @@ -6,6 +6,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Xml.Linq; +using Barotrauma.Steam; namespace Barotrauma { @@ -45,21 +46,26 @@ namespace Barotrauma class SavedExperiencePoints { - public readonly ulong SteamID; - public readonly string EndPoint; + public readonly Option AccountId; + public readonly Address Address; public readonly int ExperiencePoints; public SavedExperiencePoints(Client client) { - SteamID = client.SteamID; - EndPoint = client.Connection.EndPointString; + AccountId = client.AccountId; + Address = client.Connection.Endpoint.Address; ExperiencePoints = client.Character?.Info?.ExperiencePoints ?? 0; } public SavedExperiencePoints(XElement element) { - SteamID = element.GetAttributeUInt64("steamid", 0); - EndPoint = element.GetAttributeString("endpoint", string.Empty); + AccountId = Networking.AccountId.Parse( + element.GetAttributeString("accountid", null) + ?? element.GetAttributeString("steamid", "")); + Address = Address.Parse( + element.GetAttributeString("address", null) + ?? element.GetAttributeString("endpoint", "")) + .Fallback(new UnknownAddress()); ExperiencePoints = element.GetAttributeInt("points", 0); } } @@ -202,11 +208,11 @@ namespace Barotrauma } public int GetSavedExperiencePoints(Client client) { - return savedExperiencePoints.Find(s => s.SteamID != 0 && client.SteamID == s.SteamID || client.EndpointMatches(s.EndPoint))?.ExperiencePoints ?? 0; + return savedExperiencePoints.Find(s => client.AccountId == s.AccountId || client.Connection.Endpoint.Address == s.Address)?.ExperiencePoints ?? 0; } public void ClearSavedExperiencePoints(Client client) { - savedExperiencePoints.RemoveAll(s => s.SteamID != 0 && client.SteamID == s.SteamID || client.EndpointMatches(s.EndPoint)); + savedExperiencePoints.RemoveAll(s => client.AccountId == s.AccountId || client.Connection.Endpoint.Address == s.Address); } public void SavePlayers() @@ -805,6 +811,10 @@ namespace Barotrauma Wallet personalWallet = GetWallet(sender); personalWallet?.ForceUpdate(); + if (AllowedToManageWallets(sender)) + { + Bank.ForceUpdate(); + } if (purchasedHullRepairs != PurchasedHullRepairs) { @@ -886,7 +896,9 @@ namespace Barotrauma foreach (var item in store.Value.ToList()) { if (map?.CurrentLocation?.Stores == null || !map.CurrentLocation.Stores.ContainsKey(store.Key)) { continue; } - item.Quantity = Math.Min(map.CurrentLocation.Stores[store.Key].Stock.Find(s => s.ItemPrefab == item.ItemPrefab)?.Quantity ?? 0, item.Quantity); + int availableQuantity = map.CurrentLocation.Stores[store.Key].Stock.Find(s => s.ItemPrefab == item.ItemPrefab)?.Quantity ?? 0; + int alreadyPurchasedQuantity = CargoManager.GetBuyCrateItem(store.Key, item.ItemPrefab)?.Quantity ?? 0; + item.Quantity = Math.Min(availableQuantity - alreadyPurchasedQuantity, item.Quantity); if (item.Quantity <= 0) { continue; } CargoManager.ModifyItemQuantityInBuyCrate(store.Key, item.ItemPrefab, item.Quantity, sender); } @@ -1364,8 +1376,8 @@ namespace Barotrauma foreach (var savedExperiencePoint in savedExperiencePoints) { savedExperiencePointsElement.Add(new XElement("Point", - new XAttribute("steamid", savedExperiencePoint.SteamID), - new XAttribute("endpoint", savedExperiencePoint?.EndPoint ?? string.Empty), + new XAttribute("accountid", savedExperiencePoint.AccountId.TryUnwrap(out var accountId) ? accountId.StringRepresentation : ""), + new XAttribute("address", savedExperiencePoint.Address.StringRepresentation), new XAttribute("points", savedExperiencePoint.ExperiencePoints))); } diff --git a/Barotrauma/BarotraumaServer/ServerSource/GameSession/ReadyCheck.cs b/Barotrauma/BarotraumaServer/ServerSource/GameSession/ReadyCheck.cs index 3ac8dd6a9..d7e547b2b 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/GameSession/ReadyCheck.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/GameSession/ReadyCheck.cs @@ -26,7 +26,7 @@ namespace Barotrauma if (sender != null) { msg.Write(true); - msg.Write(sender.ID); + msg.Write(sender.SessionId); } else { @@ -99,10 +99,10 @@ namespace Barotrauma case ReadyCheckState.Update when readyCheck != null: ReadyStatus status = (ReadyStatus) inc.ReadByte(); - if (!readyCheck.Clients.ContainsKey(client.ID)) { return; } + if (!readyCheck.Clients.ContainsKey(client.SessionId)) { return; } - readyCheck.Clients[client.ID] = status; - readyCheck.UpdateReadyCheck(client.ID, status); + readyCheck.Clients[client.SessionId] = status; + readyCheck.UpdateReadyCheck(client.SessionId, status); break; } } @@ -111,8 +111,8 @@ namespace Barotrauma { if (GameMain.GameSession?.CrewManager == null || GameMain.GameSession.CrewManager.ActiveReadyCheck != null) { return; } - List connectedClients = GameMain.Server.ConnectedClients; - ReadyCheck newReadyCheck = new ReadyCheck(connectedClients.Where(c => !c.Spectating).Select(c => c.ID).ToList(), 30); + var connectedClients = GameMain.Server.ConnectedClients; + ReadyCheck newReadyCheck = new ReadyCheck(connectedClients.Where(c => !c.Spectating).Select(c => c.SessionId).ToList(), 30); GameMain.GameSession.CrewManager.ActiveReadyCheck = newReadyCheck; newReadyCheck.InitializeReadyCheck(author, sender); } diff --git a/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Machines/Fabricator.cs b/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Machines/Fabricator.cs index 347ef4ed5..bd1572c90 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Machines/Fabricator.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Machines/Fabricator.cs @@ -59,8 +59,8 @@ namespace Barotrauma.Items.Components msg.Write(timeUntilReady); uint recipeHash = fabricatedItem?.RecipeHash ?? 0; msg.Write(recipeHash); - UInt16 userID = fabricatedItem is null || user is null ? (UInt16)0 : user.ID; - msg.Write(userID); + UInt16 userId = fabricatedItem is null || user is null ? (UInt16)0 : user.ID; + msg.Write(userId); var reachedLimits = fabricationLimits.Where(kvp => kvp.Value <= 0); msg.Write((ushort)reachedLimits.Count()); diff --git a/Barotrauma/BarotraumaServer/ServerSource/Networking/BanList.cs b/Barotrauma/BarotraumaServer/ServerSource/Networking/BanList.cs index c324baf78..3b628dea4 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Networking/BanList.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Networking/BanList.cs @@ -9,56 +9,16 @@ namespace Barotrauma.Networking { partial class BannedPlayer { - private static UInt16 LastIdentifier = 0; + private static UInt32 LastIdentifier = 0; - public BannedPlayer(string name, string endPoint, string reason, DateTime? expirationTime) + public BannedPlayer( + string name, Either addressOrAccountId, string reason, DateTime? expirationTime) { this.Name = name; - this.EndPoint = endPoint; - ParseEndPointAsSteamId(); + this.AddressOrAccountId = addressOrAccountId; this.Reason = reason; this.ExpirationTime = expirationTime; this.UniqueIdentifier = LastIdentifier; LastIdentifier++; - - this.IsRangeBan = EndPoint.IndexOf(".x") > -1; - } - - public BannedPlayer(string name, ulong steamID, string reason, DateTime? expirationTime) - { - this.Name = name; - this.SteamID = steamID; - this.Reason = reason; - this.ExpirationTime = expirationTime; - this.UniqueIdentifier = LastIdentifier; LastIdentifier++; - - this.IsRangeBan = false; - - this.EndPoint = ""; - } - - public bool CompareTo(string endpointCompare) - { - if (string.IsNullOrEmpty(EndPoint) || string.IsNullOrEmpty(endpointCompare)) { return false; } - if (!IsRangeBan) - { - return endpointCompare == EndPoint; - } - else - { - int rangeBanIndex = EndPoint.IndexOf(".x"); - if (endpointCompare.Length < rangeBanIndex) return false; - return endpointCompare.Substring(0, rangeBanIndex) == EndPoint.Substring(0, rangeBanIndex); - } - } - - public bool CompareTo(IPAddress ipCompare) - { - if (string.IsNullOrEmpty(EndPoint) || ipCompare == null) { return false; } - if (ipCompare.IsIPv4MappedToIPv6 && CompareTo(ipCompare.MapToIPv4NoThrow().ToString())) - { - return true; - } - return CompareTo(ipCompare.ToString()); } } @@ -84,10 +44,10 @@ namespace Barotrauma.Networking foreach (string line in lines) { string[] separatedLine = line.Split(','); - if (separatedLine.Length < 2) continue; + if (separatedLine.Length < 2) { continue; } string name = separatedLine[0]; - string identifier = separatedLine[1]; + string endpointStr = separatedLine[1]; DateTime? expirationTime = null; if (separatedLine.Length > 2 && !string.IsNullOrEmpty(separatedLine[2])) @@ -99,84 +59,57 @@ namespace Barotrauma.Networking } string reason = separatedLine.Length > 3 ? string.Join(",", separatedLine.Skip(3)) : ""; - if (expirationTime.HasValue && DateTime.Now > expirationTime.Value) continue; + if (expirationTime.HasValue && DateTime.Now > expirationTime.Value) { continue; } - if (identifier.Contains(".") || identifier.Contains(":")) + if (AccountId.Parse(endpointStr).TryUnwrap(out var accountId)) { - //identifier is an ip - bannedPlayers.Add(new BannedPlayer(name, identifier, reason, expirationTime)); + bannedPlayers.Add(new BannedPlayer(name, accountId, reason, expirationTime)); } - else + else if (Address.Parse(endpointStr).TryUnwrap(out var address)) { - //identifier should be a steam id - if (ulong.TryParse(identifier, out ulong steamID)) - { - bannedPlayers.Add(new BannedPlayer(name, steamID, reason, expirationTime)); - } - else - { - DebugConsole.ThrowError("Error in banlist: \"" + identifier + "\" is not a valid IP or a Steam ID"); - } + bannedPlayers.Add(new BannedPlayer(name, address, reason, expirationTime)); } } } - public bool IsBanned(IPAddress IP, ulong steamID, ulong ownerSteamID, out string reason) + public void RemoveExpired() { - reason = string.Empty; - if (IPAddress.IsLoopback(IP)) { return false; } - var bannedPlayer = bannedPlayers.Find(bp => - bp.CompareTo(IP) || - (steamID > 0 && (bp.SteamID == steamID || SteamManager.SteamIDStringToUInt64(bp.EndPoint) == steamID)) || - (ownerSteamID > 0 && (bp.SteamID == ownerSteamID || SteamManager.SteamIDStringToUInt64(bp.EndPoint) == ownerSteamID))); - reason = bannedPlayer?.Reason; - return bannedPlayer != null; - } - - public bool IsBanned(IPAddress IP, out string reason) - { - reason = string.Empty; - if (IPAddress.IsLoopback(IP)) { return false; } bannedPlayers.RemoveAll(bp => bp.ExpirationTime.HasValue && DateTime.Now > bp.ExpirationTime.Value); - var bannedPlayer = bannedPlayers.Find(bp => bp.CompareTo(IP)); - reason = bannedPlayer?.Reason; + } + + public bool IsBanned(Endpoint endpoint, out string reason) + => IsBanned(endpoint.Address, out reason); + + public bool IsBanned(Address address, out string reason) + { + RemoveExpired(); + if (address.IsLocalHost) + { + reason = string.Empty; + return false; + } + var bannedPlayer = bannedPlayers.Find(bp => bp.AddressOrAccountId.TryGet(out Address adr) && address.Equals(adr)); + reason = bannedPlayer?.Reason ?? string.Empty; return bannedPlayer != null; } - public bool IsBanned(ulong steamID, out string reason) + public bool IsBanned(AccountId accountId, out string reason) { - reason = string.Empty; - bannedPlayers.RemoveAll(bp => bp.ExpirationTime.HasValue && DateTime.Now > bp.ExpirationTime.Value); - var bannedPlayer = bannedPlayers.Find(bp => - steamID > 0 && - (bp.SteamID == steamID || SteamManager.SteamIDStringToUInt64(bp.EndPoint) == steamID)); - reason = bannedPlayer?.Reason; + RemoveExpired(); + var bannedPlayer = bannedPlayers.Find(bp => bp.AddressOrAccountId.TryGet(out AccountId id) && accountId.Equals(id)); + reason = bannedPlayer?.Reason ?? string.Empty; return bannedPlayer != null; } - public void BanPlayer(string name, IPAddress ip, string reason, TimeSpan? duration) + public void BanPlayer(string name, Endpoint endpoint, string reason, TimeSpan? duration) + => BanPlayer(name, endpoint.Address, reason, duration); + + public void BanPlayer(string name, Either addressOrAccountId, string reason, TimeSpan? duration) { - string ipStr = ip.IsIPv4MappedToIPv6 ? ip.MapToIPv4NoThrow().ToString() : ip.ToString(); - BanPlayer(name, ipStr, 0, reason, duration); - } - - public void BanPlayer(string name, string endPoint, string reason, TimeSpan? duration) - { - BanPlayer(name, endPoint, 0, reason, duration); - } - - public void BanPlayer(string name, ulong steamID, string reason, TimeSpan? duration) - { - if (steamID == 0) { return; } - BanPlayer(name, "", steamID, reason, duration); - } - - private void BanPlayer(string name, string endPoint, ulong steamID, string reason, TimeSpan? duration) - { - var existingBan = bannedPlayers.Find(bp => bp.EndPoint == endPoint && bp.SteamID == steamID); + var existingBan = bannedPlayers.Find(bp => bp.AddressOrAccountId == addressOrAccountId); if (existingBan != null) { - if (!duration.HasValue) return; + if (!duration.HasValue) { return; } DebugConsole.Log("Set \"" + name + "\"'s ban duration to " + duration.Value); existingBan.ExpirationTime = DateTime.Now + duration.Value; @@ -187,8 +120,8 @@ namespace Barotrauma.Networking System.Diagnostics.Debug.Assert(!name.Contains(',')); string logMsg = "Banned " + name; - if (!string.IsNullOrEmpty(reason)) logMsg += ", reason: " + reason; - if (duration.HasValue) logMsg += ", duration: " + duration.Value.ToString(); + if (!string.IsNullOrEmpty(reason)) { logMsg += ", reason: " + reason; } + if (duration.HasValue) { logMsg += ", duration: " + duration.Value.ToString(); } DebugConsole.Log(logMsg); @@ -198,46 +131,20 @@ namespace Barotrauma.Networking expirationTime = DateTime.Now + duration.Value; } - if (!string.IsNullOrEmpty(endPoint)) - { - bannedPlayers.Add(new BannedPlayer(name, endPoint, reason, expirationTime)); - } - else if (steamID > 0) - { - bannedPlayers.Add(new BannedPlayer(name, steamID, reason, expirationTime)); - } - else - { - DebugConsole.ThrowError("Failed to ban a client (no valid IP or Steam ID given)"); - return; - } + bannedPlayers.Add(new BannedPlayer(name, addressOrAccountId, reason, expirationTime)); Save(); } - public void UnbanPlayer(string name) + public void UnbanPlayer(Endpoint endpoint) + => UnbanPlayer(endpoint.Address); + + public void UnbanPlayer(Either addressOrAccountId) { - name = name.ToLower(); - var player = bannedPlayers.Find(bp => bp.Name.ToLower() == name); + var player = bannedPlayers.Find(bp => bp.AddressOrAccountId == addressOrAccountId); if (player == null) { - DebugConsole.Log("Could not unban player \"" + name + "\". Matching player not found."); - } - else - { - RemoveBan(player); - } - } - - public void UnbanEndPoint(string endPoint) - { - ulong steamId = SteamManager.SteamIDStringToUInt64(endPoint); - var player = bannedPlayers.Find(bp => - bp.EndPoint == endPoint || - (steamId != 0 && steamId == SteamManager.SteamIDStringToUInt64(bp.EndPoint))); - if (player == null) - { - DebugConsole.Log("Could not unban endpoint \"" + endPoint + "\". Matching player not found."); + DebugConsole.Log("Could not unban endpoint \"" + addressOrAccountId + "\". Matching player not found."); } else { @@ -255,22 +162,6 @@ namespace Barotrauma.Networking Save(); } - private void RangeBan(BannedPlayer banned) - { - banned.EndPoint = ToRange(banned.EndPoint); - - BannedPlayer bp; - while ((bp = bannedPlayers.Find(x => banned.CompareTo(x.EndPoint))) != null) - { - //remove all specific bans that are now covered by the rangeban - bannedPlayers.Remove(bp); - } - - bannedPlayers.Add(banned); - - Save(); - } - public void Save() { GameServer.Log("Saving banlist", ServerLog.MessageType.ServerMessage); @@ -283,9 +174,9 @@ namespace Barotrauma.Networking foreach (BannedPlayer banned in bannedPlayers) { string line = banned.Name; - line += "," + ((banned.SteamID > 0) ? SteamManager.SteamIDUInt64ToString(banned.SteamID) : banned.EndPoint); + line += "," + (banned.AddressOrAccountId.ToString()); line += "," + (banned.ExpirationTime.HasValue ? banned.ExpirationTime.Value.ToString() : ""); - if (!string.IsNullOrWhiteSpace(banned.Reason)) line += "," + banned.Reason; + if (!string.IsNullOrWhiteSpace(banned.Reason)) { line += "," + banned.Reason; } lines.Add(line); } @@ -324,7 +215,6 @@ namespace Barotrauma.Networking outMsg.Write(bannedPlayer.Name); outMsg.Write(bannedPlayer.UniqueIdentifier); - outMsg.Write(bannedPlayer.IsRangeBan); outMsg.Write(bannedPlayer.ExpirationTime != null); outMsg.WritePadBits(); if (bannedPlayer.ExpirationTime != null) @@ -337,12 +227,19 @@ namespace Barotrauma.Networking if (c.Connection == GameMain.Server.OwnerConnection) { - outMsg.Write(bannedPlayer.EndPoint); - outMsg.Write(bannedPlayer.SteamID); + if (bannedPlayer.AddressOrAccountId.TryGet(out Address endpoint)) + { + outMsg.Write(true); outMsg.WritePadBits(); + outMsg.Write(endpoint.StringRepresentation); + } + else + { + outMsg.Write(false); outMsg.WritePadBits(); + outMsg.Write(((SteamId)bannedPlayer.AddressOrAccountId).StringRepresentation); + } } } } - catch (Exception e) { string errorMsg = "Error while writing banlist. {" + e + "}\n" + e.StackTrace.CleanupStackTrace(); @@ -355,38 +252,25 @@ namespace Barotrauma.Networking { if (!c.HasPermission(ClientPermissions.Ban)) { - UInt16 removeCount = incMsg.ReadUInt16(); - incMsg.BitPosition += removeCount * 4 * 8; - UInt16 rangeBanCount = incMsg.ReadUInt16(); - incMsg.BitPosition += rangeBanCount * 4 * 8; + UInt32 removeCount = incMsg.ReadVariableUInt32(); + incMsg.BitPosition += (int)removeCount * 4 * 8; return false; } else { - UInt16 removeCount = incMsg.ReadUInt16(); + UInt32 removeCount = incMsg.ReadVariableUInt32(); for (int i = 0; i < removeCount; i++) { - UInt16 id = incMsg.ReadUInt16(); + UInt32 id = incMsg.ReadUInt32(); BannedPlayer bannedPlayer = bannedPlayers.Find(p => p.UniqueIdentifier == id); if (bannedPlayer != null) { - GameServer.Log(GameServer.ClientLogName(c) + " unbanned " + bannedPlayer.Name + " (" + bannedPlayer.EndPoint + ")", ServerLog.MessageType.ConsoleUsage); + GameServer.Log(GameServer.ClientLogName(c) + " unbanned " + bannedPlayer.Name + " (" + bannedPlayer.AddressOrAccountId + ")", ServerLog.MessageType.ConsoleUsage); RemoveBan(bannedPlayer); } } - Int16 rangeBanCount = incMsg.ReadInt16(); - for (int i = 0; i < rangeBanCount; i++) - { - UInt16 id = incMsg.ReadUInt16(); - BannedPlayer bannedPlayer = bannedPlayers.Find(p => p.UniqueIdentifier == id); - if (bannedPlayer != null) - { - GameServer.Log(GameServer.ClientLogName(c) + " rangebanned " + bannedPlayer.Name + " (" + bannedPlayer.EndPoint + ")", ServerLog.MessageType.ConsoleUsage); - RangeBan(bannedPlayer); - } - } - return removeCount > 0 || rangeBanCount > 0; + return removeCount > 0; } } } diff --git a/Barotrauma/BarotraumaServer/ServerSource/Networking/ChatMessage.cs b/Barotrauma/BarotraumaServer/ServerSource/Networking/ChatMessage.cs index 075a0bd30..d2a56a792 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Networking/ChatMessage.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Networking/ChatMessage.cs @@ -212,7 +212,7 @@ namespace Barotrauma.Networking msg.Write(SenderClient != null); if (SenderClient != null) { - msg.Write((SenderClient.SteamID != 0) ? SenderClient.SteamID : SenderClient.ID); + msg.Write(SenderClient.AccountId.TryUnwrap(out var accountId) ? accountId.StringRepresentation : SenderClient.SessionId.ToString()); } msg.Write(Sender != null && c.InGame); if (Sender != null && c.InGame) diff --git a/Barotrauma/BarotraumaServer/ServerSource/Networking/Client.cs b/Barotrauma/BarotraumaServer/ServerSource/Networking/Client.cs index f385efcde..63c6ad087 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Networking/Client.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Networking/Client.cs @@ -57,7 +57,7 @@ namespace Barotrauma.Networking public bool ReadyToStart; - public List JobPreferences; + public List JobPreferences { get; set; } public JobVariant AssignedJob; public float DeleteDisconnectedTimer; @@ -111,7 +111,7 @@ namespace Barotrauma.Networking { JobPreferences = new List(); - VoipQueue = new VoipQueue(ID, true, true); + VoipQueue = new VoipQueue(SessionId, true, true); GameMain.Server.VoipServer.RegisterQueue(VoipQueue); //initialize to infinity, gets set to a proper value when initializing midround syncing @@ -162,7 +162,7 @@ namespace Barotrauma.Networking return true; } - public bool EndpointMatches(string endPoint) + public bool EndpointMatches(Endpoint endPoint) { return Connection.EndpointMatches(endPoint); } diff --git a/Barotrauma/BarotraumaServer/ServerSource/Networking/GameServer.cs b/Barotrauma/BarotraumaServer/ServerSource/Networking/GameServer.cs index 74984923c..ce5282fa4 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Networking/GameServer.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Networking/GameServer.cs @@ -1,5 +1,4 @@ -#define ALLOW_BOT_TRAITORS -using Barotrauma.Extensions; +using Barotrauma.Extensions; using Barotrauma.IO; using Barotrauma.Items.Components; using Barotrauma.Steam; @@ -85,7 +84,7 @@ namespace Barotrauma.Networking } #endif - public override List ConnectedClients + public override IReadOnlyList ConnectedClients { get { @@ -110,10 +109,19 @@ namespace Barotrauma.Networking public int QueryPort => serverSettings?.QueryPort ?? 0; public NetworkConnection OwnerConnection { get; private set; } - private readonly int? ownerKey; - private readonly UInt64? ownerSteamId; + private readonly Option ownerKey; + private readonly Option ownerSteamId; - public GameServer(string name, int port, int queryPort = 0, bool isPublic = false, string password = "", bool attemptUPnP = false, int maxPlayers = 10, int? ownKey = null, UInt64? steamId = null) + public GameServer( + string name, + int port, + int queryPort, + bool isPublic, + string password, + bool attemptUPnP, + int maxPlayers, + Option ownerKey, + Option ownerSteamId) { name = name.Replace(":", ""); name = name.Replace(";", ""); @@ -132,9 +140,9 @@ namespace Barotrauma.Networking Voting = new Voting(); - ownerKey = ownKey; + this.ownerKey = ownerKey; - ownerSteamId = steamId; + this.ownerSteamId = ownerSteamId; entityEventManager = new ServerEntityEventManager(this); @@ -147,15 +155,15 @@ namespace Barotrauma.Networking try { Log("Starting the server...", ServerLog.MessageType.ServerMessage); - if (!ownerSteamId.HasValue || ownerSteamId.Value == 0) + if (ownerSteamId.TryUnwrap(out var steamId)) { - Log("Using Lidgren networking. Manual port forwarding may be required. If players cannot connect to the server, you may want to use the in-game hosting menu (which uses SteamP2P networking and does not require port forwarding).", ServerLog.MessageType.ServerMessage); - serverPeer = new LidgrenServerPeer(ownerKey, serverSettings); + Log("Using SteamP2P networking.", ServerLog.MessageType.ServerMessage); + serverPeer = new SteamP2PServerPeer(steamId, ownerKey.Fallback(0), serverSettings); } else { - Log("Using SteamP2P networking.", ServerLog.MessageType.ServerMessage); - serverPeer = new SteamP2PServerPeer(ownerSteamId.Value, ownerKey.Value, serverSettings); + Log("Using Lidgren networking. Manual port forwarding may be required. If players cannot connect to the server, you may want to use the in-game hosting menu (which uses SteamP2P networking and does not require port forwarding).", ServerLog.MessageType.ServerMessage); + serverPeer = new LidgrenServerPeer(ownerKey, serverSettings); } serverPeer.OnInitializationComplete = OnInitializationComplete; @@ -253,17 +261,15 @@ namespace Barotrauma.Networking Thread.Sleep(500); } - private void OnInitializationComplete(NetworkConnection connection) + private void OnInitializationComplete(NetworkConnection connection, string clientName) { - string clName = connection.Name; - Client newClient = new Client(clName, GetNewClientID()); + Client newClient = new Client(clientName, GetNewClientSessionId()); newClient.InitClientSync(); newClient.Connection = connection; newClient.Connection.Status = NetworkConnectionStatus.Connected; - newClient.SteamID = connection.SteamID; - newClient.OwnerSteamID = connection.OwnerSteamID; + newClient.AccountInfo = connection.AccountInfo; newClient.Language = connection.Language; - ConnectedClients.Add(newClient); + connectedClients.Add(newClient); var previousPlayer = previousPlayers.Find(p => p.MatchesClient(newClient)); if (previousPlayer != null) @@ -299,10 +305,10 @@ namespace Barotrauma.Networking previousPlayer.Name = newClient.Name; } - var savedPermissions = serverSettings.ClientPermissions.Find(cp => - cp.SteamID > 0 ? - cp.SteamID == newClient.SteamID : - newClient.EndpointMatches(cp.EndPoint)); + var savedPermissions = serverSettings.ClientPermissions.Find(scp => + scp.AddressOrAccountId.TryGet(out AccountId accountId) + ? newClient.AccountId.ValueEquals(accountId) + : newClient.Connection.Endpoint.Address == scp.AddressOrAccountId); if (savedPermissions != null) { @@ -346,7 +352,7 @@ namespace Barotrauma.Networking if (OwnerConnection != null && ChildServerRelay.HasShutDown) { - Disconnect(); + Quit(); return; } @@ -377,7 +383,7 @@ namespace Barotrauma.Networking character.KillDisconnectedTimer += deltaTime; character.SetStun(1.0f); - Client owner = connectedClients.Find(c => (c.Character == null || c.Character == character) && c.EndpointMatches(character.OwnerClientEndPoint)); + Client owner = connectedClients.Find(c => (c.Character == null || c.Character == character) && c.EndpointMatches(character.OwnerClientEndpoint)); if ((OwnerConnection == null || owner?.Connection != OwnerConnection) && character.KillDisconnectedTimer > serverSettings.KillDisconnectedTime) { @@ -679,7 +685,7 @@ namespace Barotrauma.Networking pingInf.Write((byte)ConnectedClients.Count); ConnectedClients.ForEach(c2 => { - pingInf.Write(c2.ID); + pingInf.Write(c2.SessionId); pingInf.Write(c2.Ping); }); serverPeer.Send(pingInf, c.Connection, DeliveryMethod.Unreliable); @@ -788,11 +794,11 @@ namespace Barotrauma.Networking if (serverSettings.VoiceChatEnabled && !connectedClient.Muted) { byte id = inc.ReadByte(); - if (connectedClient.ID != id) + if (connectedClient.SessionId != id) { #if DEBUG DebugConsole.ThrowError( - "Client \"" + connectedClient.Name + "\" sent a VOIP update that didn't match its ID (" + id.ToString() + "!=" + connectedClient.ID.ToString() + ")"); + "Client \"" + connectedClient.Name + "\" sent a VOIP update that didn't match its ID (" + id.ToString() + "!=" + connectedClient.SessionId.ToString() + ")"); #endif return; } @@ -1010,14 +1016,14 @@ namespace Barotrauma.Networking entityEventManager.CreateEvent(serverSerializable, extraData); } - private byte GetNewClientID() + private byte GetNewClientSessionId() { - byte userID = 1; - while (connectedClients.Any(c => c.ID == userID)) + byte userId = 1; + while (connectedClients.Any(c => c.SessionId == userId)) { - userID++; + userId++; } - return userID; + return userId; } private void ClientReadLobby(IReadMessage inc) @@ -1165,6 +1171,12 @@ namespace Barotrauma.Networking DebugConsole.Log("Finished midround syncing " + c.Name + " - switching from ID " + prevID + " to " + c.LastRecvEntityEventID); //notify the client of the state of the respawn manager (so they show the respawn prompt if needed) if (respawnManager != null) { CreateEntityEvent(respawnManager); } + if (GameMain.GameSession?.GameMode is MultiPlayerCampaign campaign) + { + //notify the client of the current bank balance and purchased repairs + campaign.Bank.ForceUpdate(); + campaign.IncrementLastUpdateIdForFlag(MultiPlayerCampaign.NetFlags.Misc); + } } else { @@ -1189,7 +1201,7 @@ namespace Barotrauma.Networking { //give midround-joining clients a bit more time to get in sync if they keep receiving messages int receivedEventCount = lastRecvEntityEventID - c.LastRecvEntityEventID; - if (receivedEventCount < 0) receivedEventCount += ushort.MaxValue; + if (receivedEventCount < 0) { receivedEventCount += ushort.MaxValue; } c.MidRoundSyncTimeOut += receivedEventCount * 0.01f; DebugConsole.Log("Midround sync timeout " + c.MidRoundSyncTimeOut.ToString("0.##") + "/" + Timing.TotalTime.ToString("0.##")); } @@ -1241,7 +1253,7 @@ namespace Barotrauma.Networking } //don't read further messages if the client has been disconnected (kicked due to spam for example) - if (!connectedClients.Contains(c)) break; + if (!connectedClients.Contains(c)) { break; } } } @@ -1341,7 +1353,6 @@ namespace Barotrauma.Networking case ClientPermissions.Ban: string bannedName = inc.ReadString().ToLowerInvariant(); string banReason = inc.ReadString(); - bool range = inc.ReadBoolean(); double durationSeconds = inc.ReadDouble(); TimeSpan? banDuration = null; @@ -1351,7 +1362,7 @@ namespace Barotrauma.Networking if (bannedClient != null) { Log("Client \"" + ClientLogName(sender) + "\" banned \"" + ClientLogName(bannedClient) + "\".", ServerLog.MessageType.ServerMessage); - BanClient(bannedClient, string.IsNullOrEmpty(banReason) ? $"ServerMessage.BannedBy~[initiator]={sender.Name}" : banReason, range, banDuration); + BanClient(bannedClient, string.IsNullOrEmpty(banReason) ? $"ServerMessage.BannedBy~[initiator]={sender.Name}" : banReason, banDuration); } else { @@ -1359,7 +1370,7 @@ namespace Barotrauma.Networking if (bannedPreviousClient != null) { Log("Client \"" + ClientLogName(sender) + "\" banned \"" + bannedPreviousClient.Name + "\".", ServerLog.MessageType.ServerMessage); - BanPreviousPlayer(bannedPreviousClient, string.IsNullOrEmpty(banReason) ? $"ServerMessage.BannedBy~[initiator]={sender.Name}" : banReason, range, banDuration); + BanPreviousPlayer(bannedPreviousClient, string.IsNullOrEmpty(banReason) ? $"ServerMessage.BannedBy~[initiator]={sender.Name}" : banReason, banDuration); } else { @@ -1368,9 +1379,16 @@ namespace Barotrauma.Networking } break; case ClientPermissions.Unban: - string unbannedName = inc.ReadString(); - string unbannedIP = inc.ReadString(); - UnbanPlayer(unbannedName, unbannedIP); + bool isPlayerName = inc.ReadBoolean(); inc.ReadPadBits(); + string str = inc.ReadString(); + if (isPlayerName) + { + UnbanPlayer(playerName: str); + } + else if (Endpoint.Parse(str).TryUnwrap(out var endpoint)) + { + UnbanPlayer(endpoint); + } break; case ClientPermissions.ManageRound: bool end = inc.ReadBoolean(); @@ -1506,7 +1524,7 @@ namespace Barotrauma.Networking break; case ClientPermissions.ManagePermissions: byte targetClientID = inc.ReadByte(); - Client targetClient = connectedClients.Find(c => c.ID == targetClientID); + Client targetClient = connectedClients.Find(c => c.SessionId == targetClientID); if (targetClient == null || targetClient == sender || targetClient.Connection == OwnerConnection) { return; } targetClient.ReadPermissions(inc); @@ -1592,7 +1610,7 @@ namespace Barotrauma.Networking DebugConsole.NewMessage("Sending initial lobby update", Color.Gray); } - outmsg.Write(c.ID); + outmsg.Write(c.SessionId); var subList = GameMain.NetLobbyScreen.GetSubList(); outmsg.Write((UInt16)subList.Count); @@ -1811,15 +1829,15 @@ namespace Barotrauma.Networking { var tempClientData = new TempClient { - ID = client.ID, - SteamID = client.SteamID, - NameID = client.NameID, + SessionId = client.SessionId, + AccountInfo = client.AccountInfo, + NameId = client.NameId, Name = client.Name, PreferredJob = client.Character?.Info?.Job != null && gameStarted ? client.Character.Info.Job.Prefab.Identifier : client.PreferredJob, PreferredTeam = client.PreferredTeam, - CharacterID = client.Character == null || !gameStarted ? (ushort)0 : client.Character.ID, + CharacterId = client.Character == null || !gameStarted ? (ushort)0 : client.Character.ID, Karma = c.HasPermission(ClientPermissions.ServerLog) ? client.Karma : 100.0f, Muted = client.Muted, InGame = client.InGame, @@ -2382,7 +2400,7 @@ namespace Barotrauma.Networking mpCampaign.ClearSavedExperiencePoints(teamClients[i]); } - spawnedCharacter.OwnerClientEndPoint = teamClients[i].Connection.EndPointString; + spawnedCharacter.OwnerClientEndpoint = teamClients[i].Connection.Endpoint; spawnedCharacter.OwnerClientName = teamClients[i].Name; } @@ -2693,9 +2711,15 @@ namespace Barotrauma.Networking Identifier newJob = inc.ReadIdentifier(); CharacterTeamType newTeam = (CharacterTeamType)inc.ReadByte(); - if (c == null || string.IsNullOrEmpty(newName) || !NetIdUtils.IdMoreRecent(nameId, c.NameID)) { return false; } - - c.NameID = nameId; + if (c == null || string.IsNullOrEmpty(newName) || !NetIdUtils.IdMoreRecent(nameId, c.NameId)) { return false; } + if (!newJob.IsEmpty) + { + if (!JobPrefab.Prefabs.TryGet(newJob, out JobPrefab newJobPrefab) || newJobPrefab.HiddenJob) + { + newJob = Identifier.Empty; + } + } + c.NameId = nameId; if (newName == c.Name && newJob == c.PreferredJob && newTeam == c.PreferredTeam) { return false; } c.PreferredJob = newJob; c.PreferredTeam = newTeam; @@ -2716,7 +2740,6 @@ namespace Barotrauma.Networking { string oldName = c.Name; c.Name = newName; - c.Connection.Name = newName; SendChatMessage($"ServerMessage.NameChangeSuccessful~[oldname]={oldName}~[newname]={newName}", ChatMessageType.Server); return true; } @@ -2797,7 +2820,7 @@ namespace Barotrauma.Networking DisconnectClient(client, logMsg, msg, reason, PlayerConnectionChangeType.Kicked); } - public override void BanPlayer(string playerName, string reason, bool range = false, TimeSpan? duration = null) + public override void BanPlayer(string playerName, string reason, TimeSpan? duration = null) { Client client = connectedClients.Find(c => c.Name.Equals(playerName, StringComparison.OrdinalIgnoreCase) || @@ -2809,10 +2832,10 @@ namespace Barotrauma.Networking return; } - BanClient(client, reason, range, duration); + BanClient(client, reason, duration); } - public void BanClient(Client client, string reason, bool range = false, TimeSpan? duration = null) + public void BanClient(Client client, string reason, TimeSpan? duration = null) { if (client == null || client.Connection == OwnerConnection) { return; } @@ -2827,45 +2850,32 @@ namespace Barotrauma.Networking string targetMsg = DisconnectReason.Banned.ToString(); DisconnectClient(client, $"ServerMessage.BannedFromServer~[client]={client.Name}", targetMsg, reason, PlayerConnectionChangeType.Banned); - if (client.Connection is LidgrenConnection lidgrenConn && (client.SteamID == 0 || range)) + serverSettings.BanList.BanPlayer(client.Name, client.Connection.Endpoint, reason, duration); + if (client.AccountInfo.AccountId.TryUnwrap(out var accountId)) { - string ip = ""; - ip = lidgrenConn.IPEndPoint.Address.IsIPv4MappedToIPv6 ? - lidgrenConn.IPEndPoint.Address.MapToIPv4NoThrow().ToString() : - lidgrenConn.IPEndPoint.Address.ToString(); - if (range) { ip = BanList.ToRange(ip); } - serverSettings.BanList.BanPlayer(client.Name, ip, reason, duration); + serverSettings.BanList.BanPlayer(client.Name, accountId, reason, duration); } - if (client.SteamID > 0) + foreach (var relatedId in client.AccountInfo.OtherMatchingIds) { - serverSettings.BanList.BanPlayer(client.Name, client.SteamID, reason, duration); - } - if (client.OwnerSteamID > 0) - { - serverSettings.BanList.BanPlayer(client.Name, client.OwnerSteamID, reason, duration); + serverSettings.BanList.BanPlayer(client.Name, relatedId, reason, duration); } } - public void BanPreviousPlayer(PreviousPlayer previousPlayer, string reason, bool range = false, TimeSpan? duration = null) + public void BanPreviousPlayer(PreviousPlayer previousPlayer, string reason, TimeSpan? duration = null) { if (previousPlayer == null) { return; } //reset karma to a neutral value, so if/when the ban is revoked the client wont get immediately punished by low karma again previousPlayer.Karma = Math.Max(previousPlayer.Karma, 50.0f); - if (!string.IsNullOrEmpty(previousPlayer.EndPoint) && (previousPlayer.SteamID == 0 || range)) + serverSettings.BanList.BanPlayer(previousPlayer.Name, previousPlayer.Endpoint, reason, duration); + if (previousPlayer.AccountInfo.AccountId.TryUnwrap(out var accountId)) { - string ip = previousPlayer.EndPoint; - if (range) { ip = BanList.ToRange(ip); } - serverSettings.BanList.BanPlayer(previousPlayer.Name, ip, reason, duration); + serverSettings.BanList.BanPlayer(previousPlayer.Name, accountId, reason, duration); } - if (previousPlayer.SteamID > 0) + foreach (var relatedId in previousPlayer.AccountInfo.OtherMatchingIds) { - serverSettings.BanList.BanPlayer(previousPlayer.Name, previousPlayer.SteamID, reason, duration); - } - if (previousPlayer.OwnerSteamID > 0) - { - serverSettings.BanList.BanPlayer(previousPlayer.Name, previousPlayer.OwnerSteamID, reason, duration); + serverSettings.BanList.BanPlayer(previousPlayer.Name, relatedId, reason, duration); } string msg = $"ServerMessage.BannedFromServer~[client]={previousPlayer.Name}"; @@ -2876,16 +2886,17 @@ namespace Barotrauma.Networking SendChatMessage(msg, ChatMessageType.Server, changeType: PlayerConnectionChangeType.Banned); } - public override void UnbanPlayer(string playerName, string playerEndPoint) + public override void UnbanPlayer(string playerName) { - if (!string.IsNullOrEmpty(playerEndPoint)) - { - serverSettings.BanList.UnbanEndPoint(playerEndPoint); - } - else if (!string.IsNullOrEmpty(playerName)) - { - serverSettings.BanList.UnbanPlayer(playerName); - } + BannedPlayer bannedPlayer + = serverSettings.BanList.BannedPlayers.FirstOrDefault(bp => bp.Name == playerName); + if (bannedPlayer is null) { return; } + serverSettings.BanList.UnbanPlayer(bannedPlayer.AddressOrAccountId); + } + + public override void UnbanPlayer(Endpoint endpoint) + { + serverSettings.BanList.UnbanPlayer(endpoint); } public void DisconnectClient(NetworkConnection senderConnection, string msg = "", string targetmsg = "") @@ -2906,7 +2917,7 @@ namespace Barotrauma.Networking { if (client == null) return; - if (gameStarted && client.Character != null) + if (client.Character != null) { client.Character.ClientDisconnected = true; client.Character.ClearInputs(); @@ -2925,7 +2936,7 @@ namespace Barotrauma.Networking targetmsg += $"/\n/ServerMessage.Reason/: /{reason}"; } - if (client.SteamID != 0) { SteamManager.StopAuthSession(client.SteamID); } + if (client.AccountId is Some { Value: SteamId steamId }) { SteamManager.StopAuthSession(steamId); } var previousPlayer = previousPlayers.Find(p => p.MatchesClient(client)); if (previousPlayer == null) @@ -3363,26 +3374,26 @@ namespace Barotrauma.Networking public void UpdateClientPermissions(Client client) { - if (client.SteamID > 0) + if (client.AccountId.TryUnwrap(out var accountId)) { - serverSettings.ClientPermissions.RemoveAll(cp => cp.SteamID == client.SteamID); + serverSettings.ClientPermissions.RemoveAll(scp => scp.AddressOrAccountId == accountId); if (client.Permissions != ClientPermissions.None) { serverSettings.ClientPermissions.Add(new ServerSettings.SavedClientPermission( client.Name, - client.SteamID, + accountId, client.Permissions, client.PermittedConsoleCommands)); } } else { - serverSettings.ClientPermissions.RemoveAll(cp => client.EndpointMatches(cp.EndPoint)); + serverSettings.ClientPermissions.RemoveAll(scp => client.Connection.Endpoint.Address == scp.AddressOrAccountId); if (client.Permissions != ClientPermissions.None) { serverSettings.ClientPermissions.Add(new ServerSettings.SavedClientPermission( client.Name, - client.Connection.EndPointString, + client.Connection.Endpoint.Address, client.Permissions, client.PermittedConsoleCommands)); } @@ -3504,7 +3515,7 @@ namespace Barotrauma.Networking if (client.Character != null) { client.Character.IsRemotePlayer = false; - client.Character.OwnerClientEndPoint = null; + client.Character.OwnerClientEndpoint = null; client.Character.OwnerClientName = null; } @@ -3531,7 +3542,7 @@ namespace Barotrauma.Networking newCharacter.Info.Character = newCharacter; } - newCharacter.OwnerClientEndPoint = client.Connection.EndPointString; + newCharacter.OwnerClientEndpoint = client.Connection.Endpoint; newCharacter.OwnerClientName = client.Name; newCharacter.IsRemotePlayer = true; newCharacter.Enabled = true; @@ -3920,17 +3931,7 @@ namespace Barotrauma.Networking } } - public Tuple FindPreviousClientData(Client client) - { - var player = previousPlayers.Find(p => p.MatchesClient(client)); - if (player != null) - { - return Tuple.Create(player.SteamID, player.EndPoint); - } - return null; - } - - public override void Disconnect() + public override void Quit() { if (started) { @@ -3959,12 +3960,11 @@ namespace Barotrauma.Networking } } - partial class PreviousPlayer + class PreviousPlayer { public string Name; - public string EndPoint; - public UInt64 SteamID; - public UInt64 OwnerSteamID; + public Endpoint Endpoint; + public AccountInfo AccountInfo; public float Karma; public int KarmaKickCount; public readonly List KickVoters = new List(); @@ -3972,15 +3972,14 @@ namespace Barotrauma.Networking public PreviousPlayer(Client c) { Name = c.Name; - EndPoint = c.Connection?.EndPointString ?? ""; - SteamID = c.SteamID; - OwnerSteamID = c.OwnerSteamID; + Endpoint = c.Connection.Endpoint; + AccountInfo = c.AccountInfo; } public bool MatchesClient(Client c) { - if (c.SteamID > 0 && SteamID > 0) { return c.SteamID == SteamID; } - return c.EndpointMatches(EndPoint); + if (c.AccountInfo.AccountId.IsSome() && AccountInfo.AccountId.IsSome()) { return c.AccountInfo.AccountId == AccountInfo.AccountId; } + return c.EndpointMatches(Endpoint); } } } diff --git a/Barotrauma/BarotraumaServer/ServerSource/Networking/OrderChatMessage.cs b/Barotrauma/BarotraumaServer/ServerSource/Networking/OrderChatMessage.cs index 1aad3a99d..0cb30a078 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Networking/OrderChatMessage.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Networking/OrderChatMessage.cs @@ -1,4 +1,5 @@ -using System; +using Barotrauma.Steam; +using System; namespace Barotrauma.Networking { @@ -13,7 +14,7 @@ namespace Barotrauma.Networking msg.Write(SenderClient != null); if (SenderClient != null) { - msg.Write((SenderClient.SteamID != 0) ? SenderClient.SteamID : SenderClient.ID); + msg.Write(SenderClient.AccountId.TryUnwrap(out var accountId) ? accountId.StringRepresentation : SenderClient.SessionId.ToString()); } msg.Write(Sender != null && c.InGame); if (Sender != null && c.InGame) diff --git a/Barotrauma/BarotraumaServer/ServerSource/Networking/Primitives/Peers/Server/LidgrenServerPeer.cs b/Barotrauma/BarotraumaServer/ServerSource/Networking/Primitives/Peers/Server/LidgrenServerPeer.cs index 6e52af5c4..4cea49857 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Networking/Primitives/Peers/Server/LidgrenServerPeer.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Networking/Primitives/Peers/Server/LidgrenServerPeer.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Net; using System.Linq; +using Barotrauma.Steam; using Lidgren.Network; namespace Barotrauma.Networking @@ -13,7 +14,7 @@ namespace Barotrauma.Networking private readonly List incomingLidgrenMessages; - public LidgrenServerPeer(int? ownKey, ServerSettings settings) + public LidgrenServerPeer(Option ownKey, ServerSettings settings) { serverSettings = settings; @@ -184,7 +185,7 @@ namespace Barotrauma.Networking return; } - if (serverSettings.BanList.IsBanned(inc.SenderConnection.RemoteEndPoint.Address, 0, 0, out string banReason)) + if (serverSettings.BanList.IsBanned(new LidgrenEndpoint(inc.SenderConnection.RemoteEndPoint), out string banReason)) { //IP banned: deny immediately inc.SenderConnection.Deny(DisconnectReason.Banned.ToString() + "/ " + banReason); @@ -195,7 +196,7 @@ namespace Barotrauma.Networking if (pendingClient == null) { - pendingClient = new PendingClient(new LidgrenConnection("PENDING", inc.SenderConnection, 0)); + pendingClient = new PendingClient(new LidgrenConnection(inc.SenderConnection)); pendingClients.Add(pendingClient); } @@ -206,7 +207,7 @@ namespace Barotrauma.Networking { if (netServer == null) { return; } - PendingClient pendingClient = pendingClients.Find(c => (c.Connection is LidgrenConnection l) && l.NetConnection == inc.SenderConnection); + PendingClient pendingClient = pendingClients.Find(c => c.Connection is LidgrenConnection l && l.NetConnection == inc.SenderConnection); PacketHeader packetHeader = (PacketHeader)inc.ReadByte(); @@ -231,7 +232,9 @@ namespace Barotrauma.Networking return; } if (pendingClient != null) { pendingClients.Remove(pendingClient); } - if (serverSettings.BanList.IsBanned(conn.IPEndPoint.Address, conn.SteamID, conn.OwnerSteamID, out string banReason)) + if (serverSettings.BanList.IsBanned(conn.Endpoint, out string banReason) + || (conn.AccountInfo.AccountId.TryUnwrap(out var accountId) && serverSettings.BanList.IsBanned(accountId, out banReason)) + || conn.AccountInfo.OtherMatchingIds.Any(id => serverSettings.BanList.IsBanned(id, out banReason))) { Disconnect(conn, DisconnectReason.Banned.ToString() + "/ " + banReason); return; @@ -264,7 +267,7 @@ namespace Barotrauma.Networking } else { - disconnectMsg = $"ServerMessage.HasDisconnected~[client]={conn.Name}"; + disconnectMsg = $"ServerMessage.HasDisconnected~[client]={GameMain.Server.ConnectedClients.First(c => c.Connection == conn).Name}"; Disconnect(conn, disconnectMsg); } } @@ -285,18 +288,18 @@ namespace Barotrauma.Networking Steamworks.SteamServer.OnValidateAuthTicketResponse += OnAuthChange; } - private void OnAuthChange(Steamworks.SteamId steamID, Steamworks.SteamId ownerID, Steamworks.AuthResponse status) + private void OnAuthChange(Steamworks.SteamId steamId, Steamworks.SteamId ownerId, Steamworks.AuthResponse status) { if (netServer == null) { return; } - PendingClient pendingClient = pendingClients.Find(c => c.SteamID == steamID); - DebugConsole.Log(steamID + " validation: " + status+", "+(pendingClient!=null)); + PendingClient pendingClient = pendingClients.Find(c => c.AccountInfo.AccountId is Some { Value: SteamId id } && id.Value == steamId); + DebugConsole.Log(steamId + " validation: " + status+", "+(pendingClient!=null)); if (pendingClient == null) { if (status != Steamworks.AuthResponse.OK) { - LidgrenConnection connection = connectedClients.Find(c => c.SteamID == steamID) as LidgrenConnection; + LidgrenConnection connection = connectedClients.Find(c => c.AccountInfo.AccountId is Some { Value: SteamId id } && id.Value == steamId) as LidgrenConnection; if (connection != null) { Disconnect(connection, DisconnectReason.SteamAuthenticationFailed.ToString() + "/ Steam authentication status changed: " + status.ToString()); @@ -307,7 +310,9 @@ namespace Barotrauma.Networking LidgrenConnection pendingConnection = pendingClient.Connection as LidgrenConnection; string banReason; - if (serverSettings.BanList.IsBanned(pendingConnection.NetConnection.RemoteEndPoint.Address, steamID, ownerID, out banReason)) + if (serverSettings.BanList.IsBanned(pendingConnection.Endpoint, out banReason) + || serverSettings.BanList.IsBanned(new SteamId(steamId), out banReason) + || serverSettings.BanList.IsBanned(new SteamId(ownerId), out banReason)) { RemovePendingClient(pendingClient, DisconnectReason.Banned, banReason); return; @@ -315,7 +320,7 @@ namespace Barotrauma.Networking if (status == Steamworks.AuthResponse.OK) { - pendingClient.OwnerSteamID = ownerID; + pendingClient.Connection.SetAccountInfo(new AccountInfo(new SteamId(steamId), new SteamId(ownerId))); pendingClient.InitializationStep = serverSettings.HasPassword ? ConnectionInitialization.Password : ConnectionInitialization.ContentPackageOrder; pendingClient.UpdateTime = Timing.TotalTime; } @@ -333,7 +338,7 @@ namespace Barotrauma.Networking if (!(conn is LidgrenConnection lidgrenConn)) return; if (!connectedClients.Contains(lidgrenConn)) { - DebugConsole.ThrowError("Tried to send message to unauthenticated connection: " + lidgrenConn.IPString); + DebugConsole.ThrowError("Tried to send message to unauthenticated connection: " + lidgrenConn.Endpoint.StringRepresentation); return; } @@ -368,7 +373,7 @@ namespace Barotrauma.Networking NetSendResult result = netServer.SendMessage(lidgrenMsg, lidgrenConn.NetConnection, lidgrenDeliveryMethod); if (result != NetSendResult.Sent && result != NetSendResult.Queued) { - DebugConsole.NewMessage("Failed to send message to "+conn.Name+": " + result.ToString(), Microsoft.Xna.Framework.Color.Yellow); + DebugConsole.NewMessage("Failed to send message to "+conn.Endpoint.StringRepresentation+": " + result.ToString(), Microsoft.Xna.Framework.Color.Yellow); } } @@ -382,7 +387,7 @@ namespace Barotrauma.Networking lidgrenConn.Status = NetworkConnectionStatus.Disconnected; connectedClients.Remove(lidgrenConn); OnDisconnect?.Invoke(conn, msg); - Steam.SteamManager.StopAuthSession(conn.SteamID); + if (conn.AccountInfo.AccountId is Some { Value: SteamId steamId }) { Steam.SteamManager.StopAuthSession(steamId); } } lidgrenConn.NetConnection.Disconnect(msg ?? "Disconnected"); } @@ -409,25 +414,25 @@ namespace Barotrauma.Networking NetSendResult result = netServer.SendMessage(lidgrenMsg, lidgrenConn.NetConnection, lidgrenDeliveryMethod); if (result != NetSendResult.Sent && result != NetSendResult.Queued) { - DebugConsole.NewMessage("Failed to send message to " + conn.Name + ": " + result.ToString(), Microsoft.Xna.Framework.Color.Yellow); + DebugConsole.NewMessage("Failed to send message to " + conn.Endpoint.StringRepresentation + ": " + result.ToString(), Microsoft.Xna.Framework.Color.Yellow); } } protected override void CheckOwnership(PendingClient pendingClient) { - LidgrenConnection l = pendingClient.Connection as LidgrenConnection; - if (OwnerConnection == null && - IPAddress.IsLoopback(l.NetConnection.RemoteEndPoint.Address.MapToIPv4NoThrow()) && - ownerKey != null && pendingClient.OwnerKey != 0 && pendingClient.OwnerKey == ownerKey) + if (OwnerConnection == null + && pendingClient.Connection is LidgrenConnection l + && IPAddress.IsLoopback(l.NetConnection.RemoteEndPoint.Address) + && ownerKey.IsSome() && pendingClient.OwnerKey == ownerKey) { - ownerKey = null; + ownerKey = Option.None(); OwnerConnection = pendingClient.Connection; } } - protected override void ProcessAuthTicket(string name, int ownKey, ulong steamId, PendingClient pendingClient, byte[] ticket) + protected override void ProcessAuthTicket(string name, Option ownKey, Option steamId, PendingClient pendingClient, byte[] ticket) { - if (pendingClient.SteamID == null) + if (pendingClient.AccountInfo.AccountId.IsNone()) { bool requireSteamAuth = GameSettings.CurrentConfig.RequireSteamAuthentication; #if DEBUG @@ -436,32 +441,42 @@ namespace Barotrauma.Networking //steam auth cannot be done (SteamManager not initialized or no ticket given), //but it's not required either -> let the client join without auth - if ((!Steam.SteamManager.IsInitialized || (ticket?.Length ?? 0) == 0) && - !requireSteamAuth) + if ((!SteamManager.IsInitialized || (ticket?.Length ?? 0) == 0) + && !requireSteamAuth) { - pendingClient.Connection.Name = name; pendingClient.Name = name; pendingClient.OwnerKey = ownKey; pendingClient.InitializationStep = serverSettings.HasPassword ? ConnectionInitialization.Password : ConnectionInitialization.ContentPackageOrder; } else { - Steamworks.BeginAuthResult authSessionStartState = Steam.SteamManager.StartAuthSession(ticket, steamId); - if (authSessionStartState != Steamworks.BeginAuthResult.OK) + if (!steamId.TryUnwrap(out var id)) { if (requireSteamAuth) { - RemovePendingClient(pendingClient, DisconnectReason.SteamAuthenticationFailed, "Steam auth session failed to start: " + authSessionStartState.ToString()); + RemovePendingClient(pendingClient, DisconnectReason.SteamAuthenticationFailed, "Steam auth session failed to start: Steam ID not provided"); return; } - else + } + else + { + Steamworks.BeginAuthResult authSessionStartState = Steam.SteamManager.StartAuthSession(ticket, id); + if (authSessionStartState != Steamworks.BeginAuthResult.OK) { - steamId = 0; - pendingClient.InitializationStep = serverSettings.HasPassword ? ConnectionInitialization.Password : ConnectionInitialization.ContentPackageOrder; + if (requireSteamAuth) + { + RemovePendingClient(pendingClient, DisconnectReason.SteamAuthenticationFailed, "Steam auth session failed to start: " + authSessionStartState.ToString()); + return; + } + else + { + steamId = Option.None(); + pendingClient.InitializationStep = serverSettings.HasPassword ? ConnectionInitialization.Password : ConnectionInitialization.ContentPackageOrder; + } } } - pendingClient.SteamID = steamId; - pendingClient.Connection.Name = name; + + pendingClient.Connection.SetAccountInfo(new AccountInfo(steamId.Select(uid => (AccountId)uid))); pendingClient.Name = name; pendingClient.OwnerKey = ownKey; pendingClient.AuthSessionStarted = true; @@ -469,7 +484,7 @@ namespace Barotrauma.Networking } else { - if (pendingClient.SteamID != steamId) + if (pendingClient.AccountInfo.AccountId != steamId.Select(uid => (AccountId)uid)) { RemovePendingClient(pendingClient, DisconnectReason.SteamAuthenticationFailed, "SteamID mismatch"); return; diff --git a/Barotrauma/BarotraumaServer/ServerSource/Networking/Primitives/Peers/Server/ServerPeer.cs b/Barotrauma/BarotraumaServer/ServerSource/Networking/Primitives/Peers/Server/ServerPeer.cs index bdd1fc790..f70f77724 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Networking/Primitives/Peers/Server/ServerPeer.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Networking/Primitives/Peers/Server/ServerPeer.cs @@ -1,8 +1,7 @@ using System; using System.Collections.Generic; -using System.Diagnostics; using System.Linq; -using System.Text; +using Barotrauma.Extensions; namespace Barotrauma.Networking { @@ -10,7 +9,7 @@ namespace Barotrauma.Networking { public delegate void MessageCallback(NetworkConnection connection, IReadMessage message); public delegate void DisconnectCallback(NetworkConnection connection, string reason); - public delegate void InitializationCompleteCallback(NetworkConnection connection); + public delegate void InitializationCompleteCallback(NetworkConnection connection, string clientName); public delegate void ShutdownCallback(); public delegate void OwnerDeterminedCallback(NetworkConnection connection); @@ -20,7 +19,7 @@ namespace Barotrauma.Networking public ShutdownCallback OnShutdown; public OwnerDeterminedCallback OnOwnerDetermined; - protected int? ownerKey; + protected Option ownerKey; public NetworkConnection OwnerConnection { get; protected set; } @@ -33,43 +32,23 @@ namespace Barotrauma.Networking protected class PendingClient { public string Name; - public int OwnerKey; + public Option OwnerKey; public NetworkConnection Connection; public ConnectionInitialization InitializationStep; public double UpdateTime; public double TimeOut; public int Retries; - private UInt64? steamId; - public UInt64? SteamID - { - get { return steamId; } - set - { - steamId = value; - Connection.SetSteamIDIfUnknown(value ?? 0); - } - } - private UInt64? ownerSteamId; - public UInt64? OwnerSteamID - { - get { return ownerSteamId; } - set - { - ownerSteamId = value; - Connection.SetOwnerSteamIDIfUnknown(value ?? 0); - } - } public Int32? PasswordSalt; public bool AuthSessionStarted; + + public AccountInfo AccountInfo => Connection.AccountInfo; public PendingClient(NetworkConnection conn) { - OwnerKey = 0; + OwnerKey = Option.None(); Connection = conn; InitializationStep = ConnectionInitialization.SteamTicketAndVersion; Retries = 0; - SteamID = null; - OwnerSteamID = null; PasswordSalt = null; UpdateTime = Timing.TotalTime + Timing.Step * 3.0; TimeOut = NetworkConnection.TimeoutThreshold; @@ -101,7 +80,10 @@ namespace Barotrauma.Networking case ConnectionInitialization.SteamTicketAndVersion: string name = Client.SanitizeName(inc.ReadString()); int ownerKey = inc.ReadInt32(); - UInt64 steamId = inc.ReadUInt64(); + UInt64 steamIdVal = inc.ReadUInt64(); + Option steamId = steamIdVal != 0 + ? Option.Some(new SteamId(steamIdVal)) + : Option.None(); UInt16 ticketLength = inc.ReadUInt16(); byte[] ticketBytes = inc.ReadBytes(ticketLength); @@ -136,7 +118,7 @@ namespace Barotrauma.Networking if (!pendingClient.AuthSessionStarted) { - ProcessAuthTicket(name, ownerKey, steamId, pendingClient, ticketBytes); + ProcessAuthTicket(name, ownerKey != 0 ? Option.Some(ownerKey) : Option.None(), steamId, pendingClient, ticketBytes); } break; case ConnectionInitialization.Password: @@ -172,34 +154,37 @@ namespace Barotrauma.Networking } } - protected abstract void ProcessAuthTicket(string name, int ownKey, ulong steamId, PendingClient pendingClient, byte[] ticket); + protected abstract void ProcessAuthTicket(string name, Option ownKey, Option steamId, PendingClient pendingClient, byte[] ticket); protected void BanPendingClient(PendingClient pendingClient, string banReason, TimeSpan? duration) { - if (pendingClient.Connection is LidgrenConnection l) + void banAccountId(AccountId accountId) { - serverSettings.BanList.BanPlayer(pendingClient.Name, l.NetConnection.RemoteEndPoint.Address, banReason, duration); - } - else if (pendingClient.Connection is SteamP2PConnection s) - { - serverSettings.BanList.BanPlayer(pendingClient.Name, s.SteamID, banReason, duration); - serverSettings.BanList.BanPlayer(pendingClient.Name, s.OwnerSteamID, banReason, duration); + serverSettings.BanList.BanPlayer(pendingClient.Name, accountId, banReason, duration); } + + if (pendingClient.AccountInfo.AccountId.TryUnwrap(out var id)) { banAccountId(id); } + pendingClient.AccountInfo.OtherMatchingIds.ForEach(banAccountId); + serverSettings.BanList.BanPlayer(pendingClient.Name, pendingClient.Connection.Endpoint, banReason, duration); } - + protected bool IsPendingClientBanned(PendingClient pendingClient, out string banReason) { - if (pendingClient.Connection is LidgrenConnection l) + bool isAccountIdBanned(AccountId accountId, out string banReason) { - return serverSettings.BanList.IsBanned(l.NetConnection.RemoteEndPoint.Address, out banReason); + banReason = default; + return serverSettings.BanList.IsBanned(accountId, out banReason); } - else if (pendingClient.Connection is SteamP2PConnection s) + + banReason = default; + bool isBanned = pendingClient.AccountInfo.AccountId.TryUnwrap(out var id) + && isAccountIdBanned(id, out banReason); + foreach (var otherId in pendingClient.AccountInfo.OtherMatchingIds) { - return serverSettings.BanList.IsBanned(s.SteamID, out banReason) || - serverSettings.BanList.IsBanned(s.OwnerSteamID, out banReason); + if (isBanned) { break; } + isBanned |= isAccountIdBanned(otherId, out banReason); } - banReason = null; - return false; + return isBanned; } protected abstract void SendMsgInternal(NetworkConnection conn, DeliveryMethod deliveryMethod, IWriteMessage msg); @@ -225,7 +210,7 @@ namespace Barotrauma.Networking CheckOwnership(pendingClient); - OnInitializationComplete?.Invoke(newConnection); + OnInitializationComplete?.Invoke(newConnection, pendingClient.Name); } pendingClient.TimeOut -= Timing.Step; @@ -244,8 +229,6 @@ namespace Barotrauma.Networking switch (pendingClient.InitializationStep) { case ConnectionInitialization.ContentPackageOrder: - outMsg.Write(GameMain.Server.ServerName); - var mpContentPackages = ContentPackageManager.EnabledPackages.All.Where(cp => cp.HasMultiplayerSyncedContent).ToList(); outMsg.WriteVariableUInt32((UInt32)mpContentPackages.Count); for (int i = 0; i < mpContentPackages.Count; i++) @@ -286,11 +269,10 @@ namespace Barotrauma.Networking pendingClients.Remove(pendingClient); - if (pendingClient.AuthSessionStarted) + if (pendingClient.AuthSessionStarted && pendingClient.AccountInfo.AccountId is Some { Value: SteamId steamId }) { - Steam.SteamManager.StopAuthSession(pendingClient.SteamID.Value); - pendingClient.SteamID = null; - pendingClient.OwnerSteamID = null; + Steam.SteamManager.StopAuthSession(steamId); + pendingClient.Connection.SetAccountInfo(AccountInfo.None); pendingClient.AuthSessionStarted = false; } } diff --git a/Barotrauma/BarotraumaServer/ServerSource/Networking/Primitives/Peers/Server/SteamP2PServerPeer.cs b/Barotrauma/BarotraumaServer/ServerSource/Networking/Primitives/Peers/Server/SteamP2PServerPeer.cs index 8718bc4d5..e33afdbb9 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Networking/Primitives/Peers/Server/SteamP2PServerPeer.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Networking/Primitives/Peers/Server/SteamP2PServerPeer.cs @@ -1,8 +1,6 @@ using System; using System.Collections.Generic; -using System.Net; using System.Linq; -using System.Threading; namespace Barotrauma.Networking { @@ -10,29 +8,25 @@ namespace Barotrauma.Networking { private bool started; - public UInt64 OwnerSteamID - { - get; - private set; - } + private readonly SteamId ownerSteamId; - private UInt64 ownerKey64 => unchecked((UInt64)ownerKey.Value); + private UInt64 ownerKey64 => unchecked((UInt64)ownerKey.Fallback(0)); - private UInt64 ReadSteamId(IReadMessage inc) - => inc.ReadUInt64() ^ ownerKey64; - private void WriteSteamId(IWriteMessage msg, UInt64 val) - => msg.Write(val ^ ownerKey64); + private SteamId ReadSteamId(IReadMessage inc) + => new SteamId(inc.ReadUInt64() ^ ownerKey64); + private void WriteSteamId(IWriteMessage msg, SteamId val) + => msg.Write(val.Value ^ ownerKey64); - public SteamP2PServerPeer(UInt64 steamId, int ownerKey, ServerSettings settings) + public SteamP2PServerPeer(SteamId steamId, int ownerKey, ServerSettings settings) { serverSettings = settings; connectedClients = new List(); pendingClients = new List(); - this.ownerKey = ownerKey; + this.ownerKey = Option.Some(ownerKey); - OwnerSteamID = steamId; + ownerSteamId = steamId; started = false; } @@ -40,7 +34,7 @@ namespace Barotrauma.Networking public override void Start() { IWriteMessage outMsg = new WriteOnlyMessage(); - WriteSteamId(outMsg, OwnerSteamID); + WriteSteamId(outMsg, ownerSteamId); outMsg.Write((byte)DeliveryMethod.Reliable); outMsg.Write((byte)(PacketHeader.IsConnectionInitializationStep | PacketHeader.IsServerMessage)); @@ -129,9 +123,9 @@ namespace Barotrauma.Networking { if (!started) { return; } - UInt64 senderSteamId = ReadSteamId(inc); - UInt64 ownerSteamId = ReadSteamId(inc); - + SteamId senderSteamId = ReadSteamId(inc); + SteamId ownerSteamId = ReadSteamId(inc); + PacketHeader packetHeader = (PacketHeader)inc.ReadByte(); if (packetHeader.IsServerMessage()) @@ -140,11 +134,14 @@ namespace Barotrauma.Networking return; } - if (senderSteamId != OwnerSteamID) //sender is remote, handle disconnects and heartbeats + if (senderSteamId != this.ownerSteamId) //sender is remote, handle disconnects and heartbeats { - PendingClient pendingClient = pendingClients.Find(c => c.SteamID == senderSteamId); - SteamP2PConnection connectedClient = connectedClients.Find(c => c.SteamID == senderSteamId) as SteamP2PConnection; - + bool connectionMatches(NetworkConnection conn) + => conn is SteamP2PConnection { Endpoint: SteamP2PEndpoint { SteamId: var steamId } } + && steamId == senderSteamId; + PendingClient pendingClient = pendingClients.Find(c => connectionMatches(c.Connection)); + SteamP2PConnection connectedClient = connectedClients.Find(connectionMatches) as SteamP2PConnection; + pendingClient?.Heartbeat(); connectedClient?.Heartbeat(); @@ -171,7 +168,7 @@ namespace Barotrauma.Networking } else if (connectedClient != null) { - string disconnectMsg = $"ServerMessage.HasDisconnected~[client]={connectedClient.Name}"; + string disconnectMsg = $"ServerMessage.HasDisconnected~[client]={GameMain.Server.ConnectedClients.First(c => c.Connection == connectedClient).Name}"; Disconnect(connectedClient, disconnectMsg, false); } return; @@ -183,13 +180,9 @@ namespace Barotrauma.Networking } else if (packetHeader.IsConnectionInitializationStep()) { - if (pendingClient != null) { - if (ownerSteamId != 0) - { - pendingClient.Connection.SetOwnerSteamIDIfUnknown(ownerSteamId); - } + pendingClient.Connection.SetAccountInfo(new AccountInfo(senderSteamId, ownerSteamId)); ReadConnectionInitializationStep(pendingClient, new ReadOnlyMessage(inc.Buffer, false, inc.BytePosition, inc.LengthBytes - inc.BytePosition, null)); } else @@ -197,7 +190,7 @@ namespace Barotrauma.Networking ConnectionInitialization initializationStep = (ConnectionInitialization)inc.ReadByte(); if (initializationStep == ConnectionInitialization.ConnectionStarted) { - pendingClients.Add(new PendingClient(new SteamP2PConnection("PENDING", senderSteamId)) { SteamID = senderSteamId }); + pendingClients.Add(new PendingClient(new SteamP2PConnection(senderSteamId))); } } } @@ -228,13 +221,13 @@ namespace Barotrauma.Networking if (OwnerConnection == null) { string ownerName = inc.ReadString(); - OwnerConnection = new SteamP2PConnection(ownerName, OwnerSteamID) + OwnerConnection = new SteamP2PConnection(this.ownerSteamId) { Language = GameSettings.CurrentConfig.Language }; - OwnerConnection.SetOwnerSteamIDIfUnknown(OwnerSteamID); + OwnerConnection.SetAccountInfo(new AccountInfo(this.ownerSteamId, this.ownerSteamId)); - OnInitializationComplete?.Invoke(OwnerConnection); + OnInitializationComplete?.Invoke(OwnerConnection, ownerName); } return; } @@ -261,17 +254,19 @@ namespace Barotrauma.Networking { if (!started) { return; } - if (!(conn is SteamP2PConnection steamp2pConn)) return; + if (!(conn is SteamP2PConnection steamp2pConn)) { return; } if (!connectedClients.Contains(steamp2pConn) && conn != OwnerConnection) { - DebugConsole.ThrowError("Tried to send message to unauthenticated connection: " + steamp2pConn.SteamID.ToString()); + DebugConsole.ThrowError("Tried to send message to unauthenticated connection: " + steamp2pConn.AccountInfo.AccountId.ToString()); return; } + if (!conn.AccountInfo.AccountId.TryUnwrap(out var connAccountId) || !(connAccountId is SteamId connSteamId)) { return; } + IWriteMessage msgToSend = new WriteOnlyMessage(); byte[] msgData = new byte[16]; msg.PrepareForSending(ref msgData, compressPastThreshold, out bool isCompressed, out int length); - WriteSteamId(msgToSend, conn.SteamID); + WriteSteamId(msgToSend, connSteamId); msgToSend.Write((byte)deliveryMethod); msgToSend.Write((byte)((isCompressed ? PacketHeader.IsCompressed : PacketHeader.None) | PacketHeader.IsServerMessage)); msgToSend.Write((UInt16)length); @@ -282,7 +277,7 @@ namespace Barotrauma.Networking ChildServerRelay.Write(bufToSend); } - private void SendDisconnectMessage(UInt64 steamId, string msg) + private void SendDisconnectMessage(SteamId steamId, string msg) { if (!started) { return; } if (string.IsNullOrWhiteSpace(msg)) { return; } @@ -303,13 +298,16 @@ namespace Barotrauma.Networking if (!started) { return; } if (!(conn is SteamP2PConnection steamp2pConn)) { return; } - if (sendDisconnectMessage) { SendDisconnectMessage(steamp2pConn.SteamID, msg); } + + if (!conn.AccountInfo.AccountId.TryUnwrap(out var connAccountId) || !(connAccountId is SteamId connSteamId)) { return; } + + if (sendDisconnectMessage) { SendDisconnectMessage(connSteamId, msg); } if (connectedClients.Contains(steamp2pConn)) { steamp2pConn.Status = NetworkConnectionStatus.Disconnected; connectedClients.Remove(steamp2pConn); OnDisconnect?.Invoke(conn, msg); - Steam.SteamManager.StopAuthSession(conn.SteamID); + Steam.SteamManager.StopAuthSession(connSteamId); } else if (steamp2pConn == OwnerConnection) { @@ -324,8 +322,12 @@ namespace Barotrauma.Networking protected override void SendMsgInternal(NetworkConnection conn, DeliveryMethod deliveryMethod, IWriteMessage msg) { + var connSteamId = conn is SteamP2PConnection { Endpoint: SteamP2PEndpoint { SteamId: var id } } + ? id : null; + if (connSteamId is null) { return; } + IWriteMessage msgToSend = new WriteOnlyMessage(); - WriteSteamId(msgToSend, conn.SteamID); + WriteSteamId(msgToSend, connSteamId); msgToSend.Write((byte)deliveryMethod); msgToSend.Write(msg.Buffer, 0, msg.LengthBytes); byte[] bufToSend = (byte[])msgToSend.Buffer.Clone(); @@ -333,11 +335,10 @@ namespace Barotrauma.Networking ChildServerRelay.Write(bufToSend); } - protected override void ProcessAuthTicket(string name, int ownKey, ulong steamId, PendingClient pendingClient, byte[] ticket) + protected override void ProcessAuthTicket(string name, Option ownKey, Option steamId, PendingClient pendingClient, byte[] ticket) { pendingClient.InitializationStep = serverSettings.HasPassword ? ConnectionInitialization.Password : ConnectionInitialization.ContentPackageOrder; - pendingClient.Connection.Name = name; pendingClient.Name = name; pendingClient.AuthSessionStarted = true; } diff --git a/Barotrauma/BarotraumaServer/ServerSource/Networking/RespawnManager.cs b/Barotrauma/BarotraumaServer/ServerSource/Networking/RespawnManager.cs index c65ba58d2..cfa43ea1d 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Networking/RespawnManager.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Networking/RespawnManager.cs @@ -444,26 +444,28 @@ namespace Barotrauma.Networking } clients[i].Character = character; - character.OwnerClientEndPoint = clients[i].Connection.EndPointString; + character.OwnerClientEndpoint = clients[i].Connection.Endpoint; character.OwnerClientName = clients[i].Name; - GameServer.Log(string.Format("Respawning {0} ({1}) as {2}", GameServer.ClientLogName(clients[i]), clients[i].Connection?.EndPointString, characterInfos[i].Job.Name), ServerLog.MessageType.Spawning); + GameServer.Log( + $"Respawning {GameServer.ClientLogName(clients[i])} ({clients[i].Connection.Endpoint}) as {characterInfos[i].Job.Name}", ServerLog.MessageType.Spawning); } if (RespawnShuttle != null) { - Vector2 pos = cargoSp == null ? character.Position : cargoSp.Position; + List newRespawnItems = new List(); + Vector2 pos = cargoSp?.Position ?? character.Position; if (divingSuitPrefab != null) { var divingSuit = new Item(divingSuitPrefab, pos, respawnSub); Spawner.CreateNetworkEvent(new EntitySpawner.SpawnEntity(divingSuit)); - respawnItems.Add(divingSuit); + newRespawnItems.Add(divingSuit); if (oxyPrefab != null && divingSuit.GetComponent() != null) { var oxyTank = new Item(oxyPrefab, pos, respawnSub); Spawner.CreateNetworkEvent(new EntitySpawner.SpawnEntity(oxyTank)); divingSuit.Combine(oxyTank, user: null); - respawnItems.Add(oxyTank); + newRespawnItems.Add(oxyTank); } } @@ -473,13 +475,13 @@ namespace Barotrauma.Networking { var scooter = new Item(scooterPrefab, pos, respawnSub); Spawner.CreateNetworkEvent(new EntitySpawner.SpawnEntity(scooter)); - respawnItems.Add(scooter); + newRespawnItems.Add(scooter); if (batteryPrefab != null) { var battery = new Item(batteryPrefab, pos, respawnSub); Spawner.CreateNetworkEvent(new EntitySpawner.SpawnEntity(battery)); scooter.Combine(battery, user: null); - respawnItems.Add(battery); + newRespawnItems.Add(battery); } } } @@ -489,8 +491,9 @@ namespace Barotrauma.Networking } //try to put the items in containers in the shuttle - foreach (var respawnItem in respawnItems) + foreach (var respawnItem in newRespawnItems) { + System.Diagnostics.Debug.Assert(!respawnItem.Removed); foreach (Item shuttleItem in RespawnShuttle.GetItems(alsoFromConnectedSubs: false)) { if (shuttleItem.NonInteractable || shuttleItem.NonPlayerTeamInteractable) { continue; } @@ -500,6 +503,7 @@ namespace Barotrauma.Networking break; } } + respawnItems.Add(respawnItem); } } diff --git a/Barotrauma/BarotraumaServer/ServerSource/Networking/ServerSettings.cs b/Barotrauma/BarotraumaServer/ServerSource/Networking/ServerSettings.cs index 39f7833c9..d39451492 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Networking/ServerSettings.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Networking/ServerSettings.cs @@ -69,7 +69,6 @@ namespace Barotrauma.Networking WriteNetProperties(outMsg, c); WriteMonsterEnabled(outMsg); BanList.ServerAdminWrite(outMsg, c); - Whitelist.ServerAdminWrite(outMsg, c); } public void ServerWrite(IWriteMessage outMsg, Client c) @@ -171,7 +170,6 @@ namespace Barotrauma.Networking propertiesChanged |= changedMonsterSettings; if (changedMonsterSettings) { ReadMonsterEnabled(incMsg); } propertiesChanged |= BanList.ServerAdminRead(incMsg, c); - propertiesChanged |= Whitelist.ServerAdminRead(incMsg, c); if (propertiesChanged) { @@ -444,31 +442,27 @@ namespace Barotrauma.Networking { ClientPermissions.Clear(); - if (!File.Exists(ClientPermissionsFile)) - { - if (File.Exists("Data/clientpermissions.txt")) - { - LoadClientPermissionsOld("Data/clientpermissions.txt"); - } - return; - } + if (!File.Exists(ClientPermissionsFile)) { return; } XDocument doc = XMLExtensions.TryLoadXml(ClientPermissionsFile); if (doc == null) { return; } foreach (XElement clientElement in doc.Root.Elements()) { string clientName = clientElement.GetAttributeString("name", ""); - string clientEndPoint = clientElement.GetAttributeString("endpoint", null) ?? clientElement.GetAttributeString("ip", ""); - string steamIdStr = clientElement.GetAttributeString("steamid", ""); + string addressStr = clientElement.GetAttributeString("address", null) + ?? clientElement.GetAttributeString("endpoint", null) + ?? clientElement.GetAttributeString("ip", ""); + string accountIdStr = clientElement.GetAttributeString("accountid", null) + ?? clientElement.GetAttributeString("steamid", ""); if (string.IsNullOrWhiteSpace(clientName)) { - DebugConsole.ThrowError("Error in " + ClientPermissionsFile + " - all clients must have a name and an IP address."); + DebugConsole.ThrowError("Error in " + ClientPermissionsFile + " - all clients must have a name."); continue; } - if (string.IsNullOrWhiteSpace(clientEndPoint) && string.IsNullOrWhiteSpace(steamIdStr)) + if (string.IsNullOrWhiteSpace(addressStr) && string.IsNullOrWhiteSpace(accountIdStr)) { - DebugConsole.ThrowError("Error in " + ClientPermissionsFile + " - all clients must have an IP address or a Steam ID."); + DebugConsole.ThrowError("Error in " + ClientPermissionsFile + " - all clients must have an endpoint or a Steam ID."); continue; } @@ -525,69 +519,33 @@ namespace Barotrauma.Networking } } - if (!string.IsNullOrEmpty(steamIdStr)) + if (!string.IsNullOrEmpty(accountIdStr)) { - if (ulong.TryParse(steamIdStr, out ulong steamID)) + if (AccountId.Parse(accountIdStr).TryUnwrap(out var accountId)) { - ClientPermissions.Add(new SavedClientPermission(clientName, steamID, permissions, permittedCommands)); + ClientPermissions.Add(new SavedClientPermission(clientName, accountId, permissions, permittedCommands)); } else { - DebugConsole.ThrowError("Error in " + ClientPermissionsFile + " - \"" + steamIdStr + "\" is not a valid Steam ID."); - continue; + DebugConsole.ThrowError("Error in " + ClientPermissionsFile + " - \"" + accountIdStr + "\" is not a valid account ID."); } } else { - ClientPermissions.Add(new SavedClientPermission(clientName, clientEndPoint, permissions, permittedCommands)); - } - } - } - - /// - /// Method for loading old .txt client permission files to provide backwards compatibility - /// - private void LoadClientPermissionsOld(string file) - { - if (!File.Exists(file)) return; - - string[] lines; - try - { - lines = File.ReadAllLines(file); - } - catch (Exception e) - { - DebugConsole.ThrowError("Failed to open client permission file " + ClientPermissionsFile, e); - return; - } - - ClientPermissions.Clear(); - - foreach (string line in lines) - { - string[] separatedLine = line.Split('|'); - if (separatedLine.Length < 3) { continue; } - - string name = string.Join("|", separatedLine.Take(separatedLine.Length - 2)); - string ip = separatedLine[separatedLine.Length - 2]; - - ClientPermissions permissions; - if (Enum.TryParse(separatedLine.Last(), out permissions)) - { - ClientPermissions.Add(new SavedClientPermission(name, ip, permissions, new HashSet())); + if (Address.Parse(addressStr).TryUnwrap(out var address)) + { + ClientPermissions.Add(new SavedClientPermission(clientName, address, permissions, permittedCommands)); + } + else + { + DebugConsole.ThrowError("Error in " + ClientPermissionsFile + " - \"" + addressStr + "\" is not a valid endpoint."); + } } } } public void SaveClientPermissions() { - //delete old client permission file - if (File.Exists("Data/clientpermissions.txt")) - { - File.Delete("Data/clientpermissions.txt"); - } - GameServer.Log("Saving client permissions", ServerLog.MessageType.ServerMessage); XDocument doc = new XDocument(new XElement("ClientPermissions")); @@ -595,6 +553,7 @@ namespace Barotrauma.Networking foreach (SavedClientPermission clientPermission in ClientPermissions) { var matchingPreset = PermissionPreset.List.Find(p => p.MatchesPermissions(clientPermission.Permissions, clientPermission.PermittedCommands)); + #warning TODO: this is broken because of localization if (matchingPreset != null && matchingPreset.Name == "None") { continue; @@ -603,23 +562,14 @@ namespace Barotrauma.Networking XElement clientElement = new XElement("Client", new XAttribute("name", clientPermission.Name)); - if (clientPermission.SteamID > 0) - { - clientElement.Add(new XAttribute("steamid", clientPermission.SteamID)); - } - else - { - clientElement.Add(new XAttribute("endpoint", clientPermission.EndPoint)); - } + clientElement.Add(clientPermission.AddressOrAccountId.TryGet(out AccountId accountId) + ? new XAttribute("accountid", accountId.StringRepresentation) + : new XAttribute("address", ((Address)clientPermission.AddressOrAccountId).StringRepresentation)); - if (matchingPreset == null) - { - clientElement.Add(new XAttribute("permissions", clientPermission.Permissions.ToString())); - } - else - { - clientElement.Add(new XAttribute("preset", matchingPreset.Name)); - } + clientElement.Add(matchingPreset == null + ? new XAttribute("permissions", clientPermission.Permissions.ToString()) + : new XAttribute("preset", matchingPreset.Name)); + if (clientPermission.Permissions.HasFlag(Networking.ClientPermissions.ConsoleCommands)) { foreach (DebugConsole.Command command in clientPermission.PermittedCommands) diff --git a/Barotrauma/BarotraumaServer/ServerSource/Networking/Voting.cs b/Barotrauma/BarotraumaServer/ServerSource/Networking/Voting.cs index 0ee0a0d73..c21a8f293 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Networking/Voting.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Networking/Voting.cs @@ -257,11 +257,10 @@ namespace Barotrauma if ((DateTime.Now - sender.JoinTime).TotalSeconds > GameMain.Server.ServerSettings.DisallowKickVoteTime) { GameMain.Server.SendDirectChatMessage($"ServerMessage.kickvotedisallowed", sender); - } else { - Client kicked = GameMain.Server.ConnectedClients.Find(c => c.ID == kickedClientID); + Client kicked = GameMain.Server.ConnectedClients.Find(c => c.SessionId == kickedClientID); if (kicked != null && kicked.Connection != GameMain.Server.OwnerConnection && !kicked.HasKickVoteFrom(sender)) { kicked.AddKickVote(sender); @@ -293,9 +292,9 @@ namespace Barotrauma if (!ShouldRejectVote(sender, voteType)) { pendingVotes.Enqueue(new TransferVote(sender, - GameMain.Server.ConnectedClients.Find(c => c.ID == fromClientId), + GameMain.Server.ConnectedClients.Find(c => c.SessionId == fromClientId), amount, - GameMain.Server.ConnectedClients.Find(c => c.ID == toClientId))); + GameMain.Server.ConnectedClients.Find(c => c.SessionId == toClientId))); } } else @@ -372,14 +371,14 @@ namespace Barotrauma msg.Write((byte)yesClients.Count()); foreach (Client c in yesClients) { - msg.Write(c.ID); + msg.Write(c.SessionId); } var noClients = eligibleClients.Where(c => c.GetVote(ActiveVote.VoteType) == 1); msg.Write((byte)noClients.Count()); foreach (Client c in noClients) { - msg.Write(c.ID); + msg.Write(c.SessionId); } msg.Write((byte)eligibleClients.Count()); @@ -387,7 +386,7 @@ namespace Barotrauma switch (ActiveVote.State) { case VoteState.Started: - msg.Write(ActiveVote.VoteStarter.ID); + msg.Write(ActiveVote.VoteStarter.SessionId); msg.Write((byte)GameMain.Server.ServerSettings.VoteTimeout); switch (ActiveVote.VoteType) @@ -401,8 +400,8 @@ namespace Barotrauma break; case VoteType.TransferMoney: var transferVote = (ActiveVote as TransferVote); - msg.Write(transferVote.From?.ID ?? 0); - msg.Write(transferVote.To?.ID ?? 0); + msg.Write(transferVote.From?.SessionId ?? 0); + msg.Write(transferVote.To?.SessionId ?? 0); msg.Write(transferVote.TransferAmount); break; } @@ -430,11 +429,11 @@ namespace Barotrauma } } - var readyClients = GameMain.Server.ConnectedClients.FindAll(c => c.GetVote(VoteType.StartRound)); - msg.Write((byte)readyClients.Count); + var readyClients = GameMain.Server.ConnectedClients.Where(c => c.GetVote(VoteType.StartRound)); + msg.Write((byte)readyClients.Count()); foreach (Client c in readyClients) { - msg.Write(c.ID); + msg.Write(c.SessionId); } msg.WritePadBits(); diff --git a/Barotrauma/BarotraumaServer/ServerSource/Steam/SteamManager.cs b/Barotrauma/BarotraumaServer/ServerSource/Steam/SteamManager.cs index 25d6cc5e7..f4a37340a 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Steam/SteamManager.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Steam/SteamManager.cs @@ -1,4 +1,5 @@ using System.Linq; +using Barotrauma.Networking; namespace Barotrauma.Steam { @@ -58,7 +59,6 @@ namespace Barotrauma.Steam Steamworks.SteamServer.SetKey("contentpackage", string.Join(",", contentPackages.Select(cp => cp.Name))); Steamworks.SteamServer.SetKey("contentpackagehash", string.Join(",", contentPackages.Select(cp => cp.Hash.StringRepresentation))); Steamworks.SteamServer.SetKey("contentpackageid", string.Join(",", contentPackages.Select(cp => cp.SteamWorkshopId))); - Steamworks.SteamServer.SetKey("usingwhitelist", (server.ServerSettings.Whitelist != null && server.ServerSettings.Whitelist.Enabled).ToString()); Steamworks.SteamServer.SetKey("modeselectionmode", server.ServerSettings.ModeSelectionMode.ToString()); Steamworks.SteamServer.SetKey("subselectionmode", server.ServerSettings.SubSelectionMode.ToString()); Steamworks.SteamServer.SetKey("voicechatenabled", server.ServerSettings.VoiceChatEnabled.ToString()); @@ -76,12 +76,12 @@ namespace Barotrauma.Steam return true; } - public static Steamworks.BeginAuthResult StartAuthSession(byte[] authTicketData, ulong clientSteamID) + public static Steamworks.BeginAuthResult StartAuthSession(byte[] authTicketData, SteamId clientSteamID) { if (!IsInitialized || !Steamworks.SteamServer.IsValid) return Steamworks.BeginAuthResult.ServerNotConnectedToSteam; DebugConsole.Log("SteamManager authenticating Steam client " + clientSteamID); - Steamworks.BeginAuthResult startResult = Steamworks.SteamServer.BeginAuthSession(authTicketData, clientSteamID); + Steamworks.BeginAuthResult startResult = Steamworks.SteamServer.BeginAuthSession(authTicketData, clientSteamID.Value); if (startResult != Steamworks.BeginAuthResult.OK) { DebugConsole.Log("Authentication failed: failed to start auth session (" + startResult.ToString() + ")"); @@ -90,12 +90,12 @@ namespace Barotrauma.Steam return startResult; } - public static void StopAuthSession(ulong clientSteamID) + public static void StopAuthSession(SteamId clientSteamId) { if (!IsInitialized || !Steamworks.SteamServer.IsValid) return; - DebugConsole.Log("SteamManager ending auth session with Steam client " + clientSteamID); - Steamworks.SteamServer.EndSession(clientSteamID); + DebugConsole.Log("SteamManager ending auth session with Steam client " + clientSteamId); + Steamworks.SteamServer.EndSession(clientSteamId.Value); } public static bool CloseServer() diff --git a/Barotrauma/BarotraumaServer/WindowsServer.csproj b/Barotrauma/BarotraumaServer/WindowsServer.csproj index 0b500d712..07f7633bd 100644 --- a/Barotrauma/BarotraumaServer/WindowsServer.csproj +++ b/Barotrauma/BarotraumaServer/WindowsServer.csproj @@ -6,7 +6,7 @@ Barotrauma FakeFish, Undertow Games Barotrauma Dedicated Server - 0.19.0.0 + 0.19.1.0 Copyright © FakeFish 2018-2022 AnyCPU;x64 DedicatedServer diff --git a/Barotrauma/BarotraumaShared/Data/permissionpresets.xml b/Barotrauma/BarotraumaShared/Data/permissionpresets.xml index efff061b6..f8e9bd8f5 100644 --- a/Barotrauma/BarotraumaShared/Data/permissionpresets.xml +++ b/Barotrauma/BarotraumaShared/Data/permissionpresets.xml @@ -64,7 +64,7 @@ - + diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/EnemyAIController.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/EnemyAIController.cs index 8897ebecb..7ecbbdaa3 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/EnemyAIController.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/EnemyAIController.cs @@ -87,11 +87,11 @@ namespace Barotrauma if (_attackLimb != value) { _previousAttackLimb = _attackLimb; - _previousAttackLimb?.AttachedRope?.Snap(); + if (_previousAttackLimb != null && _previousAttackLimb.attack.SnapRopeOnNewAttack) { _previousAttackLimb.AttachedRope?.Snap(); } } else if (_attackLimb != null && _attackLimb.attack.CoolDownTimer <= 0) { - _attackLimb.AttachedRope?.Snap(); + if (_attackLimb != null && _attackLimb.attack.SnapRopeOnNewAttack) { _attackLimb.AttachedRope?.Snap(); } } _attackLimb = value; attackVector = null; @@ -3660,7 +3660,7 @@ namespace Barotrauma targetDir = Vector2.UnitY; } } - float margin = 30000; + float margin = Level.OutsideBoundsCurrentMargin; if (pos.X < -margin) { // Too far left diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveGoTo.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveGoTo.cs index 640973cda..ff815f159 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveGoTo.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveGoTo.cs @@ -197,6 +197,10 @@ namespace Barotrauma return; } character.SelectedItem = null; + if (character.SelectedSecondaryItem != null && !character.SelectedSecondaryItem.IsLadder) + { + character.SelectedSecondaryItem = null; + } if (Target is Entity e) { if (e.Removed) diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/Animation/Ragdoll.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/Animation/Ragdoll.cs index a0149777f..8c90345cf 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/Animation/Ragdoll.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/Animation/Ragdoll.cs @@ -1234,7 +1234,7 @@ namespace Barotrauma { //find the room which the limb is in //the room where the ragdoll is in is used as the "guess", meaning that it's checked first - Hull limbHull = currentHull == null ? null : Hull.FindHull(limb.WorldPosition, currentHull); + Hull newHull = currentHull == null ? null : Hull.FindHull(limb.WorldPosition, currentHull); bool prevInWater = limb.InWater; limb.InWater = false; @@ -1243,38 +1243,37 @@ namespace Barotrauma { limb.InWater = false; } - else if (limbHull == null) + else if (newHull == null) { //limb isn't in any room -> it's in the water limb.InWater = true; - if (limb.type == LimbType.Head) headInWater = true; + if (limb.type == LimbType.Head) { headInWater = true; } } - else if (limbHull.WaterVolume > 0.0f && Submarine.RectContains(limbHull.Rect, limb.Position)) + else if (newHull.WaterVolume > 0.0f && Submarine.RectContains(newHull.Rect, limb.Position)) { - if (limb.Position.Y < limbHull.Surface) + if (limb.Position.Y < newHull.Surface) { limb.InWater = true; - surfaceY = limbHull.Surface; + surfaceY = newHull.Surface; if (limb.type == LimbType.Head) { headInWater = true; } } //the limb has gone through the surface of the water - if (Math.Abs(limb.LinearVelocity.Y) > 5.0f && limb.InWater != prevInWater) + if (Math.Abs(limb.LinearVelocity.Y) > 5.0f && limb.InWater != prevInWater && newHull == limb.Hull) { - Splash(limb, limbHull); - + Splash(limb, newHull); //if the Character dropped into water, create a wave if (limb.LinearVelocity.Y < 0.0f) { Vector2 impulse = limb.LinearVelocity * limb.Mass; - int n = (int)((limb.Position.X - limbHull.Rect.X) / Hull.WaveWidth); - limbHull.WaveVel[n] += MathHelper.Clamp(impulse.Y, -5.0f, 5.0f); + int n = (int)((limb.Position.X - newHull.Rect.X) / Hull.WaveWidth); + newHull.WaveVel[n] += MathHelper.Clamp(impulse.Y, -5.0f, 5.0f); } } } - + limb.Hull = newHull; limb.Update(deltaTime); } @@ -1492,12 +1491,12 @@ namespace Barotrauma } if (flowForce.LengthSquared() > 0.001f) - { - Collider.ApplyForce(flowForce); + { + Collider.ApplyForce(flowForce * (Collider.Mass / Mass)); foreach (Limb limb in limbs) { if (!limb.InWater) { continue; } - limb.body.ApplyForce(flowForce); + limb.body.ApplyForce(flowForce * (limb.Mass / Mass * limbs.Length)); } } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/Attack.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/Attack.cs index d47bbf405..ee7cdc224 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/Attack.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/Attack.cs @@ -100,6 +100,9 @@ namespace Barotrauma [Serialize(false, IsPropertySaveable.Yes, description: "Should the AI try to turn around when aiming with this attack?"), Editable] public bool Reverse { get; private set; } + [Serialize(true, IsPropertySaveable.Yes, description: "Should the rope attached to this limb snap upon choosing a new attack?"), Editable] + public bool SnapRopeOnNewAttack { get; private set; } + [Serialize(false, IsPropertySaveable.Yes, description: "Should the AI try to steer away from the target when aiming with this attack? Best combined with PassiveAggressive behavior."), Editable] public bool Retreat { get; private set; } @@ -309,7 +312,7 @@ namespace Barotrauma List multipliedAfflictions = new List(); foreach (Affliction affliction in Afflictions.Keys) { - multipliedAfflictions.Add(affliction.CreateMultiplied(multiplier)); + multipliedAfflictions.Add(affliction.CreateMultiplied(multiplier, affliction.Probability)); } return multipliedAfflictions; } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/Character.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/Character.cs index d6b95ac15..cdc68d100 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/Character.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/Character.cs @@ -40,7 +40,7 @@ namespace Barotrauma } set { - if (value == enabled) return; + if (value == enabled) { return; } if (Removed) { @@ -63,6 +63,32 @@ namespace Barotrauma } } + + private bool disabledByEvent; + /// + /// MonsterEvents disable monsters (which includes removing them from the character list, so they essentially "don't exist") until they're ready to spawn + /// + public bool DisabledByEvent + { + get { return disabledByEvent; } + set + { + if (value == disabledByEvent) { return; } + disabledByEvent = value; + if (disabledByEvent) + { + Enabled = false; + CharacterList.Remove(this); + if (AiTarget != null) { AITarget.List.Remove(AiTarget); } + } + else + { + if (!CharacterList.Contains(this)) { CharacterList.Add(this); } + if (AiTarget != null && !AITarget.List.Contains(AiTarget)) { AITarget.List.Add(AiTarget); } + } + } + } + public Hull PreviousHull = null; public Hull CurrentHull = null; @@ -1247,23 +1273,30 @@ namespace Barotrauma if (Params.Husk && speciesName != "husk" && Prefab.VariantOf != "husk") { - // Get the non husked name and find the ragdoll with it - var matchingAffliction = AfflictionPrefab.List - .Where(p => p is AfflictionPrefabHusk) - .Select(p => p as AfflictionPrefabHusk) - .FirstOrDefault(p => p.TargetSpecies.Any(t => t == AfflictionHusk.GetNonHuskedSpeciesName(speciesName, p))); Identifier nonHuskedSpeciesName = Identifier.Empty; - if (matchingAffliction == null) + AfflictionPrefabHusk matchingAffliction = null; + foreach (var huskPrefab in AfflictionPrefab.Prefabs.OfType()) { - DebugConsole.ThrowError("Cannot find a husk infection that matches this species! Please add the speciesnames as 'targets' in the husk affliction prefab definition!"); + var nonHuskedName = AfflictionHusk.GetNonHuskedSpeciesName(speciesName, huskPrefab); + if (huskPrefab.TargetSpecies.Contains(nonHuskedName)) + { + var huskedSpeciesName = AfflictionHusk.GetHuskedSpeciesName(nonHuskedName, huskPrefab); + if (huskedSpeciesName.Equals(speciesName)) + { + nonHuskedSpeciesName = nonHuskedName; + matchingAffliction = huskPrefab; + break; + } + } + } + if (matchingAffliction == null || nonHuskedSpeciesName.IsEmpty) + { + DebugConsole.ThrowError($"Cannot find a husk infection that matches {speciesName}! Please make sure that the speciesname is added as 'targets' in the husk affliction prefab definition!\n" + + "Note that all the infected speciesnames and files must stick the following pattern: [nonhuskedspeciesname][huskedspeciesname]. E.g. Humanhusk, Crawlerhusk, or Humancustomhusk, or Crawlerzombie. Not \"Customhumanhusk!\" or \"Zombiecrawler\""); // Crashes if we fail to create a ragdoll -> Let's just use some ragdoll so that the user sees the error msg. nonHuskedSpeciesName = IsHumanoid ? CharacterPrefab.HumanSpeciesName : "crawler".ToIdentifier(); speciesName = nonHuskedSpeciesName; } - else - { - nonHuskedSpeciesName = AfflictionHusk.GetNonHuskedSpeciesName(speciesName, matchingAffliction); - } if (ragdollParams == null && prefab.VariantOf == null) { Identifier name = Params.UseHuskAppendage ? nonHuskedSpeciesName : speciesName; diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/CharacterInfo.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/CharacterInfo.cs index aa44f780e..8c37271bd 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/CharacterInfo.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/CharacterInfo.cs @@ -1287,6 +1287,11 @@ namespace Barotrauma if (splitTag[0] != "name") { continue; } if (splitTag[1] != Name) { continue; } item.ReplaceTag(tag, $"name:{newName}"); + var idCard = item.GetComponent(); + if (idCard != null) + { + idCard.OwnerName = newName; + } break; } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/Health/Afflictions/Affliction.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/Health/Afflictions/Affliction.cs index c8dca9919..4aebc88c4 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/Health/Afflictions/Affliction.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/Health/Afflictions/Affliction.cs @@ -50,6 +50,9 @@ namespace Barotrauma [Serialize(1.0f, IsPropertySaveable.Yes, description: "The probability for the affliction to be applied."), Editable(minValue: 0f, maxValue: 1f)] public float Probability { get; set; } = 1.0f; + [Serialize(true, IsPropertySaveable.Yes, description: "Explosion damage is applied per each affected limb. Should this affliction damage be divided by the count of affected limbs (1-15) or applied in full? Default: true. Only affects explosions."), Editable] + public bool DivideByLimbCount { get; set; } + public float DamagePerSecond; public float DamagePerSecondTimer; public float PreviousVitalityDecrease; @@ -96,9 +99,11 @@ namespace Barotrauma SerializableProperties = SerializableProperty.DeserializeProperties(this, element); } - public Affliction CreateMultiplied(float multiplier) + public Affliction CreateMultiplied(float multiplier, float probability) { - return Prefab.Instantiate(NonClampedStrength * multiplier, Source); + var instance = Prefab.Instantiate(NonClampedStrength * multiplier, Source); + instance.Probability = probability; + return instance; } public override string ToString() => Prefab == null ? "Affliction (Invalid)" : $"Affliction ({Prefab.Name})"; diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/Health/Afflictions/AfflictionHusk.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/Health/Afflictions/AfflictionHusk.cs index 4069abe8f..cd6e25f64 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/Health/Afflictions/AfflictionHusk.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/Health/Afflictions/AfflictionHusk.cs @@ -450,13 +450,12 @@ namespace Barotrauma public static Identifier GetHuskedSpeciesName(Identifier speciesName, AfflictionPrefabHusk prefab) { - return prefab.HuskedSpeciesName.Replace(AfflictionPrefabHusk.Tag, speciesName); + return new Identifier(speciesName.Value + prefab.HuskedSpeciesName.Value); } public static Identifier GetNonHuskedSpeciesName(Identifier huskedSpeciesName, AfflictionPrefabHusk prefab) { - Identifier nonTag = prefab.HuskedSpeciesName.Remove(AfflictionPrefabHusk.Tag); - return huskedSpeciesName.Remove(nonTag); + return huskedSpeciesName.Remove(prefab.HuskedSpeciesName); } } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/Health/Afflictions/AfflictionPrefab.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/Health/Afflictions/AfflictionPrefab.cs index 04d620a18..a18f012bc 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/Health/Afflictions/AfflictionPrefab.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/Health/Afflictions/AfflictionPrefab.cs @@ -63,8 +63,10 @@ namespace Barotrauma if (HuskedSpeciesName.IsEmpty) { DebugConsole.NewMessage($"No 'huskedspeciesname' defined for the husk affliction ({Identifier}) in {element}", Color.Orange); - HuskedSpeciesName = "[speciesname]husk".ToIdentifier(); + HuskedSpeciesName = "husk".ToIdentifier(); } + // Remove "[speciesname]" for backward support (we don't use it anymore) + HuskedSpeciesName = HuskedSpeciesName.Remove("[speciesname]").ToIdentifier(); TargetSpecies = element.GetAttributeIdentifierArray("targets", Array.Empty(), trim: true); if (TargetSpecies.Length == 0) { @@ -108,7 +110,6 @@ namespace Barotrauma public readonly Identifier HuskedSpeciesName; public readonly Identifier[] TargetSpecies; - public static readonly Identifier Tag = "[speciesname]".ToIdentifier(); public readonly bool TransferBuffs; public readonly bool SendMessages; @@ -404,8 +405,18 @@ namespace Barotrauma AfflictionType = element.GetAttributeIdentifier("type", ""); TranslationIdentifier = element.GetAttributeIdentifier("translationoverride", Identifier); - Name = TextManager.Get($"AfflictionName.{TranslationIdentifier}").Fallback(element.GetAttributeString("name", "")); - Description = TextManager.Get($"AfflictionDescription.{TranslationIdentifier}").Fallback(element.GetAttributeString("description", "")); + Name = TextManager.Get($"AfflictionName.{TranslationIdentifier}"); + string fallbackName = element.GetAttributeString("name", ""); + if (!string.IsNullOrEmpty(fallbackName)) + { + Name = Name.Fallback(fallbackName); + } + Description = TextManager.Get($"AfflictionDescription.{TranslationIdentifier}"); + string fallbackDescription = element.GetAttributeString("description", ""); + if (!string.IsNullOrEmpty(fallbackDescription)) + { + Description = Description.Fallback(fallbackDescription); + } IsBuff = element.GetAttributeBool("isbuff", false); HealableInMedicalClinic = element.GetAttributeBool("healableinmedicalclinic", diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/Health/CharacterHealth.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/Health/CharacterHealth.cs index c159dfbe5..e91b9d77e 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/Health/CharacterHealth.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/Health/CharacterHealth.cs @@ -909,19 +909,11 @@ namespace Barotrauma float vitalityDecrease = affliction.GetVitalityDecrease(this); if (limbHealth != null) { - if (limbHealth.VitalityMultipliers.ContainsKey(affliction.Prefab.Identifier)) - { - vitalityDecrease *= limbHealth.VitalityMultipliers[affliction.Prefab.Identifier]; - } - if (limbHealth.VitalityTypeMultipliers.ContainsKey(affliction.Prefab.AfflictionType)) - { - vitalityDecrease *= limbHealth.VitalityTypeMultipliers[affliction.Prefab.AfflictionType]; - } + vitalityDecrease *= GetVitalityMultiplier(affliction, limbHealth); } Vitality -= vitalityDecrease; affliction.CalculateDamagePerSecond(vitalityDecrease); } - #if CLIENT if (IsUnconscious) { @@ -930,6 +922,33 @@ namespace Barotrauma #endif } + private float GetVitalityMultiplier(Affliction affliction, LimbHealth limbHealth) + { + float multiplier = 1.0f; + if (limbHealth.VitalityMultipliers.TryGetValue(affliction.Prefab.Identifier, out float vitalityMultiplier)) + { + multiplier *= vitalityMultiplier; + } + if (limbHealth.VitalityTypeMultipliers.TryGetValue(affliction.Prefab.AfflictionType, out float vitalityTypeMultiplier)) + { + multiplier *= vitalityTypeMultiplier; + } + return multiplier; + } + + /// + /// How much vitality the affliction reduces, taking into account the effects of vitality modifiers on the limb the affliction is on (if limb-based) + /// + private float GetVitalityDecreaseWithVitalityMultipliers(Affliction affliction) + { + float vitalityDecrease = affliction.GetVitalityDecrease(this); + if (afflictions.TryGetValue(affliction, out LimbHealth limbHealth) && limbHealth != null) + { + vitalityDecrease *= GetVitalityMultiplier(affliction, limbHealth); + } + return vitalityDecrease; + } + private void Kill() { if (Unkillable || Character.GodMode) { return; } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/Limb.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/Limb.cs index 847ef13d1..030e232b1 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/Limb.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/Limb.cs @@ -218,6 +218,8 @@ namespace Barotrauma public Vector2 StepOffset => ConvertUnits.ToSimUnits(Params.StepOffset) * ragdoll.RagdollParams.JointScale; + public Hull Hull; + public bool InWater { get; set; } private FixedMouseJoint pullJoint; @@ -720,11 +722,12 @@ namespace Barotrauma tempModifiers.Clear(); var newAffliction = affliction; float random = Rand.Value(Rand.RandSync.Unsynced); - if (random > affliction.Probability) { continue; } + bool foundMatchingModifier = false; bool applyAffliction = true; foreach (DamageModifier damageModifier in DamageModifiers) { if (!damageModifier.MatchesAffliction(affliction)) { continue; } + foundMatchingModifier = true; if (random > affliction.Probability * damageModifier.ProbabilityMultiplier) { applyAffliction = false; @@ -740,6 +743,7 @@ namespace Barotrauma foreach (DamageModifier damageModifier in wearable.WearableComponent.DamageModifiers) { if (!damageModifier.MatchesAffliction(affliction)) { continue; } + foundMatchingModifier = true; if (random > affliction.Probability * damageModifier.ProbabilityMultiplier) { applyAffliction = false; @@ -751,6 +755,7 @@ namespace Barotrauma } } } + if (!foundMatchingModifier && random > affliction.Probability) { continue; } float finalDamageModifier = damageMultiplier; foreach (DamageModifier damageModifier in tempModifiers) { @@ -763,7 +768,7 @@ namespace Barotrauma } if (!MathUtils.NearlyEqual(finalDamageModifier, 1.0f)) { - newAffliction = affliction.CreateMultiplied(finalDamageModifier); + newAffliction = affliction.CreateMultiplied(finalDamageModifier, affliction.Probability); } else { diff --git a/Barotrauma/BarotraumaShared/SharedSource/ContentManagement/ContentFile/OtherFile.cs b/Barotrauma/BarotraumaShared/SharedSource/ContentManagement/ContentFile/OtherFile.cs index 57b5eaf64..6357712a1 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/ContentManagement/ContentFile/OtherFile.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/ContentManagement/ContentFile/OtherFile.cs @@ -1,5 +1,3 @@ -using Barotrauma; - namespace Barotrauma { diff --git a/Barotrauma/BarotraumaShared/SharedSource/ContentManagement/ContentPackageManager.cs b/Barotrauma/BarotraumaShared/SharedSource/ContentManagement/ContentPackageManager.cs index 1d11503a1..6eb09305c 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/ContentManagement/ContentPackageManager.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/ContentManagement/ContentPackageManager.cs @@ -7,7 +7,6 @@ using System.Collections.Immutable; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Linq; -using System.Threading.Tasks; using System.Xml.Linq; using Barotrauma.IO; using Barotrauma.Steam; diff --git a/Barotrauma/BarotraumaShared/SharedSource/DebugConsole.cs b/Barotrauma/BarotraumaShared/SharedSource/DebugConsole.cs index a1954e4a8..fc7e77728 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/DebugConsole.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/DebugConsole.cs @@ -430,7 +430,7 @@ namespace Barotrauma if (GameMain.NetworkMember == null || args.Length == 0) return; int.TryParse(args[0], out int id); - var client = GameMain.NetworkMember.ConnectedClients.Find(c => c.ID == id); + var client = GameMain.NetworkMember.ConnectedClients.Find(c => c.SessionId == id); if (client == null) { ThrowError("Client id \"" + id + "\" not found."); @@ -466,7 +466,7 @@ namespace Barotrauma banDuration = parsedBanDuration; } - GameMain.NetworkMember.BanPlayer(clientName, reason, false, banDuration); + GameMain.NetworkMember.BanPlayer(clientName, reason, banDuration); }); }); }, @@ -485,7 +485,7 @@ namespace Barotrauma if (GameMain.NetworkMember == null || args.Length == 0) return; int.TryParse(args[0], out int id); - var client = GameMain.NetworkMember.ConnectedClients.Find(c => c.ID == id); + var client = GameMain.NetworkMember.ConnectedClients.Find(c => c.SessionId == id); if (client == null) { ThrowError("Client id \"" + id + "\" not found."); @@ -509,12 +509,12 @@ namespace Barotrauma banDuration = parsedBanDuration; } - GameMain.NetworkMember.BanPlayer(client.Name, reason, false, banDuration); + GameMain.NetworkMember.BanPlayer(client.Name, reason, banDuration); }); }); })); - commands.Add(new Command("banendpoint|banip", "banendpoint [endpoint]: Ban the IP address/SteamID from the server.", null)); + commands.Add(new Command("banaddress|banip", "banaddress [endpoint]: Ban the IP address/SteamID from the server.", null)); commands.Add(new Command("teleportcharacter|teleport", "teleport [character name]: Teleport the specified character to the position of the cursor. If the name parameter is omitted, the controlled character will be teleported.", null, () => diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/EventManager.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/EventManager.cs index 3fe4f0725..8ecedce89 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Events/EventManager.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/EventManager.cs @@ -191,7 +191,6 @@ namespace Barotrauma if (unlockPathEventPrefab != null) { var newEvent = unlockPathEventPrefab.CreateInstance(); - newEvent.Init(); ActiveEvents.Add(newEvent); } else @@ -223,6 +222,7 @@ namespace Barotrauma PreloadContent(GetFilesToPreload()); roundDuration = 0.0f; + eventsInitialized = false; isCrewAway = false; crewAwayDuration = 0.0f; crewAwayResetTimer = 0.0f; @@ -460,7 +460,6 @@ namespace Barotrauma var newEvent = eventPrefab.CreateInstance(); if (newEvent == null) { continue; } - newEvent.Init(eventSet); if (i < spawnPosFilter.Count) { newEvent.SpawnPosFilter = spawnPosFilter[i]; } DebugConsole.NewMessage($"Initialized event {newEvent}", debugOnly: true); if (!selectedEvents.ContainsKey(eventSet)) @@ -490,8 +489,6 @@ namespace Barotrauma var eventPrefab = ToolBox.SelectWeightedRandom(eventPrefabs.Where(isPrefabSuitable), e => e.Commonness, rand); var newEvent = eventPrefab.CreateInstance(); if (newEvent == null) { continue; } - newEvent.Init(eventSet); - DebugConsole.NewMessage($"Initialized event {newEvent}", debugOnly: true); if (!selectedEvents.ContainsKey(eventSet)) { selectedEvents.Add(eventSet, new List()); @@ -614,12 +611,25 @@ namespace Barotrauma return true; } + private bool eventsInitialized; public void Update(float deltaTime) { if (!Enabled || level == null) { return; } if (GameMain.GameSession.Campaign?.DisableEvents ?? false) { return; } + if (!eventsInitialized) + { + foreach (var eventSet in selectedEvents.Keys) + { + foreach (var ev in selectedEvents[eventSet]) + { + ev.Init(eventSet); + } + } + eventsInitialized = true; + } + //clients only calculate the intensity but don't create any events //(the intensity is used for controlling the background music) CalculateCurrentIntensity(deltaTime); diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/BeaconMission.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/BeaconMission.cs index 9e3c000b3..d2770b68b 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/BeaconMission.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/BeaconMission.cs @@ -100,7 +100,8 @@ namespace Barotrauma if (!connectedSubs.Contains(item.Submarine)) { continue; } if (item.GetComponent() != null || item.GetComponent() != null || - item.GetComponent() != null) + item.GetComponent() != null || + item.GetComponent() != null) { item.InvulnerableToDamage = true; } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/MonsterEvent.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/MonsterEvent.cs index 8dae48c00..e76ab4c70 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Events/MonsterEvent.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/MonsterEvent.cs @@ -125,8 +125,7 @@ namespace Barotrauma var file = CharacterPrefab.FindBySpeciesName(SpeciesName)?.ContentFile; if (file == null) { - DebugConsole.ThrowError($"Failed to find config file for species \"{SpeciesName}\". Content package: \"{prefab.ConfigElement?.ContentPackage?.Name ?? "unknown"}\"."); - disallowed = true; + DebugConsole.ThrowError($"Failed to find config file for species \"{SpeciesName}\""); yield break; } else @@ -147,6 +146,32 @@ namespace Barotrauma { DebugConsole.NewMessage("Initialized MonsterEvent (" + SpeciesName + ")", Color.White); } + + monsters = new List(); + + //+1 because Range returns an integer less than the max value + int amount = Rand.Range(MinAmount, MaxAmount + 1); + for (int i = 0; i < amount; i++) + { + string seed = Level.Loaded.Seed + i.ToString(); + Character createdCharacter = Character.Create(SpeciesName, Vector2.Zero, seed, characterInfo: null, isRemotePlayer: false, hasAi: true, createNetworkEvent: true, throwErrorIfNotFound: false); + if (createdCharacter == null) + { + DebugConsole.AddWarning($"Error in MonsterEvent: failed to spawn the character \"{SpeciesName}\". Content package: \"{prefab.ConfigElement?.ContentPackage?.Name ?? "unknown"}\"."); + disallowed = true; + continue; + } + if (GameMain.GameSession.IsCurrentLocationRadiated()) + { + AfflictionPrefab radiationPrefab = AfflictionPrefab.RadiationSickness; + Affliction affliction = new Affliction(radiationPrefab, radiationPrefab.MaxStrength); + createdCharacter?.CharacterHealth.ApplyAffliction(null, affliction); + // TODO test multiplayer + createdCharacter?.Kill(CauseOfDeathType.Affliction, affliction, log: false); + } + createdCharacter.DisabledByEvent = true; + monsters.Add(createdCharacter); + } } private List GetAvailableSpawnPositions() @@ -487,9 +512,6 @@ namespace Barotrauma spawnPending = false; - //+1 because Range returns an integer less than the max value - int amount = Rand.Range(MinAmount, MaxAmount + 1); - monsters = new List(); float scatterAmount = scatter; if (SpawnPosType.HasFlag(Level.PositionType.SidePath)) { @@ -508,9 +530,9 @@ namespace Barotrauma scatterAmount = 0; } - for (int i = 0; i < amount; i++) + int i = 0; + foreach (Character monster in monsters) { - string seed = Level.Loaded.Seed + i.ToString(); CoroutineManager.Invoke(() => { //round ended before the coroutine finished @@ -533,45 +555,33 @@ namespace Barotrauma } } - Character createdCharacter = Character.Create(SpeciesName, pos, seed, characterInfo: null, isRemotePlayer: false, hasAi: true, createNetworkEvent: true, throwErrorIfNotFound: false); - if (createdCharacter == null) - { - DebugConsole.AddWarning($"Error in MonsterEvent: failed to spawn the character \"{SpeciesName}\". Content package: \"{prefab.ConfigElement?.ContentPackage?.Name ?? "unknown"}\"."); - disallowed = true; - return; - } + monster.Enabled = true; + monster.DisabledByEvent = false; + monster.AnimController.SetPosition(FarseerPhysics.ConvertUnits.ToSimUnits(pos)); + var eventManager = GameMain.GameSession.EventManager; if (eventManager != null) { if (SpawnPosType.HasFlag(Level.PositionType.MainPath) || SpawnPosType.HasFlag(Level.PositionType.SidePath)) { - eventManager.CumulativeMonsterStrengthMain += createdCharacter.Params.AI.CombatStrength; + eventManager.CumulativeMonsterStrengthMain += monster.Params.AI.CombatStrength; eventManager.AddTimeStamp(this); } else if (SpawnPosType.HasFlag(Level.PositionType.Ruin)) { - eventManager.CumulativeMonsterStrengthRuins += createdCharacter.Params.AI.CombatStrength; + eventManager.CumulativeMonsterStrengthRuins += monster.Params.AI.CombatStrength; } else if (SpawnPosType.HasFlag(Level.PositionType.Wreck)) { - eventManager.CumulativeMonsterStrengthWrecks += createdCharacter.Params.AI.CombatStrength; + eventManager.CumulativeMonsterStrengthWrecks += monster.Params.AI.CombatStrength; } else if (SpawnPosType.HasFlag(Level.PositionType.Cave)) { - eventManager.CumulativeMonsterStrengthCaves += createdCharacter.Params.AI.CombatStrength; + eventManager.CumulativeMonsterStrengthCaves += monster.Params.AI.CombatStrength; } } - if (GameMain.GameSession.IsCurrentLocationRadiated()) - { - AfflictionPrefab radiationPrefab = AfflictionPrefab.RadiationSickness; - Affliction affliction = new Affliction(radiationPrefab, radiationPrefab.MaxStrength); - createdCharacter?.CharacterHealth.ApplyAffliction(null, affliction); - // TODO test multiplayer - createdCharacter?.Kill(CauseOfDeathType.Affliction, affliction, log: false); - } - monsters.Add(createdCharacter); - if (monsters.Count == amount) + if (monster == monsters.Last()) { spawnReady = true; //this will do nothing if the monsters have no swarm behavior defined, @@ -587,6 +597,7 @@ namespace Barotrauma value: Timing.TotalTime - GameMain.GameSession.RoundStartTime); } }, delayBetweenSpawns * i); + i++; } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Extensions/StringExtensions.cs b/Barotrauma/BarotraumaShared/SharedSource/Extensions/StringExtensions.cs index b254682e4..7b2e4ab9f 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Extensions/StringExtensions.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Extensions/StringExtensions.cs @@ -3,7 +3,7 @@ using System; namespace Barotrauma { - public static class StringExtensions + static class StringExtensions { public static string FallbackNullOrEmpty(this string s, string fallback) => string.IsNullOrEmpty(s) ? fallback : s; diff --git a/Barotrauma/BarotraumaShared/SharedSource/GameAnalytics/GameAnalyticsManager.cs b/Barotrauma/BarotraumaShared/SharedSource/GameAnalytics/GameAnalyticsManager.cs index 9a0eddeed..a122a213c 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/GameAnalytics/GameAnalyticsManager.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/GameAnalytics/GameAnalyticsManager.cs @@ -467,11 +467,11 @@ namespace Barotrauma SetConsent(Consent.Error); return; } - loadedImplementation?.SetEnabledInfoLog(true); - loadedImplementation?.SetEnabledVerboseLog(true); #if DEBUG try { + loadedImplementation?.SetEnabledInfoLog(true); + loadedImplementation?.SetEnabledVerboseLog(true); } catch (Exception e) { diff --git a/Barotrauma/BarotraumaShared/SharedSource/GameSession/GameModes/CampaignMode.cs b/Barotrauma/BarotraumaShared/SharedSource/GameSession/GameModes/CampaignMode.cs index 7e6bf9e6e..b6868a586 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/GameSession/GameModes/CampaignMode.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/GameSession/GameModes/CampaignMode.cs @@ -133,6 +133,8 @@ namespace Barotrauma protected set; } + public bool PurchasedLostShuttlesInLatestSave, PurchasedHullRepairsInLatestSave, PurchasedItemRepairsInLatestSave; + public virtual bool PurchasedHullRepairs { get; set; } public virtual bool PurchasedLostShuttles { get; set; } public virtual bool PurchasedItemRepairs { get; set; } @@ -228,7 +230,8 @@ namespace Barotrauma #if CLIENT prevCampaignUIAutoOpenType = TransitionType.None; #endif - if (PurchasedHullRepairs) + + if (PurchasedHullRepairsInLatestSave) { foreach (Structure wall in Structure.WallList) { @@ -241,9 +244,9 @@ namespace Barotrauma } } } - PurchasedHullRepairs = false; + PurchasedHullRepairsInLatestSave = PurchasedHullRepairs = false; } - if (PurchasedItemRepairs) + if (PurchasedItemRepairsInLatestSave) { foreach (Item item in Item.ItemList) { @@ -256,9 +259,9 @@ namespace Barotrauma } } } - PurchasedItemRepairs = false; + PurchasedItemRepairsInLatestSave = PurchasedItemRepairs = false; } - PurchasedLostShuttles = false; + PurchasedLostShuttlesInLatestSave = PurchasedLostShuttles = false; var connectedSubs = Submarine.MainSub.GetConnectedSubs(); wasDocked = Level.Loaded.StartOutpost != null && connectedSubs.Contains(Level.Loaded.StartOutpost); } @@ -725,7 +728,7 @@ namespace Barotrauma } foreach (LocationConnection connection in Map.Connections) { - connection.Difficulty = connection.Biome.MaxDifficulty; + connection.Difficulty = connection.Biome.AdjustedMaxDifficulty; connection.LevelData = new LevelData(connection) { IsBeaconActive = false @@ -734,7 +737,7 @@ namespace Barotrauma } foreach (Location location in Map.Locations) { - location.LevelData = new LevelData(location, location.Biome.MaxDifficulty); + location.LevelData = new LevelData(location, location.Biome.AdjustedMaxDifficulty); location.Reset(); } Map.SetLocation(Map.Locations.IndexOf(Map.StartLocation)); diff --git a/Barotrauma/BarotraumaShared/SharedSource/GameSession/GameModes/CharacterCampaignData.cs b/Barotrauma/BarotraumaShared/SharedSource/GameSession/GameModes/CharacterCampaignData.cs index cc4948562..5c260e037 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/GameSession/GameModes/CharacterCampaignData.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/GameSession/GameModes/CharacterCampaignData.cs @@ -1,27 +1,16 @@ using System.Xml.Linq; +using Barotrauma.Networking; namespace Barotrauma { partial class CharacterCampaignData { - public CharacterInfo CharacterInfo - { - get; - private set; - } + public readonly CharacterInfo CharacterInfo; public readonly string Name; - public string ClientEndPoint - { - get; - private set; - } - public ulong SteamID - { - get; - private set; - } + public readonly Address ClientAddress; + public readonly Option AccountId; private XElement itemData; private XElement healthData; diff --git a/Barotrauma/BarotraumaShared/SharedSource/GameSession/GameModes/MultiPlayerCampaign.cs b/Barotrauma/BarotraumaShared/SharedSource/GameSession/GameModes/MultiPlayerCampaign.cs index 18a0f6fcf..32fbcd28a 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/GameSession/GameModes/MultiPlayerCampaign.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/GameSession/GameModes/MultiPlayerCampaign.cs @@ -151,9 +151,9 @@ namespace Barotrauma /// private void Load(XElement element) { - PurchasedLostShuttles = element.GetAttributeBool("purchasedlostshuttles", false); - PurchasedHullRepairs = element.GetAttributeBool("purchasedhullrepairs", false); - PurchasedItemRepairs = element.GetAttributeBool("purchaseditemrepairs", false); + PurchasedLostShuttlesInLatestSave = element.GetAttributeBool("purchasedlostshuttles", false); + PurchasedHullRepairsInLatestSave = element.GetAttributeBool("purchasedhullrepairs", false); + PurchasedItemRepairsInLatestSave = element.GetAttributeBool("purchaseditemrepairs", false); CheatsEnabled = element.GetAttributeBool("cheatsenabled", false); if (CheatsEnabled) { diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/ElectricalDischarger.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/ElectricalDischarger.cs index 76dd68595..0d2f9e1e1 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/ElectricalDischarger.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/ElectricalDischarger.cs @@ -203,7 +203,7 @@ namespace Barotrauma.Items.Components foreach ((Character character, Node node) in charactersInRange) { if (character == null || character.Removed) { continue; } - character.ApplyAttack(null, node.WorldPosition, attack, 1.0f); + character.ApplyAttack(null, node.WorldPosition, attack, MathHelper.Clamp(Voltage, 1.0f, MaxOverVoltageFactor)); } } DischargeProjSpecific(); diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Holdable/Holdable.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Holdable/Holdable.cs index 8e49398a5..5641b078f 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Holdable/Holdable.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Holdable/Holdable.cs @@ -295,12 +295,11 @@ namespace Barotrauma.Items.Components if (attachable) { - DeattachFromWall(); - if (body != null) { item.body = body; } + DeattachFromWall(); } if (Pusher != null) { Pusher.Enabled = false; } @@ -619,6 +618,10 @@ namespace Barotrauma.Items.Components #if CLIENT item.DrawDepthOffset = SpriteDepthWhenDropped - item.SpriteDepth; #endif + foreach (LightComponent light in item.GetComponents()) + { + light.CheckIfNeedsUpdate(); + } } public override void ParseMsg() diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Holdable/Pickable.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Holdable/Pickable.cs index 61ab48fe9..89b3f95f7 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Holdable/Pickable.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Holdable/Pickable.cs @@ -165,31 +165,32 @@ namespace Barotrauma.Items.Components pickTimer = 0.0f; while (pickTimer < requiredTime && Screen.Selected != GameMain.SubEditorScreen) { - //cancel if the item is currently selected - //attempting to pick does not select the item, so if it is selected at this point, another ItemComponent - //must have been selected and we should not keep deattaching (happens when for example interacting with - //an electrical component while holding both a screwdriver and a wrench). - if (picker.IsAnySelectedItem(item)|| - picker.IsKeyDown(InputType.Aim) || - !picker.CanInteractWith(item) || - item.Removed || item.ParentInventory != null) + if (!CoroutineManager.Paused) { - StopPicking(picker); - yield return CoroutineStatus.Success; - } + //cancel if the item is currently selected + //attempting to pick does not select the item, so if it is selected at this point, another ItemComponent + //must have been selected and we should not keep deattaching (happens when for example interacting with + //an electrical component while holding both a screwdriver and a wrench). + if (picker.IsAnySelectedItem(item) || + picker.IsKeyDown(InputType.Aim) || + !picker.CanInteractWith(item) || + item.Removed || item.ParentInventory != null) + { + StopPicking(picker); + yield return CoroutineStatus.Success; + } #if CLIENT - Character.Controlled?.UpdateHUDProgressBar( - this, - item.WorldPosition, - pickTimer / requiredTime, - GUIStyle.Red, GUIStyle.Green, - !string.IsNullOrWhiteSpace(PickingMsg) ? PickingMsg : this is Door ? "progressbar.opening" : "progressbar.deattaching"); + Character.Controlled?.UpdateHUDProgressBar( + this, + item.WorldPosition, + pickTimer / requiredTime, + GUIStyle.Red, GUIStyle.Green, + !string.IsNullOrWhiteSpace(PickingMsg) ? PickingMsg : this is Door ? "progressbar.opening" : "progressbar.deattaching"); #endif - - picker.AnimController.UpdateUseItem(!picker.IsClimbing, item.WorldPosition + new Vector2(0.0f, 100.0f) * ((pickTimer / 10.0f) % 0.1f)); - pickTimer += CoroutineManager.DeltaTime; - + picker.AnimController.UpdateUseItem(!picker.IsClimbing, item.WorldPosition + new Vector2(0.0f, 100.0f) * ((pickTimer / 10.0f) % 0.1f)); + pickTimer += CoroutineManager.DeltaTime; + } yield return CoroutineStatus.Running; } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Deconstructor.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Deconstructor.cs index c119ceec5..d7042894f 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Deconstructor.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Deconstructor.cs @@ -96,7 +96,7 @@ namespace Barotrauma.Items.Components ApplyStatusEffects(ActionType.OnActive, deltaTime, null); - progressTimer += deltaTime * Math.Min(powerConsumption <= 0.0f ? 1 : Voltage, 1.0f); + progressTimer += deltaTime * Math.Min(powerConsumption <= 0.0f ? 1 : Voltage, MaxOverVoltageFactor); float tinkeringStrength = 0f; if (repairable.IsTinkering) @@ -205,18 +205,18 @@ namespace Barotrauma.Items.Components foreach (DeconstructItem deconstructProduct in products) { - CreateDeconstructProduct(deconstructProduct, inputItems, amountMultiplier); + CreateDeconstructProduct(deconstructProduct, inputItems, (int)(amountMultiplier * deconstructProduct.Amount)); } } else { foreach (DeconstructItem deconstructProduct in validDeconstructItems) { - CreateDeconstructProduct(deconstructProduct, inputItems, amountMultiplier); + CreateDeconstructProduct(deconstructProduct, inputItems, (int)(amountMultiplier * deconstructProduct.Amount)); } } - void CreateDeconstructProduct(DeconstructItem deconstructProduct, IEnumerable inputItems, float amountMultiplier) + void CreateDeconstructProduct(DeconstructItem deconstructProduct, IEnumerable inputItems, int amount) { float percentageHealth = targetItem.Condition / targetItem.MaxCondition; @@ -284,7 +284,6 @@ namespace Barotrauma.Items.Components user.CheckTalents(AbilityEffectType.OnItemDeconstructedInventory, itemDeconstructedInventory); } - int amount = (int)amountMultiplier; for (int i = 0; i < amount; i++) { Entity.Spawner.AddItemToSpawnQueue(itemPrefab, outputContainer.Inventory, condition, onSpawned: (Item spawnedItem) => diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Engine.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Engine.cs index 1596f3c25..13f858f37 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Engine.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Engine.cs @@ -117,7 +117,7 @@ namespace Barotrauma.Items.Components Force = MathHelper.Lerp(force, (Voltage < MinVoltage) ? 0.0f : targetForce, deltaTime * 10.0f); if (Math.Abs(Force) > 1.0f) { - float voltageFactor = MinVoltage <= 0.0f ? 1.0f : Math.Min(Voltage, 1.0f); + float voltageFactor = MinVoltage <= 0.0f ? 1.0f : Math.Min(Voltage, MaxOverVoltageFactor); float currForce = force * voltageFactor; float condition = item.Condition / item.MaxCondition; // Broken engine makes more noise. diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Fabricator.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Fabricator.cs index 6c15619ce..c3a9cb39e 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Fabricator.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Fabricator.cs @@ -305,7 +305,7 @@ namespace Barotrauma.Items.Components float fabricationSpeedIncrease = 1f + tinkeringStrength * TinkeringSpeedIncrease; - timeUntilReady -= deltaTime * fabricationSpeedIncrease * Math.Min(powerConsumption <= 0 ? 1 : Voltage, 1.0f); + timeUntilReady -= deltaTime * fabricationSpeedIncrease * Math.Min(powerConsumption <= 0 ? 1 : Voltage, MaxOverVoltageFactor); UpdateRequiredTimeProjSpecific(); @@ -371,8 +371,7 @@ namespace Barotrauma.Items.Components var availableItems = availableIngredients[requiredPrefab.Identifier]; var availableItem = availableItems.FirstOrDefault(potentialPrefab => { - return potentialPrefab.ConditionPercentage >= requiredItem.MinCondition * 100.0f && - potentialPrefab.ConditionPercentage <= requiredItem.MaxCondition * 100.0f; + return requiredItem.IsConditionSuitable(potentialPrefab.ConditionPercentage); }); if (availableItem == null) { continue; } @@ -616,8 +615,7 @@ namespace Barotrauma.Items.Components var availablePrefabs = availableIngredients[requiredPrefab.Identifier]; foreach (Item availablePrefab in availablePrefabs) { - if (availablePrefab.ConditionPercentage / 100.0f >= requiredItem.MinCondition && - availablePrefab.ConditionPercentage / 100.0f <= requiredItem.MaxCondition) + if (requiredItem.IsConditionSuitable(availablePrefab.ConditionPercentage)) { availablePrefabsAmount++; } @@ -732,9 +730,7 @@ namespace Barotrauma.Items.Components var availablePrefabs = availableIngredients[requiredPrefab.Identifier]; var availablePrefab = availablePrefabs.FirstOrDefault(potentialPrefab => { - return !usedItems.Contains(potentialPrefab) && - potentialPrefab.ConditionPercentage >= requiredItem.MinCondition * 100.0f && - potentialPrefab.ConditionPercentage <= requiredItem.MaxCondition * 100.0f; + return !usedItems.Contains(potentialPrefab) && requiredItem.IsConditionSuitable(potentialPrefab.ConditionPercentage); }); if (availablePrefab == null) { continue; } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/OxygenGenerator.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/OxygenGenerator.cs index 901359d64..47609785a 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/OxygenGenerator.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/OxygenGenerator.cs @@ -2,7 +2,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Xml.Linq; namespace Barotrauma.Items.Components { @@ -52,7 +51,7 @@ namespace Barotrauma.Items.Components return; } - CurrFlow = Math.Min(PowerConsumption > 0 ? Voltage : 1.0f, 1.0f) * generatedAmount * 100.0f; + CurrFlow = Math.Min(PowerConsumption > 0 ? Voltage : 1.0f, MaxOverVoltageFactor) * generatedAmount * 100.0f; float conditionMult = item.Condition / item.MaxCondition; //100% condition = 100% oxygen //50% condition = 25% oxygen diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Pump.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Pump.cs index bfd0b23fb..db2eae084 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Pump.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Pump.cs @@ -130,7 +130,7 @@ namespace Barotrauma.Items.Components if (item.CurrentHull == null) { return; } - float powerFactor = Math.Min(currPowerConsumption <= 0.0f || MinVoltage <= 0.0f ? 1.0f : Voltage, 1.0f); + float powerFactor = Math.Min(currPowerConsumption <= 0.0f || MinVoltage <= 0.0f ? 1.0f : Voltage, MaxOverVoltageFactor); currFlow = flowPercentage / 100.0f * maxFlow * powerFactor; diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Reactor.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Reactor.cs index f8191d796..3bca94419 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Reactor.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Reactor.cs @@ -11,6 +11,8 @@ namespace Barotrauma.Items.Components { const float NetworkUpdateIntervalHigh = 0.5f; + const float TemperatureBoostAmount = 20; + //the rate at which the reactor is being run on (higher rate -> higher temperature) private float fissionRate; @@ -46,6 +48,8 @@ namespace Barotrauma.Items.Components private Vector2 optimalFissionRate, allowedFissionRate; private Vector2 optimalTurbineOutput, allowedTurbineOutput; + private float temperatureBoost; + private bool _powerOn; [Serialize(defaultValue: false, isSaveable: IsPropertySaveable.Yes)] @@ -241,6 +245,34 @@ namespace Barotrauma.Items.Components } #endif + if (signalControlledTargetFissionRate.HasValue && Math.Abs(signalControlledTargetFissionRate.Value - TargetFissionRate) > 1.0f) + { + TargetFissionRate = adjustValueWithoutOverShooting(TargetFissionRate, signalControlledTargetFissionRate.Value, deltaTime * 5.0f); +#if CLIENT + FissionRateScrollBar.BarScroll = TargetFissionRate / 100.0f; +#endif + } + else + { + signalControlledTargetFissionRate = null; + } + if (signalControlledTargetTurbineOutput.HasValue && Math.Abs(signalControlledTargetTurbineOutput.Value - TargetTurbineOutput) > 1.0f) + { + TargetTurbineOutput = adjustValueWithoutOverShooting(TargetTurbineOutput, signalControlledTargetTurbineOutput.Value, deltaTime * 5.0f); +#if CLIENT + TurbineOutputScrollBar.BarScroll = TargetTurbineOutput / 100.0f; +#endif + } + else + { + signalControlledTargetTurbineOutput = null; + } + + static float adjustValueWithoutOverShooting(float current, float target, float speed) + { + return target < current ? Math.Max(target, current - speed) : Math.Min(target, current + speed); + } + prevAvailableFuel = AvailableFuel; ApplyStatusEffects(ActionType.OnActive, deltaTime, null); @@ -270,7 +302,10 @@ namespace Barotrauma.Items.Components float temperatureDiff = (heatAmount - turbineOutput) - Temperature; Temperature += MathHelper.Clamp(Math.Sign(temperatureDiff) * 10.0f * deltaTime, -Math.Abs(temperatureDiff), Math.Abs(temperatureDiff)); - //if (item.InWater && AvailableFuel < 100.0f) Temperature -= 12.0f * deltaTime; + temperatureBoost = adjustValueWithoutOverShooting(temperatureBoost, 0.0f, deltaTime); +#if CLIENT + temperatureBoostUpButton.Enabled = temperatureBoostDownButton.Enabled = Math.Abs(temperatureBoost) < TemperatureBoostAmount * 0.9f; +#endif FissionRate = MathHelper.Lerp(fissionRate, Math.Min(TargetFissionRate, AvailableFuel), deltaTime); @@ -438,7 +473,7 @@ namespace Barotrauma.Items.Components private float GetGeneratedHeat(float fissionRate) { - return fissionRate * (prevAvailableFuel / 100.0f) * 2.0f; + return fissionRate * (prevAvailableFuel / 100.0f) * 2.0f + temperatureBoost; } /// @@ -486,13 +521,15 @@ namespace Barotrauma.Items.Components if (temperature > allowedTemperature.Y) { item.SendSignal("1", "meltdown_warning"); - //faster meltdown if the item is in a bad condition - meltDownTimer += MathHelper.Lerp(deltaTime * 2.0f, deltaTime, item.Condition / item.MaxCondition); - - if (meltDownTimer > MeltdownDelay) + if (!item.InvulnerableToDamage) { - MeltDown(); - return; + //faster meltdown if the item is in a bad condition + meltDownTimer += MathHelper.Lerp(deltaTime * 2.0f, deltaTime, item.Condition / item.MaxCondition); + if (meltDownTimer > MeltdownDelay) + { + MeltDown(); + return; + } } } else @@ -797,30 +834,31 @@ namespace Barotrauma.Items.Components AutoTemp = false; TargetFissionRate = 0.0f; TargetTurbineOutput = 0.0f; - if (GameMain.NetworkMember?.IsServer ?? false) { unsentChanges = true; } + registerUnsentChanges(); } break; case "set_fissionrate": if (PowerOn && float.TryParse(signal.value, NumberStyles.Float, CultureInfo.InvariantCulture, out float newFissionRate)) { - TargetFissionRate = MathHelper.Clamp(newFissionRate, 0.0f, 100.0f); - if (GameMain.NetworkMember?.IsServer ?? false) { unsentChanges = true; } -#if CLIENT - FissionRateScrollBar.BarScroll = TargetFissionRate / 100.0f; -#endif + signalControlledTargetFissionRate = MathHelper.Clamp(newFissionRate, 0.0f, 100.0f); + registerUnsentChanges(); } break; case "set_turbineoutput": if (PowerOn && float.TryParse(signal.value, NumberStyles.Float, CultureInfo.InvariantCulture, out float newTurbineOutput)) { - TargetTurbineOutput = MathHelper.Clamp(newTurbineOutput, 0.0f, 100.0f); - if (GameMain.NetworkMember?.IsServer ?? false) { unsentChanges = true; } -#if CLIENT - TurbineOutputScrollBar.BarScroll = TargetTurbineOutput / 100.0f; -#endif + signalControlledTargetTurbineOutput = MathHelper.Clamp(newTurbineOutput, 0.0f, 100.0f); + registerUnsentChanges(); } break; } + + void registerUnsentChanges() + { + if (GameMain.NetworkMember is { IsServer: true }) { unsentChanges = true; } + } } + + private float? signalControlledTargetFissionRate, signalControlledTargetTurbineOutput; } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Power/PowerContainer.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Power/PowerContainer.cs index e23357700..67c2f4a94 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Power/PowerContainer.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Power/PowerContainer.cs @@ -98,7 +98,7 @@ namespace Barotrauma.Items.Components set { maxRechargeSpeed = Math.Max(value, 1.0f); } } - [Editable, Serialize(10.0f, IsPropertySaveable.Yes, description: "The current recharge speed of the device.")] + [Editable, Serialize(0.0f, IsPropertySaveable.Yes, description: "The current recharge speed of the device.")] public float RechargeSpeed { get { return rechargeSpeed; } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Power/PowerTransfer.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Power/PowerTransfer.cs index 388b719fc..f123939d7 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Power/PowerTransfer.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Power/PowerTransfer.cs @@ -243,8 +243,13 @@ namespace Barotrauma.Items.Components //damage the item if voltage is too high (except if running as a client) float prevCondition = item.Condition; - item.Condition -= deltaTime * 10.0f; - + //some randomness to prevent all junction boxes from breaking at the same time + if (Rand.Range(0.0f, 1.0f) < 0.01f) + { + //damaged boxes are more sensitive to overvoltage (also preventing all boxes from breaking at the same time) + float conditionFactor = MathHelper.Lerp(5.0f, 1.0f, item.Condition / item.MaxCondition); + item.Condition -= deltaTime * Rand.Range(10.0f, 500.0f) * conditionFactor; + } if (item.Condition <= 0.0f && prevCondition > 0.0f) { overloadCooldownTimer = OverloadCooldown; diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Power/Powered.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Power/Powered.cs index f0dbf6fcb..330c6bd50 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Power/Powered.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Power/Powered.cs @@ -94,6 +94,11 @@ namespace Barotrauma.Items.Components protected Connection powerIn, powerOut; + /// + /// Maximum voltage factor when the device is being overvolted. I.e. how many times more effectively the device can function when it's being overvolted + /// + protected const float MaxOverVoltageFactor = 2.0f; + protected virtual PowerPriority Priority { get { return PowerPriority.Default; } } [Editable, Serialize(0.5f, IsPropertySaveable.Yes, description: "The minimum voltage required for the device to function. " + diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Projectile.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Projectile.cs index a6fee0611..b2d26005a 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Projectile.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Projectile.cs @@ -244,6 +244,13 @@ namespace Barotrauma.Items.Components private set; } + [Serialize(false, IsPropertySaveable.No)] + public bool DamageDoors + { + get; + set; + } + public bool IsStuckToTarget => StickTarget != null; private Category originalCollisionCategories; @@ -288,7 +295,7 @@ namespace Barotrauma.Items.Components } } - private void Launch(Character user, Vector2 simPosition, float rotation, float damageMultiplier = 1f) + private void Launch(Character user, Vector2 simPosition, float rotation, float damageMultiplier = 1f, float launchImpulseModifier = 0f) { Item.body.ResetDynamics(); Item.SetTransform(simPosition, rotation); @@ -299,7 +306,7 @@ namespace Barotrauma.Items.Components // Set user for hitscan projectiles to work properly. User = user; // Need to set null for non-characterusable items. - Use(character: null); + Use(character: null, launchImpulseModifier); // Set user for normal projectiles to work properly. User = user; if (Item.Removed) { return; } @@ -312,7 +319,7 @@ namespace Barotrauma.Items.Components } } - public void Shoot(Character user, Vector2 weaponPos, Vector2 spawnPos, float rotation, List ignoredBodies, bool createNetworkEvent, float damageMultiplier = 1f) + public void Shoot(Character user, Vector2 weaponPos, Vector2 spawnPos, float rotation, List ignoredBodies, bool createNetworkEvent, float damageMultiplier = 1f, float launchImpulseModifier = 0f) { //add the limbs of the shooter to the list of bodies to be ignored //so that the player can't shoot himself @@ -320,7 +327,7 @@ namespace Barotrauma.Items.Components Vector2 projectilePos = weaponPos; //make sure there's no obstacles between the base of the weapon (or the shoulder of the character) and the end of the barrel if (Submarine.PickBody(weaponPos, spawnPos, IgnoredBodies, Physics.CollisionWall | Physics.CollisionLevel | Physics.CollisionItemBlocking, - customPredicate: (Fixture f) => { return !IgnoredBodies.Contains(f.Body); }) == null) + customPredicate: (Fixture f) => { return IgnoredBodies == null || !IgnoredBodies.Contains(f.Body); }) == null) { //no obstacles -> we can spawn the projectile at the barrel projectilePos = spawnPos; @@ -334,7 +341,7 @@ namespace Barotrauma.Items.Components projectilePos = newPos; } } - Launch(user, projectilePos, rotation, damageMultiplier); + Launch(user, projectilePos, rotation, damageMultiplier, launchImpulseModifier); if (createNetworkEvent && !Item.Removed && GameMain.NetworkMember != null && GameMain.NetworkMember.IsServer) { #if SERVER @@ -344,7 +351,7 @@ namespace Barotrauma.Items.Components } } - public bool Use(Character character = null) + public bool Use(Character character = null, float launchImpulseModifier = 0f) { if (character != null && !characterUsable) { return false; } @@ -379,7 +386,7 @@ namespace Barotrauma.Items.Components else { item.body.SetTransform(item.body.SimPosition, launchAngle); - float modifiedLaunchImpulse = LaunchImpulse * (1 + Rand.Range(-ImpulseSpread, ImpulseSpread)); + float modifiedLaunchImpulse = (LaunchImpulse + launchImpulseModifier) * (1 + Rand.Range(-ImpulseSpread, ImpulseSpread)); DoLaunch(launchDir * modifiedLaunchImpulse * item.body.Mass); System.Diagnostics.Debug.WriteLine("launch: " + modifiedLaunchImpulse + " - " + item.body.LinearVelocity); } @@ -723,7 +730,7 @@ namespace Barotrauma.Items.Components private bool OnProjectileCollision(Fixture f1, Fixture target, Contact contact) { if (User != null && User.Removed) { User = null; return false; } - if (IgnoredBodies.Contains(target.Body)) { return false; } + if (IgnoredBodies != null && IgnoredBodies.Contains(target.Body)) { return false; } //ignore character colliders (the projectile only hits limbs) if (target.CollisionCategories == Physics.CollisionCharacter && target.Body.UserData is Character) { @@ -828,7 +835,7 @@ namespace Barotrauma.Items.Components private bool HandleProjectileCollision(Fixture target, Vector2 collisionNormal, Vector2 velocity) { if (User != null && User.Removed) { User = null; } - if (IgnoredBodies.Contains(target.Body)) { return false; } + if (IgnoredBodies != null && IgnoredBodies.Contains(target.Body)) { return false; } //ignore character colliders (the projectile only hits limbs) if (target.CollisionCategories == Physics.CollisionCharacter && target.Body.UserData is Character) { @@ -870,7 +877,7 @@ namespace Barotrauma.Items.Components else if ((target.Body.UserData as Item ?? (target.Body.UserData as ItemComponent)?.Item) is Item targetItem) { if (targetItem.Removed) { return false; } - if (Attack != null && targetItem.Prefab.DamagedByProjectiles && targetItem.Condition > 0) + if (Attack != null && (targetItem.Prefab.DamagedByProjectiles || DamageDoors && targetItem.GetComponent() != null) && targetItem.Condition > 0) { attackResult = Attack.DoDamage(User ?? Attacker, targetItem, item.WorldPosition, 1.0f); #if CLIENT @@ -1067,7 +1074,7 @@ namespace Barotrauma.Items.Components item.body.CollidesWith = Physics.CollisionWall | Physics.CollisionLevel; } } - IgnoredBodies.Clear(); + IgnoredBodies?.Clear(); } private void StickToTarget(Body targetBody, Vector2 axis) diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/Connection.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/Connection.cs index 6d3fbc207..224d1882f 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/Connection.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/Connection.cs @@ -23,6 +23,9 @@ namespace Barotrauma.Items.Components private readonly HashSet wires; public IReadOnlyCollection Wires => wires; + private bool enumeratingWires; + private readonly HashSet removedWires = new HashSet(); + private readonly Item item; public readonly bool IsOutput; @@ -239,7 +242,14 @@ namespace Barotrauma.Items.Components } prevOtherConnection.recipientsDirty = true; } - wires.Remove(wire); + if (enumeratingWires) + { + removedWires.Add(wire); + } + else + { + wires.Remove(wire); + } recipientsDirty = true; } @@ -278,6 +288,7 @@ namespace Barotrauma.Items.Components public void SendSignal(Signal signal) { + enumeratingWires = true; foreach (var wire in wires) { Connection recipient = wire.OtherConnection(this); @@ -301,6 +312,12 @@ namespace Barotrauma.Items.Components } } } + enumeratingWires = false; + foreach (var removedWire in removedWires) + { + wires.Remove(removedWire); + } + removedWires.Clear(); } public void ClearConnections() @@ -313,13 +330,23 @@ namespace Barotrauma.Items.Components Powered.ChangedConnections.Add(c); } } - foreach (var wire in wires) { wire.RemoveConnection(this); recipientsDirty = true; } - wires.Clear(); + + if (enumeratingWires) + { + foreach (var wire in wires) + { + removedWires.Add(wire); + } + } + else + { + wires.Clear(); + } } public void InitializeFromLoaded() diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/LightComponent.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/LightComponent.cs index b44d136c2..5e4ba1095 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/LightComponent.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/LightComponent.cs @@ -247,9 +247,14 @@ namespace Barotrauma.Items.Components } public override void OnMapLoaded() + { + CheckIfNeedsUpdate(); + } + + public void CheckIfNeedsUpdate() { if (item.body == null && powerConsumption <= 0.0f && Parent == null && turret == null && IsOn && - (statusEffectLists == null || !statusEffectLists.ContainsKey(ActionType.OnActive)) && + (statusEffectLists == null || !statusEffectLists.ContainsKey(ActionType.OnActive)) && (IsActiveConditionals == null || IsActiveConditionals.Count == 0)) { lightBrightness = 1.0f; @@ -261,6 +266,10 @@ namespace Barotrauma.Items.Components Light.ParentSub = item.Submarine; #endif } + else + { + IsActive = true; + } } public override void Update(float deltaTime, Camera cam) diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Turret.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Turret.cs index a0b7b75be..d599a3bce 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Turret.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Turret.cs @@ -21,12 +21,15 @@ namespace Barotrauma.Items.Components private float rotation, targetRotation; - private float reload, reloadTime; + private float reload, reloadTime, delayBetweenBurst; + private int shotsPerBurst, shotCounter; private float minRotation, maxRotation; private float launchImpulse; + private float damageMultiplier; + private Camera cam; private float angularVelocity; @@ -94,6 +97,16 @@ namespace Barotrauma.Items.Components get; set; } + + public bool flipFiringOffset; + + [Serialize(false, IsPropertySaveable.No, description: "If enabled, the firing offset will alternate from left to right (i.e. flipping the x-component of the offset each shot.)")] + public bool AlternatingFiringOffset + { + get; + set; + } + public Vector2 TransformedBarrelPos { get @@ -116,6 +129,20 @@ namespace Barotrauma.Items.Components set { reloadTime = value; } } + [Editable(1, 100), Serialize(1, IsPropertySaveable.No, description: "How many projectiles needs to be shot before we add an extra break? Think of the double coilgun.")] + public int ShotsPerBurst + { + get { return shotsPerBurst; } + set { shotsPerBurst = value; } + } + + [Editable(0.0f, 1000.0f, decimals: 3), Serialize(0.0f, IsPropertySaveable.No, description: "An extra delay between the bursts. Added to the reload.")] + public float DelayBetweenBursts + { + get { return delayBetweenBurst; } + set { delayBetweenBurst = value; } + } + [Editable(0.1f, 10f), Serialize(1.0f, IsPropertySaveable.No, description: "Modifies the duration of retraction of the barrell after recoil to get back to the original position after shooting. Reload time affects this too.")] public float RetractionDurationMultiplier { @@ -137,6 +164,13 @@ namespace Barotrauma.Items.Components set; } + [Serialize(1.0f, IsPropertySaveable.No, description: "Multiplies the damage the turret deals by this amount.")] + public float DamageMultiplier + { + get { return damageMultiplier; } + set { damageMultiplier = value; } + } + [Serialize(1, IsPropertySaveable.No, description: "How many projectiles the weapon launches when fired once.")] public int ProjectileCount { @@ -602,9 +636,9 @@ namespace Barotrauma.Items.Components if (projectiles.Any()) { ItemContainer projectileContainer = projectiles.First().Item.Container?.GetComponent(); - if (projectileContainer != null && projectileContainer.Item != item) - { - projectileContainer?.Item.Use(deltaTime, null); + if (projectileContainer != null && projectileContainer.Item != item) + { + projectileContainer?.Item.Use(deltaTime, null); } } else @@ -764,6 +798,15 @@ namespace Barotrauma.Items.Components private void Launch(Item projectile, Character user = null, float? launchRotation = null, float tinkeringStrength = 0f) { reload = reloadTime; + if (ShotsPerBurst > 1) + { + shotCounter++; + if (shotCounter >= ShotsPerBurst) + { + reload += DelayBetweenBursts; + shotCounter = 0; + } + } reload /= 1f + (tinkeringStrength * TinkeringReloadDecrease); if (user != null) @@ -773,6 +816,10 @@ namespace Barotrauma.Items.Components if (projectile != null) { + if (AlternatingFiringOffset) + { + flipFiringOffset = !flipFiringOffset; + } activeProjectiles.Add(projectile); projectile.Drop(null, setTransform: false); if (projectile.body != null) @@ -796,9 +843,9 @@ namespace Barotrauma.Items.Components projectileComponent.Attacker = projectileComponent.User = user; if (projectileComponent.Attack != null) { - projectileComponent.Attack.DamageMultiplier = 1f + (TinkeringDamageIncrease * tinkeringStrength); + projectileComponent.Attack.DamageMultiplier = (1f * DamageMultiplier) + (TinkeringDamageIncrease * tinkeringStrength); } - projectileComponent.Use(); + projectileComponent.Use(null, LaunchImpulse); projectile.GetComponent()?.Attach(item, projectile); projectileComponent.User = user; @@ -1452,7 +1499,9 @@ namespace Barotrauma.Items.Components Vector2 transformedFiringOffset = Vector2.Zero; if (useOffset) { - transformedFiringOffset = MathUtils.RotatePoint(new Vector2(-FiringOffset.Y, -FiringOffset.X) * item.Scale, -rotation); + Vector2 currOffSet = FiringOffset; + if (flipFiringOffset) { currOffSet.X = -currOffSet.X; } + transformedFiringOffset = MathUtils.RotatePoint(new Vector2(-currOffSet.Y, -currOffSet.X) * item.Scale, -rotation); } return new Vector2(item.WorldRect.X + transformedBarrelPos.X + transformedFiringOffset.X, item.WorldRect.Y - transformedBarrelPos.Y + transformedFiringOffset.Y); } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Item.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Item.cs index 6137938e3..6411b4334 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Item.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Item.cs @@ -99,6 +99,7 @@ namespace Barotrauma private bool hasComponentsToDraw; public PhysicsBody body; + private float waterDragCoefficient; public readonly XElement StaticBodyConfig; @@ -860,12 +861,14 @@ namespace Barotrauma SetActiveSprite(); + ContentXElement bodyElement = null; foreach (var subElement in element.Elements()) { switch (subElement.Name.ToString().ToLowerInvariant()) { case "body": - float density = subElement.GetAttributeFloat("density", 10.0f); + bodyElement = subElement; + float density = subElement.GetAttributeFloat("density", Physics.NeutralDensity); float minDensity = subElement.GetAttributeFloat("mindensity", density); float maxDensity = subElement.GetAttributeFloat("maxdensity", density); if (minDensity < maxDensity) @@ -905,6 +908,7 @@ namespace Barotrauma body = new PhysicsBody(subElement, ConvertUnits.ToSimUnits(Position), Scale, density, collisionCategory, collidesWith, findNewContacts: false); body.FarseerBody.AngularDamping = subElement.GetAttributeFloat("angulardamping", 0.2f); body.FarseerBody.LinearDamping = subElement.GetAttributeFloat("lineardamping", 0.1f); + body.FarseerBody.LinearDamping = subElement.GetAttributeFloat("lineardamping", 0.1f); body.UserData = this; break; case "trigger": @@ -994,6 +998,8 @@ namespace Barotrauma if (body != null) { body.Submarine = submarine; + waterDragCoefficient = bodyElement.GetAttributeFloat("waterdragcoefficient", + GetComponent() != null || GetComponent() != null ? 0.1f : 1.0f); } //cache connections into a dictionary for faster lookups @@ -1898,10 +1904,19 @@ namespace Barotrauma if (needsWaterCheck) { + bool wasInWater = inWater; inWater = IsInWater(); bool waterProof = WaterProof; if (inWater) { + //the item has gone through the surface of the water + if (!wasInWater && CurrentHull != null && body != null && body.LinearVelocity.Y < -1.0f) + { + Splash(); + //slow the item down (not physically accurate, but looks good enough) + body.LinearVelocity *= 0.2f; + } + Item container = this.Container; while (!waterProof && container != null) { @@ -1929,7 +1944,8 @@ namespace Barotrauma } } - + partial void Splash(); + public void UpdateTransform() { if (body == null) { return; } @@ -2017,23 +2033,47 @@ namespace Barotrauma { float floor = CurrentHull.Rect.Y - CurrentHull.Rect.Height; float waterLevel = floor + CurrentHull.WaterVolume / CurrentHull.Rect.Width; - //forceFactor is 1.0f if the item is completely submerged, //and goes to 0.0f as the item goes through the surface forceFactor = Math.Min((waterLevel - Position.Y) / rect.Height, 1.0f); - if (forceFactor <= 0.0f) return; + if (forceFactor <= 0.0f) { return; } } + bool moving = body.LinearVelocity.LengthSquared() > 0.001f; float volume = body.Mass / body.Density; + if (moving) + { + //measure velocity from the velocity of the front of the item and apply the drag to the other end to get the drag to turn the item the "pointy end first" - var uplift = -GameMain.World.Gravity * forceFactor * volume; + //a more "proper" (but more expensive) way to do this would be to e.g. calculate the drag separately for each edge of the fixture + //but since we define the "front" as the "pointy end", we can cheat a bit by using that, and actually even make the drag appear more realistic in some cases + //(e.g. a bullet with a rectangular fixture would be just as "aerodynamic" travelling backwards, but with this method we get it to turn the correct way) + Vector2 localFront = body.GetLocalFront(); + Vector2 frontVel = body.FarseerBody.GetLinearVelocityFromLocalPoint(localFront); - Vector2 drag = body.LinearVelocity * volume; + float speed = frontVel.Length(); + float drag = speed * speed * waterDragCoefficient * volume * Physics.NeutralDensity; + //very small drag on active projectiles to prevent affecting their trajectories much + if (body.FarseerBody.IsBullet) { drag *= 0.1f; } + Vector2 dragVec = -frontVel / speed * drag; - body.ApplyForce((uplift - drag) * 10.0f); + //apply the force slightly towards the back of the item to make it turn the front first + Vector2 back = body.FarseerBody.GetWorldPoint(-localFront * 0.01f); + body.ApplyForce(dragVec, back); + } + + //no need to apply buoyancy if the item is still and not light enough to float + if (moving || body.Density < 10.0f) + { + Vector2 buoyancy = -GameMain.World.Gravity * forceFactor * volume * Physics.NeutralDensity; + body.ApplyForce(buoyancy); + } //apply simple angular drag - body.ApplyTorque(body.AngularVelocity * volume * -0.05f); + if (Math.Abs(body.AngularVelocity) > 0.0001f) + { + body.ApplyTorque(body.AngularVelocity * volume * -0.1f); + } } @@ -3270,7 +3310,7 @@ namespace Barotrauma relativeOrigin = MathUtils.RotatePoint(relativeOrigin, -item.RotationRad); Vector2 origin = new Vector2(rect.X + rect.Width / 2, rect.Y - rect.Height / 2) + relativeOrigin; - item.rect.Location -= ((origin - oldOrigin) * scaleRelativeToPrefab).ToPoint(); + item.rect.Location -= (origin - oldOrigin).ToPoint(); } if (item.PurchasedNewSwap && !string.IsNullOrEmpty(appliedSwap.SwappableItem?.SpawnWithId)) diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/ItemPrefab.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/ItemPrefab.cs index e97bb6481..203d2dbac 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/ItemPrefab.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/ItemPrefab.cs @@ -14,6 +14,8 @@ namespace Barotrauma readonly struct DeconstructItem { public readonly Identifier ItemIdentifier; + //number of items to output + public readonly int Amount; //minCondition does <= check, meaning that below or equal to min condition will be skipped. public readonly float MinCondition; //maxCondition does > check, meaning that above this max the deconstruct item will be skipped. @@ -37,6 +39,7 @@ namespace Barotrauma public DeconstructItem(XElement element, Identifier parentDebugName) { ItemIdentifier = element.GetAttributeIdentifier("identifier", ""); + Amount = element.GetAttributeInt("amount", 1); MinCondition = element.GetAttributeFloat("mincondition", -0.1f); MaxCondition = element.GetAttributeFloat("maxcondition", 1.0f); OutConditionMin = element.GetAttributeFloat("outconditionmin", element.GetAttributeFloat("outcondition", 1.0f)); @@ -70,6 +73,20 @@ namespace Barotrauma public readonly float MinCondition; public readonly float MaxCondition; public readonly bool UseCondition; + + public bool IsConditionSuitable(float conditionPercentage) + { + float normalizedCondition = conditionPercentage / 100.0f; + if (MathUtils.NearlyEqual(normalizedCondition, MinCondition) || MathUtils.NearlyEqual(normalizedCondition, MaxCondition)) + { + return true; + } + else if (normalizedCondition >= MinCondition && normalizedCondition <= MaxCondition) + { + return true; + } + return false; + } } public class RequiredItemByIdentifier : RequiredItem @@ -393,12 +410,106 @@ namespace Barotrauma private set; } + public readonly struct CommonnessInfo + { + public float Commonness + { + get + { + return commonness; + } + } + public float AbyssCommonness + { + get + { + return abyssCommonness ?? 0.0f; + } + } + public float CaveCommonness + { + get + { + return caveCommonness ?? Commonness; + } + } + public bool CanAppear + { + get + { + if (Commonness > 0.0f) { return true; } + if (AbyssCommonness > 0.0f) { return true; } + if (CaveCommonness > 0.0f) { return true; } + return false; + } + } + + public readonly float commonness; + public readonly float? abyssCommonness; + public readonly float? caveCommonness; + + public CommonnessInfo(XElement element) + { + this.commonness = Math.Max(element?.GetAttributeFloat("commonness", 0.0f) ?? 0.0f, 0.0f); + + float? abyssCommonness = null; + XAttribute abyssCommonnessAttribute = element?.GetAttribute("abysscommonness") ?? element?.GetAttribute("abyss"); + if (abyssCommonnessAttribute != null) + { + abyssCommonness = Math.Max(abyssCommonnessAttribute.GetAttributeFloat(0.0f), 0.0f); + } + this.abyssCommonness = abyssCommonness; + + float? caveCommonness = null; + XAttribute caveCommonnessAttribute = element?.GetAttribute("cavecommonness") ?? element?.GetAttribute("cave"); + if (caveCommonnessAttribute != null) + { + caveCommonness = Math.Max(caveCommonnessAttribute.GetAttributeFloat(0.0f), 0.0f); + } + this.caveCommonness = caveCommonness; + } + + public CommonnessInfo(float commonness, float? abyssCommonness, float? caveCommonness) + { + this.commonness = commonness; + this.abyssCommonness = abyssCommonness != null ? (float?)Math.Max(abyssCommonness.Value, 0.0f) : null; + this.caveCommonness = caveCommonness != null ? (float?)Math.Max(caveCommonness.Value, 0.0f) : null; + } + + public CommonnessInfo WithInheritedCommonness(CommonnessInfo? parentInfo) + { + return new CommonnessInfo(commonness, + abyssCommonness ?? parentInfo?.abyssCommonness, + caveCommonness ?? parentInfo?.caveCommonness); + } + + public CommonnessInfo WithInheritedCommonness(params CommonnessInfo?[] parentInfos) + { + CommonnessInfo info = this; + foreach (var parentInfo in parentInfos) + { + info = info.WithInheritedCommonness(parentInfo); + } + return info; + } + + public float GetCommonness(Level.TunnelType tunnelType) + { + if (tunnelType == Level.TunnelType.Cave) + { + return CaveCommonness; + } + else + { + return Commonness; + } + } + } + /// /// How likely it is for the item to spawn in a level of a given type. - /// Key = name of the LevelGenerationParameters (empty string = default value) /* TODO: empty string = default value???? */ - /// Value = commonness /// - public ImmutableDictionary LevelCommonness { get; private set; } + private ImmutableDictionary LevelCommonness { get; set; } public readonly struct FixedQuantityResourceInfo { @@ -747,7 +858,7 @@ namespace Barotrauma AllowDroppingOnSwapWith = allowDroppingOnSwapWith.ToImmutableHashSet(); AllowDroppingOnSwap = allowDroppingOnSwapWith.Any(); - var levelCommonness = new Dictionary(); + var levelCommonness = new Dictionary(); var levelQuantity = new Dictionary(); foreach (ContentXElement subElement in ConfigElement.Elements()) @@ -871,7 +982,7 @@ namespace Barotrauma { if (!levelCommonness.ContainsKey(levelName)) { - levelCommonness.Add(levelName, levelCommonnessElement.GetAttributeFloat("commonness", 0.0f)); + levelCommonness.Add(levelName, new CommonnessInfo(levelCommonnessElement)); } } else @@ -962,6 +1073,40 @@ namespace Barotrauma this.allowedLinks = ConfigElement.GetAttributeIdentifierArray("allowedlinks", Array.Empty()).ToImmutableHashSet(); } + public CommonnessInfo? GetCommonnessInfo(Level level) + { + CommonnessInfo? levelCommonnessInfo = GetValueOrNull(level.GenerationParams.Identifier); + CommonnessInfo? biomeCommonnessInfo = GetValueOrNull(level.LevelData.Biome.Identifier); + CommonnessInfo? defaultCommonnessInfo = GetValueOrNull(Identifier.Empty); + + if (levelCommonnessInfo.HasValue) + { + return levelCommonnessInfo?.WithInheritedCommonness(biomeCommonnessInfo, defaultCommonnessInfo); + } + else if (biomeCommonnessInfo.HasValue) + { + return biomeCommonnessInfo?.WithInheritedCommonness(defaultCommonnessInfo); + } + else if (defaultCommonnessInfo.HasValue) + { + return defaultCommonnessInfo; + } + + return null; + + CommonnessInfo? GetValueOrNull(Identifier identifier) + { + if (LevelCommonness.TryGetValue(identifier, out CommonnessInfo info)) + { + return info; + } + else + { + return null; + } + } + } + public float GetTreatmentSuitability(Identifier treatmentIdentifier) { return treatmentSuitability.TryGetValue(treatmentIdentifier, out float suitability) ? suitability : 0.0f; diff --git a/Barotrauma/BarotraumaShared/SharedSource/Map/Explosion.cs b/Barotrauma/BarotraumaShared/SharedSource/Map/Explosion.cs index 8ab8ee918..329102f51 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Map/Explosion.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Map/Explosion.cs @@ -33,8 +33,6 @@ namespace Barotrauma private readonly float? flashRange; private readonly string decal; private readonly float decalSize; - // used to apply friendly afflictions in an area without effects displaying - private readonly bool abilityExplosion; private readonly bool applyToSelf; private readonly float itemRepairStrength; @@ -70,6 +68,7 @@ namespace Barotrauma applyToSelf = element.GetAttributeBool("applytoself", true); + //the "abilityexplosion" field is kept for backwards compatibility (basically the opposite of "showeffects") bool showEffects = !element.GetAttributeBool("abilityexplosion", false) && element.GetAttributeBool("showeffects", true); sparks = element.GetAttributeBool("sparks", showEffects); shockwave = element.GetAttributeBool("shockwave", showEffects); @@ -131,8 +130,15 @@ namespace Barotrauma float displayRange = Attack.Range; if (damageSource is Item sourceItem) { - displayRange *= 1.0f + sourceItem.GetQualityModifier(Quality.StatType.ExplosionRadius); - Attack.DamageMultiplier *= 1.0f + sourceItem.GetQualityModifier(Quality.StatType.ExplosionDamage); + var launcher = sourceItem.GetComponent()?.Launcher; + displayRange *= + 1.0f + + sourceItem.GetQualityModifier(Quality.StatType.ExplosionRadius) + + (launcher?.GetQualityModifier(Quality.StatType.ExplosionRadius) ?? 0); + Attack.DamageMultiplier *= + 1.0f + + sourceItem.GetQualityModifier(Quality.StatType.ExplosionDamage) + + (launcher?.GetQualityModifier(Quality.StatType.ExplosionDamage) ?? 0); Attack.SourceItem ??= sourceItem; } @@ -203,7 +209,7 @@ namespace Barotrauma } } - if (MathUtils.NearlyEqual(force, 0.0f) && MathUtils.NearlyEqual(Attack.Stun, 0.0f) && MathUtils.NearlyEqual(Attack.GetTotalDamage(false), 0.0f) && !abilityExplosion) + if (MathUtils.NearlyEqual(force, 0.0f) && MathUtils.NearlyEqual(Attack.Stun, 0.0f) && Attack.Afflictions.None()) { return; } @@ -293,12 +299,13 @@ namespace Barotrauma Dictionary distFactors = new Dictionary(); Dictionary damages = new Dictionary(); List modifiedAfflictions = new List(); + foreach (Limb limb in c.AnimController.Limbs) { if (limb.IsSevered || limb.IgnoreCollisions || !limb.body.Enabled) { continue; } float dist = Vector2.Distance(limb.WorldPosition, worldPosition); - + //calculate distance from the "outer surface" of the physics body //doesn't take the rotation of the limb into account, but should be accurate enough for this purpose float limbRadius = limb.body.GetMaxExtent(); @@ -313,17 +320,27 @@ namespace Barotrauma { distFactor *= GetObstacleDamageMultiplier(explosionPos, worldPosition, limb.SimPosition); } - distFactors.Add(limb, distFactor); + if (distFactor > 0) + { + distFactors.Add(limb, distFactor); + } + } + foreach (Limb limb in distFactors.Keys) + { + if (!distFactors.TryGetValue(limb, out float distFactor)) { continue; } modifiedAfflictions.Clear(); foreach (Affliction affliction in attack.Afflictions.Keys) { - //previously the damage would be divided by the number of limbs (the intention was to prevent characters with more limbs taking more damage from explosions) - //that didn't work well on large characters like molochs and endworms: the explosions tend to only damage one or two of their limbs, and since the characters - //have lots of limbs, they tended to only take a fraction of the damage they should - - //now we just divide by 10, which keeps the damage to normal-sized characters roughly the same as before and fixes the large characters - modifiedAfflictions.Add(affliction.CreateMultiplied(distFactor / 10)); + // Shouldn't go above 15, or the damage can be unexpectedly low -> doesn't break armor + // Effectively this makes large explosions more effective against large creatures (because more limbs are affected), but I don't think that's necessarily a bad thing. + float limbCountFactor = Math.Min(distFactors.Count, 15); + float dmgMultiplier = distFactor; + if (affliction.DivideByLimbCount) + { + dmgMultiplier /= limbCountFactor; + } + modifiedAfflictions.Add(affliction.CreateMultiplied(dmgMultiplier, affliction.Probability)); } c.LastDamageSource = damageSource; if (attacker == null) @@ -368,7 +385,7 @@ namespace Barotrauma Vector2 limbDiff = Vector2.Normalize(limb.WorldPosition - worldPosition); if (!MathUtils.IsValid(limbDiff)) { limbDiff = Rand.Vector(1.0f); } Vector2 impulse = limbDiff * distFactor * force; - Vector2 impulsePoint = limb.SimPosition - limbDiff * limbRadius; + Vector2 impulsePoint = limb.SimPosition - limbDiff * limb.body.GetMaxExtent(); limb.body.ApplyLinearImpulse(impulse, impulsePoint, maxVelocity: NetConfig.MaxPhysicsBodyVelocity * 0.2f); } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Map/Levels/Biome.cs b/Barotrauma/BarotraumaShared/SharedSource/Map/Levels/Biome.cs index 298638c46..ee915e10e 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Map/Levels/Biome.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Map/Levels/Biome.cs @@ -12,7 +12,9 @@ namespace Barotrauma public readonly bool IsEndBiome; public readonly float MinDifficulty; - public readonly float MaxDifficulty; + private readonly float maxDifficulty; + public float ActualMaxDifficulty => maxDifficulty; + public float AdjustedMaxDifficulty => maxDifficulty - 0.1f; public readonly ImmutableHashSet AllowedZones; @@ -31,7 +33,7 @@ namespace Barotrauma IsEndBiome = element.GetAttributeBool("endbiome", false); AllowedZones = element.GetAttributeIntArray("AllowedZones", new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }).ToImmutableHashSet(); MinDifficulty = element.GetAttributeFloat("MinDifficulty", 0); - MaxDifficulty = element.GetAttributeFloat("MaxDifficulty", 100); + maxDifficulty = element.GetAttributeFloat("MaxDifficulty", 100); } public static Identifier ParseIdentifier(ContentXElement element) diff --git a/Barotrauma/BarotraumaShared/SharedSource/Map/Levels/CaveGenerationParams.cs b/Barotrauma/BarotraumaShared/SharedSource/Map/Levels/CaveGenerationParams.cs index b71326832..c80309932 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Map/Levels/CaveGenerationParams.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Map/Levels/CaveGenerationParams.cs @@ -79,7 +79,7 @@ namespace Barotrauma set { maxBranchCount = Math.Max(value, minBranchCount); } } - [Serialize(50, IsPropertySaveable.Yes), Editable(MinValueInt = 0, MaxValueInt = 1000)] + [Serialize(50, IsPropertySaveable.Yes), Editable(MinValueInt = 0, MaxValueInt = 10000)] public int LevelObjectAmount { get; diff --git a/Barotrauma/BarotraumaShared/SharedSource/Map/Levels/Level.cs b/Barotrauma/BarotraumaShared/SharedSource/Map/Levels/Level.cs index a6f3e2038..6bb343533 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Map/Levels/Level.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Map/Levels/Level.cs @@ -8,6 +8,7 @@ using Microsoft.Xna.Framework; using System; using System.Collections.Generic; using System.Diagnostics; +using System.Globalization; using System.Linq; using Voronoi2; @@ -24,6 +25,22 @@ namespace Barotrauma //all entities are disabled after they reach this depth public const int MaxEntityDepth = -1000000; public const float ShaftHeight = 1000.0f; + + /// + /// How far outside the boundaries of the level the water current that pushes subs towards the level starts + /// + public const float OutsideBoundsCurrentMargin = 30000.0f; + + /// + /// How far outside the boundaries of the level the strength of the current starts to increase exponentially + /// + public const float OutsideBoundsCurrentMarginExponential = 150000.0f; + + /// + /// How far outside the boundaries of the level the current stops submarines entirely + /// + public const float OutsideBoundsCurrentHardLimit = 200000.0f; + /// /// The level generator won't try to adjust the width of the main path above this limit. /// @@ -2437,16 +2454,27 @@ namespace Barotrauma public List ClusterLocations { get; } public TunnelType TunnelType { get; } - public PathPoint(string id, Vector2 position, bool shouldContainResources, TunnelType tunnelType) + private PathPoint(string id, Vector2 position, bool shouldContainResources, TunnelType tunnelType, List resourceTags, List resourceIds, List clusterLocations) { - Id = id; + Id = id; Position = position; ShouldContainResources = shouldContainResources; - ResourceTags = new List(); - ResourceIds = new List(); - ClusterLocations = new List(); + ResourceTags = resourceTags; + ResourceIds = resourceIds; + ClusterLocations = clusterLocations; TunnelType = tunnelType; } + + public PathPoint(string id, Vector2 position, bool shouldContainResources, TunnelType tunnelType) + : this(id, position, shouldContainResources, tunnelType, new List(), new List(), new List()) + { + + } + + public PathPoint WithResources(bool containsResources) + { + return new PathPoint(Id, Position, containsResources, TunnelType, ResourceTags, ResourceIds, ClusterLocations); + } } public List AbyssResources { get; } = new List(); @@ -2485,22 +2513,26 @@ namespace Barotrauma // Such as the exploding crystals in The Great Sea private void GenerateItems() { - Identifier levelName = GenerationParams.Identifier; - float minCommonness = float.MaxValue, maxCommonness = float.MinValue; - List<(ItemPrefab itemPrefab, float commonness)> levelResources = new List<(ItemPrefab itemPrefab, float commonness)>(); + var levelResources = new List<(ItemPrefab itemPrefab, ItemPrefab.CommonnessInfo commonnessInfo)>(); var fixedResources = new List<(ItemPrefab itemPrefab, ItemPrefab.FixedQuantityResourceInfo resourceInfo)>(); + Vector2 commonnessRange = new Vector2(float.MaxValue, float.MinValue), caveCommonnessRange = new Vector2(float.MaxValue, float.MinValue); foreach (ItemPrefab itemPrefab in ItemPrefab.Prefabs.OrderBy(p => p.UintIdentifier)) { - if (itemPrefab.LevelCommonness.TryGetValue(levelName, out float commonness) || - itemPrefab.LevelCommonness.TryGetValue(LevelData.Biome.Identifier, out commonness) || - itemPrefab.LevelCommonness.TryGetValue(Identifier.Empty, out commonness)) + if (itemPrefab.GetCommonnessInfo(this) is { CanAppear: true } commonnessInfo) { - if (commonness <= 0.0f) { continue; } - if (commonness < minCommonness) { minCommonness = commonness; } - if (commonness > maxCommonness) { maxCommonness = commonness; } - levelResources.Add((itemPrefab, commonness)); + if (commonnessInfo.Commonness > 0.0) + { + if (commonnessInfo.Commonness < commonnessRange.X) { commonnessRange.X = commonnessInfo.Commonness; } + if (commonnessInfo.Commonness > commonnessRange.Y) { commonnessRange.Y = commonnessInfo.Commonness; } + } + if (commonnessInfo.CaveCommonness > 0.0) + { + if (commonnessInfo.CaveCommonness < caveCommonnessRange.X) { caveCommonnessRange.X = commonnessInfo.CaveCommonness; } + if (commonnessInfo.CaveCommonness > caveCommonnessRange.Y) { caveCommonnessRange.Y = commonnessInfo.CaveCommonness; } + } + levelResources.Add((itemPrefab, commonnessInfo)); } - else if (itemPrefab.LevelQuantity.TryGetValue(levelName, out var fixedQuantityResourceInfo) || + else if (itemPrefab.LevelQuantity.TryGetValue(GenerationParams.Identifier, out var fixedQuantityResourceInfo) || itemPrefab.LevelQuantity.TryGetValue(Identifier.Empty, out fixedQuantityResourceInfo)) { fixedResources.Add((itemPrefab, fixedQuantityResourceInfo)); @@ -2533,18 +2565,18 @@ namespace Barotrauma } } - //place some of the least common resources in the abyss + // Abyss Resources AbyssResources.Clear(); - int abyssClusterCount = (int)MathHelper.Lerp(GenerationParams.AbyssResourceClustersMin, GenerationParams.AbyssResourceClustersMax, Difficulty / 100.0f); - + var abyssResourcePrefabs = levelResources.Where(r => r.commonnessInfo.AbyssCommonness > 0.0f); + int abyssClusterCount = (int)MathHelper.Lerp(GenerationParams.AbyssResourceClustersMin, GenerationParams.AbyssResourceClustersMax, MathUtils.InverseLerp(LevelData.Biome.MinDifficulty, LevelData.Biome.AdjustedMaxDifficulty, Difficulty)); for (int i = 0; i < abyssClusterCount; i++) { - //use inverse commonness to select the abyss resources (the rarest ones are the most common in the abyss) var selectedPrefab = ToolBox.SelectWeightedRandom( - levelResources.Select(it => it.itemPrefab).ToList(), - levelResources.Select(it => it.commonness <= 0.0f ? 0.0f : 1.0f / it.commonness).ToList(), + abyssResourcePrefabs.Select(r => r.itemPrefab).ToList(), + abyssResourcePrefabs.Select(r => r.commonnessInfo.AbyssCommonness).ToList(), Rand.RandSync.ServerAndClient); + var location = allValidLocations.GetRandom(l => { if (l.Cell == null || l.Edge == null) { return false; } @@ -2554,14 +2586,16 @@ namespace Barotrauma }, randSync: Rand.RandSync.ServerAndClient); if (location.Cell == null || location.Edge == null) { break; } + int clusterSize = Rand.Range(GenerationParams.ResourceClusterSizeRange.X, GenerationParams.ResourceClusterSizeRange.Y + 1, Rand.RandSync.ServerAndClient); - PlaceResources(selectedPrefab, clusterSize, location, out var abyssResources); + PlaceResources(selectedPrefab, clusterSize, location, out var placedResources, maxResourceOverlap: 0); var abyssClusterLocation = new ClusterLocation(location.Cell, location.Edge, initializeResourceList: true); - abyssClusterLocation.Resources.AddRange(abyssResources); + abyssClusterLocation.Resources.AddRange(placedResources); AbyssResources.Add(abyssClusterLocation); + var locationIndex = allValidLocations.FindIndex(l => l.Equals(location)); allValidLocations.RemoveAt(locationIndex); - } + } PathPoints.Clear(); nextPathPointId = 0; @@ -2618,17 +2652,25 @@ namespace Barotrauma int itemCount = 0; Identifier[] exclusiveResourceTags = new Identifier[2] { "ore".ToIdentifier(), "plant".ToIdentifier() }; + var disabledPathPoints = new List(); // Create first cluster for each spawn point - foreach (var pathPoint in PathPoints.Where(p => p.ShouldContainResources)) + foreach (var pathPoint in PathPoints) { if (itemCount >= GenerationParams.ItemCount) { break; } + if (!pathPoint.ShouldContainResources) { continue; } GenerateFirstCluster(pathPoint); + if (pathPoint.ClusterLocations.Count > 0) { continue; } + disabledPathPoints.Add(pathPoint.Id); + } + // Don't try to spawn more resource clusters for points for which the initial cluster could not be spawned + foreach (string pathPointId in disabledPathPoints) + { + if (PathPoints.FirstOrNull(p => p.Id == pathPointId) is PathPoint pathPoint) + { + PathPoints.RemoveAll(p => p.Id == pathPointId); + PathPoints.Add(pathPoint.WithResources(false)); + } } - - // Don't try to spawn more resource clusters for points - // for which the initial cluster could not be spawned - PathPoints.Where(p => p.ShouldContainResources && p.ClusterLocations.Count == 0) - .ForEach(p => p.ShouldContainResources = false); var excludedPathPointIds = new List(); while (itemCount < GenerationParams.ItemCount) @@ -2647,35 +2689,16 @@ namespace Barotrauma GenerateAdditionalCluster(pathPoint); } - // If none of the point set to contain resources can take more resources, - // but we still haven't reached the item count set in the generation parameters... - while (itemCount < GenerationParams.ItemCount) - { - // We need to start filling some of the path points previously set to not contain resources - Func availablePathPoints = p => !excludedPathPointIds.Contains(p.Id) && p.ClusterLocations.None(); - if (PathPoints.None(availablePathPoints)) { break; } - var pathPoint = PathPoints.GetRandom(availablePathPoints, randSync: Rand.RandSync.ServerAndClient); - if (!GenerateFirstCluster(pathPoint)) - { - excludedPathPointIds.Add(pathPoint.Id); - continue; - } - while (pathPoint.NextClusterProbability > 0) - { - if (!GenerateAdditionalCluster(pathPoint)) { break; } - } - pathPoint.ShouldContainResources = pathPoint.ClusterLocations.Any(); - } - #if DEBUG - DebugConsole.NewMessage("Level resources spawned: " + itemCount + "\n" + - " Spawn points containing resources: " + PathPoints.Where(p => p.ClusterLocations.Any()).Count() + "/" + PathPoints.Count + "\n" + - " Total value: " + PathPoints.Sum(p => p.ClusterLocations.Sum(c => c.Resources.Sum(r => r.Prefab.DefaultPrice?.Price ?? 0))) + " mk"); + int spawnPointsContainingResources = PathPoints.Where(p => p.ClusterLocations.Any()).Count(); + string percentage = string.Format(CultureInfo.InvariantCulture, "{0:P2}", (float)spawnPointsContainingResources / PathPoints.Count); + DebugConsole.NewMessage($"Level resources spawned: {itemCount}\n" + + $" Spawn points containing resources: {spawnPointsContainingResources} ({percentage})\n" + + $" Total value: {PathPoints.Sum(p => p.ClusterLocations.Sum(c => c.Resources.Sum(r => r.Prefab.DefaultPrice?.Price ?? 0)))} mk"); if (AbyssResources.Count > 0) { - - DebugConsole.NewMessage("Abyss resources spawned: " + AbyssResources.Sum(a => a.Resources.Count) + "\n" + - " Total value: " + AbyssResources.Sum(c => c.Resources.Sum(r => r.Prefab.DefaultPrice?.Price ?? 0)) + " mk"); + DebugConsole.NewMessage($"Abyss resources spawned: {AbyssResources.Sum(a => a.Resources.Count)}\n" + + $" Total value: {AbyssResources.Sum(c => c.Resources.Sum(r => r.Prefab.DefaultPrice?.Price ?? 0))} mk"); } #endif @@ -2842,7 +2865,7 @@ namespace Barotrauma { selectedPrefab = ToolBox.SelectWeightedRandom( levelResources.Select(it => it.itemPrefab).ToList(), - levelResources.Select(it => it.commonness).ToList(), + levelResources.Select(it => it.commonnessInfo.GetCommonness(pathPoint.TunnelType)).ToList(), Rand.RandSync.ServerAndClient); selectedPrefab.Tags.ForEach(t => { @@ -2854,20 +2877,21 @@ namespace Barotrauma } else { - var filteredResources = levelResources.Where(it => - !pathPoint.ResourceIds.Contains(it.itemPrefab.Identifier) && - pathPoint.ResourceTags.Any() && it.itemPrefab.Tags.Any(t => pathPoint.ResourceTags.Contains(t))); - selectedPrefab = ToolBox.SelectWeightedRandom( + var filteredResources = pathPoint.ResourceTags.None() ? levelResources : + levelResources.Where(it => it.itemPrefab.Tags.Any(t => pathPoint.ResourceTags.Contains(t))); + selectedPrefab = ToolBox.SelectWeightedRandom( filteredResources.Select(it => it.itemPrefab).ToList(), - filteredResources.Select(it => it.commonness).ToList(), + filteredResources.Select(it => it.commonnessInfo.GetCommonness(pathPoint.TunnelType)).ToList(), Rand.RandSync.ServerAndClient); } if (selectedPrefab == null) { return false; } // Create resources for the cluster - var commonness = levelResources.First(r => r.itemPrefab == selectedPrefab).commonness; - var lerpAmount = MathUtils.InverseLerp(minCommonness, maxCommonness, commonness); + float commonness = levelResources.First(r => r.itemPrefab == selectedPrefab).commonnessInfo.GetCommonness(pathPoint.TunnelType); + float lerpAmount = pathPoint.TunnelType != TunnelType.Cave ? + MathUtils.InverseLerp(commonnessRange.X, commonnessRange.Y, commonness) : + MathUtils.InverseLerp(caveCommonnessRange.X, caveCommonnessRange.Y, commonness); var maxClusterSize = (int)MathHelper.Lerp(GenerationParams.ResourceClusterSizeRange.X, GenerationParams.ResourceClusterSizeRange.Y, lerpAmount); var maxFitOnEdge = GetMaxResourcesOnEdge(selectedPrefab, location, out var edgeLength); maxClusterSize = Math.Min(maxClusterSize, maxFitOnEdge); @@ -2898,6 +2922,7 @@ namespace Barotrauma edgeLength = 0.0f; if (location.Cell == null || location.Edge == null) { return 0; } edgeLength = Vector2.Distance(location.Edge.Point1, location.Edge.Point2); + if (resourcePrefab == null) { return 0; } return (int)Math.Floor(edgeLength / ((1.0f - maxResourceOverlap) * resourcePrefab.Size.X)); } } @@ -3041,15 +3066,19 @@ namespace Barotrauma { edgeLength ??= Vector2.Distance(location.Edge.Point1, location.Edge.Point2); Vector2 edgeDir = (location.Edge.Point2 - location.Edge.Point1) / edgeLength.Value; + if (!MathUtils.IsValid(edgeDir)) + { + edgeDir = Vector2.Zero; + } var minResourceOverlap = -((edgeLength.Value - (resourceCount * resourcePrefab.Size.X)) / (resourceCount * resourcePrefab.Size.X)); - minResourceOverlap = Math.Max(minResourceOverlap, 0.0f); + minResourceOverlap = Math.Clamp(minResourceOverlap, 0, maxResourceOverlap); var lerpAmounts = new float[resourceCount]; lerpAmounts[0] = 0.0f; var lerpAmount = 0.0f; for (int i = 1; i < resourceCount; i++) { var overlap = Rand.Range(minResourceOverlap, maxResourceOverlap, sync: Rand.RandSync.ServerAndClient); - lerpAmount += ((1.0f - overlap) * resourcePrefab.Size.X) / edgeLength.Value; + lerpAmount += (1.0f - overlap) * resourcePrefab.Size.X / edgeLength.Value; lerpAmounts[i] = Math.Clamp(lerpAmount, 0.0f, 1.0f); } var startOffset = Rand.Range(0.0f, 1.0f - lerpAmount, sync: Rand.RandSync.ServerAndClient); diff --git a/Barotrauma/BarotraumaShared/SharedSource/Map/Levels/LevelGenerationParams.cs b/Barotrauma/BarotraumaShared/SharedSource/Map/Levels/LevelGenerationParams.cs index 3742ade58..498702fa1 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Map/Levels/LevelGenerationParams.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Map/Levels/LevelGenerationParams.cs @@ -323,7 +323,7 @@ namespace Barotrauma set { caveCount = MathHelper.Clamp(value, 0, 100); } } - [Serialize(100, IsPropertySaveable.Yes), Editable(MinValueInt = 0, MaxValueInt = 10000)] + [Serialize(100, IsPropertySaveable.Yes, description: "The maximum number of level resources in the level."), Editable(MinValueInt = 0, MaxValueInt = 10000)] public int ItemCount { get; @@ -344,7 +344,7 @@ namespace Barotrauma set; } - [Serialize("2,8", IsPropertySaveable.Yes, description: "The minimum and maximum amount of resources in a single cluster. " + + [Serialize("3,6", IsPropertySaveable.Yes, description: "The minimum and maximum amount of resources in a single cluster. " + "In addition to this, resource commonness affects the cluster size. Less common resources spawn in smaller clusters."), Editable(1, 20)] public Point ResourceClusterSizeRange { diff --git a/Barotrauma/BarotraumaShared/SharedSource/Map/Map/Map.cs b/Barotrauma/BarotraumaShared/SharedSource/Map/Map/Map.cs index a1086d71c..925f45e66 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Map/Map/Map.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Map/Map/Map.cs @@ -149,7 +149,7 @@ namespace Barotrauma Biome.Prefabs.FirstOrDefault(b => b.Identifier == biomeId) ?? Biome.Prefabs.FirstOrDefault(b => !b.OldIdentifier.IsEmpty && b.OldIdentifier == biomeId) ?? Biome.Prefabs.First(); - connection.Difficulty = MathHelper.Clamp(connection.Difficulty, connection.Biome.MinDifficulty, connection.Biome.MaxDifficulty); + connection.Difficulty = MathHelper.Clamp(connection.Difficulty, connection.Biome.MinDifficulty, connection.Biome.AdjustedMaxDifficulty); connection.LevelData = new LevelData(subElement.Element("Level"), connection.Difficulty); Connections.Add(connection); connectionElements.Add(subElement); @@ -562,7 +562,7 @@ namespace Barotrauma { if (connection.Locations.Any(l => l.IsGateBetweenBiomes)) { - connection.Difficulty = connection.Locations.Min(l => l.Biome.MaxDifficulty); + connection.Difficulty = Math.Min(connection.Locations.Min(l => l.Biome.ActualMaxDifficulty), connection.Biome.AdjustedMaxDifficulty); } else { @@ -591,7 +591,7 @@ namespace Barotrauma if (biome != null) { minDifficulty = biome.MinDifficulty; - maxDifficulty = biome.MaxDifficulty; + maxDifficulty = biome.AdjustedMaxDifficulty; float diff = 1 - settingsFactor; difficulty *= 1 - (1f / biome.AllowedZones.Max() * diff); } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Map/SubmarineBody.cs b/Barotrauma/BarotraumaShared/SharedSource/Map/SubmarineBody.cs index ab8ea3922..f201efb47 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Map/SubmarineBody.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Map/SubmarineBody.cs @@ -343,14 +343,12 @@ namespace Barotrauma Math.Max(Body.LinearVelocity.Y, ConvertUnits.ToSimUnits(Level.Loaded.BottomPos - (worldBorders.Y - worldBorders.Height)))); } - //hard limit for how far outside the level the sub can go - float maxDist = 200000.0f; - //the force of the current starts to increase exponentially after this point - float exponentialForceIncreaseDist = 150000.0f; - float distance = Position.X < 0 ? Math.Abs(Position.X) : Position.X - Level.Loaded.Size.X; + float distance = Position.X < -Level.OutsideBoundsCurrentMargin ? + Math.Abs(Position.X + Level.OutsideBoundsCurrentMargin) : + Position.X - (Level.Loaded.Size.X + Level.OutsideBoundsCurrentMargin); if (distance > 0) { - if (distance > maxDist) + if (distance > Level.OutsideBoundsCurrentHardLimit) { if (Position.X < 0) { @@ -361,9 +359,9 @@ namespace Barotrauma Body.LinearVelocity = new Vector2(Math.Min(0, Body.LinearVelocity.X), Body.LinearVelocity.Y); } } - if (distance > exponentialForceIncreaseDist) + if (distance > Level.OutsideBoundsCurrentMarginExponential) { - distance += (float)Math.Pow((distance - exponentialForceIncreaseDist) * 0.01f, 2.0f); + distance += (float)Math.Pow((distance - Level.OutsideBoundsCurrentMarginExponential) * 0.01f, 2.0f); } float force = distance * 0.5f; totalForce += (Position.X < 0 ? Vector2.UnitX : -Vector2.UnitX) * force; diff --git a/Barotrauma/BarotraumaShared/SharedSource/NetStructBitField.cs b/Barotrauma/BarotraumaShared/SharedSource/NetStructBitField.cs new file mode 100644 index 000000000..964a4a9ca --- /dev/null +++ b/Barotrauma/BarotraumaShared/SharedSource/NetStructBitField.cs @@ -0,0 +1,168 @@ +#nullable enable + +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using Barotrauma.Networking; +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 + { + private const int AmountOfBoolsInByte = 7; // Reserve last bit for end marker + private readonly List Buffer = new List(); + private int index; + private bool disposed; + + public void WriteBoolean(bool b) + { + ThrowIfDisposed(); + + int arrayIndex = (int)Math.Floor(index / (float)AmountOfBoolsInByte); + if (arrayIndex >= Buffer.Count) { Buffer.Add(0); } + + int bitIndex = index % AmountOfBoolsInByte; + Buffer[arrayIndex] |= (byte)(b ? 1u << bitIndex : 0); + index++; + } + + public void WriteInteger(int value, int min, int max) + { + ThrowIfDisposed(); + + uint range = (uint)(max - min); + int numberOfBits = NetUtility.BitsToHoldUInt(range); + + uint writeValue = (uint)(value - min); + + for (int i = 0; i < numberOfBits; i++) + { + WriteBoolean((writeValue & (1u << i)) != 0); + } + } + + public void WriteFloat(float value, float min, float max, int numberOfBits) + { + ThrowIfDisposed(); + + float range = max - min; + float unit = (value - min) / range; + uint maxVal = (1u << numberOfBits) - 1; + + uint writeValue = (uint)(maxVal * unit); + for (int i = 0; i < numberOfBits; i++) + { + WriteBoolean((writeValue & (1u << i)) != 0); + } + } + + public void WriteToMessage(IWriteMessage msg) + { + ThrowIfDisposed(); + + if (Buffer.Count == 0) { Buffer.Add(0); } + + Buffer[^1] |= 1 << AmountOfBoolsInByte; // mark the last byte so we know when to stop reading + + foreach (byte b in Buffer) + { + msg.Write(b); + } + + Dispose(); + } + + public void Dispose() + { + disposed = true; + } + + private void ThrowIfDisposed() + { + if (disposed) { throw new ObjectDisposedException(nameof(WriteOnlyBitField)); } + } + } + + sealed class ReadOnlyBitField : IReadableBitField + { + private const int AmountOfBoolsInByte = 7; // Reserve last bit for end marker + private readonly ImmutableArray buffer; + private int index; + + public ReadOnlyBitField(IReadMessage inc) + { + List bytes = new List(); + byte currentByte; + int reads = 0; + do + { + 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)); + + buffer = bytes.ToImmutableArray(); + } + + public bool ReadBoolean() + { + int arrayIndex = (int)MathF.Floor(index / (float)AmountOfBoolsInByte); + int bitIndex = index % AmountOfBoolsInByte; + index++; + return IsBitSet(buffer[arrayIndex], bitIndex); + } + + public int ReadInteger(int min, int max) + { + uint range = (uint)(max - min); + int numberOfBits = NetUtility.BitsToHoldUInt(range); + + uint value = 0; + for (int i = 0; i < numberOfBits; i++) + { + value |= ReadBoolean() ? 1u << i : 0u; + } + + return (int)(min + value); + } + + public float ReadFloat(float min, float max, int numberOfBits) + { + int maxInt = (1 << numberOfBits) - 1; + + uint value = 0; + for (int i = 0; i < numberOfBits; i++) + { + value |= ReadBoolean() ? 1u << i : 0u; + } + + float range = max - min; + return min + range * value / maxInt; + } + + private static bool IsBitSet(byte b, int bitIndex) => (b & (1u << bitIndex)) != 0; + } +} \ No newline at end of file diff --git a/Barotrauma/BarotraumaShared/SharedSource/Networking/BanList.cs b/Barotrauma/BarotraumaShared/SharedSource/Networking/BanList.cs index 4bc42b15c..12564a692 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Networking/BanList.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Networking/BanList.cs @@ -1,37 +1,34 @@ -using Barotrauma.Steam; -using System; +using System; using System.Collections.Generic; using System.Linq; namespace Barotrauma.Networking { + #warning TODO: turn this into INetSerializableStruct partial class BannedPlayer { - public string Name; - public string EndPoint; public bool IsRangeBan; - public UInt64 SteamID; - public string Reason; - public DateTime? ExpirationTime; - public UInt16 UniqueIdentifier; + public readonly string Name; + public readonly Either AddressOrAccountId; - private void ParseEndPointAsSteamId() - { - ulong endPointAsSteamId = SteamManager.SteamIDStringToUInt64(EndPoint); - if (endPointAsSteamId != 0 && SteamID == 0) { SteamID = endPointAsSteamId; } - } + public readonly string Reason; + public DateTime? ExpirationTime; + public readonly UInt32 UniqueIdentifier; } partial class BanList { private readonly List bannedPlayers; + + public IReadOnlyList BannedPlayers => bannedPlayers; + public IEnumerable BannedNames { get { return bannedPlayers.Select(bp => bp.Name); } } - public IEnumerable BannedEndPoints + public IEnumerable> BannedAddresses { - get { return bannedPlayers.Select(bp => bp.EndPoint).Where(endPoint => !string.IsNullOrEmpty(endPoint)); } + get { return bannedPlayers.Select(bp => bp.AddressOrAccountId); } } partial void InitProjectSpecific(); @@ -42,19 +39,5 @@ namespace Barotrauma.Networking bannedPlayers = new List(); InitProjectSpecific(); } - - public static string ToRange(string ip) - { - if (SteamManager.SteamIDStringToUInt64(ip) != 0) { return ip; } - for (int i = ip.Length - 1; i > 0; i--) - { - if (ip[i] == '.') - { - ip = ip.Substring(0, i) + ".x"; - break; - } - } - return ip; - } } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Networking/Client.cs b/Barotrauma/BarotraumaShared/SharedSource/Networking/Client.cs index f6f1802ae..ef9030eea 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Networking/Client.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Networking/Client.cs @@ -11,10 +11,10 @@ namespace Barotrauma.Networking public string Name; public Identifier PreferredJob; public CharacterTeamType PreferredTeam; - public UInt16 NameID; - public UInt64 SteamID; - public byte ID; - public UInt16 CharacterID; + public UInt16 NameId; + public AccountInfo AccountInfo; + public byte SessionId; + public UInt16 CharacterId; public float Karma; public bool Muted; public bool InGame; @@ -28,10 +28,23 @@ namespace Barotrauma.Networking { public const int MaxNameLength = 32; - public string Name; public UInt16 NameID; - public byte ID; - public UInt64 SteamID; - public UInt64 OwnerSteamID; + public string Name; public UInt16 NameId; + + /// + /// An ID for this client for the current session. + /// THIS IS NOT A PERSISTENT VALUE. DO NOT STORE THIS LONG-TERM. + /// IT CANNOT BE USED TO IDENTIFY PLAYERS ACROSS SESSIONS. + /// + public readonly byte SessionId; + + public AccountInfo AccountInfo; + + /// + /// The ID of the account used to authenticate this session. + /// This value can be used as a persistent value to identify + /// players in the banlist and campaign saves. + /// + public Option AccountId => AccountInfo.AccountId; public LanguageIdentifier Language; @@ -90,14 +103,14 @@ namespace Barotrauma.Networking public UInt16 CharacterID; - private Vector2 spectate_position; + private Vector2 spectatePos; public Vector2? SpectatePos { get { if (character == null || character.IsDead) { - return spectate_position; + return spectatePos; } else { @@ -107,7 +120,7 @@ namespace Barotrauma.Networking set { - spectate_position = value.Value; + spectatePos = value.Value; } } @@ -177,19 +190,13 @@ namespace Barotrauma.Networking { get { return kickVoters.Count; } } - - /*public Client(NetPeer server, string name, byte ID) - : this(name, ID) - { - - }*/ partial void InitProjSpecific(); partial void DisposeProjSpecific(); - public Client(string name, byte ID) + public Client(string name, byte sessionId) { this.Name = name; - this.ID = ID; + this.SessionId = sessionId; kickVoters = new List(); @@ -234,13 +241,16 @@ namespace Barotrauma.Networking return kickVoters.Contains(voter); } - public bool HasKickVoteFromID(int id) + public bool HasKickVoteFromSessionId(int id) { - return kickVoters.Any(k => k.ID == id); + return kickVoters.Any(k => k.SessionId == id); } + public bool SessionOrAccountIdMatches(string userId) + => (AccountId.IsSome() && Networking.AccountId.Parse(userId) == AccountId) + || (byte.TryParse(userId, out byte sessionId) && SessionId == sessionId); - public static void UpdateKickVotes(List connectedClients) + public static void UpdateKickVotes(IReadOnlyList connectedClients) { foreach (Client client in connectedClients) { @@ -250,7 +260,7 @@ namespace Barotrauma.Networking public void WritePermissions(IWriteMessage msg) { - msg.Write(ID); + msg.Write(SessionId); msg.WriteRangedInteger((int)Permissions, 0, (int)ClientPermissions.All); if (HasPermission(ClientPermissions.ConsoleCommands)) { diff --git a/Barotrauma/BarotraumaShared/SharedSource/Networking/ClientPermissions.cs b/Barotrauma/BarotraumaShared/SharedSource/Networking/ClientPermissions.cs index 051c2b1f7..6e5300c4c 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Networking/ClientPermissions.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Networking/ClientPermissions.cs @@ -32,8 +32,8 @@ namespace Barotrauma.Networking class PermissionPreset { - public static List List = new List(); - + public static readonly List List = new List(); + public readonly LocalizedString Name; public readonly LocalizedString Description; public readonly ClientPermissions Permissions; @@ -87,9 +87,11 @@ namespace Barotrauma.Networking } } - public bool MatchesPermissions(ClientPermissions permissions, HashSet permittedConsoleCommands) + public bool MatchesPermissions(ClientPermissions permissions, ISet permittedConsoleCommands) { - return permissions == this.Permissions && PermittedCommands.SequenceEqual(permittedConsoleCommands); + return permissions == Permissions + && PermittedCommands.All(permittedConsoleCommands.Contains) + && permittedConsoleCommands.All(PermittedCommands.Contains); } } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Networking/INetSerializableStruct.cs b/Barotrauma/BarotraumaShared/SharedSource/Networking/INetSerializableStruct.cs index 950a58719..767c57723 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Networking/INetSerializableStruct.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Networking/INetSerializableStruct.cs @@ -3,10 +3,10 @@ using System; using System.Collections.Generic; using System.Collections.Immutable; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; -using System.Runtime.Serialization; using Barotrauma.Networking; using Microsoft.Xna.Framework; @@ -35,7 +35,7 @@ namespace Barotrauma /// Using the attribute on the struct will make all fields and properties serialized /// [AttributeUsage(AttributeTargets.Field | AttributeTargets.Struct | AttributeTargets.Property)] - public class NetworkSerialize : Attribute + public sealed class NetworkSerialize : Attribute { public int MaxValueInt = int.MaxValue; public int MinValueInt = int.MinValue; @@ -56,21 +56,37 @@ namespace Barotrauma /// /// Static class that contains serialize and deserialize functions for different types used in /// - public static class NetSerializableProperties + [SuppressMessage("ReSharper", "RedundantTypeArgumentsOfMethod")] + static class NetSerializableProperties { - public readonly struct ReadWriteBehavior + public interface IReadWriteBehavior { - public delegate dynamic? ReadDelegate(IReadMessage inc, Type type, NetworkSerialize attribute); + public delegate object? ReadDelegate(IReadMessage inc, NetworkSerialize attribute, IReadableBitField bitField); - public delegate void WriteDelegate(dynamic? obj, NetworkSerialize attribute, IWriteMessage msg); + public delegate void WriteDelegate(object? obj, NetworkSerialize attribute, IWriteMessage msg, IWritableBitField bitField); - public readonly ReadDelegate ReadAction; - public readonly WriteDelegate WriteAction; + public ReadDelegate ReadAction { get; } + public WriteDelegate WriteAction { get; } + } + + public readonly struct ReadWriteBehavior : IReadWriteBehavior + { + public delegate T ReadDelegate(IReadMessage inc, NetworkSerialize attribute, IReadableBitField bitField); + + public delegate void WriteDelegate(T obj, NetworkSerialize attribute, IWriteMessage msg, IWritableBitField bitField); + + public IReadWriteBehavior.ReadDelegate ReadAction { get; } + public IReadWriteBehavior.WriteDelegate WriteAction { get; } + + public ReadDelegate ReadActionDirect { get; } + public WriteDelegate WriteActionDirect { get; } public ReadWriteBehavior(ReadDelegate readAction, WriteDelegate writeAction) { - ReadAction = readAction; - WriteAction = writeAction; + ReadAction = (inc, attribute, bitField) => readAction(inc, attribute, bitField); + WriteAction = (o, attribute, msg, bitField) => writeAction((T)o!, attribute, msg, bitField); + ReadActionDirect = readAction; + WriteActionDirect = writeAction; } } @@ -80,17 +96,18 @@ namespace Barotrauma public delegate void SetValueDelegate(object? obj, object? value); + public readonly string Name; public readonly Type Type; - public readonly ReadWriteBehavior Behavior; + public readonly IReadWriteBehavior Behavior; public readonly NetworkSerialize Attribute; public readonly SetValueDelegate SetValue; public readonly GetValueDelegate GetValue; public readonly bool HasOwnAttribute; - public CachedReflectedVariable(MemberInfo info, ReadWriteBehavior behavior, Type baseClassType) + public CachedReflectedVariable(MemberInfo info, IReadWriteBehavior behavior, Type baseClassType) { Behavior = behavior; - + Name = info.Name; switch (info) { case PropertyInfo pi: @@ -126,343 +143,368 @@ namespace Barotrauma private static readonly Dictionary> CachedVariables = new Dictionary>(); - private static readonly ImmutableDictionary TypeBehaviors = new Dictionary - { - { typeof(Boolean), new ReadWriteBehavior(ReadBoolean, WriteDynamic) }, - { typeof(Byte), new ReadWriteBehavior(ReadByte, WriteDynamic) }, - { typeof(UInt16), new ReadWriteBehavior(ReadUInt16, WriteDynamic) }, - { typeof(Int16), new ReadWriteBehavior(ReadInt16, WriteDynamic) }, - { typeof(UInt32), new ReadWriteBehavior(ReadUInt32, WriteDynamic) }, - { typeof(Int32), new ReadWriteBehavior(ReadInt32, WriteInt32) }, - { typeof(UInt64), new ReadWriteBehavior(ReadUInt64, WriteDynamic) }, - { typeof(Int64), new ReadWriteBehavior(ReadInt64, WriteDynamic) }, - { typeof(Single), new ReadWriteBehavior(ReadSingle, WriteSingle) }, - { typeof(Double), new ReadWriteBehavior(ReadDouble, WriteDynamic) }, - { typeof(String), new ReadWriteBehavior(ReadString, WriteDynamic) }, - { typeof(Identifier), new ReadWriteBehavior(ReadIdentifier, WriteDynamic) }, - { typeof(Color), new ReadWriteBehavior(ReadColor, WriteColor) }, - { typeof(Vector2), new ReadWriteBehavior(ReadVector2, WriteVector2) } - }.ToImmutableDictionary(); + private static readonly Dictionary TypeBehaviors + = new Dictionary + { + { typeof(Boolean), new ReadWriteBehavior(ReadBoolean, WriteBoolean) }, + { typeof(Byte), new ReadWriteBehavior(ReadByte, WriteByte) }, + { typeof(UInt16), new ReadWriteBehavior(ReadUInt16, WriteUInt16) }, + { typeof(Int16), new ReadWriteBehavior(ReadInt16, WriteInt16) }, + { typeof(UInt32), new ReadWriteBehavior(ReadUInt32, WriteUInt32) }, + { typeof(Int32), new ReadWriteBehavior(ReadInt32, WriteInt32) }, + { typeof(UInt64), new ReadWriteBehavior(ReadUInt64, WriteUInt64) }, + { typeof(Int64), new ReadWriteBehavior(ReadInt64, WriteInt64) }, + { typeof(Single), new ReadWriteBehavior(ReadSingle, WriteSingle) }, + { typeof(Double), new ReadWriteBehavior(ReadDouble, WriteDouble) }, + { typeof(String), new ReadWriteBehavior(ReadString, WriteString) }, + { typeof(Identifier), new ReadWriteBehavior(ReadIdentifier, WriteIdentifier) }, + { typeof(AccountId), new ReadWriteBehavior(ReadAccountId, WriteAccountId) }, + { typeof(Color), new ReadWriteBehavior(ReadColor, WriteColor) }, + { typeof(Vector2), new ReadWriteBehavior(ReadVector2, WriteVector2) } + }; - private static readonly ImmutableDictionary, ReadWriteBehavior> TypePredicates = new Dictionary, ReadWriteBehavior> + private static readonly ImmutableDictionary, Func> BehaviorFactories = new Dictionary, Func> { // Arrays - { type => typeof(Array).IsAssignableFrom(type.BaseType), new ReadWriteBehavior(ReadArray, WriteArray) }, + { type => type.IsArray, CreateArrayBehavior }, // Nested INetSerializableStructs - { type => typeof(INetSerializableStruct).IsAssignableFrom(type), new ReadWriteBehavior(ReadINetSerializableStruct, WriteINetSerializableStruct) }, + { type => typeof(INetSerializableStruct).IsAssignableFrom(type), CreateINetSerializableStructBehavior }, // Enums - { type => type.IsEnum, new ReadWriteBehavior(ReadEnum, WriteEnum) }, + { type => type.IsEnum, CreateEnumBehavior }, // Nullable - { type => Nullable.GetUnderlyingType(type) != null, new ReadWriteBehavior(ReadNullable, WriteNullable) }, + { type => Nullable.GetUnderlyingType(type) != null, CreateNullableStructBehavior }, + + // ImmutableArray + { type => IsOfGenericType(type, typeof(ImmutableArray<>)), CreateImmutableArrayBehavior }, // Option - { type => type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Option<>), new ReadWriteBehavior(ReadOption, WriteOption) } + { type => IsOfGenericType(type, typeof(Option<>)), CreateOptionBehavior } }.ToImmutableDictionary(); - private static readonly ReadWriteBehavior InvalidReadWriteBehavior = new ReadWriteBehavior(ReadInvalid, WriteInvalid); - - private static readonly Dictionary cachedSomeCreateMethods = new Dictionary(); - private static readonly Dictionary cachedNoneCreateMethod = new Dictionary(); - - private static void WriteInvalid(dynamic? obj, NetworkSerialize attribute, IWriteMessage msg) => - throw new SerializationException($"Type {obj?.GetType()} cannot be serialized. Did you forget to implement {nameof(INetSerializableStruct)}?"); - - private static dynamic ReadInvalid(IReadMessage inc, Type type, NetworkSerialize attribute) => throw new SerializationException($"Type {type} cannot be deserialized. Did you forget to implement {nameof(INetSerializableStruct)}?"); - - private static void WriteOption(dynamic? obj, NetworkSerialize attribute, IWriteMessage msg) + /// The type that the behavior handles + /// The type that will be used as the generic parameter for the read/write methods + /// The read method. + /// It must have a generic parameter. + /// The return type must be such that if the generic parameter is replaced with funcGenericParam, you get behaviorGenericParam. + /// The write method. The first parameter's type must be the same as readFunc's return type. + /// Ideally the least specific type possible, because it's replaced by behaviorGenericParam + /// A ReadWriteBehavior<behaviorGenericParam> + private static IReadWriteBehavior CreateBehavior(Type behaviorGenericParam, + Type funcGenericParam, + ReadWriteBehavior.ReadDelegate readFunc, + ReadWriteBehavior.WriteDelegate writeFunc) { - if (obj is null) { throw new ArgumentNullException(nameof(obj), "Tried to write 'null' into a non-nullable type"); } + var behaviorType = typeof(ReadWriteBehavior<>).MakeGenericType(behaviorGenericParam); - Type type = obj.GetType(); - Type optionType = type.GetGenericTypeDefinition(); - Type underlyingType = type.GetGenericArguments()[0]; + var readDelegateType = typeof(ReadWriteBehavior<>.ReadDelegate).MakeGenericType(behaviorGenericParam); + var writeDelegateType = typeof(ReadWriteBehavior<>.WriteDelegate).MakeGenericType(behaviorGenericParam); - if (optionType == typeof(None<>)) + var constructor = behaviorType.GetConstructor(new[] { - msg.Write(false); + readDelegateType, writeDelegateType + }); + + return (constructor!.Invoke(new object[] + { + readFunc.Method.GetGenericMethodDefinition().MakeGenericMethod(funcGenericParam).CreateDelegate(readDelegateType), + writeFunc.Method.GetGenericMethodDefinition().MakeGenericMethod(funcGenericParam).CreateDelegate(writeDelegateType) + }) as IReadWriteBehavior)!; + } + + private static IReadWriteBehavior CreateArrayBehavior(Type arrayType) => + CreateBehavior( + arrayType, + arrayType.GetElementType()!, + ReadArray, + WriteArray); + + private static IReadWriteBehavior CreateINetSerializableStructBehavior(Type structType) => + CreateBehavior( + structType, + structType, + ReadINetSerializableStruct, + WriteINetSerializableStruct); + + private static IReadWriteBehavior CreateEnumBehavior(Type enumType) => + CreateBehavior( + enumType, + enumType, + ReadEnum, + WriteEnum); + + private static IReadWriteBehavior CreateNullableStructBehavior(Type nullableType) => + CreateBehavior( + nullableType, + Nullable.GetUnderlyingType(nullableType)!, + ReadNullable, + WriteNullable); + + private static IReadWriteBehavior CreateOptionBehavior(Type optionType) => + CreateBehavior( + optionType, + optionType.GetGenericArguments()[0], + ReadOption, + WriteOption); + + private static IReadWriteBehavior CreateImmutableArrayBehavior(Type arrayType) => + CreateBehavior( + arrayType, + arrayType.GetGenericArguments()[0], + ReadImmutableArray, + WriteImmutableArray); + + private static ImmutableArray ReadImmutableArray(IReadMessage inc, NetworkSerialize attribute, IReadableBitField bitField) where T : notnull + { + return ReadArray(inc, attribute, bitField).ToImmutableArray(); + } + + private static void WriteImmutableArray(ImmutableArray array, NetworkSerialize attribute, IWriteMessage msg, IWritableBitField bitField) where T : notnull + { + ToolBox.ThrowIfNull(array); + WriteIReadOnlyCollection(array, attribute, msg, bitField); + } + + private static T[] ReadArray(IReadMessage inc, NetworkSerialize attribute, IReadableBitField bitField) where T : notnull + { + int length = bitField.ReadInteger(0, attribute.ArrayMaxSize); + + T[] array = new T[length]; + + if (!TryFindBehavior(out ReadWriteBehavior behavior)) + { + throw new InvalidOperationException($"Could not find suitable behavior for type {typeof(T)} in {nameof(ReadArray)}"); } - else if (optionType == typeof(Some<>)) + + for (int i = 0; i < length; i++) { - msg.Write(true); - if (TryFindBehavior(underlyingType, out ReadWriteBehavior behavior)) - { - behavior.WriteAction(obj.Value, attribute, msg); - } + array[i] = behavior.ReadActionDirect(inc, attribute, bitField); } - else + + return array; + } + + private static void WriteArray(T[] array, NetworkSerialize attribute, IWriteMessage msg, IWritableBitField bitField) where T : notnull + { + ToolBox.ThrowIfNull(array); + WriteIReadOnlyCollection(array, attribute, msg, bitField); + } + + private static void WriteIReadOnlyCollection(IReadOnlyCollection array, NetworkSerialize attribute, IWriteMessage msg, IWritableBitField bitField) where T : notnull + { + bitField.WriteInteger(array.Count, 0, attribute.ArrayMaxSize); + + if (!TryFindBehavior(out ReadWriteBehavior behavior)) { - throw new ArgumentOutOfRangeException(nameof(obj), "Option type was neither None or Some"); + throw new InvalidOperationException($"Could not find suitable behavior for type {typeof(T)} in {nameof(WriteArray)}"); + } + + foreach (T o in array) + { + behavior.WriteActionDirect(o, attribute, msg, bitField); } } - private static dynamic? ReadOption(IReadMessage inc, Type type, NetworkSerialize attribute) + private static T ReadINetSerializableStruct(IReadMessage inc, NetworkSerialize attribute, IReadableBitField bitField) where T : INetSerializableStruct { - Type underlyingType = type.GetGenericArguments()[0]; - bool hasValue = inc.ReadBoolean(); - if (!hasValue) - { - return GetCreateMethod(typeof(None<>), underlyingType, cachedNoneCreateMethod).Invoke(null, null); - } - - if (TryFindBehavior(underlyingType, out ReadWriteBehavior behavior)) - { - dynamic? value = behavior.ReadAction(inc, underlyingType, attribute); - return GetCreateMethod(typeof(Some<>), underlyingType, cachedSomeCreateMethods).Invoke(null, new[] { value }); - } - - throw new InvalidOperationException($"Could not find suitable behavior for type {underlyingType} in {nameof(ReadOption)}"); - - static MethodInfo GetCreateMethod(Type optionType, Type type, Dictionary cache) - { - if (cache.TryGetValue(type, out MethodInfo? foundInfo)) - { - return foundInfo; - } - - Type genericType = optionType.MakeGenericType(type); - MethodInfo info = genericType.GetMethod("Create", BindingFlags.Static | BindingFlags.Public)!; - cache.Add(type, info); - return info; - } + return INetSerializableStruct.ReadInternal(inc, bitField); } - private static void WriteNullable(dynamic? obj, NetworkSerialize attribute, IWriteMessage msg) + private static void WriteINetSerializableStruct(T serializableStruct, NetworkSerialize attribute, IWriteMessage msg, IWritableBitField bitField) where T : INetSerializableStruct { - if (obj is { } notNull) - { - msg.Write(true); - - if (TryFindBehavior(notNull.GetType(), out ReadWriteBehavior behavior)) - { - // uh oh, something terrible has happened! - if (behavior.WriteAction == WriteNullable) { behavior = InvalidReadWriteBehavior; } - - behavior.WriteAction(notNull, attribute, msg); - return; - } - } - - msg.Write(false); + ToolBox.ThrowIfNull(serializableStruct); + serializableStruct.WriteInternal(msg, bitField); } - private static dynamic? ReadNullable(IReadMessage inc, Type type, NetworkSerialize attribute) + private static T ReadEnum(IReadMessage inc, NetworkSerialize attribute, IReadableBitField bitField) where T : Enum { - if (!inc.ReadBoolean()) { return null; } + var type = typeof(T); - Type? underlyingType = Nullable.GetUnderlyingType(type); - if (underlyingType is null) { throw new InvalidOperationException($"Could not get the underlying type of {type} in {nameof(ReadNullable)}"); } - - if (TryFindBehavior(underlyingType, out ReadWriteBehavior behavior)) - { - // uh oh, something terrible has happened! - if (behavior.ReadAction == ReadNullable) { behavior = InvalidReadWriteBehavior; } - - return behavior.ReadAction(inc, underlyingType, attribute); - } - - throw new InvalidOperationException($"Could not find suitable behavior for type {underlyingType} in {nameof(ReadNullable)}"); - } - - private static void WriteEnum(dynamic? obj, NetworkSerialize attribute, IWriteMessage msg) - { - if (obj is null) { throw new ArgumentNullException(nameof(obj), "Tried to write 'null' into a non-nullable type"); } - - Range range = GetEnumRange(obj.GetType()); - msg.WriteRangedInteger(Convert.ChangeType(obj, obj.GetTypeCode()), range.Start, range.End); - } - - private static dynamic ReadEnum(IReadMessage inc, Type type, NetworkSerialize attribute) - { Range range = GetEnumRange(type); - int enumIndex = inc.ReadRangedInteger(range.Start, range.End); + int enumIndex = bitField.ReadInteger(range.Start, range.End); - foreach (dynamic? e in Enum.GetValues(type)) + foreach (T e in (T[])Enum.GetValues(type)) { - if (Convert.ChangeType(e, e!.GetTypeCode()) == enumIndex) { return e; } + if ((int)Convert.ChangeType(e, e.GetTypeCode()) == enumIndex) { return e; } } throw new InvalidOperationException($"An enum {type} with value {enumIndex} could not be found in {nameof(ReadEnum)}"); } - private static void WriteINetSerializableStruct(dynamic? obj, NetworkSerialize attribute, IWriteMessage msg) + private static void WriteEnum(T value, NetworkSerialize attribute, IWriteMessage msg, IWritableBitField bitField) where T : Enum { - if (obj is null) { throw new ArgumentNullException(nameof(obj), "Tried to write 'null' into a non-nullable type"); } + ToolBox.ThrowIfNull(value); - if (!(obj is INetSerializableStruct serializableStruct)) { throw new InvalidOperationException($"Object in {nameof(WriteINetSerializableStruct)} was {obj.GetType()} but expected {nameof(INetSerializableStruct)}"); } - - serializableStruct.Write(msg); + Range range = GetEnumRange(typeof(T)); + bitField.WriteInteger((int)Convert.ChangeType(value, value.GetTypeCode()), range.Start, range.End); } - private static dynamic ReadINetSerializableStruct(IReadMessage inc, Type type, NetworkSerialize attribute) - { - return INetSerializableStruct.ReadDynamic(type, inc); - } - - private static void WriteDynamic(dynamic? obj, NetworkSerialize attribute, IWriteMessage msg) - { - if (obj is null) { throw new ArgumentNullException(nameof(obj), "Tried to write 'null' into a non-nullable type"); } - - msg.Write(obj); - } - - private static dynamic ReadArray(IReadMessage inc, Type type, NetworkSerialize attribute) - { - Type? elementType = type.GetElementType(); - if (elementType is null) { throw new InvalidOperationException($"Could not get the element type of {type} in {nameof(ReadArray)}"); } - - int length = inc.ReadRangedInteger(0, attribute.ArrayMaxSize); - - Array list = Array.CreateInstance(elementType, length); - - for (int i = 0; i < length; i++) + private static T? ReadNullable(IReadMessage inc, NetworkSerialize attribute, IReadableBitField bitField) where T : struct => + ReadOption(inc, attribute, bitField) switch { - if (TryFindBehavior(elementType, out ReadWriteBehavior behavior)) - { - list.SetValue(behavior.ReadAction(inc, elementType, attribute), i); - } - else - { - throw new InvalidOperationException($"Could not find suitable behavior for type {elementType} in {nameof(ReadArray)}"); - } + Some { Value: var value } => value, + None _ => null, + _ => throw new ArgumentOutOfRangeException() + }; + + private static void WriteNullable(T? value, NetworkSerialize attribute, IWriteMessage msg, IWritableBitField bitField) where T : struct => + WriteOption(value.HasValue ? Option.Some(value.Value) : Option.None(), attribute, msg, bitField); + + private static Option ReadOption(IReadMessage inc, NetworkSerialize attribute, IReadableBitField bitField) where T : notnull + { + bool hasValue = bitField.ReadBoolean(); + if (!hasValue) + { + return Option.None(); } - return list; + if (TryFindBehavior(out ReadWriteBehavior behavior)) + { + return Option.Some(behavior.ReadActionDirect(inc, attribute, bitField)); + } + + throw new InvalidOperationException($"Could not find suitable behavior for type {typeof(T)} in {nameof(ReadOption)}"); } - private static void WriteArray(dynamic? obj, NetworkSerialize attribute, IWriteMessage msg) + private static void WriteOption(Option option, NetworkSerialize attribute, IWriteMessage msg, IWritableBitField bitField) where T : notnull { - if (obj is null) { throw new ArgumentNullException(nameof(obj), "Tried to write 'null' into a non-nullable type"); } + ToolBox.ThrowIfNull(option); - if (!(obj is Array array)) { throw new InvalidOperationException($"Object in {nameof(WriteArray)} was {obj.GetType()} but expected {nameof(Array)}"); } - - msg.WriteRangedInteger(array.Length, 0, attribute.ArrayMaxSize); - - foreach (dynamic? o in array) + if (option.TryUnwrap(out T value)) { - if (TryFindBehavior(o!.GetType(), out ReadWriteBehavior behavior)) + bitField.WriteBoolean(true); + if (TryFindBehavior(out ReadWriteBehavior behavior)) { - behavior.WriteAction(o, attribute, msg); + behavior.WriteActionDirect(value, attribute, msg, bitField); } } + else + { + bitField.WriteBoolean(false); + } } - private static dynamic ReadBoolean(IReadMessage inc, Type type, NetworkSerialize attribute) => inc.ReadBoolean(); + 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 dynamic ReadByte(IReadMessage inc, Type type, NetworkSerialize attribute) => inc.ReadByte(); + 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.Write(b); } - private static dynamic ReadUInt16(IReadMessage inc, Type type, NetworkSerialize attribute) => inc.ReadUInt16(); + 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.Write(b); } - private static dynamic ReadInt16(IReadMessage inc, Type type, NetworkSerialize attribute) => inc.ReadInt16(); + 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.Write(b); } - private static dynamic ReadUInt32(IReadMessage inc, Type type, NetworkSerialize attribute) => inc.ReadUInt32(); + 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.Write(b); } - private static dynamic ReadInt32(IReadMessage inc, Type type, NetworkSerialize attribute) + private static int ReadInt32(IReadMessage inc, NetworkSerialize attribute, IReadableBitField bitField) { if (IsRanged(attribute.MinValueInt, attribute.MaxValueInt)) { - return inc.ReadRangedInteger(attribute.MinValueInt, attribute.MaxValueInt); + return bitField.ReadInteger(attribute.MinValueInt, attribute.MaxValueInt); } return inc.ReadInt32(); } - private static void WriteInt32(dynamic? obj, NetworkSerialize attribute, IWriteMessage msg) + private static void WriteInt32(int i, NetworkSerialize attribute, IWriteMessage msg, IWritableBitField bitField) { - if (obj is null) { throw new ArgumentNullException(nameof(obj), "Tried to write 'null' into a non-nullable type"); } + ToolBox.ThrowIfNull(i); if (IsRanged(attribute.MinValueInt, attribute.MaxValueInt)) { - msg.WriteRangedInteger(obj, attribute.MinValueInt, attribute.MaxValueInt); + bitField.WriteInteger(i, attribute.MinValueInt, attribute.MaxValueInt); return; } - msg.Write(obj); + msg.Write(i); } - private static dynamic ReadUInt64(IReadMessage inc, Type type, NetworkSerialize attribute) => inc.ReadUInt64(); + 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.Write(b); } - private static dynamic ReadInt64(IReadMessage inc, Type type, NetworkSerialize attribute) => inc.ReadInt64(); + 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.Write(b); } - private static dynamic ReadSingle(IReadMessage inc, Type type, NetworkSerialize attribute) + private static float ReadSingle(IReadMessage inc, NetworkSerialize attribute, IReadableBitField bitField) { if (IsRanged(attribute.MinValueFloat, attribute.MaxValueFloat)) { - return inc.ReadRangedSingle(attribute.MinValueFloat, attribute.MaxValueFloat, attribute.NumberOfBits); + return bitField.ReadFloat(attribute.MinValueFloat, attribute.MaxValueFloat, attribute.NumberOfBits); } return inc.ReadSingle(); } - private static void WriteSingle(dynamic? obj, NetworkSerialize attribute, IWriteMessage msg) + private static void WriteSingle(float f, NetworkSerialize attribute, IWriteMessage msg, IWritableBitField bitField) { - if (obj is null) { throw new ArgumentNullException(nameof(obj), "Tried to write 'null' into a non-nullable type"); } + ToolBox.ThrowIfNull(f); if (IsRanged(attribute.MinValueFloat, attribute.MaxValueFloat)) { - msg.WriteRangedSingle(obj, attribute.MinValueFloat, attribute.MaxValueFloat, attribute.NumberOfBits); + bitField.WriteFloat(f, attribute.MinValueFloat, attribute.MaxValueFloat, attribute.NumberOfBits); return; } - msg.Write(obj); + msg.Write(f); } - private static dynamic ReadDouble(IReadMessage inc, Type type, NetworkSerialize attribute) => inc.ReadDouble(); + 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.Write(b); } - private static dynamic ReadString(IReadMessage inc, Type type, NetworkSerialize attribute) => inc.ReadString(); + 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.Write(b); } - private static dynamic ReadIdentifier(IReadMessage inc, Type type, NetworkSerialize attribute) => inc.ReadIdentifier(); + 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.Write(b); } - private static dynamic ReadColor(IReadMessage inc, Type type, NetworkSerialize attribute) => attribute.IncludeColorAlpha ? inc.ReadColorR8G8B8A8() : inc.ReadColorR8G8B8(); - - private static void WriteColor(dynamic? obj, NetworkSerialize attribute, IWriteMessage msg) + private static AccountId ReadAccountId(IReadMessage inc, NetworkSerialize attribute, IReadableBitField bitField) { - if (obj is null) { throw new ArgumentNullException(nameof(obj), "Tried to write 'null' into a non-nullable type"); } + string str = inc.ReadString(); + return AccountId.Parse(str).TryUnwrap(out var accountId) + ? accountId + : throw new InvalidCastException($"Could not parse \"{str}\" as an {nameof(AccountId)}"); + } + + private static void WriteAccountId(AccountId accountId, NetworkSerialize attribute, IWriteMessage msg, IWritableBitField bitField) + { + msg.Write(accountId.StringRepresentation); + } + + private static Color ReadColor(IReadMessage inc, NetworkSerialize attribute, IReadableBitField bitField) => attribute.IncludeColorAlpha ? inc.ReadColorR8G8B8A8() : inc.ReadColorR8G8B8(); + + private static void WriteColor(Color color, NetworkSerialize attribute, IWriteMessage msg, IWritableBitField bitField) + { + ToolBox.ThrowIfNull(color); if (attribute.IncludeColorAlpha) { - msg.WriteColorR8G8B8A8(obj); + msg.WriteColorR8G8B8A8(color); return; } - msg.WriteColorR8G8B8(obj); + msg.WriteColorR8G8B8(color); } - private static dynamic ReadVector2(IReadMessage inc, Type type, NetworkSerialize attribute) + private static Vector2 ReadVector2(IReadMessage inc, NetworkSerialize attribute, IReadableBitField bitField) { - float x; - float y; - - if (IsRanged(attribute.MinValueFloat, attribute.MaxValueFloat)) - { - x = inc.ReadRangedSingle(attribute.MinValueFloat, attribute.MaxValueFloat, attribute.NumberOfBits); - y = inc.ReadRangedSingle(attribute.MinValueFloat, attribute.MaxValueFloat, attribute.NumberOfBits); - } - else - { - x = inc.ReadSingle(); - y = inc.ReadSingle(); - } + float x = ReadSingle(inc, attribute, bitField); + float y = ReadSingle(inc, attribute, bitField); return new Vector2(x, y); } - private static void WriteVector2(dynamic? obj, NetworkSerialize attribute, IWriteMessage msg) + private static void WriteVector2(Vector2 vector2, NetworkSerialize attribute, IWriteMessage msg, IWritableBitField bitField) { - if (obj is null) { throw new ArgumentNullException(nameof(obj), "Tried to write 'null' into a non-nullable type"); } + ToolBox.ThrowIfNull(vector2); - var (x, y) = (Vector2)obj; - if (IsRanged(attribute.MinValueFloat, attribute.MaxValueFloat)) - { - msg.WriteRangedSingle(x, attribute.MinValueFloat, attribute.MaxValueFloat, attribute.NumberOfBits); - msg.WriteRangedSingle(y, attribute.MinValueFloat, attribute.MaxValueFloat, attribute.NumberOfBits); - return; - } - - msg.Write(x); - msg.Write(y); + var (x, y) = vector2; + WriteSingle(x, attribute, msg, bitField); + WriteSingle(y, attribute, msg, bitField); } private static bool IsRanged(float minValue, float maxValue) => minValue > float.MinValue || maxValue < float.MaxValue; @@ -474,53 +516,71 @@ namespace Barotrauma return new Range(values.Min(), values.Max()); } - private static bool TryFindBehavior(Type type, out ReadWriteBehavior behavior) + private static bool TryFindBehavior(out ReadWriteBehavior behavior) where T : notnull { - if (TypeBehaviors.TryGetValue(type, out behavior)) { return true; } + bool found = TryFindBehavior(typeof(T), out var bhvr); + behavior = (ReadWriteBehavior)bhvr; + return found; + } - foreach (var (predicate, behavior2) in TypePredicates) + private static bool TryFindBehavior(Type type, out IReadWriteBehavior behavior) + { + if (TypeBehaviors.TryGetValue(type, out var outBehavior)) { - if (predicate(type)) - { - behavior = behavior2; - return true; - } + behavior = outBehavior; + return true; } - behavior = InvalidReadWriteBehavior; + foreach (var (predicate, factory) in BehaviorFactories) + { + if (!predicate(type)) { continue; } + + behavior = factory(type); + TypeBehaviors.Add(type, behavior); + return true; + } + + behavior = default!; return false; } - public static ImmutableArray GetPropertiesAndFields(Type type, Type baseClassType) + public static ImmutableArray GetPropertiesAndFields(Type type) { if (CachedVariables.TryGetValue(type, out var cached)) { return cached; } List variables = new List(); - IEnumerable propertyInfos = type.GetProperties().Where(HasAttribute); - IEnumerable fieldInfos = type.GetFields().Where(HasAttribute); + IEnumerable propertyInfos = type.GetProperties().Where(HasAttribute).Where(NotStatic); + IEnumerable fieldInfos = type.GetFields().Where(HasAttribute).Where(NotStatic); foreach (PropertyInfo info in propertyInfos) { - if (TryFindBehavior(info.PropertyType, out ReadWriteBehavior behavior)) + if (info.SetMethod is null) { - variables.Add(new CachedReflectedVariable(info, behavior, baseClassType)); + //skip get-only properties, because it's + //useful to have them but their value + //cannot be set when reading a struct + continue; + } + if (TryFindBehavior(info.PropertyType, out IReadWriteBehavior behavior)) + { + variables.Add(new CachedReflectedVariable(info, behavior, type)); } else { - throw new SerializationException($"Unable to serialize type \"{type}\"."); + throw new Exception($"Unable to serialize type \"{type}\"."); } } foreach (FieldInfo info in fieldInfos) { - if (TryFindBehavior(info.FieldType, out ReadWriteBehavior behavior)) + if (TryFindBehavior(info.FieldType, out IReadWriteBehavior behavior)) { - variables.Add(new CachedReflectedVariable(info, behavior, baseClassType)); + variables.Add(new CachedReflectedVariable(info, behavior, type)); } else { - throw new SerializationException($"Unable to serialize type \"{type}\"."); + throw new Exception($"Unable to serialize type \"{type}\"."); } } @@ -528,7 +588,20 @@ namespace Barotrauma CachedVariables.Add(type, array); return array; - bool HasAttribute(MemberInfo info) => (info.GetCustomAttribute() ?? baseClassType.GetCustomAttribute()) != null; + bool HasAttribute(MemberInfo info) => (info.GetCustomAttribute() ?? type.GetCustomAttribute()) != null; + + bool NotStatic(MemberInfo info) + => info switch + { + PropertyInfo property => property.GetGetMethod() is { IsStatic: false }, + FieldInfo field => !field.IsStatic, + _ => false + }; + } + + private static bool IsOfGenericType(Type type, Type comparedTo) + { + return type.IsGenericType && type.GetGenericTypeDefinition() == comparedTo; } } @@ -575,13 +648,15 @@ namespace Barotrauma /// float
/// double
/// string
+ ///
+ ///
///
///
/// In addition arrays, enums, and are supported.
/// Using or will make the field or property optional. /// /// - public interface INetSerializableStruct + interface INetSerializableStruct { /// /// Deserializes a network message into a struct. @@ -608,21 +683,34 @@ namespace Barotrauma /// Incoming network message /// Type of the struct that implements /// A new struct of type T with fields and properties deserialized - public static T Read(IReadMessage inc) where T : INetSerializableStruct => (T)ReadDynamic(typeof(T), inc); - - public static dynamic ReadDynamic(Type type, IReadMessage inc) + public static T Read(IReadMessage inc) where T : INetSerializableStruct { - object? newObject = Activator.CreateInstance(type); + IReadableBitField bitField = new ReadOnlyBitField(inc); + return ReadInternal(inc, bitField); + } + + public static T ReadInternal(IReadMessage inc, IReadableBitField bitField) where T : INetSerializableStruct + { + object? newObject = Activator.CreateInstance(typeof(T)); if (newObject is null) { return default!; } - var properties = NetSerializableProperties.GetPropertiesAndFields(type, type); + var properties = NetSerializableProperties.GetPropertiesAndFields(typeof(T)); foreach (NetSerializableProperties.CachedReflectedVariable property in properties) { - NetworkSerialize attribute = property.Attribute; - property.SetValue(newObject, property.Behavior.ReadAction(inc, property.Type, attribute)); + object? value = property.Behavior.ReadAction(inc, property.Attribute, bitField); + try + { + property.SetValue(newObject, value); + } + catch (Exception exception) + { + throw new Exception($"Failed to assign" + + $" {value ?? "[NULL]"} ({value?.GetType().Name ?? "[NULL]"})" + + $" to {typeof(T).Name}.{property.Name} ({property.Type.Name})", exception); + } } - return newObject; + return (T)newObject; } /// @@ -651,17 +739,26 @@ namespace Barotrauma /// Outgoing network message public void Write(IWriteMessage msg) { - Type type = GetType(); - var properties = NetSerializableProperties.GetPropertiesAndFields(type, type); + IWritableBitField bitField = new WriteOnlyBitField(); + IWriteMessage structWriteMsg = new WriteOnlyMessage(); + WriteInternal(structWriteMsg, bitField); + bitField.WriteToMessage(msg); + msg.Write(structWriteMsg.Buffer, 0, structWriteMsg.LengthBytes); + } + + public void WriteInternal(IWriteMessage msg, IWritableBitField bitField) + { + var properties = NetSerializableProperties.GetPropertiesAndFields(GetType()); + foreach (NetSerializableProperties.CachedReflectedVariable property in properties) { - NetworkSerialize attribute = property.Attribute; - property.Behavior.WriteAction(property.GetValue(this), attribute, msg); + object? value = property.GetValue(this); + property.Behavior.WriteAction(value!, property.Attribute, msg, bitField); } } } - public static class WriteOnlyMessageExtensions + static class WriteOnlyMessageExtensions { #if CLIENT public static IWriteMessage WithHeader(this IWriteMessage msg, ClientPacketHeader header) diff --git a/Barotrauma/BarotraumaShared/SharedSource/Networking/NetworkMember.cs b/Barotrauma/BarotraumaShared/SharedSource/Networking/NetworkMember.cs index afa43e536..7e93a540c 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Networking/NetworkMember.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Networking/NetworkMember.cs @@ -148,7 +148,6 @@ namespace Barotrauma.Networking InvalidVersion, MissingContentPackage, IncompatibleContentPackage, - NotOnWhitelist, ExcessiveDesyncOldEvent, ExcessiveDesyncRemovedEvent, SyncTimeout, @@ -218,10 +217,7 @@ namespace Barotrauma.Networking get { return gameStarted; } } - public virtual List ConnectedClients - { - get { return null; } - } + public abstract IReadOnlyList ConnectedClients { get; } public RespawnManager RespawnManager { @@ -268,19 +264,22 @@ namespace Barotrauma.Networking { retVal += "color:#ff9900;"; } - retVal += "metadata:" + (client.SteamID != 0 ? client.SteamID.ToString() : client.ID.ToString()) + "‖" + (name ?? client.Name).Replace("‖", "") + "‖end‖"; + retVal += "metadata:" + (client.AccountId.TryUnwrap(out var accountId) ? accountId.ToString() : client.SessionId.ToString()) + + "‖" + (name ?? client.Name).Replace("‖", "") + "‖end‖"; return retVal; } - public virtual void KickPlayer(string kickedName, string reason) { } + public abstract void KickPlayer(string kickedName, string reason); - public virtual void BanPlayer(string kickedName, string reason, bool range = false, TimeSpan? duration = null) { } + public abstract void BanPlayer(string kickedName, string reason, TimeSpan? duration = null); - public virtual void UnbanPlayer(string playerName, string playerIP) { } + public abstract void UnbanPlayer(string playerName); + + public abstract void UnbanPlayer(Endpoint endpoint); public virtual void Update(float deltaTime) { } - public virtual void Disconnect() { } + public virtual void Quit() { } /// /// Check if the two version are compatible (= if they can play together in multiplayer). diff --git a/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/AccountId/AccountId.cs b/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/AccountId/AccountId.cs new file mode 100644 index 000000000..3be504afe --- /dev/null +++ b/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/AccountId/AccountId.cs @@ -0,0 +1,24 @@ +#nullable enable + +namespace Barotrauma.Networking +{ + abstract class AccountId + { + public abstract string StringRepresentation { get; } + + public static Option Parse(string str) + => ReflectionUtils.ParseDerived(str); + + public abstract override bool Equals(object? obj); + + public abstract override int GetHashCode(); + + public override string ToString() => StringRepresentation; + + public static bool operator ==(AccountId a, AccountId b) + => a.Equals(b); + + public static bool operator !=(AccountId a, AccountId b) + => !(a == b); + } +} \ No newline at end of file diff --git a/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/AccountId/SteamId.cs b/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/AccountId/SteamId.cs new file mode 100644 index 000000000..5ae6f4fe5 --- /dev/null +++ b/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/AccountId/SteamId.cs @@ -0,0 +1,121 @@ +#nullable enable +using System; + +namespace Barotrauma.Networking +{ + sealed class SteamId : AccountId + { + public readonly UInt64 Value; + + public override string StringRepresentation { get; } + + /// Based on information found here: https://developer.valvesoftware.com/wiki/SteamID + /// ------------------------------------------------------------------------------------ + /// A SteamID is a 64-bit value (16 hexadecimal digits) that's broken up as follows: + /// + /// | a | b | c | d | + /// Most significant - | 01 | 1 | 00001 | 0546779D | - Least significant + /// + /// a) 8 bits representing the universe the account belongs to. + /// b) 4 bits representing the type of account. Typically 1. + /// c) 20 bits representing the instance of the account. Typically 1. + /// d) 32 bits representing the account number. + /// + /// The account number is additionally broken up as follows: + /// + /// | e | f | + /// Most significant - | 0000010101000110011101111001110 | 1 | - Least significant + /// + /// e) These are the 31 most significant bits of the account number. + /// f) This is the least significant bit of the account number, discriminated under the name Y for some reason. + /// + /// Barotrauma supports two textual representations of SteamIDs: + /// 1. STEAM40: Given this name as it represents 40 of the 64 bits in the ID. The account type and instance both + /// have an implied value of 1. The format is "STEAM_{universe}:{Y}:{restOfAccountNumber}". + /// 2. STEAM64: If STEAM40 does not suffice to represent an ID (i.e. the account type or instance were different + /// from 1), we use "STEAM64_{fullId}" where fullId is the 64-bit decimal representation of the full + /// ID. + + private const string steam64Prefix = "STEAM64_"; + private const string steam40Prefix = "STEAM_"; + + private const UInt64 usualAccountInstance = 1; + private const UInt64 usualAccountType = 1; + + static UInt64 ExtractBits(UInt64 id, int offset, int numberOfBits) + => (id >> offset) & ((1ul << numberOfBits) - 1ul); + + static UInt64 ExtractY(UInt64 id) + => ExtractBits(id, offset: 0, numberOfBits: 1); + static UInt64 ExtractAccountNumberRemainder(UInt64 id) + => ExtractBits(id, offset: 1, numberOfBits: 31); + static UInt64 ExtractAccountInstance(UInt64 id) + => ExtractBits(id, offset: 32, numberOfBits: 20); + static UInt64 ExtractAccountType(UInt64 id) + => ExtractBits(id, offset: 52, numberOfBits: 4); + static UInt64 ExtractUniverse(UInt64 id) + => ExtractBits(id, offset: 56, numberOfBits: 8); + + public SteamId(UInt64 value) + { + Value = value; + + if (ExtractAccountInstance(Value) == usualAccountInstance + && ExtractAccountType(Value) == usualAccountType) + { + UInt64 y = ExtractY(Value); + UInt64 accountNumberRemainder = ExtractAccountNumberRemainder(Value); + UInt64 universe = ExtractUniverse(Value); + StringRepresentation = $"{steam40Prefix}{universe}:{y}:{accountNumberRemainder}"; + } + else + { + StringRepresentation = $"{steam64Prefix}{Value}"; + } + } + + public override string ToString() => StringRepresentation; + + public new static Option Parse(string str) + { + if (str.IsNullOrWhiteSpace()) { return Option.None(); } + + if (str.StartsWith(steam64Prefix, StringComparison.InvariantCultureIgnoreCase)) { str = str[steam64Prefix.Length..]; } + if (UInt64.TryParse(str, out UInt64 retVal) && ExtractAccountInstance(retVal) > 0) + { + return Option.Some(new SteamId(retVal)); + } + + if (!str.StartsWith(steam40Prefix, StringComparison.InvariantCultureIgnoreCase)) { return Option.None(); } + string[] split = str[steam40Prefix.Length..].Split(':'); + if (split.Length != 3) { return Option.None(); } + + if (!UInt64.TryParse(split[0], out UInt64 universe)) { return Option.None(); } + if (!UInt64.TryParse(split[1], out UInt64 y)) { return Option.None(); } + if (!UInt64.TryParse(split[2], out UInt64 accountNumber)) { return Option.None(); } + + return Option.Some( + new SteamId((universe << 56) + | usualAccountType << 52 + | usualAccountInstance << 32 + | (accountNumber << 1) + | y)); + } + + public override bool Equals(object? obj) + => obj switch + { + SteamId otherId => this == otherId, + _ => false + }; + + public override int GetHashCode() + => Value.GetHashCode(); + + public static bool operator ==(SteamId a, SteamId b) + => a.Value == b.Value; + + public static bool operator !=(SteamId a, SteamId b) + => !(a == b); + } +} diff --git a/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/AccountInfo.cs b/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/AccountInfo.cs new file mode 100644 index 000000000..608486f0a --- /dev/null +++ b/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/AccountInfo.cs @@ -0,0 +1,50 @@ +#nullable enable +using System.Collections.Immutable; +using System.Linq; + +namespace Barotrauma.Networking +{ + [NetworkSerialize] + readonly struct AccountInfo : INetSerializableStruct + { + public static readonly AccountInfo None = new AccountInfo(Option.None()); + + /// + /// The primary ID for a given user + /// + public readonly Option AccountId; + + /// + /// Other user IDs that this user might be closely tied to, + /// such as the owner of the current copy of Barotrauma + /// + #warning TODO: make ImmutableArray once feature/inetserializablestruct-improvements gets merged to dev + public readonly AccountId[] OtherMatchingIds; + + public AccountInfo(AccountId accountId, params AccountId[] otherIds) : this(Option.Some(accountId), otherIds) { } + + public AccountInfo(Option accountId, params AccountId[] otherIds) + { + AccountId = accountId; + OtherMatchingIds = otherIds.Where(id => !accountId.ValueEquals(id)).ToArray(); + } + + public bool Matches(AccountId accountId) + => AccountId.ValueEquals(accountId) || OtherMatchingIds.Contains(accountId); + + public override bool Equals(object? obj) + => obj switch + { + AccountInfo otherInfo => AccountId == otherInfo.AccountId && OtherMatchingIds.All(otherInfo.OtherMatchingIds.Contains), + _ => false + }; + + public override int GetHashCode() + => AccountId.GetHashCode(); + + public static bool operator ==(AccountInfo a, AccountInfo b) + => a.Equals(b); + + public static bool operator !=(AccountInfo a, AccountInfo b) => !(a == b); + } +} \ No newline at end of file diff --git a/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/Address/Address.cs b/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/Address/Address.cs new file mode 100644 index 000000000..0724a0bca --- /dev/null +++ b/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/Address/Address.cs @@ -0,0 +1,26 @@ +#nullable enable + +namespace Barotrauma.Networking +{ + abstract class Address + { + public abstract string StringRepresentation { get; } + + public static Option
Parse(string str) + => ReflectionUtils.ParseDerived
(str); + + public abstract bool IsLocalHost { get; } + + public abstract override bool Equals(object? obj); + + public abstract override int GetHashCode(); + + public override string ToString() => StringRepresentation; + + public static bool operator ==(Address a, Address b) + => a.Equals(b); + + public static bool operator !=(Address a, Address b) + => !(a == b); + } +} diff --git a/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/Address/LidgrenAddress.cs b/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/Address/LidgrenAddress.cs new file mode 100644 index 000000000..3a724de81 --- /dev/null +++ b/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/Address/LidgrenAddress.cs @@ -0,0 +1,69 @@ +#nullable enable +using System; +using System.Linq; +using System.Net; +using System.Net.Sockets; + +namespace Barotrauma.Networking +{ + sealed class LidgrenAddress : Address + { + public readonly IPAddress NetAddress; + + public override string StringRepresentation + => NetAddress.ToString(); + + public override bool IsLocalHost => IPAddress.IsLoopback(NetAddress); + + public LidgrenAddress(IPAddress netAddress) + { + NetAddress = netAddress; + } + + public new static Option Parse(string endpointStr) + { + if (IPAddress.TryParse(endpointStr, out IPAddress? netEndpoint)) + { + return Option.Some(new LidgrenAddress(netEndpoint!)); + } + + try + { + var resolvedAddresses = Dns.GetHostAddresses(endpointStr); + return resolvedAddresses.Any() + ? Option.Some(new LidgrenAddress(resolvedAddresses.First())) + : Option.None(); + } + catch (SocketException) + { + return Option.None(); + } + catch (ArgumentOutOfRangeException) + { + return Option.None(); + } + } + + public override bool Equals(object? obj) + => obj switch + { + LidgrenAddress otherAddress => this == otherAddress, + _ => false + }; + + public override int GetHashCode() + => NetAddress.GetHashCode(); + + public static bool operator ==(LidgrenAddress a, LidgrenAddress b) + { + var addressA = a.NetAddress.MapToIPv6(); + var addressB = b.NetAddress.MapToIPv6(); + + if (IPAddress.IsLoopback(addressA) && IPAddress.IsLoopback(addressB)) { return true; } + return addressA.Equals(addressB); + } + + public static bool operator !=(LidgrenAddress a, LidgrenAddress b) + => !(a == b); + } +} diff --git a/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/Address/PipeAddress.cs b/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/Address/PipeAddress.cs new file mode 100644 index 000000000..1508dc239 --- /dev/null +++ b/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/Address/PipeAddress.cs @@ -0,0 +1,22 @@ +#nullable enable + +namespace Barotrauma.Networking +{ + sealed class PipeAddress : Address + { + public override string StringRepresentation => "PIPE"; + + public override bool IsLocalHost => true; + + public override bool Equals(object? obj) + => obj is PipeAddress; + + public override int GetHashCode() => 1; + + public static bool operator ==(PipeAddress a, PipeAddress b) + => true; + + public static bool operator !=(PipeAddress a, PipeAddress b) + => !(a == b); + } +} diff --git a/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/Address/SteamP2PAddress.cs b/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/Address/SteamP2PAddress.cs new file mode 100644 index 000000000..641815caa --- /dev/null +++ b/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/Address/SteamP2PAddress.cs @@ -0,0 +1,37 @@ +#nullable enable + +namespace Barotrauma.Networking +{ + sealed class SteamP2PAddress : Address + { + public readonly SteamId SteamId; + + public override string StringRepresentation => SteamId.StringRepresentation; + + public override bool IsLocalHost => false; + + public SteamP2PAddress(SteamId steamId) + { + SteamId = steamId; + } + + public new static Option Parse(string endpointStr) + => SteamId.Parse(endpointStr).Select(steamId => new SteamP2PAddress(steamId)); + + public override bool Equals(object? obj) + => obj switch + { + SteamP2PAddress otherAddress => this == otherAddress, + _ => false + }; + + public override int GetHashCode() + => SteamId.GetHashCode(); + + public static bool operator ==(SteamP2PAddress a, SteamP2PAddress b) + => a.SteamId == b.SteamId; + + public static bool operator !=(SteamP2PAddress a, SteamP2PAddress b) + => !(a == b); + } +} diff --git a/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/Address/UnknownAddress.cs b/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/Address/UnknownAddress.cs new file mode 100644 index 000000000..394d9c56d --- /dev/null +++ b/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/Address/UnknownAddress.cs @@ -0,0 +1,16 @@ +#nullable enable + +namespace Barotrauma.Networking +{ + sealed class UnknownAddress : Address + { + public override string StringRepresentation => "Hidden"; + + public override bool IsLocalHost => false; + + public override bool Equals(object? obj) + => ReferenceEquals(obj, this); + + public override int GetHashCode() => 1; + } +} diff --git a/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/Endpoint/Endpoint.cs b/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/Endpoint/Endpoint.cs new file mode 100644 index 000000000..6880848c4 --- /dev/null +++ b/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/Endpoint/Endpoint.cs @@ -0,0 +1,33 @@ +#nullable enable + +namespace Barotrauma.Networking +{ + abstract class Endpoint + { + public abstract string StringRepresentation { get; } + + public abstract LocalizedString ServerTypeString { get; } + + public readonly Address Address; + + public Endpoint(Address address) + { + Address = address; + } + + public abstract override bool Equals(object? obj); + + public abstract override int GetHashCode(); + + public override string ToString() => StringRepresentation; + + public static Option Parse(string str) + => ReflectionUtils.ParseDerived(str); + + public static bool operator ==(Endpoint a, Endpoint b) + => a.Equals(b); + + public static bool operator !=(Endpoint a, Endpoint b) + => !(a == b); + } +} diff --git a/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/Endpoint/LidgrenEndpoint.cs b/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/Endpoint/LidgrenEndpoint.cs new file mode 100644 index 000000000..32e85d169 --- /dev/null +++ b/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/Endpoint/LidgrenEndpoint.cs @@ -0,0 +1,63 @@ +#nullable enable +using System.Linq; +using System.Net; + +namespace Barotrauma.Networking +{ + sealed class LidgrenEndpoint : Endpoint + { + public readonly IPEndPoint NetEndpoint; + + public int Port => NetEndpoint.Port; + + public override string StringRepresentation + => NetEndpoint.ToString(); + + public override LocalizedString ServerTypeString { get; } = TextManager.Get("DedicatedServer"); + + public LidgrenEndpoint(IPAddress address, int port) : this(new IPEndPoint(address, port)) { } + + public LidgrenEndpoint(IPEndPoint netEndpoint) : base(new LidgrenAddress(netEndpoint.Address)) + { + NetEndpoint = netEndpoint; + } + + public new static Option Parse(string endpointStr) + { + if (IPEndPoint.TryParse(endpointStr, out IPEndPoint? netEndpoint)) + { + return Option.Some(new LidgrenEndpoint(netEndpoint!)); + } + + if (endpointStr.Count(c => c == ':') == 1) + { + string[] split = endpointStr.Split(':'); + string hostName = split[0]; + if (LidgrenAddress.Parse(hostName).TryUnwrap(out var adr) + && int.TryParse(split[1], out var port)) + { + return Option.Some(new LidgrenEndpoint(adr.NetAddress, port)); + } + } + + return LidgrenAddress.Parse(endpointStr) + .Select(adr => new LidgrenEndpoint(adr.NetAddress, NetConfig.DefaultPort)); + } + + public override bool Equals(object? obj) + => obj switch + { + LidgrenEndpoint otherEndpoint => this == otherEndpoint, + _ => false + }; + + public override int GetHashCode() + => NetEndpoint.GetHashCode(); + + public static bool operator ==(LidgrenEndpoint a, LidgrenEndpoint b) + => a.Address.Equals(b.Address) && a.Port == b.Port; + + public static bool operator !=(LidgrenEndpoint a, LidgrenEndpoint b) + => !(a == b); + } +} diff --git a/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/Endpoint/SteamP2PEndpoint.cs b/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/Endpoint/SteamP2PEndpoint.cs new file mode 100644 index 000000000..93c6fd1da --- /dev/null +++ b/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/Endpoint/SteamP2PEndpoint.cs @@ -0,0 +1,37 @@ +#nullable enable + +namespace Barotrauma.Networking +{ + sealed class SteamP2PEndpoint : Endpoint + { + public readonly SteamId SteamId; + + public override string StringRepresentation => SteamId.StringRepresentation; + + public override LocalizedString ServerTypeString { get; } = TextManager.Get("SteamP2PServer"); + + public SteamP2PEndpoint(SteamId steamId) : base(new SteamP2PAddress(steamId)) + { + SteamId = steamId; + } + + public new static Option Parse(string endpointStr) + => SteamId.Parse(endpointStr).Select(steamId => new SteamP2PEndpoint(steamId)); + + public override bool Equals(object? obj) + => obj switch + { + SteamP2PEndpoint otherEndpoint => this == otherEndpoint, + _ => false + }; + + public override int GetHashCode() + => SteamId.GetHashCode(); + + public static bool operator ==(SteamP2PEndpoint a, SteamP2PEndpoint b) + => a.SteamId == b.SteamId; + + public static bool operator !=(SteamP2PEndpoint a, SteamP2PEndpoint b) + => !(a == b); + } +} diff --git a/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/Message/IReadMessage.cs b/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/Message/IReadMessage.cs index f9e6b81a2..2bfc7eec4 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/Message/IReadMessage.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/Message/IReadMessage.cs @@ -4,11 +4,12 @@ using System.Text; namespace Barotrauma.Networking { - public interface IReadMessage + interface IReadMessage { bool ReadBoolean(); void ReadPadBits(); byte ReadByte(); + byte PeekByte(); UInt16 ReadUInt16(); Int16 ReadInt16(); UInt32 ReadUInt32(); diff --git a/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/Message/IWriteMessage.cs b/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/Message/IWriteMessage.cs index ae32f3bbc..65377a23f 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/Message/IWriteMessage.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/Message/IWriteMessage.cs @@ -2,7 +2,7 @@ namespace Barotrauma.Networking { - public interface IWriteMessage + interface IWriteMessage { void Write(bool val); void WritePadBits(); diff --git a/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/Message/Message.cs b/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/Message/Message.cs index 00711ed04..a05e67a59 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/Message/Message.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/Message/Message.cs @@ -11,7 +11,7 @@ namespace Barotrauma.Networking { public static class MsgConstants { - public const int MTU = 1200; + public const int MTU = 1200; //TODO: determine dynamically public const int CompressionThreshold = 1000; public const int InitialBufferSize = 256; public const int BufferOverAllocateAmount = 4; @@ -254,6 +254,12 @@ namespace Barotrauma.Networking return retval; } + internal static byte PeekByte(byte[] buf, ref int bitPos) + { + byte retval = NetBitWriter.ReadByte(buf, 8, bitPos); + return retval; + } + internal static UInt16 ReadUInt16(byte[] buf, ref int bitPos) { uint retval = NetBitWriter.ReadUInt16(buf, 16, bitPos); @@ -409,7 +415,7 @@ namespace Barotrauma.Networking } } - public class WriteOnlyMessage : IWriteMessage + class WriteOnlyMessage : IWriteMessage { private byte[] buf = new byte[MsgConstants.InitialBufferSize]; private int seekPos = 0; @@ -602,9 +608,9 @@ namespace Barotrauma.Networking } } - public class ReadOnlyMessage : IReadMessage + class ReadOnlyMessage : IReadMessage { - private byte[] buf; + private readonly byte[] buf; private int seekPos = 0; private int lengthBits = 0; @@ -720,6 +726,11 @@ namespace Barotrauma.Networking return MsgReader.ReadByte(buf, ref seekPos); } + public byte PeekByte() + { + return MsgReader.PeekByte(buf, ref seekPos); + } + public UInt16 ReadUInt16() { return MsgReader.ReadUInt16(buf, ref seekPos); @@ -801,7 +812,7 @@ namespace Barotrauma.Networking } } - public class ReadWriteMessage : IWriteMessage, IReadMessage + class ReadWriteMessage : IWriteMessage, IReadMessage { private byte[] buf; private int seekPos = 0; @@ -983,6 +994,11 @@ namespace Barotrauma.Networking return MsgReader.ReadByte(buf, ref seekPos); } + public byte PeekByte() + { + return MsgReader.PeekByte(buf, ref seekPos); + } + public UInt16 ReadUInt16() { return MsgReader.ReadUInt16(buf, ref seekPos); @@ -1067,5 +1083,6 @@ namespace Barotrauma.Networking { throw new InvalidOperationException("ReadWriteMessages are not to be sent"); } + } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/NetworkConnection/LidgrenConnection.cs b/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/NetworkConnection/LidgrenConnection.cs index f255de255..397f4836c 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/NetworkConnection/LidgrenConnection.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/NetworkConnection/LidgrenConnection.cs @@ -1,55 +1,14 @@ -using System; -using System.Net; -using Lidgren.Network; +using Lidgren.Network; namespace Barotrauma.Networking { - public class LidgrenConnection : NetworkConnection + sealed class LidgrenConnection : NetworkConnection { - public NetConnection NetConnection { get; private set; } + public readonly NetConnection NetConnection; - public IPEndPoint IPEndPoint => NetConnection.RemoteEndPoint; - - public string IPString + public LidgrenConnection(NetConnection netConnection) : base(new LidgrenEndpoint(netConnection.RemoteEndPoint)) { - get - { - return IPEndPoint.Address.IsIPv4MappedToIPv6 ? IPEndPoint.Address.MapToIPv4NoThrow().ToString() : IPEndPoint.Address.ToString(); - } - } - - public UInt16 Port - { - get - { - return (UInt16)IPEndPoint.Port; - } - } - - public LidgrenConnection(string name, NetConnection netConnection, UInt64 steamId) - { - Name = name; NetConnection = netConnection; - SteamID = steamId; - EndPointString = IPString; - } - - public override bool SetSteamIDIfUnknown(UInt64 id) - { - if (SteamID != 0) { return false; } //do not allow the SteamID to be set multiple times - SteamID = id; - return true; - } - - public override bool EndpointMatches(string endPoint) - { - if (IPEndPoint?.Address == null) { return false; } - if (!IPAddress.TryParse(endPoint, out IPAddress addr)) { return false; } - - IPAddress ip1 = IPEndPoint.Address.IsIPv4MappedToIPv6 ? IPEndPoint.Address.MapToIPv4() : IPEndPoint.Address; - IPAddress ip2 = addr.IsIPv4MappedToIPv6 ? addr.MapToIPv4() : addr; - - return ip1.ToString() == ip2.ToString(); } } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/NetworkConnection/NetworkConnection.cs b/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/NetworkConnection/NetworkConnection.cs index f78e60edd..e1a46e55d 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/NetworkConnection/NetworkConnection.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/NetworkConnection/NetworkConnection.cs @@ -8,57 +8,37 @@ namespace Barotrauma.Networking Disconnected = 0x2 } - public abstract class NetworkConnection + abstract class NetworkConnection { public const double TimeoutThreshold = 60.0; //full minute for timeout because loading screens can take quite a while public const double TimeoutThresholdInGame = 10.0; - public string Name; + public AccountInfo AccountInfo { get; private set; } = AccountInfo.None; - public UInt64 SteamID - { - get; - protected set; - } - - public UInt64 OwnerSteamID - { - get; - protected set; - } - - public string EndPointString - { - get; - protected set; - } + public readonly Endpoint Endpoint; + [Obsolete("TODO: this doesn't belong in layer 1")] public LanguageIdentifier Language { get; set; } - public abstract bool EndpointMatches(string endPoint); + public NetworkConnection(Endpoint endpoint) + { + Endpoint = endpoint; + } + + public bool EndpointMatches(Endpoint endPoint) + => Endpoint == endPoint; public NetworkConnectionStatus Status = NetworkConnectionStatus.Disconnected; - public virtual bool SetSteamIDIfUnknown(UInt64 id) + public void SetAccountInfo(AccountInfo newInfo) { - //by default, don't allow setting the ID, this is only done - //with Lidgren connections since those are initialized before - //the SteamID can be known; it's set once the Steam auth ticket - //is received by the server. - return false; - } - - public bool SetOwnerSteamIDIfUnknown(UInt64 id) - { - //we know that for both Lidgren and SteamP2P, the - //owner id isn't known until the auth ticket is - //processed, so this method is the same for both - if (OwnerSteamID != 0) { return false; } - OwnerSteamID = id; - return true; + AccountInfo = newInfo; } + + public sealed override string ToString() + => Endpoint.StringRepresentation; } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/NetworkConnection/PipeConnection.cs b/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/NetworkConnection/PipeConnection.cs index ef2fee23c..bae9ac6e8 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/NetworkConnection/PipeConnection.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/NetworkConnection/PipeConnection.cs @@ -1,19 +1,33 @@ -using Barotrauma.Steam; +#nullable enable using System; namespace Barotrauma.Networking { - public class PipeConnection : NetworkConnection + sealed class PipeEndpoint : Endpoint { - public PipeConnection(ulong steamId) - { - EndPointString = "PIPE"; - SteamID = steamId; - } + public override string StringRepresentation => "PIPE"; + + public override LocalizedString ServerTypeString => throw new InvalidOperationException(); - public override bool EndpointMatches(string endPoint) + public PipeEndpoint() : base(new PipeAddress()) { } + + public override bool Equals(object? obj) + => obj is PipeEndpoint; + + public override int GetHashCode() => 1; + + public static bool operator ==(PipeEndpoint a, PipeEndpoint b) + => true; + + public static bool operator !=(PipeEndpoint a, PipeEndpoint b) + => !(a == b); + } + + sealed class PipeConnection : NetworkConnection + { + public PipeConnection(AccountId accountId) : base(new PipeEndpoint()) { - return SteamManager.SteamIDStringToUInt64(endPoint) == SteamID || endPoint == "PIPE"; + SetAccountInfo(new AccountInfo(Option.Some(accountId))); } } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/NetworkConnection/SteamP2PConnection.cs b/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/NetworkConnection/SteamP2PConnection.cs index 7e70ad98b..425e1bfd4 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/NetworkConnection/SteamP2PConnection.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/NetworkConnection/SteamP2PConnection.cs @@ -1,18 +1,13 @@ -using Barotrauma.Steam; -using System; - -namespace Barotrauma.Networking +namespace Barotrauma.Networking { - public class SteamP2PConnection : NetworkConnection + sealed class SteamP2PConnection : NetworkConnection { public double Timeout = 0.0; - public SteamP2PConnection(string name, UInt64 steamId) + public SteamP2PConnection(SteamId steamId) : this(new SteamP2PEndpoint(steamId)) { } + + public SteamP2PConnection(SteamP2PEndpoint endpoint) : base(endpoint) { - SteamID = steamId; - OwnerSteamID = 0; - EndPointString = SteamManager.SteamIDUInt64ToString(SteamID); - Name = name; Heartbeat(); } @@ -25,10 +20,5 @@ namespace Barotrauma.Networking { Timeout = TimeoutThreshold; } - - public override bool EndpointMatches(string endPoint) - { - return SteamManager.SteamIDStringToUInt64(endPoint) == SteamID; - } } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Networking/RespawnManager.cs b/Barotrauma/BarotraumaShared/SharedSource/Networking/RespawnManager.cs index c282b31f2..1f1c31596 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Networking/RespawnManager.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Networking/RespawnManager.cs @@ -269,6 +269,7 @@ namespace Barotrauma.Networking #endif } } + respawnItems.Clear(); foreach (Structure wall in Structure.WallList) { diff --git a/Barotrauma/BarotraumaShared/SharedSource/Networking/ServerSettings.cs b/Barotrauma/BarotraumaShared/SharedSource/Networking/ServerSettings.cs index ec76db8e0..e626f1c23 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Networking/ServerSettings.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Networking/ServerSettings.cs @@ -70,27 +70,18 @@ namespace Barotrauma.Networking public class SavedClientPermission { - public readonly string EndPoint; - public readonly ulong SteamID; + public readonly Either AddressOrAccountId; public readonly string Name; - public HashSet PermittedCommands; + public readonly ImmutableHashSet PermittedCommands; - public ClientPermissions Permissions; + public readonly ClientPermissions Permissions; - public SavedClientPermission(string name, string endpoint, ClientPermissions permissions, HashSet permittedCommands) + public SavedClientPermission(string name, Either addressOrAccountId, ClientPermissions permissions, IEnumerable permittedCommands) { this.Name = name; - this.EndPoint = endpoint; + this.AddressOrAccountId = addressOrAccountId; this.Permissions = permissions; - this.PermittedCommands = permittedCommands; - } - public SavedClientPermission(string name, ulong steamID, ClientPermissions permissions, HashSet permittedCommands) - { - this.Name = name; - this.SteamID = steamID; - - this.Permissions = permissions; - this.PermittedCommands = permittedCommands; + this.PermittedCommands = permittedCommands.ToImmutableHashSet(); } } @@ -279,7 +270,6 @@ namespace Barotrauma.Networking { ServerLog = new ServerLog(serverName); - Whitelist = new WhiteList(); BanList = new BanList(); ExtraCargo = new Dictionary(); @@ -398,8 +388,6 @@ namespace Barotrauma.Networking public List ClientPermissions { get; private set; } = new List(); - public WhiteList Whitelist { get; private set; } - [Serialize(20, IsPropertySaveable.Yes)] public int TickRate { diff --git a/Barotrauma/BarotraumaShared/SharedSource/Networking/Voip/VoipQueue.cs b/Barotrauma/BarotraumaShared/SharedSource/Networking/Voip/VoipQueue.cs index 7c24c7f02..29411143a 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Networking/Voip/VoipQueue.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Networking/Voip/VoipQueue.cs @@ -1,12 +1,8 @@ using System; -using System.Collections.Generic; -using System.Text; -using Microsoft.Xna.Framework; namespace Barotrauma.Networking { - - public class VoipQueue : IDisposable + class VoipQueue : IDisposable { public const int BUFFER_COUNT = 8; protected int[] bufferLengths; diff --git a/Barotrauma/BarotraumaShared/SharedSource/Networking/Voting.cs b/Barotrauma/BarotraumaShared/SharedSource/Networking/Voting.cs index 5fd149b62..e26cb7e62 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Networking/Voting.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Networking/Voting.cs @@ -8,7 +8,7 @@ namespace Barotrauma { public enum VoteState { None = 0, Started = 1, Running = 2, Passed = 3, Failed = 4 }; - private IReadOnlyDictionary GetVoteCounts(VoteType voteType, List voters) + private IReadOnlyDictionary GetVoteCounts(VoteType voteType, IEnumerable voters) { Dictionary voteList = new Dictionary(); @@ -57,7 +57,7 @@ namespace Barotrauma return selected; } - public void ResetVotes(List connectedClients) + public void ResetVotes(IEnumerable connectedClients) { foreach (Client client in connectedClients) { diff --git a/Barotrauma/BarotraumaShared/SharedSource/Physics/Physics.cs b/Barotrauma/BarotraumaShared/SharedSource/Physics/Physics.cs index 79e8f0e01..69232df45 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Physics/Physics.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Physics/Physics.cs @@ -19,7 +19,9 @@ namespace Barotrauma public static float DisplayToRealWorldRatio = 1.0f / 100.0f; - public const float DisplayToSimRation = 100.0f; + public const float DisplayToSimRation = 100.0f; + + public const float NeutralDensity = 10.0f; public static bool TryParseCollisionCategory(string categoryName, out Category category) { diff --git a/Barotrauma/BarotraumaShared/SharedSource/Physics/PhysicsBody.cs b/Barotrauma/BarotraumaShared/SharedSource/Physics/PhysicsBody.cs index 95ce1d5c7..ee9831e4d 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Physics/PhysicsBody.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Physics/PhysicsBody.cs @@ -369,7 +369,7 @@ namespace Barotrauma float radius = ConvertUnits.ToSimUnits(colliderParams.Radius) * colliderParams.Ragdoll.LimbScale; float height = ConvertUnits.ToSimUnits(colliderParams.Height) * colliderParams.Ragdoll.LimbScale; float width = ConvertUnits.ToSimUnits(colliderParams.Width) * colliderParams.Ragdoll.LimbScale; - density = 10; + density = Physics.NeutralDensity; CreateBody(width, height, radius, density, BodyType.Dynamic, Physics.CollisionCharacter, Physics.CollisionWall | Physics.CollisionLevel, @@ -417,7 +417,7 @@ namespace Barotrauma float radius = ConvertUnits.ToSimUnits(element.GetAttributeFloat("radius", 0.0f)) * scale; float height = ConvertUnits.ToSimUnits(element.GetAttributeFloat("height", 0.0f)) * scale; float width = ConvertUnits.ToSimUnits(element.GetAttributeFloat("width", 0.0f)) * scale; - density = Math.Max(forceDensity ?? element.GetAttributeFloat("density", 10.0f), MinDensity); + density = Math.Max(forceDensity ?? element.GetAttributeFloat("density", Physics.NeutralDensity), MinDensity); Enum.TryParse(element.GetAttributeString("bodytype", "Dynamic"), out BodyType bodyType); CreateBody(width, height, radius, density, bodyType, collisionCategory, collidesWith, findNewContacts); _collisionCategories = collisionCategory; diff --git a/Barotrauma/BarotraumaShared/SharedSource/Serialization/XMLExtensions.cs b/Barotrauma/BarotraumaShared/SharedSource/Serialization/XMLExtensions.cs index 89c8bc1bd..ee27a296b 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Serialization/XMLExtensions.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Serialization/XMLExtensions.cs @@ -394,25 +394,6 @@ namespace Barotrauma return val; } - public static UInt64 GetAttributeSteamID(this XElement element, string name, UInt64 defaultValue) - { - var attribute = element?.GetAttribute(name); - if (attribute == null) { return defaultValue; } - - UInt64 val = defaultValue; - - try - { - val = Steam.SteamManager.SteamIDStringToUInt64(attribute.Value); - } - catch (Exception e) - { - DebugConsole.ThrowError("Error in " + element + "! ", e); - } - - return val; - } - public static int[] GetAttributeIntArray(this XElement element, string name, int[] defaultValue) { var attribute = element?.GetAttribute(name); diff --git a/Barotrauma/BarotraumaShared/SharedSource/StatusEffects/DelayedEffect.cs b/Barotrauma/BarotraumaShared/SharedSource/StatusEffects/DelayedEffect.cs index 94e6c7bef..ebd8a0b36 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/StatusEffects/DelayedEffect.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/StatusEffects/DelayedEffect.cs @@ -119,6 +119,8 @@ namespace Barotrauma if (!HasRequiredConditions(currentTargets)) { return; } + if (Entity.Spawner != null && Entity.Spawner.IsInRemoveQueue(entity)) { return; } + switch (delayType) { case DelayTypes.Timer: diff --git a/Barotrauma/BarotraumaShared/SharedSource/StatusEffects/StatusEffect.cs b/Barotrauma/BarotraumaShared/SharedSource/StatusEffects/StatusEffect.cs index 71b24e12a..29f5fe5ba 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/StatusEffects/StatusEffect.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/StatusEffects/StatusEffect.cs @@ -8,7 +8,6 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; using System.Xml.Linq; -using Barotrauma.Networking; namespace Barotrauma { @@ -158,11 +157,11 @@ namespace Barotrauma ///
public readonly bool SpawnIfCantBeContained; public readonly float Impulse; - public readonly float Rotation; + public readonly float RotationRad; public readonly int Count; public readonly float Spread; public readonly SpawnRotationType RotationType; - public readonly float AimSpread; + public readonly float AimSpreadRad; public readonly bool Equip; public readonly float Condition; @@ -198,14 +197,14 @@ namespace Barotrauma SpawnIfInventoryFull = element.GetAttributeBool("spawnifinventoryfull", false); SpawnIfCantBeContained = element.GetAttributeBool("spawnifcantbecontained", true); - Impulse = element.GetAttributeFloat("impulse", element.GetAttributeFloat("speed", 0.0f)); + Impulse = element.GetAttributeFloat("impulse", element.GetAttributeFloat("launchimpulse", element.GetAttributeFloat("speed", 0.0f))); Condition = MathHelper.Clamp(element.GetAttributeFloat("condition", 1.0f), 0.0f, 1.0f); - Rotation = element.GetAttributeFloat("rotation", 0.0f); + RotationRad = MathHelper.ToRadians(element.GetAttributeFloat("rotation", 0.0f)); Count = element.GetAttributeInt("count", 1); Spread = element.GetAttributeFloat("spread", 0f); - AimSpread = element.GetAttributeFloat("aimspread", 0f); + AimSpreadRad = MathHelper.ToRadians(element.GetAttributeFloat("aimspread", 0f)); Equip = element.GetAttributeBool("equip", false); string spawnTypeStr = element.GetAttributeString("spawnposition", "This"); @@ -213,7 +212,7 @@ namespace Barotrauma { DebugConsole.ThrowError("Error in StatusEffect config - \"" + spawnTypeStr + "\" is not a valid spawn position."); } - string rotationTypeStr = element.GetAttributeString("rotationtype", Rotation != 0 ? "Fixed" : "Target"); + string rotationTypeStr = element.GetAttributeString("rotationtype", RotationRad != 0 ? "Fixed" : "Target"); if (!Enum.TryParse(rotationTypeStr, ignoreCase: true, out RotationType)) { DebugConsole.ThrowError("Error in StatusEffect config - \"" + rotationTypeStr + "\" is not a valid rotation type."); @@ -1668,11 +1667,11 @@ namespace Barotrauma Character.Controlled = newCharacter; } #elif SERVER - foreach (Client c in GameMain.Server.ConnectedClients) + /*foreach (Client c in GameMain.Server.ConnectedClients) { if (c.Character != target) { continue; } GameMain.Server.SetClientCharacter(c, newCharacter); - } + }*/ #endif } if (characterSpawnInfo.RemovePreviousCharacter) { Entity.Spawner?.AddEntityToRemoveQueue(character); } @@ -1705,92 +1704,101 @@ namespace Barotrauma case ItemSpawnInfo.SpawnPositionType.This: Entity.Spawner.AddItemToSpawnQueue(chosenItemSpawnInfo.ItemPrefab, position + Rand.Vector(chosenItemSpawnInfo.Spread, Rand.RandSync.Unsynced), onSpawned: newItem => { + Item parentItem = entity as Item; Projectile projectile = newItem.GetComponent(); - if (projectile != null && user != null && sourceBody != null && entity != null) + if (entity != null) { var rope = newItem.GetComponent(); - if (rope != null && sourceBody.UserData is Limb sourceLimb) + if (rope != null && sourceBody != null && sourceBody.UserData is Limb sourceLimb) { rope.Attach(sourceLimb, newItem); #if SERVER newItem.CreateServerEvent(rope); #endif } - float spread = MathHelper.ToRadians(Rand.Range(-chosenItemSpawnInfo.AimSpread, chosenItemSpawnInfo.AimSpread)); - var worldPos = sourceBody.Position; - float rotation = 0; - if (user.Submarine != null) + float spread = Rand.Range(-chosenItemSpawnInfo.AimSpreadRad, chosenItemSpawnInfo.AimSpreadRad); + float rotation = chosenItemSpawnInfo.RotationRad; + Vector2 worldPos; + if (sourceBody != null) { - worldPos += user.Submarine.Position; + worldPos = sourceBody.Position; + if (user?.Submarine != null) + { + worldPos += user.Submarine.Position; + } + } + else + { + worldPos = entity.WorldPosition; } switch (chosenItemSpawnInfo.RotationType) { case ItemSpawnInfo.SpawnRotationType.Fixed: - rotation = sourceBody.TransformRotation(chosenItemSpawnInfo.Rotation); + if (sourceBody != null) + { + rotation = sourceBody.TransformRotation(chosenItemSpawnInfo.RotationRad); + } + else if (parentItem?.body != null) + { + rotation = parentItem.body.TransformRotation(chosenItemSpawnInfo.RotationRad); + } break; case ItemSpawnInfo.SpawnRotationType.Target: rotation = MathUtils.VectorToAngle(entity.WorldPosition - worldPos); break; case ItemSpawnInfo.SpawnRotationType.Limb: - rotation = sourceBody.TransformedRotation; + if (sourceBody != null) + { + rotation = sourceBody.TransformedRotation; + } break; case ItemSpawnInfo.SpawnRotationType.Collider: - rotation = user.AnimController.Collider.Rotation + MathHelper.PiOver2; + if (parentItem?.body != null) + { + rotation = parentItem.body.Rotation; + } + else if (user != null) + { + rotation = user.AnimController.Collider.Rotation + MathHelper.PiOver2; + } break; case ItemSpawnInfo.SpawnRotationType.MainLimb: - rotation = user.AnimController.MainLimb.body.TransformedRotation; + if (user != null) + { + rotation = user.AnimController.MainLimb.body.TransformedRotation; + } break; case ItemSpawnInfo.SpawnRotationType.Random: - DebugConsole.ShowError("Random rotation is not supported for Projectiles."); + if (projectile != null) + { + DebugConsole.ShowError("Random rotation is not supported for Projectiles."); + } + else + { + rotation = Rand.Range(0f, MathHelper.TwoPi, Rand.RandSync.Unsynced); + } break; default: - throw new NotImplementedException("Projectile spawn rotation type not implemented: " + chosenItemSpawnInfo.RotationType); + throw new NotImplementedException("Item spawn rotation type not implemented: " + chosenItemSpawnInfo.RotationType); } - rotation += MathHelper.ToRadians(chosenItemSpawnInfo.Rotation * user.AnimController.Dir); - projectile.Shoot(user, ConvertUnits.ToSimUnits(worldPos), ConvertUnits.ToSimUnits(worldPos), rotation + spread, ignoredBodies: user.AnimController.Limbs.Where(l => !l.IsSevered).Select(l => l.body.FarseerBody).ToList(), createNetworkEvent: true); - } - else - { - var body = newItem.body; - if (body != null) + if (user != null) { - float rotation = MathHelper.ToRadians(chosenItemSpawnInfo.Rotation); - switch (chosenItemSpawnInfo.RotationType) - { - case ItemSpawnInfo.SpawnRotationType.Fixed: - if (sourceBody != null) - { - rotation = sourceBody.TransformRotation(chosenItemSpawnInfo.Rotation); - } - break; - case ItemSpawnInfo.SpawnRotationType.Limb: - if (sourceBody != null) - { - rotation += sourceBody.Rotation; - } - break; - case ItemSpawnInfo.SpawnRotationType.Collider: - if (entity is Character character) - { - rotation += character.AnimController.Collider.Rotation + MathHelper.PiOver2; - } - break; - case ItemSpawnInfo.SpawnRotationType.MainLimb: - if (entity is Character c) - { - rotation = c.AnimController.MainLimb.body.TransformedRotation; - } - break; - case ItemSpawnInfo.SpawnRotationType.Random: - rotation = Rand.Range(0f, MathHelper.TwoPi, Rand.RandSync.Unsynced); - break; - case ItemSpawnInfo.SpawnRotationType.Target: - break; - default: - throw new NotImplementedException("Spawn rotation type not implemented: " + chosenItemSpawnInfo.RotationType); - } - body.SetTransform(newItem.SimPosition, rotation); - body.ApplyLinearImpulse(Rand.Vector(1) * chosenItemSpawnInfo.Impulse); + rotation += chosenItemSpawnInfo.RotationRad * user.AnimController.Dir; + } + rotation += spread; + if (projectile != null) + { + projectile.Shoot(user, + ConvertUnits.ToSimUnits(worldPos), + ConvertUnits.ToSimUnits(worldPos), + rotation, + ignoredBodies: user?.AnimController.Limbs.Where(l => !l.IsSevered).Select(l => l.body.FarseerBody).ToList(), createNetworkEvent: true); + } + else if (newItem.body != null) + { + newItem.body.SetTransform(newItem.SimPosition, rotation); + Vector2 impulseDir = new Vector2(MathF.Cos(rotation), MathF.Sin(rotation)); + newItem.body.ApplyLinearImpulse(impulseDir * chosenItemSpawnInfo.Impulse); } } newItem.Condition = newItem.MaxCondition * chosenItemSpawnInfo.Condition; @@ -2082,7 +2090,7 @@ namespace Barotrauma if (!MathUtils.NearlyEqual(afflictionMultiplier, 1.0f)) { - return affliction.CreateMultiplied(afflictionMultiplier); + return affliction.CreateMultiplied(afflictionMultiplier, affliction.Probability); } return affliction; } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Steam/SteamManager.cs b/Barotrauma/BarotraumaShared/SharedSource/Steam/SteamManager.cs index ca1a02271..5eb17570d 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Steam/SteamManager.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Steam/SteamManager.cs @@ -2,6 +2,7 @@ using Steamworks.Data; using System; using System.Collections.Generic; using System.Linq; +using Barotrauma.Networking; namespace Barotrauma.Steam { @@ -42,14 +43,14 @@ namespace Barotrauma.Steam InitializeProjectSpecific(); } - public static ulong GetSteamID() + public static Option GetSteamId() { if (!IsInitialized || !Steamworks.SteamClient.IsValid) { - return 0; + return Option.None(); } - return Steamworks.SteamClient.SteamId; + return Option.Some(new SteamId(Steamworks.SteamClient.SteamId)); } public static bool IsFamilyShared() @@ -249,37 +250,5 @@ namespace Barotrauma.Steam return 0; } - - public static UInt64 SteamIDStringToUInt64(string str) - { - if (string.IsNullOrWhiteSpace(str)) { return 0; } - UInt64 retVal; - if (str.StartsWith("STEAM64_", StringComparison.InvariantCultureIgnoreCase)) { str = str.Substring(8); } - if (UInt64.TryParse(str, out retVal) && retVal > (1 << 52)) { return retVal; } - if (!str.StartsWith("STEAM_", StringComparison.InvariantCultureIgnoreCase)) { return 0; } - string[] split = str.Substring(6).Split(':'); - if (split.Length != 3) { return 0; } - - if (!UInt64.TryParse(split[0], out UInt64 universe)) { return 0; } - if (!UInt64.TryParse(split[1], out UInt64 y)) { return 0; } - if (!UInt64.TryParse(split[2], out UInt64 accountNumber)) { return 0; } - - UInt64 accountInstance = 1; UInt64 accountType = 1; - - return (universe << 56) | (accountType << 52) | (accountInstance << 32) | (accountNumber << 1) | y; - } - - public static string SteamIDUInt64ToString(UInt64 uint64) - { - UInt64 y = uint64 & 0x1; - UInt64 accountNumber = (uint64 >> 1) & 0x7fffffff; - UInt64 universe = (uint64 >> 56) & 0xff; - - string retVal = "STEAM_" + universe.ToString() + ":" + y.ToString() + ":" + accountNumber.ToString(); - - if (SteamIDStringToUInt64(retVal) != uint64) { return "STEAM64_" + uint64.ToString(); } - - return retVal; - } } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Text/RichString.cs b/Barotrauma/BarotraumaShared/SharedSource/Text/RichString.cs index 7a710827c..f370ddd71 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Text/RichString.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Text/RichString.cs @@ -181,7 +181,7 @@ namespace Barotrauma public static bool operator !=(string? a, RichString? b) => !(a == b); } - public class StripRichTagsLString : LocalizedString + class StripRichTagsLString : LocalizedString { public readonly RichString RichStr; diff --git a/Barotrauma/BarotraumaShared/SharedSource/Utils/Either.cs b/Barotrauma/BarotraumaShared/SharedSource/Utils/Either.cs index 2f24d0601..740abe381 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Utils/Either.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Utils/Either.cs @@ -1,8 +1,9 @@ +#nullable enable using System; namespace Barotrauma { - public abstract class Either + public abstract class Either where T : notnull where U : notnull { public static implicit operator Either(T t) => new EitherT(t); public static implicit operator Either(U u) => new EitherU(u); @@ -15,22 +16,32 @@ namespace Barotrauma public abstract bool TryCast(out V v); - public abstract override string ToString(); + public abstract override string? ToString(); + + public abstract override bool Equals(object? obj); + + public abstract override int GetHashCode(); + + public static bool operator ==(Either? a, Either? b) + => a is null ? b is null : a.Equals(b); + + public static bool operator !=(Either? a, Either? b) + => !(a == b); } - public sealed class EitherT : Either + public sealed class EitherT : Either where T : notnull where U : notnull { public readonly T Value; public EitherT(T value) { Value = value; } - public override string ToString() + public override string? ToString() { return Value.ToString(); } public override bool TryGet(out T t) { t = Value; return true; } - public override bool TryGet(out U u) { u = default; return false; } + public override bool TryGet(out U u) { u = default!; return false; } public override bool TryCast(out V v) { @@ -41,24 +52,34 @@ namespace Barotrauma } else { - v = default; + v = default!; return false; } } + + public override bool Equals(object? obj) + => obj switch + { + EitherT other => Value.Equals(other.Value), + T value => Value.Equals(value), + _ => false + }; + + public override int GetHashCode() => Value.GetHashCode(); } - public sealed class EitherU : Either + public sealed class EitherU : Either where T : notnull where U : notnull { public readonly U Value; public EitherU(U value) { Value = value; } - public override string ToString() + public override string? ToString() { return Value.ToString(); } - public override bool TryGet(out T t) { t = default; return false; } + public override bool TryGet(out T t) { t = default!; return false; } public override bool TryGet(out U u) { u = Value; return true; } public override bool TryCast(out V v) @@ -70,9 +91,19 @@ namespace Barotrauma } else { - v = default; + v = default!; return false; } } + + public override bool Equals(object? obj) + => obj switch + { + EitherU other => Value.Equals(other.Value), + U value => Value.Equals(value), + _ => false + }; + + public override int GetHashCode() => Value.GetHashCode(); } } \ No newline at end of file diff --git a/Barotrauma/BarotraumaShared/SharedSource/Utils/Option/None.cs b/Barotrauma/BarotraumaShared/SharedSource/Utils/Option/None.cs index 08631f611..db6e813b9 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Utils/Option/None.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Utils/Option/None.cs @@ -5,5 +5,13 @@ namespace Barotrauma private None() { } public static Option Create() => new None(); + + public override Option Fallback(Option fallback) => fallback; + public override T Fallback(T fallback) => fallback; + + public override bool ValueEquals(T value) => false; + + public override string ToString() + => $"None<{typeof(T).Name}>"; } } \ No newline at end of file diff --git a/Barotrauma/BarotraumaShared/SharedSource/Utils/Option/Option.cs b/Barotrauma/BarotraumaShared/SharedSource/Utils/Option/Option.cs index 73c6d6860..30a219a32 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Utils/Option/Option.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Utils/Option/Option.cs @@ -1,3 +1,4 @@ +#nullable enable using System; namespace Barotrauma @@ -23,7 +24,7 @@ namespace Barotrauma outValue = value; return true; case None _: - outValue = default; + outValue = default!; return false; default: throw new ArgumentOutOfRangeException(); @@ -37,5 +38,30 @@ namespace Barotrauma None _ => Option.None(), _ => throw new ArgumentOutOfRangeException() }; + + public abstract Option Fallback(Option fallback); + public abstract T Fallback(T fallback); + + public abstract bool ValueEquals(T value); + + public override bool Equals(object? obj) + => obj switch + { + Some { Value: var value } => this is Some { Value: { } selfValue } && selfValue.Equals(value), + None _ => IsNone(), + T value => this is Some { Value: { } selfValue } && selfValue.Equals(value), + _ => false + }; + + public override int GetHashCode() + => this is Some { Value: { } value } ? value.GetHashCode() : 0; + + public static bool operator ==(Option a, Option b) + => a.Equals(b); + + public static bool operator !=(Option a, Option b) + => !(a == b); + + public abstract override string ToString(); } } \ No newline at end of file diff --git a/Barotrauma/BarotraumaShared/SharedSource/Utils/Option/Some.cs b/Barotrauma/BarotraumaShared/SharedSource/Utils/Option/Some.cs index fad94a2a7..5fd1dc3b0 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Utils/Option/Some.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Utils/Option/Some.cs @@ -13,5 +13,13 @@ namespace Barotrauma } public static Option Create(T value) => new Some(value); + + public override Option Fallback(Option fallback) => this; + public override T Fallback(T fallback) => Value; + + public override bool ValueEquals(T value) => Value.Equals(value); + + public override string ToString() + => $"Some<{typeof(T).Name}>({Value})"; } } \ No newline at end of file diff --git a/Barotrauma/BarotraumaShared/SharedSource/Utils/ReflectionUtils.cs b/Barotrauma/BarotraumaShared/SharedSource/Utils/ReflectionUtils.cs index eb17b94a8..e02fe1c68 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Utils/ReflectionUtils.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Utils/ReflectionUtils.cs @@ -1,5 +1,7 @@ +#nullable enable using System; using System.Collections.Generic; +using System.Collections.Immutable; using System.Linq; using System.Reflection; @@ -7,14 +9,52 @@ namespace Barotrauma { public static class ReflectionUtils { - private static Type[] cachedNonAbstractTypes; + private static readonly Dictionary> cachedNonAbstractTypes + = new Dictionary>(); + public static IEnumerable GetDerivedNonAbstract() { - if (cachedNonAbstractTypes == null) + Assembly assembly = typeof(T).Assembly; + if (!cachedNonAbstractTypes.ContainsKey(assembly)) { - cachedNonAbstractTypes = Assembly.GetEntryAssembly().GetTypes().Where(t => !t.IsAbstract).ToArray(); + cachedNonAbstractTypes[assembly] = assembly.GetTypes() + .Where(t => !t.IsAbstract).ToImmutableArray(); } - return cachedNonAbstractTypes.Where(t => t.IsSubclassOf(typeof(T))); + return cachedNonAbstractTypes[assembly].Where(t => t.IsSubclassOf(typeof(T))); + } + + public static Option ParseDerived(string str) + { + static Option none() => Option.None(); + + var derivedTypes = GetDerivedNonAbstract(); + + Option parseOfType(Type t) + { + //every T1 type is expected to have a method with the following signature: + // public static Option Parse(string str) + var parseFunc = t.GetMethod("Parse", BindingFlags.Public | BindingFlags.Static); + if (parseFunc is null) { return none(); } + + var parameters = parseFunc.GetParameters(); + if (parameters.Length != 1) { return none(); } + + var returnType = parseFunc.ReturnType; + if (!returnType.IsConstructedGenericType) { return none(); } + if (returnType.GetGenericTypeDefinition() != typeof(Option<>)) { return none(); } + if (returnType.GenericTypeArguments[0] != t) { return none(); } + + //some hacky business to convert from Option to Option when we only know T2 at runtime + static Option convert(Option option) where T2 : T1 + => option.Select(v => (T1)v); + Func, Option> f = convert; + var constructedConverter = f.Method.GetGenericMethodDefinition().MakeGenericMethod(typeof(T1), t); + + return constructedConverter.Invoke(null, new object?[] { parseFunc.Invoke(null, new object[] { str }) }) + as Option ?? none(); + } + + return derivedTypes.Select(parseOfType).FirstOrDefault(t => t.IsSome()) ?? none(); } } } \ No newline at end of file diff --git a/Barotrauma/BarotraumaShared/SharedSource/Utils/SafeIO.cs b/Barotrauma/BarotraumaShared/SharedSource/Utils/SafeIO.cs index 651f13975..1a2e8968c 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Utils/SafeIO.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Utils/SafeIO.cs @@ -4,8 +4,10 @@ using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; +#if CLIENT using Barotrauma.Networking; using Barotrauma.Steam; +#endif namespace Barotrauma.IO { diff --git a/Barotrauma/BarotraumaShared/SharedSource/Utils/ToolBox.cs b/Barotrauma/BarotraumaShared/SharedSource/Utils/ToolBox.cs index 9922dc37f..e7a38ef78 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Utils/ToolBox.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Utils/ToolBox.cs @@ -26,14 +26,14 @@ namespace Barotrauma } } - public static partial class ToolBox + static partial class ToolBox { - static internal class Epoch + internal static class Epoch { private static readonly DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); /// - /// Returns the current Unix Epoch (Coordinated Universal Time ) + /// Returns the current Unix Epoch (Coordinated Universal Time) /// public static int NowUTC { @@ -712,5 +712,10 @@ namespace Barotrauma return e; } + + public static void ThrowIfNull(T o) + { + if (o is null) { throw new ArgumentNullException(); } + } } } diff --git a/Barotrauma/BarotraumaShared/changelog.txt b/Barotrauma/BarotraumaShared/changelog.txt index d3ba6592d..3b27b64c9 100644 --- a/Barotrauma/BarotraumaShared/changelog.txt +++ b/Barotrauma/BarotraumaShared/changelog.txt @@ -1,3 +1,86 @@ +--------------------------------------------------------------------------------------------------------- +v0.19.1.0 +--------------------------------------------------------------------------------------------------------- + +Unstable only: +- Option to lock or reset draggable item UIs. +- Force item UI layout update when resolution changes. Fixes item repositioned item UIs potentially getting left outside the window when switching to a smaller resolution. +- Item UIs can't be dragged under each other. +- Fixed dragging a wire in a connection panel dragging the panel too if you bring the cursor close to the edges of the panel. +- Fixed seated bots being unable to get up from the chair. +- Fixed some more unwired lights in ResearchModule_02_Colony. +- Fixed another minor gap issue in Winterhalter. +- Fixed hull/item repairs and the money spent on them appearing to reset if you join mid-round after repairs have been purchased. +- Fixed light source staying in place after detaching a glowing item (e.g. mineral) from a wall. +- Fixed server trying to place all previously spawned respawn items into containers on every respawn, even if the items have already been removed. Happened because we never cleared respawnItems, and because we used that list when placing new respawn items into containers. + +Changes and additions: +- Overvoltage makes devices perform better, increasing the output of engines, making fabricators, deconstructors and fabricators operate faster, electrical discharge coils do more damage and oxygen generators generate more oxygen. Incentivizes operating the reactor manually and hopefully makes it a little more engaging. +- Added more randomness to junction box overvoltage damage, and made partially damaged boxes take more damage from overvoltage. Prevents all boxes from breaking at the same time, making overvoltage less of a pain in the ass to deal with and intentionally overvolting the devices more worthwhile. +- Experimental: Added a way to immediately increase/decrease the temperatureof the reactor for a brief amount of time (atm bumps the gauge up/down by a fifth, and the boost fades out in 20 seconds). Allows reacting to load fluctuations very quickly, and to conserve fuel by operating the reactor at a lower fission rate = serves as another incentive to operate it manually. +- Signals no longer set the fission and turbine rates of the reactor instantaneously, making automated reactor circuits less overpowered. They are still viable, but especially now with the addition of the extra incentives for operating the reactor manually, they're no longer as clearly the best and most efficient way to operate the reactor, making manual operation more worthwhile. +- Added a Large Weapon Hardpoint. +- Railgun is now considered a large weapon. +- Added Flak Cannon and Double Coilgun as large weapons. +- Pulse Laser and Railgun now have similar power consumption as other turrets. +- Improved the way drag is applied on submerged items. Fixes heavy items dropping at unnaturally high speeds in water. +- Added a splash effect when an item falls into water. + +Balance: +- Reduced the pulse laser tri-laser bolt spread. +- Explosions are now calculated differently, using the number of limbs to divide the damage (to a max of 15 limbs). Adjusted explosion damage values to match new calculations. +- Coilgun costs 5000 to install, Pulse Laser and Chaingun 6000. Large turrets all cost 7500. +- Make mudraptor eggs slightly viable for farming (decreased cost from shop, increased deconstruction yields) +- Mineral yield and spawn rates rebalance, minerals found are now much more dependant on location (biome, cave, abyss) + +Submarines: +- Added a new intermediate transport sub, Camel. Still WIP, but feedback is welcome. +- Fixed messy wiring in Typhon 2's bottom left hardpoint. +- Added some loose vents and panels to Herja, Winterhalter and Barsuk, fixed invisible "loose panel" (news stand) in Orca 2. + +Fixes: +- Fixed brief freezes when monsters spawn mid-round. +- Fixed vitality modifiers not being taken into account in the readings in the health interface. For example, gunshot wounds on the head cause a x2 larger vitality drop than on other limbs, but this wasn't displayed on the health interface. +- Fixed Planet Neon Sign sprite bleed. +- Fixed Grenade Launcher quality doing basically nothing, because it increased the minuscule amount of blunt force trauma the grenade causes on impact instead of the explosion damage. +- Fixed level resource spawn rate not properly respecting level generations parameters' resource spawn chance values. +- Fixed some text overflows in the hiring menu when using a small HUD scale. +- Fixed name on an ID card resetting to the original name if you rename a character and then start a new round. +- Fixed handcuffs in the backmost hand being drawn in front of the character. +- Fixed water splashes appearing in an incorrect hull when a character's limb moves from a flooded hull to another hull, where the limb is no longer underwater. +- Fixed crashing when a signal causes a wired item to get dropped (e.g. when you attach a detonator to a destructible ice wall and blow it up). +- Oxygen generators and shelves don't fill up oxygen tanks when on fire. Caused repeated explosions when the tank constantly refilled and re-exploded. +- Fixed "gene harvester" and "deep sea slayer" working on all enemies, not just monsters. +- Fixed floating point inaccuracy sometimes preventing items from being used as fabrication ingredients (e.g. oxygen generator may sometimes only fill tanks up to something like 99.9998%, which prevented it from being used in recipes that require a full tank). +- Fixed item picking timer (e.g. detaching an item from a wall) ticking down when the game is paused. +- Fixed outpost supply cabs missing the oxygen tank spawns. +- Made the water current outside the levels start from the same point where monsters start heading towards the level, to make sure monsters can't escape too far from sub with a weak engine. +- Fixed hardened diving knife recipe. +- Fixed probability multiplier not being shown in wearable tooltip if the damage multiplier is 1. +- Yet another attempt to prevent beacon missions from failing for apparently no reason: sonar monitors won't get damaged by water after the beacon's been activated. +- Don't stop selecting text in a textbox if the cursor goes outside the box. + +Multiplayer: +- Fixed clients getting stuck in the loading screen if they happen to disconnect at the right moment between rounds. +- Fixed bank balance not getting corrected if it's gotten desynced by e.g. client-side commands. +- Fixed server not registering a client's character as disconnected if the client disconnects and reconnects before the round has fully started, causing the client to get stuck as a spectator when they rejoin. +- Fixed clients disabling their client-side-only mods when they join a server. +- Fixed hull/item repairs purchased from an outpost sometimes not getting applied client-side. + +Submarine editor: +- Fixed prefab placement breaking in the sub editor if LMB is held while moving the cursor outside of the selection panel. +- Fixed several instances of janky UI interactions in the submarine editor: dragging selection rectangle now works even if cursor reaches into the prefab list, letting go of a dragged entity works even if cursor reaches into the prefab list, dragged entity no longer goes invisible when reaching into the prefab list. +- Made PowerContainer recharge speed always default to 0. +- Fixed adding resizeable items (like ladders) not being registered in sub editor's command history, preventing undoing it. + +Modding: +- Added DamageMultiplier and LaunchImpulse to Turret. LaunchImpulse is now defined on turrets instead of ammunition (total impulse is the sum of turret + ammunition). +- Added SnapRopeOnNewAttack property to Attacks: allows characters to switch attacks without snapping ropes from previous attacks. +- Added dividebylimbcount to Explosion, which determines whether the damage is spread out among limbs (if set to true). +- UpgradeCategories with no upgrades in them are hidden from the upgrade menu (i.e. if you modify the upgrades so some of the vanilla categories no longer contain any upgrades, those categories won't be shown). +- Fixed affliction names and descriptions being empty if they're not available in the selected language nor configured in the affliction xml directly. +- Fix custom infected husks seeking for any husk infection targeting the matching species instead of checking that also the husk affliction prefab matches the husk. + --------------------------------------------------------------------------------------------------------- v0.19.0.0 --------------------------------------------------------------------------------------------------------- @@ -35,6 +118,8 @@ Balance: - Adjusted supplies in pirate submarines. - Turn some weapons' burn damage into explosion damage (wip). - Terminal ignores empty signals. +- Reduce commonness of Molochs (as they can take a lot of time to kill, running into multiple of them can quickly become a chore) +- Remove steel requirement for depth charges. Fabricate decoy depth charges from depth charge, rather than base material. Multiplayer: - Clients who've recently joined (by default 2 minutes) are not allowed to vote to kick others, and vote kicking someone always requires at least 2 votes. From 0a45e81c836379a2ba70c8644e9320e0d71e6fce Mon Sep 17 00:00:00 2001 From: Joonas Rikkonen Date: Sat, 20 Aug 2022 11:36:40 +0300 Subject: [PATCH 03/11] Update bug_report.yml --- .github/ISSUE_TEMPLATE/bug_report.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 78ce050fd..9e14f5ba4 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -52,7 +52,8 @@ body: label: Version description: Which version of the game did the bug happen in? You can see the current version number in the bottom left corner of your screen in the main menu. options: - - 0.18.15.0 + - 0.18.15.1 + - 0.19.1.0 (unstable) - Other validations: required: true From 975d9b2e3d272d6e2a4166f4670b4b5d7c84d532 Mon Sep 17 00:00:00 2001 From: Joonas Rikkonen Date: Fri, 26 Aug 2022 16:51:56 +0300 Subject: [PATCH 04/11] Update bug_report.yml --- .github/ISSUE_TEMPLATE/bug_report.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 9e14f5ba4..375fc0bf6 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -52,8 +52,8 @@ body: label: Version description: Which version of the game did the bug happen in? You can see the current version number in the bottom left corner of your screen in the main menu. options: - - 0.18.15.1 - - 0.19.1.0 (unstable) + - 0.18.15.1 / 0.18.15.2 on macOS + - 0.19.2.0 (unstable) - Other validations: required: true From af4b63519bce52396333fc93f9e0ffec31ff6f9d Mon Sep 17 00:00:00 2001 From: Joonas Rikkonen Date: Fri, 2 Sep 2022 20:28:47 +0300 Subject: [PATCH 05/11] Update bug_report.yml --- .github/ISSUE_TEMPLATE/bug_report.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 375fc0bf6..ca60d65a8 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -53,7 +53,7 @@ body: description: Which version of the game did the bug happen in? You can see the current version number in the bottom left corner of your screen in the main menu. options: - 0.18.15.1 / 0.18.15.2 on macOS - - 0.19.2.0 (unstable) + - 0.19.3.0 (unstable) - Other validations: required: true From 3f2c843247af9dae62cbecc7f29aed67a95c0bb7 Mon Sep 17 00:00:00 2001 From: Juan Pablo Arce Date: Fri, 2 Sep 2022 15:10:56 -0300 Subject: [PATCH 06/11] Unstable v0.19.3.0 --- .../BarotraumaClient/ClientSource/Camera.cs | 6 +- .../Characters/CharacterNetworking.cs | 16 +- .../ContentPackage/ModProject.cs | 2 +- .../ClientSource/DebugConsole.cs | 12 +- .../Events/EventActions/ConversationAction.cs | 12 +- .../Events/Missions/CombatMission.cs | 6 +- .../ClientSource/Events/Missions/Mission.cs | 4 + .../ClientSource/GUI/ChatBox.cs | 35 +- .../ClientSource/GUI/CrewManagement.cs | 22 +- .../BarotraumaClient/ClientSource/GUI/GUI.cs | 8 + .../ClientSource/GUI/GUIComponent.cs | 7 +- .../ClientSource/GUI/GUIDragHandle.cs | 2 + .../ClientSource/GUI/GUIListBox.cs | 6 +- .../ClientSource/GUI/GUIMessageBox.cs | 99 ++- .../ClientSource/GUI/GUIStyle.cs | 18 +- .../ClientSource/GUI/GUITextBlock.cs | 2 +- .../ClientSource/GUI/HUDLayoutSettings.cs | 31 +- .../ClientSource/GUI/SubmarineSelection.cs | 15 +- .../ClientSource/GUI/TabMenu.cs | 12 +- .../ClientSource/GUI/UpgradeStore.cs | 83 +- .../ClientSource/GUI/VideoPlayer.cs | 4 +- .../BarotraumaClient/ClientSource/GameMain.cs | 2 + .../ClientSource/GameSession/CrewManager.cs | 5 +- .../GameModes/MultiPlayerCampaign.cs | 28 +- .../GameModes/SinglePlayerCampaign.cs | 33 +- .../GameModes/Tutorials/CaptainTutorial.cs | 346 -------- .../GameModes/Tutorials/DoctorTutorial.cs | 521 ------------ .../GameModes/Tutorials/EngineerTutorial.cs | 664 --------------- .../GameModes/Tutorials/MechanicTutorial.cs | 737 ----------------- .../GameModes/Tutorials/OfficerTutorial.cs | 526 ------------ .../GameModes/Tutorials/ScenarioTutorial.cs | 307 ------- .../GameModes/Tutorials/Tutorial.cs | 780 ++++++++++++------ .../GameModes/Tutorials/TutorialMode.cs | 7 +- .../ClientSource/GameSession/MedicalClinic.cs | 4 +- .../ClientSource/GameSession/ReadyCheck.cs | 16 +- .../ClientSource/Items/Components/Growable.cs | 4 +- .../Items/Components/Holdable/Holdable.cs | 4 +- .../Items/Components/ItemComponent.cs | 14 +- .../Items/Components/ItemContainer.cs | 2 + .../Items/Components/LightComponent.cs | 2 +- .../Components/Machines/Deconstructor.cs | 31 +- .../Items/Components/Machines/Fabricator.cs | 147 ++-- .../Items/Components/Machines/MiniMap.cs | 2 +- .../Items/Components/Machines/Pump.cs | 2 +- .../Items/Components/Machines/Reactor.cs | 59 +- .../Items/Components/Machines/Sonar.cs | 38 +- .../Items/Components/Machines/Steering.cs | 69 +- .../Items/Components/Power/Powered.cs | 6 +- .../Items/Components/Repairable.cs | 2 +- .../Items/Components/Signal/ButtonTerminal.cs | 1 - .../Items/Components/Signal/Connection.cs | 8 +- .../Components/Signal/ConnectionPanel.cs | 13 +- .../Components/Signal/CustomInterface.cs | 12 +- .../Items/Components/Signal/Terminal.cs | 2 +- .../Items/Components/Signal/Wire.cs | 6 +- .../ClientSource/Items/DockingPort.cs | 2 +- .../ClientSource/Items/Item.cs | 11 +- .../ClientSource/Items/ItemPrefab.cs | 2 +- .../BarotraumaClient/ClientSource/Map/Hull.cs | 2 +- .../ClientSource/Map/MapEntity.cs | 9 + .../ClientSource/Map/Structure.cs | 11 - .../ClientSource/Map/StructurePrefab.cs | 5 +- .../ClientSource/Map/SubmarineInfo.cs | 21 +- .../ClientSource/Map/SubmarinePreview.cs | 3 +- .../ClientSource/Networking/BanList.cs | 37 +- .../ClientSource/Networking/ChatMessage.cs | 6 +- .../Networking/FileTransfer/FileReceiver.cs | 50 +- .../ClientSource/Networking/GameClient.cs | 300 ++++--- .../ClientEntityEventManager.cs | 2 +- .../NetEntityEvent/NetEntityEvent.cs | 2 +- .../Networking/OrderChatMessage.cs | 4 +- .../Networking/Primitives/Peers/ClientPeer.cs | 179 ++-- .../Primitives/Peers/LidgrenClientPeer.cs | 177 ++-- .../Primitives/Peers/SteamP2PClientPeer.cs | 308 ++++--- .../Primitives/Peers/SteamP2POwnerPeer.cs | 447 +++++----- .../ClientSource/Networking/RespawnManager.cs | 9 +- .../ClientSource/Networking/ServerInfo.cs | 2 +- .../ClientSource/Networking/ServerSettings.cs | 30 +- .../Networking/Voip/VoipCapture.cs | 32 +- .../Networking/Voip/VoipClient.cs | 4 +- .../ClientSource/Networking/Voting.cs | 28 +- .../ClientSource/Networking/WhiteList.cs | 245 ------ .../CampaignSetupUI/CampaignSetupUI.cs | 8 +- .../MultiPlayerCampaignSetupUI.cs | 13 +- .../SinglePlayerCampaignSetupUI.cs | 24 +- .../Screens/EventEditor/EventEditorScreen.cs | 4 +- .../ClientSource/Screens/MainMenuScreen.cs | 47 +- .../ClientSource/Screens/ModDownloadScreen.cs | 4 +- .../ClientSource/Screens/NetLobbyScreen.cs | 84 +- .../ClientSource/Screens/SubEditorScreen.cs | 42 +- .../ClientSource/Settings/SettingsMenu.cs | 2 +- .../ClientSource/Sounds/SoundPlayer.cs | 2 +- .../BarotraumaClient/LinuxClient.csproj | 16 +- Barotrauma/BarotraumaClient/MacClient.csproj | 5 +- .../BarotraumaClient/WindowsClient.csproj | 5 +- .../BarotraumaServer/LinuxServer.csproj | 16 +- Barotrauma/BarotraumaServer/MacServer.csproj | 5 +- .../ServerSource/Characters/CharacterInfo.cs | 32 +- .../Characters/CharacterNetworking.cs | 212 ++--- .../ServerSource/DebugConsole.cs | 35 +- .../Events/EventActions/ConversationAction.cs | 36 +- .../Events/EventActions/StatusEffectAction.cs | 12 +- .../Missions/AbandonedOutpostMission.cs | 10 +- .../Events/Missions/AlienRuinMission.cs | 6 +- .../Events/Missions/CargoMission.cs | 2 +- .../Events/Missions/CombatMission.cs | 13 +- .../Events/Missions/EscortMission.cs | 6 +- .../Events/Missions/MineralMission.cs | 14 +- .../ServerSource/Events/Missions/Mission.cs | 8 +- .../Events/Missions/MonsterMission.cs | 2 +- .../Events/Missions/NestMission.cs | 8 +- .../Events/Missions/PirateMission.cs | 4 +- .../Events/Missions/SalvageMission.cs | 10 +- .../Events/Missions/ScanMission.cs | 8 +- .../ServerSource/GameSession/CrewManager.cs | 6 +- .../GameModes/MultiPlayerCampaign.cs | 150 ++-- .../ServerSource/GameSession/MedicalClinic.cs | 6 +- .../ServerSource/GameSession/ReadyCheck.cs | 42 +- .../Items/Components/DockingPort.cs | 6 +- .../ServerSource/Items/Components/Door.cs | 12 +- .../Items/Components/GeneticMaterial.cs | 6 +- .../ServerSource/Items/Components/Growable.cs | 8 +- .../Items/Components/Holdable/Holdable.cs | 10 +- .../Components/Holdable/LevelResource.cs | 2 +- .../Items/Components/ItemLabel.cs | 2 +- .../Items/Components/LightComponent.cs | 2 +- .../Items/Components/Machines/Controller.cs | 4 +- .../Components/Machines/Deconstructor.cs | 6 +- .../Items/Components/Machines/Engine.cs | 2 +- .../Items/Components/Machines/Fabricator.cs | 12 +- .../Items/Components/Machines/Pump.cs | 10 +- .../Items/Components/Machines/Reactor.cs | 4 +- .../Items/Components/Machines/Steering.cs | 24 +- .../Items/Components/Projectile.cs | 34 +- .../Items/Components/Repairable.cs | 14 +- .../ServerSource/Items/Components/Rope.cs | 16 +- .../ServerSource/Items/Components/Scanner.cs | 2 +- .../Components/Signal/ConnectionPanel.cs | 2 +- .../Components/Signal/CustomInterface.cs | 6 +- .../Components/Signal/MemoryComponent.cs | 2 +- .../Items/Components/Signal/Terminal.cs | 4 +- .../Items/Components/Signal/Wire.cs | 4 +- .../ServerSource/Items/Item.cs | 96 +-- .../ServerSource/Levels/Level.cs | 10 +- .../Map/Creatures/BallastFloraBehavior.cs | 36 +- .../BarotraumaServer/ServerSource/Map/Hull.cs | 4 +- .../ServerSource/Map/Structure.cs | 2 +- .../ServerSource/Map/Submarine.cs | 6 +- .../ServerSource/Networking/BanList.cs | 146 ++-- .../ServerSource/Networking/ChatMessage.cs | 22 +- .../ServerSource/Networking/Client.cs | 79 +- .../ServerSource/Networking/EntitySpawner.cs | 8 +- .../Networking/FileTransfer/FileSender.cs | 32 +- .../ServerSource/Networking/GameServer.cs | 322 ++++---- .../ServerEntityEventManager.cs | 10 +- .../Networking/OrderChatMessage.cs | 16 +- .../Peers/Server/LidgrenServerPeer.cs | 256 +++--- .../Primitives/Peers/Server/ServerPeer.cs | 178 ++-- .../Peers/Server/SteamP2PServerPeer.cs | 204 ++--- .../ServerSource/Networking/RespawnManager.cs | 27 +- .../ServerSource/Networking/ServerSettings.cs | 47 +- .../Networking/Voip/VoipServer.cs | 4 +- .../ServerSource/Networking/Voting.cs | 66 +- .../ServerSource/Networking/WhiteList.cs | 207 ----- .../ServerSource/Physics/PhysicsBody.cs | 8 +- .../Traitors/TraitorMissionResult.cs | 10 +- .../BarotraumaServer/WindowsServer.csproj | 5 +- .../DeployGameAnalytics.props | 2 +- .../Characters/AI/EnemyAIController.cs | 2 +- .../Characters/AI/Objectives/AIObjective.cs | 10 + .../AI/Objectives/AIObjectiveCombat.cs | 9 +- .../AI/Objectives/AIObjectiveContainItem.cs | 17 +- .../AI/Objectives/AIObjectiveDecontainItem.cs | 8 +- .../AI/Objectives/AIObjectiveFixLeak.cs | 2 +- .../AI/Objectives/AIObjectiveGetItem.cs | 16 +- .../AI/Objectives/AIObjectiveGetItems.cs | 4 +- .../AI/Objectives/AIObjectiveIdle.cs | 7 +- .../Characters/AI/Wreck/WreckAI.cs | 2 +- .../Animation/HumanoidAnimController.cs | 80 +- .../SharedSource/Characters/Character.cs | 4 +- .../SharedSource/Characters/CharacterInfo.cs | 4 +- .../Characters/Health/CharacterHealth.cs | 12 +- .../SharedSource/Characters/HumanPrefab.cs | 6 +- .../AbilityConditionAboveVitality.cs | 6 +- .../AbilityConditionAlliesAboveVitality.cs | 3 +- .../AbilityConditionCoauthor.cs | 5 +- .../AbilityConditionCrouched.cs | 5 +- .../AbilityConditionHasAffliction.cs | 16 +- .../AbilityConditionHasItem.cs | 42 +- .../AbilityConditionHasVelocity.cs | 5 +- .../AbilityConditionShipFlooded.cs | 15 +- .../CharacterAbilityModifyStatToFlooding.cs | 15 +- .../Abilities/CharacterAbilityUnlockTree.cs | 21 +- .../CharacterAbilityInsurancePolicy.cs | 12 +- .../AbilityGroups/CharacterAbilityGroup.cs | 8 +- .../Characters/Talents/TalentTree.cs | 55 +- .../ContentFile/TutorialsFile.cs | 16 + .../SharedSource/DebugConsole.cs | 111 +-- .../EventActions/CheckAfflictionAction.cs | 10 +- .../EventActions/CheckConditionalAction.cs | 71 ++ .../Events/EventActions/CheckOrderAction.cs | 59 ++ .../Events/EventActions/MessageBoxAction.cs | 116 +++ .../Events/EventActions/MissionAction.cs | 6 +- .../Events/EventActions/SpawnAction.cs | 14 + .../Events/EventActions/TagAction.cs | 9 +- .../EventActions/TutorialCompleteAction.cs | 32 + .../EventActions/TutorialSegmentAction.cs | 95 +++ .../Events/EventActions/UnlockPathAction.cs | 6 +- .../Events/Missions/CombatMission.cs | 1 + .../Events/Missions/MineralMission.cs | 112 ++- .../SharedSource/Events/Missions/Mission.cs | 6 +- .../SharedSource/GameSession/CrewManager.cs | 6 + .../GameModes/MultiPlayerCampaign.cs | 26 +- .../GameSession/GameModes/PvPMode.cs | 44 +- .../GameModes/Tutorials/TutorialPrefab.cs | 73 ++ .../SharedSource/GameSession/GameSession.cs | 6 +- .../GameSession/UpgradeManager.cs | 65 +- .../SharedSource/InputType.cs | 1 + .../Items/Components/DockingPort.cs | 2 +- .../SharedSource/Items/Components/Growable.cs | 32 +- .../Items/Components/Holdable/MeleeWeapon.cs | 15 +- .../Items/Components/Holdable/Pickable.cs | 2 +- .../Items/Components/ItemComponent.cs | 11 +- .../Items/Components/ItemContainer.cs | 4 +- .../Components/Machines/Deconstructor.cs | 8 +- .../Items/Components/Machines/Fabricator.cs | 20 +- .../Items/Components/Machines/Reactor.cs | 11 +- .../Items/Components/Machines/Sonar.cs | 28 +- .../Items/Components/Machines/Steering.cs | 2 - .../Components/Signal/ConnectionPanel.cs | 6 +- .../Components/Signal/CustomInterface.cs | 31 +- .../Items/Components/Signal/LightComponent.cs | 10 +- .../Items/Components/Signal/RelayComponent.cs | 2 +- .../SharedSource/Items/Components/Turret.cs | 11 +- .../SharedSource/Items/Components/Wearable.cs | 2 +- .../SharedSource/Items/Inventory.cs | 4 +- .../SharedSource/Items/Item.cs | 58 +- .../SharedSource/Items/ItemPrefab.cs | 83 +- .../SharedSource/Items/RelatedItem.cs | 49 +- .../BarotraumaShared/SharedSource/Map/Gap.cs | 19 +- .../BarotraumaShared/SharedSource/Map/Hull.cs | 10 +- .../SharedSource/Map/Levels/Level.cs | 145 ++-- .../SharedSource/Map/LinkedSubmarine.cs | 24 +- .../SharedSource/Map/MapEntity.cs | 12 +- .../SharedSource/Map/Structure.cs | 51 +- .../SharedSource/Map/StructurePrefab.cs | 23 +- .../SharedSource/Map/Submarine.cs | 24 +- .../SharedSource/Map/SubmarineBody.cs | 11 +- .../SharedSource/Map/SubmarineInfo.cs | 40 +- .../SharedSource/NetStructBitField.cs | 2 +- .../SharedSource/Networking/BanList.cs | 3 +- .../Networking/ChildServerRelay.cs | 13 +- .../SharedSource/Networking/Client.cs | 48 +- .../Networking/INetSerializableStruct.cs | 64 +- .../Networking/NetBufferExtensions.cs | 15 - .../NetEntityEvent/NetEntityEventManager.cs | 12 +- .../SharedSource/Networking/NetIdUtils.cs | 13 + .../Networking/OrderChatMessage.cs | 36 +- .../Primitives/Message/IWriteMessage.cs | 28 +- .../Networking/Primitives/Message/Message.cs | 393 ++++----- .../Primitives/{Enums.cs => NetworkEnums.cs} | 1 + .../Primitives/NetworkExtensions.cs | 68 ++ .../Primitives/NetworkPeerStructs.cs | 142 ++++ .../SharedSource/Networking/RespawnManager.cs | 5 + .../SharedSource/Networking/ServerSettings.cs | 72 +- .../SharedSource/Networking/Voip/VoipQueue.cs | 8 +- .../SharedSource/Networking/WhiteList.cs | 37 - .../Serialization/SerializableProperty.cs | 9 +- .../Serialization/XMLExtensions.cs | 16 +- .../SharedSource/Settings/GameSettings.cs | 63 +- .../StatusEffects/StatusEffect.cs | 17 +- .../SharedSource/Steam/SteamManager.cs | 2 +- .../Text/LocalizedString/InputTypeLString.cs | 18 +- .../SharedSource/Text/TextManager.cs | 4 +- .../SharedSource/Upgrades/Upgrade.cs | 151 ++-- .../SharedSource/Upgrades/UpgradePrefab.cs | 147 +++- .../SharedSource/Utils/IPExtensions.cs | 21 - .../SharedSource/Utils/SafeIO.cs | 14 +- .../SharedSource/Utils/SaveUtil.cs | 137 ++- .../SharedSource/Utils/ToolBox.cs | 14 +- Barotrauma/BarotraumaShared/changelog.txt | 146 +++- .../BarotraumaTest/CommonnessInfoTests.cs | 84 ++ .../BarotraumaTest/EndpointComparisonTests.cs | 15 + .../BarotraumaTest/EndpointParseTests.cs | 67 ++ ...tSerializableStructImplementationChecks.cs | 55 ++ .../INetSerializableStructTests.cs | 104 ++- Barotrauma/BarotraumaTest/NetIdUtilsTests.cs | 20 + BuildScripts/app_1026340.vdf | 15 + BuildScripts/app_602960.vdf | 16 + Deploy/DeployAll.bat | 4 + Deploy/DeployAll.sh | 4 + Deploy/DeployAll/DeployAll.csproj | 22 + Deploy/DeployAll/Deployables.cs | 111 +++ Deploy/DeployAll/DotnetCmd.cs | 123 +++ Deploy/DeployAll/GitCmd.cs | 86 ++ Deploy/DeployAll/Program.cs | 58 ++ Deploy/DeployAll/SteamPipeAssistant.cs | 248 ++++++ Deploy/DeployAll/Util.cs | 106 +++ .../Contents/Resources/barotrauma.icns | Bin 0 -> 3672382 bytes .../Barotrauma.app/Contents/info.plist | 36 + .../Barotrauma.app/installscript.vdf | 31 + Deploy/Linux/DeployLinux.sh | 10 - Deploy/Linux/DeployLinuxServer.sh | 4 - Deploy/Linux/DeployLinuxUnstable.sh | 10 - Deploy/Linux/DeployMac.sh | 10 - Deploy/Linux/DeployMacUnstable.sh | 10 - Deploy/Linux/DeployWindows.sh | 10 - Deploy/Linux/DeployWindowsUnstable.sh | 10 - Deploy/ManualScripts/Linux/DeployLinux.sh | 10 + .../ManualScripts/Linux/DeployLinuxServer.sh | 4 + .../Linux/DeployLinuxUnstable.sh | 10 + Deploy/ManualScripts/Linux/DeployMac.sh | 10 + .../ManualScripts/Linux/DeployMacUnstable.sh | 10 + Deploy/ManualScripts/Linux/DeployWindows.sh | 10 + .../Linux/DeployWindowsUnstable.sh | 10 + .../SteamPipeBuildScripts/app_1026340.vdf | 15 + .../SteamPipeBuildScripts/app_602960.vdf | 16 + .../SteamPipeBuildScripts}/depot_1026341.vdf | 0 .../SteamPipeBuildScripts}/depot_1026342.vdf | 0 .../SteamPipeBuildScripts}/depot_602961.vdf | 0 .../SteamPipeBuildScripts}/depot_602962.vdf | 0 .../SteamPipeBuildScripts}/depot_602963.vdf | 0 Deploy/ManualScripts/Windows/DeployLinux.bat | 12 + .../Windows/DeployLinuxUnstable.bat | 12 + Deploy/ManualScripts/Windows/DeployMac.bat | 12 + .../Windows/DeployMacUnstable.bat | 12 + .../ManualScripts/Windows/DeployWindows.bat | 12 + .../Windows/DeployWindowsServer.bat | 6 + .../Windows/DeployWindowsUnstable.bat | 12 + Deploy/Windows/DeployLinux.bat | 12 - Deploy/Windows/DeployLinuxUnstable.bat | 12 - Deploy/Windows/DeployMac.bat | 12 - Deploy/Windows/DeployMacUnstable.bat | 12 - Deploy/Windows/DeployWindows.bat | 12 - Deploy/Windows/DeployWindowsServer.bat | 6 - Deploy/Windows/DeployWindowsUnstable.bat | 12 - 336 files changed, 7152 insertions(+), 7739 deletions(-) delete mode 100644 Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/CaptainTutorial.cs delete mode 100644 Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/DoctorTutorial.cs delete mode 100644 Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/EngineerTutorial.cs delete mode 100644 Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/MechanicTutorial.cs delete mode 100644 Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/OfficerTutorial.cs delete mode 100644 Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/ScenarioTutorial.cs delete mode 100644 Barotrauma/BarotraumaClient/ClientSource/Networking/WhiteList.cs delete mode 100644 Barotrauma/BarotraumaServer/ServerSource/Networking/WhiteList.cs create mode 100644 Barotrauma/BarotraumaShared/SharedSource/ContentManagement/ContentFile/TutorialsFile.cs create mode 100644 Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/CheckConditionalAction.cs create mode 100644 Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/CheckOrderAction.cs create mode 100644 Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/MessageBoxAction.cs create mode 100644 Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/TutorialCompleteAction.cs create mode 100644 Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/TutorialSegmentAction.cs create mode 100644 Barotrauma/BarotraumaShared/SharedSource/GameSession/GameModes/Tutorials/TutorialPrefab.cs delete mode 100644 Barotrauma/BarotraumaShared/SharedSource/Networking/NetBufferExtensions.cs rename Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/{Enums.cs => NetworkEnums.cs} (98%) create mode 100644 Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/NetworkExtensions.cs create mode 100644 Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/NetworkPeerStructs.cs delete mode 100644 Barotrauma/BarotraumaShared/SharedSource/Networking/WhiteList.cs delete mode 100644 Barotrauma/BarotraumaShared/SharedSource/Utils/IPExtensions.cs create mode 100644 Barotrauma/BarotraumaTest/CommonnessInfoTests.cs create mode 100644 Barotrauma/BarotraumaTest/EndpointComparisonTests.cs create mode 100644 Barotrauma/BarotraumaTest/EndpointParseTests.cs create mode 100644 Barotrauma/BarotraumaTest/INetSerializableStructImplementationChecks.cs create mode 100644 Barotrauma/BarotraumaTest/NetIdUtilsTests.cs create mode 100644 BuildScripts/app_1026340.vdf create mode 100644 BuildScripts/app_602960.vdf create mode 100644 Deploy/DeployAll.bat create mode 100644 Deploy/DeployAll.sh create mode 100644 Deploy/DeployAll/DeployAll.csproj create mode 100644 Deploy/DeployAll/Deployables.cs create mode 100644 Deploy/DeployAll/DotnetCmd.cs create mode 100644 Deploy/DeployAll/GitCmd.cs create mode 100644 Deploy/DeployAll/Program.cs create mode 100644 Deploy/DeployAll/SteamPipeAssistant.cs create mode 100644 Deploy/DeployAll/Util.cs create mode 100644 Deploy/DeployAll/macSkeleton/Barotrauma.app/Contents/Resources/barotrauma.icns create mode 100644 Deploy/DeployAll/macSkeleton/Barotrauma.app/Contents/info.plist create mode 100644 Deploy/DeployAll/macSkeleton/Barotrauma.app/installscript.vdf delete mode 100755 Deploy/Linux/DeployLinux.sh delete mode 100644 Deploy/Linux/DeployLinuxServer.sh delete mode 100755 Deploy/Linux/DeployLinuxUnstable.sh delete mode 100644 Deploy/Linux/DeployMac.sh delete mode 100644 Deploy/Linux/DeployMacUnstable.sh delete mode 100644 Deploy/Linux/DeployWindows.sh delete mode 100644 Deploy/Linux/DeployWindowsUnstable.sh create mode 100644 Deploy/ManualScripts/Linux/DeployLinux.sh create mode 100644 Deploy/ManualScripts/Linux/DeployLinuxServer.sh create mode 100644 Deploy/ManualScripts/Linux/DeployLinuxUnstable.sh create mode 100644 Deploy/ManualScripts/Linux/DeployMac.sh create mode 100644 Deploy/ManualScripts/Linux/DeployMacUnstable.sh create mode 100644 Deploy/ManualScripts/Linux/DeployWindows.sh create mode 100644 Deploy/ManualScripts/Linux/DeployWindowsUnstable.sh create mode 100644 Deploy/ManualScripts/SteamPipeBuildScripts/app_1026340.vdf create mode 100644 Deploy/ManualScripts/SteamPipeBuildScripts/app_602960.vdf rename {BuildScripts => Deploy/ManualScripts/SteamPipeBuildScripts}/depot_1026341.vdf (100%) rename {BuildScripts => Deploy/ManualScripts/SteamPipeBuildScripts}/depot_1026342.vdf (100%) rename {BuildScripts => Deploy/ManualScripts/SteamPipeBuildScripts}/depot_602961.vdf (100%) rename {BuildScripts => Deploy/ManualScripts/SteamPipeBuildScripts}/depot_602962.vdf (100%) rename {BuildScripts => Deploy/ManualScripts/SteamPipeBuildScripts}/depot_602963.vdf (100%) create mode 100644 Deploy/ManualScripts/Windows/DeployLinux.bat create mode 100644 Deploy/ManualScripts/Windows/DeployLinuxUnstable.bat create mode 100644 Deploy/ManualScripts/Windows/DeployMac.bat create mode 100644 Deploy/ManualScripts/Windows/DeployMacUnstable.bat create mode 100644 Deploy/ManualScripts/Windows/DeployWindows.bat create mode 100644 Deploy/ManualScripts/Windows/DeployWindowsServer.bat create mode 100644 Deploy/ManualScripts/Windows/DeployWindowsUnstable.bat delete mode 100644 Deploy/Windows/DeployLinux.bat delete mode 100644 Deploy/Windows/DeployLinuxUnstable.bat delete mode 100644 Deploy/Windows/DeployMac.bat delete mode 100644 Deploy/Windows/DeployMacUnstable.bat delete mode 100644 Deploy/Windows/DeployWindows.bat delete mode 100644 Deploy/Windows/DeployWindowsServer.bat delete mode 100644 Deploy/Windows/DeployWindowsUnstable.bat diff --git a/Barotrauma/BarotraumaClient/ClientSource/Camera.cs b/Barotrauma/BarotraumaClient/ClientSource/Camera.cs index 02ab56891..0bfac9a82 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Camera.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Camera.cs @@ -179,9 +179,9 @@ namespace Barotrauma { if (Character.Controlled != null && !Character.Controlled.IsDead) { return; } - msg.Write((byte)ClientNetObject.SPECTATING_POS); - msg.Write(position.X); - msg.Write(position.Y); + msg.WriteByte((byte)ClientNetObject.SPECTATING_POS); + msg.WriteSingle(position.X); + msg.WriteSingle(position.Y); } private void CreateMatrices() diff --git a/Barotrauma/BarotraumaClient/ClientSource/Characters/CharacterNetworking.cs b/Barotrauma/BarotraumaClient/ClientSource/Characters/CharacterNetworking.cs index 6f32c617c..4ad12a2d4 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Characters/CharacterNetworking.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Characters/CharacterNetworking.cs @@ -114,27 +114,27 @@ namespace Barotrauma public void ClientWriteInput(IWriteMessage msg) { - msg.Write((byte)ClientNetObject.CHARACTER_INPUT); + msg.WriteByte((byte)ClientNetObject.CHARACTER_INPUT); if (memInput.Count > 60) { memInput.RemoveRange(60, memInput.Count - 60); } - msg.Write(LastNetworkUpdateID); + msg.WriteUInt16(LastNetworkUpdateID); byte inputCount = Math.Min((byte)memInput.Count, (byte)60); - msg.Write(inputCount); + msg.WriteByte(inputCount); for (int i = 0; i < inputCount; i++) { msg.WriteRangedInteger((int)memInput[i].states, 0, (int)InputNetFlags.MaxVal); - msg.Write(memInput[i].intAim); + msg.WriteUInt16(memInput[i].intAim); if (memInput[i].states.HasFlag(InputNetFlags.Select) || memInput[i].states.HasFlag(InputNetFlags.Deselect) || memInput[i].states.HasFlag(InputNetFlags.Use) || memInput[i].states.HasFlag(InputNetFlags.Health) || memInput[i].states.HasFlag(InputNetFlags.Grab)) { - msg.Write(memInput[i].interact); + msg.WriteUInt16(memInput[i].interact); } } } @@ -150,16 +150,16 @@ namespace Barotrauma Inventory.ClientEventWrite(msg, inventoryStateEventData); break; case TreatmentEventData _: - msg.Write(AnimController.Anim == AnimController.Animation.CPR); + msg.WriteBoolean(AnimController.Anim == AnimController.Animation.CPR); break; case CharacterStatusEventData _: //do nothing break; case UpdateTalentsEventData _: - msg.Write((ushort)characterTalents.Count); + msg.WriteUInt16((ushort)characterTalents.Count); foreach (var unlockedTalent in characterTalents) { - msg.Write(unlockedTalent.Prefab.UintIdentifier); + msg.WriteUInt32(unlockedTalent.Prefab.UintIdentifier); } break; default: diff --git a/Barotrauma/BarotraumaClient/ClientSource/ContentManagement/ContentPackage/ModProject.cs b/Barotrauma/BarotraumaClient/ClientSource/ContentManagement/ContentPackage/ModProject.cs index 088fb2725..34d2a3a75 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/ContentManagement/ContentPackage/ModProject.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/ContentManagement/ContentPackage/ModProject.cs @@ -74,7 +74,7 @@ namespace Barotrauma get => name; set { - var charsToRemove = Path.GetInvalidFileNameChars(); + var charsToRemove = Path.GetInvalidFileNameCharsCrossPlatform(); name = string.Concat(value.Where(c => !charsToRemove.Contains(c))); } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/DebugConsole.cs b/Barotrauma/BarotraumaClient/ClientSource/DebugConsole.cs index 22196a3e7..98fdaa449 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/DebugConsole.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/DebugConsole.cs @@ -723,7 +723,7 @@ namespace Barotrauma AssignOnExecute("explosion", (string[] args) => { - Vector2 explosionPos = GameMain.GameScreen.Cam.ScreenToWorld(PlayerInput.MousePosition); + Vector2 explosionPos = Screen.Selected.Cam.ScreenToWorld(PlayerInput.MousePosition); float range = 500, force = 10, damage = 50, structureDamage = 20, itemDamage = 100, empStrength = 0.0f, ballastFloraStrength = 50f; if (args.Length > 0) float.TryParse(args[0], out range); if (args.Length > 1) float.TryParse(args[1], out force); @@ -3056,6 +3056,11 @@ namespace Barotrauma commands.Add(new Command("reloadwearables", "Reloads the sprites of all limbs and wearable sprites (clothing) of the controlled character. Provide id or name if you want to target another character.", args => { + if (GameMain.GameSession != null) + { + ThrowError("Using the command is not allowed during an active game session: the command is intended to be used in the character editor or in the main menu."); + return; + } var character = (args.Length == 0) ? Character.Controlled : FindMatchingCharacter(args, true); if (character == null) { @@ -3067,6 +3072,11 @@ namespace Barotrauma commands.Add(new Command("loadwearable", "Force select certain variant for the selected character.", args => { + if (GameMain.GameSession != null) + { + ThrowError("Using the command is not allowed during an active game session: the command is intended to be used in the character editor or in the main menu."); + return; + } var character = Character.Controlled; if (character == null) { diff --git a/Barotrauma/BarotraumaClient/ClientSource/Events/EventActions/ConversationAction.cs b/Barotrauma/BarotraumaClient/ClientSource/Events/EventActions/ConversationAction.cs index e8bddc5f7..065feb05f 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Events/EventActions/ConversationAction.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Events/EventActions/ConversationAction.cs @@ -381,18 +381,18 @@ namespace Barotrauma private static void SendResponse(UInt16 actionId, int selectedOption) { IWriteMessage outmsg = new WriteOnlyMessage(); - outmsg.Write((byte)ClientPacketHeader.EVENTMANAGER_RESPONSE); - outmsg.Write(actionId); - outmsg.Write((byte)selectedOption); + outmsg.WriteByte((byte)ClientPacketHeader.EVENTMANAGER_RESPONSE); + outmsg.WriteUInt16(actionId); + outmsg.WriteByte((byte)selectedOption); GameMain.Client?.ClientPeer?.Send(outmsg, DeliveryMethod.Reliable); } private static void SendIgnore(UInt16 actionId) { IWriteMessage outmsg = new WriteOnlyMessage(); - outmsg.Write((byte)ClientPacketHeader.EVENTMANAGER_RESPONSE); - outmsg.Write(actionId); - outmsg.Write(byte.MaxValue); + outmsg.WriteByte((byte)ClientPacketHeader.EVENTMANAGER_RESPONSE); + outmsg.WriteUInt16(actionId); + outmsg.WriteByte(byte.MaxValue); GameMain.Client?.ClientPeer?.Send(outmsg, DeliveryMethod.Reliable); } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Events/Missions/CombatMission.cs b/Barotrauma/BarotraumaClient/ClientSource/Events/Missions/CombatMission.cs index 3957dff43..291366b9b 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Events/Missions/CombatMission.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Events/Missions/CombatMission.cs @@ -1,6 +1,4 @@ -using Barotrauma.Networking; - -namespace Barotrauma +namespace Barotrauma { partial class CombatMission : Mission { @@ -8,7 +6,7 @@ namespace Barotrauma { get { - if (descriptions == null) return ""; + if (descriptions == null) { return ""; } if (GameMain.Client?.Character == null) { diff --git a/Barotrauma/BarotraumaClient/ClientSource/Events/Missions/Mission.cs b/Barotrauma/BarotraumaClient/ClientSource/Events/Missions/Mission.cs index cff6b76b9..28eafbc6c 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Events/Missions/Mission.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Events/Missions/Mission.cs @@ -80,6 +80,10 @@ namespace Barotrauma LocalizedString header = messageIndex < Headers.Length ? Headers[messageIndex] : ""; LocalizedString message = messageIndex < Messages.Length ? Messages[messageIndex] : ""; + if (!message.IsNullOrEmpty()) + { + message = ModifyMessage(message); + } CoroutineManager.StartCoroutine(ShowMessageBoxAfterRoundSummary(header, message)); } diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/ChatBox.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/ChatBox.cs index 114d62cdc..094a4b81c 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/ChatBox.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/ChatBox.cs @@ -325,6 +325,12 @@ namespace Barotrauma ToggleOpen = PreferChatBoxOpen = GameSettings.CurrentConfig.ChatOpen; } + public void Toggle() + { + ToggleOpen = !ToggleOpen; + CloseAfterMessageSent = false; + } + public bool TypingChatMessage(GUITextBox textBox, string text) { string command = ChatMessage.GetChatMessageCommand(text, out _); @@ -605,22 +611,29 @@ namespace Barotrauma showNewMessagesButton.Visible = false; } - if (PlayerInput.KeyHit(InputType.ToggleChatMode) && GUI.KeyboardDispatcher.Subscriber == null && Screen.Selected == GameMain.GameScreen) + if (Screen.Selected == GameMain.GameScreen && GUI.KeyboardDispatcher.Subscriber == null) { - try + if (PlayerInput.KeyHit(InputType.ToggleChatMode)) { - var mode = GameMain.ActiveChatMode switch + try { - ChatMode.Local => ChatMode.Radio, - ChatMode.Radio => ChatMode.Local, - _ => throw new NotImplementedException() - }; - ChatModeDropDown.SelectItem(mode); - // TODO: Play a sound? + var mode = GameMain.ActiveChatMode switch + { + ChatMode.Local => ChatMode.Radio, + ChatMode.Radio => ChatMode.Local, + _ => throw new NotImplementedException() + }; + ChatModeDropDown.SelectItem(mode); + // TODO: Play a sound? + } + catch (NotImplementedException) + { + DebugConsole.ThrowError($"Error toggling chat mode: not implemented for current mode \"{GameMain.ActiveChatMode}\""); + } } - catch (NotImplementedException) + else if (PlayerInput.KeyHit(InputType.ChatBox)) { - DebugConsole.ThrowError($"Error toggling chat mode: not implemented for current mode \"{GameMain.ActiveChatMode}\""); + Toggle(); } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/CrewManagement.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/CrewManagement.cs index 80de95f63..b25b07ca4 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/CrewManagement.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/CrewManagement.cs @@ -889,35 +889,35 @@ namespace Barotrauma if (campaign is MultiPlayerCampaign) { IWriteMessage msg = new WriteOnlyMessage(); - msg.Write((byte)ClientPacketHeader.CREW); + msg.WriteByte((byte)ClientPacketHeader.CREW); - msg.Write(updatePending); + msg.WriteBoolean(updatePending); if (updatePending) { - msg.Write((ushort)PendingHires.Count); + msg.WriteUInt16((ushort)PendingHires.Count); foreach (CharacterInfo pendingHire in PendingHires) { - msg.Write(pendingHire.GetIdentifierUsingOriginalName()); + msg.WriteInt32(pendingHire.GetIdentifierUsingOriginalName()); } } - msg.Write(validateHires); + msg.WriteBoolean(validateHires); bool validRenaming = renameCharacter.info != null && !string.IsNullOrEmpty(renameCharacter.newName); - msg.Write(validRenaming); + msg.WriteBoolean(validRenaming); if (validRenaming) { int identifier = renameCharacter.info.GetIdentifierUsingOriginalName(); - msg.Write(identifier); - msg.Write(renameCharacter.newName); + msg.WriteInt32(identifier); + msg.WriteString(renameCharacter.newName); bool existingCrewMember = campaign.CrewManager?.GetCharacterInfos().Any(ci => ci.GetIdentifierUsingOriginalName() == identifier) ?? false; - msg.Write(existingCrewMember); + msg.WriteBoolean(existingCrewMember); } - msg.Write(firedCharacter != null); + msg.WriteBoolean(firedCharacter != null); if (firedCharacter != null) { - msg.Write(firedCharacter.GetIdentifier()); + msg.WriteInt32(firedCharacter.GetIdentifier()); } GameMain.Client.ClientPeer?.Send(msg, DeliveryMethod.Reliable); diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUI.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUI.cs index 4e4f7c94d..cbe1cb50d 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUI.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUI.cs @@ -1018,6 +1018,11 @@ namespace Barotrauma if (c.Enabled) { + var dragHandle = c as GUIDragHandle ?? parent as GUIDragHandle; + if (dragHandle != null) + { + return dragHandle.Dragging ? CursorState.Dragging : CursorState.Hand; + } // Some parent elements take priority // but not when the child is a GUIButton or GUITickBox if (!(parent is GUIButton) && !(parent is GUIListBox) || @@ -1027,6 +1032,7 @@ namespace Barotrauma } } + // Children in list boxes can be interacted with despite not having // a GUIButton inside of them so instead of hard coding we check if // the children can be interacted with by checking their hover state @@ -1097,6 +1103,8 @@ namespace Barotrauma return list; case GUIScrollBar bar: return bar; + case GUIDragHandle dragHandle: + return dragHandle; } } component = parent; diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIComponent.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIComponent.cs index 61ddb8f50..764382577 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIComponent.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIComponent.cs @@ -813,9 +813,9 @@ namespace Barotrauma flashColor = (color == null) ? GUIStyle.Red : (Color)color; } - public void FadeOut(float duration, bool removeAfter, float wait = 0.0f) + public void FadeOut(float duration, bool removeAfter, float wait = 0.0f, Action onRemove = null) { - CoroutineManager.StartCoroutine(LerpAlpha(0.0f, duration, removeAfter, wait)); + CoroutineManager.StartCoroutine(LerpAlpha(0.0f, duration, removeAfter, wait, onRemove)); } public void FadeIn(float wait, float duration) @@ -877,7 +877,7 @@ namespace Barotrauma yield return CoroutineStatus.Success; } - private IEnumerable LerpAlpha(float to, float duration, bool removeAfter, float wait = 0.0f) + private IEnumerable LerpAlpha(float to, float duration, bool removeAfter, float wait = 0.0f, Action onRemove = null) { State = ComponentState.None; float t = 0.0f; @@ -902,6 +902,7 @@ namespace Barotrauma if (removeAfter && Parent != null) { Parent.RemoveChild(this); + onRemove?.Invoke(); } yield return CoroutineStatus.Success; diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIDragHandle.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIDragHandle.cs index 678b3fb29..492772759 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIDragHandle.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIDragHandle.cs @@ -16,6 +16,8 @@ namespace Barotrauma public Func ValidatePosition; + public bool Dragging => dragStarted; + public GUIDragHandle(RectTransform rectT, RectTransform elementToMove, string style = "GUIDragIndicator") : base(style, rectT) { diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIListBox.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIListBox.cs index 579e492c2..b532b7900 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIListBox.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIListBox.cs @@ -57,7 +57,8 @@ namespace Barotrauma { SelectSingle, SelectMultiple, - RequireShiftToSelectMultiple + RequireShiftToSelectMultiple, + None } public SelectMode CurrentSelectMode = SelectMode.SelectSingle; @@ -1058,7 +1059,7 @@ namespace Barotrauma public void Select(int childIndex, Force force = Force.No, AutoScroll autoScroll = AutoScroll.Enabled, TakeKeyBoardFocus takeKeyBoardFocus = TakeKeyBoardFocus.No, PlaySelectSound playSelectSound = PlaySelectSound.No) { - if (childIndex >= Content.CountChildren || childIndex < 0) { return; } + if (childIndex >= Content.CountChildren || childIndex < 0 || CurrentSelectMode == SelectMode.None) { return; } GUIComponent child = Content.GetChild(childIndex); if (child is null) { return; } @@ -1157,6 +1158,7 @@ namespace Barotrauma public void Select(IEnumerable children) { + if (CurrentSelectMode == SelectMode.None) { return; } Selected = true; selected.Clear(); selected.AddRange(children.Where(c => Content.Children.Contains(c))); diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIMessageBox.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIMessageBox.cs index 8936fb126..f7bad7dc1 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIMessageBox.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIMessageBox.cs @@ -1,9 +1,7 @@ using Microsoft.Xna.Framework; -using Microsoft.Xna.Framework.Graphics; using System; using System.Collections.Generic; using System.Linq; -using Barotrauma.Networking; using Barotrauma.Extensions; namespace Barotrauma @@ -25,9 +23,12 @@ namespace Barotrauma Default, InGame, Vote, - Hint + Hint, + Tutorial } + private bool IsAnimated => type == Type.InGame || type == Type.Hint || type == Type.Tutorial; + public List Buttons { get; private set; } = new List(); public GUILayoutGroup Content { get; private set; } public GUIFrame InnerFrame { get; private set; } @@ -60,6 +61,9 @@ namespace Barotrauma public GUIImage BackgroundIcon { get; private set; } private GUIImage newBackgroundIcon; + /// + /// Close the message box automatically after enough time has passed () + /// public bool AutoClose; private float openState; @@ -69,6 +73,11 @@ namespace Barotrauma private readonly Type type; + /// + /// Close the message box automatically if the condition is met + /// + private readonly Func autoCloseCondition; + public Type MessageBoxType => type; public static GUIComponent VisibleBox => MessageBoxes.LastOrDefault(); @@ -79,7 +88,9 @@ namespace Barotrauma this.Buttons[0].OnClicked = Close; } - public GUIMessageBox(RichString headerText, RichString text, LocalizedString[] buttons, Vector2? relativeSize = null, Point? minSize = null, Alignment textAlignment = Alignment.TopLeft, Type type = Type.Default, string tag = "", Sprite icon = null, string iconStyle = "", Sprite backgroundIcon = null) + public GUIMessageBox(RichString headerText, RichString text, LocalizedString[] buttons, + Vector2? relativeSize = null, Point? minSize = null, Alignment textAlignment = Alignment.TopLeft, Type type = Type.Default, string tag = "", + Sprite icon = null, string iconStyle = "", Sprite backgroundIcon = null, Func autoCloseCondition = null, bool hideCloseButton = false) : base(new RectTransform(GUI.Canvas.RelativeSize, GUI.Canvas, Anchor.Center), style: GUIStyle.GetComponentStyle("GUIMessageBox." + type) != null ? "GUIMessageBox." + type : "GUIMessageBox") { int width = (int)(DefaultWidth * type switch @@ -116,6 +127,7 @@ namespace Barotrauma Anchor anchor = type switch { Type.InGame => Anchor.TopCenter, + Type.Tutorial => Anchor.TopCenter, Type.Hint => Anchor.TopRight, Type.Vote => Anchor.TopRight, _ => Anchor.Center @@ -188,7 +200,7 @@ namespace Barotrauma Buttons.Add(button); } } - else if (type == Type.InGame) + else if (type == Type.InGame || type == Type.Tutorial) { InnerFrame.RectTransform.AbsoluteOffset = new Point(0, GameMain.GraphicsHeight); CanBeFocused = false; @@ -212,37 +224,43 @@ namespace Barotrauma Content = new GUILayoutGroup(new RectTransform(new Vector2(Icon != null ? 0.65f : 0.85f, 1.0f), horizontalLayoutGroup.RectTransform)); - var buttonContainer = new GUIFrame(new RectTransform(new Vector2(0.15f, 1.0f), horizontalLayoutGroup.RectTransform), style: null); - Buttons = new List(1) + if (!hideCloseButton) { - new GUIButton(new RectTransform(new Vector2(0.3f, 0.5f), buttonContainer.RectTransform, Anchor.Center), - style: "UIToggleButton") + var buttonContainer = new GUIFrame(new RectTransform(new Vector2(0.15f, 1.0f), horizontalLayoutGroup.RectTransform), style: null); + Buttons = new List(1) { - OnClicked = Close - } - }; - - InputType? closeInput = null; - if (GameSettings.CurrentConfig.KeyMap.Bindings[InputType.Use].MouseButton == MouseButton.None) - { - closeInput = InputType.Use; - } - else if (GameSettings.CurrentConfig.KeyMap.Bindings[InputType.Select].MouseButton == MouseButton.None) - { - closeInput = InputType.Select; - } - if (closeInput.HasValue) - { - Buttons[0].ToolTip = TextManager.ParseInputTypes($"{TextManager.Get("Close")} ([InputType.{closeInput.Value}])"); - Buttons[0].OnAddedToGUIUpdateList += (GUIComponent component) => - { - if (!closing && openState >= 1.0f && PlayerInput.KeyHit(closeInput.Value)) + new GUIButton(new RectTransform(new Vector2(0.3f, 0.5f), buttonContainer.RectTransform, Anchor.Center), + style: "UIToggleButton") { - GUIButton btn = component as GUIButton; - btn?.OnClicked(btn, btn.UserData); - btn?.Flash(GUIStyle.Green); + OnClicked = Close } }; + InputType? closeInput = null; + if (GameSettings.CurrentConfig.KeyMap.Bindings[InputType.Use].MouseButton == MouseButton.None) + { + closeInput = InputType.Use; + } + else if (GameSettings.CurrentConfig.KeyMap.Bindings[InputType.Select].MouseButton == MouseButton.None) + { + closeInput = InputType.Select; + } + if (closeInput.HasValue) + { + Buttons[0].ToolTip = TextManager.ParseInputTypes($"{TextManager.Get("Close")} ([InputType.{closeInput.Value}])"); + Buttons[0].OnAddedToGUIUpdateList += (GUIComponent component) => + { + if (!closing && openState >= 1.0f && PlayerInput.KeyHit(closeInput.Value)) + { + GUIButton btn = component as GUIButton; + btn?.OnClicked(btn, btn.UserData); + btn?.Flash(GUIStyle.Green); + } + }; + } + } + else + { + Buttons.Clear(); } Header = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), Content.RectTransform), headerText, wrap: true); @@ -274,7 +292,10 @@ namespace Barotrauma Content.RectTransform.NonScaledSize = new Point(Content.Rect.Width, height); } - Buttons[0].RectTransform.MaxSize = new Point((int)(0.4f * Buttons[0].Rect.Y), Buttons[0].Rect.Y); + if (!hideCloseButton) + { + Buttons[0].RectTransform.MaxSize = new Point((int)(0.4f * Buttons[0].Rect.Y), Buttons[0].Rect.Y); + } } else if (type == Type.Hint) { @@ -408,6 +429,8 @@ namespace Barotrauma } } + this.autoCloseCondition = autoCloseCondition; + MessageBoxes.Add(this); } @@ -511,13 +534,15 @@ namespace Barotrauma } } - if (type == Type.InGame || type == Type.Hint) + if (IsAnimated) { Vector2 initialPos, defaultPos, endPos; - if (type == Type.InGame) + if (type == Type.InGame || type == Type.Tutorial) { initialPos = new Vector2(0.0f, GameMain.GraphicsHeight); - defaultPos = new Vector2(0.0f, HUDLayoutSettings.InventoryAreaLower.Y - InnerFrame.Rect.Height - 20 * GUI.Scale); + defaultPos = type == Type.InGame ? + new Vector2(0.0f, HUDLayoutSettings.InventoryAreaLower.Y - InnerFrame.Rect.Height - 20 * GUI.Scale) : + new Vector2(0.0f, GameMain.GraphicsHeight / 2); endPos = new Vector2(GameMain.GraphicsWidth, defaultPos.Y); } else @@ -549,7 +574,7 @@ namespace Barotrauma inGameCloseTimer += deltaTime; } - if (inGameCloseTimer >= inGameCloseTime) + if (inGameCloseTimer >= inGameCloseTime || (autoCloseCondition != null && autoCloseCondition())) { Close(); } @@ -612,7 +637,7 @@ namespace Barotrauma public void Close() { - if (type == Type.InGame || type == Type.Hint) + if (IsAnimated) { closing = true; } diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIStyle.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIStyle.cs index 27be2752f..6451c8d24 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIStyle.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIStyle.cs @@ -141,7 +141,23 @@ namespace Barotrauma public readonly static GUIColor HealthBarColorMedium = new GUIColor("HealthBarColorMedium"); public readonly static GUIColor HealthBarColorHigh = new GUIColor("HealthBarColorHigh"); - public static Point ItemFrameMargin => new Point(50, 56).Multiply(GUI.SlicedSpriteScale); + public static Point ItemFrameMargin + { + get + { + Point size = new Point(50, 56).Multiply(GUI.SlicedSpriteScale); + + var style = GetComponentStyle("ItemUI"); + var sprite = style?.Sprites[GUIComponent.ComponentState.None].First(); + if (sprite != null) + { + size.X = Math.Min(sprite.Slices[0].Width + sprite.Slices[2].Width, size.X); + size.Y = Math.Min(sprite.Slices[0].Height + sprite.Slices[6].Height, size.Y); + } + return size; + } + } + public static Point ItemFrameOffset => new Point(0, 3).Multiply(GUI.SlicedSpriteScale); public static GUIComponentStyle GetComponentStyle(string name) diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUITextBlock.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUITextBlock.cs index 404c09927..99461d746 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUITextBlock.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUITextBlock.cs @@ -587,7 +587,7 @@ namespace Barotrauma if (Shadow) { - Vector2 shadowOffset = new Vector2(GUI.IntScale(2)); + Vector2 shadowOffset = new Vector2(Math.Max(GUI.IntScale(2), 1)); Font.DrawString(spriteBatch, textToShow, pos + shadowOffset, Color.Black, 0.0f, origin, TextScale, SpriteEffects.None, textDepth, alignment: textAlignment, forceUpperCase: ForceUpperCase); } diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/HUDLayoutSettings.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/HUDLayoutSettings.cs index 0552340d0..ded2b870e 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/HUDLayoutSettings.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/HUDLayoutSettings.cs @@ -25,6 +25,10 @@ namespace Barotrauma { get; private set; } + public static Rectangle TutorialObjectiveListArea + { + get; private set; + } public static Rectangle MessageAreaTop { @@ -167,6 +171,10 @@ namespace Barotrauma HealthWindowAreaLeft = new Rectangle(healthWindowX, healthWindowY, healthWindowWidth, healthWindowHeight); + int objectiveListAreaX = HealthWindowAreaLeft.Right + Padding; + int objectiveListAreaY = ButtonAreaTop.Bottom + Padding; + TutorialObjectiveListArea = new Rectangle(objectiveListAreaX, objectiveListAreaY, (GameMain.GraphicsWidth - Padding) - objectiveListAreaX, (AfflictionAreaLeft.Top - Padding) - objectiveListAreaY); + int votingAreaWidth = (int)(400 * GUI.Scale); int votingAreaX = GameMain.GraphicsWidth - Padding - votingAreaWidth; int votingAreaY = Padding + ButtonAreaTop.Height; @@ -179,16 +187,19 @@ namespace Barotrauma public static void Draw(SpriteBatch spriteBatch) { - GUI.DrawRectangle(spriteBatch, ButtonAreaTop, Color.White * 0.5f); - GUI.DrawRectangle(spriteBatch, MessageAreaTop, GUIStyle.Orange * 0.5f); - GUI.DrawRectangle(spriteBatch, CrewArea, Color.Blue * 0.5f); - GUI.DrawRectangle(spriteBatch, ChatBoxArea, Color.Cyan * 0.5f); - GUI.DrawRectangle(spriteBatch, HealthBarArea, Color.Red * 0.5f); - GUI.DrawRectangle(spriteBatch, AfflictionAreaLeft, Color.Red * 0.5f); - GUI.DrawRectangle(spriteBatch, InventoryAreaLower, Color.Yellow * 0.5f); - GUI.DrawRectangle(spriteBatch, HealthWindowAreaLeft, Color.Red * 0.5f); - GUI.DrawRectangle(spriteBatch, BottomRightInfoArea, Color.Green * 0.5f); - GUI.DrawRectangle(spriteBatch, ItemHUDArea, Color.Magenta * 0.3f); + DrawRectangle(ButtonAreaTop, Color.White * 0.5f); + DrawRectangle(TutorialObjectiveListArea, GUIStyle.Blue * 0.5f); + DrawRectangle(MessageAreaTop, GUIStyle.Orange * 0.5f); + DrawRectangle(CrewArea, Color.Blue * 0.5f); + DrawRectangle(ChatBoxArea, Color.Cyan * 0.5f); + DrawRectangle(HealthBarArea, Color.Red * 0.5f); + DrawRectangle(AfflictionAreaLeft, Color.Red * 0.5f); + DrawRectangle(InventoryAreaLower, Color.Yellow * 0.5f); + DrawRectangle(HealthWindowAreaLeft, Color.Red * 0.5f); + DrawRectangle(BottomRightInfoArea, Color.Green * 0.5f); + DrawRectangle(ItemHUDArea, Color.Magenta * 0.3f); + + void DrawRectangle(Rectangle r, Color c) => GUI.DrawRectangle(spriteBatch, r, c); } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/SubmarineSelection.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/SubmarineSelection.cs index 47d184dd0..6e140e57b 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/SubmarineSelection.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/SubmarineSelection.cs @@ -56,6 +56,7 @@ namespace Barotrauma public SubmarineInfo displayedSubmarine; public GUITextBlock submarineName; public GUITextBlock submarineClass; + public GUITextBlock submarineTier; public GUITextBlock submarineFee; public GUIButton selectSubmarineButton; public GUITextBlock middleTextBlock; @@ -162,7 +163,12 @@ namespace Barotrauma IgnoreLayoutGroups = true }; new GUIListBox(new RectTransform(Vector2.One, infoFrame.RectTransform)) { IgnoreLayoutGroups = true, CanBeFocused = false }; - specsFrame = new GUIListBox(new RectTransform(new Vector2(0.39f, 1f), infoFrame.RectTransform), style: null) { Spacing = GUI.IntScale(5), Padding = new Vector4(HUDLayoutSettings.Padding / 2f, HUDLayoutSettings.Padding, 0, 0) }; + specsFrame = new GUIListBox(new RectTransform(new Vector2(0.39f, 1f), infoFrame.RectTransform), style: null) + { + CurrentSelectMode = GUIListBox.SelectMode.None, + Spacing = GUI.IntScale(5), + Padding = new Vector4(HUDLayoutSettings.Padding / 2f, HUDLayoutSettings.Padding, 0, 0) + }; new GUIFrame(new RectTransform(new Vector2(0.02f, 0.8f), infoFrame.RectTransform) { RelativeOffset = new Vector2(0.0f, 0.1f) }, style: "VerticalLine"); GUIListBox descriptionFrame = new GUIListBox(new RectTransform(new Vector2(0.59f, 1f), infoFrame.RectTransform), style: null) { Padding = new Vector4(HUDLayoutSettings.Padding / 2f, HUDLayoutSettings.Padding * 1.5f, HUDLayoutSettings.Padding * 1.5f, HUDLayoutSettings.Padding / 2f) }; descriptionTextBlock = new GUITextBlock(new RectTransform(new Vector2(1, 0), descriptionFrame.Content.RectTransform), string.Empty, font: GUIStyle.Font, wrap: true) { CanBeFocused = false }; @@ -221,7 +227,8 @@ namespace Barotrauma submarineDisplayElement.submarineImage = new GUIImage(new RectTransform(new Vector2(0.8f, 1f), submarineDisplayElement.background.RectTransform, Anchor.Center), null, true); submarineDisplayElement.middleTextBlock = new GUITextBlock(new RectTransform(new Vector2(0.8f, 1f), submarineDisplayElement.background.RectTransform, Anchor.Center), string.Empty, textAlignment: Alignment.Center); submarineDisplayElement.submarineName = new GUITextBlock(new RectTransform(new Vector2(1f, 0.1f), submarineDisplayElement.background.RectTransform, Anchor.TopCenter, Pivot.TopCenter) { AbsoluteOffset = new Point(0, HUDLayoutSettings.Padding) }, string.Empty, textAlignment: Alignment.Center, font: GUIStyle.SubHeadingFont); - submarineDisplayElement.submarineClass = new GUITextBlock(new RectTransform(new Vector2(1f, 0.1f), submarineDisplayElement.background.RectTransform, Anchor.TopCenter, Pivot.TopCenter) { AbsoluteOffset = new Point(0, HUDLayoutSettings.Padding + (int)GUIStyle.Font.MeasureString(submarineDisplayElement.submarineName.Text).Y) }, string.Empty, textAlignment: Alignment.Center); + submarineDisplayElement.submarineClass = new GUITextBlock(new RectTransform(new Vector2(1f, 0.1f), submarineDisplayElement.background.RectTransform, Anchor.TopCenter, Pivot.TopCenter) { AbsoluteOffset = new Point(0, HUDLayoutSettings.Padding + (int)GUIStyle.Font.MeasureString(submarineDisplayElement.submarineName.Text).Y) }, string.Empty, textAlignment: Alignment.Left); + submarineDisplayElement.submarineTier = new GUITextBlock(new RectTransform(new Vector2(1f, 0.1f), submarineDisplayElement.background.RectTransform, Anchor.TopCenter, Pivot.TopCenter) { AbsoluteOffset = new Point(0, HUDLayoutSettings.Padding + (int)GUIStyle.Font.MeasureString(submarineDisplayElement.submarineName.Text).Y) }, string.Empty, textAlignment: Alignment.Right); submarineDisplayElement.submarineFee = new GUITextBlock(new RectTransform(new Vector2(1f, 0.1f), submarineDisplayElement.background.RectTransform, Anchor.BottomCenter, Pivot.BottomCenter) { AbsoluteOffset = new Point(0, HUDLayoutSettings.Padding) }, string.Empty, textAlignment: Alignment.Center, font: GUIStyle.SubHeadingFont); submarineDisplayElement.selectSubmarineButton = new GUIButton(new RectTransform(Vector2.One, submarineDisplayElement.background.RectTransform), style: null); submarineDisplayElement.previewButton = new GUIButton(new RectTransform(Vector2.One * 0.12f, submarineDisplayElement.background.RectTransform, anchor: Anchor.BottomRight, pivot: Pivot.BottomRight, scaleBasis: ScaleBasis.BothHeight) { AbsoluteOffset = new Point((int)(0.03f * background.Rect.Height)) }, style: "ExpandButton") @@ -355,6 +362,7 @@ namespace Barotrauma submarineDisplays[i].submarineName.Text = string.Empty; submarineDisplays[i].submarineFee.Text = string.Empty; submarineDisplays[i].submarineClass.Text = string.Empty; + submarineDisplays[i].submarineTier.Text = string.Empty; submarineDisplays[i].selectSubmarineButton.Enabled = false; submarineDisplays[i].selectSubmarineButton.OnClicked = null; submarineDisplays[i].displayedSubmarine = null; @@ -389,6 +397,7 @@ namespace Barotrauma submarineDisplays[i].submarineName.Text = subToDisplay.DisplayName; submarineDisplays[i].submarineClass.Text = TextManager.GetWithVariable("submarineclass.classsuffixformat", "[type]", TextManager.Get($"submarineclass.{subToDisplay.SubmarineClass}")); + submarineDisplays[i].submarineTier.Text = TextManager.Get($"submarinetier.{subToDisplay.Tier}"); if (!GameMain.GameSession.IsSubmarineOwned(subToDisplay)) { @@ -847,7 +856,7 @@ namespace Barotrauma msgBox = new GUIMessageBox(TextManager.Get("purchasesubmarineheader"), TextManager.GetWithVariables("purchasesubmarinetext", ("[submarinename]", selectedSubmarine.DisplayName), ("[amount]", selectedSubmarine.Price.ToString()), - ("[currencyname]", currencyName)), messageBoxOptions); + ("[currencyname]", currencyName)) + '\n' + TextManager.Get("submarineswitchinstruction"), messageBoxOptions); msgBox.Buttons[0].OnClicked = (applyButton, obj) => { diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/TabMenu.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/TabMenu.cs index 1e7d1cd03..1f49c63f0 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/TabMenu.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/TabMenu.cs @@ -1722,7 +1722,7 @@ namespace Barotrauma var subInfoTextLayout = new GUILayoutGroup(new RectTransform(Vector2.One, paddedFrame.RectTransform)); - LocalizedString className = !sub.Info.HasTag(SubmarineTag.Shuttle) ? TextManager.Get($"submarineclass.{sub.Info.SubmarineClass}") : TextManager.Get("shuttle"); + LocalizedString className = !sub.Info.HasTag(SubmarineTag.Shuttle) ? $"{TextManager.Get($"submarineclass.{sub.Info.SubmarineClass}")} ({TextManager.Get($"submarinetier.{sub.Info.Tier}")})" : TextManager.Get("shuttle"); int nameHeight = (int)GUIStyle.LargeFont.MeasureString(sub.Info.DisplayName, true).Y; int classHeight = (int)GUIStyle.SubHeadingFont.MeasureString(className).Y; @@ -1763,7 +1763,10 @@ namespace Barotrauma } else { - var specsListBox = new GUIListBox(new RectTransform(new Vector2(1f, 0.57f), paddedFrame.RectTransform, Anchor.BottomLeft, Pivot.BottomLeft)); + var specsListBox = new GUIListBox(new RectTransform(new Vector2(1f, 0.57f), paddedFrame.RectTransform, Anchor.BottomLeft, Pivot.BottomLeft)) + { + CurrentSelectMode = GUIListBox.SelectMode.None + }; sub.Info.CreateSpecsWindow(specsListBox, GUIStyle.Font, includeTitle: false, includeClass: false, includeDescription: true); } } @@ -1954,14 +1957,15 @@ namespace Barotrauma Point iconSize = cornerIcon.RectTransform.NonScaledSize; cornerIcon.RectTransform.AbsoluteOffset = new Point(iconSize.X / 2, iconSize.Y / 2); - if (subTree.TalentOptionStages.Count <= i) { continue; } + if (subTree.TalentOptionStages.Length <= i) { continue; } TalentOption talentOption = subTree.TalentOptionStages[i]; GUILayoutGroup talentOptionCenterGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.75f, 0.7f), talentOptionFrame.RectTransform, Anchor.Center), childAnchor: Anchor.CenterLeft); GUILayoutGroup talentOptionLayoutGroup = new GUILayoutGroup(new RectTransform(Vector2.One, talentOptionCenterGroup.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterLeft) { Stretch = true }; - foreach (TalentPrefab talent in talentOption.Talents.OrderBy(t => t.Identifier)) + foreach (Identifier talentId in talentOption.TalentIdentifiers.OrderBy(t => t)) { + if (!TalentPrefab.TalentPrefabs.TryGet(talentId, out TalentPrefab talent)) { continue; } GUIFrame talentFrame = new GUIFrame(new RectTransform(Vector2.One, talentOptionLayoutGroup.RectTransform), style: null) { CanBeFocused = false diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/UpgradeStore.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/UpgradeStore.cs index fc4cc62f2..db946f01a 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/UpgradeStore.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/UpgradeStore.cs @@ -17,7 +17,7 @@ using PlayerBalanceElement = Barotrauma.CampaignUI.PlayerBalanceElement; namespace Barotrauma { - internal class UpgradeStore + internal sealed class UpgradeStore { public readonly struct CategoryData { @@ -847,7 +847,8 @@ namespace Barotrauma foreach (UpgradePrefab prefab in prefabs) { - CreateUpgradeEntry(prefab, category, parent.Content, entitiesOnSub); + if (prefab.MaxLevel is 0) { continue; } + CreateUpgradeEntry(prefab, category, parent.Content, submarine, entitiesOnSub); } } @@ -1112,7 +1113,7 @@ namespace Barotrauma GUILayoutGroup? buyButtonLayout = null; if (addProgressBar) - { + { progressLayout = new GUILayoutGroup(rectT(1, 0.25f, textLayout), isHorizontal: true, childAnchor: Anchor.CenterLeft) { UserData = "progressbar" }; new GUIProgressBar(rectT(0.8f, 0.75f, progressLayout), 0.0f, GUIStyle.Orange); new GUITextBlock(rectT(0.2f, 1, progressLayout), string.Empty, font: GUIStyle.SmallFont, textAlignment: Alignment.Center) { Padding = Vector4.Zero }; @@ -1124,7 +1125,11 @@ namespace Barotrauma //negative price = refund if (price < 0) { formattedPrice = "+" + formattedPrice; } buyButtonLayout = new GUILayoutGroup(rectT(0.2f, 1, prefabLayout), childAnchor: Anchor.TopCenter) { UserData = "buybutton" }; - var priceText = new GUITextBlock(rectT(1, 0.2f, buyButtonLayout), formattedPrice, textAlignment: Alignment.Center); + var priceText = new GUITextBlock(rectT(1, 0.2f, buyButtonLayout), formattedPrice, textAlignment: Alignment.Center) + { + //prices on swappable items are always visible, upgrade prices are enabled in UpdateUpgradeEntry for purchasable upgrades + Visible = userData is ItemPrefab + }; if (price < 0) { priceText.TextColor = GUIStyle.Green; @@ -1183,9 +1188,10 @@ namespace Barotrauma } } - private void CreateUpgradeEntry(UpgradePrefab prefab, UpgradeCategory category, GUIComponent parent, List? itemsOnSubmarine) + private void CreateUpgradeEntry(UpgradePrefab prefab, UpgradeCategory category, GUIComponent parent, Submarine submarine, List? itemsOnSubmarine) { - if (Campaign is null) { return; } + Submarine? sub = GameMain.GameSession?.Submarine ?? Submarine.MainSub; + if (Campaign is null || sub is null) { return; } GUIFrame prefabFrame = CreateUpgradeFrame(prefab, category, Campaign, rectT(1f, 0.25f, parent)); var prefabLayout = prefabFrame.GetChild(); @@ -1201,7 +1207,7 @@ namespace Barotrauma var buyButtonLayout = childLayouts[2]; var buyButton = buyButtonLayout.GetChild(); - if (!HasPermission || (itemsOnSubmarine != null && !itemsOnSubmarine.Any(it => category.CanBeApplied(it, prefab)))) + if (!HasPermission || !prefab.IsApplicable(submarine.Info) || (itemsOnSubmarine != null && !itemsOnSubmarine.Any(it => category.CanBeApplied(it, prefab)))) { prefabFrame.Enabled = false; description.Enabled = false; @@ -1446,7 +1452,7 @@ namespace Barotrauma * |--------------------------------------------------| * | name | * |--------------------------------------------------| - * | class | + * | class + tier | * |--------------------------------------------------| * | description | * | | @@ -1456,13 +1462,31 @@ namespace Barotrauma submarineInfoFrame = new GUILayoutGroup(rectT(0.25f, 0.2f, mainStoreLayout, Anchor.TopRight)) { IgnoreLayoutGroups = true }; // submarine name new GUITextBlock(rectT(1, 0, submarineInfoFrame), submarine.Info.DisplayName, textAlignment: Alignment.Right, font: GUIStyle.LargeFont); - // submarine class - new GUITextBlock(rectT(1, 0, submarineInfoFrame), $"{TextManager.GetWithVariable("submarineclass.classsuffixformat", "[type]", TextManager.Get($"submarineclass.{submarine.Info.SubmarineClass}"))}", textAlignment: Alignment.Right, font: GUIStyle.Font); + + GUILayoutGroup classLayout = new GUILayoutGroup(rectT(1, 0.15f, submarineInfoFrame), isHorizontal: true) { Stretch = true }; + LocalizedString classText = $"{TextManager.GetWithVariable("submarineclass.classsuffixformat", "[type]", TextManager.Get($"submarineclass.{submarine.Info.SubmarineClass}"))}"; + // submarine class + tier + new GUITextBlock(rectT(0.8f, 1, classLayout), classText, textAlignment: Alignment.Right, font: GUIStyle.Font) + { + ToolTip = TextManager.Get("submarineclass.description") + '\n' + TextManager.Get($"submarineclass.{submarine.Info.SubmarineClass}.description") + }; + int tier = submarine.Info.Tier; + string tierStyle = $"SubmarineTier.{tier}"; + if (GUIStyle.GetComponentStyle(tierStyle) != null) + { + LocalizedString tooltip = TextManager.Get("submarinetier.description").Fallback(string.Empty); + new GUIImage(rectT(0.15f, 1, classLayout), style: tierStyle, scaleToFit: false) + { + ToolTip = tooltip + }; + } + var description = new GUITextBlock(rectT(1, 0, submarineInfoFrame), submarine.Info.Description, textAlignment: Alignment.Right, wrap: true); submarineInfoFrame.RectTransform.ScreenSpaceOffset = new Point(0, (int)(16 * GUI.Scale)); - + description.Padding = new Vector4(description.Padding.X, 24 * GUI.Scale, description.Padding.Z, description.Padding.W); - List pointsOfInterest = (from category in UpgradeCategory.Categories from item in submarine.GetItems(UpgradeManager.UpgradeAlsoConnectedSubs) where category.CanBeApplied(item, null) && item.IsPlayerTeamInteractable select item).Cast().ToList(); + List pointsOfInterest = (from category in UpgradeCategory.Categories from item in submarine.GetItems(UpgradeManager.UpgradeAlsoConnectedSubs) + where category.CanBeApplied(item, null) && item.IsPlayerTeamInteractable select item).Cast().Distinct().ToList(); List ids = GameMain.GameSession.SubmarineInfo?.LeftBehindDockingPortIDs ?? new List(); pointsOfInterest.AddRange(submarine.GetItems(UpgradeManager.UpgradeAlsoConnectedSubs).Where(item => ids.Contains(item.ID))); @@ -1610,6 +1634,7 @@ namespace Barotrauma List textBlocks = buttonParent.GetAllChildren().ToList(); GUITextBlock priceLabel = textBlocks[0]; + priceLabel.Visible = true; int price = prefab.Price.GetBuyprice(campaign.UpgradeManager.GetUpgradeLevel(prefab, category), campaign.Map?.CurrentLocation); if (priceLabel != null && !WaitForServerUpdate) @@ -1648,9 +1673,15 @@ namespace Barotrauma IEnumerable applicableCategories) { // Disables the parent and only re-enables if the submarine contains valid items - if (!category.IsWallUpgrade && drawnSubmarine != null) + if (!category.IsWallUpgrade && drawnSubmarine?.Info != null) { - if (applicableCategories.Contains(category)) + if (UpgradePrefab.Prefabs.None(p => p.UpgradeCategories.Contains(category) && p.GetMaxLevel(drawnSubmarine.Info) > 0)) + { + parent.ToolTip = TextManager.Get("upgradecategorynotapplicable"); + parent.Enabled = false; + parent.SelectedColor = GUIStyle.Red * 0.5f; + } + else if (applicableCategories.Contains(category)) { parent.Enabled = true; parent.SelectedColor = parent.Style.SelectedColor; @@ -1670,14 +1701,27 @@ namespace Barotrauma { if (component.UserData != prefab) { continue; } + if (prefab.MaxLevel is 0) + { + component.Visible = false; + continue; + } + Dictionary styles = GUIStyle.GetComponentStyle("upgradeindicator").ChildStyles; if (!styles.ContainsKey("upgradeindicatoron") || !styles.ContainsKey("upgradeindicatordim") || !styles.ContainsKey("upgradeindicatoroff")) { continue; } GUIComponentStyle onStyle = styles["upgradeindicatoron".ToIdentifier()]; GUIComponentStyle dimStyle = styles["upgradeindicatordim".ToIdentifier()]; GUIComponentStyle offStyle = styles["upgradeindicatoroff".ToIdentifier()]; + int maxLevel = prefab.MaxLevel; - if (campaign.UpgradeManager.GetUpgradeLevel(prefab, category) >= prefab.MaxLevel) + if (maxLevel == 0) + { + SetOff(); + continue; + } + + if (campaign.UpgradeManager.GetUpgradeLevel(prefab, category) >= maxLevel) { // we check this to avoid flickering from re-applying the same style if (image.Style == onStyle) { continue; } @@ -1690,13 +1734,18 @@ namespace Barotrauma } else { - if (image.Style == offStyle) { continue; } + SetOff(); + } + + void SetOff() + { + if (image.Style == offStyle) { return; } image.ApplyStyle(offStyle); } } } } - + private void ScrollToCategory(Predicate predicate, GUIListBox.PlaySelectSound playSelectSound = GUIListBox.PlaySelectSound.No) { if (currentStoreLayout == null) { return; } diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/VideoPlayer.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/VideoPlayer.cs index 5b596f54d..6152fa2dc 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/VideoPlayer.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/VideoPlayer.cs @@ -131,9 +131,9 @@ namespace Barotrauma LoadContent(contentPath, videoSettings, textSettings, contentId, startPlayback, new RawLString(""), null); } - public void LoadContent(string contentPath, VideoSettings videoSettings, TextSettings textSettings, Identifier contentId, bool startPlayback, LocalizedString objective, Action callback = null) + public void LoadContent(string contentPath, VideoSettings videoSettings, TextSettings textSettings, Identifier contentId, bool startPlayback, LocalizedString objective, Action onStop = null) { - callbackOnStop = callback; + callbackOnStop = onStop; filePath = contentPath + videoSettings.File; if (!File.Exists(filePath)) diff --git a/Barotrauma/BarotraumaClient/ClientSource/GameMain.cs b/Barotrauma/BarotraumaClient/ClientSource/GameMain.cs index b1dcac1fe..ffd792e44 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GameMain.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GameMain.cs @@ -557,6 +557,8 @@ namespace Barotrauma new GUIMessageBox(TextManager.Get("Error"), TextManager.Get(steamError)); } + GameSettings.OnGameMainHasLoaded?.Invoke(); + TitleScreen.LoadState = 100.0f; HasLoaded = true; if (GameSettings.CurrentConfig.VerboseLogging) diff --git a/Barotrauma/BarotraumaClient/ClientSource/GameSession/CrewManager.cs b/Barotrauma/BarotraumaClient/ClientSource/GameSession/CrewManager.cs index 7614a8b8d..01f09f376 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GameSession/CrewManager.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GameSession/CrewManager.cs @@ -183,14 +183,13 @@ namespace Barotrauma { chatBox.ToggleButton = new GUIButton(new RectTransform(new Point((int)(182f * GUI.Scale * 0.4f), (int)(99f * GUI.Scale * 0.4f)), chatBox.GUIFrame.Parent.RectTransform), style: "ChatToggleButton") { - ToolTip = TextManager.Get("chat"), + ToolTip = TextManager.GetWithVariable("hudbutton.chatbox", "[key]", GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.ChatBox)), ClampMouseRectToParent = false }; chatBox.ToggleButton.RectTransform.AbsoluteOffset = new Point(0, HUDLayoutSettings.ChatBoxArea.Height - chatBox.ToggleButton.Rect.Height); chatBox.ToggleButton.OnClicked += (GUIButton btn, object userdata) => { - chatBox.ToggleOpen = !chatBox.ToggleOpen; - chatBox.CloseAfterMessageSent = false; + chatBox.Toggle(); return true; }; } diff --git a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/MultiPlayerCampaign.cs b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/MultiPlayerCampaign.cs index a757aa34a..6fff8e5e9 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/MultiPlayerCampaign.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/MultiPlayerCampaign.cs @@ -540,37 +540,37 @@ namespace Barotrauma { System.Diagnostics.Debug.Assert(map.Locations.Count < UInt16.MaxValue); - msg.Write(map.CurrentLocationIndex == -1 ? UInt16.MaxValue : (UInt16)map.CurrentLocationIndex); - msg.Write(map.SelectedLocationIndex == -1 ? UInt16.MaxValue : (UInt16)map.SelectedLocationIndex); + msg.WriteUInt16(map.CurrentLocationIndex == -1 ? UInt16.MaxValue : (UInt16)map.CurrentLocationIndex); + msg.WriteUInt16(map.SelectedLocationIndex == -1 ? UInt16.MaxValue : (UInt16)map.SelectedLocationIndex); var selectedMissionIndices = map.GetSelectedMissionIndices(); - msg.Write((byte)selectedMissionIndices.Count()); + msg.WriteByte((byte)selectedMissionIndices.Count()); foreach (int selectedMissionIndex in selectedMissionIndices) { - msg.Write((byte)selectedMissionIndex); + msg.WriteByte((byte)selectedMissionIndex); } - msg.Write(PurchasedHullRepairs); - msg.Write(PurchasedItemRepairs); - msg.Write(PurchasedLostShuttles); + msg.WriteBoolean(PurchasedHullRepairs); + msg.WriteBoolean(PurchasedItemRepairs); + msg.WriteBoolean(PurchasedLostShuttles); WriteItems(msg, CargoManager.ItemsInBuyCrate); WriteItems(msg, CargoManager.ItemsInSellFromSubCrate); WriteItems(msg, CargoManager.PurchasedItems); WriteItems(msg, CargoManager.SoldItems); - msg.Write((ushort)UpgradeManager.PurchasedUpgrades.Count); + msg.WriteUInt16((ushort)UpgradeManager.PurchasedUpgrades.Count); foreach (var (prefab, category, level) in UpgradeManager.PurchasedUpgrades) { - msg.Write(prefab.Identifier); - msg.Write(category.Identifier); - msg.Write((byte)level); + msg.WriteIdentifier(prefab.Identifier); + msg.WriteIdentifier(category.Identifier); + msg.WriteByte((byte)level); } - msg.Write((ushort)UpgradeManager.PurchasedItemSwaps.Count); + msg.WriteUInt16((ushort)UpgradeManager.PurchasedItemSwaps.Count); foreach (var itemSwap in UpgradeManager.PurchasedItemSwaps) { - msg.Write(itemSwap.ItemToRemove.ID); - msg.Write(itemSwap.ItemToInstall?.Identifier ?? Identifier.Empty); + msg.WriteUInt16(itemSwap.ItemToRemove.ID); + msg.WriteIdentifier(itemSwap.ItemToInstall?.Identifier ?? Identifier.Empty); } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/SinglePlayerCampaign.cs b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/SinglePlayerCampaign.cs index 06f1d24df..dc7bc12b1 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/SinglePlayerCampaign.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/SinglePlayerCampaign.cs @@ -1,12 +1,8 @@ -using Barotrauma.Extensions; -using Microsoft.Xna.Framework; -using Microsoft.Xna.Framework.Graphics; +using Microsoft.Xna.Framework; using System; using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using System.Xml.Linq; -using Barotrauma.Networking; namespace Barotrauma { @@ -49,6 +45,31 @@ namespace Barotrauma private bool showCampaignResetText; + public override bool PurchasedHullRepairs + { + get { return PurchasedHullRepairsInLatestSave; } + set + { + PurchasedHullRepairsInLatestSave = value; + } + } + public override bool PurchasedLostShuttles + { + get { return PurchasedLostShuttlesInLatestSave; } + set + { + PurchasedLostShuttlesInLatestSave = value; + } + } + public override bool PurchasedItemRepairs + { + get { return PurchasedItemRepairsInLatestSave; } + set + { + PurchasedItemRepairsInLatestSave = value; + } + } + #region Constructors/initialization /// @@ -214,7 +235,7 @@ namespace Barotrauma base.Start(); CargoManager.CreatePurchasedItems(); UpgradeManager.ApplyUpgrades(); - UpgradeManager.SanityCheckUpgrades(Submarine.MainSub); + UpgradeManager.SanityCheckUpgrades(); if (!savedOnStart) { diff --git a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/CaptainTutorial.cs b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/CaptainTutorial.cs deleted file mode 100644 index beb99fcb6..000000000 --- a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/CaptainTutorial.cs +++ /dev/null @@ -1,346 +0,0 @@ -using Barotrauma.Items.Components; -using Barotrauma.Networking; -using Microsoft.Xna.Framework; -using System.Collections.Generic; -using System.Linq; - -namespace Barotrauma.Tutorials -{ - class CaptainTutorial : ScenarioTutorial - { - // Room 1 - private float shakeTimer = 1f; - private float shakeAmount = 20f; - - // Room 2 - private Door captain_firstDoor; - private LightComponent captain_firstDoorLight; - - // Room 3 - private Character captain_medic; - private MotionSensor captain_medicObjectiveSensor; - private Vector2 captain_medicSpawnPos; - private Door tutorial_submarineDoor; - private LightComponent tutorial_submarineDoorLight; - - // Submarine - private MotionSensor captain_enteredSubmarineSensor; - private Steering captain_navConsole; - private Sonar captain_sonar; - private Item captain_statusMonitor; - private Character captain_security; - private Character captain_mechanic; - private Character captain_engineer; - private Reactor tutorial_submarineReactor; - private Door tutorial_lockedDoor_1; - private Door tutorial_lockedDoor_2; - - // Variables - private Character captain; - private LocalizedString radioSpeakerName; - private Sprite captain_steerIcon; - private Color captain_steerIconColor; - - public CaptainTutorial() : base("tutorial.captaintraining".ToIdentifier(), - new Segment( - "Captain.CommandMedic".ToIdentifier(), - "Captain.CommandMedicObjective".ToIdentifier(), - TutorialContentType.ManualVideo, - textContent: new Segment.Text { Tag = "Captain.CommandMedicText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center }, - videoContent: new Segment.Video { File = "tutorial_command.webm", TextTag = "Captain.CommandMedicText".ToIdentifier(), Width = 450, Height = 80 }), - new Segment( - "Captain.CommandMechanic".ToIdentifier(), - "Captain.CommandMechanicObjective".ToIdentifier(), - TutorialContentType.TextOnly, - textContent: new Segment.Text { Tag = "Captain.CommandMechanicText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center }), - new Segment( - "Captain.CommandSecurity".ToIdentifier(), - "Captain.CommandSecurityObjective".ToIdentifier(), - TutorialContentType.TextOnly, - textContent: new Segment.Text { Tag = "Captain.CommandSecurityText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center }), - new Segment( - "Captain.CommandEngineer".ToIdentifier(), - "Captain.CommandEngineerObjective".ToIdentifier(), - TutorialContentType.TextOnly, - textContent: new Segment.Text { Tag = "Captain.CommandEngineerText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center }), - new Segment( - "Captain.Undock".ToIdentifier(), - "Captain.UndockObjective".ToIdentifier(), - TutorialContentType.ManualVideo, - textContent: new Segment.Text { Tag = "Captain.UndockText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center }, - videoContent: new Segment.Video { File = "tutorial_undock.webm", TextTag = "Captain.UndockText".ToIdentifier(), Width = 450, Height = 80 }), - new Segment( - "Captain.Navigate".ToIdentifier(), - "Captain.NavigateObjective".ToIdentifier(), - TutorialContentType.ManualVideo, - textContent: new Segment.Text { Tag = "Captain.NavigateText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center }, - videoContent: new Segment.Video { File = "tutorial_navigation.webm", TextTag = "Captain.NavigateText".ToIdentifier(), Width = 450, Height = 80 }), - new Segment( - "Captain.Dock".ToIdentifier(), - "Captain.DockObjective".ToIdentifier(), - TutorialContentType.ManualVideo, - textContent: new Segment.Text { Tag = "Captain.DockText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center }, - videoContent: new Segment.Video { File = "tutorial_docking.webm", TextTag = "Captain.DockText".ToIdentifier(), Width = 450, Height = 80 })) - { } - - protected override CharacterInfo GetCharacterInfo() - { - return new CharacterInfo( - CharacterPrefab.HumanSpeciesName, - jobOrJobPrefab: new Job( - JobPrefab.Prefabs["captain"], Rand.RandSync.Unsynced, 0, - new Skill("medical".ToIdentifier(), 20), - new Skill("weapons".ToIdentifier(), 20), - new Skill("mechanical".ToIdentifier(), 20), - new Skill("electrical".ToIdentifier(), 20), - new Skill("helm".ToIdentifier(), 70))); - } - - protected override void Initialize() - { - captain = Character.Controlled; - radioSpeakerName = TextManager.Get("Tutorial.Radio.Watchman"); - GameMain.GameSession.CrewManager.AllowCharacterSwitch = false; - - foreach (Item item in captain.Inventory.AllItemsMod) - { - if (item.HasTag("identitycard") || item.HasTag("mobileradio")) { continue; } - item.Unequip(captain); - captain.Inventory.RemoveItem(item); - } - - var steerOrder = OrderPrefab.Prefabs["steer"]; - captain_steerIcon = steerOrder.SymbolSprite; - captain_steerIconColor = steerOrder.Color; - - // Room 2 - captain_firstDoor = Item.ItemList.Find(i => i.HasTag("captain_firstdoor")).GetComponent(); - captain_firstDoorLight = Item.ItemList.Find(i => i.HasTag("captain_firstdoorlight")).GetComponent(); - - SetDoorAccess(captain_firstDoor, captain_firstDoorLight, true); - - // Room 3 - captain_medicObjectiveSensor = Item.ItemList.Find(i => i.HasTag("captain_medicobjectivesensor")).GetComponent(); - captain_medicSpawnPos = Item.ItemList.Find(i => i.HasTag("captain_medicspawnpos")).WorldPosition; - tutorial_submarineDoor = Item.ItemList.Find(i => i.HasTag("tutorial_submarinedoor")).GetComponent(); - tutorial_submarineDoorLight = Item.ItemList.Find(i => i.HasTag("tutorial_submarinedoorlight")).GetComponent(); - var medicInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobOrJobPrefab: JobPrefab.Get("medicaldoctor".ToIdentifier())) - { - TeamID = CharacterTeamType.Team1 - }; - captain_medic = Character.Create(medicInfo, captain_medicSpawnPos, "medicaldoctor"); - captain_medic.GiveJobItems(null); - captain_medic.CanSpeak = captain_medic.AIController.Enabled = false; - SetDoorAccess(tutorial_submarineDoor, tutorial_submarineDoorLight, false); - - // Submarine - captain_enteredSubmarineSensor = Item.ItemList.Find(i => i.HasTag("captain_enteredsubmarinesensor")).GetComponent(); - tutorial_submarineReactor = Item.ItemList.Find(i => i.HasTag("engineer_submarinereactor")).GetComponent(); - captain_navConsole = Item.ItemList.Find(i => i.HasTag("command")).GetComponent(); - captain_sonar = captain_navConsole.Item.GetComponent(); - captain_statusMonitor = Item.ItemList.Find(i => i.HasTag("captain_statusmonitor")); - - tutorial_submarineReactor.CanBeSelected = false; - tutorial_submarineReactor.IsActive = tutorial_submarineReactor.AutoTemp = false; - - tutorial_lockedDoor_1 = Item.ItemList.Find(i => i.HasTag("tutorial_lockeddoor_1")).GetComponent(); - tutorial_lockedDoor_2 = Item.ItemList.Find(i => i.HasTag("tutorial_lockeddoor_2")).GetComponent(); - SetDoorAccess(tutorial_lockedDoor_1, null, false); - SetDoorAccess(tutorial_lockedDoor_2, null, false); - - var mechanicInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobOrJobPrefab: JobPrefab.Get("mechanic".ToIdentifier())) - { - TeamID = CharacterTeamType.Team1 - }; - captain_mechanic = Character.Create(mechanicInfo, WayPoint.GetRandom(SpawnType.Human, mechanicInfo.Job?.Prefab, Submarine.MainSub).WorldPosition, "mechanic"); - captain_mechanic.GiveJobItems(); - - var securityInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobOrJobPrefab: JobPrefab.Get("securityofficer".ToIdentifier())) - { - TeamID = CharacterTeamType.Team1 - }; - captain_security = Character.Create(securityInfo, WayPoint.GetRandom(SpawnType.Human, securityInfo.Job?.Prefab, Submarine.MainSub).WorldPosition, "securityofficer"); - captain_security.GiveJobItems(); - - var engineerInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobOrJobPrefab: JobPrefab.Get("engineer".ToIdentifier())) - { - TeamID = CharacterTeamType.Team1 - }; - captain_engineer = Character.Create(engineerInfo, WayPoint.GetRandom(SpawnType.Human, engineerInfo.Job?.Prefab, Submarine.MainSub).WorldPosition, "engineer"); - captain_engineer.GiveJobItems(); - - captain_mechanic.CanSpeak = captain_security.CanSpeak = captain_engineer.CanSpeak = false; - captain_mechanic.AIController.Enabled = captain_security.AIController.Enabled = captain_engineer.AIController.Enabled = false; - - GameAnalyticsManager.AddDesignEvent("Tutorial:CaptainTutorial:Started"); - GameAnalyticsManager.AddDesignEvent("Tutorial:Started"); - } - - public override IEnumerable UpdateState() - { - while (GameMain.Instance.LoadingScreenOpen) yield return null; - - // Room 1 - while (shakeTimer > 0.0f) // Wake up, shake - { - shakeTimer -= 0.1f; - GameMain.GameScreen.Cam.Shake = shakeAmount; - yield return new WaitForSeconds(0.1f, false); - } - - // Room 2 - do { yield return null; } while (!captain_firstDoor.IsOpen); - captain_medic.AIController.Enabled = true; - - // Room 3 - do { yield return null; } while (!captain_medicObjectiveSensor.MotionDetected); - GameMain.GameSession?.CrewManager.AddSinglePlayerChatMessage(captain_medic.Info.DisplayName, TextManager.Get("Captain.Radio.Medic"), ChatMessageType.Radio, null); - yield return new WaitForSeconds(2f, false); - GameMain.GameSession.CrewManager.AutoShowCrewList(); - GameMain.GameSession.CrewManager.AddCharacter(captain_medic); - TriggerTutorialSegment(0, GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Command)); - do - { - yield return null; - // TODO: Rework order highlighting for new command UI - // GameMain.GameSession.CrewManager.HighlightOrderButton(captain_medic, "follow", highlightColor, new Vector2(5, 5)); - } - while (!HasOrder(captain_medic, "follow")); - SetDoorAccess(tutorial_submarineDoor, tutorial_submarineDoorLight, true); - RemoveCompletedObjective(0); - GameAnalyticsManager.AddDesignEvent("Tutorial:CaptainTutorial:Objective0"); - - // Submarine - do { yield return null; } while (!captain_enteredSubmarineSensor.MotionDetected); - yield return new WaitForSeconds(3f, false); - captain_mechanic.AIController.Enabled = captain_security.AIController.Enabled = captain_engineer.AIController.Enabled = true; - TriggerTutorialSegment(1, GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Command)); - GameMain.GameSession.CrewManager.AddCharacter(captain_mechanic); - do - { - yield return null; - // TODO: Rework order highlighting for new command UI - // GameMain.GameSession.CrewManager.HighlightOrderButton(captain_mechanic, "repairsystems", highlightColor, new Vector2(5, 5)); - //HighlightOrderOption("jobspecific"); - } while (!HasOrder(captain_mechanic, "repairsystems") && !HasOrder(captain_mechanic, "repairmechanical") && !HasOrder(captain_mechanic, "repairelectrical")); - RemoveCompletedObjective(1); - GameAnalyticsManager.AddDesignEvent("Tutorial:CaptainTutorial:Objective1"); - - yield return new WaitForSeconds(2f, false); - TriggerTutorialSegment(2, GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Command)); - GameMain.GameSession.CrewManager.AddCharacter(captain_security); - do - { - yield return null; - // TODO: Rework order highlighting for new command UI - // GameMain.GameSession.CrewManager.HighlightOrderButton(captain_security, "operateweapons", highlightColor, new Vector2(5, 5)); - HighlightOrderOption("fireatwill"); - } - while (!HasOrder(captain_security, "operateweapons")); - RemoveCompletedObjective(2); - GameAnalyticsManager.AddDesignEvent("Tutorial:CaptainTutorial:Objective2"); - - yield return new WaitForSeconds(4f, false); - TriggerTutorialSegment(3, GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Command)); - GameMain.GameSession.CrewManager.AddCharacter(captain_engineer); - tutorial_submarineReactor.CanBeSelected = true; - //recreate autonomous objectives to make sure the engineer didn't abandon the operate reactor objective because it was not selectable - (captain_engineer.AIController as HumanAIController).ObjectiveManager.CreateAutonomousObjectives(); - do - { - yield return null; - // TODO: Rework order highlighting for new command UI - // GameMain.GameSession.CrewManager.HighlightOrderButton(captain_engineer, "operatereactor", highlightColor, new Vector2(5, 5)); - HighlightOrderOption("powerup"); - } - while (!HasOrder(captain_engineer, "operatereactor", "powerup")); - RemoveCompletedObjective(3); - GameAnalyticsManager.AddDesignEvent("Tutorial:CaptainTutorial:Objective3"); - - do { yield return null; } while (!tutorial_submarineReactor.IsActive); // Wait until reactor on - TriggerTutorialSegment(4); - while (ContentRunning) yield return null; - captain.AddActiveObjectiveEntity(captain_navConsole.Item, captain_steerIcon, captain_steerIconColor); - SetHighlight(captain_navConsole.Item, true); - SetHighlight(captain_sonar.Item, true); - SetHighlight(captain_statusMonitor, true); - do - { - //captain_navConsoleCustomInterface.HighlightElement(0, uiHighlightColor, duration: 1.0f, pulsateAmount: 0.0f); - yield return new WaitForSeconds(1.0f, false); - } while (Submarine.MainSub.DockedTo.Any()); - captain_navConsole.UseAutoDocking = false; - RemoveCompletedObjective(4); - GameAnalyticsManager.AddDesignEvent("Tutorial:CaptainTutorial:Objective4"); - - yield return new WaitForSeconds(2f, false); - TriggerTutorialSegment(5); // Navigate to destination - do - { - if (IsSelectedItem(captain_navConsole.Item)) - { - if (captain_sonar.SonarModeSwitch.Frame.FlashTimer <= 0) - { - captain_sonar.SonarModeSwitch.Frame.Flash(highlightColor, 1.5f, false, false, new Vector2(2.5f, 2.5f)); - } - } - yield return null; - } while (captain_sonar.CurrentMode != Sonar.Mode.Active); - do { yield return null; } while (Vector2.Distance(Submarine.MainSub.WorldPosition, Level.Loaded.EndPosition) > 4000f); - RemoveCompletedObjective(5); - GameAnalyticsManager.AddDesignEvent("Tutorial:CaptainTutorial:Objective5"); - - captain_navConsole.UseAutoDocking = true; - yield return new WaitForSeconds(4f, false); - TriggerTutorialSegment(6); // Docking - do - { - //captain_navConsoleCustomInterface.HighlightElement(0, uiHighlightColor, duration: 1.0f, pulsateAmount: 0.0f); - yield return new WaitForSeconds(1.0f, false); - } while (!Submarine.MainSub.AtEndExit || !Submarine.MainSub.DockedTo.Any()); - RemoveCompletedObjective(6); - GameAnalyticsManager.AddDesignEvent("Tutorial:CaptainTutorial:Objective6"); - - yield return new WaitForSeconds(3f, false); - GameMain.GameSession?.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.GetWithVariable("Captain.Radio.Complete", "[OUTPOSTNAME]", GameMain.GameSession.EndLocation.Name), ChatMessageType.Radio, null); - SetHighlight(captain_navConsole.Item, false); - SetHighlight(captain_sonar.Item, false); - SetHighlight(captain_statusMonitor, false); - captain.RemoveActiveObjectiveEntity(captain_navConsole.Item); - - GameAnalyticsManager.AddDesignEvent("Tutorial:CaptainTutorial:Completed"); - CoroutineManager.StartCoroutine(TutorialCompleted()); - } - - private void HighlightOrderOption(string option) - { - if (GameMain.GameSession.CrewManager.OrderOptionButtons.Count == 0) return; - var order = GameMain.GameSession.CrewManager.OrderOptionButtons[0].UserData as Order; - - int orderIndex = 0; - for (int i = 0; i < GameMain.GameSession.CrewManager.OrderOptionButtons.Count; i++) - { - if (orderIndex >= order.Options.Length) - { - orderIndex = 0; - } - if (order.Options[orderIndex] == option) - { - if (GameMain.GameSession.CrewManager.OrderOptionButtons[i].FlashTimer <= 0) - { - GameMain.GameSession.CrewManager.OrderOptionButtons[i].Flash(highlightColor); - } - } - - orderIndex++; - } - } - - private bool IsSelectedItem(Item item) - { - return - captain?.SelectedItem == item || - (captain?.SelectedItem?.linkedTo?.Contains(item) ?? false); - } - } -} diff --git a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/DoctorTutorial.cs b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/DoctorTutorial.cs deleted file mode 100644 index 442f36b07..000000000 --- a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/DoctorTutorial.cs +++ /dev/null @@ -1,521 +0,0 @@ -using Barotrauma.Items.Components; -using Barotrauma.Networking; -using Microsoft.Xna.Framework; -using System; -using System.Collections.Generic; -using System.Linq; - -namespace Barotrauma.Tutorials -{ - class DoctorTutorial : ScenarioTutorial - { - // Room 1 - private float shakeTimer = 1f; - private float shakeAmount = 20f; - - private LocalizedString radioSpeakerName; - private Character doctor; - - private ItemContainer doctor_suppliesCabinet; - private ItemContainer doctor_medBayCabinet; - private Character patient1, patient2; - private List subPatients; - private Hull medBay; - - private Door doctor_firstDoor; - private Door doctor_secondDoor; - private Door doctor_thirdDoor; - private Door tutorial_upperFinalDoor; - private Door tutorial_lockedDoor_2; - - private LightComponent doctor_firstDoorLight; - private LightComponent doctor_secondDoorLight; - private LightComponent doctor_thirdDoorLight; - private Door tutorial_submarineDoor; - private LightComponent tutorial_submarineDoorLight; - - // Variables - private Sprite doctor_firstAidIcon; - private Color doctor_firstAidIconColor; - - - public DoctorTutorial() : base("tutorial.medicaldoctortraining".ToIdentifier(), - new Segment( - "Doctor.Supplies".ToIdentifier(), - "Doctor.SuppliesObjective".ToIdentifier(), - TutorialContentType.TextOnly, - textContent: new Segment.Text { Tag = "Doctor.SuppliesText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center }), - new Segment( - "Doctor.OpenMedicalInterface".ToIdentifier(), - "Doctor.OpenMedicalInterfaceObjective".ToIdentifier(), - TutorialContentType.ManualVideo, - textContent: new Segment.Text { Tag = "Doctor.OpenMedicalInterfaceText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center }, - videoContent: new Segment.Video { File = "tutorial_medinterface1.webm", TextTag = "Doctor.OpenMedicalInterfaceText".ToIdentifier(), Width = 450, Height = 80 }), - new Segment( - "Doctor.FirstAidSelf".ToIdentifier(), - "Doctor.FirstAidSelfObjective".ToIdentifier(), - TutorialContentType.ManualVideo, - textContent: new Segment.Text { Tag = "Doctor.FirstAidSelfText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center }, - videoContent: new Segment.Video { File = "tutorial_medinterface1.webm", TextTag = "Doctor.FirstAidSelfText".ToIdentifier(), Width = 450, Height = 80 }), - new Segment( - "Doctor.Medbay".ToIdentifier(), - "Doctor.MedbayObjective".ToIdentifier(), - TutorialContentType.ManualVideo, - textContent: new Segment.Text { Tag = "Doctor.MedbayText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center }, - videoContent: new Segment.Video { File = "tutorial_command.webm", TextTag = "Doctor.MedbayText".ToIdentifier(), Width = 450, Height = 80 }), - new Segment( - "Doctor.TreatBurns".ToIdentifier(), - "Doctor.TreatBurnsObjective".ToIdentifier(), - TutorialContentType.ManualVideo, - textContent: new Segment.Text { Tag = "Doctor.TreatBurnsText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center }, - videoContent: new Segment.Video { File = "tutorial_medinterface2.webm", TextTag = "Doctor.TreatBurnsText".ToIdentifier(), Width = 450, Height = 80 }), - new Segment( - "Doctor.CPR".ToIdentifier(), - "Doctor.CPRObjective".ToIdentifier(), - TutorialContentType.ManualVideo, - textContent: new Segment.Text { Tag = "Doctor.CPRText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center }, - videoContent: new Segment.Video { File = "tutorial_cpr.webm", TextTag = "Doctor.CPRText".ToIdentifier(), Width = 450, Height = 80 }), - new Segment( - "Doctor.Submarine".ToIdentifier(), - "Doctor.SubmarineObjective".ToIdentifier(), - TutorialContentType.TextOnly, - textContent: new Segment.Text { Tag = "Doctor.SubmarineText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center })) - { } - - protected override CharacterInfo GetCharacterInfo() - { - return new CharacterInfo( - CharacterPrefab.HumanSpeciesName, - jobOrJobPrefab: new Job( - JobPrefab.Prefabs["medicaldoctor"], Rand.RandSync.Unsynced, 0, - new Skill("medical".ToIdentifier(), 70), - new Skill("weapons".ToIdentifier(), 20), - new Skill("mechanical".ToIdentifier(), 20), - new Skill("electrical".ToIdentifier(), 20), - new Skill("helm".ToIdentifier(), 20))); - } - - protected override void Initialize() - { - var firstAidOrder = OrderPrefab.Prefabs["requestfirstaid"]; - doctor_firstAidIcon = firstAidOrder.SymbolSprite; - doctor_firstAidIconColor = firstAidOrder.Color; - - subPatients = new List(); - radioSpeakerName = TextManager.Get("Tutorial.Radio.Speaker"); - doctor = Character.Controlled; - - foreach (Item item in doctor.Inventory.AllItemsMod) - { - if (item.HasTag("clothing") || item.HasTag("identitycard") || item.HasTag("mobileradio")) { continue; } - item.Unequip(doctor); - doctor.Inventory.RemoveItem(item); - } - - doctor_suppliesCabinet = Item.ItemList.Find(i => i.HasTag("doctor_suppliescabinet"))?.GetComponent(); - doctor_medBayCabinet = Item.ItemList.Find(i => i.HasTag("doctor_medbaycabinet"))?.GetComponent(); - - var patientHull1 = WayPoint.WayPointList.Find(wp => wp.IdCardDesc == "waitingroom").CurrentHull; - var patientHull2 = WayPoint.WayPointList.Find(wp => wp.IdCardDesc == "airlock").CurrentHull; - medBay = WayPoint.WayPointList.Find(wp => wp.IdCardDesc == "medbay").CurrentHull; - - var assistantInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobOrJobPrefab: JobPrefab.Get("assistant".ToIdentifier())) - { - TeamID = CharacterTeamType.Team1 - }; - patient1 = Character.Create(assistantInfo, patientHull1.WorldPosition, "1"); - patient1.GiveJobItems(null); - patient1.CanSpeak = false; - patient1.Params.Health.BurnReduction = 0; - patient1.AddDamage(patient1.WorldPosition, new List() { new Affliction(AfflictionPrefab.Burn, 15.0f) }, stun: 0, playSound: false); - patient1.AIController.Enabled = false; - - assistantInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobOrJobPrefab: JobPrefab.Get("assistant".ToIdentifier())) - { - TeamID = CharacterTeamType.Team1 - }; - patient2 = Character.Create(assistantInfo, patientHull2.WorldPosition, "2"); - patient2.GiveJobItems(null); - patient2.CanSpeak = false; - patient2.AIController.Enabled = false; - - var mechanicInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobOrJobPrefab: JobPrefab.Get("engineer".ToIdentifier())) - { - TeamID = CharacterTeamType.Team1 - }; - var subPatient1 = Character.Create(mechanicInfo, WayPoint.GetRandom(SpawnType.Human, mechanicInfo.Job?.Prefab, Submarine.MainSub).WorldPosition, "3"); - subPatient1.Params.Health.BurnReduction = 0; - subPatient1.AddDamage(patient1.WorldPosition, new List() { new Affliction(AfflictionPrefab.Burn, 40.0f) }, stun: 0, playSound: false); - subPatients.Add(subPatient1); - - var securityInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobOrJobPrefab: JobPrefab.Get("securityofficer".ToIdentifier())); - var subPatient2 = Character.Create(securityInfo, WayPoint.GetRandom(SpawnType.Human, securityInfo.Job?.Prefab, Submarine.MainSub).WorldPosition, "3"); - subPatient2.TeamID = CharacterTeamType.Team1; - subPatient2.AddDamage(patient1.WorldPosition, new List() { new Affliction(AfflictionPrefab.InternalDamage, 40.0f) }, stun: 0, playSound: false); - subPatients.Add(subPatient2); - - var engineerInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobOrJobPrefab: JobPrefab.Get("engineer".ToIdentifier())) - { - TeamID = CharacterTeamType.Team1 - }; - var subPatient3 = Character.Create(securityInfo, WayPoint.GetRandom(SpawnType.Human, engineerInfo.Job?.Prefab, Submarine.MainSub).WorldPosition, "3"); - subPatient3.Params.Health.BurnReduction = 0; - subPatient3.AddDamage(patient1.WorldPosition, new List() { new Affliction(AfflictionPrefab.Burn, 20.0f) }, stun: 0, playSound: false); - subPatients.Add(subPatient3); - - doctor_firstDoor = Item.ItemList.Find(i => i.HasTag("doctor_firstdoor")).GetComponent(); - doctor_secondDoor = Item.ItemList.Find(i => i.HasTag("doctor_seconddoor")).GetComponent(); - doctor_thirdDoor = Item.ItemList.Find(i => i.HasTag("doctor_thirddoor")).GetComponent(); - tutorial_upperFinalDoor = Item.ItemList.Find(i => i.HasTag("tutorial_upperfinaldoor")).GetComponent(); - doctor_firstDoorLight = Item.ItemList.Find(i => i.HasTag("doctor_firstdoorlight")).GetComponent(); - doctor_secondDoorLight = Item.ItemList.Find(i => i.HasTag("doctor_seconddoorlight")).GetComponent(); - doctor_thirdDoorLight = Item.ItemList.Find(i => i.HasTag("doctor_thirddoorlight")).GetComponent(); - SetDoorAccess(doctor_firstDoor, doctor_firstDoorLight, false); - SetDoorAccess(doctor_secondDoor, doctor_secondDoorLight, false); - SetDoorAccess(doctor_thirdDoor, doctor_thirdDoorLight, false); - tutorial_submarineDoor = Item.ItemList.Find(i => i.HasTag("tutorial_submarinedoor")).GetComponent(); - tutorial_submarineDoorLight = Item.ItemList.Find(i => i.HasTag("tutorial_submarinedoorlight")).GetComponent(); - SetDoorAccess(tutorial_submarineDoor, tutorial_submarineDoorLight, false); - tutorial_lockedDoor_2 = Item.ItemList.Find(i => i.HasTag("tutorial_lockeddoor_2")).GetComponent(); - SetDoorAccess(tutorial_lockedDoor_2, null, true); - - - foreach (var patient in subPatients) - { - patient.CanSpeak = false; - patient.AIController.Enabled = false; - patient.GiveJobItems(); - } - - Item reactorItem = Item.ItemList.Find(i => i.Submarine == Submarine.MainSub && i.GetComponent() != null); - reactorItem.GetComponent().AutoTemp = true; - - GameAnalyticsManager.AddDesignEvent("Tutorial:DoctorTutorial:Started"); - GameAnalyticsManager.AddDesignEvent("Tutorial:Started"); - } - - public override IEnumerable UpdateState() - { - while (GameMain.Instance.LoadingScreenOpen) yield return null; - - // explosions and radio messages ------------------------------------------------------ - - yield return new WaitForSeconds(3.0f, false); - - //SoundPlayer.PlayDamageSound("StructureBlunt", 10, Character.Controlled.WorldPosition); - //// Room 1 - //while (shakeTimer > 0.0f) // Wake up, shake - //{ - // shakeTimer -= 0.1f; - // GameMain.GameScreen.Cam.Shake = shakeAmount; - // yield return new WaitForSeconds(0.1f); - //} - //yield return new WaitForSeconds(2.5f); - //GameMain.GameSession?.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.Get("Mechanic.Radio.WakeUp"), ChatMessageType.Radio, null); - - //yield return new WaitForSeconds(2.5f); - - doctor.SetStun(1.5f); - var explosion = new Explosion(range: 100, force: 10, damage: 0, structureDamage: 0, itemDamage: 0); - explosion.DisableParticles(); - GameMain.GameScreen.Cam.Shake = shakeAmount; - explosion.Explode(Character.Controlled.WorldPosition - Vector2.UnitX * 25, null); - SoundPlayer.PlayDamageSound("StructureBlunt", 10, Character.Controlled.WorldPosition - Vector2.UnitX * 25); - - yield return new WaitForSeconds(0.5f, false); - - doctor.DamageLimb( - Character.Controlled.WorldPosition, - doctor.AnimController.GetLimb(LimbType.Torso), - new List { new Affliction(AfflictionPrefab.InternalDamage, 10.0f) }, - stun: 3.0f, playSound: true, attackImpulse: 0.0f); - - shakeTimer = 0.5f; - while (shakeTimer > 0.0f) // Wake up, shake - { - shakeTimer -= 0.1f; - GameMain.GameScreen.Cam.Shake = shakeAmount; - yield return new WaitForSeconds(0.1f, false); - } - - yield return new WaitForSeconds(3.0f, false); - GameMain.GameSession?.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.Get("Doctor.Radio.KnockedDown"), ChatMessageType.Radio, null); - - // first tutorial segment, get medical supplies ------------------------------------------------------ - - yield return new WaitForSeconds(1.5f, false); - SetHighlight(doctor_suppliesCabinet.Item, true); - - /*while (doctor.CurrentHull != doctor_suppliesCabinet.Item.CurrentHull) - { - yield return new WaitForSeconds(2.0f); - }*/ - - TriggerTutorialSegment(0, GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Select), GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Deselect), "None"); // Medical supplies objective - - do - { - for (int i = 0; i < doctor_suppliesCabinet.Inventory.Capacity; i++) - { - if (doctor_suppliesCabinet.Inventory.GetItemAt(i) != null) - { - HighlightInventorySlot(doctor_suppliesCabinet.Inventory, i, highlightColor, .5f, .5f, 0f); - } - } - if (doctor.SelectedItem == doctor_suppliesCabinet.Item) - { - for (int i = 0; i < doctor.Inventory.Capacity; i++) - { - if (doctor.Inventory.GetItemAt(i) == null) { HighlightInventorySlot(doctor.Inventory, i, highlightColor, .5f, .5f, 0f); } - } - } - yield return null; - } while (doctor.Inventory.FindItemByIdentifier("antidama1".ToIdentifier()) == null); // Wait until looted - yield return new WaitForSeconds(1.0f, false); - - SetHighlight(doctor_suppliesCabinet.Item, false); - RemoveCompletedObjective(0); - GameAnalyticsManager.AddDesignEvent("Tutorial:DoctorTutorial:Objective0"); - - yield return new WaitForSeconds(1.0f, false); - - // 2nd tutorial segment, treat self ------------------------------------------------------------------------- - - TriggerTutorialSegment(1, GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Health)); // Open health interface - while (CharacterHealth.OpenHealthWindow == null) - { - doctor.CharacterHealth.HealthBarPulsateTimer = 1.0f; - yield return null; - } - yield return null; - RemoveCompletedObjective(1); - GameAnalyticsManager.AddDesignEvent("Tutorial:DoctorTutorial:Objective1"); - yield return new WaitForSeconds(1.0f, false); - TriggerTutorialSegment(2); //Treat self - while (doctor.CharacterHealth.GetAfflictionStrength("damage") > 0.01f) - { - if (CharacterHealth.OpenHealthWindow == null) - { - doctor.CharacterHealth.HealthBarPulsateTimer = 1.0f; - } - else - { - HighlightInventorySlot(doctor.Inventory, "antidama1".ToIdentifier(), highlightColor, .5f, .5f, 0f); - } - - yield return null; - } - - RemoveCompletedObjective(2); - GameAnalyticsManager.AddDesignEvent("Tutorial:DoctorTutorial:Objective2"); - SetDoorAccess(doctor_firstDoor, doctor_firstDoorLight, true); - - while (CharacterHealth.OpenHealthWindow != null) - { - yield return new WaitForSeconds(1.0f, false); - } - - // treat patient -------------------------------------------------------------------------------------------- - - //patient 1 requests first aid - var newOrder = new Order(OrderPrefab.Prefabs["requestfirstaid"], patient1.CurrentHull, null, orderGiver: patient1); - doctor.AddActiveObjectiveEntity(patient1, doctor_firstAidIcon, doctor_firstAidIconColor); - //GameMain.GameSession.CrewManager.AddOrder(newOrder, newOrder.FadeOutTime); - GameMain.GameSession.CrewManager.AddSinglePlayerChatMessage(patient1.Name, newOrder.GetChatMessage("", patient1.CurrentHull?.DisplayName?.Value, givingOrderToSelf: false), ChatMessageType.Order, null); - - while (doctor.CurrentHull != patient1.CurrentHull) - { - yield return new WaitForSeconds(1.0f, false); - } - yield return new WaitForSeconds(0.0f, false); - - GameMain.GameSession.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.Get("Doctor.Radio.AssistantBurns"), ChatMessageType.Radio, null); - GameMain.GameSession.CrewManager.AllowCharacterSwitch = false; - GameMain.GameSession.CrewManager.AddCharacter(doctor); - GameMain.GameSession.CrewManager.AddCharacter(patient1); - GameMain.GameSession.CrewManager.AutoShowCrewList(); - patient1.CharacterHealth.UseHealthWindow = false; - - yield return new WaitForSeconds(3.0f, false); - patient1.AIController.Enabled = true; - doctor.RemoveActiveObjectiveEntity(patient1); - TriggerTutorialSegment(3, GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Command)); // Get the patient to medbay - - while (patient1.GetCurrentOrderWithTopPriority()?.Identifier != "follow") - { - // TODO: Rework order highlighting for new command UI - // GameMain.GameSession.CrewManager.HighlightOrderButton(patient1, "follow", highlightColor, new Vector2(5, 5)); - yield return null; - } - - SetDoorAccess(doctor_secondDoor, doctor_secondDoorLight, true); - - while (patient1.CurrentHull != medBay) - { - yield return new WaitForSeconds(1.0f, false); - } - RemoveCompletedObjective(3); - GameAnalyticsManager.AddDesignEvent("Tutorial:DoctorTutorial:Objective3"); - SetHighlight(doctor_medBayCabinet.Item, true); - SetDoorAccess(doctor_thirdDoor, doctor_thirdDoorLight, true); - patient1.CharacterHealth.UseHealthWindow = true; - - yield return new WaitForSeconds(2.0f, false); - - TriggerTutorialSegment(4, GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Health)); // treat burns - - do - { - for (int i = 0; i < 3; i++) - { - if (doctor_medBayCabinet.Inventory.GetItemAt(i) != null) - { - HighlightInventorySlot(doctor_medBayCabinet.Inventory, i, highlightColor, .5f, .5f, 0f); - } - } - if (doctor.SelectedItem == doctor_medBayCabinet.Item) - { - for (int i = 0; i < doctor.Inventory.Capacity; i++) - { - if (doctor.Inventory.GetItemAt(i) == null) { HighlightInventorySlot(doctor.Inventory, i, highlightColor, .5f, .5f, 0f); } - } - } - yield return null; - } while (doctor.Inventory.FindItemByIdentifier("antibleeding1".ToIdentifier()) == null); // Wait until looted - SetHighlight(doctor_medBayCabinet.Item, false); - SetHighlight(patient1, true); - - while (patient1.CharacterHealth.GetAfflictionStrength("burn") > 0.01f) - { - if (CharacterHealth.OpenHealthWindow == null) - { - doctor.CharacterHealth.HealthBarPulsateTimer = 1.0f; - } - else - { - HighlightInventorySlot(doctor.Inventory, "antibleeding1".ToIdentifier(), highlightColor, .5f, .5f, 0f); - } - yield return null; - - } - RemoveCompletedObjective(4); - GameAnalyticsManager.AddDesignEvent("Tutorial:DoctorTutorial:Objective4"); - SetHighlight(patient1, false); - yield return new WaitForSeconds(1.0f, false); - - GameMain.GameSession.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.Get("Doctor.Radio.AssistantBurnsHealed"), ChatMessageType.Radio, null); - - // treat unconscious patient ------------------------------------------------------ - - //patient calls for help - //patient2.CanSpeak = true; - yield return new WaitForSeconds(2.0f, false); - newOrder = new Order(OrderPrefab.Prefabs["requestfirstaid"], patient2.CurrentHull, null, orderGiver: patient2); - doctor.AddActiveObjectiveEntity(patient2, doctor_firstAidIcon, doctor_firstAidIconColor); - //GameMain.GameSession.CrewManager.AddOrder(newOrder, newOrder.FadeOutTime); - GameMain.GameSession.CrewManager.AddSinglePlayerChatMessage(patient2.Name, newOrder.GetChatMessage("", patient1.CurrentHull?.DisplayName?.Value, givingOrderToSelf: false), ChatMessageType.Order, null); - patient2.AIController.Enabled = true; - patient2.Oxygen = -50; - CoroutineManager.StartCoroutine(KeepPatientAlive(patient2), "KeepPatient2Alive"); - - /*while (doctor.CurrentHull != patient2.CurrentHull) - { - yield return new WaitForSeconds(1.0f); - }*/ - do { yield return null; } while (!tutorial_upperFinalDoor.IsOpen); - yield return new WaitForSeconds(2.0f, false); - - TriggerTutorialSegment(5, GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Health)); // perform CPR - SetHighlight(patient2, true); - while (patient2.IsUnconscious) - { - if (CharacterHealth.OpenHealthWindow != null && doctor.AnimController.Anim != AnimController.Animation.CPR) - { - //Disabled pulse until it's replaced by a better effect - //CharacterHealth.OpenHealthWindow.CPRButton.Pulsate(Vector2.One, Vector2.One * 1.5f, 1.0f); - if (CharacterHealth.OpenHealthWindow.CPRButton.FlashTimer <= 0.0f) - { - CharacterHealth.OpenHealthWindow.CPRButton.Flash(highlightColor); - } - } - yield return null; - } - RemoveCompletedObjective(5); - GameAnalyticsManager.AddDesignEvent("Tutorial:DoctorTutorial:Objective5"); - SetHighlight(patient2, false); - doctor.RemoveActiveObjectiveEntity(patient2); - CoroutineManager.StopCoroutines("KeepPatient2Alive"); - - SetDoorAccess(tutorial_submarineDoor, tutorial_submarineDoorLight, true); - - while (doctor.Submarine != Submarine.MainSub) - { - yield return new WaitForSeconds(1.0f, false); - } - - subPatients[2].Oxygen = -50; - CoroutineManager.StartCoroutine(KeepPatientAlive(subPatients[2]), "KeepPatient3Alive"); - - yield return new WaitForSeconds(5.0f, false); - GameMain.GameSession.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.Get("Doctor.Radio.EnteredSub"), ChatMessageType.Radio, null); - - yield return new WaitForSeconds(3.0f, false); - TriggerTutorialSegment(6, GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Health)); // give treatment to anyone in need - - foreach (var patient in subPatients) - { - //patient.CanSpeak = true; - patient.AIController.Enabled = true; - SetHighlight(patient, true); - } - - double subEnterTime = Timing.TotalTime; - - bool[] patientCalledHelp = new bool[] { false, false, false }; - - while (subPatients.Any(p => p.Vitality < p.MaxVitality * 0.9f && !p.IsDead)) - { - for (int i = 0; i < subPatients.Count; i++) - { - //make patients call for help to make sure the player finds them - //(within 1 minute intervals of entering the sub) - if (!patientCalledHelp[i] && Timing.TotalTime > subEnterTime + 60 * (i + 1)) - { - doctor.AddActiveObjectiveEntity(subPatients[i], doctor_firstAidIcon, doctor_firstAidIconColor); - newOrder = new Order(OrderPrefab.Prefabs["requestfirstaid"], subPatients[i].CurrentHull, null, orderGiver: subPatients[i]); - string message = newOrder.GetChatMessage("", subPatients[i].CurrentHull?.DisplayName?.Value, givingOrderToSelf: false); - GameMain.GameSession.CrewManager.AddSinglePlayerChatMessage(subPatients[i].Name, message, ChatMessageType.Order, null); - patientCalledHelp[i] = true; - } - - if (subPatients[i].ExternalHighlight && subPatients[i].Vitality >= subPatients[i].MaxVitality * 0.9f) - { - doctor.RemoveActiveObjectiveEntity(subPatients[i]); - SetHighlight(subPatients[i], false); - } - } - yield return new WaitForSeconds(1.0f, false); - } - RemoveCompletedObjective(6); - GameAnalyticsManager.AddDesignEvent("Tutorial:DoctorTutorial:Objective6"); - foreach (var patient in subPatients) - { - SetHighlight(patient, false); - doctor.RemoveActiveObjectiveEntity(patient); - } - - // END TUTORIAL - GameAnalyticsManager.AddDesignEvent("Tutorial:DoctorTutorial:Completed"); - CoroutineManager.StartCoroutine(TutorialCompleted()); - } - - public IEnumerable KeepPatientAlive(Character patient) - { - while (patient != null && !patient.Removed) - { - patient.Oxygen = Math.Max(patient.Oxygen, -50); - yield return null; - } - } - } -} diff --git a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/EngineerTutorial.cs b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/EngineerTutorial.cs deleted file mode 100644 index 3e30b7672..000000000 --- a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/EngineerTutorial.cs +++ /dev/null @@ -1,664 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Xml.Linq; -using Barotrauma.Items.Components; -using Barotrauma.Networking; -using Microsoft.Xna.Framework; - -namespace Barotrauma.Tutorials -{ - class EngineerTutorial : ScenarioTutorial - { - // Other tutorial items - private LightComponent tutorial_securityFinalDoorLight; - private LightComponent tutorial_mechanicFinalDoorLight; - private Steering tutorial_submarineSteering; - - // Room 1 - private float shakeTimer = 1f; - private float shakeAmount = 20f; - - // Room 2 - private MotionSensor engineer_equipmentObjectiveSensor; - private ItemContainer engineer_equipmentCabinet; - private Door engineer_firstDoor; - private LightComponent engineer_firstDoorLight; - - // Room 3 - private Powered tutorial_oxygenGenerator; - private Reactor engineer_reactor; - private Door engineer_secondDoor; - private LightComponent engineer_secondDoorLight; - - // Room 4 - private Item engineer_brokenJunctionBox; - private Door engineer_thirdDoor; - private LightComponent engineer_thirdDoorLight; - - // Room 5 - private PowerTransfer[] engineer_disconnectedJunctionBoxes; - private ConnectionPanel[] engineer_disconnectedConnectionPanels; - private Item engineer_wire_1; - private Powered engineer_lamp_1; - private Item engineer_wire_2; - private Powered engineer_lamp_2; - private Door engineer_fourthDoor; - private LightComponent engineer_fourthDoorLight; - - // Room 6 - private Pump engineer_workingPump; - private Door tutorial_lockedDoor_1; - - // Submarine - private Door tutorial_submarineDoor; - private LightComponent tutorial_submarineDoorLight; - private MotionSensor tutorial_enteredSubmarineSensor; - private Item engineer_submarineJunctionBox_1; - private Item engineer_submarineJunctionBox_2; - private Item engineer_submarineJunctionBox_3; - private Reactor engineer_submarineReactor; - - // Variables - private LocalizedString radioSpeakerName; - private Character engineer; - private int[] reactorLoads = new int[5] { 1500, 3000, 2000, 5000, 3500 }; - private float reactorLoadChangeTime = 2f; - private float reactorLoadError = 200f; - private bool reactorOperatedProperly; - private const float waterVolumeBeforeOpening = 15f; - private Sprite engineer_repairIcon; - private Color engineer_repairIconColor; - private Sprite engineer_reactorIcon; - private Color engineer_reactorIconColor; - private bool wiringActive = false; - - public EngineerTutorial() : base("tutorial.engineertraining".ToIdentifier(), - new Segment( - "Mechanic.Equipment".ToIdentifier(), - "Mechanic.EquipmentObjective".ToIdentifier(), - TutorialContentType.TextOnly, - textContent: new Segment.Text { Tag = "Mechanic.EquipmentText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center }), - new Segment( - "Engineer.Reactor".ToIdentifier(), - "Engineer.ReactorObjective".ToIdentifier(), - TutorialContentType.ManualVideo, - textContent: new Segment.Text { Tag = "Engineer.ReactorText".ToIdentifier(), Width = 700, Height = 80, Anchor = Anchor.Center }, - videoContent: new Segment.Video { File = "tutorial_reactor.webm", TextTag = "Engineer.ReactorText".ToIdentifier(), Width = 700, Height = 80 }), - new Segment( - "Engineer.OperateReactor".ToIdentifier(), - "Engineer.OperateReactorObjective".ToIdentifier(), - TutorialContentType.ManualVideo, - textContent: new Segment.Text { Tag = "Engineer.OperateReactorText".ToIdentifier(), Width = 700, Height = 80, Anchor = Anchor.Center }, - videoContent: new Segment.Video { File = "tutorial_reactor.webm", TextTag = "Engineer.ReactorText".ToIdentifier(), Width = 700, Height = 80 }), - new Segment( - "Engineer.RepairJunctionBox".ToIdentifier(), - "Engineer.RepairJunctionBoxObjective".ToIdentifier(), - TutorialContentType.TextOnly, - textContent: new Segment.Text { Tag = "Engineer.RepairJunctionBoxText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center }), - new Segment( - "Engineer.WireJunctionBoxes".ToIdentifier(), - "Engineer.WireJunctionBoxesObjective".ToIdentifier(), - TutorialContentType.ManualVideo, - textContent: new Segment.Text { Tag = "Engineer.WireJunctionBoxesText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center }, - videoContent: new Segment.Video { File = "tutorial_wiring.webm", TextTag = "Engineer.WireJunctionBoxesText".ToIdentifier(), Width = 450, Height = 80 }), - new Segment( - "Engineer.RepairElectricalRoom".ToIdentifier(), - "Engineer.RepairElectricalRoomObjective".ToIdentifier(), - TutorialContentType.TextOnly, - textContent: new Segment.Text { Tag = "Engineer.RepairElectricalRoomText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center }), - new Segment( - "Engineer.PowerUpReactor".ToIdentifier(), - "Engineer.PowerUpReactorObjective".ToIdentifier(), - TutorialContentType.TextOnly, - textContent: new Segment.Text { Tag = "Engineer.PowerUpReactorText".ToIdentifier(), Width = 700, Height = 80, Anchor = Anchor.Center })) - { } - - protected override CharacterInfo GetCharacterInfo() - { - return new CharacterInfo( - CharacterPrefab.HumanSpeciesName, - jobOrJobPrefab: new Job( - JobPrefab.Prefabs["engineer"], Rand.RandSync.Unsynced, 0, - new Skill("medical".ToIdentifier(), 0), - new Skill("weapons".ToIdentifier(), 0), - new Skill("mechanical".ToIdentifier(), 20), - new Skill("electrical".ToIdentifier(), 60), - new Skill("helm".ToIdentifier(), 0))); - } - - protected override void Initialize() - { - radioSpeakerName = TextManager.Get("Tutorial.Radio.Speaker"); - engineer = Character.Controlled; - - foreach (Item item in engineer.Inventory.AllItemsMod) - { - if (item.HasTag("clothing") || item.HasTag("identitycard") || item.HasTag("mobileradio")) { continue; } - item.Unequip(engineer); - engineer.Inventory.RemoveItem(item); - } - - var repairOrder = OrderPrefab.Prefabs["repairsystems"]; - engineer_repairIcon = repairOrder.SymbolSprite; - engineer_repairIconColor = repairOrder.Color; - - var reactorOrder = OrderPrefab.Prefabs["operatereactor"]; - engineer_reactorIcon = reactorOrder.SymbolSprite; - engineer_reactorIconColor = reactorOrder.Color; - - // Other tutorial items - tutorial_securityFinalDoorLight = Item.ItemList.Find(i => i.HasTag("tutorial_securityfinaldoorlight")).GetComponent(); - tutorial_mechanicFinalDoorLight = Item.ItemList.Find(i => i.HasTag("tutorial_mechanicfinaldoorlight")).GetComponent(); - tutorial_submarineSteering = Item.ItemList.Find(i => i.HasTag("command")).GetComponent(); - - tutorial_submarineSteering.CanBeSelected = false; - foreach (ItemComponent ic in tutorial_submarineSteering.Item.Components) - { - ic.CanBeSelected = false; - } - - SetDoorAccess(null, tutorial_securityFinalDoorLight, false); - SetDoorAccess(null, tutorial_mechanicFinalDoorLight, false); - - // Room 2 - engineer_equipmentObjectiveSensor = Item.ItemList.Find(i => i.HasTag("engineer_equipmentobjectivesensor")).GetComponent(); - engineer_equipmentCabinet = Item.ItemList.Find(i => i.HasTag("engineer_equipmentcabinet")).GetComponent(); - engineer_firstDoor = Item.ItemList.Find(i => i.HasTag("engineer_firstdoor")).GetComponent(); - engineer_firstDoorLight = Item.ItemList.Find(i => i.HasTag("engineer_firstdoorlight")).GetComponent(); - - SetDoorAccess(engineer_firstDoor, engineer_firstDoorLight, false); - - // Room 3 - tutorial_oxygenGenerator = Item.ItemList.Find(i => i.HasTag("tutorial_oxygengenerator")).GetComponent(); - engineer_reactor = Item.ItemList.Find(i => i.HasTag("engineer_reactor")).GetComponent(); - engineer_reactor.FireDelay = engineer_reactor.MeltdownDelay = float.PositiveInfinity; - engineer_reactor.FuelConsumptionRate = 0.0f; - engineer_reactor.PowerOn = true; - reactorOperatedProperly = false; - - engineer_secondDoor = Item.ItemList.Find(i => i.HasTag("engineer_seconddoor")).GetComponent(); ; - engineer_secondDoorLight = Item.ItemList.Find(i => i.HasTag("engineer_seconddoorlight")).GetComponent(); - - SetDoorAccess(engineer_secondDoor, engineer_secondDoorLight, false); - - // Room 4 - engineer_brokenJunctionBox = Item.ItemList.Find(i => i.HasTag("engineer_brokenjunctionbox")); - engineer_thirdDoor = Item.ItemList.Find(i => i.HasTag("engineer_thirddoor")).GetComponent(); - engineer_thirdDoorLight = Item.ItemList.Find(i => i.HasTag("engineer_thirddoorlight")).GetComponent(); - - engineer_brokenJunctionBox.Indestructible = false; - engineer_brokenJunctionBox.Condition = 0f; - - SetDoorAccess(engineer_thirdDoor, engineer_thirdDoorLight, false); - - // Room 5 - engineer_disconnectedJunctionBoxes = new PowerTransfer[4]; - engineer_disconnectedConnectionPanels = new ConnectionPanel[4]; - - for (int i = 0; i < engineer_disconnectedJunctionBoxes.Length; i++) - { - engineer_disconnectedJunctionBoxes[i] = Item.ItemList.Find(item => item.HasTag($"engineer_disconnectedjunctionbox_{i + 1}")).GetComponent(); - engineer_disconnectedConnectionPanels[i] = engineer_disconnectedJunctionBoxes[i].Item.GetComponent(); - engineer_disconnectedConnectionPanels[i].Locked = false; - - for (int j = 0; j < engineer_disconnectedJunctionBoxes[i].PowerConnections.Count; j++) - { - foreach (Wire wire in engineer_disconnectedJunctionBoxes[i].PowerConnections[j].Wires) - { - if (wire == null) continue; - wire.Locked = true; - } - } - } - - engineer_wire_1 = Item.ItemList.Find(i => i.HasTag("engineer_wire_1")); - engineer_wire_1.SpriteColor = Color.Transparent; - engineer_wire_2 = Item.ItemList.Find(i => i.HasTag("engineer_wire_2")); - engineer_wire_2.SpriteColor = Color.Transparent; - engineer_lamp_1 = Item.ItemList.Find(i => i.HasTag("engineer_lamp_1")).GetComponent(); - engineer_lamp_2 = Item.ItemList.Find(i => i.HasTag("engineer_lamp_2")).GetComponent(); - engineer_fourthDoor = Item.ItemList.Find(i => i.HasTag("engineer_fourthdoor")).GetComponent(); - engineer_fourthDoorLight = Item.ItemList.Find(i => i.HasTag("engineer_fourthdoorlight")).GetComponent(); - SetDoorAccess(engineer_fourthDoor, engineer_fourthDoorLight, false); - - // Room 6 - engineer_workingPump = Item.ItemList.Find(i => i.HasTag("engineer_workingpump")).GetComponent(); - engineer_workingPump.Item.CurrentHull.WaterVolume += engineer_workingPump.Item.CurrentHull.Volume; - engineer_workingPump.IsActive = true; - tutorial_lockedDoor_1 = Item.ItemList.Find(i => i.HasTag("tutorial_lockeddoor_1")).GetComponent(); - SetDoorAccess(tutorial_lockedDoor_1, null, true); - - // Submarine - tutorial_submarineDoor = Item.ItemList.Find(i => i.HasTag("tutorial_submarinedoor")).GetComponent(); - tutorial_submarineDoorLight = Item.ItemList.Find(i => i.HasTag("tutorial_submarinedoorlight")).GetComponent(); - SetDoorAccess(tutorial_submarineDoor, tutorial_submarineDoorLight, true); - - tutorial_enteredSubmarineSensor = Item.ItemList.Find(i => i.HasTag("tutorial_enteredsubmarinesensor")).GetComponent(); - engineer_submarineJunctionBox_1 = Item.ItemList.Find(i => i.HasTag("engineer_submarinejunctionbox_1")); - engineer_submarineJunctionBox_2 = Item.ItemList.Find(i => i.HasTag("engineer_submarinejunctionbox_2")); - engineer_submarineJunctionBox_3 = Item.ItemList.Find(i => i.HasTag("engineer_submarinejunctionbox_3")); - engineer_submarineReactor = Item.ItemList.Find(i => i.HasTag("engineer_submarinereactor")).GetComponent(); - engineer_submarineReactor.PowerOn = true; - engineer_submarineReactor.IsActive = engineer_submarineReactor.AutoTemp = false; - - engineer_submarineJunctionBox_1.Indestructible = false; - engineer_submarineJunctionBox_1.Condition = 0f; - engineer_submarineJunctionBox_2.Indestructible = false; - engineer_submarineJunctionBox_2.Condition = 0f; - engineer_submarineJunctionBox_3.Indestructible = false; - engineer_submarineJunctionBox_3.Condition = 0f; - - GameAnalyticsManager.AddDesignEvent("Tutorial:EngineerTutorial:Started"); - GameAnalyticsManager.AddDesignEvent("Tutorial:Started"); - } - - public override IEnumerable UpdateState() - { - while (GameMain.Instance.LoadingScreenOpen) { yield return null; } - - // Room 1 - SoundPlayer.PlayDamageSound("StructureBlunt", 10, Character.Controlled.WorldPosition); - while (shakeTimer > 0.0f) // Wake up, shake - { - shakeTimer -= 0.1f; - GameMain.GameScreen.Cam.Shake = shakeAmount; - yield return new WaitForSeconds(0.1f, false); - } - - //// Remove - //for (int i = 0; i < engineer_disconnectedJunctionBoxes.Length; i++) - //{ - // SetHighlight(engineer_disconnectedJunctionBoxes[i].Item, true); - //} - //do { CheckGhostWires(); HandleJunctionBoxWiringHighlights(); yield return null; } while (engineer_workingPump.Voltage < engineer_workingPump.MinVoltage); // Wait until connected all the way to the pump - //CheckGhostWires(); - //// Remove - - GameMain.GameSession.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.Get("Engineer.Radio.WakeUp"), ChatMessageType.Radio, null); - SetHighlight(engineer_equipmentCabinet.Item, true); - - // Room 2 - do { yield return null; } while (!engineer_equipmentObjectiveSensor.MotionDetected); - GameMain.GameSession.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.Get("Engineer.Radio.Equipment"), ChatMessageType.Radio, null); - yield return new WaitForSeconds(0.5f, false); - TriggerTutorialSegment(0, GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Select), GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Deselect)); // Retrieve equipment - bool firstSlotRemoved = false; - bool secondSlotRemoved = false; - bool thirdSlotRemoved = false; - bool fourthSlotRemoved = false; - do - { - if (IsSelectedItem(engineer_equipmentCabinet.Item)) - { - if (!firstSlotRemoved) - { - HighlightInventorySlot(engineer_equipmentCabinet.Inventory, 0, highlightColor, .5f, .5f, 0f); - if (engineer_equipmentCabinet.Inventory.GetItemAt(0) == null) { firstSlotRemoved = true; } - } - - if (!secondSlotRemoved) - { - HighlightInventorySlot(engineer_equipmentCabinet.Inventory, 1, highlightColor, .5f, .5f, 0f); - if (engineer_equipmentCabinet.Inventory.GetItemAt(1) == null) { secondSlotRemoved = true; } - } - - if (!thirdSlotRemoved) - { - HighlightInventorySlot(engineer_equipmentCabinet.Inventory, 2, highlightColor, .5f, .5f, 0f); - if (engineer_equipmentCabinet.Inventory.GetItemAt(2) == null) { thirdSlotRemoved = true; } - } - - if (!fourthSlotRemoved) - { - HighlightInventorySlot(engineer_equipmentCabinet.Inventory, 3, highlightColor, .5f, .5f, 0f); - if (engineer_equipmentCabinet.Inventory.GetItemAt(2) == null) { fourthSlotRemoved = true; } - } - - for (int i = 0; i < engineer.Inventory.visualSlots.Length; i++) - { - if (engineer.Inventory.GetItemAt(i) == null) { HighlightInventorySlot(engineer.Inventory, i, highlightColor, .5f, .5f, 0f); } - } - } - - yield return null; - } while (!engineer_equipmentCabinet.Inventory.IsEmpty()); // Wait until looted - RemoveCompletedObjective(0); - GameAnalyticsManager.AddDesignEvent("Tutorial:EngineerTutorial:Objective0"); - SetHighlight(engineer_equipmentCabinet.Item, false); - SetHighlight(engineer_reactor.Item, true); - SetDoorAccess(engineer_firstDoor, engineer_firstDoorLight, true); - - // Room 3 - do { yield return null; } while (!IsSelectedItem(engineer_reactor.Item)); - yield return new WaitForSeconds(0.5f, false); - TriggerTutorialSegment(1); - do - { - if (IsSelectedItem(engineer_reactor.Item)) - { - engineer_reactor.AutoTemp = false; - if (engineer_reactor.PowerButton.FlashTimer <= 0) - { - engineer_reactor.PowerButton.Flash(highlightColor, 1.5f, false); - } - } - yield return null; - } while (!engineer_reactor.PowerOn); - do - { - if (IsSelectedItem(engineer_reactor.Item) && engineer_reactor.Item.OwnInventory.visualSlots != null) - { - engineer_reactor.AutoTemp = false; - HighlightInventorySlot(engineer.Inventory, "fuelrod".ToIdentifier(), highlightColor, 0.5f, 0.5f, 0f); - - for (int i = 0; i < engineer_reactor.Item.OwnInventory.visualSlots.Length; i++) - { - HighlightInventorySlot(engineer_reactor.Item.OwnInventory, i, highlightColor, 0.5f, 0.5f, 0f); - } - } - yield return null; - } while (engineer_reactor.AvailableFuel == 0); - RemoveCompletedObjective(1); - GameAnalyticsManager.AddDesignEvent("Tutorial:EngineerTutorial:Objective1"); - TriggerTutorialSegment(2); - CoroutineManager.StartCoroutine(ReactorOperatedProperly()); - do - { - if (IsSelectedItem(engineer_reactor.Item)) - { - engineer_reactor.AutoTemp = false; - if (engineer_reactor.FissionRateScrollBar.FlashTimer <= 0) - { - engineer_reactor.FissionRateScrollBar.Flash(highlightColor, 1.5f); - } - - if (engineer_reactor.TurbineOutputScrollBar.FlashTimer <= 0) - { - engineer_reactor.TurbineOutputScrollBar.Flash(highlightColor, 1.5f); - } - } - yield return null; - } while (!reactorOperatedProperly); - yield return new WaitForSeconds(2f, false); - GameMain.GameSession.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.Get("Engineer.Radio.ReactorStable"), ChatMessageType.Radio, null); - do - { - if (IsSelectedItem(engineer_reactor.Item)) - { - if (engineer_reactor.AutoTempSwitch.FlashTimer <= 0) - { - engineer_reactor.AutoTempSwitch.Flash(highlightColor, 1.5f, false, false, new Vector2(10, 10)); - } - } - yield return null; - } while (!engineer_reactor.AutoTemp); - - float wait = 1.5f; - do - { - yield return new WaitForSeconds(0.1f, false); - wait -= 0.1f; - engineer_reactor.AutoTemp = true; - } while (wait > 0.0f); - engineer.SelectedItem = null; - engineer_reactor.CanBeSelected = false; - RemoveCompletedObjective(2); - GameAnalyticsManager.AddDesignEvent("Tutorial:EngineerTutorial:Objective2"); - SetHighlight(engineer_reactor.Item, false); - SetHighlight(engineer_brokenJunctionBox, true); - SetDoorAccess(engineer_secondDoor, engineer_secondDoorLight, true); - - // Room 4 - do { yield return null; } while (!engineer_secondDoor.IsOpen); - yield return new WaitForSeconds(1f, false); - Repairable repairableJunctionBoxComponent = engineer_brokenJunctionBox.GetComponent(); - TriggerTutorialSegment(3, GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Select)); // Repair the junction box - do - { - if (!engineer.HasEquippedItem("screwdriver".ToIdentifier())) - { - HighlightInventorySlot(engineer.Inventory, "screwdriver".ToIdentifier(), highlightColor, .5f, .5f, 0f); - } - else if (IsSelectedItem(engineer_brokenJunctionBox) && repairableJunctionBoxComponent.CurrentFixer == null) - { - if (repairableJunctionBoxComponent.RepairButton.FlashTimer <= 0) - { - repairableJunctionBoxComponent.RepairButton.Flash(); - } - } - yield return null; - } while (repairableJunctionBoxComponent.IsBelowRepairThreshold); // Wait until repaired - SetHighlight(engineer_brokenJunctionBox, false); - RemoveCompletedObjective(3); - GameAnalyticsManager.AddDesignEvent("Tutorial:EngineerTutorial:Objective3"); - SetDoorAccess(engineer_thirdDoor, engineer_thirdDoorLight, true); - for (int i = 0; i < engineer_disconnectedJunctionBoxes.Length; i++) - { - SetHighlight(engineer_disconnectedJunctionBoxes[i].Item, true); - } - - // Room 5 - do { yield return null; } while (!engineer_thirdDoor.IsOpen); - GameMain.GameSession.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.Get("Engineer.Radio.FaultyWiring"), ChatMessageType.Radio, null); - yield return new WaitForSeconds(2f, false); - TriggerTutorialSegment(4, GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Use), GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Deselect)); // Connect the junction boxes - do { CheckGhostWires(); HandleJunctionBoxWiringHighlights(); yield return null; } while (engineer_workingPump.Voltage < engineer_workingPump.MinVoltage); // Wait until connected all the way to the pump - CheckGhostWires(); - for (int i = 0; i < engineer_disconnectedJunctionBoxes.Length; i++) - { - SetHighlight(engineer_disconnectedJunctionBoxes[i].Item, false); - } - RemoveCompletedObjective(4); - GameAnalyticsManager.AddDesignEvent("Tutorial:EngineerTutorial:Objective4"); - do { yield return null; } while (engineer_workingPump.Item.CurrentHull.WaterPercentage > waterVolumeBeforeOpening); // Wait until drained - wiringActive = false; - SetDoorAccess(engineer_fourthDoor, engineer_fourthDoorLight, true); - GameMain.GameSession.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.Get("Engineer.Radio.ChangeOfPlans"), ChatMessageType.Radio, null); - - // Submarine - do { yield return null; } while (!tutorial_enteredSubmarineSensor.MotionDetected); - GameMain.GameSession.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.Get("Engineer.Radio.Submarine"), ChatMessageType.Radio, null); - yield return new WaitForSeconds(2f, false); - TriggerTutorialSegment(5); // Repair junction box - while (ContentRunning) yield return null; - engineer.AddActiveObjectiveEntity(engineer_submarineJunctionBox_1, engineer_repairIcon, engineer_repairIconColor); - engineer.AddActiveObjectiveEntity(engineer_submarineJunctionBox_2, engineer_repairIcon, engineer_repairIconColor); - engineer.AddActiveObjectiveEntity(engineer_submarineJunctionBox_3, engineer_repairIcon, engineer_repairIconColor); - SetHighlight(engineer_submarineJunctionBox_1, true); - SetHighlight(engineer_submarineJunctionBox_2, true); - SetHighlight(engineer_submarineJunctionBox_3, true); - - Repairable repairableJunctionBoxComponent1 = engineer_submarineJunctionBox_1.GetComponent(); - Repairable repairableJunctionBoxComponent2 = engineer_submarineJunctionBox_2.GetComponent(); - Repairable repairableJunctionBoxComponent3 = engineer_submarineJunctionBox_3.GetComponent(); - - // Remove highlights when each individual machine is repaired - do { CheckJunctionBoxHighlights(repairableJunctionBoxComponent1, repairableJunctionBoxComponent2, repairableJunctionBoxComponent3); yield return null; } while (repairableJunctionBoxComponent1.IsBelowRepairThreshold || repairableJunctionBoxComponent2.IsBelowRepairThreshold || repairableJunctionBoxComponent3.IsBelowRepairThreshold); - CheckJunctionBoxHighlights(repairableJunctionBoxComponent1, repairableJunctionBoxComponent2, repairableJunctionBoxComponent3); - RemoveCompletedObjective(5); - GameAnalyticsManager.AddDesignEvent("Tutorial:EngineerTutorial:Objective5"); - yield return new WaitForSeconds(2f, false); - - TriggerTutorialSegment(6); // Powerup reactor - SetHighlight(engineer_submarineReactor.Item, true); - engineer.AddActiveObjectiveEntity(engineer_submarineReactor.Item, engineer_reactorIcon, engineer_reactorIconColor); - do { yield return null; } while (!IsReactorPoweredUp(engineer_submarineReactor)); // Wait until ~matches load - engineer.RemoveActiveObjectiveEntity(engineer_submarineReactor.Item); - SetHighlight(engineer_submarineReactor.Item, false); - RemoveCompletedObjective(6); - GameAnalyticsManager.AddDesignEvent("Tutorial:EngineerTutorial:Objective6"); - GameMain.GameSession.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.Get("Engineer.Radio.Complete"), ChatMessageType.Radio, null); - - yield return new WaitForSeconds(4f, false); - - GameAnalyticsManager.AddDesignEvent("Tutorial:EngineerTutorial:Completed"); - CoroutineManager.StartCoroutine(TutorialCompleted()); - } - - public override void Update(float deltaTime) - { - base.Update(deltaTime); - - if (wiringActive) - { - for (int i = 0; i < engineer_disconnectedJunctionBoxes.Length; i++) - { - for (int j = 0; j < engineer_disconnectedJunctionBoxes[i].PowerConnections.Count; j++) - { - engineer_disconnectedJunctionBoxes[i].PowerConnections[j].UpdateFlashTimer(deltaTime); - } - } - } - } - - private bool IsSelectedItem(Item item) - { - return engineer?.SelectedItem == item; - } - - private IEnumerable ReactorOperatedProperly() - { - float timer; - - for (int i = 0; i < reactorLoads.Length; i++) - { - timer = reactorLoadChangeTime; - tutorial_oxygenGenerator.PowerConsumption = reactorLoads[i]; - while (timer > 0) - { - yield return CoroutineStatus.Running; - if (CoroutineManager.DeltaTime > 0.0f && IsReactorPoweredUp(engineer_reactor)) - { - timer -= CoroutineManager.DeltaTime; - } - } - } - - reactorOperatedProperly = true; - } - - private void CheckGhostWires() - { - Color wireColor = - Color.Orange * - MathHelper.Lerp(0.25f, 0.75f, (float)(Math.Sin((Timing.TotalTime * 4.0f)) + 1.0f) / 2.0f); - - if (engineer_wire_1 != null) - { - engineer_wire_1.SpriteColor = wireColor; - if (engineer_lamp_1.Voltage > engineer_lamp_1.MinVoltage) - { - engineer_wire_1.Remove(); - engineer_wire_1 = null; - } - } - - - if (engineer_wire_2 != null) - { - engineer_wire_2.SpriteColor = wireColor; - if (engineer_lamp_2.Voltage > engineer_lamp_2.MinVoltage) - { - engineer_wire_2.Remove(); - engineer_wire_2 = null; - } - } - - } - - private void HandleJunctionBoxWiringHighlights() - { - Item selected = engineer.SelectedItem; - - if (!engineer.HasEquippedItem("screwdriver".ToIdentifier())) - { - HighlightInventorySlot(engineer.Inventory, "screwdriver".ToIdentifier(), highlightColor, 0.5f, 0.5f, 0f); - } - - int selectedIndex = -1; - - if (selected != null) - { - for (int i = 0; i < engineer_disconnectedJunctionBoxes.Length; i++) - { - if (selected == engineer_disconnectedJunctionBoxes[i].Item) - { - selectedIndex = i; - break; - } - } - } - - wiringActive = selectedIndex != -1; - - if (!engineer.HasEquippedItem("wire".ToIdentifier())) - { - HighlightInventorySlotWithTag(engineer.Inventory, "wire".ToIdentifier(), highlightColor, 0.5f, 0.5f, 0f); - } - else - { - if (!wiringActive) return; - for (int i = 0; i < engineer_disconnectedConnectionPanels[selectedIndex].Connections.Count; i++) - { - var connection = engineer_disconnectedConnectionPanels[selectedIndex].Connections[i]; - if (connection.IsPower && connection.FlashTimer <= 0) - { - foreach (Wire wire in engineer_disconnectedConnectionPanels[selectedIndex].Connections[i].Wires) - { - if (wire == null) continue; - if (!wire.Locked) - { - return; - } - } - - connection.Flash(highlightColor); - } - } - } - } - - private void CheckJunctionBoxHighlights(Repairable comp1, Repairable comp2, Repairable comp3) - { - if (!comp1.IsBelowRepairThreshold && engineer_submarineJunctionBox_1.ExternalHighlight) - { - SetHighlight(engineer_submarineJunctionBox_1, false); - engineer.RemoveActiveObjectiveEntity(engineer_submarineJunctionBox_1); - } - if (!comp2.IsBelowRepairThreshold && engineer_submarineJunctionBox_2.ExternalHighlight) - { - SetHighlight(engineer_submarineJunctionBox_2, false); - engineer.RemoveActiveObjectiveEntity(engineer_submarineJunctionBox_2); - } - if (!comp3.IsBelowRepairThreshold && engineer_submarineJunctionBox_3.ExternalHighlight) - { - SetHighlight(engineer_submarineJunctionBox_3, false); - engineer.RemoveActiveObjectiveEntity(engineer_submarineJunctionBox_3); - } - } - - private bool IsReactorPoweredUp(Reactor reactor) - { - float load = 0.0f; - List connections = reactor.Item.Connections; - if (connections != null && connections.Count > 0) - { - foreach (Connection connection in connections) - { - if (!connection.IsPower) continue; - foreach (Connection recipient in connection.Recipients) - { - if (!(recipient.Item is Item it)) continue; - - PowerTransfer pt = it.GetComponent(); - if (pt == null) continue; - - load = Math.Max(load, pt.PowerLoad); - } - } - } - - return Math.Abs(load + reactor.CurrPowerConsumption) < reactorLoadError; - } - } -} diff --git a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/MechanicTutorial.cs b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/MechanicTutorial.cs deleted file mode 100644 index e96dfc137..000000000 --- a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/MechanicTutorial.cs +++ /dev/null @@ -1,737 +0,0 @@ -using System.Collections.Generic; -using System.Xml.Linq; -using Barotrauma.Items.Components; -using Barotrauma.Networking; -using Microsoft.Xna.Framework; - -namespace Barotrauma.Tutorials -{ - class MechanicTutorial : ScenarioTutorial - { - // Other tutorial items - private LightComponent tutorial_securityFinalDoorLight; - private Door tutorial_upperFinalDoor; - private Steering tutorial_submarineSteering; - - // Room 1 - private float shakeTimer = 1f; - private float shakeAmount = 20f; - private Door mechanic_firstDoor; - private LightComponent mechanic_firstDoorLight; - - // Room 2 - private MotionSensor mechanic_equipmentObjectiveSensor; - private ItemContainer mechanic_equipmentCabinet; - private Door mechanic_secondDoor; - private LightComponent mechanic_secondDoorLight; - - // Room 3 - private MotionSensor mechanic_weldingObjectiveSensor; - private Pump mechanic_workingPump; - private Door mechanic_thirdDoor; - private LightComponent mechanic_thirdDoorLight; - private Structure mechanic_brokenWall_1; - private Hull mechanic_brokenhull_1; - - // Room 4 - private MotionSensor mechanic_craftingObjectiveSensor; - private Deconstructor mechanic_deconstructor; - private Fabricator mechanic_fabricator; - private ItemContainer mechanic_craftingCabinet; - private Door mechanic_fourthDoor; - private LightComponent mechanic_fourthDoorLight; - - // Room 5 - private MotionSensor mechanic_fireSensor; - private DummyFireSource mechanic_fire; - private Door mechanic_fifthDoor; - private LightComponent mechanic_fifthDoorLight; - - // Room 6 - private MotionSensor mechanic_divingSuitObjectiveSensor; - private ItemContainer mechanic_divingSuitContainer; - private ItemContainer mechanic_oxygenContainer; - private Door tutorial_mechanicFinalDoor; - private LightComponent tutorial_mechanicFinalDoorLight; - - // Room 7 - private Pump mechanic_brokenPump; - private Structure mechanic_brokenWall_2; - private Hull mechanic_brokenhull_2; - private Door tutorial_submarineDoor; - private LightComponent tutorial_submarineDoorLight; - - // Submarine - private MotionSensor tutorial_enteredSubmarineSensor; - private Engine mechanic_submarineEngine; - private Pump mechanic_ballastPump_1; - private Pump mechanic_ballastPump_2; - - // Variables - private const float waterVolumeBeforeOpening = 15f; - private LocalizedString radioSpeakerName; - private Character mechanic; - private Sprite mechanic_repairIcon; - private Color mechanic_repairIconColor; - private Sprite mechanic_weldIcon; - - public MechanicTutorial() : base("tutorial.mechanictraining".ToIdentifier(), - new Segment( - "Mechanic.OpenDoor".ToIdentifier(), - "Mechanic.OpenDoorObjective".ToIdentifier(), - TutorialContentType.TextOnly, - textContent: new Segment.Text { Tag = "Mechanic.OpenDoorText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center }), - new Segment( - "Mechanic.Equipment".ToIdentifier(), - "Mechanic.EquipmentObjective".ToIdentifier(), - TutorialContentType.ManualVideo, - textContent: new Segment.Text { Tag = "Mechanic.EquipmentText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center }, - videoContent: new Segment.Video { File = "tutorial_inventory.webm", TextTag = "Mechanic.EquipmentText".ToIdentifier(), Width = 450, Height = 80 }), - new Segment( - "Mechanic.Welding".ToIdentifier(), - "Mechanic.WeldingObjective".ToIdentifier(), - TutorialContentType.ManualVideo, - textContent: new Segment.Text { Tag = "Mechanic.WeldingText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center }, - videoContent: new Segment.Video { File = "tutorial_equip.webm", TextTag = "Mechanic.WeldingText".ToIdentifier(), Width = 450, Height = 80 }), - new Segment( - "Mechanic.Drain".ToIdentifier(), - "Mechanic.DrainObjective".ToIdentifier(), - TutorialContentType.TextOnly, - textContent: new Segment.Text { Tag = "Mechanic.DrainText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center }), - new Segment( - "Mechanic.Deconstruct".ToIdentifier(), - "Mechanic.DeconstructObjective".ToIdentifier(), - TutorialContentType.ManualVideo, - textContent: new Segment.Text { Tag = "Mechanic.DeconstructText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center }, - videoContent: new Segment.Video { File = "tutorial_deconstruct.webm", TextTag = "Mechanic.DeconstructText".ToIdentifier(), Width = 450, Height = 80 }), - new Segment( - "Mechanic.Fabricate".ToIdentifier(), - "Mechanic.FabricateObjective".ToIdentifier(), - TutorialContentType.ManualVideo, - textContent: new Segment.Text { Tag = "Mechanic.FabricateText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center }, - videoContent: new Segment.Video { File = "tutorial_fabricate.webm", TextTag = "Mechanic.FabricateText".ToIdentifier(), Width = 450, Height = 80 }), - new Segment( - "Mechanic.Extinguisher".ToIdentifier(), - "Mechanic.ExtinguisherObjective".ToIdentifier(), - TutorialContentType.TextOnly, - textContent: new Segment.Text { Tag = "Mechanic.ExtinguisherText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center }), - new Segment( - "Mechanic.DropExtinguisher".ToIdentifier(), - "Mechanic.DropExtinguisherObjective".ToIdentifier(), - TutorialContentType.TextOnly, - textContent: new Segment.Text { Tag = "Mechanic.DropExtinguisherText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center }), - new Segment( - "Mechanic.Diving".ToIdentifier(), - "Mechanic.DivingObjective".ToIdentifier(), - TutorialContentType.TextOnly, - textContent: new Segment.Text { Tag = "Mechanic.DivingText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center }), - new Segment( - "Mechanic.RepairPump".ToIdentifier(), - "Mechanic.RepairPumpObjective".ToIdentifier(), - TutorialContentType.TextOnly, - textContent: new Segment.Text { Tag = "Mechanic.RepairPumpText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center }), - new Segment( - "Mechanic.RepairSubmarine".ToIdentifier(), - "Mechanic.RepairSubmarineObjective".ToIdentifier(), - TutorialContentType.TextOnly, - textContent: new Segment.Text { Tag = "Mechanic.RepairSubmarineText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center }), - new Segment( - "tutorial.laddertitle".ToIdentifier(), - "tutorial.laddertitle".ToIdentifier(), - TutorialContentType.TextOnly, - textContent: new Segment.Text { Tag = "tutorial.ladderdescription".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center })) - { } - - protected override CharacterInfo GetCharacterInfo() - { - return new CharacterInfo( - CharacterPrefab.HumanSpeciesName, - jobOrJobPrefab: new Job( - JobPrefab.Prefabs["mechanic"], Rand.RandSync.Unsynced, 0, - new Skill("medical".ToIdentifier(), 0), - new Skill("weapons".ToIdentifier(), 0), - new Skill("mechanical".ToIdentifier(), 50), - new Skill("electrical".ToIdentifier(), 20), - new Skill("helm".ToIdentifier(), 0))); - } - - protected override void Initialize() - { - radioSpeakerName = TextManager.Get("Tutorial.Radio.Speaker"); - mechanic = Character.Controlled; - - foreach (Item item in mechanic.Inventory.AllItemsMod) - { - if (item.HasTag("clothing") || item.HasTag("identitycard") || item.HasTag("mobileradio")) { continue; } - item.Unequip(mechanic); - mechanic.Inventory.RemoveItem(item); - } - - var repairOrder = OrderPrefab.Prefabs["repairsystems"]; - mechanic_repairIcon = repairOrder.SymbolSprite; - mechanic_repairIconColor = repairOrder.Color; - mechanic_weldIcon = new Sprite("Content/UI/MainIconsAtlas.png", new Rectangle(1, 256, 127, 127), new Vector2(0.5f, 0.5f)); - - // Other tutorial items - tutorial_securityFinalDoorLight = Item.ItemList.Find(i => i.HasTag("tutorial_securityfinaldoorlight")).GetComponent(); - tutorial_upperFinalDoor = Item.ItemList.Find(i => i.HasTag("tutorial_upperfinaldoor")).GetComponent(); - tutorial_submarineSteering = Item.ItemList.Find(i => i.HasTag("command")).GetComponent(); - - tutorial_submarineSteering.CanBeSelected = false; - foreach (ItemComponent ic in tutorial_submarineSteering.Item.Components) - { - ic.CanBeSelected = false; - } - - SetDoorAccess(null, tutorial_securityFinalDoorLight, false); - SetDoorAccess(tutorial_upperFinalDoor, null, false); - - // Room 1 - mechanic_firstDoor = Item.ItemList.Find(i => i.HasTag("mechanic_firstdoor")).GetComponent(); - mechanic_firstDoorLight = Item.ItemList.Find(i => i.HasTag("mechanic_firstdoorlight")).GetComponent(); - - SetDoorAccess(mechanic_firstDoor, mechanic_firstDoorLight, false); - - // Room 2 - mechanic_equipmentObjectiveSensor = Item.ItemList.Find(i => i.HasTag("mechanic_equipmentobjectivesensor")).GetComponent(); - mechanic_equipmentCabinet = Item.ItemList.Find(i => i.HasTag("mechanic_equipmentcabinet")).GetComponent(); - mechanic_secondDoor = Item.ItemList.Find(i => i.HasTag("mechanic_seconddoor")).GetComponent(); - mechanic_secondDoorLight = Item.ItemList.Find(i => i.HasTag("mechanic_seconddoorlight")).GetComponent(); - - SetDoorAccess(mechanic_secondDoor, mechanic_secondDoorLight, false); - - // Room 3 - mechanic_weldingObjectiveSensor = Item.ItemList.Find(i => i.HasTag("mechanic_weldingobjectivesensor")).GetComponent(); - mechanic_workingPump = Item.ItemList.Find(i => i.HasTag("mechanic_workingpump")).GetComponent(); - mechanic_thirdDoor = Item.ItemList.Find(i => i.HasTag("mechanic_thirddoor")).GetComponent(); - mechanic_thirdDoorLight = Item.ItemList.Find(i => i.HasTag("mechanic_thirddoorlight")).GetComponent(); - mechanic_brokenWall_1 = Structure.WallList.Find(i => i.SpecialTag == "mechanic_brokenwall_1"); - //mechanic_ladderSensor = Item.ItemList.Find(i => i.HasTag("mechanic_laddersensor")).GetComponent(); - - SetDoorAccess(mechanic_thirdDoor, mechanic_thirdDoorLight, false); - mechanic_brokenWall_1.Indestructible = false; - mechanic_brokenWall_1.SpriteColor = Color.White; - for (int i = 0; i < mechanic_brokenWall_1.SectionCount; i++) - { - mechanic_brokenWall_1.AddDamage(i, 85); - } - mechanic_brokenhull_1 = mechanic_brokenWall_1.Sections[0].gap.FlowTargetHull; - - // Room 4 - mechanic_craftingObjectiveSensor = Item.ItemList.Find(i => i.HasTag("mechanic_craftingobjectivesensor")).GetComponent(); - mechanic_deconstructor = Item.ItemList.Find(i => i.HasTag("mechanic_deconstructor")).GetComponent(); - mechanic_fabricator = Item.ItemList.Find(i => i.HasTag("mechanic_fabricator")).GetComponent(); - mechanic_craftingCabinet = Item.ItemList.Find(i => i.HasTag("mechanic_craftingcabinet")).GetComponent(); - mechanic_fourthDoor = Item.ItemList.Find(i => i.HasTag("mechanic_fourthdoor")).GetComponent(); - mechanic_fourthDoorLight = Item.ItemList.Find(i => i.HasTag("mechanic_fourthdoorlight")).GetComponent(); - - SetDoorAccess(mechanic_fourthDoor, mechanic_fourthDoorLight, false); - - // Room 5 - mechanic_fifthDoor = Item.ItemList.Find(i => i.HasTag("mechanic_fifthdoor")).GetComponent(); - mechanic_fifthDoorLight = Item.ItemList.Find(i => i.HasTag("mechanic_fifthdoorlight")).GetComponent(); - mechanic_fireSensor = Item.ItemList.Find(i => i.HasTag("mechanic_firesensor")).GetComponent(); - - SetDoorAccess(mechanic_fifthDoor, mechanic_fifthDoorLight, false); - - // Room 6 - mechanic_divingSuitObjectiveSensor = Item.ItemList.Find(i => i.HasTag("mechanic_divingsuitobjectivesensor")).GetComponent(); - mechanic_divingSuitContainer = Item.ItemList.Find(i => i.HasTag("mechanic_divingsuitcontainer")).GetComponent(); - foreach (Item item in mechanic_divingSuitContainer.Inventory.AllItems) - { - foreach (ItemComponent ic in item.Components) - { - ic.CanBePicked = true; - } - } - - mechanic_oxygenContainer = Item.ItemList.Find(i => i.HasTag("mechanic_oxygencontainer")).GetComponent(); - foreach (Item item in mechanic_oxygenContainer.Inventory.AllItems) - { - foreach (ItemComponent ic in item.Components) - { - ic.CanBePicked = true; - } - } - - tutorial_mechanicFinalDoor = Item.ItemList.Find(i => i.HasTag("tutorial_mechanicfinaldoor")).GetComponent(); - tutorial_mechanicFinalDoorLight = Item.ItemList.Find(i => i.HasTag("tutorial_mechanicfinaldoorlight")).GetComponent(); - - SetDoorAccess(tutorial_mechanicFinalDoor, tutorial_mechanicFinalDoorLight, false); - - // Room 7 - mechanic_brokenPump = Item.ItemList.Find(i => i.HasTag("mechanic_brokenpump")).GetComponent(); - mechanic_brokenPump.Item.Indestructible = false; - mechanic_brokenPump.Item.Condition = 0; - mechanic_brokenPump.CanBeSelected = false; - mechanic_brokenPump.Item.GetComponent().CanBeSelected = false; - mechanic_brokenWall_2 = Structure.WallList.Find(i => i.SpecialTag == "mechanic_brokenwall_2"); - tutorial_submarineDoor = Item.ItemList.Find(i => i.HasTag("tutorial_submarinedoor")).GetComponent(); - tutorial_submarineDoorLight = Item.ItemList.Find(i => i.HasTag("tutorial_submarinedoorlight")).GetComponent(); - - mechanic_brokenWall_2.Indestructible = false; - mechanic_brokenWall_2.SpriteColor = Color.White; - for (int i = 0; i < mechanic_brokenWall_2.SectionCount; i++) - { - mechanic_brokenWall_2.AddDamage(i, 85); - } - mechanic_brokenhull_2 = mechanic_brokenWall_2.Sections[0].gap.FlowTargetHull; - SetDoorAccess(tutorial_submarineDoor, tutorial_submarineDoorLight, false); - - // Submarine - tutorial_enteredSubmarineSensor = Item.ItemList.Find(i => i.HasTag("tutorial_enteredsubmarinesensor")).GetComponent(); - mechanic_submarineEngine = Item.ItemList.Find(i => i.HasTag("mechanic_submarineengine")).GetComponent(); - mechanic_submarineEngine.Item.Indestructible = false; - mechanic_submarineEngine.Item.Condition = 0f; - mechanic_ballastPump_1 = Item.ItemList.Find(i => i.HasTag("mechanic_ballastpump_1")).GetComponent(); - mechanic_ballastPump_1.Item.Indestructible = false; - mechanic_ballastPump_1.Item.Condition = 0f; - mechanic_ballastPump_2 = Item.ItemList.Find(i => i.HasTag("mechanic_ballastpump_2")).GetComponent(); - mechanic_ballastPump_2.Item.Indestructible = false; - mechanic_ballastPump_2.Item.Condition = 0f; - - GameAnalyticsManager.AddDesignEvent("Tutorial:MechanicTutorial:Started"); - GameAnalyticsManager.AddDesignEvent("Tutorial:Started"); - } - - public override void Update(float deltaTime) - { - if (mechanic_brokenhull_1 != null) - { - mechanic_brokenhull_1.WaterVolume = MathHelper.Clamp(mechanic_brokenhull_1.WaterVolume, 0, mechanic_brokenhull_1.Volume * 0.85f); - } - base.Update(deltaTime); - } - - public override IEnumerable UpdateState() - { - while (GameMain.Instance.LoadingScreenOpen) yield return null; - - // Room 1 - SoundPlayer.PlayDamageSound("StructureBlunt", 10, Character.Controlled.WorldPosition); - while (shakeTimer > 0.0f) // Wake up, shake - { - shakeTimer -= 0.1f; - GameMain.GameScreen.Cam.Shake = shakeAmount; - yield return new WaitForSeconds(0.1f, false); - } - yield return new WaitForSeconds(2.5f, false); - - mechanic_fabricator.RemoveFabricationRecipes(allowedIdentifiers: - new[] { "extinguisher", "wrench", "weldingtool", "weldingfuel", "divingmask", "railgunshell", "nuclearshell", "uex", "harpoongun" }.ToIdentifiers()); - GameMain.GameSession?.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.Get("Mechanic.Radio.WakeUp"), ChatMessageType.Radio, null); - - yield return new WaitForSeconds(2.5f, false); - TriggerTutorialSegment(0, GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Up), GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Left), GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Down), GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Right), GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Select), GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Select)); // Open door objective - yield return new WaitForSeconds(0.0f, false); - SetDoorAccess(mechanic_firstDoor, mechanic_firstDoorLight, true); - SetHighlight(mechanic_firstDoor.Item, true); - do { yield return null; } while (!mechanic_firstDoor.IsOpen); - SetHighlight(mechanic_firstDoor.Item, false); - yield return new WaitForSeconds(1.5f, false); - RemoveCompletedObjective(0); - GameAnalyticsManager.AddDesignEvent("Tutorial:MechanicTutorial:Objective0"); - - // Room 2 - yield return new WaitForSeconds(0.0f, false); - GameMain.GameSession?.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.Get("Mechanic.Radio.Equipment"), ChatMessageType.Radio, null); - do { yield return null; } while (!mechanic_equipmentObjectiveSensor.MotionDetected); - TriggerTutorialSegment(1, GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Select), GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Deselect)); // Equipment & inventory objective - SetHighlight(mechanic_equipmentCabinet.Item, true); - bool firstSlotRemoved = false; - bool secondSlotRemoved = false; - bool thirdSlotRemoved = false; - do - { - if (IsSelectedItem(mechanic_equipmentCabinet.Item)) - { - if (!firstSlotRemoved) - { - HighlightInventorySlot(mechanic_equipmentCabinet.Inventory, 0, highlightColor, .5f, .5f, 0f); - if (mechanic_equipmentCabinet.Inventory.GetItemAt(0) == null) { firstSlotRemoved = true; } - } - - if (!secondSlotRemoved) - { - HighlightInventorySlot(mechanic_equipmentCabinet.Inventory, 1, highlightColor, .5f, .5f, 0f); - if (mechanic_equipmentCabinet.Inventory.GetItemAt(1) == null) { secondSlotRemoved = true; } - } - - if (!thirdSlotRemoved) - { - HighlightInventorySlot(mechanic_equipmentCabinet.Inventory, 2, highlightColor, .5f, .5f, 0f); - if (mechanic_equipmentCabinet.Inventory.GetItemAt(2) == null) { thirdSlotRemoved = true; } - } - - for (int i = 0; i < mechanic.Inventory.Capacity; i++) - { - if (mechanic.Inventory.GetItemAt(i) == null) { HighlightInventorySlot(mechanic.Inventory, i, highlightColor, .5f, .5f, 0f); } - } - } - - yield return null; - } while (mechanic.Inventory.FindItemByIdentifier("divingmask".ToIdentifier()) == null || mechanic.Inventory.FindItemByIdentifier("weldingtool".ToIdentifier()) == null || mechanic.Inventory.FindItemByIdentifier("wrench".ToIdentifier()) == null); // Wait until looted - SetHighlight(mechanic_equipmentCabinet.Item, false); - yield return new WaitForSeconds(1.5f, false); - RemoveCompletedObjective(1); - GameAnalyticsManager.AddDesignEvent("Tutorial:MechanicTutorial:Objective1"); - GameMain.GameSession?.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.Get("Mechanic.Radio.Breach"), ChatMessageType.Radio, null); - - // Room 3 - do { yield return null; } while (!mechanic_weldingObjectiveSensor.MotionDetected); - TriggerTutorialSegment(2, GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Aim), GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Shoot)); // Welding objective - do - { - if (!mechanic.HasEquippedItem("divingmask".ToIdentifier())) - { - HighlightInventorySlot(mechanic.Inventory, "divingmask".ToIdentifier(), highlightColor, .5f, .5f, 0f); - } - - if (!mechanic.HasEquippedItem("weldingtool".ToIdentifier())) - { - HighlightInventorySlot(mechanic.Inventory, "weldingtool".ToIdentifier(), highlightColor, .5f, .5f, 0f); - } - yield return null; - } while (!mechanic.HasEquippedItem("divingmask".ToIdentifier()) || !mechanic.HasEquippedItem("weldingtool".ToIdentifier())); // Wait until equipped - SetDoorAccess(mechanic_secondDoor, mechanic_secondDoorLight, true); - mechanic.AddActiveObjectiveEntity(mechanic_brokenWall_1, mechanic_weldIcon, mechanic_repairIconColor); - do { yield return null; } while (WallHasDamagedSections(mechanic_brokenWall_1)); // Highlight until repaired - mechanic.RemoveActiveObjectiveEntity(mechanic_brokenWall_1); - RemoveCompletedObjective(2); - GameAnalyticsManager.AddDesignEvent("Tutorial:MechanicTutorial:Objective2"); - - yield return new WaitForSeconds(1f, false); - TriggerTutorialSegment(3, GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Select)); // Pump objective - SetHighlight(mechanic_workingPump.Item, true); - do - { - yield return null; - if (IsSelectedItem(mechanic_workingPump.Item)) - { - if (mechanic_workingPump.PowerButton.FlashTimer <= 0) - { - mechanic_workingPump.PowerButton.Flash(uiHighlightColor, 1.5f, true); - } - } - } while (mechanic_workingPump.FlowPercentage >= 0 || !mechanic_workingPump.IsActive); // Highlight until draining - SetHighlight(mechanic_workingPump.Item, false); - do { yield return null; } while (mechanic_brokenhull_1 != null && mechanic_brokenhull_1.WaterPercentage > waterVolumeBeforeOpening); // Unlock door once drained - RemoveCompletedObjective(3); - GameAnalyticsManager.AddDesignEvent("Tutorial:MechanicTutorial:Objective3"); - - SetDoorAccess(mechanic_thirdDoor, mechanic_thirdDoorLight, true); - //TriggerTutorialSegment(11, GameSettings.CurrentConfig.KeyMap.Bindings[InputType.Select], GameSettings.CurrentConfig.KeyMap.Bindings[InputType.Up], GameSettings.CurrentConfig.KeyMap.Bindings[InputType.Down], GameSettings.CurrentConfig.KeyMap.Bindings[InputType.Select]); // Ladder objective - //do { yield return null; } while (!mechanic_ladderSensor.MotionDetected); - //RemoveCompletedObjective(segments[11]); - GameMain.GameSession?.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.Get("Mechanic.Radio.News"), ChatMessageType.Radio, null); - yield return new WaitForSeconds(1f, false); - GameMain.GameSession?.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.Get("Mechanic.Radio.Fire"), ChatMessageType.Radio, null); - - // Room 4 - do { yield return null; } while (!mechanic_thirdDoor.IsOpen); - yield return new WaitForSeconds(1f, false); - mechanic_fire = new DummyFireSource(new Vector2(20f, 2f), Item.ItemList.Find(i => i.HasTag("mechanic_fire")).WorldPosition); - //do { yield return null; } while (!mechanic_craftingObjectiveSensor.MotionDetected); - TriggerTutorialSegment(4); // Deconstruct - - SetHighlight(mechanic_craftingCabinet.Item, true); - - bool gotOxygenTank = false; - bool gotSodium = false; - do - { - if (mechanic.SelectedItem == mechanic_craftingCabinet.Item) - { - for (int i = 0; i < mechanic.Inventory.Capacity; i++) - { - if (mechanic.Inventory.GetItemAt(i) == null) { HighlightInventorySlot(mechanic.Inventory, i, highlightColor, .5f, .5f, 0f); } - } - - if (mechanic.Inventory.FindItemByIdentifier("oxygentank".ToIdentifier()) == null && mechanic.Inventory.FindItemByIdentifier("aluminium".ToIdentifier()) == null) - { - for (int i = 0; i < mechanic_craftingCabinet.Capacity; i++) - { - Item item = mechanic_craftingCabinet.Inventory.GetItemAt(i); - if (item != null && item.Prefab.Identifier == "oxygentank") - { - HighlightInventorySlot(mechanic_craftingCabinet.Inventory, i, highlightColor, .5f, .5f, 0f); - } - } - } - - if (mechanic.Inventory.FindItemByIdentifier("sodium".ToIdentifier()) == null) - { - for (int i = 0; i < mechanic_craftingCabinet.Inventory.Capacity; i++) - { - Item item = mechanic_craftingCabinet.Inventory.GetItemAt(i); - if (item != null && item.Prefab.Identifier == "sodium") - { - HighlightInventorySlot(mechanic_craftingCabinet.Inventory, i, highlightColor, .5f, .5f, 0f); - } - } - } - } - - if (!gotOxygenTank && (mechanic.Inventory.FindItemByIdentifier("oxygentank".ToIdentifier()) != null || - mechanic_deconstructor.InputContainer.Inventory.FindItemByIdentifier("oxygentank".ToIdentifier()) != null)) - { - gotOxygenTank = true; - } - if (!gotSodium && mechanic.Inventory.FindItemByIdentifier("sodium".ToIdentifier()) != null) - { - gotSodium = true; - } - yield return null; - } while (!gotOxygenTank || !gotSodium); // Wait until looted - - yield return new WaitForSeconds(1.0f, false); - SetHighlight(mechanic_craftingCabinet.Item, false); - SetHighlight(mechanic_deconstructor.Item, true); - do - { - if (IsSelectedItem(mechanic_deconstructor.Item)) - { - if (mechanic_deconstructor.OutputContainer.Inventory.FindItemByIdentifier("aluminium".ToIdentifier()) != null) - { - HighlightInventorySlot(mechanic_deconstructor.OutputContainer.Inventory, "aluminium".ToIdentifier(), highlightColor, .5f, .5f, 0f); - - for (int i = 0; i < mechanic.Inventory.Capacity; i++) - { - if (mechanic.Inventory.GetItemAt(i) == null) { HighlightInventorySlot(mechanic.Inventory, i, highlightColor, .5f, .5f, 0f); } - } - } - else - { - if (mechanic.Inventory.FindItemByIdentifier("oxygentank".ToIdentifier()) != null && mechanic_deconstructor.InputContainer.Inventory.FindItemByIdentifier("oxygentank".ToIdentifier()) == null) - { - HighlightInventorySlot(mechanic.Inventory, "oxygentank".ToIdentifier(), highlightColor, .5f, .5f, 0f); - for (int i = 0; i < mechanic_deconstructor.InputContainer.Inventory.Capacity; i++) - { - HighlightInventorySlot(mechanic_deconstructor.InputContainer.Inventory, i, highlightColor, .5f, .5f, 0f); - } - } - - if (mechanic_deconstructor.InputContainer.Inventory.FindItemByIdentifier("oxygentank".ToIdentifier()) != null && !mechanic_deconstructor.IsActive) - { - if (mechanic_deconstructor.ActivateButton.FlashTimer <= 0) - { - mechanic_deconstructor.ActivateButton.Flash(highlightColor, 1.5f, false); - } - } - } - } - yield return null; - } while ( - mechanic.Inventory.FindItemByIdentifier("aluminium".ToIdentifier()) == null && - mechanic_fabricator.InputContainer.Inventory.FindItemByIdentifier("aluminium".ToIdentifier()) == null); // Wait until aluminium obtained - - SetHighlight(mechanic_deconstructor.Item, false); - RemoveCompletedObjective(4); - GameAnalyticsManager.AddDesignEvent("Tutorial:MechanicTutorial:Objective4"); - - yield return new WaitForSeconds(1f, false); - TriggerTutorialSegment(5); // Fabricate - SetHighlight(mechanic_fabricator.Item, true); - do - { - if (IsSelectedItem(mechanic_fabricator.Item)) - { - if (mechanic_fabricator.SelectedItem?.TargetItem.Identifier != "extinguisher") - { - mechanic_fabricator.HighlightRecipe("extinguisher", highlightColor); - } - else - { - if (mechanic_fabricator.OutputContainer.Inventory.FindItemByIdentifier("extinguisher".ToIdentifier()) != null) - { - HighlightInventorySlot(mechanic_fabricator.OutputContainer.Inventory, "extinguisher".ToIdentifier(), highlightColor, .5f, .5f, 0f); - - /*for (int i = 0; i < mechanic.Inventory.Capacity; i++) - { - if (mechanic.Inventory.Items[i] == null) HighlightInventorySlot(mechanic.Inventory, i, highlightColor, .5f, .5f, 0f); - }*/ - } - else if (mechanic_fabricator.InputContainer.Inventory.FindItemByIdentifier("aluminium".ToIdentifier()) != null && mechanic_fabricator.InputContainer.Inventory.FindItemByIdentifier("sodium".ToIdentifier()) != null && !mechanic_fabricator.IsActive) - { - if (mechanic_fabricator.ActivateButton.FlashTimer <= 0) - { - mechanic_fabricator.ActivateButton.Flash(highlightColor, 1.5f, false); - } - } - else if (mechanic.Inventory.FindItemByIdentifier("aluminium".ToIdentifier()) != null || mechanic.Inventory.FindItemByIdentifier("sodium".ToIdentifier()) != null) - { - HighlightInventorySlot(mechanic.Inventory, "aluminium".ToIdentifier(), highlightColor, .5f, .5f, 0f); - HighlightInventorySlot(mechanic.Inventory, "sodium".ToIdentifier(), highlightColor, .5f, .5f, 0f); - - if (mechanic_fabricator.InputContainer.Inventory.GetItemAt(0) == null) - { - HighlightInventorySlot(mechanic_fabricator.InputContainer.Inventory, 0, highlightColor, .5f, .5f, 0f); - } - - if (mechanic_fabricator.InputContainer.Inventory.GetItemAt(1) == null) - { - HighlightInventorySlot(mechanic_fabricator.InputContainer.Inventory, 1, highlightColor, .5f, .5f, 0f); - } - } - } - } - yield return null; - } while (mechanic.Inventory.FindItemByIdentifier("extinguisher".ToIdentifier()) == null); // Wait until extinguisher is created - RemoveCompletedObjective(5); - GameAnalyticsManager.AddDesignEvent("Tutorial:MechanicTutorial:Objective5"); - SetHighlight(mechanic_fabricator.Item, false); - SetDoorAccess(mechanic_fourthDoor, mechanic_fourthDoorLight, true); - - // Room 5 - do { yield return null; } while (!mechanic_fireSensor.MotionDetected); - TriggerTutorialSegment(6, GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Aim), GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Shoot)); // Using the extinguisher - do { yield return null; } while (!mechanic_fire.Removed); // Wait until extinguished - yield return new WaitForSeconds(3f, false); - RemoveCompletedObjective(6); - GameAnalyticsManager.AddDesignEvent("Tutorial:MechanicTutorial:Objective6"); - - if (mechanic.HasEquippedItem("extinguisher".ToIdentifier())) // do not trigger if dropped already - { - TriggerTutorialSegment(7); - do - { - HighlightInventorySlot(mechanic.Inventory, "extinguisher".ToIdentifier(), highlightColor, 0.5f, 0.5f, 0f); - yield return null; - } while (mechanic.HasEquippedItem("extinguisher".ToIdentifier())); - RemoveCompletedObjective(7); - GameAnalyticsManager.AddDesignEvent("Tutorial:MechanicTutorial:Objective7"); - } - SetDoorAccess(mechanic_fifthDoor, mechanic_fifthDoorLight, true); - - // Room 6 - GameMain.GameSession?.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.Get("Mechanic.Radio.Diving"), ChatMessageType.Radio, null); - do { yield return null; } while (!mechanic_divingSuitObjectiveSensor.MotionDetected); - TriggerTutorialSegment(8); // Dangers of pressure, equip diving suit objective - SetHighlight(mechanic_divingSuitContainer.Item, true); - do - { - if (IsSelectedItem(mechanic_divingSuitContainer.Item)) - { - if (mechanic_divingSuitContainer.Inventory.visualSlots != null) - { - for (int i = 0; i < mechanic_divingSuitContainer.Inventory.Capacity; i++) - { - HighlightInventorySlot(mechanic_divingSuitContainer.Inventory, i, highlightColor, 0.5f, 0.5f, 0f); - } - } - } - yield return null; - } while (!mechanic.HasEquippedItem("divingsuit".ToIdentifier(), slotType: InvSlotType.OuterClothes)); - SetHighlight(mechanic_divingSuitContainer.Item, false); - RemoveCompletedObjective(8); - GameAnalyticsManager.AddDesignEvent("Tutorial:MechanicTutorial:Objective8"); - SetDoorAccess(tutorial_mechanicFinalDoor, tutorial_mechanicFinalDoorLight, true); - - // Room 7 - mechanic.AddActiveObjectiveEntity(mechanic_brokenWall_2, mechanic_weldIcon, mechanic_repairIconColor); - do { yield return null; } while (WallHasDamagedSections(mechanic_brokenWall_2)); - mechanic.RemoveActiveObjectiveEntity(mechanic_brokenWall_2); - yield return new WaitForSeconds(2f, false); - - TriggerTutorialSegment(9, GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Use)); // Repairing machinery (pump) - SetHighlight(mechanic_brokenPump.Item, true); - mechanic_brokenPump.CanBeSelected = true; - Repairable repairablePumpComponent = mechanic_brokenPump.Item.GetComponent(); - repairablePumpComponent.CanBeSelected = true; - do - { - yield return null; - if (repairablePumpComponent.IsBelowRepairThreshold) - { - if (!mechanic.HasEquippedItem("wrench".ToIdentifier())) - { - HighlightInventorySlot(mechanic.Inventory, "wrench".ToIdentifier(), highlightColor, 0.5f, 0.5f, 0f); - } - else if (IsSelectedItem(mechanic_brokenPump.Item) && repairablePumpComponent.CurrentFixer == null) - { - if (repairablePumpComponent.RepairButton.FlashTimer <= 0) - { - repairablePumpComponent.RepairButton.Flash(); - } - } - } - else - { - if (IsSelectedItem(mechanic_brokenPump.Item)) - { - if (mechanic_brokenPump.PowerButton.FlashTimer <= 0) - { - mechanic_brokenPump.PowerButton.Flash(uiHighlightColor, 1.5f, true); - } - } - } - } while (repairablePumpComponent.IsBelowRepairThreshold || mechanic_brokenPump.FlowPercentage >= 0 || !mechanic_brokenPump.IsActive); - RemoveCompletedObjective(9); - GameAnalyticsManager.AddDesignEvent("Tutorial:MechanicTutorial:Objective9"); - SetHighlight(mechanic_brokenPump.Item, false); - do { yield return null; } while (mechanic_brokenhull_2.WaterPercentage > waterVolumeBeforeOpening); - SetDoorAccess(tutorial_submarineDoor, tutorial_submarineDoorLight, true); - - // Submarine - do { yield return null; } while (!tutorial_enteredSubmarineSensor.MotionDetected); - GameMain.GameSession?.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.Get("Mechanic.Radio.Submarine"), ChatMessageType.Radio, null); - TriggerTutorialSegment(10); // Repairing ballast pumps, engine - while (ContentRunning) yield return null; - mechanic.AddActiveObjectiveEntity(mechanic_ballastPump_1.Item, mechanic_repairIcon, mechanic_repairIconColor); - mechanic.AddActiveObjectiveEntity(mechanic_ballastPump_2.Item, mechanic_repairIcon, mechanic_repairIconColor); - mechanic.AddActiveObjectiveEntity(mechanic_submarineEngine.Item, mechanic_repairIcon, mechanic_repairIconColor); - SetHighlight(mechanic_ballastPump_1.Item, true); - SetHighlight(mechanic_ballastPump_2.Item, true); - SetHighlight(mechanic_submarineEngine.Item, true); - - Repairable repairablePumpComponent1 = mechanic_ballastPump_1.Item.GetComponent(); - Repairable repairablePumpComponent2 = mechanic_ballastPump_2.Item.GetComponent(); - Repairable repairableEngineComponent = mechanic_submarineEngine.Item.GetComponent(); - - // Remove highlights when each individual machine is repaired - do { CheckHighlights(repairablePumpComponent1, repairablePumpComponent2, repairableEngineComponent); yield return null; } while (repairablePumpComponent1.IsBelowRepairThreshold || repairablePumpComponent2.IsBelowRepairThreshold || repairableEngineComponent.IsBelowRepairThreshold); - CheckHighlights(repairablePumpComponent1, repairablePumpComponent2, repairableEngineComponent); - RemoveCompletedObjective(10); - GameAnalyticsManager.AddDesignEvent("Tutorial:MechanicTutorial:Objective10"); - GameMain.GameSession?.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.Get("Mechanic.Radio.Complete"), ChatMessageType.Radio, null); - - // END TUTORIAL - GameAnalyticsManager.AddDesignEvent("Tutorial:MechanicTutorial:Completed"); - CoroutineManager.StartCoroutine(TutorialCompleted()); - } - - private bool IsSelectedItem(Item item) - { - return mechanic?.SelectedItem == item; - } - - private bool WallHasDamagedSections(Structure wall) - { - for (int i = 0; i < wall.SectionCount; i++) - { - if (wall.Sections[i].damage > 0) return true; - } - - return false; - } - - private void CheckHighlights(Repairable comp1, Repairable comp2, Repairable comp3) - { - if (!comp1.IsBelowRepairThreshold && mechanic_ballastPump_1.Item.ExternalHighlight) - { - SetHighlight(mechanic_ballastPump_1.Item, false); - mechanic.RemoveActiveObjectiveEntity(mechanic_ballastPump_1.Item); - } - if (!comp2.IsBelowRepairThreshold && mechanic_ballastPump_2.Item.ExternalHighlight) - { - SetHighlight(mechanic_ballastPump_2.Item, false); - mechanic.RemoveActiveObjectiveEntity(mechanic_ballastPump_2.Item); - } - if (!comp3.IsBelowRepairThreshold && mechanic_submarineEngine.Item.ExternalHighlight) - { - SetHighlight(mechanic_submarineEngine.Item, false); - mechanic.RemoveActiveObjectiveEntity(mechanic_submarineEngine.Item); - } - } - } -} diff --git a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/OfficerTutorial.cs b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/OfficerTutorial.cs deleted file mode 100644 index 3cfb4551f..000000000 --- a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/OfficerTutorial.cs +++ /dev/null @@ -1,526 +0,0 @@ -using System; -using System.Collections.Generic; -using Barotrauma.IO; -using System.Xml.Linq; -using System.Linq; -using Barotrauma.Items.Components; -using Barotrauma.Networking; -using Barotrauma.Extensions; -using Microsoft.Xna.Framework; - -namespace Barotrauma.Tutorials -{ - class OfficerTutorial : ScenarioTutorial - { - // Other tutorial items - private LightComponent tutorial_mechanicFinalDoorLight; - private Steering tutorial_submarineSteering; - - // Room 1 - private float shakeTimer = 1f; - private float shakeAmount = 20f; - - // Room 2 - private MotionSensor officer_equipmentObjectiveSensor; - private ItemContainer officer_equipmentCabinet; - private Door officer_firstDoor; - private LightComponent officer_firstDoorLight; - - // Room 3 - private MotionSensor officer_crawlerSensor; - private Character officer_crawler; - private Vector2 officer_crawlerSpawnPos; - private Door officer_secondDoor; - private LightComponent officer_secondDoorLight; - - // Room 4 - private MotionSensor officer_somethingBigSensor; - private ItemContainer officer_coilgunLoader; - private ItemContainer officer_ammoShelf_1; - private ItemContainer officer_ammoShelf_2; - private PowerContainer officer_superCapacitor; - private Item officer_coilgunPeriscope; - private Character officer_hammerhead; - private Vector2 officer_hammerheadSpawnPos; - private Door officer_thirdDoor; - private LightComponent officer_thirdDoorLight; - - // Room 5 - private MotionSensor officer_rangedWeaponSensor; - private ItemContainer officer_rangedWeaponCabinet; - private ItemContainer officer_rangedWeaponHolder; - private Door officer_fourthDoor; - private LightComponent officer_fourthDoorLight; - - // Room 6 - private MotionSensor officer_mudraptorObjectiveSensor; - private Vector2 officer_mudraptorSpawnPos; - private Character officer_mudraptor; - private Door tutorial_securityFinalDoor; - private LightComponent tutorial_securityFinalDoorLight; - - // Submarine - private Door tutorial_submarineDoor; - private LightComponent tutorial_submarineDoorLight; - private MotionSensor tutorial_enteredSubmarineSensor; - private Item officer_subAmmoBox_1; - private Item officer_subAmmoBox_2; - private ItemContainer officer_subAmmoShelf; - private ItemContainer officer_subLoader_1; - private ItemContainer officer_subLoader_2; - private PowerContainer officer_subSuperCapacitor_1; - private PowerContainer officer_subSuperCapacitor_2; - - // Variables - private LocalizedString radioSpeakerName; - private Character officer; - private float superCapacitorRechargeRate = 10; - private Sprite officer_gunIcon; - private Color officer_gunIconColor; - - public OfficerTutorial() : base("tutorial.securityofficertraining".ToIdentifier(), - new Segment( - "Mechanic.Equipment".ToIdentifier(), - "Mechanic.EquipmentObjective".ToIdentifier(), - TutorialContentType.TextOnly, - textContent: new Segment.Text { Tag = "Mechanic.EquipmentText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center }), - new Segment( - "Officer.MeleeWeapon".ToIdentifier(), - "Officer.MeleeWeaponObjective".ToIdentifier(), - TutorialContentType.TextOnly, - textContent: new Segment.Text { Tag = "Officer.MeleeWeaponText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center }), - new Segment( - "Officer.Crawler".ToIdentifier(), - "Officer.CrawlerObjective".ToIdentifier(), - TutorialContentType.TextOnly, - textContent: new Segment.Text { Tag = "Officer.CrawlerText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center }), - new Segment( - "Officer.SomethingBig".ToIdentifier(), - "Officer.SomethingBigObjective".ToIdentifier(), - TutorialContentType.ManualVideo, - textContent: new Segment.Text { Tag = "Officer.SomethingBigText".ToIdentifier(), Width = 700, Height = 80, Anchor = Anchor.Center }, - videoContent: new Segment.Video { File = "tutorial_loaders.webm", TextTag = "Officer.SomethingBigText".ToIdentifier(), Width = 700, Height = 80 }), - new Segment( - "Officer.Hammerhead".ToIdentifier(), - "Officer.HammerheadObjective".ToIdentifier(), - TutorialContentType.TextOnly, - textContent: new Segment.Text { Tag = "Officer.HammerheadText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center }), - new Segment( - "Officer.RangedWeapon".ToIdentifier(), - "Officer.RangedWeaponObjective".ToIdentifier(), - TutorialContentType.ManualVideo, - textContent: new Segment.Text { Tag = "Officer.RangedWeaponText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center }, - videoContent: new Segment.Video { File = "tutorial_ranged.webm", TextTag = "Officer.RangedWeaponText".ToIdentifier(), Width = 450, Height = 80 }), - new Segment( - "Officer.Mudraptor".ToIdentifier(), - "Officer.MudraptorObjective".ToIdentifier(), - TutorialContentType.TextOnly, - textContent: new Segment.Text { Tag = "Officer.MudraptorText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center }), - new Segment( - "Officer.ArmSubmarine".ToIdentifier(), - "Officer.ArmSubmarineObjective".ToIdentifier(), - TutorialContentType.TextOnly, - textContent: new Segment.Text { Tag = "Officer.ArmSubmarineText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center })) - { } - - protected override CharacterInfo GetCharacterInfo() - { - return new CharacterInfo( - CharacterPrefab.HumanSpeciesName, - jobOrJobPrefab: new Job( - JobPrefab.Prefabs["securityofficer"], Rand.RandSync.Unsynced, 0, - new Skill("medical".ToIdentifier(), 20), - new Skill("weapons".ToIdentifier(), 70), - new Skill("mechanical".ToIdentifier(), 20), - new Skill("electrical".ToIdentifier(), 20), - new Skill("helm".ToIdentifier(), 20))); - } - - protected override void Initialize() - { - radioSpeakerName = TextManager.Get("Tutorial.Radio.Speaker"); - officer = Character.Controlled; - - foreach (Item item in officer.Inventory.AllItemsMod) - { - if (item.HasTag("clothing") || item.HasTag("identitycard") || item.HasTag("mobileradio")) { continue; } - item.Unequip(officer); - officer.Inventory.RemoveItem(item); - } - - var gunOrder = OrderPrefab.Prefabs["operateweapons"]; - officer_gunIcon = gunOrder.SymbolSprite; - officer_gunIconColor = gunOrder.Color; - - var bandage = FindOrGiveItem(officer, "antibleeding1".ToIdentifier()); - bandage.Unequip(officer); - officer.Inventory.RemoveItem(bandage); - FindOrGiveItem(officer, "antibleeding1".ToIdentifier()); - - // Other tutorial items - tutorial_mechanicFinalDoorLight = Item.ItemList.Find(i => i.HasTag("tutorial_mechanicfinaldoorlight")).GetComponent(); - tutorial_submarineSteering = Item.ItemList.Find(i => i.HasTag("command")).GetComponent(); - - tutorial_submarineSteering.CanBeSelected = false; - foreach (ItemComponent ic in tutorial_submarineSteering.Item.Components) - { - ic.CanBeSelected = false; - } - - SetDoorAccess(null, tutorial_mechanicFinalDoorLight, false); - - // Room 2 - officer_equipmentObjectiveSensor = Item.ItemList.Find(i => i.HasTag("officer_equipmentobjectivesensor")).GetComponent(); - officer_equipmentCabinet = Item.ItemList.Find(i => i.HasTag("officer_equipmentcabinet")).GetComponent(); - officer_firstDoor = Item.ItemList.Find(i => i.HasTag("officer_firstdoor")).GetComponent(); - officer_firstDoorLight = Item.ItemList.Find(i => i.HasTag("officer_firstdoorlight")).GetComponent(); - - SetDoorAccess(officer_firstDoor, officer_firstDoorLight, false); - - // Room 3 - officer_crawlerSensor = Item.ItemList.Find(i => i.HasTag("officer_crawlerobjectivesensor")).GetComponent(); - officer_crawlerSpawnPos = Item.ItemList.Find(i => i.HasTag("officer_crawlerspawn")).WorldPosition; - officer_secondDoor = Item.ItemList.Find(i => i.HasTag("officer_seconddoor")).GetComponent(); - officer_secondDoorLight = Item.ItemList.Find(i => i.HasTag("officer_seconddoorlight")).GetComponent(); - - SetDoorAccess(officer_secondDoor, officer_secondDoorLight, false); - - // Room 4 - officer_somethingBigSensor = Item.ItemList.Find(i => i.HasTag("officer_somethingbigobjectivesensor")).GetComponent(); - officer_coilgunLoader = Item.ItemList.Find(i => i.HasTag("officer_coilgunloader")).GetComponent(); - officer_superCapacitor = Item.ItemList.Find(i => i.HasTag("officer_supercapacitor")).GetComponent(); - officer_coilgunPeriscope = Item.ItemList.Find(i => i.HasTag("officer_coilgunperiscope")); - officer_hammerheadSpawnPos = Item.ItemList.Find(i => i.HasTag("officer_hammerheadspawn")).WorldPosition; - officer_thirdDoor = Item.ItemList.Find(i => i.HasTag("officer_thirddoor")).GetComponent(); - officer_thirdDoorLight = Item.ItemList.Find(i => i.HasTag("officer_thirddoorlight")).GetComponent(); - officer_ammoShelf_1 = Item.ItemList.Find(i => i.HasTag("officer_ammoshelf_1")).GetComponent(); - officer_ammoShelf_2 = Item.ItemList.Find(i => i.HasTag("officer_ammoshelf_2")).GetComponent(); - - SetDoorAccess(officer_thirdDoor, officer_thirdDoorLight, false); - - // Room 5 - officer_rangedWeaponSensor = Item.ItemList.Find(i => i.HasTag("officer_rangedweaponobjectivesensor")).GetComponent(); - officer_rangedWeaponCabinet = Item.ItemList.Find(i => i.HasTag("officer_rangedweaponcabinet")).GetComponent(); - officer_rangedWeaponHolder = Item.ItemList.Find(i => i.HasTag("officer_rangedweaponholder")).GetComponent(); - officer_fourthDoor = Item.ItemList.Find(i => i.HasTag("officer_fourthdoor")).GetComponent(); - officer_fourthDoorLight = Item.ItemList.Find(i => i.HasTag("officer_fourthdoorlight")).GetComponent(); - - SetDoorAccess(officer_fourthDoor, officer_fourthDoorLight, false); - - // Room 6 - officer_mudraptorObjectiveSensor = Item.ItemList.Find(i => i.HasTag("officer_mudraptorobjectivesensor")).GetComponent(); - officer_mudraptorSpawnPos = Item.ItemList.Find(i => i.HasTag("officer_mudraptorspawn")).WorldPosition; - tutorial_securityFinalDoor = Item.ItemList.Find(i => i.HasTag("tutorial_securityfinaldoor")).GetComponent(); - tutorial_securityFinalDoorLight = Item.ItemList.Find(i => i.HasTag("tutorial_securityfinaldoorlight")).GetComponent(); - - SetDoorAccess(tutorial_securityFinalDoor, tutorial_securityFinalDoorLight, false); - - // Submarine - tutorial_submarineDoor = Item.ItemList.Find(i => i.HasTag("tutorial_submarinedoor")).GetComponent(); - tutorial_submarineDoorLight = Item.ItemList.Find(i => i.HasTag("tutorial_submarinedoorlight")).GetComponent(); - tutorial_enteredSubmarineSensor = Item.ItemList.Find(i => i.HasTag("tutorial_enteredsubmarinesensor")).GetComponent(); - officer_subAmmoBox_1 = Item.ItemList.Find(i => i.HasTag("officer_subammobox_1")); - officer_subAmmoBox_2 = Item.ItemList.Find(i => i.HasTag("officer_subammobox_2")); - officer_subLoader_1 = Item.ItemList.Find(i => i.HasTag("officer_subloader_1")).GetComponent(); - officer_subLoader_2 = Item.ItemList.Find(i => i.HasTag("officer_subloader_2")).GetComponent(); - officer_subSuperCapacitor_1 = Item.ItemList.Find(i => i.HasTag("officer_subsupercapacitor_1")).GetComponent(); - officer_subSuperCapacitor_2 = Item.ItemList.Find(i => i.HasTag("officer_subsupercapacitor_2")).GetComponent(); - officer_subAmmoShelf = Item.ItemList.Find(i => i.HasTag("officer_subammoshelf")).GetComponent(); - SetDoorAccess(tutorial_submarineDoor, tutorial_submarineDoorLight, true); - - GameAnalyticsManager.AddDesignEvent("Tutorial:OfficerTutorial:Started"); - GameAnalyticsManager.AddDesignEvent("Tutorial:Started"); - } - - public override IEnumerable UpdateState() - { - while (GameMain.Instance.LoadingScreenOpen) yield return null; - - yield return new WaitForSeconds(0.01f); - - // Room 1 - SoundPlayer.PlayDamageSound("StructureBlunt", 10, Character.Controlled.WorldPosition); - while (shakeTimer > 0.0f) // Wake up, shake - { - shakeTimer -= 0.1f; - GameMain.GameScreen.Cam.Shake = shakeAmount; - yield return new WaitForSeconds(0.1f, false); - } - - GameMain.GameSession?.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.Get("Officer.Radio.WakeUp"), ChatMessageType.Radio, null); - - // Room 2 - do { yield return null; } while (!officer_equipmentObjectiveSensor.MotionDetected); - GameMain.GameSession?.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.Get("Officer.Radio.Equipment"), ChatMessageType.Radio, null); - yield return new WaitForSeconds(3f, false); - //TriggerTutorialSegment(0, GameSettings.CurrentConfig.KeyMap.Bindings[InputType.Select], GameSettings.CurrentConfig.KeyMap.Bindings[InputType.Deselect]); // Retrieve equipment - SetHighlight(officer_equipmentCabinet.Item, true); - bool firstSlotRemoved = false; - bool secondSlotRemoved = false; - bool thirdSlotRemoved = false; - do - { - if (IsSelectedItem(officer_equipmentCabinet.Item)) - { - if (!firstSlotRemoved) - { - HighlightInventorySlot(officer_equipmentCabinet.Inventory, 0, highlightColor, .5f, .5f, 0f); - if (officer_equipmentCabinet.Inventory.GetItemAt(0) == null) { firstSlotRemoved = true; } - } - - if (!secondSlotRemoved) - { - HighlightInventorySlot(officer_equipmentCabinet.Inventory, 1, highlightColor, .5f, .5f, 0f); - if (officer_equipmentCabinet.Inventory.GetItemAt(1) == null) { secondSlotRemoved = true; } - } - - if (!thirdSlotRemoved) - { - HighlightInventorySlot(officer_equipmentCabinet.Inventory, 2, highlightColor, .5f, .5f, 0f); - if (officer_equipmentCabinet.Inventory.GetItemAt(2) == null) { thirdSlotRemoved = true; } - } - - for (int i = 0; i < officer.Inventory.visualSlots.Length; i++) - { - if (officer.Inventory.GetItemAt(i) == null) { HighlightInventorySlot(officer.Inventory, i, highlightColor, .5f, .5f, 0f); } - } - } - - yield return null; - } while (!officer_equipmentCabinet.Inventory.IsEmpty()); // Wait until looted - //RemoveCompletedObjective(segments[0]); - GameAnalyticsManager.AddDesignEvent("Tutorial:OfficerTutorial:Objective0"); - SetHighlight(officer_equipmentCabinet.Item, false); - do { yield return null; } while (IsSelectedItem(officer_equipmentCabinet.Item)); - TriggerTutorialSegment(1, GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Aim), GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Shoot)); // Equip melee weapon & armor - do - { - if (!officer.HasEquippedItem("stunbaton".ToIdentifier())) - { - HighlightInventorySlot(officer.Inventory, "stunbaton".ToIdentifier(), highlightColor, .5f, .5f, 0f); - } - if (!officer.HasEquippedItem("bodyarmor".ToIdentifier())) - { - HighlightInventorySlot(officer.Inventory, "bodyarmor".ToIdentifier(), highlightColor, .5f, .5f, 0f); - } - if (!officer.HasEquippedItem("ballistichelmet1".ToIdentifier())) - { - HighlightInventorySlot(officer.Inventory, "ballistichelmet1".ToIdentifier(), highlightColor, .5f, .5f, 0f); - } - yield return new WaitForSeconds(1f, false); - } while (!officer.HasEquippedItem("stunbaton".ToIdentifier()) || !officer.HasEquippedItem("bodyarmor".ToIdentifier()) || !officer.HasEquippedItem("ballistichelmet1".ToIdentifier())); - RemoveCompletedObjective(1); - GameAnalyticsManager.AddDesignEvent("Tutorial:OfficerTutorial:Objective1"); - SetDoorAccess(officer_firstDoor, officer_firstDoorLight, true); - - // Room 3 - do { yield return null; } while (!officer_crawlerSensor.MotionDetected); - TriggerTutorialSegment(2); - officer_crawler = SpawnMonster("crawler", officer_crawlerSpawnPos); - do { yield return null; } while (!officer_crawler.IsDead); - RemoveCompletedObjective(2); - GameAnalyticsManager.AddDesignEvent("Tutorial:OfficerTutorial:Objective2"); - Heal(officer); - yield return new WaitForSeconds(1f, false); - GameMain.GameSession?.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.Get("Officer.Radio.CrawlerDead"), ChatMessageType.Radio, null); - SetDoorAccess(officer_secondDoor, officer_secondDoorLight, true); - - // Room 4 - do { yield return null; } while (!officer_somethingBigSensor.MotionDetected); - GameMain.GameSession?.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.Get("Officer.Radio.SomethingBig"), ChatMessageType.Radio, null); - yield return new WaitForSeconds(2f, false); - TriggerTutorialSegment(3); // Arm coilgun - do - { - SetHighlight(officer_coilgunLoader.Item, officer_coilgunLoader.Inventory.GetItemAt(0) == null || officer_coilgunLoader.Inventory.GetItemAt(0).Condition == 0); - HighlightInventorySlot(officer_coilgunLoader.Inventory, 0, highlightColor, .5f, .5f, 0f); - SetHighlight(officer_superCapacitor.Item, officer_superCapacitor.RechargeSpeed < superCapacitorRechargeRate); - SetHighlight(officer_ammoShelf_1.Item, officer_coilgunLoader.Item.ExternalHighlight ); - SetHighlight(officer_ammoShelf_2.Item, officer_coilgunLoader.Item.ExternalHighlight ); - if (IsSelectedItem(officer_coilgunLoader.Item)) - { - HighlightInventorySlot(officer.Inventory, "coilgunammobox".ToIdentifier(), highlightColor, .5f, .5f, 0f); - } - yield return null; - } while (officer_coilgunLoader.Inventory.GetItemAt(0) == null || officer_superCapacitor.RechargeSpeed < superCapacitorRechargeRate || officer_coilgunLoader.Inventory.GetItemAt(0).Condition == 0); - SetHighlight(officer_coilgunLoader.Item, false); - SetHighlight(officer_superCapacitor.Item, false); - SetHighlight(officer_ammoShelf_1.Item, false); - SetHighlight(officer_ammoShelf_2.Item, false); - RemoveCompletedObjective(3); - GameAnalyticsManager.AddDesignEvent("Tutorial:OfficerTutorial:Objective3"); - - yield return new WaitForSeconds(2f, false); - TriggerTutorialSegment(4, GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Select), GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Shoot), GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Deselect)); // Kill hammerhead - officer_hammerhead = SpawnMonster("hammerhead", officer_hammerheadSpawnPos); - officer_hammerhead.Params.AI.AvoidAbyss = false; - officer_hammerhead.Params.AI.StayInAbyss = false; - officer_hammerhead.AIController.SelectTarget(officer.AiTarget); - SetHighlight(officer_coilgunPeriscope, true); - float originalDistance = Vector2.Distance(officer_coilgunPeriscope.WorldPosition, officer_hammerheadSpawnPos); - do - { - float distance = Vector2.Distance(officer_coilgunPeriscope.WorldPosition, officer_hammerhead.WorldPosition); - if (distance > originalDistance * 1.5f || officer_hammerhead.WorldPosition.Y > officer_coilgunPeriscope.WorldPosition.Y) - { - // Don't let the Hammerhead go too far. - officer_hammerhead.TeleportTo(officer_hammerheadSpawnPos + new Vector2(0, -1000)); - } - if (distance > originalDistance) - { - // Ensure that the Hammerhead targets the player - officer.AiTarget.SoundRange = float.MaxValue; - officer.AiTarget.SightRange = float.MaxValue; - officer_hammerhead.AIController.SelectTarget(officer.AiTarget); - if ((officer_hammerhead.AIController as EnemyAIController)?.SelectedTargetingParams != null) - { - ((EnemyAIController)officer_hammerhead.AIController).SelectedTargetingParams.ReactDistance = 5000.0f; - } - /*var ai = officer_hammerhead.AIController as EnemyAIController; - ai.sight = 2.0f;*/ - } - yield return null; - } - while(!officer_hammerhead.IsDead); - Heal(officer); - SetHighlight(officer_coilgunPeriscope, false); - RemoveCompletedObjective(4); - GameAnalyticsManager.AddDesignEvent("Tutorial:OfficerTutorial:Objective4"); - - yield return new WaitForSeconds(1f, false); - GameMain.GameSession?.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.Get("Officer.Radio.HammerheadDead"), ChatMessageType.Radio, null); - SetDoorAccess(officer_thirdDoor, officer_thirdDoorLight, true); - - // Room 5 - //do { yield return null; } while (!officer_rangedWeaponSensor.MotionDetected); - do { yield return null; } while (!officer_thirdDoor.IsOpen); - yield return new WaitForSeconds(3f, false); - TriggerTutorialSegment(5, GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Aim), GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Shoot)); // Ranged weapons - SetHighlight(officer_rangedWeaponHolder.Item, true); - do { yield return null; } while (!officer_rangedWeaponHolder.Inventory.IsEmpty()); // Wait until looted - SetHighlight(officer_rangedWeaponHolder.Item, false); - do - { - HighlightInventorySlot(officer.Inventory, "shotgun".ToIdentifier(), highlightColor, 0.5f, 0.5f, 0f); - yield return null; - } while (!officer.HasEquippedItem("shotgun".ToIdentifier())); // Wait until equipped - ItemContainer shotGunChamber = officer.Inventory.FindItemByIdentifier("shotgun".ToIdentifier()).GetComponent(); - SetHighlight(officer_rangedWeaponCabinet.Item, true); - do - { - if (IsSelectedItem(officer_rangedWeaponCabinet.Item)) - { - if (officer_rangedWeaponCabinet.Inventory.visualSlots != null) - { - for (int i = 0; i < officer_rangedWeaponCabinet.Inventory.Capacity; i++) - { - if (officer_rangedWeaponCabinet.Inventory.GetItemAt(i)?.Prefab.Identifier == "shotgunshell") - { - HighlightInventorySlot(officer_rangedWeaponCabinet.Inventory, i, highlightColor, 0.5f, 0.5f, 0f); - } - } - } - } - - for (int i = 0; i < officer.Inventory.Capacity; i++) - { - if (officer.Inventory.GetItemAt(i)?.Prefab.Identifier == "shotgunshell") - { - HighlightInventorySlot(officer.Inventory, i, highlightColor, 0.5f, 0.5f, 0f); - } - } - - if (officer.Inventory.FindItemByIdentifier("shotgunshell".ToIdentifier()) != null || (IsSelectedItem(officer_rangedWeaponCabinet.Item) && officer_rangedWeaponCabinet.Inventory.FindItemByIdentifier("shotgunshell".ToIdentifier()) != null)) - { - HighlightInventorySlot(officer.Inventory, "shotgun".ToIdentifier(), highlightColor, 0.5f, 0.5f, 0f); - } - yield return null; - } while (!shotGunChamber.Inventory.IsFull(takeStacksIntoAccount: true)); // Wait until all six harpoons loaded - RemoveCompletedObjective(5); - GameAnalyticsManager.AddDesignEvent("Tutorial:OfficerTutorial:Objective5"); - SetHighlight(officer_rangedWeaponCabinet.Item, false); - SetDoorAccess(officer_fourthDoor, officer_fourthDoorLight, true); - - // Room 6 - do { yield return null; } while (!officer_mudraptorObjectiveSensor.MotionDetected); - TriggerTutorialSegment(6); - officer_mudraptor = SpawnMonster("mudraptor", officer_mudraptorSpawnPos); - do { yield return null; } while (!officer_mudraptor.IsDead); - Heal(officer); - RemoveCompletedObjective(6); - GameAnalyticsManager.AddDesignEvent("Tutorial:OfficerTutorial:Objective6"); - SetDoorAccess(tutorial_securityFinalDoor, tutorial_securityFinalDoorLight, true); - - // Submarine - do { yield return null; } while (!tutorial_enteredSubmarineSensor.MotionDetected); - TriggerTutorialSegment(7); - while (ContentRunning) yield return null; - officer.AddActiveObjectiveEntity(officer_subAmmoBox_1, officer_gunIcon, officer_gunIconColor); - officer.AddActiveObjectiveEntity(officer_subAmmoBox_2, officer_gunIcon, officer_gunIconColor); - officer.AddActiveObjectiveEntity(officer_subSuperCapacitor_1.Item, officer_gunIcon, officer_gunIconColor); - officer.AddActiveObjectiveEntity(officer_subSuperCapacitor_2.Item, officer_gunIcon, officer_gunIconColor); - SetHighlight(officer_subSuperCapacitor_1.Item, true); - SetHighlight(officer_subSuperCapacitor_2.Item, true); - GameMain.GameSession?.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.Get("Officer.Radio.Submarine"), ChatMessageType.Radio, null); - do - { - SetHighlight(officer_subLoader_1.Item, officer_subLoader_1.Inventory.GetItemAt(0) == null || officer_subLoader_1.Inventory.GetItemAt(0).Condition == 0); - SetHighlight(officer_subLoader_2.Item, officer_subLoader_2.Inventory.GetItemAt(0) == null || officer_subLoader_2.Inventory.GetItemAt(0).Condition == 0); - HighlightInventorySlot(officer_subLoader_1.Inventory, 0, highlightColor, .5f, .5f, 0f); - HighlightInventorySlot(officer_subLoader_2.Inventory, 0, highlightColor, .5f, .5f, 0f); - - if (officer_subSuperCapacitor_1.Item.ExternalHighlight && officer_subSuperCapacitor_1.RechargeSpeed >= superCapacitorRechargeRate) - { - SetHighlight(officer_subSuperCapacitor_1.Item, false); - officer.RemoveActiveObjectiveEntity(officer_subSuperCapacitor_1.Item); - } - - if (officer_subSuperCapacitor_2.Item.ExternalHighlight && officer_subSuperCapacitor_2.RechargeSpeed >= superCapacitorRechargeRate) - { - SetHighlight(officer_subSuperCapacitor_2.Item, false); - officer.RemoveActiveObjectiveEntity(officer_subSuperCapacitor_2.Item); - } - - SetHighlight(officer_subAmmoBox_1, officer_subAmmoBox_1.ParentInventory != officer_subLoader_1.Inventory && officer_subAmmoBox_1.ParentInventory != officer_subLoader_2.Inventory); - SetHighlight(officer_subAmmoBox_2, officer_subAmmoBox_2.ParentInventory != officer_subLoader_1.Inventory && officer_subAmmoBox_2.ParentInventory != officer_subLoader_2.Inventory); - SetHighlight(officer_subAmmoShelf.Item, officer_subLoader_1.Item.ExternalHighlight || officer_subLoader_2.Item.ExternalHighlight); - if (officer_subAmmoBox_1.ParentInventory == officer_subLoader_1.Inventory || officer_subAmmoBox_1.ParentInventory == officer_subLoader_2.Inventory) officer.RemoveActiveObjectiveEntity(officer_subAmmoBox_1); - if (officer_subAmmoBox_2.ParentInventory == officer_subLoader_1.Inventory || officer_subAmmoBox_2.ParentInventory == officer_subLoader_2.Inventory) officer.RemoveActiveObjectiveEntity(officer_subAmmoBox_2); - yield return null; - } while (officer_subLoader_1.Item.ExternalHighlight || officer_subLoader_2.Item.ExternalHighlight || officer_subSuperCapacitor_1.Item.ExternalHighlight || officer_subSuperCapacitor_2.Item.ExternalHighlight); - SetHighlight(officer_subLoader_1.Item, false); - SetHighlight(officer_subLoader_2.Item, false); - SetHighlight(officer_subSuperCapacitor_1.Item, false); - SetHighlight(officer_subSuperCapacitor_2.Item, false); - SetHighlight(officer_subAmmoBox_1, false); - SetHighlight(officer_subAmmoBox_2, false); - SetHighlight(officer_subAmmoShelf.Item, false); - officer.RemoveActiveObjectiveEntity(officer_subSuperCapacitor_1.Item); - officer.RemoveActiveObjectiveEntity(officer_subSuperCapacitor_2.Item); - officer.RemoveActiveObjectiveEntity(officer_subAmmoBox_1); - officer.RemoveActiveObjectiveEntity(officer_subAmmoBox_2); - RemoveCompletedObjective(7); - GameAnalyticsManager.AddDesignEvent("Tutorial:OfficerTutorial:Objective7"); - GameMain.GameSession?.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.Get("Officer.Radio.Complete"), ChatMessageType.Radio, null); - - yield return new WaitForSeconds(4f, false); - GameAnalyticsManager.AddDesignEvent("Tutorial:OfficerTutorial:Completed"); - CoroutineManager.StartCoroutine(TutorialCompleted()); - } - - private bool IsSelectedItem(Item item) - { - return officer?.SelectedItem == item; - } - - private Character SpawnMonster(string speciesName, Vector2 pos) - { - var character = Character.Create(speciesName, pos, ToolBox.RandomSeed(8)); - var ai = character.AIController as EnemyAIController; - ai.TargetOutposts = true; - character.CharacterHealth.SetVitality(character.Health / 2); - character.AnimController.Limbs.Where(l => l.attack != null).Select(l => l.attack).ForEach(a => a.AfterAttack = AIBehaviorAfterAttack.FallBack); - return character; - } - } -} diff --git a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/ScenarioTutorial.cs b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/ScenarioTutorial.cs deleted file mode 100644 index 7d72179b1..000000000 --- a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/ScenarioTutorial.cs +++ /dev/null @@ -1,307 +0,0 @@ -using Barotrauma.Items.Components; -using Microsoft.Xna.Framework; -using System.Collections.Generic; -using System.Linq; - -namespace Barotrauma.Tutorials -{ - abstract class ScenarioTutorial : Tutorial - { - private CoroutineHandle tutorialCoroutine; - - private Character character; - - private const string submarinePath = "Content/Tutorials/Dugong_Tutorial.sub"; - private const string startOutpostPath = "Content/Tutorials/TutorialOutpost.sub"; - //private const string endOutpostPath = ""; - - private const string levelSeed = "nLoZLLtza"; - private const string levelParams = "ColdCavernsTutorial"; - - //private const string spawnSub = "startoutpost"; - private const SpawnType spawnPointType = SpawnType.Human; - - private SubmarineInfo startOutpost = null; - private SubmarineInfo endOutpost = null; - private bool currentTutorialCompleted = false; - private float fadeOutTime = 3f; - protected float waitBeforeFade = 4f; - - // Colors - protected Color highlightColor = Color.OrangeRed; - protected Color uiHighlightColor = new Color(150, 50, 0); - protected Color buttonHighlightColor = new Color(255, 100, 0); - protected Color inaccessibleColor = GUIStyle.Red; - protected Color accessibleColor = GUIStyle.Green; - - protected ScenarioTutorial(Identifier identifier, params Segment[] segments) : base(identifier, segments) { } - - protected abstract void Initialize(); - - protected override IEnumerable Loading() - { - SubmarineInfo subInfo = new SubmarineInfo(submarinePath); - - LevelGenerationParams generationParams = LevelGenerationParams.LevelParams.Find(p => p.Identifier == levelParams); - - yield return CoroutineStatus.Running; - - GameMain.GameSession = new GameSession(subInfo, GameModePreset.Tutorial, missionPrefabs: null); - (GameMain.GameSession.GameMode as TutorialMode).Tutorial = this; - - if (generationParams != null) - { - Biome biome = - Biome.Prefabs.FirstOrDefault(b => generationParams.AllowedBiomeIdentifiers.Contains(b.Identifier)) ?? - Biome.Prefabs.First(); - - if (!string.IsNullOrEmpty(startOutpostPath)) - { - startOutpost = new SubmarineInfo(startOutpostPath); - } - - /*if (!string.IsNullOrEmpty(endOutpostPath)) - { - endOutpost = new SubmarineInfo(endOutpostPath); - }*/ - - LevelData tutorialLevel = new LevelData(levelSeed, 0, 0, generationParams, biome); - GameMain.GameSession.StartRound(tutorialLevel, startOutpost: startOutpost, endOutpost: endOutpost); - } - else - { - GameMain.GameSession.StartRound(levelSeed); - } - - GameMain.GameSession.EventManager.ActiveEvents.Clear(); - GameMain.GameSession.EventManager.Enabled = false; - GameMain.GameScreen.Select(); - - - Submarine.MainSub.GodMode = true; - foreach (Structure wall in Structure.WallList) - { - if (wall.Submarine != null && wall.Submarine.Info.IsOutpost) - { - wall.Indestructible = true; - } - } - - CharacterInfo charInfo = GetCharacterInfo(); - - WayPoint wayPoint = GetSpawnPoint(charInfo); - - if (wayPoint == null) - { - DebugConsole.ThrowError("A waypoint with the spawntype \"" + spawnPointType + "\" is required for the tutorial event"); - yield return CoroutineStatus.Failure; - yield break; - } - - character = Character.Create(charInfo, wayPoint.WorldPosition, "", isRemotePlayer: false, hasAi: false); - character.TeamID = CharacterTeamType.Team1; - Character.Controlled = character; - character.GiveJobItems(null); - - var idCard = character.Inventory.FindItemByTag("identitycard".ToIdentifier()); - if (idCard == null) - { - DebugConsole.ThrowError("Item prefab \"ID Card\" not found!"); - yield return CoroutineStatus.Failure; - yield break; - } - idCard.AddTag("com"); - idCard.AddTag("eng"); - - foreach (Item item in Item.ItemList) - { - Door door = item.GetComponent(); - if (door != null) - { - door.CanBeWelded = false; - } - } - - tutorialCoroutine = CoroutineManager.StartCoroutine(UpdateState()); - - Initialize(); - - yield return CoroutineStatus.Success; - } - - protected abstract CharacterInfo GetCharacterInfo(); - - public override void AddToGUIUpdateList() - { - if (!currentTutorialCompleted) - { - base.AddToGUIUpdateList(); - } - } - - private WayPoint GetSpawnPoint(CharacterInfo charInfo) - { - /*Submarine spawnSub = null; - - if (this.spawnSub != string.Empty) - { - switch (this.spawnSub) - { - case "startoutpost": - spawnSub = Level.Loaded.StartOutpost; - break; - - case "endoutpost": - spawnSub = Level.Loaded.EndOutpost; - break; - - default: - spawnSub = Submarine.MainSub; - break; - } - }*/ - Submarine spawnSub = Level.Loaded.StartOutpost; - return WayPoint.GetRandom(spawnPointType, charInfo.Job?.Prefab, spawnSub); - } - - protected bool HasOrder(Character character, string identifier, string option = null) - { - var currentOrderInfo = character.GetCurrentOrderWithTopPriority(); - if (currentOrderInfo?.Identifier == identifier) - { - if (option == null) - { - return true; - } - else - { - return currentOrderInfo?.Option == option; - } - } - - return false; - } - - protected void SetHighlight(Item item, bool state) - { - if (item.ExternalHighlight == state) return; - item.SpriteColor = (state) ? highlightColor : Color.White; - item.ExternalHighlight = state; - } - - protected void SetHighlight(Structure structure, bool state) - { - structure.SpriteColor = (state) ? highlightColor : Color.White; - structure.ExternalHighlight = state; - } - - protected void SetHighlight(Character character, bool state) - { - character.ExternalHighlight = state; - } - - protected void SetDoorAccess(Door door, LightComponent light, bool state) - { - if (state && door != null) door.requiredItems.Clear(); - if (light != null) light.LightColor = (state) ? accessibleColor : inaccessibleColor; - } - - public override void Update(float deltaTime) - { - base.Update(deltaTime); - if (character != null) - { - if (character.Oxygen < 1) - { - character.Oxygen = 1; - } - if (character.IsDead) - { - CoroutineManager.StartCoroutine(Dead()); - } - else if (Character.Controlled == null) - { - if (tutorialCoroutine != null) - { - CoroutineManager.StopCoroutines(tutorialCoroutine); - } - GUI.PreventPauseMenuToggle = false; - ContentRunning = false; - infoBox = null; - } - else if (Character.Controlled.IsDead) - { - CoroutineManager.StartCoroutine(Dead()); - } - } - } - - public override void Stop() - { - if (tutorialCoroutine != null) - { - CoroutineManager.StopCoroutines(tutorialCoroutine); - } - base.Stop(); - } - - private IEnumerable Dead() - { - GUI.PreventPauseMenuToggle = true; - Character.Controlled = character = null; - Stop(); - - GameAnalyticsManager.AddDesignEvent("Tutorial:Died"); - - yield return new WaitForSeconds(3.0f); - - var messageBox = new GUIMessageBox(TextManager.Get("Tutorial.TryAgainHeader"), TextManager.Get("Tutorial.TryAgain"), new LocalizedString[] { TextManager.Get("Yes"), TextManager.Get("No") }); - - messageBox.Buttons[0].OnClicked += Restart; - messageBox.Buttons[0].OnClicked += messageBox.Close; - - - messageBox.Buttons[1].OnClicked = GameMain.MainMenuScreen.ReturnToMainMenu; - messageBox.Buttons[1].OnClicked += messageBox.Close; - - yield return CoroutineStatus.Success; - } - - protected IEnumerable TutorialCompleted() - { - GUI.PreventPauseMenuToggle = true; - - Character.Controlled.ClearInputs(); - Character.Controlled = null; - - GameAnalyticsManager.AddDesignEvent("Tutorial:Completed"); - - yield return new WaitForSeconds(waitBeforeFade); - - var endCinematic = new CameraTransition(Submarine.MainSub, GameMain.GameScreen.Cam, null, Alignment.Center, panDuration: fadeOutTime); - currentTutorialCompleted = Completed = true; - while (endCinematic.Running) yield return null; - Stop(); - GameMain.MainMenuScreen.ReturnToMainMenu(null, null); - } - - protected void Heal(Character character) - { - character.SetAllDamage(0.0f, 0.0f, 0.0f); - character.Oxygen = 100.0f; - character.Bloodloss = 0.0f; - character.SetStun(0.0f, true); - } - - protected Item FindOrGiveItem(Character character, Identifier identifier) - { - var item = character.Inventory.FindItemByIdentifier(identifier); - if (item != null && !item.Removed) { return item; } - - ItemPrefab itemPrefab = MapEntityPrefab.Find(name: null, identifier: identifier) as ItemPrefab; - item = new Item(itemPrefab, Vector2.Zero, submarine: null); - character.Inventory.TryPutItem(item, character, item.AllowedSlots); - return item; - } - } -} diff --git a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/Tutorial.cs b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/Tutorial.cs index 42795e0bf..ea4e51c49 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/Tutorial.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/Tutorial.cs @@ -1,30 +1,32 @@ -using Microsoft.Xna.Framework; -using Microsoft.Xna.Framework.Input; +using Barotrauma.Extensions; +using Barotrauma.Items.Components; +using Microsoft.Xna.Framework; using System; using System.Collections.Generic; -using System.Reflection; -using System.Linq; -using System.Xml.Linq; -using Barotrauma.Items.Components; -using Barotrauma.Extensions; using System.Collections.Immutable; +using System.Linq; namespace Barotrauma.Tutorials { - enum TutorialContentType { None = 0, Video = 1, ManualVideo = 2, TextOnly = 3 }; + enum AutoPlayVideo { Yes, No }; - /// - /// If you're seeing this and are currently working on improving the tutorials, consider - /// deleting this class and all that derive from it, and starting from scratch. - /// - abstract class Tutorial + enum TutorialSegmentType { MessageBox, InfoBox }; + + class Tutorial { #region Constants - public const string PlayableContentPath = "Content/Tutorials/TutorialVideos/"; + + private const string PlayableContentPath = "Content/Tutorials/TutorialVideos/"; + private const SpawnType SpawnPointType = SpawnType.Human; + private const float FadeOutTime = 3f; + private const float WaitBeforeFade = 4f; + #endregion #region Tutorial variables + public static ImmutableHashSet Types; + static Tutorial() { Types = ReflectionUtils.GetDerivedNonAbstract() @@ -37,30 +39,41 @@ namespace Barotrauma.Tutorials public bool ContentRunning { get; protected set; } - protected GUIComponent infoBox; + private GUIComponent infoBox; private Action infoBoxClosedCallback; - protected VideoPlayer videoPlayer; - protected Point screenResolution; - protected WindowMode windowMode; - protected float prevUIScale; + private VideoPlayer videoPlayer; + private Point screenResolution; + private WindowMode windowMode; + private float prevUIScale; - private GUIFrame holderFrame, objectiveFrame; - private readonly List activeObjectives; - private readonly LocalizedString objectiveTranslated; + private GUILayoutGroup objectiveGroup; + private readonly LocalizedString objectiveTextTranslated; - protected readonly ImmutableArray segments; - protected Index activeContentSegmentIndex; - protected Segment activeContentSegment => segments[activeContentSegmentIndex]; + private readonly List ActiveObjectives = new List(); + private const float ObjectiveComponentRemovalTime = 1.5f; + private Segment ActiveContentSegment { get; set; } - protected class Segment + public class Segment { public struct Text { + private const Anchor DefaultAnchor = Anchor.Center; + public Identifier Tag; public int Width; public int Height; public Anchor Anchor; + + public Text(Identifier tag, int? width = null, int? height = null, Anchor? anchor = null) + { + Tag = tag; + Width = width ?? DefaultWidth; + Height = height ?? DefaultHeight; + Anchor = anchor ?? DefaultAnchor; + } + + public Text(string tag, int? width = null, int? height = null, Anchor? anchor = null) : this(tag.ToIdentifier(), width, height, anchor) { } } public struct Video @@ -69,36 +82,63 @@ namespace Barotrauma.Tutorials public Identifier TextTag; public int Width; public int Height; + + public Video(string file, Identifier textTag, int? width = null, int? height = null) + { + File = file; + TextTag = textTag; + Width = width ?? DefaultWidth; + Height = height ?? DefaultHeight; + } + + public Video(string file, string textTag, int? width = null, int? height = null) : this(file, textTag.ToIdentifier(), width, height) { } } - public bool IsTriggered; - public GUIButton ReplayButton; - public GUITextBlock LinkedTitle, LinkedText; - public object[] Args; - public LocalizedString Objective; + private const int DefaultWidth = 450; + private const int DefaultHeight = 80; + + public GUIImage ObjectiveStateIndicator; + public GUIButton ObjectiveButton; + public GUITextBlock LinkedTextBlock; + public LocalizedString ObjectiveText; public readonly Identifier Id; public readonly Text? TextContent; public readonly Video? VideoContent; - public readonly TutorialContentType ContentType; + public readonly AutoPlayVideo AutoPlayVideo; - public Segment(Identifier id, Identifier objectiveTextTag, TutorialContentType contentType, Text? textContent = null, Video? videoContent = null) + public Action OnClickToDisplayMessage; + + public readonly TutorialSegmentType SegmentType; + + public Segment(Identifier id, Identifier objectiveTextTag, AutoPlayVideo autoPlayVideo, Text? textContent = null, Video? videoContent = null) { Id = id; - Objective = TextManager.ParseInputTypes(TextManager.Get(objectiveTextTag)); - ContentType = contentType; + ObjectiveText = TextManager.ParseInputTypes(TextManager.Get(objectiveTextTag)); + AutoPlayVideo = autoPlayVideo; TextContent = textContent; VideoContent = videoContent; + SegmentType = TutorialSegmentType.InfoBox; + } - IsTriggered = false; + public Segment(Identifier id, Action onClickToDisplayMessage) + { + Id = id; + var objetiveTextTag = $"{id}.objective".ToIdentifier(); + ObjectiveText = TextManager.ParseInputTypes(TextManager.Get(objetiveTextTag)); + OnClickToDisplayMessage = onClickToDisplayMessage; + SegmentType = TutorialSegmentType.MessageBox; } } private bool completed; public bool Completed { - get { return completed; } - protected set + get + { + return completed; + } + private set { if (completed == value) { return; } completed = value; @@ -109,26 +149,150 @@ namespace Barotrauma.Tutorials GameSettings.SaveCurrentConfig(); } } + + public readonly TutorialPrefab TutorialPrefab; + private readonly EventPrefab eventPrefab; + + private CoroutineHandle tutorialCoroutine; + + private Character character; + + private readonly string submarinePath = "Content/Tutorials/Dugong_Tutorial.sub"; + private readonly string startOutpostPath = "Content/Tutorials/TutorialOutpost.sub"; + + private readonly string levelSeed = "nLoZLLtza"; + private readonly string levelParams = "ColdCavernsTutorial"; + + private SubmarineInfo startOutpost = null; + #endregion #region Tutorial Controls - protected Tutorial(Identifier identifier, params Segment[] segments) + + public Tutorial(TutorialPrefab prefab) { - Identifier = identifier; - this.segments = segments.ToImmutableArray(); + Identifier = $"tutorial.{prefab?.Identifier ?? Identifier.Empty}".ToIdentifier(); DisplayName = TextManager.Get(Identifier); - activeObjectives = new List(); - objectiveTranslated = TextManager.Get("Tutorial.Objective"); + objectiveTextTranslated = TextManager.Get("Tutorial.Objective"); + + TutorialPrefab = prefab; + submarinePath = prefab.SubmarinePath.Value; + startOutpostPath = prefab.OutpostPath.Value; + levelSeed = prefab.LevelSeed; + levelParams = prefab.LevelParams; + eventPrefab = EventSet.GetEventPrefab(prefab.EventIdentifier); } - protected abstract IEnumerable Loading(); + private IEnumerable Loading() + { + SubmarineInfo subInfo = new SubmarineInfo(submarinePath); + + LevelGenerationParams generationParams = LevelGenerationParams.LevelParams.Find(p => p.Identifier == levelParams); + + yield return CoroutineStatus.Running; + + GameMain.GameSession = new GameSession(subInfo, GameModePreset.Tutorial, missionPrefabs: null); + (GameMain.GameSession.GameMode as TutorialMode).Tutorial = this; + + if (generationParams != null) + { + Biome biome = + Biome.Prefabs.FirstOrDefault(b => generationParams.AllowedBiomeIdentifiers.Contains(b.Identifier)) ?? + Biome.Prefabs.First(); + + if (!string.IsNullOrEmpty(startOutpostPath)) + { + startOutpost = new SubmarineInfo(startOutpostPath); + } + + LevelData tutorialLevel = new LevelData(levelSeed, 0, 0, generationParams, biome); + GameMain.GameSession.StartRound(tutorialLevel, startOutpost: startOutpost); + } + else + { + GameMain.GameSession.StartRound(levelSeed); + } + + GameMain.GameSession.EventManager.ActiveEvents.Clear(); + GameMain.GameSession.EventManager.Enabled = true; + GameMain.GameScreen.Select(); + + if (Submarine.MainSub != null) + { + Submarine.MainSub.GodMode = true; + } + foreach (Structure wall in Structure.WallList) + { + if (wall.Submarine != null && wall.Submarine.Info.IsOutpost) + { + wall.Indestructible = true; + } + } + + var charInfo = TutorialPrefab.GetTutorialCharacterInfo(); + + var wayPoint = WayPoint.GetRandom(SpawnPointType, charInfo.Job?.Prefab, Level.Loaded.StartOutpost); + + if (wayPoint == null) + { + DebugConsole.ThrowError("A waypoint with the spawntype \"" + SpawnPointType + "\" is required for the tutorial event"); + yield return CoroutineStatus.Failure; + yield break; + } + + character = Character.Create(charInfo, wayPoint.WorldPosition, "", isRemotePlayer: false, hasAi: false); + character.TeamID = CharacterTeamType.Team1; + Character.Controlled = character; + character.GiveJobItems(null); + + var idCard = character.Inventory.FindItemByTag("identitycard".ToIdentifier()); + if (idCard == null) + { + DebugConsole.ThrowError("Item prefab \"ID Card\" not found!"); + yield return CoroutineStatus.Failure; + yield break; + } + idCard.AddTag("com"); + idCard.AddTag("eng"); + + foreach (Item item in Item.ItemList) + { + Door door = item.GetComponent(); + if (door != null) + { + door.CanBeWelded = false; + } + } + + tutorialCoroutine = CoroutineManager.StartCoroutine(UpdateState()); + + Initialize(); + + yield return CoroutineStatus.Success; + } + + private void Initialize() + { + GameMain.GameSession.CrewManager.AllowCharacterSwitch = TutorialPrefab.AllowCharacterSwitch; + + if (Character.Controlled is Character character) + { + foreach (Item item in character.Inventory.AllItemsMod) + { + if (item.HasTag(TutorialPrefab.StartingItemTags)) { continue; } + item.Unequip(character); + character.Inventory.RemoveItem(item); + } + } + } public void Start() { videoPlayer = new VideoPlayer(); GameMain.Instance.ShowLoading(Loading()); - - activeObjectives.Clear(); + ActiveObjectives.Clear(); + ActiveContentSegment = null; + CreateObjectiveFrame(); // Setup doors: Clear all requirements, unless the door is setup as locked. @@ -145,35 +309,73 @@ namespace Barotrauma.Tutorials } } - public virtual void AddToGUIUpdateList() + public void AddToGUIUpdateList() { if (GameMain.GraphicsWidth != screenResolution.X || GameMain.GraphicsHeight != screenResolution.Y || prevUIScale != GUI.Scale || GameSettings.CurrentConfig.Graphics.DisplayMode != windowMode) { CreateObjectiveFrame(); } - - if (objectiveFrame != null && activeObjectives.Count > 0) + if (ActiveObjectives.Count > 0) { - objectiveFrame.AddToGUIUpdateList(order: -1); + objectiveGroup?.AddToGUIUpdateList(order: -1); } - - if (infoBox != null) infoBox.AddToGUIUpdateList(order: 100); - if (videoPlayer != null) videoPlayer.AddToGUIUpdateList(order: 100); + infoBox?.AddToGUIUpdateList(order: 100); + videoPlayer?.AddToGUIUpdateList(order: 100); } - public virtual void Update(float deltaTime) + public void Update() { videoPlayer?.Update(); - if (activeObjectives != null) + if (character != null) { - for (int i = 0; i < activeObjectives.Count; i++) + if (character.Oxygen < 1) { - CheckActiveObjectives(activeObjectives[i], deltaTime); + character.Oxygen = 1; + } + if (character.IsDead) + { + CoroutineManager.StartCoroutine(Dead()); + } + else if (Character.Controlled == null) + { + if (tutorialCoroutine != null) + { + CoroutineManager.StopCoroutines(tutorialCoroutine); + } + GUI.PreventPauseMenuToggle = false; + ContentRunning = false; + infoBox = null; + } + else if (Character.Controlled.IsDead) + { + CoroutineManager.StartCoroutine(Dead()); } } } + private IEnumerable Dead() + { + GUI.PreventPauseMenuToggle = true; + Character.Controlled = character = null; + Stop(); + + GameAnalyticsManager.AddDesignEvent("Tutorial:Died"); + + yield return new WaitForSeconds(3.0f); + + var messageBox = new GUIMessageBox(TextManager.Get("Tutorial.TryAgainHeader"), TextManager.Get("Tutorial.TryAgain"), new LocalizedString[] { TextManager.Get("Yes"), TextManager.Get("No") }); + + messageBox.Buttons[0].OnClicked += Restart; + messageBox.Buttons[0].OnClicked += messageBox.Close; + + + messageBox.Buttons[1].OnClicked = GameMain.MainMenuScreen.ReturnToMainMenu; + messageBox.Buttons[1].OnClicked += messageBox.Close; + + yield return CoroutineStatus.Success; + } + public void CloseActiveContentGUI() { if (videoPlayer.IsPlaying) @@ -182,257 +384,307 @@ namespace Barotrauma.Tutorials } else if (infoBox != null) { - CloseInfoFrame(null, null); + CloseInfoFrame(); } } - public virtual IEnumerable UpdateState() + public IEnumerable UpdateState() { + while (GameMain.Instance.LoadingScreenOpen || Level.Loaded == null || Level.Loaded.Generating) + { + yield return new WaitForSeconds(0.1f); + } + + if (eventPrefab == null) + { + DebugConsole.ShowError($"No tutorial event defined for the tutorial (identifier: \"{TutorialPrefab?.Identifier.ToString() ?? "null"})\""); + yield return CoroutineStatus.Failure; + } + + if (eventPrefab.CreateInstance() is Event eventInstance) + { + GameMain.GameSession.EventManager.QueuedEvents.Enqueue(eventInstance); + while (!eventInstance.IsFinished) + { + yield return CoroutineStatus.Running; + } + } + else + { + DebugConsole.ShowError($"Failed to create an instance for a tutorial event (identifier: \"{eventPrefab.Identifier}\""); + yield return CoroutineStatus.Failure; + } + yield return CoroutineStatus.Success; } - protected bool Restart(GUIButton button, object obj) + public void Complete() + { + GameAnalyticsManager.AddDesignEvent($"Tutorial:{Identifier}:Completed"); + CoroutineManager.StartCoroutine(TutorialCompleted()); + + IEnumerable TutorialCompleted() + { + GUI.PreventPauseMenuToggle = true; + Character.Controlled.ClearInputs(); + Character.Controlled = null; + GameAnalyticsManager.AddDesignEvent("Tutorial:Completed"); + + yield return new WaitForSeconds(WaitBeforeFade); + + var endCinematic = new CameraTransition(Submarine.MainSub, GameMain.GameScreen.Cam, null, Alignment.Center, panDuration: FadeOutTime); + Completed = true; + + while (endCinematic.Running) { yield return null; } + + Stop(); + GameMain.MainMenuScreen.ReturnToMainMenu(null, null); + } + } + + private bool Restart(GUIButton button, object obj) { GUI.PreventPauseMenuToggle = false; return true; } - protected virtual void TriggerTutorialSegment(Index index, params object[] args) + public void TriggerTutorialSegment(Segment segment) { + if (segment.SegmentType == TutorialSegmentType.MessageBox) + { + ActiveObjectives.Add(segment); + AddToObjectiveList(segment); + return; + } + Inventory.DraggingItems.Clear(); ContentRunning = true; - activeContentSegmentIndex = index; - segments[index].Args = args; + ActiveContentSegment = segment; - LocalizedString tutorialText = TextManager.GetFormatted(segments[index].TextContent.Value.Tag, args); + var title = TextManager.Get(segment.Id); + LocalizedString tutorialText = TextManager.GetFormatted(segment.TextContent.Value.Tag); tutorialText = TextManager.ParseInputTypes(tutorialText); - LocalizedString objectiveText = string.Empty; - if (!segments[index].Objective.IsNullOrEmpty()) + switch (segment.AutoPlayVideo) { - if (args.Length == 0) - { - objectiveText = segments[index].Objective; - } - else - { - objectiveText = TextManager.GetFormatted(segments[index].Objective, args); - } - objectiveText = TextManager.ParseInputTypes(objectiveText); - segments[index].Objective = objectiveText; - } - else - { - segments[index].IsTriggered = true; // Complete at this stage only if no related objective - } - - - switch (segments[index].ContentType) - { - case TutorialContentType.None: + case AutoPlayVideo.Yes: + infoBox = CreateInfoFrame( + title, + tutorialText, + segment.TextContent.Value.Width, + segment.TextContent.Value.Height, + segment.TextContent.Value.Anchor, + hasButton: true, + onInfoBoxClosed: LoadActiveContentVideo); break; - case TutorialContentType.Video: - infoBox = CreateInfoFrame(TextManager.Get(activeContentSegment.Id), tutorialText, - activeContentSegment.TextContent.Value.Width, - activeContentSegment.TextContent.Value.Height, - activeContentSegment.TextContent.Value.Anchor, true, () => LoadVideo(activeContentSegment)); - break; - case TutorialContentType.ManualVideo: - infoBox = CreateInfoFrame(TextManager.Get(activeContentSegment.Id), tutorialText, - activeContentSegment.TextContent.Value.Width, - activeContentSegment.TextContent.Value.Height, - activeContentSegment.TextContent.Value.Anchor, true, StopCurrentContentSegment, () => LoadVideo(activeContentSegment)); - break; - case TutorialContentType.TextOnly: - infoBox = CreateInfoFrame(TextManager.Get(activeContentSegment.Id), tutorialText, - activeContentSegment.TextContent.Value.Width, - activeContentSegment.TextContent.Value.Height, - activeContentSegment.TextContent.Value.Anchor, true, StopCurrentContentSegment); + case AutoPlayVideo.No: + infoBox = CreateInfoFrame( + title, + tutorialText, + segment.TextContent.Value.Width, + segment.TextContent.Value.Height, + segment.TextContent.Value.Anchor, + hasButton: true, + onInfoBoxClosed: StopCurrentContentSegment, + onVideoButtonClicked: LoadActiveContentVideo); break; } } - public virtual void Stop() + public void CompleteTutorialSegment(Identifier segmentId) { + if (!(GetActiveObjective(segmentId) is Segment segment)) + { + DebugConsole.AddWarning($"Warning: tried to complete the tutorial segment \"{segmentId}\" in tutorial \"{Identifier}\" but it isn't active!"); + return; + } + if (GUIStyle.GetComponentStyle("ObjectiveIndicatorCompleted") is GUIComponentStyle style) + { + segment.ObjectiveStateIndicator.ApplyStyle(style); + segment.ObjectiveStateIndicator.Flash(color: GUIStyle.Green); + } + segment.ObjectiveButton.OnClicked = null; + segment.ObjectiveButton.CanBeFocused = false; + } + + public void RemoveTutorialSegment(Identifier segmentId) + { + if (!(GetActiveObjective(segmentId) is Segment segment)) + { + DebugConsole.AddWarning($"Warning: tried to remove the tutorial segment \"{segmentId}\" in tutorial \"{Identifier}\" but it isn't active!"); + return; + } + segment.ObjectiveStateIndicator.FadeOut(ObjectiveComponentRemovalTime, false); + segment.LinkedTextBlock.FadeOut(ObjectiveComponentRemovalTime, false); + var parent = segment.LinkedTextBlock.Parent; + parent.FadeOut(ObjectiveComponentRemovalTime, true, onRemove: () => + { + ActiveObjectives.Remove(segment); + objectiveGroup?.Recalculate(); + }); + var targetPos = new Point(GameMain.GraphicsWidth - parent.Rect.X, 0); + parent.RectTransform.MoveOverTime(targetPos, ObjectiveComponentRemovalTime); + segment.ObjectiveButton.OnClicked = null; + segment.ObjectiveButton.CanBeFocused = false; + } + + private Segment GetActiveObjective(Identifier id) => ActiveObjectives.FirstOrDefault(s => s.Id == id); + + public void Stop() + { + if (tutorialCoroutine != null) + { + CoroutineManager.StopCoroutines(tutorialCoroutine); + } ContentRunning = false; infoBox = null; - videoPlayer.Remove(); + videoPlayer?.Remove(); } + #endregion #region Objectives + + /// + /// Create the objective list that holds the objectives (called on start and on resolution change) + /// private void CreateObjectiveFrame() { - holderFrame = new GUIFrame(new RectTransform(new Point(GameMain.GraphicsWidth, GameMain.GraphicsHeight), GUI.Canvas, Anchor.Center)); - objectiveFrame = new GUIFrame(HUDLayoutSettings.ToRectTransform(HUDLayoutSettings.ObjectiveAnchor, holderFrame.RectTransform), style: null); - - for (int i = 0; i < activeObjectives.Count; i++) + var objectiveListFrame = new GUIFrame(HUDLayoutSettings.ToRectTransform(HUDLayoutSettings.TutorialObjectiveListArea, GUI.Canvas), style: null); + objectiveGroup = new GUILayoutGroup(new RectTransform(Vector2.One, objectiveListFrame.RectTransform)) { - CreateObjectiveGUI(activeObjectives[i], i, segments[activeObjectives[i]].ContentType); + AbsoluteSpacing = (int)GUIStyle.Font.LineHeight + }; + for (int i = 0; i < ActiveObjectives.Count; i++) + { + AddToObjectiveList(ActiveObjectives[i]); } - screenResolution = new Point(GameMain.GraphicsWidth, GameMain.GraphicsHeight); windowMode = GameSettings.CurrentConfig.Graphics.DisplayMode; prevUIScale = GUI.Scale; } - protected void StopCurrentContentSegment() + /// + /// Stops content running and adds the active segment to the objective list + /// + private void StopCurrentContentSegment() { - if (!activeContentSegment.Objective.IsNullOrEmpty()) + if (!ActiveContentSegment.ObjectiveText.IsNullOrEmpty()) { - AddNewObjective(activeContentSegmentIndex, activeContentSegment.ContentType); + ActiveObjectives.Add(ActiveContentSegment); + AddToObjectiveList(ActiveContentSegment); } - ContentRunning = false; - activeContentSegmentIndex = Index.End; + ActiveContentSegment = null; } - protected virtual void CheckActiveObjectives(Index objective, float deltaTime) + /// + /// Adds the segment to the objective list + /// + private void AddToObjectiveList(Segment segment) { - - } - - protected bool HasObjective(Index segment) - { - return activeObjectives.Contains(segment); - } - - protected void AddNewObjective(Index segment, TutorialContentType type) - { - activeObjectives.Add(segment); - CreateObjectiveGUI(segment, activeObjectives.Count - 1, type); - } - - private void CreateObjectiveGUI(Index segmentIndex, int index, TutorialContentType type) - { - var segment = segments[segmentIndex]; - LocalizedString objectiveText = TextManager.ParseInputTypes(segment.Objective); - Point replayButtonSize = new Point((int)(GUIStyle.LargeFont.MeasureString(objectiveText).X), (int)(GUIStyle.LargeFont.MeasureString(objectiveText).Y * 1.45f)); - - segment.ReplayButton = new GUIButton(new RectTransform(replayButtonSize, objectiveFrame.RectTransform, Anchor.TopLeft, Pivot.TopLeft) { AbsoluteOffset = new Point(0, (replayButtonSize.Y + (int)(20f * GUI.Scale)) * index) }, style: null); - segment.ReplayButton.OnClicked += (GUIButton btn, object userdata) => + var frameRt = new RectTransform(new Vector2(1.0f, 0.1f), objectiveGroup.RectTransform) { - if (type == TutorialContentType.Video) - { - ReplaySegmentVideo(segment); - } - else - { - ShowSegmentText(segment); - } - return true; + MinSize = new Point(0, objectiveGroup.AbsoluteSpacing) + }; + var frame = new GUIFrame(frameRt, style: null) + { + CanBeFocused = true }; - LocalizedString objectiveTitleText = TextManager.ParseInputTypes(objectiveTranslated); - int yOffset = (int)((GUIStyle.SubHeadingFont.MeasureString(objectiveTitleText).Y + 5)); - segment.LinkedTitle = new GUITextBlock(new RectTransform(new Point((int)GUIStyle.SubHeadingFont.MeasureString(objectiveTitleText).X, yOffset), segment.ReplayButton.RectTransform, Anchor.CenterLeft, Pivot.BottomLeft) /*{ AbsoluteOffset = new Point((int)(-10 * GUI.Scale), 0) }*/, - objectiveTitleText, textColor: Color.White, font: GUIStyle.SubHeadingFont, textAlignment: Alignment.CenterLeft) - { - ForceUpperCase = ForceUpperCase.Yes - }; + segment.LinkedTextBlock = new GUITextBlock( + new RectTransform(new Point(frameRt.Rect.Width - objectiveGroup.AbsoluteSpacing, 0), frame.RectTransform, anchor: Anchor.TopRight), + TextManager.ParseInputTypes(segment.ObjectiveText), + wrap: true); - segment.LinkedText = new GUITextBlock(new RectTransform(new Point((int)GUIStyle.LargeFont.MeasureString(objectiveText).X, yOffset), segment.ReplayButton.RectTransform, Anchor.CenterLeft, Pivot.TopLeft) /*{ AbsoluteOffset = new Point((int)(10 * GUI.Scale), 0) }*/, - objectiveText, textColor: new Color(4, 180, 108), font: GUIStyle.LargeFont, textAlignment: Alignment.CenterLeft); - - segment.LinkedTitle.Color = segment.LinkedTitle.HoverColor = segment.LinkedTitle.PressedColor = segment.LinkedTitle.SelectedColor = Color.Transparent; - segment.LinkedText.Color = segment.LinkedText.HoverColor = segment.LinkedText.PressedColor = segment.LinkedText.SelectedColor = Color.Transparent; - segment.ReplayButton.Color = segment.ReplayButton.HoverColor = segment.ReplayButton.PressedColor = segment.ReplayButton.SelectedColor = Color.Transparent; + var size = new Point(segment.LinkedTextBlock.Rect.Width, segment.LinkedTextBlock.Rect.Height); + segment.LinkedTextBlock.RectTransform.NonScaledSize = size; + segment.LinkedTextBlock.RectTransform.MinSize = size; + segment.LinkedTextBlock.RectTransform.MaxSize = size; + segment.LinkedTextBlock.RectTransform.IsFixedSize = true; + frame.RectTransform.Resize(new Point(frame.Rect.Width, segment.LinkedTextBlock.RectTransform.Rect.Height), resizeChildren: false); + frame.RectTransform.IsFixedSize = true; + + var indicatorRt = new RectTransform(new Point(objectiveGroup.AbsoluteSpacing), frame.RectTransform, isFixedSize: true); + segment.ObjectiveStateIndicator = new GUIImage(indicatorRt, "ObjectiveIndicatorIncomplete");; + + SetTransparent(segment.LinkedTextBlock); + + segment.ObjectiveButton = new GUIButton(new RectTransform(Vector2.One, segment.LinkedTextBlock.RectTransform, Anchor.TopLeft, Pivot.TopLeft), style: null) + { + ToolTip = objectiveTextTranslated, + OnClicked = (GUIButton btn, object userdata) => + { + if (segment.SegmentType == TutorialSegmentType.InfoBox) + { + if (segment.AutoPlayVideo == AutoPlayVideo.Yes) + { + ReplaySegmentVideo(segment); + } + else + { + ShowSegmentText(segment); + } + } + else if (segment.SegmentType == TutorialSegmentType.MessageBox) + { + segment.OnClickToDisplayMessage?.Invoke(); + } + return true; + } + }; + SetTransparent(segment.ObjectiveButton); + + static void SetTransparent(GUIComponent component) => component.Color = component.HoverColor = component.PressedColor = component.SelectedColor = Color.Transparent; } private void ReplaySegmentVideo(Segment segment) { - if (ContentRunning) return; + if (ContentRunning) { return; } Inventory.DraggingItems.Clear(); ContentRunning = true; LoadVideo(segment); - //videoPlayer.LoadContent(playableContentPath, new VideoPlayer.VideoSettings(segment.VideoContent), new VideoPlayer.TextSettings(segment.VideoContent), segment.Id, true, callback: () => ContentRunning = false); } private void ShowSegmentText(Segment segment) { - if (ContentRunning) return; + if (ContentRunning) { return; } Inventory.DraggingItems.Clear(); ContentRunning = true; - - LocalizedString tutorialText = TextManager.GetFormatted(segment.TextContent.Value.Tag, segment.Args); - - Action videoAction = null; - - if (segment.ContentType != TutorialContentType.TextOnly) - { - videoAction = () => LoadVideo(segment); - } - - infoBox = CreateInfoFrame(TextManager.Get(segment.Id), tutorialText, - segment.TextContent.Value.Width, - segment.TextContent.Value.Height, - segment.TextContent.Value.Anchor, true, () => ContentRunning = false, videoAction); - } - - protected void RemoveCompletedObjective(Index segmentIndex) - { - if (!HasObjective(segmentIndex)) return; - var segment = segments[segmentIndex]; - segment.IsTriggered = true; - segment.ReplayButton.OnClicked = null; - - int checkMarkHeight = (int)(segment.ReplayButton.Rect.Height * 1.2f); - int checkMarkWidth = (int)(checkMarkHeight * 0.93f); - - Color color = new Color(4, 180, 108); - - int objectiveTextWidth = segment.LinkedText.Rect.Width; - int objectiveTitleWidth = segment.LinkedTitle.Rect.Width; - - RectTransform rectTA; - if (objectiveTextWidth > objectiveTitleWidth) - { - rectTA = new RectTransform(new Point(checkMarkWidth, checkMarkHeight), segment.ReplayButton.RectTransform, Anchor.BottomRight, Pivot.BottomRight); - rectTA.AbsoluteOffset = new Point(-rectTA.Rect.Width - (int)(25 * GUI.Scale), 0); - } - else - { - rectTA = new RectTransform(new Point(checkMarkWidth, checkMarkHeight), segment.ReplayButton.RectTransform, Anchor.BottomRight, Pivot.BottomRight); - rectTA.AbsoluteOffset = new Point(-rectTA.Rect.Width - (int)(25 * GUI.Scale) - (objectiveTitleWidth - objectiveTextWidth), 0); - } - - GUIImage checkmark = new GUIImage(rectTA, "CheckMark"); - checkmark.Color = checkmark.SelectedColor = checkmark.HoverColor = checkmark.PressedColor = color; - - RectTransform rectTB = new RectTransform(new Vector2(1.0f, .8f), segment.LinkedText.RectTransform, Anchor.Center, Pivot.Center); - GUIImage stroke = new GUIImage(rectTB, "Stroke"); - stroke.Color = stroke.SelectedColor = stroke.HoverColor = stroke.PressedColor = color; - - CoroutineManager.StartCoroutine(WaitForObjectiveEnd(segmentIndex)); - } - - private IEnumerable WaitForObjectiveEnd(Index objectiveIndex) - { - var objective = segments[objectiveIndex]; - yield return new WaitForSeconds(2.0f); - objectiveFrame.RemoveChild(objective.ReplayButton); - activeObjectives.Remove(objectiveIndex); - - for (int i = 0; i < activeObjectives.Count; i++) - { - var activeObjective = segments[activeObjectives[i]]; - activeObjective.ReplayButton.RectTransform.AbsoluteOffset = new Point(0, (activeObjective.ReplayButton.Rect.Height + 20) * i); - } + ActiveContentSegment = segment; + infoBox = CreateInfoFrame( + TextManager.Get(segment.Id), + TextManager.Get(segment.TextContent.Value.Tag), + segment.TextContent.Value.Width, + segment.TextContent.Value.Height, + segment.TextContent.Value.Anchor, + hasButton: true, + onInfoBoxClosed: () => ContentRunning = false, + onVideoButtonClicked: () => LoadVideo(segment)); } #endregion #region InfoFrame - protected bool CloseInfoFrame(GUIButton button, object userData) + + private void CloseInfoFrame() => CloseInfoFrame(null, null); + + private bool CloseInfoFrame(GUIButton button, object userData) { infoBox = null; infoBoxClosedCallback?.Invoke(); return true; } - protected GUIComponent CreateInfoFrame(LocalizedString title, LocalizedString text, int width = 300, int height = 80, Anchor anchor = Anchor.TopRight, bool hasButton = false, Action callback = null, Action showVideo = null) + /// + // Creates and displays a tutorial info box + /// + private GUIComponent CreateInfoFrame(LocalizedString title, LocalizedString text, int width = 300, int height = 80, Anchor anchor = Anchor.TopRight, bool hasButton = false, Action onInfoBoxClosed = null, Action onVideoButtonClicked = null) { - if (hasButton) height += 60; + if (hasButton) + { + height += 60; + } width = (int)(width * GUI.Scale); height = (int)(height * GUI.Scale); @@ -467,7 +719,7 @@ namespace Barotrauma.Tutorials GUITextBlock textBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), infoContent.RectTransform), text, wrap: true); textBlock.RectTransform.IsFixedSize = true; - infoBoxClosedCallback = callback; + infoBoxClosedCallback = onInfoBoxClosed; if (hasButton) { @@ -477,7 +729,7 @@ namespace Barotrauma.Tutorials }; buttonContainer.RectTransform.IsFixedSize = true; - if (showVideo != null) + if (onVideoButtonClicked != null) { buttonContainer.Stretch = true; var videoButton = new GUIButton(new RectTransform(new Vector2(0.4f, 1.0f), buttonContainer.RectTransform), @@ -485,7 +737,7 @@ namespace Barotrauma.Tutorials { OnClicked = (GUIButton button, object obj) => { - showVideo(); + onVideoButtonClicked(); return true; } }; @@ -509,57 +761,39 @@ namespace Barotrauma.Tutorials return background; } + #endregion #region Video - protected void LoadVideo(Segment segment) + + private void LoadVideo(Segment segment) { - if (videoPlayer == null) videoPlayer = new VideoPlayer(); - if (segment.ContentType != TutorialContentType.ManualVideo) + videoPlayer ??= new VideoPlayer(); + if (segment.AutoPlayVideo == AutoPlayVideo.Yes) { videoPlayer.LoadContent( - PlayableContentPath, - new VideoPlayer.VideoSettings(segment.VideoContent.Value.File), - new VideoPlayer.TextSettings(segment.VideoContent.Value.TextTag, segment.VideoContent.Value.Width), - segment.Id, true, segment.Objective, StopCurrentContentSegment); + contentPath: PlayableContentPath, + videoSettings: new VideoPlayer.VideoSettings(segment.VideoContent.Value.File), + textSettings: new VideoPlayer.TextSettings(segment.VideoContent.Value.TextTag, segment.VideoContent.Value.Width), + contentId: segment.Id, + startPlayback: true, + objective: segment.ObjectiveText, + onStop: StopCurrentContentSegment); } else { - videoPlayer.LoadContent(PlayableContentPath, new VideoPlayer.VideoSettings(segment.VideoContent.Value.File), null, segment.Id, true, string.Empty, null); - } - } - #endregion - - #region Highlights - protected void HighlightInventorySlot(Inventory inventory, Identifier identifier, Color color, float fadeInDuration, float fadeOutDuration, float scaleUpAmount) - { - if (inventory.visualSlots == null) { return; } - for (int i = 0; i < inventory.Capacity; i++) - { - if (inventory.GetItemAt(i)?.Prefab.Identifier == identifier) - { - HighlightInventorySlot(inventory, i, color, fadeInDuration, fadeOutDuration, scaleUpAmount); - } + videoPlayer.LoadContent( + contentPath: PlayableContentPath, + videoSettings: new VideoPlayer.VideoSettings(segment.VideoContent.Value.File), + textSettings: null, + contentId: segment.Id, + startPlayback: true, + objective: string.Empty); } } - protected void HighlightInventorySlotWithTag(Inventory inventory, Identifier tag, Color color, float fadeInDuration, float fadeOutDuration, float scaleUpAmount) - { - if (inventory.visualSlots == null) { return; } - for (int i = 0; i < inventory.Capacity; i++) - { - if (inventory.GetItemAt(i)?.HasTag(tag) ?? false) - { - HighlightInventorySlot(inventory, i, color, fadeInDuration, fadeOutDuration, scaleUpAmount); - } - } - } + private void LoadActiveContentVideo() => LoadVideo(ActiveContentSegment); - protected void HighlightInventorySlot(Inventory inventory, int index, Color color, float fadeInDuration, float fadeOutDuration, float scaleUpAmount) - { - if (inventory.visualSlots == null || index < 0 || inventory.visualSlots[index].HighlightTimer > 0) { return; } - inventory.visualSlots[index].ShowBorderHighlight(color, fadeInDuration, fadeOutDuration, scaleUpAmount); - } #endregion } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/TutorialMode.cs b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/TutorialMode.cs index 2b904f82f..d155a1c23 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/TutorialMode.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/TutorialMode.cs @@ -6,10 +6,7 @@ namespace Barotrauma { public Tutorial Tutorial; - public TutorialMode(GameModePreset preset) - : base(preset) - { - } + public TutorialMode(GameModePreset preset) : base(preset) { } public override void Start() { @@ -31,7 +28,7 @@ namespace Barotrauma public override void Update(float deltaTime) { base.Update(deltaTime); - Tutorial.Update(deltaTime); + Tutorial.Update(); } } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/GameSession/MedicalClinic.cs b/Barotrauma/BarotraumaClient/ClientSource/GameSession/MedicalClinic.cs index 0811b26ce..c06efe8d5 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GameSession/MedicalClinic.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GameSession/MedicalClinic.cs @@ -354,14 +354,14 @@ namespace Barotrauma private static IWriteMessage StartSending() { IWriteMessage writeMessage = new WriteOnlyMessage(); - writeMessage.Write((byte)ClientPacketHeader.MEDICAL); + writeMessage.WriteByte((byte)ClientPacketHeader.MEDICAL); return writeMessage; } private static void ClientSend(INetSerializableStruct? netStruct, NetworkHeader header, DeliveryMethod deliveryMethod) { IWriteMessage msg = StartSending(); - msg.Write((byte)header); + msg.WriteByte((byte)header); netStruct?.Write(msg); GameMain.Client.ClientPeer?.Send(msg, deliveryMethod); } diff --git a/Barotrauma/BarotraumaClient/ClientSource/GameSession/ReadyCheck.cs b/Barotrauma/BarotraumaClient/ClientSource/GameSession/ReadyCheck.cs index 1d1b488d3..eed8abac4 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GameSession/ReadyCheck.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GameSession/ReadyCheck.cs @@ -139,7 +139,7 @@ namespace Barotrauma public static void ClientRead(IReadMessage inc) { - ReadyCheckState state = (ReadyCheckState) inc.ReadByte(); + ReadyCheckState state = (ReadyCheckState)inc.ReadByte(); CrewManager? crewManager = GameMain.GameSession?.CrewManager; var otherClients = GameMain.Client.ConnectedClients; if (crewManager == null || otherClients == null) @@ -196,7 +196,7 @@ namespace Barotrauma } break; case ReadyCheckState.Update: - ReadyStatus newState = (ReadyStatus) inc.ReadByte(); + ReadyStatus newState = (ReadyStatus)inc.ReadByte(); byte targetId = inc.ReadByte(); if (crewManager.ActiveReadyCheck != null) { @@ -208,7 +208,7 @@ namespace Barotrauma for (int i = 0; i < count; i++) { byte id = inc.ReadByte(); - ReadyStatus status = (ReadyStatus) inc.ReadByte(); + ReadyStatus status = (ReadyStatus)inc.ReadByte(); crewManager.ActiveReadyCheck?.UpdateState(id, status); } @@ -269,9 +269,9 @@ namespace Barotrauma private static void SendState(ReadyStatus status) { IWriteMessage msg = new WriteOnlyMessage(); - msg.Write((byte) ClientPacketHeader.READY_CHECK); - msg.Write((byte) ReadyCheckState.Update); - msg.Write((byte) status); + msg.WriteByte((byte)ClientPacketHeader.READY_CHECK); + msg.WriteByte((byte)ReadyCheckState.Update); + msg.WriteByte((byte)status); GameMain.Client?.ClientPeer?.Send(msg, DeliveryMethod.Reliable); } @@ -283,8 +283,8 @@ namespace Barotrauma ReadyCheckCooldown = DateTime.Now.AddMinutes(1); #endif IWriteMessage msg = new WriteOnlyMessage(); - msg.Write((byte) ClientPacketHeader.READY_CHECK); - msg.Write((byte) ReadyCheckState.Start); + msg.WriteByte((byte)ClientPacketHeader.READY_CHECK); + msg.WriteByte((byte)ReadyCheckState.Start); GameMain.Client?.ClientPeer?.Send(msg, DeliveryMethod.Reliable); return; } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Growable.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Growable.cs index 8428d53ff..5b8af4a6a 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Growable.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Growable.cs @@ -166,10 +166,10 @@ namespace Barotrauma.Items.Components List tiles = new List(); for (int i = 0; i < vineCount; i++) { - VineTileType vineType = (VineTileType) msg.ReadRangedInteger(0b0000, 0b1111); + VineTileType vineType = (VineTileType)msg.ReadRangedInteger(0b0000, 0b1111); int flowerConfig = msg.ReadRangedInteger(0, 0xFFF); int leafConfig = msg.ReadRangedInteger(0, 0xFFF); - sbyte posX = (sbyte) msg.ReadByte(), posY = (sbyte) msg.ReadByte(); + sbyte posX = (sbyte)msg.ReadByte(), posY = (sbyte)msg.ReadByte(); Vector2 pos = new Vector2(posX * VineTile.Size, posY * VineTile.Size); tiles.Add(new VineTile(this, pos, vineType, FoliageConfig.Deserialize(flowerConfig), FoliageConfig.Deserialize(leafConfig))); diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Holdable/Holdable.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Holdable/Holdable.cs index 77da549e2..5380f8940 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Holdable/Holdable.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Holdable/Holdable.cs @@ -69,8 +69,8 @@ namespace Barotrauma.Items.Components var eventData = ExtractEventData(extraData); Vector2 attachPos = eventData.AttachPos; - msg.Write(attachPos.X); - msg.Write(attachPos.Y); + msg.WriteSingle(attachPos.X); + msg.WriteSingle(attachPos.Y); } public override void ClientEventRead(IReadMessage msg, float sendingTime) diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/ItemComponent.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/ItemComponent.cs index ebbc45e0b..a1b1857e8 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/ItemComponent.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/ItemComponent.cs @@ -66,6 +66,8 @@ namespace Barotrauma.Items.Components public float IsActiveTimer; + public virtual bool RecreateGUIOnResolutionChange => false; + public GUILayoutSettings DefaultLayout { get; protected set; } public GUILayoutSettings AlternativeLayout { get; protected set; } @@ -574,7 +576,7 @@ namespace Barotrauma.Items.Components { GuiFrame.RectTransform.ParentChanged += OnGUIParentChanged; } - GameMain.Instance.ResolutionChanged += OnResolutionChanged; + GameMain.Instance.ResolutionChanged += OnResolutionChangedPrivate; } protected void TryCreateDragHandle() @@ -610,13 +612,17 @@ namespace Barotrauma.Items.Components return false; } } + foreach (ItemComponent ic in activeHuds) + { + //refresh slots to ensure they're rendered at the correct position + (ic as ItemContainer)?.Inventory.CreateSlots(); + } return true; }; - int buttonHeight = (int)(GUIStyle.ItemFrameMargin.Y * 0.4f); - new GUIButton(new RectTransform(new Point(buttonHeight), handle.RectTransform, Anchor.TopLeft) { AbsoluteOffset = new Point(buttonHeight / 10) }, - style: "GUIButtonRefresh") + new GUIButton(new RectTransform(new Point(buttonHeight), handle.RectTransform, Anchor.TopLeft) { AbsoluteOffset = new Point(buttonHeight / 4) }, + style: "GUIButtonSettings") { OnClicked = (btn, userdata) => { diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/ItemContainer.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/ItemContainer.cs index 5fe21e897..a759f9ac7 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/ItemContainer.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/ItemContainer.cs @@ -45,6 +45,8 @@ namespace Barotrauma.Items.Components private set; } + public override bool RecreateGUIOnResolutionChange => true; + /// /// Depth at which the contained sprites are drawn. If not set, the original depth of the item sprites is used. /// diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/LightComponent.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/LightComponent.cs index 5bfc4e192..332f924cd 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/LightComponent.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/LightComponent.cs @@ -90,8 +90,8 @@ namespace Barotrauma.Items.Components { Light.LightSpriteEffect = Light.LightSpriteEffect == SpriteEffects.None ? SpriteEffects.FlipHorizontally : SpriteEffects.None; - SetLightSourceTransformProjSpecific(); } + SetLightSourceTransformProjSpecific(); } partial void OnStateChanged() diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Deconstructor.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Deconstructor.cs index 1c4dfe80b..5a31e20c3 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Deconstructor.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Deconstructor.cs @@ -5,6 +5,7 @@ using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using System.Linq; using System.Xml.Linq; +using Barotrauma.Extensions; namespace Barotrauma.Items.Components { @@ -33,14 +34,18 @@ namespace Barotrauma.Items.Components [Serialize(0.0f, IsPropertySaveable.Yes)] public float InfoAreaWidth { get; set; } - partial void InitProjSpecific(XElement element) + [Serialize(true, IsPropertySaveable.Yes)] + public bool ShowOutput { get; set; } + + partial void InitProjSpecific(XElement _) { CreateGUI(); } + public override bool RecreateGUIOnResolutionChange => true; + protected override void OnResolutionChanged() { - base.OnResolutionChanged(); OnItemLoadedProjSpecific(); } @@ -122,11 +127,14 @@ namespace Barotrauma.Items.Components // === OUTPUT SLOTS === // outputInventoryHolder = new GUIFrame(new RectTransform(new Vector2(1f - InfoAreaWidth, 1f), outputArea.RectTransform, Anchor.CenterLeft), style: null); - GUILayoutGroup outputDisplayLayout = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.25f), paddedFrame.RectTransform), childAnchor: Anchor.TopCenter); - GUILayoutGroup outDisplayTopGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.2f), outputDisplayLayout.RectTransform), isHorizontal: true); - GUITextBlock outDisplayBlock = new GUITextBlock(new RectTransform(Vector2.One, outDisplayTopGroup.RectTransform), TextManager.Get("deconstructor.output"), font: GUIStyle.SubHeadingFont) { Padding = Vector4.Zero }; - GUILayoutGroup outDisplayBottomGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.975f, 0.8f), outputDisplayLayout.RectTransform), isHorizontal: true); - outputDisplayListBox = new GUIListBox(new RectTransform(new Vector2(1f, 1f), outDisplayBottomGroup.RectTransform), isHorizontal: true, style: null); + if (ShowOutput) + { + GUILayoutGroup outputDisplayLayout = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.25f), paddedFrame.RectTransform), childAnchor: Anchor.TopCenter); + GUILayoutGroup outDisplayTopGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.2f), outputDisplayLayout.RectTransform), isHorizontal: true); + GUITextBlock outDisplayBlock = new GUITextBlock(new RectTransform(Vector2.One, outDisplayTopGroup.RectTransform), TextManager.Get("deconstructor.output"), font: GUIStyle.SubHeadingFont) { Padding = Vector4.Zero }; + GUILayoutGroup outDisplayBottomGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.975f, 0.8f), outputDisplayLayout.RectTransform), isHorizontal: true); + outputDisplayListBox = new GUIListBox(new RectTransform(new Vector2(1f, 1f), outDisplayBottomGroup.RectTransform), isHorizontal: true, style: null); + } if (InfoAreaWidth >= 0.0f) { @@ -255,16 +263,17 @@ namespace Barotrauma.Items.Components foreach (DeconstructItem deconstructItem in it.Prefab.DeconstructItems) { + if (!deconstructItem.IsValidDeconstructor(item)) { continue; } RegisterItem(deconstructItem.ItemIdentifier, deconstructItem.Amount); } - if (it.OwnInventory is { } inventory) + /*if (it.OwnInventory is { } inventory) { foreach (Item inventoryItems in inventory.AllItems) { RegisterItem(inventoryItems.Prefab.Identifier); } - } + }*/ void RegisterItem(Identifier identifier, int amount = 1) { @@ -383,6 +392,8 @@ namespace Barotrauma.Items.Components inputContainer.Inventory.RectTransform = inputInventoryHolder.RectTransform; outputContainer.AllowUIOverlap = true; outputContainer.Inventory.RectTransform = outputInventoryHolder.RectTransform; + + inputContainer.Inventory.Locked = IsActive; } private void DrawOverLay(SpriteBatch spriteBatch, GUICustomComponent overlayComponent) @@ -446,7 +457,7 @@ namespace Barotrauma.Items.Components public void ClientEventWrite(IWriteMessage msg, NetEntityEvent.IData extraData = null) { - msg.Write(pendingState); + msg.WriteBoolean(pendingState); } public void ClientEventRead(IReadMessage msg, float sendingTime) diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Fabricator.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Fabricator.cs index 90849cd19..0f81a432a 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Fabricator.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Fabricator.cs @@ -51,11 +51,13 @@ namespace Barotrauma.Items.Components [Serialize("vendingmachine.outofstock", IsPropertySaveable.Yes)] public string FabricationLimitReachedText { get; set; } + public override bool RecreateGUIOnResolutionChange => true; + protected override void OnResolutionChanged() { if (GuiFrame != null) { - OnItemLoadedProjSpecific(); + InitInventoryUIs(); } } @@ -232,6 +234,17 @@ namespace Barotrauma.Items.Components } } + private void InitInventoryUIs() + { + if (inputInventoryHolder != null) + { + inputContainer.AllowUIOverlap = true; + inputContainer.Inventory.RectTransform = inputInventoryHolder.RectTransform; + } + outputContainer.AllowUIOverlap = true; + outputContainer.Inventory.RectTransform = outputInventoryHolder.RectTransform; + } + private LocalizedString GetRecipeNameAndAmount(FabricationRecipe fabricationRecipe) { if (fabricationRecipe == null) { return ""; } @@ -249,13 +262,7 @@ namespace Barotrauma.Items.Components partial void OnItemLoadedProjSpecific() { CreateGUI(); - if (inputInventoryHolder != null) - { - inputContainer.AllowUIOverlap = true; - inputContainer.Inventory.RectTransform = inputInventoryHolder.RectTransform; - } - outputContainer.AllowUIOverlap = true; - outputContainer.Inventory.RectTransform = outputInventoryHolder.RectTransform; + InitInventoryUIs(); } partial void SelectProjSpecific(Character character) @@ -328,76 +335,112 @@ namespace Barotrauma.Items.Components } } + private readonly Dictionary missingIngredientCounts = new Dictionary(); + private float ingredientHighlightTimer; + private void DrawInputOverLay(SpriteBatch spriteBatch, GUICustomComponent overlayComponent) { overlayComponent.RectTransform.SetAsLastChild(); + missingIngredientCounts.Clear(); + FabricationRecipe targetItem = fabricatedItem ?? selectedItem; if (targetItem != null) { - int slotIndex = 0; - - var missingItems = new List(); - foreach (FabricationRecipe.RequiredItem requiredItem in targetItem.RequiredItems) { - for (int i = 0; i < requiredItem.Amount; i++) + if (missingIngredientCounts.ContainsKey(requiredItem)) { - missingItems.Add(requiredItem); + missingIngredientCounts[requiredItem] += requiredItem.Amount; + } + else + { + missingIngredientCounts[requiredItem] = requiredItem.Amount; } } foreach (Item item in inputContainer.Inventory.AllItems) { - missingItems.Remove(missingItems.FirstOrDefault(mi => mi.ItemPrefabs.Contains(item.Prefab))); - } - var missingCounts = missingItems.GroupBy(missingItem => missingItem).ToDictionary(x => x.Key, x => x.Count()); - missingItems = missingItems.Distinct().ToList(); + var missingIngredient = missingIngredientCounts.Keys.FirstOrDefault(mi => mi.MatchesItem(item)); + if (missingIngredient == null) { continue; } - foreach (FabricationRecipe.RequiredItem requiredItem in missingItems) + if (missingIngredientCounts[missingIngredient] == 1) + { + missingIngredientCounts.Remove(missingIngredient); + } + else + { + missingIngredientCounts[missingIngredient]--; + } + } + + if (ingredientHighlightTimer <= 0.0f) { + //highlight inventory slots that contain suitable ingredients in linked inventories + foreach (var inventory in linkedInventories) + { + if (inventory.visualSlots == null) { continue; } + for (int i = 0; i < inventory.Capacity; i++) + { + if (inventory.visualSlots[i].HighlightTimer > 0.0f) { continue; } + var availableItem = inventory.GetItemAt(i); + if (availableItem == null) { continue; } + + if (missingIngredientCounts.Keys.Any(it => it.MatchesItem(availableItem))) + { + inventory.visualSlots[i].ShowBorderHighlight(GUIStyle.Green, 0.5f, 0.5f, 0.2f); + continue; + } + if (availableItem.OwnInventory != null) + { + for (int j = 0; j < availableItem.OwnInventory.Capacity; j++) + { + var availableContainedItem = availableItem.OwnInventory.GetItemAt(i); + if (availableContainedItem == null) { continue; } + if (missingIngredientCounts.Keys.Any(it => it.MatchesItem(availableContainedItem))) + { + inventory.visualSlots[i].ShowBorderHighlight(GUIStyle.Green, 0.5f, 0.5f, 0.2f); + break; + } + } + } + } + } + ingredientHighlightTimer = 1.0f; + } + + int slotIndex = 0; + foreach (var kvp in missingIngredientCounts) + { + var requiredItem = kvp.Key; + int missingCount = kvp.Value; + while (slotIndex < inputContainer.Capacity && inputContainer.Inventory.GetItemAt(slotIndex) != null) { slotIndex++; } - requiredItem.ItemPrefabs - .Where(requiredPrefab => availableIngredients.ContainsKey(requiredPrefab.Identifier)) - .ForEach(requiredPrefab => { - var availableItems = availableIngredients[requiredPrefab.Identifier]; - foreach (Item it in availableItems) - { - if (it.ParentInventory == inputContainer.Inventory) { continue; } - var rootInventoryOwner = it.GetRootInventoryOwner(); - Inventory rootInventory = (rootInventoryOwner as Item)?.OwnInventory as Inventory ?? (rootInventoryOwner as Character)?.Inventory; - if (rootInventory?.visualSlots == null) { continue; } - int availableSlotIndex = rootInventory.FindIndex((it.Container != rootInventoryOwner ? it.Container : it) ?? it); - if (availableSlotIndex < 0) { continue; } - if (rootInventory.visualSlots[availableSlotIndex].HighlightTimer <= 0.0f) - { - rootInventory.visualSlots[availableSlotIndex].ShowBorderHighlight(GUIStyle.Green, 0.5f, 0.5f, 0.2f); - if (slotIndex < inputContainer.Capacity) - { - inputContainer.Inventory.visualSlots[slotIndex].ShowBorderHighlight(GUIStyle.Green, 0.5f, 0.5f, 0.2f); - } - } - } - }); - if (slotIndex >= inputContainer.Capacity) { break; } - var itemIcon = requiredItem.ItemPrefabs.First().InventoryIcon ?? requiredItem.ItemPrefabs.First().Sprite; + if (slotIndex < inputContainer.Capacity && + inputContainer.Inventory.visualSlots[slotIndex].HighlightTimer <= 0.0f && + availableIngredients.Any(i => i.Value.Any() && requiredItem.MatchesItem(i.Value.First()))) + { + inputContainer.Inventory.visualSlots[slotIndex].ShowBorderHighlight(GUIStyle.Green, 0.5f, 0.5f, 0.2f); + } + + var requiredItemPrefab = requiredItem.FirstMatchingPrefab; + var itemIcon = requiredItemPrefab.InventoryIcon ?? requiredItemPrefab.Sprite; Rectangle slotRect = inputContainer.Inventory.visualSlots[slotIndex].Rect; itemIcon.Draw( spriteBatch, slotRect.Center.ToVector2(), - color: requiredItem.ItemPrefabs.First().InventoryIconColor * 0.3f, + color: requiredItemPrefab.InventoryIconColor * 0.3f, scale: Math.Min(slotRect.Width / itemIcon.size.X, slotRect.Height / itemIcon.size.Y)); - - - if (missingCounts[requiredItem] > 1) + + if (missingCount > 1) { Vector2 stackCountPos = new Vector2(slotRect.Right, slotRect.Bottom); - string stackCountText = "x" + missingCounts[requiredItem]; + string stackCountText = "x" + missingCount; stackCountPos -= GUIStyle.SmallFont.MeasureString(stackCountText) + new Vector2(4, 2); GUIStyle.SmallFont.DrawString(spriteBatch, stackCountText, stackCountPos + Vector2.One, Color.Black); GUIStyle.SmallFont.DrawString(spriteBatch, stackCountText, stackCountPos, Color.White); @@ -446,9 +489,9 @@ namespace Barotrauma.Items.Components { toolTipText = TextManager.GetWithVariable("displayname.emptyitem", "[itemname]", toolTipText); } - if (!requiredItem.ItemPrefabs.First().Description.IsNullOrEmpty()) + if (!requiredItemPrefab.Description.IsNullOrEmpty()) { - toolTipText += '\n' + requiredItem.ItemPrefabs.First().Description; + toolTipText += '\n' + requiredItemPrefab.Description; } tooltip = new ToolTip { TargetElement = slotRect, Tooltip = toolTipText }; } @@ -715,6 +758,8 @@ namespace Barotrauma.Items.Components activateButton.Enabled = false; inSufficientPowerWarning.Visible = IsActive && !hasPower; + ingredientHighlightTimer -= deltaTime; + if (!IsActive) { //only check ingredients if the fabricator isn't active (if it is, this is done in Update) @@ -763,7 +808,7 @@ namespace Barotrauma.Items.Components public void ClientEventWrite(IWriteMessage msg, NetEntityEvent.IData extraData = null) { uint recipeHash = pendingFabricatedItem?.RecipeHash ?? 0; - msg.Write(recipeHash); + msg.WriteUInt32(recipeHash); } public void ClientEventRead(IReadMessage msg, float sendingTime) diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/MiniMap.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/MiniMap.cs index 5a917c369..fce57ab20 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/MiniMap.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/MiniMap.cs @@ -510,7 +510,7 @@ namespace Barotrauma.Items.Components Vector2 origin = weaponSprite.Origin; float scale = parentWidth / Math.Max(weaponSprite.size.X, weaponSprite.size.Y); Color color = !hasPower ? NoPowerColor : turret.ActiveUser is null ? Color.DimGray : GUIStyle.Green; - weaponSprite.Draw(batch, center, color, origin, rotation, scale, it.SpriteEffects); + weaponSprite.Draw(batch, center, color, origin, rotation, scale, SpriteEffects.None); } }); diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Pump.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Pump.cs index f3bfe988b..4ca36908c 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Pump.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Pump.cs @@ -219,7 +219,7 @@ namespace Barotrauma.Items.Components { //flowpercentage can only be adjusted at 10% intervals -> no need for more accuracy than this msg.WriteRangedInteger((int)(flowPercentage / 10.0f), -10, 10); - msg.Write(IsActive); + msg.WriteBoolean(IsActive); } public void ClientEventRead(IReadMessage msg, float sendingTime) diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Reactor.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Reactor.cs index 5e973af30..30a3a35ba 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Reactor.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Reactor.cs @@ -34,9 +34,8 @@ namespace Barotrauma.Items.Components private Color optimalRangeColor = new Color(74,238,104,255); private Color offRangeColor = Color.Orange; private Color warningColor = Color.Red; - private Color coldColor = Color.LightBlue; - private Color warmColor = Color.Orange; - private Color hotColor = Color.Red; + + private readonly Color[] temperatureColors = new Color[] { Color.Blue, Color.LightBlue, Color.Orange, Color.Red }; private Color outputColor = Color.Goldenrod; private Color loadColor = Color.LightSteelBlue; @@ -66,10 +65,11 @@ namespace Barotrauma.Items.Components "ReactorWarningOverheating", "ReactorWarningHighOutput", "ReactorWarningFuelOut", "ReactorWarningSCRAM" }; + public override bool RecreateGUIOnResolutionChange => true; + partial void InitProjSpecific(ContentXElement element) { - // TODO: need to recreate the gui when the resolution changes - + CreateGUI(); fissionRateMeter = new Sprite(element.GetChildElement("fissionratemeter")?.GetChildElement("sprite")); turbineOutputMeter = new Sprite(element.GetChildElement("turbineoutputmeter")?.GetChildElement("sprite")); meterPointer = new Sprite(element.GetChildElement("meterpointer")?.GetChildElement("sprite")); @@ -81,7 +81,6 @@ namespace Barotrauma.Items.Components foreach (var subElement in element.Elements()) { - string textureDir = GetTextureDirectory(subElement); switch (subElement.Name.ToString().ToLowerInvariant()) { case "temperatureboostsoundup": @@ -92,11 +91,16 @@ namespace Barotrauma.Items.Components break; } } + } + + protected override void CreateGUI() + { + warningButtons.Clear(); paddedFrame = new GUILayoutGroup(new RectTransform( - GuiFrame.Rect.Size - GUIStyle.ItemFrameMargin, GuiFrame.RectTransform, Anchor.Center) - { AbsoluteOffset = GUIStyle.ItemFrameOffset }, - isHorizontal: true) + GuiFrame.Rect.Size - GUIStyle.ItemFrameMargin, GuiFrame.RectTransform, Anchor.Center) + { AbsoluteOffset = GUIStyle.ItemFrameOffset }, + isHorizontal: true) { RelativeSpacing = 0.012f, Stretch = true @@ -438,6 +442,19 @@ namespace Barotrauma.Items.Components }; LocalizedString outputStr = TextManager.Get("ReactorOutput"); outputText.TextGetter += () => $"{outputStr.Replace("[kw]", ((int)-currPowerConsumption).ToString())} {kW}"; + + InitInventoryUI(); + } + + private void InitInventoryUI() + { + var itemContainer = item.GetComponent(); + if (itemContainer != null) + { + itemContainer.UILabel = ""; + itemContainer.AllowUIOverlap = true; + itemContainer.Inventory.RectTransform = inventoryContainer.RectTransform; + } } public override void OnItemLoaded() @@ -445,23 +462,10 @@ namespace Barotrauma.Items.Components base.OnItemLoaded(); TurbineOutputScrollBar.BarScroll = TargetTurbineOutput / 100.0f; FissionRateScrollBar.BarScroll = TargetFissionRate / 100.0f; - var itemContainer = item.GetComponent(); - if (itemContainer != null) - { - itemContainer.UILabel = ""; - itemContainer.AllowUIOverlap = true; - itemContainer.Inventory.RectTransform = inventoryContainer.RectTransform; - /*var inventoryLabel = inventoryContainer.Parent?.GetChild(); - if (inventoryLabel != null) - { - inventoryLabel.RectTransform.MinSize = new Point(100, 0); - inventoryLabel.Text = itemContainer.GetUILabel(); - inventoryLabel.CalculateHeightFromText(); - (inventoryLabel.Parent as GUILayoutGroup).Recalculate(); - }*/ - } + InitInventoryUI(); } + private void DrawTempMeter(SpriteBatch spriteBatch, GUICustomComponent container) { Vector2 meterPos = new Vector2(container.Rect.X, container.Rect.Y); @@ -474,7 +478,7 @@ namespace Barotrauma.Items.Components while (meterBarPos.Y > container.Rect.Bottom + (int)(5 * GUI.yScale) - container.Rect.Height * tempFill) { float tempRatio = 1.0f - ((meterBarPos.Y - container.Rect.Y) / container.Rect.Height); - Color color = ToolBox.GradientLerp(tempRatio, coldColor, optimalRangeColor, warmColor, hotColor); + Color color = ToolBox.GradientLerp(tempRatio, temperatureColors); tempMeterBar.Draw(spriteBatch, meterBarPos, color: color, scale: meterBarScale); int spacing = 2; meterBarPos.Y -= tempMeterBar.size.Y * meterBarScale + spacing; @@ -691,7 +695,6 @@ namespace Barotrauma.Items.Components float normalizedValue = (value - range.X) / (range.Y - range.X); float valueRad = MathHelper.Lerp(sectorRad.X, sectorRad.Y, normalizedValue); - Vector2 offset = new Vector2(0, 40) * scale; meterPointer.Draw(spriteBatch, pointerPos, valueRad, scale); } @@ -769,8 +772,8 @@ namespace Barotrauma.Items.Components public void ClientEventWrite(IWriteMessage msg, NetEntityEvent.IData extraData = null) { - msg.Write(autoTemp); - msg.Write(PowerOn); + msg.WriteBoolean(autoTemp); + msg.WriteBoolean(PowerOn); msg.WriteRangedSingle(TargetFissionRate, 0.0f, 100.0f, 8); msg.WriteRangedSingle(TargetTurbineOutput, 0.0f, 100.0f, 8); diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Sonar.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Sonar.cs index ca210f1fb..2deca5a59 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Sonar.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Sonar.cs @@ -140,8 +140,7 @@ namespace Barotrauma.Items.Components set; } - private bool AllowUsingMineralScanner => - HasMineralScanner && !isConnectedToSteering; + public override bool RecreateGUIOnResolutionChange => true; partial void InitProjSpecific(ContentXElement element) { @@ -195,7 +194,6 @@ namespace Barotrauma.Items.Components protected override void OnResolutionChanged() { - base.OnResolutionChanged(); UpdateGUIElements(); } @@ -302,7 +300,7 @@ namespace Barotrauma.Items.Components TextManager.Get("SonarDirectionalPing"), GUIStyle.TextColorNormal, GUIStyle.SubHeadingFont, Alignment.CenterLeft); textBlocksToScaleAndNormalize.Add(directionalModeSwitchText); - if (AllowUsingMineralScanner) + if (HasMineralScanner) { AddMineralScannerSwitchToGUI(); } @@ -373,7 +371,7 @@ namespace Barotrauma.Items.Components { base.OnItemLoaded(); zoomSlider.BarScroll = MathUtils.InverseLerp(MinZoom, MaxZoom, zoom); - if (AllowUsingMineralScanner && mineralScannerSwitch == null) + if (HasMineralScanner && mineralScannerSwitch == null) { AddMineralScannerSwitchToGUI(); GUITextBlock.AutoScaleAndNormalize(textBlocksToScaleAndNormalize); @@ -417,12 +415,32 @@ namespace Barotrauma.Items.Components unsentChanges = true; correctionTimer = CorrectionDelay; } + return true; } }; var mineralScannerSwitchText = new GUITextBlock(new RectTransform(new Vector2(0.7f, 1), mineralScannerFrame.RectTransform, Anchor.CenterRight), TextManager.Get("SonarMineralScanner"), GUIStyle.TextColorNormal, GUIStyle.SubHeadingFont, Alignment.CenterLeft); textBlocksToScaleAndNormalize.Add(mineralScannerSwitchText); + + PreventMineralScannerOverlap(); + } + + private void PreventMineralScannerOverlap() + { + if (item.GetComponent() is { } steering && controlContainer is { } container) + { + int containerBottom = container.Rect.Y + container.Rect.Height, + steeringTop = steering.ControlContainer.Rect.Top; + + int amountRaised = 0; + + while (GetContainerBottom() > steeringTop) { amountRaised++; } + + container.RectTransform.AbsoluteOffset = new Point(0, -amountRaised); + + int GetContainerBottom() => containerBottom - amountRaised; + } } public override void UpdateHUD(Character character, float deltaTime, Camera cam) @@ -502,7 +520,7 @@ namespace Barotrauma.Items.Components Vector2.DistanceSquared(sonarView.Rect.Center.ToVector2(), PlayerInput.MousePosition) < (sonarView.Rect.Width / 2 * sonarView.Rect.Width / 2); - if (AllowUsingMineralScanner && Level.Loaded != null && !Level.Loaded.Generating) + if (HasMineralScanner && Level.Loaded != null && !Level.Loaded.Generating) { if (MineralClusters == null) { @@ -985,7 +1003,7 @@ namespace Barotrauma.Items.Components missionIndex++; } - if (AllowUsingMineralScanner && useMineralScanner && CurrentMode == Mode.Active && MineralClusters != null && + if (HasMineralScanner && useMineralScanner && CurrentMode == Mode.Active && MineralClusters != null && (item.CurrentHull == null || !DetectSubmarineWalls)) { foreach (var c in MineralClusters) @@ -1754,17 +1772,17 @@ namespace Barotrauma.Items.Components public void ClientEventWrite(IWriteMessage msg, NetEntityEvent.IData extraData = null) { - msg.Write(currentMode == Mode.Active); + msg.WriteBoolean(currentMode == Mode.Active); if (currentMode == Mode.Active) { msg.WriteRangedSingle(zoom, MinZoom, MaxZoom, 8); - msg.Write(useDirectionalPing); + msg.WriteBoolean(useDirectionalPing); if (useDirectionalPing) { float pingAngle = MathUtils.WrapAngleTwoPi(MathUtils.VectorToAngle(pingDirection)); msg.WriteRangedSingle(MathUtils.InverseLerp(0.0f, MathHelper.TwoPi, pingAngle), 0.0f, 1.0f, 8); } - msg.Write(useMineralScanner); + msg.WriteBoolean(useMineralScanner); } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Steering.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Steering.cs index 8eed52986..d4d043455 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Steering.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Steering.cs @@ -25,7 +25,9 @@ namespace Barotrauma.Items.Components private GUITickBox maintainPosTickBox, levelEndTickBox, levelStartTickBox; - private GUIComponent statusContainer, dockingContainer, controlContainer; + private GUIComponent statusContainer, dockingContainer; + + public GUIComponent ControlContainer { get; private set; } private bool dockingNetworkMessagePending; @@ -90,6 +92,24 @@ namespace Barotrauma.Items.Components } } + private bool disableControls; + /// + /// Can be used by status effects to disable all the UI controls + /// + public bool DisableControls + { + get { return disableControls; } + set + { + if (disableControls == value) { return; } + disableControls = value; + UpdateGUIElements(); + } + } + + public override bool RecreateGUIOnResolutionChange => true; + + partial void InitProjSpecific(ContentXElement element) { foreach (var subElement in element.Elements()) @@ -112,8 +132,8 @@ namespace Barotrauma.Items.Components protected override void CreateGUI() { - controlContainer = new GUIFrame(new RectTransform(new Vector2(Sonar.controlBoxSize.X, 1 - Sonar.controlBoxSize.Y * 2), GuiFrame.RectTransform, Anchor.CenterRight), "ItemUI"); - var paddedControlContainer = new GUIFrame(new RectTransform(controlContainer.Rect.Size - GUIStyle.ItemFrameMargin, controlContainer.RectTransform, Anchor.Center) + ControlContainer = new GUIFrame(new RectTransform(new Vector2(Sonar.controlBoxSize.X, 1 - Sonar.controlBoxSize.Y * 2), GuiFrame.RectTransform, Anchor.CenterRight), "ItemUI"); + var paddedControlContainer = new GUIFrame(new RectTransform(ControlContainer.Rect.Size - GUIStyle.ItemFrameMargin, ControlContainer.RectTransform, Anchor.Center) { AbsoluteOffset = GUIStyle.ItemFrameOffset }, style: null); @@ -472,7 +492,6 @@ namespace Barotrauma.Items.Components protected override void OnResolutionChanged() { - base.OnResolutionChanged(); UpdateGUIElements(); } @@ -658,6 +677,11 @@ namespace Barotrauma.Items.Components } } + if (DisableControls) + { + dockingModeEnabled = false; + } + dockingContainer.Visible = DockingModeEnabled; statusContainer.Visible = !DockingModeEnabled; if (!DockingModeEnabled) @@ -745,7 +769,7 @@ namespace Barotrauma.Items.Components iceSpireWarningText.Visible = item.Submarine != null && !pressureWarningText.Visible && showIceSpireWarning && Timing.TotalTime % 1.0f < 0.8f; - if (Vector2.DistanceSquared(PlayerInput.MousePosition, steerArea.Rect.Center.ToVector2()) < steerRadius * steerRadius) + if (!disableControls && Vector2.DistanceSquared(PlayerInput.MousePosition, steerArea.Rect.Center.ToVector2()) < steerRadius * steerRadius) { if (PlayerInput.PrimaryMouseButtonHeld() && !CrewManager.IsCommandInterfaceOpen && !GameSession.IsTabMenuOpen && (!GameMain.GameSession?.Campaign?.ShowCampaignUI ?? true) && !GUIMessageBox.MessageBoxes.Any(msgBox => msgBox is GUIMessageBox { MessageBoxType: GUIMessageBox.Type.Default })) @@ -815,7 +839,7 @@ namespace Barotrauma.Items.Components keyboardInput = Vector2.Zero; } - if (!UseAutoDocking) { return; } + if (!UseAutoDocking || DisableControls) { return; } if (checkConnectedPortsTimer <= 0.0f) { @@ -894,27 +918,27 @@ namespace Barotrauma.Items.Components public void ClientEventWrite(IWriteMessage msg, NetEntityEvent.IData extraData = null) { - msg.Write(AutoPilot); - msg.Write(dockingNetworkMessagePending); + msg.WriteBoolean(AutoPilot); + msg.WriteBoolean(dockingNetworkMessagePending); dockingNetworkMessagePending = false; if (!AutoPilot) { //no need to write steering info if autopilot is controlling - msg.Write(steeringInput.X); - msg.Write(steeringInput.Y); + msg.WriteSingle(steeringInput.X); + msg.WriteSingle(steeringInput.Y); } else { - msg.Write(posToMaintain != null); + msg.WriteBoolean(posToMaintain != null); if (posToMaintain != null) { - msg.Write(((Vector2)posToMaintain).X); - msg.Write(((Vector2)posToMaintain).Y); + msg.WriteSingle(((Vector2)posToMaintain).X); + msg.WriteSingle(((Vector2)posToMaintain).Y); } else { - msg.Write(LevelStartSelected); + msg.WriteBoolean(LevelStartSelected); } } } @@ -998,9 +1022,20 @@ namespace Barotrauma.Items.Components steeringModeSwitch.Selected = AutoPilot; autopilotIndicator.Selected = AutoPilot; manualPilotIndicator.Selected = !AutoPilot; - maintainPosTickBox.Enabled = AutoPilot; - levelEndTickBox.Enabled = AutoPilot; - levelStartTickBox.Enabled = AutoPilot; + if (DisableControls) + { + steeringModeSwitch.Enabled = false; + maintainPosTickBox.Enabled = false; + levelEndTickBox.Enabled = false; + levelStartTickBox.Enabled = false; + } + else + { + steeringModeSwitch.Enabled = true; + maintainPosTickBox.Enabled = AutoPilot; + levelEndTickBox.Enabled = AutoPilot; + levelStartTickBox.Enabled = AutoPilot; + } } } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Power/Powered.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Power/Powered.cs index e3d4e35c4..ae0b6e456 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Power/Powered.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Power/Powered.cs @@ -1,8 +1,4 @@ -using Barotrauma.Sounds; -using System.Collections.Generic; -using System.Xml.Linq; - -namespace Barotrauma.Items.Components +namespace Barotrauma.Items.Components { partial class Powered : ItemComponent { diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Repairable.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Repairable.cs index c67963162..83f660f0d 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Repairable.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Repairable.cs @@ -451,7 +451,7 @@ namespace Barotrauma.Items.Components public void ClientEventWrite(IWriteMessage msg, NetEntityEvent.IData extraData = null) { msg.WriteRangedInteger((int)requestStartFixAction, 0, 2); - msg.Write(qteSuccess); + msg.WriteBoolean(qteSuccess); } } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Signal/ButtonTerminal.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Signal/ButtonTerminal.cs index 89d1a7583..80fbd44db 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Signal/ButtonTerminal.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Signal/ButtonTerminal.cs @@ -94,7 +94,6 @@ namespace Barotrauma.Items.Components protected override void OnResolutionChanged() { - base.OnResolutionChanged(); OnItemLoadedProjSpecific(); } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Signal/Connection.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Signal/Connection.cs index fe6ba3270..022972368 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Signal/Connection.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Signal/Connection.cs @@ -21,12 +21,13 @@ namespace Barotrauma.Items.Components public float FlashTimer { get; private set; } public static Wire DraggingConnected { get; private set; } - public static void DrawConnections(SpriteBatch spriteBatch, ConnectionPanel panel, Character character) + public static void DrawConnections(SpriteBatch spriteBatch, ConnectionPanel panel, Rectangle dragArea, Character character) { if (DraggingConnected?.Item?.Removed ?? true) { DraggingConnected = null; } + Rectangle panelRect = panel.GuiFrame.Rect; int x = panelRect.X, y = panelRect.Y; int width = panelRect.Width, height = panelRect.Height; @@ -131,7 +132,10 @@ namespace Barotrauma.Items.Components { if (mouseInRect) { - DrawWire(spriteBatch, DraggingConnected, PlayerInput.MousePosition, new Vector2(x + width / 2, y + height - 10), null, panel, ""); + Vector2 wireDragPos = new Vector2( + MathHelper.Clamp(PlayerInput.MousePosition.X, dragArea.X, dragArea.Right), + MathHelper.Clamp(PlayerInput.MousePosition.Y, dragArea.Y, dragArea.Bottom)); + DrawWire(spriteBatch, DraggingConnected, wireDragPos, new Vector2(x + width / 2, y + height - 10), null, panel, ""); } panel.TriggerRewiringSound(); diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Signal/ConnectionPanel.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Signal/ConnectionPanel.cs index c0d624511..63560b853 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Signal/ConnectionPanel.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Signal/ConnectionPanel.cs @@ -5,7 +5,6 @@ using Microsoft.Xna.Framework.Graphics; using System; using System.Collections.Generic; using System.Linq; -using System.Xml.Linq; namespace Barotrauma.Items.Components { @@ -27,6 +26,10 @@ namespace Barotrauma.Items.Components private Point originalMaxSize; private Vector2 originalRelativeSize; + private GUIComponent dragArea; + + public override bool RecreateGUIOnResolutionChange => true; + partial void InitProjSpecific() { if (GuiFrame == null) { return; } @@ -40,9 +43,8 @@ namespace Barotrauma.Items.Components content.RectTransform.SetAsFirstChild(); //prevents inputs from going through the GUICustomComponent to the drag handle - var blocker = new GUIFrame(new RectTransform(GuiFrame.Rect.Size - GUIStyle.ItemFrameMargin, GuiFrame.RectTransform, Anchor.Center) - { AbsoluteOffset = GUIStyle.ItemFrameOffset }, - style: null); + dragArea = new GUIFrame(new RectTransform(GuiFrame.Rect.Size - GUIStyle.ItemFrameMargin, GuiFrame.RectTransform, Anchor.Center) + { AbsoluteOffset = GUIStyle.ItemFrameOffset }, style: null); } public void TriggerRewiringSound() @@ -111,7 +113,7 @@ namespace Barotrauma.Items.Components if (user != Character.Controlled || user == null) { return; } HighlightedWire = null; - Connection.DrawConnections(spriteBatch, this, user); + Connection.DrawConnections(spriteBatch, this, dragArea.Rect, user); foreach (UISprite sprite in GUIStyle.GetComponentStyle("ConnectionPanelFront").Sprites[GUIComponent.ComponentState.None]) { @@ -121,7 +123,6 @@ namespace Barotrauma.Items.Components protected override void OnResolutionChanged() { - base.OnResolutionChanged(); if (GuiFrame == null) { return; } CheckForLabelOverlap(); } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Signal/CustomInterface.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Signal/CustomInterface.cs index 706105771..cdb1d4ac9 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Signal/CustomInterface.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Signal/CustomInterface.cs @@ -14,6 +14,8 @@ namespace Barotrauma.Items.Components private Point ElementMaxSize => new Point(uiElementContainer.Rect.Width, (int)(65 * GUI.yScale)); + public override bool RecreateGUIOnResolutionChange => true; + partial void InitProjSpecific() { CreateGUI(); @@ -354,29 +356,29 @@ namespace Barotrauma.Items.Components { if (!element.IsNumberInput) { - msg.Write(((GUITextBox)uiElements[i]).Text); + msg.WriteString(((GUITextBox)uiElements[i]).Text); } else { switch (element.NumberType) { case NumberType.Float: - msg.Write(((GUINumberInput)uiElements[i]).FloatValue.ToString()); + msg.WriteString(((GUINumberInput)uiElements[i]).FloatValue.ToString()); break; case NumberType.Int: default: - msg.Write(((GUINumberInput)uiElements[i]).IntValue.ToString()); + msg.WriteString(((GUINumberInput)uiElements[i]).IntValue.ToString()); break; } } } else if (element.ContinuousSignal) { - msg.Write(((GUITickBox)uiElements[i]).Selected); + msg.WriteBoolean(((GUITickBox)uiElements[i]).Selected); } else { - msg.Write(extraData is Item.ComponentStateEventData { ComponentData: EventData eventData } && eventData.BtnElement == customInterfaceElementList[i]); + msg.WriteBoolean(extraData is Item.ComponentStateEventData { ComponentData: EventData eventData } && eventData.BtnElement == customInterfaceElementList[i]); } } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Signal/Terminal.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Signal/Terminal.cs index 980a6f256..ec3054df9 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Signal/Terminal.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Signal/Terminal.cs @@ -149,7 +149,7 @@ namespace Barotrauma.Items.Components { if (TryExtractEventData(extraData, out ClientEventData eventData)) { - msg.Write(eventData.Text); + msg.WriteString(eventData.Text); } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Signal/Wire.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Signal/Wire.cs index 4c1ac0f07..17922b0b4 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Signal/Wire.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Signal/Wire.cs @@ -603,11 +603,11 @@ namespace Barotrauma.Items.Components { var eventData = ExtractEventData(extraData); int nodeCount = eventData.NodeCount; - msg.Write((byte)nodeCount); + msg.WriteByte((byte)nodeCount); if (nodeCount > 0) { - msg.Write(nodes.Last().X); - msg.Write(nodes.Last().Y); + msg.WriteSingle(nodes.Last().X); + msg.WriteSingle(nodes.Last().Y); } } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/DockingPort.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/DockingPort.cs index 9466e4377..eeeb4f627 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/DockingPort.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/DockingPort.cs @@ -185,7 +185,7 @@ namespace Barotrauma.Items.Components public void ClientEventWrite(IWriteMessage msg, NetEntityEvent.IData extraData = null) { - msg.Write((byte)allowOutpostAutoDocking); + msg.WriteByte((byte)allowOutpostAutoDocking); } } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Item.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Item.cs index 8547be8c6..1a6590180 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Item.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Item.cs @@ -594,7 +594,10 @@ namespace Barotrauma if (body.LinearVelocity.Y < 0.0f) { int n = (int)((Position.X - CurrentHull.Rect.X) / Hull.WaveWidth); - CurrentHull.WaveVel[n] += MathHelper.Clamp(body.LinearVelocity.Y * massFactor, -5.0f, 5.0f); + if (n >= 0 && n < currentHull.WaveVel.Length) + { + CurrentHull.WaveVel[n] += MathHelper.Clamp(body.LinearVelocity.Y * massFactor, -5.0f, 5.0f); + } } SoundPlayer.PlaySplashSound(WorldPosition, Math.Abs(body.LinearVelocity.Y) + Rand.Range(-10.0f, -5.0f)); } @@ -1469,8 +1472,8 @@ namespace Barotrauma case TreatmentEventData treatmentEventData: Character targetCharacter = treatmentEventData.TargetCharacter; - msg.Write(targetCharacter.ID); - msg.Write(treatmentEventData.LimbIndex); + msg.WriteUInt16(targetCharacter.ID); + msg.WriteByte(treatmentEventData.LimbIndex); break; case ChangePropertyEventData changePropertyEventData: WritePropertyChange(msg, changePropertyEventData, inGameEditableOnly: true); @@ -1478,7 +1481,7 @@ namespace Barotrauma break; case CombineEventData combineEventData: Item combineTarget = combineEventData.CombineTarget; - msg.Write(combineTarget.ID); + msg.WriteUInt16(combineTarget.ID); break; default: throw error($"Unsupported event type {eventData.GetType().Name}"); diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/ItemPrefab.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/ItemPrefab.cs index cedbfbf72..bab357ba1 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/ItemPrefab.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/ItemPrefab.cs @@ -222,7 +222,7 @@ namespace Barotrauma if (!ResizeHorizontal && !ResizeVertical) { - if (PlayerInput.PrimaryMouseButtonClicked()) + if (PlayerInput.PrimaryMouseButtonClicked() && GUI.MouseOn == null) { var item = new Item(new Rectangle((int)position.X, (int)position.Y, (int)(Sprite.size.X * Scale), (int)(Sprite.size.Y * Scale)), this, Submarine.MainSub) { diff --git a/Barotrauma/BarotraumaClient/ClientSource/Map/Hull.cs b/Barotrauma/BarotraumaClient/ClientSource/Map/Hull.cs index 01bab48a4..7024d24bb 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Map/Hull.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Map/Hull.cs @@ -611,7 +611,7 @@ namespace Barotrauma case DecalEventData decalEventData: var decal = decalEventData.Decal; int decalIndex = decals.IndexOf(decal); - msg.Write((byte)(decalIndex < 0 ? 255 : decalIndex)); + msg.WriteByte((byte)(decalIndex < 0 ? 255 : decalIndex)); msg.WriteRangedSingle(decal.BaseAlpha, 0.0f, 1.0f, 8); break; default: diff --git a/Barotrauma/BarotraumaClient/ClientSource/Map/MapEntity.cs b/Barotrauma/BarotraumaClient/ClientSource/Map/MapEntity.cs index c7a818db0..a33dfa34a 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Map/MapEntity.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Map/MapEntity.cs @@ -741,6 +741,15 @@ namespace Barotrauma /// public static void DrawSelecting(SpriteBatch spriteBatch, Camera cam) { + if (Screen.Selected is SubEditorScreen subEditor) + { + if (subEditor.IsMouseOnEditorGUI()) { return; } + } + else if (GUI.MouseOn != null) + { + return; + } + Vector2 position = PlayerInput.MousePosition; position = cam.ScreenToWorld(position); diff --git a/Barotrauma/BarotraumaClient/ClientSource/Map/Structure.cs b/Barotrauma/BarotraumaClient/ClientSource/Map/Structure.cs index 596935d5b..1342557f5 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Map/Structure.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Map/Structure.cs @@ -37,17 +37,6 @@ namespace Barotrauma } } -#if DEBUG - [Editable, Serialize("", IsPropertySaveable.Yes)] -#else - [Serialize("", IsPropertySaveable.Yes)] -#endif - public string SpecialTag - { - get; - set; - } - partial void InitProjSpecific() { Prefab.Sprite?.EnsureLazyLoaded(); diff --git a/Barotrauma/BarotraumaClient/ClientSource/Map/StructurePrefab.cs b/Barotrauma/BarotraumaClient/ClientSource/Map/StructurePrefab.cs index 9ff0f0d9e..f031e7fab 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Map/StructurePrefab.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Map/StructurePrefab.cs @@ -27,9 +27,10 @@ namespace Barotrauma if (placePosition == Vector2.Zero) { - if (PlayerInput.PrimaryMouseButtonClicked() && GUI.MouseOn == null) + if (PlayerInput.PrimaryMouseButtonHeld() && GUI.MouseOn == null) + { placePosition = Submarine.MouseToWorldGrid(cam, Submarine.MainSub); - + } newRect.X = (int)position.X; newRect.Y = (int)position.Y; } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Map/SubmarineInfo.cs b/Barotrauma/BarotraumaClient/ClientSource/Map/SubmarineInfo.cs index 463d94253..f0047e10c 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Map/SubmarineInfo.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Map/SubmarineInfo.cs @@ -80,7 +80,8 @@ namespace Barotrauma { UserData = "descriptionbox", ScrollBarVisible = true, - Spacing = 5 + Spacing = 5, + CurrentSelectMode = GUIListBox.SelectMode.None }; GUIFont font = parent.Rect.Width < 350 ? GUIStyle.SmallFont : GUIStyle.Font; @@ -92,22 +93,32 @@ namespace Barotrauma { float leftPanelWidth = 0.6f; float rightPanelWidth = 0.4f / leftPanelWidth; - LocalizedString className = !HasTag(SubmarineTag.Shuttle) ? TextManager.Get($"submarineclass.{SubmarineClass}") : TextManager.Get("shuttle"); + LocalizedString className = !HasTag(SubmarineTag.Shuttle) + ? $"{TextManager.Get($"submarineclass.{SubmarineClass}")} ({TextManager.Get($"submarinetier.{Tier}")})" + : TextManager.Get("shuttle"); + int classHeight = (int)GUIStyle.SubHeadingFont.MeasureString(className).Y; - int leftPanelWidthInt = (int)(parent.Rect.Width * leftPanelWidth); + int leftPanelWidthInt = (int)(parent.Rect.Width * leftPanelWidth); GUITextBlock submarineNameText = null; GUITextBlock submarineClassText = null; if (includeTitle) { int nameHeight = (int)GUIStyle.LargeFont.MeasureString(DisplayName, true).Y; - submarineNameText = new GUITextBlock(new RectTransform(new Point(leftPanelWidthInt, nameHeight + HUDLayoutSettings.Padding / 2), parent.Content.RectTransform), DisplayName, textAlignment: Alignment.CenterLeft, font: GUIStyle.LargeFont) { CanBeFocused = false }; + submarineNameText = new GUITextBlock(new RectTransform(new Point(leftPanelWidthInt, nameHeight + HUDLayoutSettings.Padding / 2), parent.Content.RectTransform), DisplayName, textAlignment: Alignment.CenterLeft, font: GUIStyle.LargeFont) + { + CanBeFocused = false + }; submarineNameText.RectTransform.MinSize = new Point(0, (int)submarineNameText.TextSize.Y); } if (includeClass) { - submarineClassText = new GUITextBlock(new RectTransform(new Point(leftPanelWidthInt, classHeight), parent.Content.RectTransform), className, textAlignment: Alignment.CenterLeft, font: GUIStyle.SubHeadingFont) { CanBeFocused = false }; + submarineClassText = new GUITextBlock(new RectTransform(new Point(leftPanelWidthInt, classHeight), parent.Content.RectTransform), className, textAlignment: Alignment.CenterLeft, font: GUIStyle.SubHeadingFont) + { + ToolTip = TextManager.Get("submarinetierandclass.description")+"\n\n"+ TextManager.Get($"submarineclass.{SubmarineClass}.description") + }; + submarineClassText.HoverColor = Color.Transparent; submarineClassText.RectTransform.MinSize = new Point(0, (int)submarineClassText.TextSize.Y); } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Map/SubmarinePreview.cs b/Barotrauma/BarotraumaClient/ClientSource/Map/SubmarinePreview.cs index e72fc7fb1..e547ec854 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Map/SubmarinePreview.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Map/SubmarinePreview.cs @@ -144,10 +144,11 @@ namespace Barotrauma specsContainer = new GUIListBox(new RectTransform(new Vector2(0.4f, 1f), innerPadded.RectTransform, Anchor.TopLeft) { RelativeOffset = new Vector2(0.015f, 0.07f) }) { + CurrentSelectMode = GUIListBox.SelectMode.None, Color = Color.Black * 0.65f, ScrollBarEnabled = false, ScrollBarVisible = false, - Spacing = 5 + Spacing = GUI.IntScale(5) }; subInfo.CreateSpecsWindow(specsContainer, GUIStyle.Font, includeTitle: false, includeDescription: true); int width = specsContainer.Rect.Width; diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/BanList.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/BanList.cs index 23afe3580..8d0f64b01 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Networking/BanList.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/BanList.cs @@ -1,4 +1,5 @@ -using Microsoft.Xna.Framework; +#nullable enable +using Microsoft.Xna.Framework; using System; using System.Collections.Generic; using System.Linq; @@ -24,36 +25,31 @@ namespace Barotrauma.Networking partial class BanList { - private GUIComponent banFrame; - - public GUIComponent BanFrame - { - get { return banFrame; } - } + public GUIComponent? BanFrame { get; private set; } public List localRemovedBans = new List(); private void RecreateBanFrame() { - if (banFrame != null) + if (BanFrame != null) { - var parent = banFrame.Parent; - parent.RemoveChild(banFrame); + var parent = BanFrame.Parent; + parent.RemoveChild(BanFrame); CreateBanFrame(parent); } } public GUIComponent CreateBanFrame(GUIComponent parent) { - banFrame = new GUIListBox(new RectTransform(Vector2.One, parent.RectTransform, Anchor.Center)); + BanFrame = new GUIListBox(new RectTransform(Vector2.One, parent.RectTransform, Anchor.Center)); foreach (BannedPlayer bannedPlayer in bannedPlayers) { if (localRemovedBans.Contains(bannedPlayer.UniqueIdentifier)) { continue; } - var playerFrame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.2f), ((GUIListBox)banFrame).Content.RectTransform) { MinSize = new Point(0, 70) }) + var playerFrame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.2f), ((GUIListBox)BanFrame).Content.RectTransform) { MinSize = new Point(0, 70) }) { - UserData = banFrame + UserData = BanFrame }; var paddedPlayerFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.85f), playerFrame.RectTransform, Anchor.Center)) @@ -102,16 +98,15 @@ namespace Barotrauma.Networking paddedPlayerFrame.Recalculate(); - new GUIFrame(new RectTransform(new Vector2(1.0f, 0.01f), ((GUIListBox)banFrame).Content.RectTransform), style: "HorizontalLine"); + new GUIFrame(new RectTransform(new Vector2(1.0f, 0.01f), ((GUIListBox)BanFrame).Content.RectTransform), style: "HorizontalLine"); } - return banFrame; + return BanFrame; } private bool RemoveBan(GUIButton button, object obj) { - BannedPlayer banned = obj as BannedPlayer; - if (banned == null) { return false; } + if (!(obj is BannedPlayer banned)) { return false; } localRemovedBans.Add(banned.UniqueIdentifier); RecreateBanFrame(); @@ -178,10 +173,10 @@ namespace Barotrauma.Networking bannedPlayers.Add(new BannedPlayer(uniqueIdentifier, name, addressOrAccountId, reason, expiration)); } - if (banFrame != null) + if (BanFrame != null) { - var parent = banFrame.Parent; - parent.RemoveChild(banFrame); + var parent = BanFrame.Parent; + parent.RemoveChild(BanFrame); CreateBanFrame(parent); } } @@ -191,7 +186,7 @@ namespace Barotrauma.Networking outMsg.WriteVariableUInt32((UInt32)localRemovedBans.Count); foreach (UInt32 uniqueId in localRemovedBans) { - outMsg.Write(uniqueId); + outMsg.WriteUInt32(uniqueId); } localRemovedBans.Clear(); diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/ChatMessage.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/ChatMessage.cs index ec7909d75..8c1319fe5 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Networking/ChatMessage.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/ChatMessage.cs @@ -8,11 +8,11 @@ namespace Barotrauma.Networking { public virtual void ClientWrite(IWriteMessage msg) { - msg.Write((byte)ClientNetObject.CHAT_MESSAGE); - msg.Write(NetStateID); + msg.WriteByte((byte)ClientNetObject.CHAT_MESSAGE); + msg.WriteUInt16(NetStateID); msg.WriteRangedInteger((int)Type, 0, Enum.GetValues(typeof(ChatMessageType)).Length - 1); msg.WriteRangedInteger((int)ChatMode, 0, Enum.GetValues(typeof(ChatMode)).Length - 1); - msg.Write(Text); + msg.WriteString(Text); } public static void ClientRead(IReadMessage msg) diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/FileTransfer/FileReceiver.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/FileTransfer/FileReceiver.cs index 59be7ad9e..1809817cb 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Networking/FileTransfer/FileReceiver.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/FileTransfer/FileReceiver.cs @@ -12,7 +12,7 @@ namespace Barotrauma.Networking class FileReceiver { public class FileTransferIn : IDisposable - { + { public string FileName { get; @@ -36,7 +36,7 @@ namespace Barotrauma.Networking get; private set; } - + public int LastSeen { get; set; } public FileTransferType FileType @@ -93,6 +93,12 @@ namespace Barotrauma.Networking public int ID; + public const int DataBufferSize = 50; + /// + /// Data that we've ignored because we're waiting for some earlier data. Key = byte offset, value = the actual data + /// + public readonly Dictionary DataBuffer = new Dictionary(); + public FileTransferIn(NetworkConnection connection, string filePath, FileTransferType fileType) { FilePath = filePath; @@ -128,20 +134,25 @@ namespace Barotrauma.Networking bytesToRead -= Received + bytesToRead - FileSize; } - byte[] all = inc.ReadBytes(bytesToRead); - Received += all.Length; - WriteStream.Write(all, 0, all.Length); + ReadBytes(inc.ReadBytes(bytesToRead)); + } + + public void ReadBytes(byte[] data) + { + Received += data.Length; + WriteStream.Write(data, 0, data.Length); int passed = Environment.TickCount - TimeStarted; float psec = passed / 1000.0f; - if (GameSettings.CurrentConfig.VerboseLogging) - { - DebugConsole.Log($"Received {all.Length} bytes of the file {FileName} ({Received / 1000}/{FileSize / 1000} kB received)"); - } - BytesPerSecond = Received / psec; + var outdatedKeys = DataBuffer.Keys.Where(k => k < Received).ToList(); + foreach (int key in outdatedKeys) + { + DataBuffer.Remove(key); + } + Status = Received >= FileSize ? FileTransferStatus.Finished : FileTransferStatus.Receiving; } @@ -349,6 +360,10 @@ namespace Barotrauma.Networking if (offset != activeTransfer.Received) { activeTransfer.LastSeen = Math.Max(offset, activeTransfer.LastSeen); + if (!activeTransfer.DataBuffer.ContainsKey(offset) && activeTransfer.DataBuffer.Count < FileTransferIn.DataBufferSize) + { + activeTransfer.DataBuffer.Add(offset, inc.ReadBytes(bytesToRead)); + } DebugConsole.Log($"Received {bytesToRead} bytes of the file {activeTransfer.FileName} (ignoring: offset {offset}, waiting for {activeTransfer.Received})"); GameMain.Client.UpdateFileTransfer(activeTransfer, activeTransfer.Received, activeTransfer.LastSeen); return; @@ -370,7 +385,16 @@ namespace Barotrauma.Networking try { - activeTransfer.ReadBytes(inc, bytesToRead); + activeTransfer.ReadBytes(inc, bytesToRead); + if (GameSettings.CurrentConfig.VerboseLogging) + { + DebugConsole.Log($"Received {bytesToRead} bytes of the file {activeTransfer.FileName} ({activeTransfer.Received / 1000}/{activeTransfer.FileSize / 1000} kB received)"); + } + while (activeTransfer.DataBuffer.TryGetValue(activeTransfer.Received, out byte[] data)) + { + activeTransfer.ReadBytes(data); + DebugConsole.Log($"Read {data.Length} bytes of buffer data of the file {activeTransfer.FileName} ({activeTransfer.Received / 1000}/{activeTransfer.FileSize / 1000} kB received)"); + } } catch (Exception e) { @@ -434,7 +458,7 @@ namespace Barotrauma.Networking } if (string.IsNullOrEmpty(fileName) || - fileName.IndexOfAny(Path.GetInvalidFileNameChars().ToArray()) > -1) + fileName.IndexOfAny(Path.GetInvalidFileNameCharsCrossPlatform().ToArray()) > -1) { errorMessage = "Illegal characters in file name ''" + fileName + "''"; return false; @@ -470,7 +494,7 @@ namespace Barotrauma.Networking System.IO.Stream stream; try { - stream = SaveUtil.DecompressFiletoStream(fileTransfer.FilePath); + stream = SaveUtil.DecompressFileToStream(fileTransfer.FilePath); } catch (Exception e) { diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/GameClient.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/GameClient.cs index 9a04ff9e6..30ab2172f 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Networking/GameClient.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/GameClient.cs @@ -674,13 +674,13 @@ namespace Barotrauma.Networking { case ServerPacketHeader.PING_REQUEST: IWriteMessage response = new WriteOnlyMessage(); - response.Write((byte)ClientPacketHeader.PING_RESPONSE); + response.WriteByte((byte)ClientPacketHeader.PING_RESPONSE); byte requestLen = inc.ReadByte(); - response.Write(requestLen); + response.WriteByte(requestLen); for (int i = 0; i < requestLen; i++) { byte b = inc.ReadByte(); - response.Write(b); + response.WriteByte(b); } clientPeer.Send(response, DeliveryMethod.Unreliable); break; @@ -752,7 +752,7 @@ namespace Barotrauma.Networking } IWriteMessage readyToStartMsg = new WriteOnlyMessage(); - readyToStartMsg.Write((byte)ClientPacketHeader.RESPONSE_STARTGAME); + readyToStartMsg.WriteByte((byte)ClientPacketHeader.RESPONSE_STARTGAME); if (campaign != null) { campaign.PendingSubmarineSwitch = null; } GameMain.NetLobbyScreen.UsingShuttle = usingShuttle; @@ -770,7 +770,7 @@ namespace Barotrauma.Networking campaign.LastSaveID == campaignSaveID && campaignUpdateIDs.All(kvp => campaign.GetLastUpdateIdForFlag(kvp.Key) == kvp.Value); } - readyToStartMsg.Write(readyToStart); + readyToStartMsg.WriteBoolean(readyToStart); DebugConsole.Log(readyToStart ? "Ready to start." : "Not ready to start."); @@ -1202,7 +1202,8 @@ namespace Barotrauma.Networking VoipClient = new VoipClient(this, clientPeer); - if (Screen.Selected != GameMain.GameScreen && !(Screen.Selected is RoundSummaryScreen)) + //if we're still in the game, roundsummary or lobby screen, we don't need to redownload the mods + if (!(Screen.Selected is GameScreen) && !(Screen.Selected is RoundSummaryScreen) && !(Screen.Selected is NetLobbyScreen)) { GameMain.ModDownloadScreen.Select(); } @@ -1639,7 +1640,7 @@ namespace Barotrauma.Networking DateTime requestFinalizeTime = DateTime.Now; TimeSpan requestFinalizeInterval = new TimeSpan(0, 0, 2); IWriteMessage msg = new WriteOnlyMessage(); - msg.Write((byte)ClientPacketHeader.REQUEST_STARTGAMEFINALIZE); + msg.WriteByte((byte)ClientPacketHeader.REQUEST_STARTGAMEFINALIZE); clientPeer.Send(msg, DeliveryMethod.Unreliable); GUIMessageBox interruptPrompt = null; @@ -1653,7 +1654,7 @@ namespace Barotrauma.Networking if (DateTime.Now > requestFinalizeTime) { msg = new WriteOnlyMessage(); - msg.Write((byte)ClientPacketHeader.REQUEST_STARTGAMEFINALIZE); + msg.WriteByte((byte)ClientPacketHeader.REQUEST_STARTGAMEFINALIZE); clientPeer.Send(msg, DeliveryMethod.Unreliable); requestFinalizeTime = DateTime.Now + requestFinalizeInterval; } @@ -1816,16 +1817,24 @@ namespace Barotrauma.Networking if (Screen.Selected == GameMain.GameScreen) { + Submarine refSub = Submarine.MainSub; + if (Submarine.MainSubs[1] != null && + GameMain.GameSession.GameMode is PvPMode && + GameMain.GameSession.WinningTeam.HasValue && GameMain.GameSession.WinningTeam == CharacterTeamType.Team1) + { + refSub = Submarine.MainSubs[1]; + } + // Enable characters near the main sub for the endCinematic foreach (Character c in Character.CharacterList) { - if (Vector2.DistanceSquared(Submarine.MainSub.WorldPosition, c.WorldPosition) < MathUtils.Pow2(c.Params.DisableDistance)) + if (Vector2.DistanceSquared(refSub.WorldPosition, c.WorldPosition) < MathUtils.Pow2(c.Params.DisableDistance)) { c.Enabled = true; } } - EndCinematic = new CameraTransition(Submarine.MainSub, GameMain.GameScreen.Cam, Alignment.CenterLeft, Alignment.CenterRight); + EndCinematic = new CameraTransition(refSub, GameMain.GameScreen.Cam, Alignment.CenterLeft, Alignment.CenterRight); while (EndCinematic.Running && Screen.Selected == GameMain.GameScreen) { yield return CoroutineStatus.Running; @@ -1874,7 +1883,7 @@ namespace Barotrauma.Networking } GameMain.NetLobbyScreen.UpdateSubList(GameMain.NetLobbyScreen.SubList, ServerSubmarines); - GameMain.NetLobbyScreen.UpdateSubList(GameMain.NetLobbyScreen.ShuttleList.ListBox, ServerSubmarines); + GameMain.NetLobbyScreen.UpdateSubList(GameMain.NetLobbyScreen.ShuttleList.ListBox, ServerSubmarines.Where(s => s.HasTag(SubmarineTag.Shuttle))); gameStarted = inc.ReadBoolean(); bool allowSpectating = inc.ReadBoolean(); @@ -2073,7 +2082,7 @@ namespace Barotrauma.Networking (isInitialUpdate || initialUpdateReceived)) { ReadWriteMessage settingsBuf = new ReadWriteMessage(); - settingsBuf.Write(settingsData, 0, settingsLen); settingsBuf.BitPosition = 0; + settingsBuf.WriteBytes(settingsData, 0, settingsLen); settingsBuf.BitPosition = 0; serverSettings.ClientRead(settingsBuf); if (!IsServerOwner) { @@ -2325,38 +2334,38 @@ namespace Barotrauma.Networking private void SendLobbyUpdate() { IWriteMessage outmsg = new WriteOnlyMessage(); - outmsg.Write((byte)ClientPacketHeader.UPDATE_LOBBY); + outmsg.WriteByte((byte)ClientPacketHeader.UPDATE_LOBBY); - outmsg.Write((byte)ClientNetObject.SYNC_IDS); - outmsg.Write(GameMain.NetLobbyScreen.LastUpdateID); - outmsg.Write(ChatMessage.LastID); - outmsg.Write(LastClientListUpdateID); - outmsg.Write(nameId); - outmsg.Write(Name); + outmsg.WriteByte((byte)ClientNetObject.SYNC_IDS); + outmsg.WriteUInt16(GameMain.NetLobbyScreen.LastUpdateID); + outmsg.WriteUInt16(ChatMessage.LastID); + outmsg.WriteUInt16(LastClientListUpdateID); + outmsg.WriteUInt16(nameId); + outmsg.WriteString(Name); var jobPreferences = GameMain.NetLobbyScreen.JobPreferences; if (jobPreferences.Count > 0) { - outmsg.Write(jobPreferences[0].Prefab.Identifier); + outmsg.WriteIdentifier(jobPreferences[0].Prefab.Identifier); } else { - outmsg.Write(""); + outmsg.WriteIdentifier(Identifier.Empty); } - outmsg.Write((byte)MultiplayerPreferences.Instance.TeamPreference); + outmsg.WriteByte((byte)MultiplayerPreferences.Instance.TeamPreference); if (!(GameMain.GameSession?.GameMode is MultiPlayerCampaign campaign) || campaign.LastSaveID == 0) { - outmsg.Write((UInt16)0); + outmsg.WriteUInt16((UInt16)0); } else { - outmsg.Write(campaign.LastSaveID); - outmsg.Write(campaign.CampaignID); + outmsg.WriteUInt16(campaign.LastSaveID); + outmsg.WriteByte(campaign.CampaignID); foreach (MultiPlayerCampaign.NetFlags netFlag in Enum.GetValues(typeof(MultiPlayerCampaign.NetFlags))) { - outmsg.Write(campaign.GetLastUpdateIdForFlag(netFlag)); + outmsg.WriteUInt16(campaign.GetLastUpdateIdForFlag(netFlag)); } - outmsg.Write(GameMain.NetLobbyScreen.CampaignCharacterDiscarded); + outmsg.WriteBoolean(GameMain.NetLobbyScreen.CampaignCharacterDiscarded); } chatMsgQueue.RemoveAll(cMsg => !NetIdUtils.IdMoreRecent(cMsg.NetStateID, lastSentChatMsgID)); @@ -2369,7 +2378,7 @@ namespace Barotrauma.Networking } chatMsgQueue[i].ClientWrite(outmsg); } - outmsg.Write((byte)ClientNetObject.END_OF_MESSAGE); + outmsg.WriteByte((byte)ClientNetObject.END_OF_MESSAGE); if (outmsg.LengthBytes > MsgConstants.MTU) { @@ -2382,29 +2391,29 @@ namespace Barotrauma.Networking private void SendIngameUpdate() { IWriteMessage outmsg = new WriteOnlyMessage(); - outmsg.Write((byte)ClientPacketHeader.UPDATE_INGAME); - outmsg.Write(entityEventManager.MidRoundSyncingDone); + outmsg.WriteByte((byte)ClientPacketHeader.UPDATE_INGAME); + outmsg.WriteBoolean(entityEventManager.MidRoundSyncingDone); outmsg.WritePadBits(); - outmsg.Write((byte)ClientNetObject.SYNC_IDS); + outmsg.WriteByte((byte)ClientNetObject.SYNC_IDS); //outmsg.Write(GameMain.NetLobbyScreen.LastUpdateID); - outmsg.Write(ChatMessage.LastID); - outmsg.Write(entityEventManager.LastReceivedID); - outmsg.Write(LastClientListUpdateID); + outmsg.WriteUInt16(ChatMessage.LastID); + outmsg.WriteUInt16(entityEventManager.LastReceivedID); + outmsg.WriteUInt16(LastClientListUpdateID); if (!(GameMain.GameSession?.GameMode is MultiPlayerCampaign campaign) || campaign.LastSaveID == 0) { - outmsg.Write((UInt16)0); + outmsg.WriteUInt16((UInt16)0); } else { - outmsg.Write(campaign.LastSaveID); - outmsg.Write(campaign.CampaignID); + outmsg.WriteUInt16(campaign.LastSaveID); + outmsg.WriteByte(campaign.CampaignID); foreach (MultiPlayerCampaign.NetFlags flag in Enum.GetValues(typeof(MultiPlayerCampaign.NetFlags))) { - outmsg.Write(campaign.GetLastUpdateIdForFlag(flag)); + outmsg.WriteUInt16(campaign.GetLastUpdateIdForFlag(flag)); } - outmsg.Write(GameMain.NetLobbyScreen.CampaignCharacterDiscarded); + outmsg.WriteBoolean(GameMain.NetLobbyScreen.CampaignCharacterDiscarded); } Character.Controlled?.ClientWriteInput(outmsg); @@ -2423,7 +2432,7 @@ namespace Barotrauma.Networking chatMsgQueue[i].ClientWrite(outmsg); } - outmsg.Write((byte)ClientNetObject.END_OF_MESSAGE); + outmsg.WriteByte((byte)ClientNetObject.END_OF_MESSAGE); if (outmsg.LengthBytes > MsgConstants.MTU) { @@ -2462,8 +2471,8 @@ namespace Barotrauma.Networking { WaitForNextRoundRespawn = waitForNextRoundRespawn; IWriteMessage msg = new WriteOnlyMessage(); - msg.Write((byte)ClientPacketHeader.READY_TO_SPAWN); - msg.Write((bool)waitForNextRoundRespawn); + msg.WriteByte((byte)ClientPacketHeader.READY_TO_SPAWN); + msg.WriteBoolean((bool)waitForNextRoundRespawn); clientPeer?.Send(msg, DeliveryMethod.Reliable); } @@ -2475,13 +2484,13 @@ namespace Barotrauma.Networking $"Sending a file request to the server (type: {fileType}, path: {file ?? "null"}"); IWriteMessage msg = new WriteOnlyMessage(); - msg.Write((byte)ClientPacketHeader.FILE_REQUEST); - msg.Write((byte)FileTransferMessageType.Initiate); - msg.Write((byte)fileType); + msg.WriteByte((byte)ClientPacketHeader.FILE_REQUEST); + msg.WriteByte((byte)FileTransferMessageType.Initiate); + msg.WriteByte((byte)fileType); if (fileType != FileTransferType.CampaignSave) { - msg.Write(file ?? throw new ArgumentNullException(nameof(file))); - msg.Write(fileHash ?? throw new ArgumentNullException(nameof(fileHash))); + msg.WriteString(file ?? throw new ArgumentNullException(nameof(file))); + msg.WriteString(fileHash ?? throw new ArgumentNullException(nameof(fileHash))); } clientPeer.Send(msg, DeliveryMethod.Reliable); } @@ -2500,20 +2509,20 @@ namespace Barotrauma.Networking transfer.RecordOffsetAckTime(); IWriteMessage msg = new WriteOnlyMessage(); - msg.Write((byte)ClientPacketHeader.FILE_REQUEST); - msg.Write((byte)FileTransferMessageType.Data); - msg.Write((byte)transfer.ID); - msg.Write(expecting); - msg.Write(lastSeen); + msg.WriteByte((byte)ClientPacketHeader.FILE_REQUEST); + msg.WriteByte((byte)FileTransferMessageType.Data); + msg.WriteByte((byte)transfer.ID); + msg.WriteInt32(expecting); + msg.WriteInt32(lastSeen); clientPeer.Send(msg, reliable ? DeliveryMethod.Reliable : DeliveryMethod.Unreliable); } public void CancelFileTransfer(int id) { IWriteMessage msg = new WriteOnlyMessage(); - msg.Write((byte)ClientPacketHeader.FILE_REQUEST); - msg.Write((byte)FileTransferMessageType.Cancel); - msg.Write((byte)id); + msg.WriteByte((byte)ClientPacketHeader.FILE_REQUEST); + msg.WriteByte((byte)FileTransferMessageType.Cancel); + msg.WriteByte((byte)id); clientPeer.Send(msg, DeliveryMethod.Reliable); } @@ -2547,8 +2556,7 @@ namespace Barotrauma.Networking Color newSubTextColor = new Color(subElement.GetChild().TextColor, 1.0f); subElement.GetChild().TextColor = newSubTextColor; - GUITextBlock classTextBlock = subElement.GetChildByUserData("classtext") as GUITextBlock; - if (classTextBlock != null) + if (subElement.GetChildByUserData("classtext") is GUITextBlock classTextBlock) { Color newSubClassTextColor = new Color(classTextBlock.TextColor, 0.8f); classTextBlock.Text = TextManager.Get($"submarineclass.{newSub.SubmarineClass}"); @@ -2742,39 +2750,39 @@ namespace Barotrauma.Networking public void SendCharacterInfo(string newName = null) { IWriteMessage msg = new WriteOnlyMessage(); - msg.Write((byte)ClientPacketHeader.UPDATE_CHARACTERINFO); + msg.WriteByte((byte)ClientPacketHeader.UPDATE_CHARACTERINFO); WriteCharacterInfo(msg, newName); - msg.Write((byte)ServerNetObject.END_OF_MESSAGE); + msg.WriteByte((byte)ServerNetObject.END_OF_MESSAGE); clientPeer?.Send(msg, DeliveryMethod.Reliable); } public void WriteCharacterInfo(IWriteMessage msg, string newName = null) { - msg.Write(characterInfo == null); + msg.WriteBoolean(characterInfo == null); if (characterInfo == null) { return; } - msg.Write(newName ?? string.Empty); + msg.WriteString(newName ?? string.Empty); - msg.Write((byte)characterInfo.Head.Preset.TagSet.Count); + msg.WriteByte((byte)characterInfo.Head.Preset.TagSet.Count); foreach (Identifier tag in characterInfo.Head.Preset.TagSet) { - msg.Write(tag); + msg.WriteIdentifier(tag); } - msg.Write((byte)characterInfo.Head.HairIndex); - msg.Write((byte)characterInfo.Head.BeardIndex); - msg.Write((byte)characterInfo.Head.MoustacheIndex); - msg.Write((byte)characterInfo.Head.FaceAttachmentIndex); + msg.WriteByte((byte)characterInfo.Head.HairIndex); + msg.WriteByte((byte)characterInfo.Head.BeardIndex); + msg.WriteByte((byte)characterInfo.Head.MoustacheIndex); + msg.WriteByte((byte)characterInfo.Head.FaceAttachmentIndex); msg.WriteColorR8G8B8(characterInfo.Head.SkinColor); msg.WriteColorR8G8B8(characterInfo.Head.HairColor); msg.WriteColorR8G8B8(characterInfo.Head.FacialHairColor); var jobPreferences = GameMain.NetLobbyScreen.JobPreferences; int count = Math.Min(jobPreferences.Count, 3); - msg.Write((byte)count); + msg.WriteByte((byte)count); for (int i = 0; i < count; i++) { - msg.Write(jobPreferences[i].Prefab.Identifier); - msg.Write((byte)jobPreferences[i].Variant); + msg.WriteIdentifier(jobPreferences[i].Prefab.Identifier); + msg.WriteByte((byte)jobPreferences[i].Variant); } } @@ -2783,10 +2791,10 @@ namespace Barotrauma.Networking if (clientPeer == null) { return; } IWriteMessage msg = new WriteOnlyMessage(); - msg.Write((byte)ClientPacketHeader.UPDATE_LOBBY); - msg.Write((byte)ClientNetObject.VOTE); + msg.WriteByte((byte)ClientPacketHeader.UPDATE_LOBBY); + msg.WriteByte((byte)ClientNetObject.VOTE); Voting.ClientWrite(msg, voteType, data); - msg.Write((byte)ServerNetObject.END_OF_MESSAGE); + msg.WriteByte((byte)ServerNetObject.END_OF_MESSAGE); clientPeer.Send(msg, DeliveryMethod.Reliable); } @@ -2794,7 +2802,6 @@ namespace Barotrauma.Networking public void VoteForKick(Client votedClient) { if (votedClient == null) { return; } - votedClient.AddKickVote(ConnectedClients.FirstOrDefault(c => c.SessionId == SessionId)); Vote(VoteType.Kick, votedClient); } @@ -2840,10 +2847,10 @@ namespace Barotrauma.Networking public override void KickPlayer(string kickedName, string reason) { IWriteMessage msg = new WriteOnlyMessage(); - msg.Write((byte)ClientPacketHeader.SERVER_COMMAND); - msg.Write((UInt16)ClientPermissions.Kick); - msg.Write(kickedName); - msg.Write(reason); + msg.WriteByte((byte)ClientPacketHeader.SERVER_COMMAND); + msg.WriteUInt16((UInt16)ClientPermissions.Kick); + msg.WriteString(kickedName); + msg.WriteString(reason); clientPeer.Send(msg, DeliveryMethod.Reliable); } @@ -2851,11 +2858,11 @@ namespace Barotrauma.Networking public override void BanPlayer(string kickedName, string reason, TimeSpan? duration = null) { IWriteMessage msg = new WriteOnlyMessage(); - msg.Write((byte)ClientPacketHeader.SERVER_COMMAND); - msg.Write((UInt16)ClientPermissions.Ban); - msg.Write(kickedName); - msg.Write(reason); - msg.Write(duration.HasValue ? duration.Value.TotalSeconds : 0.0); //0 = permaban + msg.WriteByte((byte)ClientPacketHeader.SERVER_COMMAND); + msg.WriteUInt16((UInt16)ClientPermissions.Ban); + msg.WriteString(kickedName); + msg.WriteString(reason); + msg.WriteDouble(duration.HasValue ? duration.Value.TotalSeconds : 0.0); //0 = permaban clientPeer.Send(msg, DeliveryMethod.Reliable); } @@ -2863,28 +2870,28 @@ namespace Barotrauma.Networking public override void UnbanPlayer(string playerName) { IWriteMessage msg = new WriteOnlyMessage(); - msg.Write((byte)ClientPacketHeader.SERVER_COMMAND); - msg.Write((UInt16)ClientPermissions.Unban); - msg.Write(true); msg.WritePadBits(); - msg.Write(playerName); + msg.WriteByte((byte)ClientPacketHeader.SERVER_COMMAND); + msg.WriteUInt16((UInt16)ClientPermissions.Unban); + msg.WriteBoolean(true); msg.WritePadBits(); + msg.WriteString(playerName); clientPeer.Send(msg, DeliveryMethod.Reliable); } public override void UnbanPlayer(Endpoint endpoint) { IWriteMessage msg = new WriteOnlyMessage(); - msg.Write((byte)ClientPacketHeader.SERVER_COMMAND); - msg.Write((UInt16)ClientPermissions.Unban); - msg.Write(false); msg.WritePadBits(); - msg.Write(endpoint.StringRepresentation); + msg.WriteByte((byte)ClientPacketHeader.SERVER_COMMAND); + msg.WriteUInt16((UInt16)ClientPermissions.Unban); + msg.WriteBoolean(false); msg.WritePadBits(); + msg.WriteString(endpoint.StringRepresentation); clientPeer.Send(msg, DeliveryMethod.Reliable); } public void UpdateClientPermissions(Client targetClient) { IWriteMessage msg = new WriteOnlyMessage(); - msg.Write((byte)ClientPacketHeader.SERVER_COMMAND); - msg.Write((UInt16)ClientPermissions.ManagePermissions); + msg.WriteByte((byte)ClientPacketHeader.SERVER_COMMAND); + msg.WriteUInt16((UInt16)ClientPermissions.ManagePermissions); targetClient.WritePermissions(msg); clientPeer.Send(msg, DeliveryMethod.Reliable); } @@ -2897,10 +2904,10 @@ namespace Barotrauma.Networking return; } IWriteMessage msg = new WriteOnlyMessage(); - msg.Write((byte)ClientPacketHeader.SERVER_COMMAND); - msg.Write((UInt16)ClientPermissions.ManageCampaign); + msg.WriteByte((byte)ClientPacketHeader.SERVER_COMMAND); + msg.WriteUInt16((UInt16)ClientPermissions.ManageCampaign); campaign.ClientWrite(msg); - msg.Write((byte)ServerNetObject.END_OF_MESSAGE); + msg.WriteByte((byte)ServerNetObject.END_OF_MESSAGE); clientPeer.Send(msg, DeliveryMethod.Reliable); } @@ -2913,12 +2920,12 @@ namespace Barotrauma.Networking } IWriteMessage msg = new WriteOnlyMessage(); - msg.Write((byte)ClientPacketHeader.SERVER_COMMAND); - msg.Write((UInt16)ClientPermissions.ConsoleCommands); - msg.Write(command); + msg.WriteByte((byte)ClientPacketHeader.SERVER_COMMAND); + msg.WriteUInt16((UInt16)ClientPermissions.ConsoleCommands); + msg.WriteString(command); Vector2 cursorWorldPos = GameMain.GameScreen.Cam.ScreenToWorld(PlayerInput.MousePosition); - msg.Write(cursorWorldPos.X); - msg.Write(cursorWorldPos.Y); + msg.WriteSingle(cursorWorldPos.X); + msg.WriteSingle(cursorWorldPos.Y); clientPeer.Send(msg, DeliveryMethod.Reliable); } @@ -2929,10 +2936,10 @@ namespace Barotrauma.Networking public void RequestStartRound(bool continueCampaign = false) { IWriteMessage msg = new WriteOnlyMessage(); - msg.Write((byte)ClientPacketHeader.SERVER_COMMAND); - msg.Write((UInt16)ClientPermissions.ManageRound); - msg.Write(false); //indicates round start - msg.Write(continueCampaign); + msg.WriteByte((byte)ClientPacketHeader.SERVER_COMMAND); + msg.WriteUInt16((UInt16)ClientPermissions.ManageRound); + msg.WriteBoolean(false); //indicates round start + msg.WriteBoolean(continueCampaign); clientPeer.Send(msg, DeliveryMethod.Reliable); } @@ -2940,25 +2947,16 @@ namespace Barotrauma.Networking /// /// Tell the server to select a submarine (permission required) /// - public void RequestSelectSub(int subIndex, bool isShuttle) + public void RequestSelectSub(SubmarineInfo sub, bool isShuttle) { - if (!HasPermission(ClientPermissions.SelectSub)) return; - - var subList = isShuttle ? GameMain.NetLobbyScreen.ShuttleList.ListBox : GameMain.NetLobbyScreen.SubList; - - if (subIndex < 0 || subIndex >= subList.Content.CountChildren) - { - DebugConsole.ThrowError("Submarine index out of bounds (" + subIndex + ")\n" + Environment.StackTrace.CleanupStackTrace()); - return; - } + if (!HasPermission(ClientPermissions.SelectSub) || sub == null) { return; } IWriteMessage msg = new WriteOnlyMessage(); - msg.Write((byte)ClientPacketHeader.SERVER_COMMAND); - msg.Write((UInt16)ClientPermissions.SelectSub); - msg.Write(isShuttle); msg.WritePadBits(); - msg.Write((UInt16)subIndex); - msg.Write((byte)ServerNetObject.END_OF_MESSAGE); - + msg.WriteByte((byte)ClientPacketHeader.SERVER_COMMAND); + msg.WriteUInt16((UInt16)ClientPermissions.SelectSub); + msg.WriteBoolean(isShuttle); msg.WritePadBits(); + msg.WriteString(sub.MD5Hash.StringRepresentation); + msg.WriteByte((byte)ServerNetObject.END_OF_MESSAGE); clientPeer.Send(msg, DeliveryMethod.Reliable); } @@ -2975,10 +2973,10 @@ namespace Barotrauma.Networking } IWriteMessage msg = new WriteOnlyMessage(); - msg.Write((byte)ClientPacketHeader.SERVER_COMMAND); - msg.Write((UInt16)ClientPermissions.SelectMode); - msg.Write((UInt16)modeIndex); - msg.Write((byte)ServerNetObject.END_OF_MESSAGE); + msg.WriteByte((byte)ClientPacketHeader.SERVER_COMMAND); + msg.WriteUInt16((UInt16)ClientPermissions.SelectMode); + msg.WriteUInt16((UInt16)modeIndex); + msg.WriteByte((byte)ServerNetObject.END_OF_MESSAGE); clientPeer.Send(msg, DeliveryMethod.Reliable); } @@ -2991,14 +2989,14 @@ namespace Barotrauma.Networking saveName = Path.GetFileNameWithoutExtension(saveName); IWriteMessage msg = new WriteOnlyMessage(); - msg.Write((byte)ClientPacketHeader.CAMPAIGN_SETUP_INFO); + msg.WriteByte((byte)ClientPacketHeader.CAMPAIGN_SETUP_INFO); - msg.Write(true); msg.WritePadBits(); - msg.Write(saveName); - msg.Write(mapSeed); - msg.Write(sub.Name); - msg.Write(sub.MD5Hash.StringRepresentation); - msg.Write(settings); + msg.WriteBoolean(true); msg.WritePadBits(); + msg.WriteString(saveName); + msg.WriteString(mapSeed); + msg.WriteString(sub.Name); + msg.WriteString(sub.MD5Hash.StringRepresentation); + msg.WriteNetSerializableStruct(settings); clientPeer.Send(msg, DeliveryMethod.Reliable); } @@ -3011,10 +3009,10 @@ namespace Barotrauma.Networking GameMain.NetLobbyScreen.CampaignFrame.Visible = false; IWriteMessage msg = new WriteOnlyMessage(); - msg.Write((byte)ClientPacketHeader.CAMPAIGN_SETUP_INFO); + msg.WriteByte((byte)ClientPacketHeader.CAMPAIGN_SETUP_INFO); - msg.Write(false); msg.WritePadBits(); - msg.Write(saveName); + msg.WriteBoolean(false); msg.WritePadBits(); + msg.WriteString(saveName); clientPeer.Send(msg, DeliveryMethod.Reliable); } @@ -3025,10 +3023,10 @@ namespace Barotrauma.Networking public void RequestRoundEnd(bool save) { IWriteMessage msg = new WriteOnlyMessage(); - msg.Write((byte)ClientPacketHeader.SERVER_COMMAND); - msg.Write((UInt16)ClientPermissions.ManageRound); - msg.Write(true); //indicates round end - msg.Write(save); + msg.WriteByte((byte)ClientPacketHeader.SERVER_COMMAND); + msg.WriteUInt16((UInt16)ClientPermissions.ManageRound); + msg.WriteBoolean(true); //indicates round end + msg.WriteBoolean(save); clientPeer.Send(msg, DeliveryMethod.Reliable); } @@ -3049,11 +3047,11 @@ namespace Barotrauma.Networking if (clientPeer == null) { return false; } IWriteMessage readyToStartMsg = new WriteOnlyMessage(); - readyToStartMsg.Write((byte)ClientPacketHeader.RESPONSE_STARTGAME); + readyToStartMsg.WriteByte((byte)ClientPacketHeader.RESPONSE_STARTGAME); //assume we have the required sub files to start the round //(if not, we'll find out when the server sends the STARTGAME message and can initiate a file transfer) - readyToStartMsg.Write(true); + readyToStartMsg.WriteBoolean(true); WriteCharacterInfo(readyToStartMsg); @@ -3480,10 +3478,6 @@ namespace Barotrauma.Networking UserData = client, OnClicked = (btn, userdata) => { VoteForKick(client); btn.Enabled = false; return true; } }; - if (GameMain.NetworkMember.ConnectedClients != null) - { - kickVoteButton.Enabled = !client.HasKickVoteFromSessionId(SessionId); - } } } @@ -3568,21 +3562,21 @@ namespace Barotrauma.Networking public void ReportError(ClientNetError error, UInt16 expectedId = 0, UInt16 eventId = 0, UInt16 entityId = 0) { IWriteMessage outMsg = new WriteOnlyMessage(); - outMsg.Write((byte)ClientPacketHeader.ERROR); - outMsg.Write((byte)error); + outMsg.WriteByte((byte)ClientPacketHeader.ERROR); + outMsg.WriteByte((byte)error); switch (error) { case ClientNetError.MISSING_EVENT: - outMsg.Write(expectedId); - outMsg.Write(eventId); + outMsg.WriteUInt16(expectedId); + outMsg.WriteUInt16(eventId); break; case ClientNetError.MISSING_ENTITY: - outMsg.Write(eventId); - outMsg.Write(entityId); - outMsg.Write((byte)Submarine.Loaded.Count); + outMsg.WriteUInt16(eventId); + outMsg.WriteUInt16(entityId); + outMsg.WriteByte((byte)Submarine.Loaded.Count); foreach (Submarine sub in Submarine.Loaded) { - outMsg.Write(sub.Info.Name); + outMsg.WriteString(sub.Info.Name); } break; } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/NetEntityEvent/ClientEntityEventManager.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/NetEntityEvent/ClientEntityEventManager.cs index 929701014..4a46f3c9e 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Networking/NetEntityEvent/ClientEntityEventManager.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/NetEntityEvent/ClientEntityEventManager.cs @@ -103,7 +103,7 @@ namespace Barotrauma.Networking eventLastSent[entityEvent.ID] = (float)Lidgren.Network.NetTime.Now; } - msg.Write((byte)ClientNetObject.ENTITY_STATE); + msg.WriteByte((byte)ClientNetObject.ENTITY_STATE); Write(msg, eventsToSync, out _); } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/NetEntityEvent/NetEntityEvent.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/NetEntityEvent/NetEntityEvent.cs index 0bca588f9..f474cd2fd 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Networking/NetEntityEvent/NetEntityEvent.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/NetEntityEvent/NetEntityEvent.cs @@ -17,7 +17,7 @@ namespace Barotrauma.Networking public void Write(IWriteMessage msg) { - msg.Write(CharacterStateID); + msg.WriteUInt16(CharacterStateID); serializable.ClientEventWrite(msg, Data); } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/OrderChatMessage.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/OrderChatMessage.cs index 673a8423f..b21592b8d 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Networking/OrderChatMessage.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/OrderChatMessage.cs @@ -6,8 +6,8 @@ namespace Barotrauma.Networking { public override void ClientWrite(IWriteMessage msg) { - msg.Write((byte)ClientNetObject.CHAT_MESSAGE); - msg.Write(NetStateID); + msg.WriteByte((byte)ClientNetObject.CHAT_MESSAGE); + msg.WriteUInt16(NetStateID); msg.WriteRangedInteger((int)ChatMessageType.Order, 0, Enum.GetValues(typeof(ChatMessageType)).Length - 1); msg.WriteRangedInteger((int)ChatMode.None, 0, Enum.GetValues(typeof(ChatMode)).Length - 1); WriteOrder(msg); diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/Primitives/Peers/ClientPeer.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/Primitives/Peers/ClientPeer.cs index b7aa17ec1..e2ce04903 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Networking/Primitives/Peers/ClientPeer.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/Primitives/Peers/ClientPeer.cs @@ -1,60 +1,23 @@ #nullable enable using Barotrauma.Steam; using System; -using System.Collections.Generic; using System.Collections.Immutable; -using System.Linq; namespace Barotrauma.Networking { - abstract class ClientPeer + internal abstract class ClientPeer { - public class ServerContentPackage - { - public readonly string Name; - public readonly Md5Hash Hash; - public readonly UInt64 WorkshopId; - public readonly DateTime InstallTime; - - public RegularPackage? RegularPackage - { - get - { - return ContentPackageManager.RegularPackages.FirstOrDefault(p => p.Hash.Equals(Hash)); - } - } - - public CorePackage? CorePackage - { - get - { - return ContentPackageManager.CorePackages.FirstOrDefault(p => p.Hash.Equals(Hash)); - } - } - - public ContentPackage? ContentPackage - => (ContentPackage?)RegularPackage ?? CorePackage; - - - public string GetPackageStr() - => $"\"{Name}\" (hash {Hash.ShortRepresentation})"; - - public ServerContentPackage(string name, Md5Hash hash, UInt64 workshopId, DateTime installTime) - { - Name = name; - Hash = hash; - WorkshopId = workshopId; - InstallTime = installTime; - } - } - public ImmutableArray ServerContentPackages { get; set; } = ImmutableArray.Empty; public delegate void MessageCallback(IReadMessage message); + public delegate void DisconnectCallback(bool disableReconnect); + public delegate void DisconnectMessageCallback(string message); + public delegate void PasswordCallback(int salt, int retries); + public delegate void InitializationCompleteCallback(); [Obsolete("TODO: delete in nr3-layer-1-2-cleanup")] @@ -65,8 +28,12 @@ namespace Barotrauma.Networking public readonly DisconnectMessageCallback OnDisconnectMessageReceived; public readonly PasswordCallback OnRequestPassword; public readonly InitializationCompleteCallback OnInitializationComplete; - - public Callbacks(MessageCallback onMessageReceived, DisconnectCallback onDisconnect, DisconnectMessageCallback onDisconnectMessageReceived, PasswordCallback onRequestPassword, InitializationCompleteCallback onInitializationComplete) + + public Callbacks(MessageCallback onMessageReceived, + DisconnectCallback onDisconnect, + DisconnectMessageCallback onDisconnectMessageReceived, + PasswordCallback onRequestPassword, + InitializationCompleteCallback onInitializationComplete) { OnMessageReceived = onMessageReceived; OnDisconnect = onDisconnect; @@ -91,98 +58,106 @@ namespace Barotrauma.Networking this.ownerKey = ownerKey; isOwner = ownerKey.IsSome(); } - + public abstract void Start(); public abstract void Close(string? msg = null, bool disableReconnect = false); public abstract void Update(float deltaTime); public abstract void Send(IWriteMessage msg, DeliveryMethod deliveryMethod, bool compressPastThreshold = true); public abstract void SendPassword(string password); - protected abstract void SendMsgInternal(DeliveryMethod deliveryMethod, IWriteMessage msg); + protected abstract void SendMsgInternal(PeerPacketHeaders headers, INetSerializableStruct? body); protected ConnectionInitialization initializationStep; public bool ContentPackageOrderReceived { get; protected set; } protected int passwordSalt; protected Steamworks.AuthTicket? steamAuthTicket; - protected void ReadConnectionInitializationStep(IReadMessage inc) + + public struct IncomingInitializationMessage { - ConnectionInitialization step = (ConnectionInitialization)inc.ReadByte(); + public ConnectionInitialization InitializationStep; + public IReadMessage Message; + } - IWriteMessage outMsg; - - switch (step) + protected void ReadConnectionInitializationStep(IncomingInitializationMessage inc) + { + switch (inc.InitializationStep) { case ConnectionInitialization.SteamTicketAndVersion: + { if (initializationStep != ConnectionInitialization.SteamTicketAndVersion) { return; } - outMsg = new WriteOnlyMessage(); - outMsg.Write((byte)PacketHeader.IsConnectionInitializationStep); - outMsg.Write((byte)ConnectionInitialization.SteamTicketAndVersion); - outMsg.Write(GameMain.Client.Name); - outMsg.Write(ownerKey.Fallback(0)); - outMsg.Write(SteamManager.GetSteamId().Select(steamId => steamId.Value).Fallback(0)); - if (steamAuthTicket == null) - { - outMsg.Write((UInt16)0); - } - else - { - outMsg.Write((UInt16)steamAuthTicket.Data.Length); - outMsg.Write(steamAuthTicket.Data, 0, steamAuthTicket.Data.Length); - } - outMsg.Write(GameMain.Version.ToString()); - outMsg.Write(GameSettings.CurrentConfig.Language.Value); - SendMsgInternal(DeliveryMethod.Reliable, outMsg); + PeerPacketHeaders headers = new PeerPacketHeaders + { + DeliveryMethod = DeliveryMethod.Reliable, + PacketHeader = PacketHeader.IsConnectionInitializationStep, + Initialization = ConnectionInitialization.SteamTicketAndVersion + }; + + ClientSteamTicketAndVersionPacket body = new ClientSteamTicketAndVersionPacket + { + Name = GameMain.Client.Name, + OwnerKey = ownerKey, + SteamId = SteamManager.GetSteamId().Select(id => (AccountId)id), + SteamAuthTicket = steamAuthTicket switch + { + null => Option.None(), + var ticket => Option.Some(ticket.Data) + }, + GameVersion = GameMain.Version.ToString(), + Language = GameSettings.CurrentConfig.Language.Value + }; + + SendMsgInternal(headers, body); break; + } case ConnectionInitialization.ContentPackageOrder: + { if (initializationStep == ConnectionInitialization.SteamTicketAndVersion || - initializationStep == ConnectionInitialization.Password) { initializationStep = ConnectionInitialization.ContentPackageOrder; } - if (initializationStep != ConnectionInitialization.ContentPackageOrder) { return; } - outMsg = new WriteOnlyMessage(); - outMsg.Write((byte)PacketHeader.IsConnectionInitializationStep); - outMsg.Write((byte)ConnectionInitialization.ContentPackageOrder); - - UInt32 packageCount = inc.ReadVariableUInt32(); - List serverPackages = new List(); - for (int i = 0; i < packageCount; i++) + initializationStep == ConnectionInitialization.Password) { - string name = inc.ReadString(); - UInt32 hashByteCount = inc.ReadVariableUInt32(); - byte[] hashBytes = inc.ReadBytes((int)hashByteCount); - UInt64 workshopId = inc.ReadUInt64(); - UInt32 installTimeDiffSeconds = inc.ReadUInt32(); - DateTime installTime = DateTime.UtcNow + TimeSpan.FromSeconds(installTimeDiffSeconds); - - var pkg = new ServerContentPackage(name, Md5Hash.BytesAsHash(hashBytes), workshopId, installTime); - serverPackages.Add(pkg); + initializationStep = ConnectionInitialization.ContentPackageOrder; } + if (initializationStep != ConnectionInitialization.ContentPackageOrder) { return; } + + PeerPacketHeaders headers = new PeerPacketHeaders + { + DeliveryMethod = DeliveryMethod.Reliable, + PacketHeader = PacketHeader.IsConnectionInitializationStep, + Initialization = ConnectionInitialization.ContentPackageOrder + }; + + var orderPacket = INetSerializableStruct.Read(inc.Message); + if (!ContentPackageOrderReceived) { - ServerContentPackages = serverPackages.ToImmutableArray(); - if (serverPackages.Count == 0) + ServerContentPackages = orderPacket.ContentPackages; + if (ServerContentPackages.Length == 0) { string errorMsg = "Error in ContentPackageOrder message: list of content packages enabled on the server was empty."; GameAnalyticsManager.AddErrorEventOnce("ClientPeer.ReadConnectionInitializationStep:NoContentPackages", GameAnalyticsManager.ErrorSeverity.Error, errorMsg); DebugConsole.ThrowError(errorMsg); } ContentPackageOrderReceived = true; - SendMsgInternal(DeliveryMethod.Reliable, outMsg); + + SendMsgInternal(headers, null); } + break; + } case ConnectionInitialization.Password: - if (initializationStep == ConnectionInitialization.SteamTicketAndVersion) { initializationStep = ConnectionInitialization.Password; } + if (initializationStep == ConnectionInitialization.SteamTicketAndVersion) + { + initializationStep = ConnectionInitialization.Password; + } + if (initializationStep != ConnectionInitialization.Password) { return; } - bool incomingSalt = inc.ReadBoolean(); inc.ReadPadBits(); - int retries = 0; - if (incomingSalt) - { - passwordSalt = inc.ReadInt32(); - } - else - { - retries = inc.ReadInt32(); - } + + var passwordPacket = INetSerializableStruct.Read(inc.Message); + + passwordPacket.Salt.TryUnwrap(out passwordSalt); + passwordPacket.RetriesLeft.TryUnwrap(out var retries); + callbacks.OnRequestPassword.Invoke(passwordSalt, retries); break; } @@ -192,4 +167,4 @@ namespace Barotrauma.Networking public abstract void ForceTimeOut(); #endif } -} +} \ No newline at end of file diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/Primitives/Peers/LidgrenClientPeer.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/Primitives/Peers/LidgrenClientPeer.cs index 80e5a7f65..5cb7795d0 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Networking/Primitives/Peers/LidgrenClientPeer.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/Primitives/Peers/LidgrenClientPeer.cs @@ -1,21 +1,22 @@ -using Barotrauma.Steam; -using Lidgren.Network; +#nullable enable using System; using System.Collections.Generic; using System.Text; +using Lidgren.Network; +using Barotrauma.Steam; namespace Barotrauma.Networking { - class LidgrenClientPeer : ClientPeer + internal sealed class LidgrenClientPeer : ClientPeer { private bool isActive; - private NetClient netClient; - private NetPeerConfiguration netPeerConfiguration; + private NetClient? netClient; + private readonly NetPeerConfiguration netPeerConfiguration; - List incomingLidgrenMessages; + private readonly List incomingLidgrenMessages; - private LidgrenEndpoint lidgrenEndpoint - => ServerConnection is LidgrenConnection { Endpoint: LidgrenEndpoint result } + private LidgrenEndpoint lidgrenEndpoint => + ServerConnection is LidgrenConnection { Endpoint: LidgrenEndpoint result } ? result : throw new InvalidOperationException(); @@ -25,13 +26,6 @@ namespace Barotrauma.Networking netClient = null; isActive = false; - } - - public override void Start() - { - if (isActive) { return; } - - ContentPackageOrderReceived = false; netPeerConfiguration = new NetPeerConfiguration("barotrauma") { @@ -45,6 +39,17 @@ namespace Barotrauma.Networking | NetIncomingMessageType.ErrorMessage | NetIncomingMessageType.Error); + incomingLidgrenMessages = new List(); + } + + public override void Start() + { + if (isActive) { return; } + + incomingLidgrenMessages.Clear(); + + ContentPackageOrderReceived = false; + netClient = new NetClient(netPeerConfiguration); if (SteamManager.IsInitialized) @@ -56,14 +61,13 @@ namespace Barotrauma.Networking } } - incomingLidgrenMessages = new List(); - initializationStep = ConnectionInitialization.SteamTicketAndVersion; - if (!(ServerEndpoint is LidgrenEndpoint lidgrenEndpoint)) + if (!(ServerEndpoint is LidgrenEndpoint lidgrenEndpointValue)) { - throw new InvalidCastException("endPoint is not IPEndPoint"); + throw new InvalidCastException($"Endpoint is not {nameof(LidgrenEndpoint)}"); } + if (ServerConnection != null) { throw new InvalidOperationException("ServerConnection is not null"); @@ -71,8 +75,8 @@ namespace Barotrauma.Networking netClient.Start(); - var netConnection = netClient.Connect(lidgrenEndpoint.NetEndpoint); - + var netConnection = netClient.Connect(lidgrenEndpointValue.NetEndpoint); + ServerConnection = new LidgrenConnection(netConnection) { Status = NetworkConnectionStatus.Connected @@ -85,11 +89,18 @@ namespace Barotrauma.Networking { if (!isActive) { return; } + ToolBox.ThrowIfNull(netClient); + ToolBox.ThrowIfNull(incomingLidgrenMessages); + if (isOwner && !(ChildServerRelay.Process is { HasExited: false })) { Close(); var msgBox = new GUIMessageBox(TextManager.Get("ConnectionLost"), ChildServerRelay.CrashMessage); - msgBox.Buttons[0].OnClicked += (btn, obj) => { GameMain.MainMenuScreen.Select(); return false; }; + msgBox.Buttons[0].OnClicked += (btn, obj) => + { + GameMain.MainMenuScreen.Select(); + return false; + }; return; } @@ -101,7 +112,11 @@ namespace Barotrauma.Networking foreach (NetIncomingMessage inc in incomingLidgrenMessages) { - if (!inc.SenderConnection.RemoteEndPoint.Equals(lidgrenEndpoint.NetEndpoint)) { continue; } + if (!inc.SenderConnection.RemoteEndPoint.Equals(lidgrenEndpoint.NetEndpoint)) + { + DebugConsole.AddWarning($"Mismatched endpoint: expected {lidgrenEndpoint.NetEndpoint}, got {inc.SenderConnection.RemoteEndPoint}"); + continue; + } switch (inc.MessageType) { @@ -115,15 +130,23 @@ namespace Barotrauma.Networking } } - private void HandleDataMessage(NetIncomingMessage inc) + private void HandleDataMessage(NetIncomingMessage lidgrenMsg) { if (!isActive) { return; } - PacketHeader packetHeader = (PacketHeader)inc.ReadByte(); + ToolBox.ThrowIfNull(ServerConnection); + + IReadMessage inc = lidgrenMsg.ToReadMessage(); + + var (_, packetHeader, initialization) = INetSerializableStruct.Read(inc); if (packetHeader.IsConnectionInitializationStep() && initializationStep != ConnectionInitialization.Success) { - ReadConnectionInitializationStep(new ReadWriteMessage(inc.Data, (int)inc.Position, inc.LengthBits, false)); + ReadConnectionInitializationStep(new IncomingInitializationMessage + { + InitializationStep = initialization ?? throw new Exception("Initialization step missing"), + Message = inc + }); } else { @@ -132,9 +155,9 @@ namespace Barotrauma.Networking callbacks.OnInitializationComplete.Invoke(); initializationStep = ConnectionInitialization.Success; } - UInt16 length = inc.ReadUInt16(); - IReadMessage msg = new ReadOnlyMessage(inc.Data, packetHeader.IsCompressed(), inc.PositionInBytes, length, ServerConnection); - callbacks.OnMessageReceived.Invoke(msg); + + var packet = INetSerializableStruct.Read(inc); + callbacks.OnMessageReceived.Invoke(packet.GetReadMessage(packetHeader.IsCompressed(), ServerConnection)); } } @@ -142,7 +165,7 @@ namespace Barotrauma.Networking { if (!isActive) { return; } - NetConnectionStatus status = (NetConnectionStatus)inc.ReadByte(); + NetConnectionStatus status = inc.ReadHeader(); switch (status) { case NetConnectionStatus.Disconnected: @@ -157,29 +180,38 @@ namespace Barotrauma.Networking { if (!isActive) { return; } + ToolBox.ThrowIfNull(netClient); + if (initializationStep != ConnectionInitialization.Password) { return; } - NetOutgoingMessage outMsg = netClient.CreateMessage(); - outMsg.Write((byte)PacketHeader.IsConnectionInitializationStep); - outMsg.Write((byte)ConnectionInitialization.Password); - byte[] saltedPw = ServerSettings.SaltPassword(Encoding.UTF8.GetBytes(password), passwordSalt); - outMsg.Write((byte)saltedPw.Length); - outMsg.Write(saltedPw, 0, saltedPw.Length); - NetSendResult result = netClient.SendMessage(outMsg, NetDeliveryMethod.ReliableUnordered); - if (result != NetSendResult.Queued && result != NetSendResult.Sent) + + var headers = new PeerPacketHeaders { - DebugConsole.NewMessage("Failed to send " + initializationStep.ToString() + " message to host: " + result); - } + DeliveryMethod = DeliveryMethod.Reliable, + PacketHeader = PacketHeader.IsConnectionInitializationStep, + Initialization = ConnectionInitialization.Password + }; + var body = new ClientPeerPasswordPacket + { + Password = ServerSettings.SaltPassword(Encoding.UTF8.GetBytes(password), passwordSalt) + }; + + SendMsgInternal(headers, body); } - public override void Close(string msg = null, bool disableReconnect = false) + public override void Close(string? msg = null, bool disableReconnect = false) { if (!isActive) { return; } + ToolBox.ThrowIfNull(netClient); + isActive = false; netClient.Shutdown(msg ?? TextManager.Get("Disconnecting").Value); netClient = null; - steamAuthTicket?.Cancel(); steamAuthTicket = null; + + steamAuthTicket?.Cancel(); + steamAuthTicket = null; + callbacks.OnDisconnect.Invoke(disableReconnect); } @@ -187,19 +219,8 @@ namespace Barotrauma.Networking { if (!isActive) { return; } - NetDeliveryMethod lidgrenDeliveryMethod = NetDeliveryMethod.Unreliable; - switch (deliveryMethod) - { - case DeliveryMethod.Unreliable: - lidgrenDeliveryMethod = NetDeliveryMethod.Unreliable; - break; - case DeliveryMethod.Reliable: - lidgrenDeliveryMethod = NetDeliveryMethod.ReliableUnordered; - break; - case DeliveryMethod.ReliableOrdered: - lidgrenDeliveryMethod = NetDeliveryMethod.ReliableOrdered; - break; - } + ToolBox.ThrowIfNull(netClient); + ToolBox.ThrowIfNull(netPeerConfiguration); #if DEBUG netPeerConfiguration.SimulatedDuplicatesChance = GameMain.Client.SimulatedDuplicatesChance; @@ -208,30 +229,42 @@ namespace Barotrauma.Networking netPeerConfiguration.SimulatedLoss = GameMain.Client.SimulatedLoss; #endif - NetOutgoingMessage lidgrenMsg = netClient.CreateMessage(); - byte[] msgData = new byte[msg.LengthBytes]; - msg.PrepareForSending(ref msgData, compressPastThreshold, out bool isCompressed, out int length); - lidgrenMsg.Write((byte)(isCompressed ? PacketHeader.IsCompressed : PacketHeader.None)); - lidgrenMsg.Write((UInt16)length); - lidgrenMsg.Write(msgData, 0, length); + byte[] bufAux = msg.PrepareForSending(compressPastThreshold, out bool isCompressed, out _); - NetSendResult result = netClient.SendMessage(lidgrenMsg, lidgrenDeliveryMethod); + var headers = new PeerPacketHeaders + { + DeliveryMethod = deliveryMethod, + PacketHeader = isCompressed ? PacketHeader.IsCompressed : PacketHeader.None, + Initialization = null + }; + var body = new PeerPacketMessage + { + Buffer = bufAux + }; + + SendMsgInternal(headers, body); + } + + protected override void SendMsgInternal(PeerPacketHeaders headers, INetSerializableStruct? body) + { + ToolBox.ThrowIfNull(netClient); + + IWriteMessage msg = new WriteOnlyMessage(); + msg.WriteNetSerializableStruct(headers); + body?.Write(msg); + + NetSendResult result = ForwardToLidgren(msg, DeliveryMethod.Reliable); if (result != NetSendResult.Queued && result != NetSendResult.Sent) { - DebugConsole.NewMessage("Failed to send message to host: " + result); + DebugConsole.NewMessage($"Failed to send message to host: {result}\n{Environment.StackTrace}"); } } - protected override void SendMsgInternal(DeliveryMethod deliveryMethod, IWriteMessage msg) + private NetSendResult ForwardToLidgren(IWriteMessage msg, DeliveryMethod deliveryMethod) { - NetOutgoingMessage lidgrenMsg = netClient.CreateMessage(); - lidgrenMsg.Write(msg.Buffer, 0, msg.LengthBytes); + ToolBox.ThrowIfNull(netClient); - NetSendResult result = netClient.SendMessage(lidgrenMsg, NetDeliveryMethod.ReliableUnordered); - if (result != NetSendResult.Queued && result != NetSendResult.Sent) - { - DebugConsole.NewMessage("Failed to send message to host: " + result + "\n" + Environment.StackTrace); - } + return netClient.SendMessage(msg.ToLidgren(netClient), deliveryMethod.ToLidgren()); } #if DEBUG @@ -241,4 +274,4 @@ namespace Barotrauma.Networking } #endif } -} +} \ No newline at end of file diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/Primitives/Peers/SteamP2PClientPeer.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/Primitives/Peers/SteamP2PClientPeer.cs index c4c30ce12..64c8b29b5 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Networking/Primitives/Peers/SteamP2PClientPeer.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/Primitives/Peers/SteamP2PClientPeer.cs @@ -1,13 +1,14 @@ -using Barotrauma.Steam; +#nullable enable using System; using System.Collections.Generic; using System.Linq; using System.Text; +using Barotrauma.Steam; using System.Threading; namespace Barotrauma.Networking { - class SteamP2PClientPeer : ClientPeer + internal sealed class SteamP2PClientPeer : ClientPeer { private bool isActive; private readonly SteamId hostSteamId; @@ -17,20 +18,20 @@ namespace Barotrauma.Networking private long sentBytes, receivedBytes; - private List incomingInitializationMessages; - private List incomingDataMessages; + private readonly List incomingInitializationMessages = new List(); + private readonly List incomingDataMessages = new List(); public SteamP2PClientPeer(SteamP2PEndpoint endpoint, Callbacks callbacks) : base(endpoint, callbacks, Option.None()) { ServerConnection = null; isActive = false; - + if (!(ServerEndpoint is SteamP2PEndpoint steamIdEndpoint)) { throw new InvalidCastException("endPoint is not SteamId"); } - + hostSteamId = steamIdEndpoint.SteamId; } @@ -55,16 +56,13 @@ namespace Barotrauma.Networking ServerConnection = new SteamP2PConnection(hostSteamId); ServerConnection.SetAccountInfo(new AccountInfo(hostSteamId)); - incomingInitializationMessages = new List(); - incomingDataMessages = new List(); - - IWriteMessage outMsg = new WriteOnlyMessage(); - outMsg.Write((byte)DeliveryMethod.Reliable); - outMsg.Write((byte)PacketHeader.IsConnectionInitializationStep); - outMsg.Write((byte)ConnectionInitialization.ConnectionStarted); - - Steamworks.SteamNetworking.SendP2PPacket(hostSteamId.Value, outMsg.Buffer, outMsg.LengthBytes, 0, Steamworks.P2PSend.Reliable); - sentBytes += outMsg.LengthBytes; + var headers = new PeerPacketHeaders + { + DeliveryMethod = DeliveryMethod.Reliable, + PacketHeader = PacketHeader.IsConnectionInitializationStep, + Initialization = ConnectionInitialization.ConnectionStarted + }; + SendMsgInternal(headers, null); initializationStep = ConnectionInitialization.SteamTicketAndVersion; @@ -78,6 +76,7 @@ namespace Barotrauma.Networking private void OnIncomingConnection(Steamworks.SteamId steamId) { if (!isActive) { return; } + if (steamId == hostSteamId.Value) { Steamworks.SteamNetworking.AcceptP2PSessionWithUser(steamId); @@ -86,16 +85,18 @@ namespace Barotrauma.Networking initializationStep != ConnectionInitialization.ContentPackageOrder && initializationStep != ConnectionInitialization.Success) { - DebugConsole.ThrowError($"Connection from incorrect SteamID was rejected: "+ - $"expected {hostSteamId}," + - $"got {new SteamId(steamId)}"); + DebugConsole.ThrowError("Connection from incorrect SteamID was rejected: " + + $"expected {hostSteamId}," + + $"got {new SteamId(steamId)}"); } } private void OnConnectionFailed(Steamworks.SteamId steamId, Steamworks.P2PSessionError error) { if (!isActive) { return; } + if (steamId != hostSteamId.Value) { return; } + Close($"SteamP2P connection failed: {error}"); callbacks.OnDisconnectMessageReceived.Invoke($"{DisconnectReason.SteamP2PError}/SteamP2P connection failed: {error}"); } @@ -103,27 +104,31 @@ namespace Barotrauma.Networking private void OnP2PData(ulong steamId, byte[] data, int dataLength) { if (!isActive) { return; } + if (steamId != hostSteamId.Value) { return; } - timeout = Screen.Selected == GameMain.GameScreen ? - NetworkConnection.TimeoutThresholdInGame : - NetworkConnection.TimeoutThreshold; - - PacketHeader packetHeader = (PacketHeader)data[0]; + timeout = Screen.Selected == GameMain.GameScreen + ? NetworkConnection.TimeoutThresholdInGame + : NetworkConnection.TimeoutThreshold; + + IReadMessage inc = new ReadOnlyMessage(data, false, 0, dataLength, ServerConnection); + + var (deliveryMethod, packetHeader, initialization) = INetSerializableStruct.Read(inc); if (!packetHeader.IsServerMessage()) { return; } - if (packetHeader.IsConnectionInitializationStep()) + if (packetHeader.IsConnectionInitializationStep() && initialization.HasValue) { - ulong low = Lidgren.Network.NetBitWriter.ReadUInt32(data, 32, 8); - ulong high = Lidgren.Network.NetBitWriter.ReadUInt32(data, 32, 8 + 32); - ulong lobbyId = low + (high << 32); + var relayPacket = INetSerializableStruct.Read(inc); - Steam.SteamManager.JoinLobby(lobbyId, false); - IReadMessage inc = new ReadOnlyMessage(data, false, 1 + 8, dataLength - (1 + 8), ServerConnection); + SteamManager.JoinLobby(relayPacket.LobbyID, false); if (initializationStep != ConnectionInitialization.Success) { - incomingInitializationMessages.Add(inc); + incomingInitializationMessages.Add(new IncomingInitializationMessage + { + InitializationStep = initialization.Value, + Message = relayPacket.Message.GetReadMessage() + }); } } else if (packetHeader.IsHeartbeatMessage()) @@ -132,17 +137,14 @@ namespace Barotrauma.Networking } else if (packetHeader.IsDisconnectMessage()) { - IReadMessage inc = new ReadOnlyMessage(data, false, 1, dataLength - 1, ServerConnection); - string msg = inc.ReadString(); - Close(msg); - callbacks.OnDisconnectMessageReceived.Invoke(msg); + PeerDisconnectPacket packet = INetSerializableStruct.Read(inc); + Close(packet.Message); + callbacks.OnDisconnectMessageReceived.Invoke(packet.Message); } else { - UInt16 length = Lidgren.Network.NetBitWriter.ReadUInt16(data, 16, 8); - - IReadMessage inc = new ReadOnlyMessage(data, packetHeader.IsCompressed(), 3, length, ServerConnection); - incomingDataMessages.Add(inc); + var packet = INetSerializableStruct.Read(inc); + incomingDataMessages.Add(packet.GetReadMessage()); } } @@ -154,6 +156,7 @@ namespace Barotrauma.Networking { timeout -= deltaTime; } + heartbeatTimer -= deltaTime; if (initializationStep != ConnectionInitialization.Password && @@ -163,20 +166,20 @@ namespace Barotrauma.Networking connectionStatusTimer -= deltaTime; if (connectionStatusTimer <= 0.0) { - var state = Steamworks.SteamNetworking.GetP2PSessionState(hostSteamId.Value); - if (state == null) + if (Steamworks.SteamNetworking.GetP2PSessionState(hostSteamId.Value) is { } state) + { + if (state.P2PSessionError != Steamworks.P2PSessionError.None) + { + Close($"SteamP2P error code: {state.P2PSessionError}"); + callbacks.OnDisconnectMessageReceived.Invoke($"{DisconnectReason.SteamP2PError}/SteamP2P error code: {state.P2PSessionError}"); + } + } + else { Close("SteamP2P connection could not be established"); callbacks.OnDisconnectMessageReceived.Invoke(DisconnectReason.SteamP2PError.ToString()); } - else - { - if (state?.P2PSessionError != Steamworks.P2PSessionError.None) - { - Close($"SteamP2P error code: {state?.P2PSessionError}"); - callbacks.OnDisconnectMessageReceived.Invoke($"{DisconnectReason.SteamP2PError}/SteamP2P error code: {state?.P2PSessionError}"); - } - } + connectionStatusTimer = 1.0f; } } @@ -184,11 +187,12 @@ namespace Barotrauma.Networking for (int i = 0; i < 100; i++) { if (!Steamworks.SteamNetworking.IsP2PPacketAvailable()) { break; } + var packet = Steamworks.SteamNetworking.ReadP2PPacket(); - if (packet.HasValue) + if (packet is { SteamId: var steamId, Data: var data }) { - OnP2PData(packet?.SteamId ?? 0, packet?.Data, packet?.Data.Length ?? 0); - receivedBytes += packet?.Data.Length ?? 0; + OnP2PData(steamId, data, data.Length); + receivedBytes += data.Length; } } @@ -197,14 +201,13 @@ namespace Barotrauma.Networking if (heartbeatTimer < 0.0) { - IWriteMessage outMsg = new WriteOnlyMessage(); - outMsg.Write((byte)DeliveryMethod.Unreliable); - outMsg.Write((byte)PacketHeader.IsHeartbeatMessage); - - Steamworks.SteamNetworking.SendP2PPacket(hostSteamId.Value, outMsg.Buffer, outMsg.LengthBytes, 0, Steamworks.P2PSend.Unreliable); - sentBytes += outMsg.LengthBytes; - - heartbeatTimer = 5.0; + var headers = new PeerPacketHeaders + { + DeliveryMethod = DeliveryMethod.Unreliable, + PacketHeader = PacketHeader.IsHeartbeatMessage, + Initialization = null + }; + SendMsgInternal(headers, null); } if (timeout < 0.0) @@ -238,7 +241,7 @@ namespace Barotrauma.Networking } else { - foreach (IReadMessage inc in incomingInitializationMessages) + foreach (var inc in incomingInitializationMessages) { ReadConnectionInitializationStep(inc); } @@ -261,76 +264,40 @@ namespace Barotrauma.Networking { if (!isActive) { return; } - byte[] buf = new byte[msg.LengthBytes + 4]; - buf[0] = (byte)deliveryMethod; + byte[] bufAux = msg.PrepareForSending(compressPastThreshold, out bool isCompressed, out _); - byte[] bufAux = new byte[msg.LengthBytes]; - msg.PrepareForSending(ref bufAux, compressPastThreshold, out bool isCompressed, out int length); - - buf[1] = (byte)(isCompressed ? PacketHeader.IsCompressed : PacketHeader.None); - - buf[2] = (byte)(length & 0xff); - buf[3] = (byte)((length >> 8) & 0xff); - - Array.Copy(bufAux, 0, buf, 4, length); - - Steamworks.P2PSend sendType; - switch (deliveryMethod) + var headers = new PeerPacketHeaders { - case DeliveryMethod.Reliable: - case DeliveryMethod.ReliableOrdered: - //the documentation seems to suggest that the Reliable send type - //enforces packet order (TODO: verify) - sendType = Steamworks.P2PSend.Reliable; - break; - default: - sendType = Steamworks.P2PSend.Unreliable; - break; - } - - if (length + 8 >= MsgConstants.MTU) + DeliveryMethod = deliveryMethod, + PacketHeader = isCompressed ? PacketHeader.IsCompressed : PacketHeader.None, + Initialization = null + }; + var body = new PeerPacketMessage { - DebugConsole.Log("WARNING: message length comes close to exceeding MTU, forcing reliable send (" + length.ToString() + " bytes)"); - sendType = Steamworks.P2PSend.Reliable; - } + Buffer = bufAux + }; heartbeatTimer = 5.0; + // Using an extra local method here to reduce chance of error whenever we need to change this + void performSend() => SendMsgInternal(headers, body); #if DEBUG CoroutineManager.Invoke(() => - { - if (GameMain.Client == null) { return; } - if (Rand.Range(0.0f, 1.0f) < GameMain.Client.SimulatedLoss && sendType != Steamworks.P2PSend.Reliable) { return; } - int count = Rand.Range(0.0f, 1.0f) < GameMain.Client.SimulatedDuplicatesChance ? 2 : 1; - for (int i = 0; i < count; i++) { - Send(buf, length + 4, sendType); - } - }, - GameMain.Client.SimulatedMinimumLatency + Rand.Range(0.0f, GameMain.Client.SimulatedRandomLatency)); -#else - Send(buf, length + 4, sendType); -#endif - } + if (GameMain.Client == null) { return; } - private void Send(byte[] buf, int length, Steamworks.P2PSend sendType) - { - bool successSend = Steamworks.SteamNetworking.SendP2PPacket(hostSteamId.Value, buf, length + 4, 0, sendType); - sentBytes += length + 4; - if (!successSend) - { - if (sendType != Steamworks.P2PSend.Reliable) - { - DebugConsole.Log("WARNING: message couldn't be sent unreliably, forcing reliable send (" + length.ToString() + " bytes)"); - sendType = Steamworks.P2PSend.Reliable; - successSend = Steamworks.SteamNetworking.SendP2PPacket(hostSteamId.Value, buf, length + 4, 0, sendType); - sentBytes += length + 4; - } - if (!successSend) - { - DebugConsole.AddWarning("Failed to send message to remote peer! (" + length.ToString() + " bytes)"); - } - } + if (Rand.Range(0.0f, 1.0f) < GameMain.Client.SimulatedLoss && deliveryMethod is DeliveryMethod.Unreliable) { return; } + + int count = Rand.Range(0.0f, 1.0f) < GameMain.Client.SimulatedDuplicatesChance ? 2 : 1; + for (int i = 0; i < count; i++) + { + performSend(); + } + }, + GameMain.Client.SimulatedMinimumLatency + Rand.Range(0.0f, GameMain.Client.SimulatedRandomLatency)); +#else + performSend(); +#endif } public override void SendPassword(string password) @@ -338,20 +305,22 @@ namespace Barotrauma.Networking if (!isActive) { return; } if (initializationStep != ConnectionInitialization.Password) { return; } - IWriteMessage outMsg = new WriteOnlyMessage(); - outMsg.Write((byte)DeliveryMethod.Reliable); - outMsg.Write((byte)PacketHeader.IsConnectionInitializationStep); - outMsg.Write((byte)ConnectionInitialization.Password); - byte[] saltedPw = ServerSettings.SaltPassword(Encoding.UTF8.GetBytes(password), passwordSalt); - outMsg.Write((byte)saltedPw.Length); - outMsg.Write(saltedPw, 0, saltedPw.Length); - heartbeatTimer = 5.0; - Steamworks.SteamNetworking.SendP2PPacket(hostSteamId.Value, outMsg.Buffer, outMsg.LengthBytes, 0, Steamworks.P2PSend.Reliable); - sentBytes += outMsg.LengthBytes; + var headers = new PeerPacketHeaders + { + DeliveryMethod = DeliveryMethod.Reliable, + PacketHeader = PacketHeader.IsConnectionInitializationStep, + Initialization = ConnectionInitialization.Password + }; + var body = new ClientPeerPasswordPacket + { + Password = ServerSettings.SaltPassword(Encoding.UTF8.GetBytes(password), passwordSalt) + }; + + SendMsgInternal(headers, body); } - - public override void Close(string msg = null, bool disableReconnect = false) + + public override void Close(string? msg = null, bool disableReconnect = false) { if (!isActive) { return; } @@ -359,54 +328,59 @@ namespace Barotrauma.Networking isActive = false; - IWriteMessage outMsg = new WriteOnlyMessage(); - outMsg.Write((byte)DeliveryMethod.Reliable); - outMsg.Write((byte)PacketHeader.IsDisconnectMessage); - outMsg.Write(msg ?? "Disconnected"); + var headers = new PeerPacketHeaders + { + DeliveryMethod = DeliveryMethod.Reliable, + PacketHeader = PacketHeader.IsDisconnectMessage, + Initialization = null + }; + var body = new PeerDisconnectPacket + { + Message = msg ?? "Disconnected" + }; - try - { - Steamworks.SteamNetworking.SendP2PPacket(hostSteamId.Value, outMsg.Buffer, outMsg.LengthBytes, 0, Steamworks.P2PSend.Reliable); - sentBytes += outMsg.LengthBytes; - } - catch (Exception e) - { - DebugConsole.ThrowError("Failed to send a disconnect message to the server using SteamP2P.", e); - } + SendMsgInternal(headers, body); Thread.Sleep(100); Steamworks.SteamNetworking.ResetActions(); Steamworks.SteamNetworking.CloseP2PSessionWithUser(hostSteamId.Value); - steamAuthTicket?.Cancel(); steamAuthTicket = null; + steamAuthTicket?.Cancel(); + steamAuthTicket = null; callbacks.OnDisconnect.Invoke(disableReconnect); } - protected override void SendMsgInternal(DeliveryMethod deliveryMethod, IWriteMessage msg) + protected override void SendMsgInternal(PeerPacketHeaders headers, INetSerializableStruct? body) { - Steamworks.P2PSend sendType; - switch (deliveryMethod) + IWriteMessage msgToSend = new WriteOnlyMessage(); + msgToSend.WriteNetSerializableStruct(headers); + body?.Write(msgToSend); + ForwardToSteamP2P(msgToSend, headers.DeliveryMethod); + } + + private void ForwardToSteamP2P(IWriteMessage msg, DeliveryMethod deliveryMethod) + { + heartbeatTimer = 5.0; + int length = msg.LengthBytes; + + bool successSend = Steamworks.SteamNetworking.SendP2PPacket(hostSteamId.Value, msg.Buffer, length, 0, deliveryMethod.ToSteam()); + sentBytes += length; + + if (successSend) { return; } + + if (deliveryMethod is DeliveryMethod.Unreliable) { - case DeliveryMethod.Reliable: - case DeliveryMethod.ReliableOrdered: - //the documentation seems to suggest that the Reliable send type - //enforces packet order (TODO: verify) - sendType = Steamworks.P2PSend.Reliable; - break; - default: - sendType = Steamworks.P2PSend.Unreliable; - break; + DebugConsole.Log($"WARNING: message couldn't be sent unreliably, forcing reliable send ({length} bytes)"); + successSend = Steamworks.SteamNetworking.SendP2PPacket(hostSteamId.Value, msg.Buffer, length, 0, DeliveryMethod.Reliable.ToSteam()); + sentBytes += length; } - IWriteMessage msgToSend = new WriteOnlyMessage(); - msgToSend.Write((byte)deliveryMethod); - msgToSend.Write(msg.Buffer, 0, msg.LengthBytes); - - heartbeatTimer = 5.0; - Steamworks.SteamNetworking.SendP2PPacket(hostSteamId.Value, msgToSend.Buffer, msgToSend.LengthBytes, 0, sendType); - sentBytes += msg.LengthBytes; + if (!successSend) + { + DebugConsole.AddWarning($"Failed to send message to remote peer! ({length} bytes)"); + } } #if DEBUG @@ -416,4 +390,4 @@ namespace Barotrauma.Networking } #endif } -} +} \ No newline at end of file diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/Primitives/Peers/SteamP2POwnerPeer.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/Primitives/Peers/SteamP2POwnerPeer.cs index 0f6641332..23deeacce 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Networking/Primitives/Peers/SteamP2POwnerPeer.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/Primitives/Peers/SteamP2POwnerPeer.cs @@ -1,38 +1,46 @@ -using Barotrauma.Extensions; +#nullable enable using Barotrauma.Steam; using System; using System.Collections.Generic; using System.Threading; +using Barotrauma.Extensions; namespace Barotrauma.Networking { - class SteamP2POwnerPeer : ClientPeer + sealed class SteamP2POwnerPeer : ClientPeer { private bool isActive; private readonly SteamId selfSteamID; private UInt64 ownerKey64 => unchecked((UInt64)ownerKey.Fallback(0)); - private SteamId ReadSteamId(IReadMessage inc) - => new SteamId(inc.ReadUInt64() ^ ownerKey64); - private void WriteSteamId(IWriteMessage msg, SteamId val) - => msg.Write(val.Value ^ ownerKey64); - + private SteamId ReadSteamId(IReadMessage inc) => new SteamId(inc.ReadUInt64() ^ ownerKey64); + private void WriteSteamId(IWriteMessage msg, SteamId val) => msg.WriteUInt64(val.Value ^ ownerKey64); + private long sentBytes, receivedBytes; - class RemotePeer + private sealed class RemotePeer { - public SteamId SteamId; + public readonly SteamId SteamId; public Option OwnerSteamId; public double? DisconnectTime; public bool Authenticating; public bool Authenticated; - public class UnauthedMessage + public readonly struct UnauthedMessage { - public DeliveryMethod DeliveryMethod; - public IWriteMessage Message; + public readonly SteamId Sender; + public readonly byte[] Bytes; + public readonly int Length; + + public UnauthedMessage(SteamId sender, byte[] bytes) + { + Sender = sender; + Bytes = bytes; + Length = bytes.Length; + } } + public readonly List UnauthedMessages; public RemotePeer(SteamId steamId) @@ -45,9 +53,9 @@ namespace Barotrauma.Networking UnauthedMessages = new List(); } - } - List remotePeers; + + private List remotePeers = null!; public SteamP2POwnerPeer(Callbacks callbacks, int ownerKey) : base(new PipeEndpoint(), callbacks, Option.Some(ownerKey)) { @@ -84,8 +92,8 @@ namespace Barotrauma.Networking private void OnAuthChange(Steamworks.SteamId steamId, Steamworks.SteamId ownerId, Steamworks.AuthResponse status) { - RemotePeer remotePeer = remotePeers.Find(p => p.SteamId.Value == steamId); - DebugConsole.Log(steamId + " validation: " + status + ", " + (remotePeer != null)); + RemotePeer? remotePeer = remotePeers.Find(p => p.SteamId.Value == steamId); + DebugConsole.Log($"{steamId} validation: {status}, {remotePeer != null}"); if (remotePeer == null) { return; } @@ -93,36 +101,32 @@ namespace Barotrauma.Networking { if (status != Steamworks.AuthResponse.OK) { - DisconnectPeer(remotePeer, DisconnectReason.SteamAuthenticationFailed.ToString() + "/ Steam authentication status changed: " + status.ToString()); + DisconnectPeer(remotePeer, $"{DisconnectReason.SteamAuthenticationFailed}/ Steam authentication status changed: {status}"); } + return; } if (status == Steamworks.AuthResponse.OK) { - remotePeer.OwnerSteamId = Option.Some(new SteamId(ownerId)); + SteamId ownerSteamId = new SteamId(ownerId); + remotePeer.OwnerSteamId = Option.Some(ownerSteamId); remotePeer.Authenticated = true; remotePeer.Authenticating = false; - foreach (var msg in remotePeer.UnauthedMessages) + foreach (var unauthedMessage in remotePeer.UnauthedMessages) { - //rewrite the owner id before - //forwarding the messages to - //the server, since it's only - //known now - int prevBitPosition = msg.Message.BitPosition; - msg.Message.BitPosition = sizeof(ulong) * 8; - WriteSteamId(msg.Message, new SteamId(ownerId)); - msg.Message.BitPosition = prevBitPosition; - byte[] msgToSend = (byte[])msg.Message.Buffer.Clone(); - Array.Resize(ref msgToSend, msg.Message.LengthBytes); - ChildServerRelay.Write(msgToSend); + IWriteMessage msg = new WriteOnlyMessage(); + WriteSteamId(msg, unauthedMessage.Sender); + WriteSteamId(msg, ownerSteamId); + msg.WriteBytes(unauthedMessage.Bytes, 0, unauthedMessage.Length); + ForwardToServerProcess(msg); } + remotePeer.UnauthedMessages.Clear(); } else { - DisconnectPeer(remotePeer, DisconnectReason.SteamAuthenticationFailed.ToString() + "/ Steam authentication failed: " + status.ToString()); - return; + DisconnectPeer(remotePeer, $"{DisconnectReason.SteamAuthenticationFailed}/ Steam authentication failed: {status}"); } } @@ -138,58 +142,54 @@ namespace Barotrauma.Networking Steamworks.SteamNetworking.AcceptP2PSessionWithUser(steamId); //accept all connections, the server will figure things out later } - private void OnP2PData(ulong steamId, byte[] data, int dataLength, int _) + private void OnP2PData(ulong steamId, IReadMessage inc) { if (!isActive) { return; } - RemotePeer remotePeer = remotePeers.Find(p => p.SteamId.Value == steamId); + RemotePeer? remotePeer = remotePeers.Find(p => p.SteamId.Value == steamId); if (remotePeer == null) { return; } + if (remotePeer.DisconnectTime != null) { return; } - IWriteMessage outMsg = new WriteOnlyMessage(); - var steamUserId = new SteamId(steamId); - WriteSteamId(outMsg, steamUserId); - WriteSteamId(outMsg, remotePeer.OwnerSteamId.Fallback(steamUserId)); - outMsg.Write(data, 1, dataLength - 1); - - DeliveryMethod deliveryMethod = (DeliveryMethod)data[0]; - - PacketHeader packetHeader = (PacketHeader)data[1]; + var peerPacketHeaders = INetSerializableStruct.Read(inc); + + PacketHeader packetHeader = peerPacketHeaders.PacketHeader; if (!remotePeer.Authenticated && !remotePeer.Authenticating && packetHeader.IsConnectionInitializationStep()) { remotePeer.DisconnectTime = null; - IReadMessage authMsg = new ReadOnlyMessage(data, packetHeader.IsCompressed(), 2, dataLength - 2, null); - ConnectionInitialization initializationStep = (ConnectionInitialization)authMsg.ReadByte(); - if (initializationStep == ConnectionInitialization.SteamTicketAndVersion) + ConnectionInitialization initialization = peerPacketHeaders.Initialization ?? throw new Exception("Initialization step missing"); + if (initialization == ConnectionInitialization.SteamTicketAndVersion) { remotePeer.Authenticating = true; - - authMsg.ReadString(); //skip name - authMsg.ReadInt32(); //skip owner key - authMsg.ReadUInt64(); //skip steamid - UInt16 ticketLength = authMsg.ReadUInt16(); - byte[] ticket = authMsg.ReadBytes(ticketLength); - Steamworks.BeginAuthResult authSessionStartState = Steam.SteamManager.StartAuthSession(ticket, steamId); + var packet = INetSerializableStruct.Read(inc); + + packet.SteamAuthTicket.TryUnwrap(out byte[] ticket); + + Steamworks.BeginAuthResult authSessionStartState = SteamManager.StartAuthSession(ticket, steamId); if (authSessionStartState != Steamworks.BeginAuthResult.OK) { - DisconnectPeer(remotePeer, DisconnectReason.SteamAuthenticationFailed.ToString() + "/ Steam auth session failed to start: " + authSessionStartState.ToString()); + DisconnectPeer(remotePeer, $"{DisconnectReason.SteamAuthenticationFailed}/ Steam auth session failed to start: {authSessionStartState}"); return; } } } + var steamUserId = new SteamId(steamId); if (remotePeer.Authenticating) { - remotePeer.UnauthedMessages.Add(new RemotePeer.UnauthedMessage() { DeliveryMethod = deliveryMethod, Message = outMsg }); + remotePeer.UnauthedMessages.Add(new RemotePeer.UnauthedMessage(steamUserId, inc.Buffer)); } else { - byte[] msgToSend = (byte[])outMsg.Buffer.Clone(); - Array.Resize(ref msgToSend, outMsg.LengthBytes); - ChildServerRelay.Write(msgToSend); + IWriteMessage outMsg = new WriteOnlyMessage(); + WriteSteamId(outMsg, steamUserId); + WriteSteamId(outMsg, remotePeer.OwnerSteamId.Fallback(steamUserId)); + outMsg.WriteBytes(inc.Buffer, 0, inc.LengthBytes); + + ForwardToServerProcess(outMsg); } } @@ -201,7 +201,11 @@ namespace Barotrauma.Networking { Close(); var msgBox = new GUIMessageBox(TextManager.Get("ConnectionLost"), ChildServerRelay.CrashMessage); - msgBox.Buttons[0].OnClicked += (btn, obj) => { GameMain.MainMenuScreen.Select(); return false; }; + msgBox.Buttons[0].OnClicked += (btn, obj) => + { + GameMain.MainMenuScreen.Select(); + return false; + }; return; } @@ -216,11 +220,12 @@ namespace Barotrauma.Networking for (int i = 0; i < 100; i++) { if (!Steamworks.SteamNetworking.IsP2PPacketAvailable()) { break; } + var packet = Steamworks.SteamNetworking.ReadP2PPacket(); - if (packet.HasValue) + if (packet is { SteamId: var steamId, Data: var data }) { - OnP2PData(packet?.SteamId ?? 0, packet?.Data, packet?.Data.Length ?? 0, 0); - receivedBytes += packet?.Data.Length ?? 0; + OnP2PData(steamId, new ReadWriteMessage(data, 0, data.Length * 8, false)); + receivedBytes += data.Length; } } @@ -240,155 +245,144 @@ namespace Barotrauma.Networking if (!isActive) { return; } SteamId recipientSteamId = ReadSteamId(inc); - DeliveryMethod deliveryMethod = (DeliveryMethod)inc.ReadByte(); - int p2pDataStart = inc.BytePosition; - - PacketHeader packetHeader = (PacketHeader)inc.ReadByte(); + var peerPacketHeaders = INetSerializableStruct.Read(inc); if (recipientSteamId != selfSteamID) { - if (!packetHeader.IsServerMessage()) - { - DebugConsole.ThrowError("Received non-server message meant for remote peer"); - return; - } - - RemotePeer peer = remotePeers.Find(p => p.SteamId == recipientSteamId); - - if (peer == null) { return; } - - if (packetHeader.IsDisconnectMessage()) - { - DisconnectPeer(peer, inc.ReadString()); - return; - } - - Steamworks.P2PSend sendType; - switch (deliveryMethod) - { - case DeliveryMethod.Reliable: - case DeliveryMethod.ReliableOrdered: - //the documentation seems to suggest that the - //Reliable send type enforces packet order - sendType = Steamworks.P2PSend.Reliable; - break; - default: - sendType = Steamworks.P2PSend.Unreliable; - break; - } - - byte[] p2pData; - - if (packetHeader.IsConnectionInitializationStep()) - { - p2pData = new byte[inc.LengthBytes - p2pDataStart + 8]; - p2pData[0] = inc.Buffer[p2pDataStart]; - Lidgren.Network.NetBitWriter.WriteUInt64(SteamManager.CurrentLobbyID, 8 * 8, p2pData, 1 * 8); - Array.Copy(inc.Buffer, p2pDataStart+1, p2pData, 1 + 8, inc.LengthBytes - p2pDataStart - 1); - } - else - { - p2pData = new byte[inc.LengthBytes - p2pDataStart]; - Array.Copy(inc.Buffer, p2pDataStart, p2pData, 0, p2pData.Length); - - if (!packetHeader.IsHeartbeatMessage() && !packetHeader.IsDisconnectMessage()) - { - UInt16 length = Lidgren.Network.NetBitWriter.ReadUInt16(p2pData, 16, 8); - if (length > p2pData.Length - 2) - { - string errorMsg = $"Length written in message to send to client is larger than buffer size ({length} > {p2pData.Length - 2})"; - DebugConsole.ThrowError(errorMsg); - GameAnalyticsManager.AddErrorEventOnce( - "SteamP2POwnerPeerLengthValidationFail", - GameAnalyticsManager.ErrorSeverity.Error, - errorMsg); - } - } - } - - if (p2pData.Length + 4 >= MsgConstants.MTU) - { - DebugConsole.Log("WARNING: message length comes close to exceeding MTU, forcing reliable send (" + p2pData.Length.ToString() + " bytes)"); - sendType = Steamworks.P2PSend.Reliable; - } - - bool successSend = Steamworks.SteamNetworking.SendP2PPacket(recipientSteamId.Value, p2pData, p2pData.Length, 0, sendType); - sentBytes += p2pData.Length; - - if (!successSend) - { - if (sendType != Steamworks.P2PSend.Reliable) - { - DebugConsole.Log("WARNING: message couldn't be sent unreliably, forcing reliable send (" + p2pData.Length.ToString() + " bytes)"); - sendType = Steamworks.P2PSend.Reliable; - successSend = Steamworks.SteamNetworking.SendP2PPacket(recipientSteamId.Value, p2pData, p2pData.Length, 0, sendType); - sentBytes += p2pData.Length; - } - if (!successSend) - { - DebugConsole.AddWarning("Failed to send message to remote peer! (" + p2pData.Length.ToString() + " bytes)"); - } - } + HandleMessageForRemotePeer(peerPacketHeaders, recipientSteamId, inc); } else { - if (packetHeader.IsDisconnectMessage()) - { - DebugConsole.ThrowError("Received disconnect message from owned server"); - return; - } - if (!packetHeader.IsServerMessage()) - { - DebugConsole.ThrowError("Received non-server message from owned server"); - return; - } - if (packetHeader.IsHeartbeatMessage()) - { - return; //no timeout since we're using pipes, ignore this message - } - if (packetHeader.IsConnectionInitializationStep()) - { - IWriteMessage outMsg = new WriteOnlyMessage(); - WriteSteamId(outMsg, selfSteamID); - WriteSteamId(outMsg, selfSteamID); - outMsg.Write((byte)(PacketHeader.IsConnectionInitializationStep)); - outMsg.Write(GameMain.Client.Name); - - byte[] msgToSend = (byte[])outMsg.Buffer.Clone(); - Array.Resize(ref msgToSend, outMsg.LengthBytes); - ChildServerRelay.Write(msgToSend); - return; - } - else - { - if (initializationStep != ConnectionInitialization.Success) - { - callbacks.OnInitializationComplete.Invoke(); - initializationStep = ConnectionInitialization.Success; - } - UInt16 length = inc.ReadUInt16(); - IReadMessage msg = new ReadOnlyMessage(inc.Buffer, packetHeader.IsCompressed(), inc.BytePosition, length, ServerConnection); - callbacks.OnMessageReceived.Invoke(msg); - - return; - } + HandleMessageForOwner(peerPacketHeaders, inc); } } + private static byte[] GetRemainingBytes(IReadMessage msg) + { + return msg.Buffer[msg.BytePosition..msg.LengthBytes]; + } + + private void HandleMessageForRemotePeer(PeerPacketHeaders peerPacketHeaders, SteamId recipientSteamId, IReadMessage inc) + { + var (deliveryMethod, packetHeader, initialization) = peerPacketHeaders; + + if (!packetHeader.IsServerMessage()) + { + DebugConsole.ThrowError("Received non-server message meant for remote peer"); + return; + } + + RemotePeer? peer = remotePeers.Find(p => p.SteamId == recipientSteamId); + if (peer is null) { return; } + + if (packetHeader.IsDisconnectMessage()) + { + var packet = INetSerializableStruct.Read(inc); + DisconnectPeer(peer, packet.Message); + return; + } + + IWriteMessage outMsg = new WriteOnlyMessage(); + + outMsg.WriteNetSerializableStruct(new PeerPacketHeaders + { + DeliveryMethod = deliveryMethod, + PacketHeader = packetHeader, + Initialization = initialization + }); + + if (packetHeader.IsConnectionInitializationStep()) + { + var initRelayPacket = new SteamP2PInitializationRelayPacket + { + LobbyID = SteamManager.CurrentLobbyID, + Message = new PeerPacketMessage + { + Buffer = GetRemainingBytes(inc) + } + }; + + outMsg.WriteNetSerializableStruct(initRelayPacket); + } + else + { + byte[] userMessage = GetRemainingBytes(inc); + outMsg.WriteBytes(userMessage, 0, userMessage.Length); + } + + ForwardToRemotePeer(deliveryMethod, recipientSteamId, outMsg); + } + + private void HandleMessageForOwner(PeerPacketHeaders peerPacketHeaders, IReadMessage inc) + { + var (_, packetHeader, _) = peerPacketHeaders; + + if (packetHeader.IsDisconnectMessage()) + { + DebugConsole.ThrowError("Received disconnect message from owned server"); + return; + } + + if (!packetHeader.IsServerMessage()) + { + DebugConsole.ThrowError("Received non-server message from owned server"); + return; + } + + if (packetHeader.IsHeartbeatMessage()) + { + return; //no timeout since we're using pipes, ignore this message + } + + if (packetHeader.IsConnectionInitializationStep()) + { + IWriteMessage outMsg = new WriteOnlyMessage(); + WriteSteamId(outMsg, selfSteamID); + WriteSteamId(outMsg, selfSteamID); + outMsg.WriteNetSerializableStruct(new PeerPacketHeaders + { + DeliveryMethod = DeliveryMethod.Reliable, + PacketHeader = PacketHeader.IsConnectionInitializationStep, + Initialization = ConnectionInitialization.SteamTicketAndVersion + }); + outMsg.WriteNetSerializableStruct(new SteamP2PInitializationOwnerPacket + { + OwnerName = GameMain.Client.Name + }); + ForwardToServerProcess(outMsg); + } + else + { + if (initializationStep != ConnectionInitialization.Success) + { + callbacks.OnInitializationComplete.Invoke(); + initializationStep = ConnectionInitialization.Success; + } + + PeerPacketMessage packet = INetSerializableStruct.Read(inc); + IReadMessage msg = new ReadOnlyMessage(packet.Buffer, packetHeader.IsCompressed(), 0, packet.Length, ServerConnection); + callbacks.OnMessageReceived.Invoke(msg); + } + } + private void DisconnectPeer(RemotePeer peer, string msg) { if (!string.IsNullOrWhiteSpace(msg)) { - if (peer.DisconnectTime == null) - { - peer.DisconnectTime = Timing.TotalTime + 1.0; - } + peer.DisconnectTime ??= Timing.TotalTime + 1.0; IWriteMessage outMsg = new WriteOnlyMessage(); - outMsg.Write((byte)(PacketHeader.IsServerMessage | PacketHeader.IsDisconnectMessage)); - outMsg.Write(msg); - + outMsg.WriteNetSerializableStruct(new PeerPacketHeaders + { + DeliveryMethod = DeliveryMethod.Reliable, + PacketHeader = PacketHeader.IsServerMessage | PacketHeader.IsDisconnectMessage + }); + outMsg.WriteNetSerializableStruct(new PeerDisconnectPacket + { + Message = msg + }); + Steamworks.SteamNetworking.SendP2PPacket(peer.SteamId.Value, outMsg.Buffer, outMsg.LengthBytes, 0, Steamworks.P2PSend.Reliable); sentBytes += outMsg.LengthBytes; } @@ -406,10 +400,10 @@ namespace Barotrauma.Networking public override void SendPassword(string password) { - return; //owner doesn't send passwords + //owner doesn't send passwords } - public override void Close(string msg = null, bool disableReconnect = false) + public override void Close(string? msg = null, bool disableReconnect = false) { if (!isActive) { return; } @@ -441,25 +435,62 @@ namespace Barotrauma.Networking if (!isActive) { return; } IWriteMessage msgToSend = new WriteOnlyMessage(); - byte[] msgData = new byte[msg.LengthBytes]; - msg.PrepareForSending(ref msgData, compressPastThreshold, out bool isCompressed, out int length); + byte[] msgData = msg.PrepareForSending(compressPastThreshold, out bool isCompressed, out _); WriteSteamId(msgToSend, selfSteamID); WriteSteamId(msgToSend, selfSteamID); - msgToSend.Write((byte)(isCompressed ? PacketHeader.IsCompressed : PacketHeader.None)); - msgToSend.Write((UInt16)length); - msgToSend.Write(msgData, 0, length); - - byte[] bufToSend = (byte[])msgToSend.Buffer.Clone(); - Array.Resize(ref bufToSend, msgToSend.LengthBytes); - ChildServerRelay.Write(bufToSend); + msgToSend.WriteNetSerializableStruct(new PeerPacketHeaders + { + DeliveryMethod = deliveryMethod, + PacketHeader = isCompressed ? PacketHeader.IsCompressed : PacketHeader.None + }); + msgToSend.WriteNetSerializableStruct(new PeerPacketMessage + { + Buffer = msgData + }); + ForwardToServerProcess(msgToSend); } - protected override void SendMsgInternal(DeliveryMethod deliveryMethod, IWriteMessage msg) + protected override void SendMsgInternal(PeerPacketHeaders headers, INetSerializableStruct? body) { //not currently used by SteamP2POwnerPeer throw new NotImplementedException(); } + private static void ForwardToServerProcess(IWriteMessage msg) + { + byte[] bufToSend = new byte[msg.LengthBytes]; + msg.Buffer[..msg.LengthBytes].CopyTo(bufToSend.AsSpan()); + ChildServerRelay.Write(bufToSend); + } + + private void ForwardToRemotePeer(DeliveryMethod deliveryMethod, SteamId recipent, IWriteMessage outMsg) + { + byte[] buf = outMsg.PrepareForSending(compressPastThreshold: false, out _, out int length); + + if (length + 4 >= MsgConstants.MTU) + { + DebugConsole.Log($"WARNING: message length comes close to exceeding MTU, forcing reliable send ({length} bytes)"); + deliveryMethod = DeliveryMethod.Reliable; + } + + bool successSend = Steamworks.SteamNetworking.SendP2PPacket(recipent.Value, buf, length, 0, deliveryMethod.ToSteam()); + sentBytes += length; + + if (successSend) { return; } + + if (deliveryMethod is DeliveryMethod.Unreliable) + { + DebugConsole.Log($"WARNING: message couldn't be sent unreliably, forcing reliable send ({length} bytes)"); + successSend = Steamworks.SteamNetworking.SendP2PPacket(recipent.Value, buf, length, 0, DeliveryMethod.Reliable.ToSteam()); + sentBytes += length; + } + + if (!successSend) + { + DebugConsole.AddWarning($"Failed to send message to remote peer! ({length} bytes)"); + } + } + #if DEBUG public override void ForceTimeOut() { @@ -467,4 +498,4 @@ namespace Barotrauma.Networking } #endif } -} +} \ No newline at end of file diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/RespawnManager.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/RespawnManager.cs index 092f871d4..30a3b78a8 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Networking/RespawnManager.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/RespawnManager.cs @@ -44,14 +44,19 @@ namespace Barotrauma.Networking if (!UseRespawnPrompt) { return; } if (CoroutineManager.IsCoroutineRunning(respawnPromptCoroutine) || GUIMessageBox.MessageBoxes.Any(mb => mb.UserData as string == "respawnquestionprompt")) { - return; + return; } respawnPromptCoroutine = CoroutineManager.Invoke(() => { if (Character.Controlled != null || (!(GameMain.GameSession?.IsRunning ?? false))) { return; } + + LocalizedString text = + TextManager.GetWithVariable("respawnskillpenalty", "[percentage]", ((int)(SkillReductionOnDeath * 100)).ToString()) + + "\n\n" + TextManager.Get("respawnquestionprompt"); + var respawnPrompt = new GUIMessageBox( - TextManager.Get("tutorial.tryagainheader"), TextManager.Get("respawnquestionprompt"), + TextManager.Get("tutorial.tryagainheader"), text, new LocalizedString[] { TextManager.Get("respawnquestionpromptrespawn"), TextManager.Get("respawnquestionpromptwait") }) { UserData = "respawnquestionprompt" diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerInfo.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerInfo.cs index acfa28618..93e854e66 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerInfo.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerInfo.cs @@ -348,7 +348,7 @@ namespace Barotrauma.Networking ServerName = element.GetAttributeString("ServerName", ""), ServerMessage = element.GetAttributeString("ServerMessage", ""), Endpoint = endpoint, - QueryPort = element.GetAttributeInt("QueryPort", 0), + QueryPort = !string.IsNullOrEmpty(element.GetAttributeString("QueryPort", string.Empty)) ? element.GetAttributeInt("QueryPort", 0) : 0, GameMode = element.GetAttributeIdentifier("GameMode", Identifier.Empty), GameVersion = element.GetAttributeString("GameVersion", ""), MaxPlayers = Math.Min(element.GetAttributeInt("MaxPlayers", 0), NetConfig.MaxPlayers), diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerSettings.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerSettings.cs index 26cc5098c..018a897a3 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerSettings.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerSettings.cs @@ -182,9 +182,9 @@ namespace Barotrauma.Networking IWriteMessage outMsg = new WriteOnlyMessage(); - outMsg.Write((byte)ClientPacketHeader.SERVER_SETTINGS); + outMsg.WriteByte((byte)ClientPacketHeader.SERVER_SETTINGS); - outMsg.Write((byte)dataToSend); + outMsg.WriteByte((byte)dataToSend); if (dataToSend.HasFlag(NetFlags.Name)) { @@ -192,7 +192,7 @@ namespace Barotrauma.Networking { ServerName = GameMain.NetLobbyScreen.ServerName.Text; } - outMsg.Write(ServerName); + outMsg.WriteString(ServerName); } if (dataToSend.HasFlag(NetFlags.Message)) @@ -201,7 +201,7 @@ namespace Barotrauma.Networking { ServerMessageText = GameMain.NetLobbyScreen.ServerMessage.Text; } - outMsg.Write(ServerMessageText); + outMsg.WriteString(ServerMessageText); } if (dataToSend.HasFlag(NetFlags.Properties)) @@ -213,15 +213,15 @@ namespace Barotrauma.Networking UInt32 count = (UInt32)changedProperties.Count(); bool changedMonsterSettings = tempMonsterEnabled != null && tempMonsterEnabled.Any(p => p.Value != MonsterEnabled[p.Key]); - outMsg.Write(count); + outMsg.WriteUInt32(count); foreach (KeyValuePair prop in changedProperties) { DebugConsole.NewMessage(prop.Value.Name.Value, Color.Lime); - outMsg.Write(prop.Key); + outMsg.WriteUInt32(prop.Key); prop.Value.Write(outMsg, prop.Value.GUIComponentValue); } - outMsg.Write(changedMonsterSettings); outMsg.WritePadBits(); + outMsg.WriteBoolean(changedMonsterSettings); outMsg.WritePadBits(); if (changedMonsterSettings) WriteMonsterEnabled(outMsg, tempMonsterEnabled); BanList.ClientAdminWrite(outMsg); } @@ -235,23 +235,23 @@ namespace Barotrauma.Networking { outMsg.WriteRangedInteger(missionTypeOr ?? (int)Barotrauma.MissionType.None, 0, (int)Barotrauma.MissionType.All); outMsg.WriteRangedInteger(missionTypeAnd ?? (int)Barotrauma.MissionType.All, 0, (int)Barotrauma.MissionType.All); - outMsg.Write((byte)(traitorSetting + 1)); - outMsg.Write((byte)(botCount + 1)); - outMsg.Write((byte)(botSpawnMode + 1)); + outMsg.WriteByte((byte)(traitorSetting + 1)); + outMsg.WriteByte((byte)(botCount + 1)); + outMsg.WriteByte((byte)(botSpawnMode + 1)); - outMsg.Write(levelDifficulty ?? -1000.0f); + outMsg.WriteSingle(levelDifficulty ?? -1000.0f); - outMsg.Write(useRespawnShuttle ?? UseRespawnShuttle); + outMsg.WriteBoolean(useRespawnShuttle ?? UseRespawnShuttle); - outMsg.Write(autoRestart != null); - outMsg.Write(autoRestart ?? false); + outMsg.WriteBoolean(autoRestart != null); + outMsg.WriteBoolean(autoRestart ?? false); outMsg.WritePadBits(); } if (dataToSend.HasFlag(NetFlags.LevelSeed)) { - outMsg.Write(GameMain.NetLobbyScreen.SeedBox.Text); + outMsg.WriteString(GameMain.NetLobbyScreen.SeedBox.Text); } GameMain.Client.ClientPeer.Send(outMsg, DeliveryMethod.Reliable); diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/Voip/VoipCapture.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/Voip/VoipCapture.cs index 617e7d40f..bfbba0c7f 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Networking/Voip/VoipCapture.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/Voip/VoipCapture.cs @@ -4,7 +4,6 @@ using Microsoft.Xna.Framework; using OpenAL; using System; using System.Collections.Generic; -using System.Diagnostics; using System.Linq; using System.Runtime.InteropServices; using System.Threading; @@ -22,13 +21,13 @@ namespace Barotrauma.Networking public static IReadOnlyList CaptureDeviceNames => Alc.GetStringList(IntPtr.Zero, OpenAL.Alc.CaptureDeviceSpecifier); - private IntPtr captureDevice; + private readonly IntPtr captureDevice; private Thread captureThread; private bool capturing; - private OpusEncoder encoder; + private readonly OpusEncoder encoder; public double LastdB { @@ -171,8 +170,8 @@ namespace Barotrauma.Networking } IntPtr nativeBuffer; - short[] uncompressedBuffer = new short[VoipConfig.BUFFER_SIZE]; - short[] prevUncompressedBuffer = new short[VoipConfig.BUFFER_SIZE]; + readonly short[] uncompressedBuffer = new short[VoipConfig.BUFFER_SIZE]; + readonly short[] prevUncompressedBuffer = new short[VoipConfig.BUFFER_SIZE]; bool prevCaptured = true; int captureTimer; @@ -227,16 +226,20 @@ namespace Barotrauma.Networking bool allowEnqueue = overrideSound != null; if (GameMain.WindowActive && SettingsMenu.Instance is null) { - bool usingActiveMode = PlayerInput.KeyDown(InputType.Voice); bool usingLocalMode = PlayerInput.KeyDown(InputType.LocalVoice); bool usingRadioMode = PlayerInput.KeyDown(InputType.RadioVoice); - bool pttDown = (usingActiveMode || usingLocalMode || usingRadioMode) && GUI.KeyboardDispatcher.Subscriber == null; - if (pttDown || captureTimer <= 0) - { - ForceLocal = (usingActiveMode && GameMain.ActiveChatMode == ChatMode.Local) || usingLocalMode; - } if (GameSettings.CurrentConfig.Audio.VoiceSetting == VoiceMode.Activity) { + bool pttDown = (usingLocalMode || usingRadioMode) && GUI.KeyboardDispatcher.Subscriber == null; + if (pttDown) + { + ForceLocal = usingLocalMode; + } + //in Activity mode, we default to the active mode UNLESS a specific ptt key is held + else + { + ForceLocal = GameMain.ActiveChatMode == ChatMode.Local; + } if (dB > GameSettings.CurrentConfig.Audio.NoiseGateThreshold) { allowEnqueue = true; @@ -244,6 +247,13 @@ namespace Barotrauma.Networking } else if (GameSettings.CurrentConfig.Audio.VoiceSetting == VoiceMode.PushToTalk) { + //in push-to-talk mode, InputType.Voice uses the active chat mode + bool usingActiveMode = PlayerInput.KeyDown(InputType.Voice); + bool pttDown = (usingActiveMode || usingLocalMode || usingRadioMode) && GUI.KeyboardDispatcher.Subscriber == null; + if (pttDown || captureTimer <= 0) + { + ForceLocal = (usingActiveMode && GameMain.ActiveChatMode == ChatMode.Local) || usingLocalMode; + } if (pttDown) { allowEnqueue = true; diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/Voip/VoipClient.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/Voip/VoipClient.cs index eabc6004a..934820e0d 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Networking/Voip/VoipClient.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/Voip/VoipClient.cs @@ -72,8 +72,8 @@ namespace Barotrauma.Networking { IWriteMessage msg = new WriteOnlyMessage(); - msg.Write((byte)ClientPacketHeader.VOICE); - msg.Write((byte)VoipCapture.Instance.QueueID); + msg.WriteByte((byte)ClientPacketHeader.VOICE); + msg.WriteByte((byte)VoipCapture.Instance.QueueID); VoipCapture.Instance.Write(msg); netClient.Send(msg, DeliveryMethod.Unreliable); diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/Voting.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/Voting.cs index 38c935426..b2f044280 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Networking/Voting.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/Voting.cs @@ -113,35 +113,35 @@ namespace Barotrauma public void ClientWrite(IWriteMessage msg, VoteType voteType, object data) { - msg.Write((byte)voteType); + msg.WriteByte((byte)voteType); switch (voteType) { case VoteType.Sub: if (!(data is SubmarineInfo sub)) { return; } - msg.Write(sub.EqualityCheckVal); + msg.WriteInt32(sub.EqualityCheckVal); if (sub.EqualityCheckVal == 0) { //sub doesn't exist client-side, use hash to let the server know which one we voted for - msg.Write(sub.MD5Hash.StringRepresentation); + msg.WriteString(sub.MD5Hash.StringRepresentation); } break; case VoteType.Mode: if (!(data is GameModePreset gameMode)) { return; } - msg.Write(gameMode.Identifier); + msg.WriteIdentifier(gameMode.Identifier); break; case VoteType.EndRound: if (!(data is bool)) { return; } - msg.Write((bool)data); + msg.WriteBoolean((bool)data); break; case VoteType.Kick: if (!(data is Client votedClient)) { return; } - msg.Write(votedClient.SessionId); + msg.WriteByte(votedClient.SessionId); break; case VoteType.StartRound: if (!(data is bool)) { return; } - msg.Write((bool)data); + msg.WriteBoolean((bool)data); break; case VoteType.PurchaseAndSwitchSub: case VoteType.PurchaseSub: @@ -149,22 +149,22 @@ namespace Barotrauma if (data is (SubmarineInfo voteSub, bool transferItems)) { //initiate sub vote - msg.Write(true); - msg.Write(voteSub.Name); - msg.Write(transferItems); + msg.WriteBoolean(true); + msg.WriteString(voteSub.Name); + msg.WriteBoolean(transferItems); } else { // vote if (!(data is int)) { return; } - msg.Write(false); - msg.Write((int)data); + msg.WriteBoolean(false); + msg.WriteInt32((int)data); } break; case VoteType.TransferMoney: if (!(data is int)) { return; } - msg.Write(false); //not initiating a vote - msg.Write((int)data); + msg.WriteBoolean(false); //not initiating a vote + msg.WriteInt32((int)data); break; } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/WhiteList.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/WhiteList.cs deleted file mode 100644 index 554d32169..000000000 --- a/Barotrauma/BarotraumaClient/ClientSource/Networking/WhiteList.cs +++ /dev/null @@ -1,245 +0,0 @@ -using Microsoft.Xna.Framework; -using System; -using System.Collections.Generic; -using System.Linq; - -namespace Barotrauma.Networking -{ - partial class WhiteListedPlayer - { - public WhiteListedPlayer(string name, UInt16 identifier, string ip) - { - Name = name; - IP = ip; - - UniqueIdentifier = identifier; - } - } - - partial class WhiteList - { - private GUIComponent whitelistFrame; - - private GUITextBox nameBox; - private GUITextBox ipBox; - private GUIButton addNewButton; - - public class LocalAdded - { - public string Name; - public string IP; - }; - - public bool localEnabled; - public List localRemoved = new List(); - public List localAdded = new List(); - - public GUIComponent CreateWhiteListFrame(GUIComponent parent) - { - if (whitelistFrame != null) - { - whitelistFrame.Parent.ClearChildren(); - whitelistFrame = null; - } - - whitelistFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.95f), parent.RectTransform, Anchor.Center)) - { - Stretch = true, - RelativeSpacing = 0.02f - }; - - var enabledTick = new GUITickBox(new RectTransform(new Vector2(0.1f, 0.1f), whitelistFrame.RectTransform), TextManager.Get("WhiteListEnabled")) - { - Selected = localEnabled, - UpdateOrder = 1, - OnSelected = (GUITickBox box) => - { - nameBox.Enabled = box.Selected; - ipBox.Enabled = box.Selected; - addNewButton.Enabled = box.Selected && !string.IsNullOrEmpty(ipBox.Text) && !string.IsNullOrEmpty(nameBox.Text); - localEnabled = box.Selected; - return true; - } - }; - - var listBox = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.7f), whitelistFrame.RectTransform)); - foreach (WhiteListedPlayer wlp in whitelistedPlayers) - { - if (localRemoved.Contains(wlp.UniqueIdentifier)) continue; - string blockText = wlp.Name; - if (!string.IsNullOrWhiteSpace(wlp.IP)) blockText += " (" + wlp.IP + ")"; - GUITextBlock textBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.1f), listBox.Content.RectTransform), - blockText) - { - UserData = wlp - }; - - var removeButton = new GUIButton(new RectTransform(new Vector2(0.3f, 0.8f), textBlock.RectTransform, Anchor.CenterRight), - TextManager.Get("WhiteListRemove"), style: "GUIButtonSmall") - { - UserData = wlp, - OnClicked = RemoveFromWhiteList - }; - } - - foreach (LocalAdded lad in localAdded) - { - string blockText = lad.Name; - if (!string.IsNullOrWhiteSpace(lad.IP)) blockText += " (" + lad.IP + ")"; - GUITextBlock textBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.1f), listBox.Content.RectTransform), - blockText) - { - UserData = lad - }; - - var removeButton = new GUIButton(new RectTransform(new Vector2(0.3f, 0.8f), textBlock.RectTransform, Anchor.CenterRight), - TextManager.Get("WhiteListRemove"), style: "GUIButtonSmall") - { - UserData = lad, - OnClicked = RemoveFromWhiteList - }; - } - - foreach (GUIComponent c in listBox.Content.Children) - { - c.RectTransform.MinSize = new Point(0, Math.Max((int)(20 * GUI.Scale), c.RectTransform.Children.Max(c2 => c2.MinSize.Y))); - } - - var nameArea = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), whitelistFrame.RectTransform), isHorizontal: true) - { - Stretch = true, - RelativeSpacing = 0.05f - }; - new GUITextBlock(new RectTransform(new Vector2(0.3f, 1.0f), nameArea.RectTransform), TextManager.Get("WhiteListName")); - nameBox = new GUITextBox(new RectTransform(new Vector2(0.7f, 1.0f), nameArea.RectTransform), ""); - nameBox.OnTextChanged += (textBox, text) => - { - addNewButton.Enabled = !string.IsNullOrEmpty(ipBox.Text) && !string.IsNullOrEmpty(nameBox.Text); - return true; - }; - nameArea.RectTransform.MinSize = new Point(0, nameBox.RectTransform.MinSize.Y); - - var ipArea = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), whitelistFrame.RectTransform), isHorizontal: true) - { - Stretch = true, - RelativeSpacing = 0.05f - }; - new GUITextBlock(new RectTransform(new Vector2(0.3f, 1.0f), ipArea.RectTransform), TextManager.Get("WhiteListIP")); - ipBox = new GUITextBox(new RectTransform(new Vector2(0.7f, 1.0f), ipArea.RectTransform), ""); - ipBox.OnTextChanged += (textBox, text) => - { - addNewButton.Enabled = !string.IsNullOrEmpty(ipBox.Text) && !string.IsNullOrEmpty(nameBox.Text); - return true; - }; - ipBox.RectTransform.MinSize = new Point(0, ipBox.RectTransform.MinSize.Y); - - addNewButton = new GUIButton(new RectTransform(new Vector2(0.5f, 0.1f), whitelistFrame.RectTransform), TextManager.Get("WhiteListAdd"), style: "GUIButtonSmall") - { - OnClicked = AddToWhiteList - }; - GUITextBlock.AutoScaleAndNormalize(addNewButton.TextBlock); - - nameBox.Enabled = localEnabled; - ipBox.Enabled = localEnabled; - addNewButton.Enabled = false; - - return parent; - } - - private bool RemoveFromWhiteList(GUIButton button, object obj) - { - if (obj is WhiteListedPlayer) - { - if (!(obj is WhiteListedPlayer wlp)) return false; - if (!localRemoved.Contains(wlp.UniqueIdentifier)) localRemoved.Add(wlp.UniqueIdentifier); - } - else if (obj is LocalAdded) - { - if (!(obj is LocalAdded lad)) return false; - if (localAdded.Contains(lad)) localAdded.Remove(lad); - } - - if (whitelistFrame != null) - { - CreateWhiteListFrame(whitelistFrame.Parent); - } - - return true; - } - - private bool AddToWhiteList(GUIButton button, object obj) - { - if (string.IsNullOrWhiteSpace(nameBox.Text)) return false; - if (whitelistedPlayers.Any(x => x.Name.ToLower() == nameBox.Text.ToLower() && x.IP == ipBox.Text)) return false; - - if (!localAdded.Any(p => p.IP == ipBox.Text)) localAdded.Add(new LocalAdded() { Name = nameBox.Text, IP = ipBox.Text }); - - if (whitelistFrame != null) - { - CreateWhiteListFrame(whitelistFrame.Parent); - } - return true; - } - - public void ClientAdminRead(IReadMessage incMsg) - { - bool hasPermission = incMsg.ReadBoolean(); - if (!hasPermission) - { - incMsg.ReadPadBits(); - return; - } - - bool isOwner = incMsg.ReadBoolean(); - localEnabled = incMsg.ReadBoolean(); - Enabled = localEnabled; - incMsg.ReadPadBits(); - - whitelistedPlayers.Clear(); - UInt32 bannedPlayerCount = incMsg.ReadVariableUInt32(); - for (int i = 0; i < (int)bannedPlayerCount; i++) - { - string name = incMsg.ReadString(); - UInt16 uniqueIdentifier = incMsg.ReadUInt16(); - - string ip = ""; - if (isOwner) - { - ip = incMsg.ReadString(); - } - else - { - ip = "IP concealed by host"; - } - whitelistedPlayers.Add(new WhiteListedPlayer(name, uniqueIdentifier, ip)); - } - - if (whitelistFrame != null) - { - CreateWhiteListFrame(whitelistFrame.Parent); - } - } - - public void ClientAdminWrite(IWriteMessage outMsg) - { - outMsg.Write(localEnabled); - outMsg.WritePadBits(); - - outMsg.Write((UInt16)localRemoved.Count); - foreach (UInt16 uniqueId in localRemoved) - { - outMsg.Write(uniqueId); - } - - outMsg.Write((UInt16)localAdded.Count); - foreach (LocalAdded lad in localAdded) - { - outMsg.Write(lad.Name); - outMsg.Write(lad.IP); //TODO: ENCRYPT - } - - localRemoved.Clear(); - localAdded.Clear(); - } - } -} diff --git a/Barotrauma/BarotraumaClient/ClientSource/Screens/CampaignSetupUI/CampaignSetupUI.cs b/Barotrauma/BarotraumaClient/ClientSource/Screens/CampaignSetupUI/CampaignSetupUI.cs index 0b33e0a5a..46dfef1ef 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Screens/CampaignSetupUI/CampaignSetupUI.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Screens/CampaignSetupUI/CampaignSetupUI.cs @@ -61,7 +61,8 @@ namespace Barotrauma UserData = saveInfo.FilePath }; - var nameText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), saveFrame.RectTransform), Path.GetFileNameWithoutExtension(saveInfo.FilePath)) + var nameText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), saveFrame.RectTransform), Path.GetFileNameWithoutExtension(saveInfo.FilePath), + textColor: GUIStyle.TextColorBright) { CanBeFocused = false }; @@ -85,7 +86,6 @@ namespace Barotrauma UserData = saveInfo.FilePath }; - string saveTimeStr = string.Empty; if (saveInfo.SaveTime > 0) { @@ -187,9 +187,9 @@ namespace Barotrauma SettingValue startingSetInput = CreateSelectionCarousel(settingsList.Content, TextManager.Get("startitemset"), TextManager.Get("startitemsettooltip"), prevStartingSet, verticalSize, startingSetOptions); ImmutableArray> fundOptions = ImmutableArray.Create( - new SettingCarouselElement(StartingBalanceAmount.High, "startingfunds.high"), + new SettingCarouselElement(StartingBalanceAmount.Low, "startingfunds.low"), new SettingCarouselElement(StartingBalanceAmount.Medium, "startingfunds.medium"), - new SettingCarouselElement(StartingBalanceAmount.Low, "startingfunds.low") + new SettingCarouselElement(StartingBalanceAmount.High, "startingfunds.high") ); SettingCarouselElement prevStartingFund = fundOptions.FirstOrNull(element => element.Value == prevSettings.StartingBalanceAmount) ?? fundOptions[1]; diff --git a/Barotrauma/BarotraumaClient/ClientSource/Screens/CampaignSetupUI/MultiPlayerCampaignSetupUI.cs b/Barotrauma/BarotraumaClient/ClientSource/Screens/CampaignSetupUI/MultiPlayerCampaignSetupUI.cs index 0c297bbf1..70a8bbd8c 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Screens/CampaignSetupUI/MultiPlayerCampaignSetupUI.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Screens/CampaignSetupUI/MultiPlayerCampaignSetupUI.cs @@ -11,7 +11,9 @@ namespace Barotrauma class MultiPlayerCampaignSetupUI : CampaignSetupUI { private GUIButton deleteMpSaveButton; - + + private int prevInitialMoney; + public MultiPlayerCampaignSetupUI(GUIComponent newGameContainer, GUIComponent loadGameContainer, List saveFiles = null) : base(newGameContainer, loadGameContainer) { @@ -133,6 +135,7 @@ namespace Barotrauma StartButton.RectTransform.MaxSize = RectTransform.MaxPoint; StartButton.Children.ForEach(c => c.RectTransform.MaxSize = RectTransform.MaxPoint); + prevInitialMoney = 8000; InitialMoneyText = new GUITextBlock(new RectTransform(new Vector2(0.6f, 1f), buttonContainer.RectTransform), "", font: GUIStyle.SmallFont, textColor: GUIStyle.Green) { TextGetter = () => @@ -142,11 +145,17 @@ namespace Barotrauma { initialMoney = definition.GetInt(elements.StartingFunds.GetValue().ToIdentifier()); } + if (prevInitialMoney != initialMoney) + { + GameMain.NetLobbyScreen.RefreshEnabledElements(); + prevInitialMoney = initialMoney; + } if (GameMain.NetLobbyScreen.SelectedSub != null) { initialMoney -= GameMain.NetLobbyScreen.SelectedSub.Price; } - initialMoney = Math.Max(initialMoney, MultiPlayerCampaign.MinimumInitialMoney); + initialMoney = Math.Max(initialMoney, 0); + return TextManager.GetWithVariable("campaignstartingmoney", "[money]", string.Format(CultureInfo.InvariantCulture, "{0:N0}", initialMoney)); } }; diff --git a/Barotrauma/BarotraumaClient/ClientSource/Screens/CampaignSetupUI/SinglePlayerCampaignSetupUI.cs b/Barotrauma/BarotraumaClient/ClientSource/Screens/CampaignSetupUI/SinglePlayerCampaignSetupUI.cs index 7f98cdc43..5688ea044 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Screens/CampaignSetupUI/SinglePlayerCampaignSetupUI.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Screens/CampaignSetupUI/SinglePlayerCampaignSetupUI.cs @@ -476,8 +476,7 @@ namespace Barotrauma { foreach (GUIComponent child in subList.Content.Children) { - SubmarineInfo sub = child.UserData as SubmarineInfo; - if (sub == null) { return; } + if (!(child.UserData is SubmarineInfo sub)) { return; } child.Visible = string.IsNullOrEmpty(filter) || sub.DisplayName.Contains(filter.ToLower(), StringComparison.OrdinalIgnoreCase); } } @@ -523,9 +522,11 @@ namespace Barotrauma subsToShow.Sort((s1, s2) => { - int p1 = s1.Price > CurrentSettings.InitialMoney ? 10 : 0; - int p2 = s2.Price > CurrentSettings.InitialMoney ? 10 : 0; - return p1.CompareTo(p2) * 100 + s1.Name.CompareTo(s2.Name); + int p1 = s1.Price; + if (!s1.IsCampaignCompatible) { p1 += 100000; } + int p2 = s2.Price; + if (!s2.IsCampaignCompatible) { p2 += 100000; } + return p1.CompareTo(p2) * 100 + s1.Name.CompareTo(s2.Name); }); subList.ClearChildren(); @@ -533,7 +534,7 @@ namespace Barotrauma foreach (SubmarineInfo sub in subsToShow) { var textBlock = new GUITextBlock( - new RectTransform(new Vector2(1, 0.1f), subList.Content.RectTransform) { MinSize = new Point(0, 30) }, + new RectTransform(new Vector2(1, 0.15f), subList.Content.RectTransform) { MinSize = new Point(0, 30) }, ToolBox.LimitString(sub.DisplayName.Value, GUIStyle.Font, subList.Rect.Width - 65), style: "ListBoxElement") { ToolTip = sub.Description, @@ -546,12 +547,19 @@ namespace Barotrauma textBlock.ToolTip = TextManager.Get("ContentPackageMismatch") + "\n\n" + textBlock.ToolTip.SanitizedString; } - var priceText = new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), textBlock.RectTransform, Anchor.CenterRight), - TextManager.GetWithVariable("currencyformat", "[credits]", string.Format(CultureInfo.InvariantCulture, "{0:N0}", sub.Price)), textAlignment: Alignment.CenterRight, font: GUIStyle.SmallFont) + var infoContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.5f, 1.0f), textBlock.RectTransform, Anchor.CenterRight), isHorizontal: false); + new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), infoContainer.RectTransform), + TextManager.GetWithVariable("currencyformat", "[credits]", string.Format(CultureInfo.InvariantCulture, "{0:N0}", sub.Price)), textAlignment: Alignment.BottomRight, font: GUIStyle.SmallFont) { TextColor = sub.Price > CurrentSettings.InitialMoney ? GUIStyle.Red : textBlock.TextColor * 0.8f, ToolTip = textBlock.ToolTip }; + new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), infoContainer.RectTransform), + TextManager.Get($"submarineclass.{sub.SubmarineClass}"), textAlignment: Alignment.TopRight, font: GUIStyle.SmallFont) + { + TextColor = textBlock.TextColor * 0.8f, + ToolTip = textBlock.ToolTip + }; #if !DEBUG if (!GameMain.DebugDraw) { diff --git a/Barotrauma/BarotraumaClient/ClientSource/Screens/EventEditor/EventEditorScreen.cs b/Barotrauma/BarotraumaClient/ClientSource/Screens/EventEditor/EventEditorScreen.cs index 22b86c510..620f10795 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Screens/EventEditor/EventEditorScreen.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Screens/EventEditor/EventEditorScreen.cs @@ -179,7 +179,7 @@ namespace Barotrauma // Ok button msgBox.Buttons[1].OnClicked = delegate { - foreach (var illegalChar in Path.GetInvalidFileNameChars()) + foreach (var illegalChar in Path.GetInvalidFileNameCharsCrossPlatform()) { if (!nameInput.Text.Contains(illegalChar)) { continue; } @@ -274,7 +274,7 @@ namespace Barotrauma // Ok button msgBox.Buttons[1].OnClicked = delegate { - foreach (var illegalChar in Path.GetInvalidFileNameChars()) + foreach (var illegalChar in Path.GetInvalidFileNameCharsCrossPlatform()) { if (!nameInput.Text.Contains(illegalChar)) { continue; } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Screens/MainMenuScreen.cs b/Barotrauma/BarotraumaClient/ClientSource/Screens/MainMenuScreen.cs index fa017d9c0..0f1ec526f 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Screens/MainMenuScreen.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Screens/MainMenuScreen.cs @@ -434,25 +434,18 @@ namespace Barotrauma { PlaySoundOnSelect = true, }; - var tutorialTypes = new List() + foreach (var tutorialPrefab in TutorialPrefab.Prefabs.OrderBy(p => p.Order)) { - typeof(MechanicTutorial), - typeof(EngineerTutorial), - typeof(DoctorTutorial), - typeof(OfficerTutorial), - typeof(CaptainTutorial), - }; - foreach (Type tutorialType in tutorialTypes) - { - Tutorial tutorial = (Tutorial)Activator.CreateInstance(tutorialType); + var tutorial = new Tutorial(tutorialPrefab); var tutorialText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.15f), tutorialList.Content.RectTransform), tutorial.DisplayName, textAlignment: Alignment.Center, font: GUIStyle.LargeFont) { + TextColor = GUIStyle.Green, UserData = tutorial }; } tutorialList.OnSelected += (component, obj) => { - (obj as Tutorial).Start(); + (obj as Tutorial)?.Start(); return true; }; @@ -737,34 +730,12 @@ namespace Barotrauma private void UpdateTutorialList() { - var tutorialList = menuTabs[Tab.Tutorials].GetChild(); - - int completedTutorials = 0; - - foreach (GUITextBlock tutorialText in tutorialList.Content.Children) + foreach (GUITextBlock tutorialText in menuTabs[Tab.Tutorials].GetChild().Content.Children) { - if (CompletedTutorials.Instance.Contains(((Tutorial)tutorialText.UserData).Identifier)) - { - completedTutorials++; - } - } - - for (int i = 0; i < tutorialList.Content.Children.Count(); i++) - { - if (i < completedTutorials + 1) - { - (tutorialList.Content.GetChild(i) as GUITextBlock).TextColor = GUIStyle.Green; -#if !DEBUG - (tutorialList.Content.GetChild(i) as GUITextBlock).CanBeFocused = true; -#endif - } - else - { - (tutorialList.Content.GetChild(i) as GUITextBlock).TextColor = Color.Gray; -#if !DEBUG - (tutorialList.Content.GetChild(i) as GUITextBlock).CanBeFocused = false; -#endif - } + var tutorial = (Tutorial)tutorialText.UserData; + tutorialText.Text = CompletedTutorials.Instance.Contains(tutorial.Identifier) ? + TextManager.GetWithVariable("tutorialcompleted", "[tutorialname]", tutorial.DisplayName) : + tutorial.DisplayName; } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Screens/ModDownloadScreen.cs b/Barotrauma/BarotraumaClient/ClientSource/Screens/ModDownloadScreen.cs index 599aa2c60..e638bf0e5 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Screens/ModDownloadScreen.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Screens/ModDownloadScreen.cs @@ -9,7 +9,7 @@ using Barotrauma.Steam; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using Color = Microsoft.Xna.Framework.Color; -using ServerContentPackage = Barotrauma.Networking.ClientPeer.ServerContentPackage; +using ServerContentPackage = Barotrauma.Networking.ServerContentPackage; namespace Barotrauma { @@ -21,7 +21,7 @@ namespace Barotrauma private readonly List downloadedPackages = new List(); public IEnumerable DownloadedPackages => downloadedPackages; - + private bool confirmDownload; public void Reset() diff --git a/Barotrauma/BarotraumaClient/ClientSource/Screens/NetLobbyScreen.cs b/Barotrauma/BarotraumaClient/ClientSource/Screens/NetLobbyScreen.cs index 7321d64d6..9c9e999d6 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Screens/NetLobbyScreen.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Screens/NetLobbyScreen.cs @@ -5,6 +5,7 @@ using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; namespace Barotrauma @@ -866,7 +867,7 @@ namespace Barotrauma { OnSelected = (component, obj) => { - GameMain.Client?.RequestSelectSub(component.Parent.GetChildIndex(component), isShuttle: true); + GameMain.Client?.RequestSelectSub(obj as SubmarineInfo, isShuttle: true); return true; } }; @@ -1794,7 +1795,7 @@ namespace Barotrauma MissionType = missionType; } - public void UpdateSubList(GUIComponent subList, List submarines) + public void UpdateSubList(GUIComponent subList, IEnumerable submarines) { if (subList == null) { return; } @@ -1817,7 +1818,7 @@ namespace Barotrauma subList = dropDown.ListBox.Content; } - var frame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.1f), subList.RectTransform) { MinSize = new Point(0, 20) }, + var frame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.15f), subList.RectTransform) { MinSize = new Point(0, 25) }, style: "ListBoxElement") { ToolTip = sub.Description, @@ -1873,7 +1874,7 @@ namespace Barotrauma { if (sub.HasTag(SubmarineTag.Shuttle)) { - var shuttleText = new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), parent.RectTransform, Anchor.CenterRight) { AbsoluteOffset = new Point(GUI.IntScale(20), 0) }, + new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), parent.RectTransform, Anchor.CenterRight) { AbsoluteOffset = new Point(GUI.IntScale(20), 0) }, TextManager.Get("Shuttle", "RespawnShuttle"), textAlignment: Alignment.CenterRight, font: GUIStyle.SmallFont) { TextColor = subTextBlock.TextColor * 0.8f, @@ -1881,7 +1882,7 @@ namespace Barotrauma CanBeFocused = false }; //make shuttles more dim in the sub list (selecting a shuttle as the main sub is allowed but not recommended) - if (subList == this.SubList.Content) + if (subList == SubList.Content) { subTextBlock.TextColor *= 0.8f; foreach (GUIComponent child in parent.Children) @@ -1892,8 +1893,16 @@ namespace Barotrauma } else { - new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), parent.RectTransform, Anchor.CenterRight) { AbsoluteOffset = new Point(GUI.IntScale(20), 0) }, - TextManager.Get($"submarineclass.{sub.SubmarineClass}"), textAlignment: Alignment.CenterRight, font: GUIStyle.SmallFont) + var infoContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.5f, 1.0f), parent.RectTransform, Anchor.CenterRight) { AbsoluteOffset = new Point(GUI.IntScale(20), 0) }, isHorizontal: false); + new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), infoContainer.RectTransform), + TextManager.GetWithVariable("currencyformat", "[credits]", string.Format(CultureInfo.InvariantCulture, "{0:N0}", sub.Price)), textAlignment: Alignment.BottomRight, font: GUIStyle.SmallFont) + { + UserData = "pricetext", + TextColor = subTextBlock.TextColor * 0.8f, + CanBeFocused = false + }; + new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), infoContainer.RectTransform), + TextManager.Get($"submarineclass.{sub.SubmarineClass}"), textAlignment: Alignment.TopRight, font: GUIStyle.SmallFont) { UserData = "classtext", TextColor = subTextBlock.TextColor * 0.8f, @@ -1913,6 +1922,17 @@ namespace Barotrauma if (!GameMain.Client.ServerSettings.AllowSubVoting) { var selectedSub = component.UserData as SubmarineInfo; + if (SelectedMode == GameModePreset.MultiPlayerCampaign && CampaignSetupUI != null) + { + if (selectedSub.Price > CampaignSetupUI.CurrentSettings.InitialMoney) + { + new GUIMessageBox(TextManager.Get("warning"), TextManager.Get("campaignsubtooexpensive")); + } + if (!selectedSub.IsCampaignCompatible) + { + new GUIMessageBox(TextManager.Get("warning"), TextManager.Get("campaignsubincompatible")); + } + } if (!selectedSub.RequiredContentPackagesInstalled) { var msgBox = new GUIMessageBox(TextManager.Get("ContentPackageMismatch"), @@ -1924,7 +1944,7 @@ namespace Barotrauma msgBox.Buttons[0].OnClicked = msgBox.Close; msgBox.Buttons[0].OnClicked += (button, obj) => { - GameMain.Client.RequestSelectSub(component.Parent.GetChildIndex(component), isShuttle: false); + GameMain.Client.RequestSelectSub(obj as SubmarineInfo, isShuttle: false); return true; }; msgBox.Buttons[1].OnClicked = msgBox.Close; @@ -1932,7 +1952,7 @@ namespace Barotrauma } else if (GameMain.Client.HasPermission(ClientPermissions.SelectSub)) { - GameMain.Client.RequestSelectSub(component.Parent.GetChildIndex(component), isShuttle: false); + GameMain.Client.RequestSelectSub(selectedSub, isShuttle: false); return true; } return false; @@ -2518,7 +2538,6 @@ namespace Barotrauma var kickVoteButton = new GUIButton(new RectTransform(new Vector2(0.34f, 1.0f), buttonAreaLower.RectTransform), TextManager.Get("VoteToKick")) { - Enabled = !selectedClient.HasKickVoteFromSessionId(GameMain.Client.SessionId), OnClicked = (btn, userdata) => { GameMain.Client.VoteForKick(selectedClient); btn.Enabled = false; return true; }, UserData = selectedClient }; @@ -3223,6 +3242,22 @@ namespace Barotrauma { if (GameMain.Client == null) { return; } + foreach (var subElement in SubList.Content.Children) + { + subElement.CanBeFocused = true; + foreach (var textBlock in subElement.GetAllChildren()) + { + textBlock.Enabled = true; + } + } + + SubList.Content.RectTransform.SortChildren((rt1, rt2) => + { + SubmarineInfo s1 = rt1.GUIComponent.UserData as SubmarineInfo; + SubmarineInfo s2 = rt2.GUIComponent.UserData as SubmarineInfo; + return s1.Name.CompareTo(s2.Name); + }); + autoRestartBox.Parent.Visible = true; settingsBlocker.Visible = false; if (SelectedMode == GameModePreset.Mission || SelectedMode == GameModePreset.PvP) @@ -3255,6 +3290,33 @@ namespace Barotrauma TextManager.Get("campaignstarting"), font: GUIStyle.SubHeadingFont, textAlignment: Alignment.Center, wrap: true); } } + + if (CampaignSetupUI != null) + { + foreach (var subElement in SubList.Content.Children) + { + var sub = subElement.UserData as SubmarineInfo; + bool tooExpensive = sub.Price > CampaignSetupUI.CurrentSettings.InitialMoney; + if (tooExpensive || !sub.IsCampaignCompatible) + { + foreach (var textBlock in subElement.GetAllChildren()) + { + textBlock.DisabledTextColor = (textBlock.UserData as string == "pricetext" && tooExpensive ? GUIStyle.Red : GUIStyle.TextColorNormal) * 0.7f; + textBlock.Enabled = false; + } + } + } + SubList.Content.RectTransform.SortChildren((rt1, rt2) => + { + SubmarineInfo s1 = rt1.GUIComponent.UserData as SubmarineInfo; + SubmarineInfo s2 = rt2.GUIComponent.UserData as SubmarineInfo; + int p1 = s1.Price; + if (!s1.IsCampaignCompatible) { p1 += 100000; } + int p2 = s2.Price; + if (!s2.IsCampaignCompatible) { p2 += 100000; } + return p1.CompareTo(p2) * 100 + s1.Name.CompareTo(s2.Name); + }); + } } else { @@ -3656,7 +3718,7 @@ namespace Barotrauma } } - private List visibilityMenuOrder = new List(); + private readonly List visibilityMenuOrder = new List(); private void CreateSubmarineVisibilityMenu() { var messageBox = new GUIMessageBox(TextManager.Get("SubmarineVisibility"), "", diff --git a/Barotrauma/BarotraumaClient/ClientSource/Screens/SubEditorScreen.cs b/Barotrauma/BarotraumaClient/ClientSource/Screens/SubEditorScreen.cs index 96e66ded3..3178cff7e 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Screens/SubEditorScreen.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Screens/SubEditorScreen.cs @@ -1839,7 +1839,7 @@ namespace Barotrauma return false; } - foreach (var illegalChar in Path.GetInvalidFileNameChars()) + foreach (var illegalChar in Path.GetInvalidFileNameCharsCrossPlatform()) { if (!name.Contains(illegalChar)) { continue; } GUI.AddMessage(TextManager.GetWithVariable("SubNameIllegalCharsWarning", "[illegalchar]", illegalChar.ToString()), GUIStyle.Red); @@ -2410,12 +2410,15 @@ namespace Barotrauma Stretch = true }; var classText = new GUITextBlock(new RectTransform(new Vector2(0.6f, 1.0f), classGroup.RectTransform), - TextManager.Get("submarineclass"), textAlignment: Alignment.CenterLeft, wrap: true); + TextManager.Get("submarineclass"), textAlignment: Alignment.CenterLeft, wrap: true) + { + ToolTip = TextManager.Get("submarineclass.description") + }; GUIDropDown classDropDown = new GUIDropDown(new RectTransform(new Vector2(0.4f, 1.0f), classGroup.RectTransform)); classDropDown.RectTransform.MinSize = new Point(0, subTypeContainer.RectTransform.Children.Max(c => c.MinSize.Y)); - foreach (SubmarineClass @class in Enum.GetValues(typeof(SubmarineClass))) + foreach (SubmarineClass subClass in Enum.GetValues(typeof(SubmarineClass))) { - classDropDown.AddItem(TextManager.Get($"{nameof(SubmarineClass)}.{@class}"), @class); + classDropDown.AddItem(TextManager.Get($"{nameof(SubmarineClass)}.{subClass}"), subClass, toolTip: TextManager.Get($"submarineclass.{subClass}.description")); } classDropDown.AddItem(TextManager.Get(nameof(SubmarineTag.Shuttle)), SubmarineTag.Shuttle); classDropDown.OnSelected += (selected, userdata) => @@ -2435,6 +2438,31 @@ namespace Barotrauma }; classDropDown.SelectItem(!MainSub.Info.HasTag(SubmarineTag.Shuttle) ? MainSub.Info.SubmarineClass : (object)SubmarineTag.Shuttle); + var tierGroup = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.25f), subSettingsContainer.RectTransform), isHorizontal: true) + { + Stretch = true + }; + new GUITextBlock(new RectTransform(new Vector2(0.6f, 1.0f), tierGroup.RectTransform), + TextManager.Get("subeditor.tier"), textAlignment: Alignment.CenterLeft, wrap: true) + { + ToolTip = TextManager.Get("submarinetier.description") + }; + + new GUINumberInput(new RectTransform(new Vector2(0.4f, 1.0f), tierGroup.RectTransform), NumberType.Int) + { + IntValue = SubmarineInfo.GetDefaultTier(MainSub.Info.Price), + MinValueInt = 1, + MaxValueInt = 3, + OnValueChanged = (numberInput) => + { + MainSub.Info.Tier = numberInput.IntValue; + } + }; + if (MainSub?.Info != null) + { + MainSub.Info.Tier = Math.Clamp(MainSub.Info.Tier, 1, 3); + } + var crewSizeArea = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.25f), subSettingsContainer.RectTransform), isHorizontal: true) { Stretch = true, @@ -2970,7 +2998,7 @@ namespace Barotrauma return false; } - foreach (char illegalChar in Path.GetInvalidFileNameChars()) + foreach (char illegalChar in Path.GetInvalidFileNameCharsCrossPlatform()) { if (nameBox.Text.Contains(illegalChar)) { @@ -5014,6 +5042,10 @@ namespace Barotrauma SkipInventorySlotUpdate = false; ImageManager.Update((float)deltaTime); +#if DEBUG + Hull.UpdateCheats((float)deltaTime, cam); +#endif + if (GameMain.GraphicsWidth != screenResolution.X || GameMain.GraphicsHeight != screenResolution.Y) { saveFrame = null; diff --git a/Barotrauma/BarotraumaClient/ClientSource/Settings/SettingsMenu.cs b/Barotrauma/BarotraumaClient/ClientSource/Settings/SettingsMenu.cs index b11d5eaf1..8e2172550 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Settings/SettingsMenu.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Settings/SettingsMenu.cs @@ -229,7 +229,7 @@ namespace Barotrauma }; } - private string Percentage(float v) => TextManager.GetWithVariable("percentageformat", "[value]", Round(v * 100).ToString()).Value; + private string Percentage(float v) => ToolBox.GetFormattedPercentage(v); private int Round(float v) => (int)MathF.Round(v); diff --git a/Barotrauma/BarotraumaClient/ClientSource/Sounds/SoundPlayer.cs b/Barotrauma/BarotraumaClient/ClientSource/Sounds/SoundPlayer.cs index 0705c3084..5870847e0 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Sounds/SoundPlayer.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Sounds/SoundPlayer.cs @@ -282,7 +282,7 @@ namespace Barotrauma } else { - if (FlowSounds[i] == null) { continue; } + if (FlowSounds[i]?.Sound == null) { continue; } Vector2 soundPos = new Vector2(GameMain.SoundManager.ListenerPosition.X + (flowVolumeRight[i] - flowVolumeLeft[i]) * 100, GameMain.SoundManager.ListenerPosition.Y); if (flowSoundChannels[i] == null || !flowSoundChannels[i].IsPlaying) { diff --git a/Barotrauma/BarotraumaClient/LinuxClient.csproj b/Barotrauma/BarotraumaClient/LinuxClient.csproj index 560289dd2..ce5e7b251 100644 --- a/Barotrauma/BarotraumaClient/LinuxClient.csproj +++ b/Barotrauma/BarotraumaClient/LinuxClient.csproj @@ -2,40 +2,30 @@ WinExe - netcoreapp3.1 + net6.0 Barotrauma FakeFish, Undertow Games Barotrauma - 0.19.1.0 + 0.19.3.0 Copyright © FakeFish 2018-2022 AnyCPU;x64 Barotrauma ..\BarotraumaShared\Icon.ico Debug;Release;Unstable + true ;NU1605;CS0114;CS0108CS8597;CS8600;CS8601;CS8602;CS8603;CS8604;CS8605;CS8606;CS8607;CS8608;CS8609;CS8610;CS8611;CS8612;CS8613;CS8614;CS8615;CS8616;CS8617;CS8618;CS8619;CS8620;CS8621;CS8622;CS8624;CS8625;CS8626;CS8629;CS8631;CS8632;CS8633;CS8634;CS8638;CS8643;CS8644;CS8645;CS8653;CS8654;CS8655;CS8667;CS8669;CS8670;CS8714;CS8717;CS8765 - - DEBUG;TRACE;CLIENT;LINUX;USE_STEAM x64 ..\bin\$(Configuration)Linux\ - net6.0 - 8 TRACE;DEBUG;CLIENT;LINUX;X64;USE_STEAM x64 ..\bin\$(Configuration)Linux\ - net6.0 - 8 diff --git a/Barotrauma/BarotraumaClient/MacClient.csproj b/Barotrauma/BarotraumaClient/MacClient.csproj index 4e6d3e5a8..fd0d561b2 100644 --- a/Barotrauma/BarotraumaClient/MacClient.csproj +++ b/Barotrauma/BarotraumaClient/MacClient.csproj @@ -2,16 +2,17 @@ WinExe - netcoreapp3.1 + net6.0 Barotrauma FakeFish, Undertow Games Barotrauma - 0.19.1.0 + 0.19.3.0 Copyright © FakeFish 2018-2022 AnyCPU;x64 Barotrauma ..\BarotraumaShared\Icon.ico Debug;Release;Unstable + true ;NU1605;CS0114;CS0108CS8597;CS8600;CS8601;CS8602;CS8603;CS8604;CS8605;CS8606;CS8607;CS8608;CS8609;CS8610;CS8611;CS8612;CS8613;CS8614;CS8615;CS8616;CS8617;CS8618;CS8619;CS8620;CS8621;CS8622;CS8624;CS8625;CS8626;CS8629;CS8631;CS8632;CS8633;CS8634;CS8638;CS8643;CS8644;CS8645;CS8653;CS8654;CS8655;CS8667;CS8669;CS8670;CS8714;CS8717;CS8765 diff --git a/Barotrauma/BarotraumaClient/WindowsClient.csproj b/Barotrauma/BarotraumaClient/WindowsClient.csproj index 54cc0ce82..4e4bc2642 100644 --- a/Barotrauma/BarotraumaClient/WindowsClient.csproj +++ b/Barotrauma/BarotraumaClient/WindowsClient.csproj @@ -2,16 +2,17 @@ WinExe - netcoreapp3.1 + net6.0 Barotrauma FakeFish, Undertow Games Barotrauma - 0.19.1.0 + 0.19.3.0 Copyright © FakeFish 2018-2022 AnyCPU;x64 Barotrauma ..\BarotraumaShared\Icon.ico Debug;Release;Unstable + true app.manifest ;NU1605;CS0114;CS0108CS8597;CS8600;CS8601;CS8602;CS8603;CS8604;CS8605;CS8606;CS8607;CS8608;CS8609;CS8610;CS8611;CS8612;CS8613;CS8614;CS8615;CS8616;CS8617;CS8618;CS8619;CS8620;CS8621;CS8622;CS8624;CS8625;CS8626;CS8629;CS8631;CS8632;CS8633;CS8634;CS8638;CS8643;CS8644;CS8645;CS8653;CS8654;CS8655;CS8667;CS8669;CS8670;CS8714;CS8717;CS8765 diff --git a/Barotrauma/BarotraumaServer/LinuxServer.csproj b/Barotrauma/BarotraumaServer/LinuxServer.csproj index 83cba5533..f60b3ea38 100644 --- a/Barotrauma/BarotraumaServer/LinuxServer.csproj +++ b/Barotrauma/BarotraumaServer/LinuxServer.csproj @@ -2,40 +2,30 @@ Exe - netcoreapp3.1 + net6.0 Barotrauma FakeFish, Undertow Games Barotrauma Dedicated Server - 0.19.1.0 + 0.19.3.0 Copyright © FakeFish 2018-2022 AnyCPU;x64 DedicatedServer ..\BarotraumaShared\Icon.ico Debug;Release;Unstable + true ;NU1605;CS0114;CS0108CS8597;CS8600;CS8601;CS8602;CS8603;CS8604;CS8605;CS8606;CS8607;CS8608;CS8609;CS8610;CS8611;CS8612;CS8613;CS8614;CS8615;CS8616;CS8617;CS8618;CS8619;CS8620;CS8621;CS8622;CS8624;CS8625;CS8626;CS8629;CS8631;CS8632;CS8633;CS8634;CS8638;CS8643;CS8644;CS8645;CS8653;CS8654;CS8655;CS8667;CS8669;CS8670;CS8714;CS8717;CS8765 - - DEBUG;TRACE;SERVER;LINUX;USE_STEAM x64 ..\bin\$(Configuration)Linux\ - net6.0 - 8 TRACE;DEBUG;SERVER;LINUX;X64;USE_STEAM x64 ..\bin\$(Configuration)Linux\ - net6.0 - 8 diff --git a/Barotrauma/BarotraumaServer/MacServer.csproj b/Barotrauma/BarotraumaServer/MacServer.csproj index 36a90f48b..2f621c063 100644 --- a/Barotrauma/BarotraumaServer/MacServer.csproj +++ b/Barotrauma/BarotraumaServer/MacServer.csproj @@ -2,16 +2,17 @@ Exe - netcoreapp3.1 + net6.0 Barotrauma FakeFish, Undertow Games Barotrauma Dedicated Server - 0.19.1.0 + 0.19.3.0 Copyright © FakeFish 2018-2022 AnyCPU;x64 DedicatedServer ..\BarotraumaShared\Icon.ico Debug;Release;Unstable + true ;NU1605;CS0114;CS0108CS8597;CS8600;CS8601;CS8602;CS8603;CS8604;CS8605;CS8606;CS8607;CS8608;CS8609;CS8610;CS8611;CS8612;CS8613;CS8614;CS8615;CS8616;CS8617;CS8618;CS8619;CS8620;CS8621;CS8622;CS8624;CS8625;CS8626;CS8629;CS8631;CS8632;CS8633;CS8634;CS8638;CS8643;CS8644;CS8645;CS8653;CS8654;CS8655;CS8667;CS8669;CS8670;CS8714;CS8717;CS8765 diff --git a/Barotrauma/BarotraumaServer/ServerSource/Characters/CharacterInfo.cs b/Barotrauma/BarotraumaServer/ServerSource/Characters/CharacterInfo.cs index 5dc354ccb..561218a63 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Characters/CharacterInfo.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Characters/CharacterInfo.cs @@ -46,39 +46,39 @@ namespace Barotrauma public void ServerWrite(IWriteMessage msg) { - msg.Write(ID); - msg.Write(Name); - msg.Write(OriginalName); - msg.Write((byte)Head.Preset.TagSet.Count); + msg.WriteUInt16(ID); + msg.WriteString(Name); + msg.WriteString(OriginalName); + msg.WriteByte((byte)Head.Preset.TagSet.Count); foreach (Identifier tag in Head.Preset.TagSet) { - msg.Write(tag); + msg.WriteIdentifier(tag); } - msg.Write((byte)Head.HairIndex); - msg.Write((byte)Head.BeardIndex); - msg.Write((byte)Head.MoustacheIndex); - msg.Write((byte)Head.FaceAttachmentIndex); + msg.WriteByte((byte)Head.HairIndex); + msg.WriteByte((byte)Head.BeardIndex); + msg.WriteByte((byte)Head.MoustacheIndex); + msg.WriteByte((byte)Head.FaceAttachmentIndex); msg.WriteColorR8G8B8(Head.SkinColor); msg.WriteColorR8G8B8(Head.HairColor); msg.WriteColorR8G8B8(Head.FacialHairColor); - msg.Write(ragdollFileName); + msg.WriteString(ragdollFileName); if (Job != null) { - msg.Write(Job.Prefab.UintIdentifier); - msg.Write((byte)Job.Variant); + msg.WriteUInt32(Job.Prefab.UintIdentifier); + msg.WriteByte((byte)Job.Variant); foreach (SkillPrefab skillPrefab in Job.Prefab.Skills.OrderBy(s => s.Identifier)) { - msg.Write(Job.GetSkill(skillPrefab.Identifier).Level); + msg.WriteSingle(Job.GetSkill(skillPrefab.Identifier).Level); } } else { - msg.Write((uint)0); - msg.Write((byte)0); + msg.WriteUInt32((uint)0); + msg.WriteByte((byte)0); } - msg.Write((ushort)ExperiencePoints); + msg.WriteUInt16((ushort)ExperiencePoints); msg.WriteRangedInteger(AdditionalTalentPoints, 0, MaxAdditionalTalentPoints); } } diff --git a/Barotrauma/BarotraumaServer/ServerSource/Characters/CharacterNetworking.cs b/Barotrauma/BarotraumaServer/ServerSource/Characters/CharacterNetworking.cs index 37dd065db..953e09573 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Characters/CharacterNetworking.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Characters/CharacterNetworking.cs @@ -8,7 +8,7 @@ namespace Barotrauma { partial class Character { - public Endpoint OwnerClientEndpoint; + public Address OwnerClientAddress; public string OwnerClientName; public bool ClientDisconnected; public float KillDisconnectedTimer; @@ -301,25 +301,25 @@ namespace Barotrauma public void ServerWritePosition(IWriteMessage msg, Client c) { - msg.Write(ID); + msg.WriteUInt16(ID); IWriteMessage tempBuffer = new WriteOnlyMessage(); if (this == c.Character) { - tempBuffer.Write(true); + tempBuffer.WriteBoolean(true); if (LastNetworkUpdateID < memInput.Count + 1) { - tempBuffer.Write((UInt16)0); + tempBuffer.WriteUInt16((UInt16)0); } else { - tempBuffer.Write((UInt16)(LastNetworkUpdateID - memInput.Count - 1)); + tempBuffer.WriteUInt16((UInt16)(LastNetworkUpdateID - memInput.Count - 1)); } } else { - tempBuffer.Write(false); + tempBuffer.WriteBoolean(false); bool aiming = false; bool use = false; @@ -342,41 +342,41 @@ namespace Barotrauma networkUpdateSent = true; } - tempBuffer.Write(aiming); - tempBuffer.Write(shoot); - tempBuffer.Write(use); + tempBuffer.WriteBoolean(aiming); + tempBuffer.WriteBoolean(shoot); + tempBuffer.WriteBoolean(use); if (AnimController is HumanoidAnimController) { - tempBuffer.Write(((HumanoidAnimController)AnimController).Crouching); + tempBuffer.WriteBoolean(((HumanoidAnimController)AnimController).Crouching); } - tempBuffer.Write(attack); + tempBuffer.WriteBoolean(attack); Vector2 relativeCursorPos = cursorPosition - AimRefPosition; - tempBuffer.Write((UInt16)(65535.0 * Math.Atan2(relativeCursorPos.Y, relativeCursorPos.X) / (2.0 * Math.PI))); + tempBuffer.WriteUInt16((UInt16)(65535.0 * Math.Atan2(relativeCursorPos.Y, relativeCursorPos.X) / (2.0 * Math.PI))); - tempBuffer.Write(IsRagdolled || Stun > 0.0f || IsDead || IsIncapacitated); + tempBuffer.WriteBoolean(IsRagdolled || Stun > 0.0f || IsDead || IsIncapacitated); - tempBuffer.Write(AnimController.Dir > 0.0f); + tempBuffer.WriteBoolean(AnimController.Dir > 0.0f); } if (SelectedCharacter != null || HasSelectedAnyItem) { - tempBuffer.Write(true); - tempBuffer.Write(SelectedCharacter != null ? SelectedCharacter.ID : NullEntityID); - tempBuffer.Write(SelectedItem != null ? SelectedItem.ID : NullEntityID); - tempBuffer.Write(SelectedSecondaryItem != null ? SelectedSecondaryItem.ID : NullEntityID); + tempBuffer.WriteBoolean(true); + tempBuffer.WriteUInt16(SelectedCharacter != null ? SelectedCharacter.ID : NullEntityID); + tempBuffer.WriteUInt16(SelectedItem != null ? SelectedItem.ID : NullEntityID); + tempBuffer.WriteUInt16(SelectedSecondaryItem != null ? SelectedSecondaryItem.ID : NullEntityID); if (SelectedCharacter != null) { - tempBuffer.Write(AnimController.Anim == AnimController.Animation.CPR); + tempBuffer.WriteBoolean(AnimController.Anim == AnimController.Animation.CPR); } } else { - tempBuffer.Write(false); + tempBuffer.WriteBoolean(false); } - tempBuffer.Write(SimPosition.X); - tempBuffer.Write(SimPosition.Y); + tempBuffer.WriteSingle(SimPosition.X); + tempBuffer.WriteSingle(SimPosition.Y); float MaxVel = NetConfig.MaxPhysicsBodyVelocity; AnimController.Collider.LinearVelocity = new Vector2( MathHelper.Clamp(AnimController.Collider.LinearVelocity.X, -MaxVel, MaxVel), @@ -385,17 +385,17 @@ namespace Barotrauma tempBuffer.WriteRangedSingle(AnimController.Collider.LinearVelocity.Y, -MaxVel, MaxVel, 12); bool fixedRotation = AnimController.Collider.FarseerBody.FixedRotation || !AnimController.Collider.PhysEnabled; - tempBuffer.Write(fixedRotation); + tempBuffer.WriteBoolean(fixedRotation); if (!fixedRotation) { - tempBuffer.Write(AnimController.Collider.Rotation); + tempBuffer.WriteSingle(AnimController.Collider.Rotation); float MaxAngularVel = NetConfig.MaxPhysicsBodyAngularVelocity; AnimController.Collider.AngularVelocity = NetConfig.Quantize(AnimController.Collider.AngularVelocity, -MaxAngularVel, MaxAngularVel, 8); tempBuffer.WriteRangedSingle(MathHelper.Clamp(AnimController.Collider.AngularVelocity, -MaxAngularVel, MaxAngularVel), -MaxAngularVel, MaxAngularVel, 8); } bool writeStatus = healthUpdateTimer <= 0.0f; - tempBuffer.Write(writeStatus); + tempBuffer.WriteBoolean(writeStatus); if (writeStatus) { WriteStatus(tempBuffer); @@ -406,7 +406,7 @@ namespace Barotrauma tempBuffer.WritePadBits(); msg.WriteVariableUInt32((uint)tempBuffer.LengthBytes); - msg.Write(tempBuffer.Buffer, 0, tempBuffer.LengthBytes); + msg.WriteBytes(tempBuffer.Buffer, 0, tempBuffer.LengthBytes); } public virtual void ServerEventWrite(IWriteMessage msg, Client c, NetEntityEvent.IData extraData = null) @@ -417,13 +417,13 @@ namespace Barotrauma switch (eventData) { case InventoryStateEventData _: - msg.Write(GameMain.Server.EntityEventManager.Events.Last()?.ID ?? (ushort)0); + msg.WriteUInt16(GameMain.Server.EntityEventManager.Events.Last()?.ID ?? (ushort)0); Inventory.ServerEventWrite(msg, c); break; case ControlEventData controlEventData: Client owner = controlEventData.Owner; - msg.Write(owner == c && owner.Character == this); - msg.Write(owner != null && owner.Character == this && GameMain.Server.ConnectedClients.Contains(owner) ? owner.SessionId : (byte)0); + msg.WriteBoolean(owner == c && owner.Character == this); + msg.WriteByte(owner != null && owner.Character == this && GameMain.Server.ConnectedClients.Contains(owner) ? owner.SessionId : (byte)0); break; case CharacterStatusEventData statusEventData: WriteStatus(msg, statusEventData.ForceAfflictionData); @@ -431,16 +431,16 @@ namespace Barotrauma case UpdateSkillsEventData _: if (Info?.Job == null) { - msg.Write((byte)0); + msg.WriteByte((byte)0); } else { var skills = Info.Job.GetSkills(); - msg.Write((byte)skills.Count()); + msg.WriteByte((byte)skills.Count()); foreach (Skill skill in skills) { - msg.Write(skill.Identifier); - msg.Write(skill.Level); + msg.WriteIdentifier(skill.Identifier); + msg.WriteSingle(skill.Level); } } break; @@ -457,33 +457,33 @@ namespace Barotrauma targetLimbIndex = targetLimbsArray.IndexOf(attackEventData.TargetLimb); } } - msg.Write((byte)(attackLimbIndex < 0 ? 255 : attackLimbIndex)); - msg.Write((ushort)targetEntityId); - msg.Write((byte)(targetLimbIndex < 0 ? 255 : targetLimbIndex)); - msg.Write(attackEventData.TargetSimPos.X); - msg.Write(attackEventData.TargetSimPos.Y); + msg.WriteByte((byte)(attackLimbIndex < 0 ? 255 : attackLimbIndex)); + msg.WriteUInt16((ushort)targetEntityId); + msg.WriteByte((byte)(targetLimbIndex < 0 ? 255 : targetLimbIndex)); + msg.WriteSingle(attackEventData.TargetSimPos.X); + msg.WriteSingle(attackEventData.TargetSimPos.Y); } break; case AssignCampaignInteractionEventData _: - msg.Write((byte)CampaignInteractionType); - msg.Write(RequireConsciousnessForCustomInteract); + msg.WriteByte((byte)CampaignInteractionType); + msg.WriteBoolean(RequireConsciousnessForCustomInteract); break; case ObjectiveManagerStateEventData objectiveManagerStateEventData: AIObjectiveManager.ObjectiveType type = objectiveManagerStateEventData.ObjectiveType; msg.WriteRangedInteger((int)type, (int)AIObjectiveManager.ObjectiveType.MinValue, (int)AIObjectiveManager.ObjectiveType.MaxValue); if (!(AIController is HumanAIController controller)) { - msg.Write(false); + msg.WriteBoolean(false); break; } if (type == AIObjectiveManager.ObjectiveType.Order) { var currentOrderInfo = controller.ObjectiveManager.GetCurrentOrderInfo(); bool validOrder = currentOrderInfo != null; - msg.Write(validOrder); + msg.WriteBoolean(validOrder); if (!validOrder) { break; } var orderPrefab = currentOrderInfo.Prefab; - msg.Write(orderPrefab.UintIdentifier); + msg.WriteUInt32(orderPrefab.UintIdentifier); if (!orderPrefab.HasOptions) { break; } int optionIndex = orderPrefab.AllOptions.IndexOf(currentOrderInfo.Option); if (optionIndex == -1) @@ -496,65 +496,65 @@ namespace Barotrauma { var objective = controller.ObjectiveManager.CurrentObjective; bool validObjective = objective?.Identifier is { IsEmpty: false }; - msg.Write(validObjective); + msg.WriteBoolean(validObjective); if (!validObjective) { break; } - msg.Write(objective.Identifier); - msg.Write(objective.Option); + msg.WriteIdentifier(objective.Identifier); + msg.WriteIdentifier(objective.Option); UInt16 targetEntityId = 0; if (objective is AIObjectiveOperateItem operateObjective && operateObjective.OperateTarget != null) { targetEntityId = operateObjective.OperateTarget.ID; } - msg.Write(targetEntityId); + msg.WriteUInt16(targetEntityId); } break; case TeamChangeEventData _: - msg.Write((byte)TeamID); + msg.WriteByte((byte)TeamID); break; case AddToCrewEventData addToCrewEventData: - msg.Write((byte)addToCrewEventData.TeamType); // team id + msg.WriteByte((byte)addToCrewEventData.TeamType); // team id ushort[] inventoryItemIDs = addToCrewEventData.InventoryItems.Select(item => item.ID).ToArray(); - msg.Write((ushort)inventoryItemIDs.Length); + msg.WriteUInt16((ushort)inventoryItemIDs.Length); for (int i = 0; i < inventoryItemIDs.Length; i++) { - msg.Write(inventoryItemIDs[i]); + msg.WriteUInt16(inventoryItemIDs[i]); } break; case UpdateExperienceEventData _: - msg.Write(Info.ExperiencePoints); + msg.WriteInt32(Info.ExperiencePoints); break; case UpdateTalentsEventData _: - msg.Write((ushort)characterTalents.Count); + msg.WriteUInt16((ushort)characterTalents.Count); foreach (var unlockedTalent in characterTalents) { - msg.Write(unlockedTalent.AddedThisRound); - msg.Write(unlockedTalent.Prefab.UintIdentifier); + msg.WriteBoolean(unlockedTalent.AddedThisRound); + msg.WriteUInt32(unlockedTalent.Prefab.UintIdentifier); } break; case UpdateMoneyEventData _: - msg.Write(GameMain.GameSession.Campaign.GetWallet(c).Balance); + msg.WriteInt32(GameMain.GameSession.Campaign.GetWallet(c).Balance); break; case UpdatePermanentStatsEventData updatePermanentStatsEventData: StatTypes statType = updatePermanentStatsEventData.StatType; if (Info == null) { - msg.Write((byte)0); - msg.Write((byte)0); + msg.WriteByte((byte)0); + msg.WriteByte((byte)0); } else if (!Info.SavedStatValues.ContainsKey(statType)) { - msg.Write((byte)0); - msg.Write((byte)statType); + msg.WriteByte((byte)0); + msg.WriteByte((byte)statType); } else { - msg.Write((byte)Info.SavedStatValues[statType].Count); - msg.Write((byte)statType); + msg.WriteByte((byte)Info.SavedStatValues[statType].Count); + msg.WriteByte((byte)statType); foreach (var savedStatValue in Info.SavedStatValues[statType]) { - msg.Write(savedStatValue.StatIdentifier); - msg.Write(savedStatValue.StatValue); - msg.Write(savedStatValue.RemoveOnDeath); + msg.WriteString(savedStatValue.StatIdentifier); + msg.WriteSingle(savedStatValue.StatValue); + msg.WriteBoolean(savedStatValue.RemoveOnDeath); } } break; @@ -568,15 +568,15 @@ namespace Barotrauma /// Normally full affliction data is not written for dead characters, this can be used to force them to be written private void WriteStatus(IWriteMessage msg, bool forceAfflictionData = false) { - msg.Write(IsDead); + msg.WriteBoolean(IsDead); if (IsDead) { msg.WriteRangedInteger((int)CauseOfDeath.Type, 0, Enum.GetValues(typeof(CauseOfDeathType)).Length - 1); if (CauseOfDeath.Type == CauseOfDeathType.Affliction) { - msg.Write(CauseOfDeath.Affliction.UintIdentifier); + msg.WriteUInt32(CauseOfDeath.Affliction.UintIdentifier); } - msg.Write(forceAfflictionData); + msg.WriteBoolean(forceAfflictionData); if (forceAfflictionData) { CharacterHealth.ServerWrite(msg); @@ -589,7 +589,7 @@ namespace Barotrauma if (AnimController?.LimbJoints == null) { //0 limbs severed - msg.Write((byte)0); + msg.WriteByte((byte)0); } else { @@ -601,10 +601,10 @@ namespace Barotrauma severedJointIndices.Add(i); } } - msg.Write((byte)severedJointIndices.Count); + msg.WriteByte((byte)severedJointIndices.Count); foreach (int jointIndex in severedJointIndices) { - msg.Write((byte)jointIndex); + msg.WriteByte((byte)jointIndex); } } } @@ -615,24 +615,24 @@ namespace Barotrauma int initialMsgLength = msg.LengthBytes; - msg.Write(Info == null); - msg.Write(entityId); - msg.Write(SpeciesName); - msg.Write(Seed); + msg.WriteBoolean(Info == null); + msg.WriteUInt16(entityId); + msg.WriteIdentifier(SpeciesName); + msg.WriteString(Seed); if (Removed) { - msg.Write(0.0f); - msg.Write(0.0f); + msg.WriteSingle(0.0f); + msg.WriteSingle(0.0f); } else { - msg.Write(WorldPosition.X); - msg.Write(WorldPosition.Y); + msg.WriteSingle(WorldPosition.X); + msg.WriteSingle(WorldPosition.Y); } - msg.Write(Enabled); - msg.Write(DisabledByEvent); + msg.WriteBoolean(Enabled); + msg.WriteBoolean(DisabledByEvent); //character with no characterinfo (e.g. some monster) if (Info == null) @@ -644,54 +644,54 @@ namespace Barotrauma Client ownerClient = GameMain.Server.ConnectedClients.Find(c => c.Character == this); if (ownerClient != null) { - msg.Write(true); - msg.Write(ownerClient.SessionId); + msg.WriteBoolean(true); + msg.WriteByte(ownerClient.SessionId); } else if (GameMain.Server.Character == this) { - msg.Write(true); - msg.Write((byte)0); + msg.WriteBoolean(true); + msg.WriteByte((byte)0); } else { - msg.Write(false); + msg.WriteBoolean(false); } - msg.Write(HumanPrefabHealthMultiplier); - msg.Write(Wallet.Balance); + msg.WriteSingle(HumanPrefabHealthMultiplier); + msg.WriteInt32(Wallet.Balance); msg.WriteRangedInteger(Wallet.RewardDistribution, 0, 100); - msg.Write((byte)TeamID); - msg.Write(this is AICharacter); - msg.Write(info.SpeciesName); + msg.WriteByte((byte)TeamID); + msg.WriteBoolean(this is AICharacter); + msg.WriteIdentifier(info.SpeciesName); int msgLengthBeforeInfo = msg.LengthBytes; info.ServerWrite(msg); int infoLength = msg.LengthBytes - msgLengthBeforeInfo; - msg.Write((byte)CampaignInteractionType); + msg.WriteByte((byte)CampaignInteractionType); if (CampaignInteractionType == CampaignMode.InteractionType.Store) { - msg.Write(MerchantIdentifier); + msg.WriteIdentifier(MerchantIdentifier); } int msgLengthBeforeOrders = msg.LengthBytes; // Current orders - msg.Write((byte)info.CurrentOrders.Count(o => o != null)); + msg.WriteByte((byte)info.CurrentOrders.Count(o => o != null)); foreach (var orderInfo in info.CurrentOrders) { if (orderInfo == null) { continue; } - msg.Write(orderInfo.Prefab.UintIdentifier); - msg.Write(orderInfo.TargetEntity == null ? (UInt16)0 : orderInfo.TargetEntity.ID); + msg.WriteUInt32(orderInfo.Prefab.UintIdentifier); + msg.WriteUInt16(orderInfo.TargetEntity == null ? (UInt16)0 : orderInfo.TargetEntity.ID); var hasOrderGiver = orderInfo.OrderGiver != null; - msg.Write(hasOrderGiver); - if (hasOrderGiver) { msg.Write(orderInfo.OrderGiver.ID); } - msg.Write((byte)(orderInfo.Option == Identifier.Empty ? 0 : orderInfo.Prefab.Options.IndexOf(orderInfo.Option))); - msg.Write((byte)orderInfo.ManualPriority); + msg.WriteBoolean(hasOrderGiver); + if (hasOrderGiver) { msg.WriteUInt16(orderInfo.OrderGiver.ID); } + msg.WriteByte((byte)(orderInfo.Option == Identifier.Empty ? 0 : orderInfo.Prefab.Options.IndexOf(orderInfo.Option))); + msg.WriteByte((byte)orderInfo.ManualPriority); var hasTargetPosition = orderInfo.TargetPosition != null; - msg.Write(hasTargetPosition); + msg.WriteBoolean(hasTargetPosition); if (hasTargetPosition) { - msg.Write(orderInfo.TargetPosition.Position.X); - msg.Write(orderInfo.TargetPosition.Position.Y); - msg.Write(orderInfo.TargetPosition.Hull == null ? (UInt16)0 : orderInfo.TargetPosition.Hull.ID); + msg.WriteSingle(orderInfo.TargetPosition.Position.X); + msg.WriteSingle(orderInfo.TargetPosition.Position.Y); + msg.WriteUInt16(orderInfo.TargetPosition.Hull == null ? (UInt16)0 : orderInfo.TargetPosition.Hull.ID); } } int ordersLength = msg.LengthBytes - msgLengthBeforeOrders; @@ -713,7 +713,7 @@ namespace Barotrauma WriteStatus(tempBuffer, forceAfflictionData: true); if (msgLengthBeforeStatus + tempBuffer.LengthBytes >= 255 && restrictMessageSize) { - msg.Write(false); + msg.WriteBoolean(false); if (msgLengthBeforeStatus < 255) { string errorMsg = $"Error when writing character spawn data for \"{Name}\": status data caused the length of the message to exceed 255 bytes ({msgLengthBeforeStatus} + {tempBuffer.LengthBytes})"; @@ -723,7 +723,7 @@ namespace Barotrauma } else { - msg.Write(true); + msg.WriteBoolean(true); WriteStatus(msg, forceAfflictionData: true); } } diff --git a/Barotrauma/BarotraumaServer/ServerSource/DebugConsole.cs b/Barotrauma/BarotraumaServer/ServerSource/DebugConsole.cs index 6c3a29f56..29f57d01b 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/DebugConsole.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/DebugConsole.cs @@ -302,9 +302,9 @@ namespace Barotrauma { client ??= GameMain.Server.ConnectedClients.Find(c => c.SessionId == id); } - if (Endpoint.Parse(arg).TryUnwrap(out var endpoint)) + if (Address.Parse(arg).TryUnwrap(out var address)) { - client ??= GameMain.Server.ConnectedClients.Find(c => c.EndpointMatches(endpoint)); + client ??= GameMain.Server.ConnectedClients.Find(c => c.AddressMatches(address)); } if (AccountId.Parse(arg).TryUnwrap(out var argAccountId)) { @@ -915,7 +915,7 @@ namespace Barotrauma { if (GameMain.Server == null || args.Length == 0) return; - if (!(Endpoint.Parse(args[0]).TryUnwrap(out var endpoint))) { return; } + if (!(Address.Parse(args[0]).TryUnwrap(out var address))) { return; } ShowQuestionPrompt("Reason for banning the endpoint \"" + args[0] + "\"? (c to cancel)", (reason) => { @@ -934,10 +934,10 @@ namespace Barotrauma banDuration = parsedBanDuration; } - var clients = GameMain.Server.ConnectedClients.Where(c => c.EndpointMatches(endpoint)).ToList(); + var clients = GameMain.Server.ConnectedClients.Where(c => c.AddressMatches(address)).ToList(); if (clients.Count == 0) { - GameMain.Server.ServerSettings.BanList.BanPlayer("Unnamed", endpoint, reason, banDuration); + GameMain.Server.ServerSettings.BanList.BanPlayer("Unnamed", address, reason, banDuration); } else { @@ -1510,8 +1510,8 @@ namespace Barotrauma (Client client, Vector2 cursorPos, string[] args) => { if (args.Length < 1) { return; } - if (!(Endpoint.Parse(args[0]).TryUnwrap(out var endpoint))) { return; } - var clients = GameMain.Server.ConnectedClients.Where(c => c.EndpointMatches(endpoint)).ToList(); + if (!(Address.Parse(args[0]).TryUnwrap(out var address))) { return; } + var clients = GameMain.Server.ConnectedClients.Where(c => c.AddressMatches(address)).ToList(); TimeSpan? duration = null; if (args.Length > 1) { @@ -1530,7 +1530,7 @@ namespace Barotrauma if (clients.Count == 0) { - GameMain.Server.ServerSettings.BanList.BanPlayer("Unnamed", endpoint, reason, duration); + GameMain.Server.ServerSettings.BanList.BanPlayer("Unnamed", address, reason, duration); } else { @@ -1866,20 +1866,17 @@ namespace Barotrauma } foreach (var talentTree in talentTrees) - { - foreach (var subTree in talentTree.TalentSubTrees) + { + foreach (var talentId in talentTree.AllTalentIdentifiers) { - foreach (var option in subTree.TalentOptionStages) + if (TalentPrefab.TalentPrefabs.TryGet(talentId, out TalentPrefab talentPrefab)) { - foreach (var talent in option.Talents) - { - targetCharacter.GiveTalent(talent); - NewMessage($"Talent \"{talent.DisplayName}\" given to \"{targetCharacter.Name}\" by \"{client.Name}\"."); - GameMain.Server.SendConsoleMessage($"Gave talent \"{talent.DisplayName}\" to \"{targetCharacter.Name}\".", client); - NewMessage($"Unlocked talent \"{talent.DisplayName}\"."); - } + targetCharacter.GiveTalent(talentPrefab); + NewMessage($"Talent \"{talentPrefab.DisplayName}\" given to \"{targetCharacter.Name}\" by \"{client.Name}\"."); + GameMain.Server.SendConsoleMessage($"Gave talent \"{talentPrefab.DisplayName}\" to \"{targetCharacter.Name}\".", client); + NewMessage($"Unlocked talent \"{talentPrefab.DisplayName}\"."); } - } + } } } ); diff --git a/Barotrauma/BarotraumaServer/ServerSource/Events/EventActions/ConversationAction.cs b/Barotrauma/BarotraumaServer/ServerSource/Events/EventActions/ConversationAction.cs index 0336b9ed0..c4a043bbd 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Events/EventActions/ConversationAction.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Events/EventActions/ConversationAction.cs @@ -115,36 +115,36 @@ namespace Barotrauma public void ServerWrite(Character speaker, Client client, bool interrupt) { IWriteMessage outmsg = new WriteOnlyMessage(); - outmsg.Write((byte)ServerPacketHeader.EVENTACTION); - outmsg.Write((byte)EventManager.NetworkEventType.CONVERSATION); - outmsg.Write(Identifier); - outmsg.Write(EventSprite); - outmsg.Write((byte)DialogType); - outmsg.Write(ContinueConversation); + outmsg.WriteByte((byte)ServerPacketHeader.EVENTACTION); + outmsg.WriteByte((byte)EventManager.NetworkEventType.CONVERSATION); + outmsg.WriteUInt16(Identifier); + outmsg.WriteString(EventSprite); + outmsg.WriteByte((byte)DialogType); + outmsg.WriteBoolean(ContinueConversation); if (interrupt) { - outmsg.Write(speaker?.ID ?? Entity.NullEntityID); - outmsg.Write(string.Empty); - outmsg.Write(false); - outmsg.Write((byte)0); - outmsg.Write((byte)0); + outmsg.WriteUInt16(speaker?.ID ?? Entity.NullEntityID); + outmsg.WriteString(string.Empty); + outmsg.WriteBoolean(false); + outmsg.WriteByte((byte)0); + outmsg.WriteByte((byte)0); } else { - outmsg.Write(speaker?.ID ?? Entity.NullEntityID); - outmsg.Write(Text ?? string.Empty); - outmsg.Write(FadeToBlack); - outmsg.Write((byte)Options.Count); + outmsg.WriteUInt16(speaker?.ID ?? Entity.NullEntityID); + outmsg.WriteString(Text ?? string.Empty); + outmsg.WriteBoolean(FadeToBlack); + outmsg.WriteByte((byte)Options.Count); for (int i = 0; i < Options.Count; i++) { - outmsg.Write(Options[i].Text); + outmsg.WriteString(Options[i].Text); } int[] endings = GetEndingOptions(); - outmsg.Write((byte)endings.Length); + outmsg.WriteByte((byte)endings.Length); foreach (var end in endings) { - outmsg.Write((byte)end); + outmsg.WriteByte((byte)end); } } GameMain.Server?.ServerPeer?.Send(outmsg, client.Connection, DeliveryMethod.Reliable); diff --git a/Barotrauma/BarotraumaServer/ServerSource/Events/EventActions/StatusEffectAction.cs b/Barotrauma/BarotraumaServer/ServerSource/Events/EventActions/StatusEffectAction.cs index 6eccd6150..a8119efe2 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Events/EventActions/StatusEffectAction.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Events/EventActions/StatusEffectAction.cs @@ -10,14 +10,14 @@ namespace Barotrauma private void ServerWrite(IEnumerable targets) { IWriteMessage outmsg = new WriteOnlyMessage(); - outmsg.Write((byte)ServerPacketHeader.EVENTACTION); - outmsg.Write((byte)EventManager.NetworkEventType.STATUSEFFECT); - outmsg.Write(ParentEvent.Prefab.Identifier); - outmsg.Write((UInt16)actionIndex); - outmsg.Write((UInt16)targets.Count()); + outmsg.WriteByte((byte)ServerPacketHeader.EVENTACTION); + outmsg.WriteByte((byte)EventManager.NetworkEventType.STATUSEFFECT); + outmsg.WriteIdentifier(ParentEvent.Prefab.Identifier); + outmsg.WriteUInt16((UInt16)actionIndex); + outmsg.WriteUInt16((UInt16)targets.Count()); foreach (Entity target in targets) { - outmsg.Write(target.ID); + outmsg.WriteUInt16(target.ID); } foreach (Client c in GameMain.Server.ConnectedClients) { diff --git a/Barotrauma/BarotraumaServer/ServerSource/Events/Missions/AbandonedOutpostMission.cs b/Barotrauma/BarotraumaServer/ServerSource/Events/Missions/AbandonedOutpostMission.cs index 1ab83b7ab..bfa52267f 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Events/Missions/AbandonedOutpostMission.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Events/Missions/AbandonedOutpostMission.cs @@ -12,19 +12,19 @@ namespace Barotrauma public override void ServerWriteInitial(IWriteMessage msg, Client c) { base.ServerWriteInitial(msg, c); - msg.Write((ushort)spawnedItems.Count); + msg.WriteUInt16((ushort)spawnedItems.Count); foreach (Item item in spawnedItems) { item.WriteSpawnData(msg, item.ID, Entity.NullEntityID, 0, -1); } - msg.Write((byte)characters.Count); + msg.WriteByte((byte)characters.Count); foreach (Character character in characters) { character.WriteSpawnData(msg, character.ID, restrictMessageSize: false); - msg.Write(requireKill.Contains(character)); - msg.Write(requireRescue.Contains(character)); - msg.Write((ushort)characterItems[character].Count()); + msg.WriteBoolean(requireKill.Contains(character)); + msg.WriteBoolean(requireRescue.Contains(character)); + msg.WriteUInt16((ushort)characterItems[character].Count()); foreach (Item item in characterItems[character]) { item.WriteSpawnData(msg, item.ID, item.ParentInventory?.Owner?.ID ?? Entity.NullEntityID, 0, item.ParentInventory?.FindIndex(item) ?? -1); diff --git a/Barotrauma/BarotraumaServer/ServerSource/Events/Missions/AlienRuinMission.cs b/Barotrauma/BarotraumaServer/ServerSource/Events/Missions/AlienRuinMission.cs index dd8138d18..af7c2c1a9 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Events/Missions/AlienRuinMission.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Events/Missions/AlienRuinMission.cs @@ -7,12 +7,12 @@ namespace Barotrauma public override void ServerWriteInitial(IWriteMessage msg, Client c) { base.ServerWriteInitial(msg, c); - msg.Write((ushort)existingTargets.Count); + msg.WriteUInt16((ushort)existingTargets.Count); foreach (var t in existingTargets) { - msg.Write(t != null ? t.ID : Entity.NullEntityID); + msg.WriteUInt16(t != null ? t.ID : Entity.NullEntityID); } - msg.Write((ushort)spawnedTargets.Count); + msg.WriteUInt16((ushort)spawnedTargets.Count); foreach (var t in spawnedTargets) { t.WriteSpawnData(msg, t.ID, false); diff --git a/Barotrauma/BarotraumaServer/ServerSource/Events/Missions/CargoMission.cs b/Barotrauma/BarotraumaServer/ServerSource/Events/Missions/CargoMission.cs index 6b54790d7..3a144fa3b 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Events/Missions/CargoMission.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Events/Missions/CargoMission.cs @@ -7,7 +7,7 @@ namespace Barotrauma public override void ServerWriteInitial(IWriteMessage msg, Client c) { base.ServerWriteInitial(msg, c); - msg.Write((ushort)items.Count); + msg.WriteUInt16((ushort)items.Count); foreach (Item item in items) { item.WriteSpawnData(msg, diff --git a/Barotrauma/BarotraumaServer/ServerSource/Events/Missions/CombatMission.cs b/Barotrauma/BarotraumaServer/ServerSource/Events/Missions/CombatMission.cs index 5446c04e1..f7656922a 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Events/Missions/CombatMission.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Events/Missions/CombatMission.cs @@ -5,12 +5,16 @@ namespace Barotrauma { partial class CombatMission { + const float RoundEndDuration = 5.0f; + private readonly bool[] teamDead = new bool[2]; private List[] crews; private bool initialized = false; + private float roundEndTimer; + public override LocalizedString Description { get @@ -53,6 +57,7 @@ namespace Barotrauma { teamDead[0] = crews[0].All(c => c.IsDead || c.IsIncapacitated); teamDead[1] = crews[1].All(c => c.IsDead || c.IsIncapacitated); + if (teamDead[0] && teamDead[1]) { state = 1; } } if (state == 0) @@ -66,13 +71,17 @@ namespace Barotrauma GameMain.GameSession.WinningTeam = i == 0 ? CharacterTeamType.Team1 : CharacterTeamType.Team2; - state = 1; + //state 1 = team 1 won, 2 = team 2 won + State = i + 1; break; } } } else { + roundEndTimer -= deltaTime; + if (roundEndTimer > 0.0f) { return; } + if (teamDead[0] && teamDead[1]) { GameMain.GameSession.WinningTeam = CharacterTeamType.None; @@ -81,7 +90,7 @@ namespace Barotrauma else if (GameMain.GameSession.WinningTeam != CharacterTeamType.None) { GameMain.Server.EndGame(); - } + } } } } diff --git a/Barotrauma/BarotraumaServer/ServerSource/Events/Missions/EscortMission.cs b/Barotrauma/BarotraumaServer/ServerSource/Events/Missions/EscortMission.cs index dea3acc83..5415379fb 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Events/Missions/EscortMission.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Events/Missions/EscortMission.cs @@ -16,12 +16,12 @@ namespace Barotrauma throw new InvalidOperationException("Server attempted to write escort mission data when no characters had been spawned."); } - msg.Write((byte)characters.Count); + msg.WriteByte((byte)characters.Count); foreach (Character character in characters) { character.WriteSpawnData(msg, character.ID, restrictMessageSize: false); - msg.Write(terroristCharacters.Contains(character)); - msg.Write((ushort)characterItems[character].Count()); + msg.WriteBoolean(terroristCharacters.Contains(character)); + msg.WriteUInt16((ushort)characterItems[character].Count()); foreach (Item item in characterItems[character]) { item.WriteSpawnData(msg, item.ID, item.ParentInventory?.Owner?.ID ?? Entity.NullEntityID, 0, item.ParentInventory?.FindIndex(item) ?? -1); diff --git a/Barotrauma/BarotraumaServer/ServerSource/Events/Missions/MineralMission.cs b/Barotrauma/BarotraumaServer/ServerSource/Events/Missions/MineralMission.cs index ada2e763a..65a5653e8 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Events/Missions/MineralMission.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Events/Missions/MineralMission.cs @@ -7,17 +7,17 @@ namespace Barotrauma public override void ServerWriteInitial(IWriteMessage msg, Client c) { base.ServerWriteInitial(msg, c); - msg.Write((byte)caves.Count); + msg.WriteByte((byte)caves.Count); foreach (var cave in caves) { - msg.Write((byte)(Level.Loaded == null || !Level.Loaded.Caves.Contains(cave) ? 255 : Level.Loaded.Caves.IndexOf(cave))); + msg.WriteByte((byte)(Level.Loaded == null || !Level.Loaded.Caves.Contains(cave) ? 255 : Level.Loaded.Caves.IndexOf(cave))); } foreach (var kvp in spawnedResources) { - msg.Write((byte)kvp.Value.Count); + msg.WriteByte((byte)kvp.Value.Count); var rotation = resourceClusters[kvp.Key].Rotation; - msg.Write(rotation); + msg.WriteSingle(rotation); foreach (var r in kvp.Value) { r.WriteSpawnData(msg, r.ID, Entity.NullEntityID, 0, -1); @@ -26,11 +26,11 @@ namespace Barotrauma foreach (var kvp in relevantLevelResources) { - msg.Write(kvp.Key); - msg.Write((byte)kvp.Value.Length); + msg.WriteIdentifier(kvp.Key); + msg.WriteByte((byte)kvp.Value.Length); foreach (var i in kvp.Value) { - msg.Write(i.ID); + msg.WriteUInt16(i.ID); } } } diff --git a/Barotrauma/BarotraumaServer/ServerSource/Events/Missions/Mission.cs b/Barotrauma/BarotraumaServer/ServerSource/Events/Missions/Mission.cs index 064ccd3e3..433b33075 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Events/Missions/Mission.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Events/Missions/Mission.cs @@ -12,18 +12,22 @@ namespace Barotrauma LocalizedString header = messageIndex < Headers.Length ? Headers[messageIndex] : ""; LocalizedString message = messageIndex < Messages.Length ? Messages[messageIndex] : ""; + if (!message.IsNullOrEmpty()) + { + message = ModifyMessage(message, color: false); + } GameServer.Log($"{TextManager.Get("MissionInfo")}: {header} - {message}", ServerLog.MessageType.ServerMessage); } public virtual void ServerWriteInitial(IWriteMessage msg, Client c) { - msg.Write((ushort)State); + msg.WriteUInt16((ushort)State); } public virtual void ServerWrite(IWriteMessage msg) { - msg.Write((ushort)State); + msg.WriteUInt16((ushort)State); } } } \ No newline at end of file diff --git a/Barotrauma/BarotraumaServer/ServerSource/Events/Missions/MonsterMission.cs b/Barotrauma/BarotraumaServer/ServerSource/Events/Missions/MonsterMission.cs index 937e23511..9af7f048e 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Events/Missions/MonsterMission.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Events/Missions/MonsterMission.cs @@ -14,7 +14,7 @@ namespace Barotrauma throw new InvalidOperationException("Server attempted to write monster mission data when no monsters had been spawned."); } - msg.Write((byte)monsters.Count); + msg.WriteByte((byte)monsters.Count); foreach (Character monster in monsters) { monster.WriteSpawnData(msg, monster.ID, restrictMessageSize: false); diff --git a/Barotrauma/BarotraumaServer/ServerSource/Events/Missions/NestMission.cs b/Barotrauma/BarotraumaServer/ServerSource/Events/Missions/NestMission.cs index f8e974834..35649469e 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Events/Missions/NestMission.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Events/Missions/NestMission.cs @@ -9,10 +9,10 @@ namespace Barotrauma public override void ServerWriteInitial(IWriteMessage msg, Client c) { base.ServerWriteInitial(msg, c); - msg.Write((byte)(selectedCave == null || Level.Loaded == null || !Level.Loaded.Caves.Contains(selectedCave) ? 255 : Level.Loaded.Caves.IndexOf(selectedCave))); - msg.Write(nestPosition.X); - msg.Write(nestPosition.Y); - msg.Write((ushort)items.Count); + msg.WriteByte((byte)(selectedCave == null || Level.Loaded == null || !Level.Loaded.Caves.Contains(selectedCave) ? 255 : Level.Loaded.Caves.IndexOf(selectedCave))); + msg.WriteSingle(nestPosition.X); + msg.WriteSingle(nestPosition.Y); + msg.WriteUInt16((ushort)items.Count); foreach (Item item in items) { item.WriteSpawnData(msg, item.ID, Entity.NullEntityID, 0, -1); diff --git a/Barotrauma/BarotraumaServer/ServerSource/Events/Missions/PirateMission.cs b/Barotrauma/BarotraumaServer/ServerSource/Events/Missions/PirateMission.cs index c04b48601..3295780ce 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Events/Missions/PirateMission.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Events/Missions/PirateMission.cs @@ -17,11 +17,11 @@ namespace Barotrauma throw new InvalidOperationException("Server attempted to write escort mission data when no characters had been spawned."); } - msg.Write((byte)characters.Count); + msg.WriteByte((byte)characters.Count); foreach (Character character in characters) { character.WriteSpawnData(msg, character.ID, restrictMessageSize: false); - msg.Write((ushort)characterItems[character].Count()); + msg.WriteUInt16((ushort)characterItems[character].Count()); foreach (Item item in characterItems[character]) { item.WriteSpawnData(msg, item.ID, item.ParentInventory?.Owner?.ID ?? Entity.NullEntityID, 0, item.ParentInventory?.FindIndex(item) ?? -1); diff --git a/Barotrauma/BarotraumaServer/ServerSource/Events/Missions/SalvageMission.cs b/Barotrauma/BarotraumaServer/ServerSource/Events/Missions/SalvageMission.cs index cdc8e3622..52a944a4e 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Events/Missions/SalvageMission.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Events/Missions/SalvageMission.cs @@ -18,21 +18,21 @@ namespace Barotrauma { base.ServerWriteInitial(msg, c); - msg.Write(usedExistingItem); + msg.WriteBoolean(usedExistingItem); if (usedExistingItem) { - msg.Write(item.ID); + msg.WriteUInt16(item.ID); } else { item.WriteSpawnData(msg, item.ID, originalInventoryID, originalItemContainerIndex, originalSlotIndex); } - msg.Write((byte)executedEffectIndices.Count); + msg.WriteByte((byte)executedEffectIndices.Count); foreach (Pair effectIndex in executedEffectIndices) { - msg.Write((byte)effectIndex.First); - msg.Write((byte)effectIndex.Second); + msg.WriteByte((byte)effectIndex.First); + msg.WriteByte((byte)effectIndex.Second); } } } diff --git a/Barotrauma/BarotraumaServer/ServerSource/Events/Missions/ScanMission.cs b/Barotrauma/BarotraumaServer/ServerSource/Events/Missions/ScanMission.cs index 010ed0224..ec766fd9a 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Events/Missions/ScanMission.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Events/Missions/ScanMission.cs @@ -7,7 +7,7 @@ namespace Barotrauma public override void ServerWriteInitial(IWriteMessage msg, Client c) { base.ServerWriteInitial(msg, c); - msg.Write((ushort)startingItems.Count); + msg.WriteUInt16((ushort)startingItems.Count); foreach (var item in startingItems) { item.WriteSpawnData(msg, @@ -27,11 +27,11 @@ namespace Barotrauma private void ServerWriteScanTargetStatus(IWriteMessage msg) { - msg.Write((byte)scanTargets.Count); + msg.WriteByte((byte)scanTargets.Count); foreach (var kvp in scanTargets) { - msg.Write(kvp.Key != null ? kvp.Key.ID : Entity.NullEntityID); - msg.Write(kvp.Value); + msg.WriteUInt16(kvp.Key != null ? kvp.Key.ID : Entity.NullEntityID); + msg.WriteBoolean(kvp.Value); } } } diff --git a/Barotrauma/BarotraumaServer/ServerSource/GameSession/CrewManager.cs b/Barotrauma/BarotraumaServer/ServerSource/GameSession/CrewManager.cs index 2c7358b04..c14233f30 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/GameSession/CrewManager.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/GameSession/CrewManager.cs @@ -47,7 +47,7 @@ namespace Barotrauma public void ServerWriteActiveOrders(IWriteMessage msg) { ushort count = (ushort)ActiveOrders.Count(o => o.Order != null && !o.FadeOutTime.HasValue); - msg.Write(count); + msg.WriteUInt16(count); if (count > 0) { foreach (var activeOrder in ActiveOrders) @@ -55,10 +55,10 @@ namespace Barotrauma if (!(activeOrder?.Order is Order order) || activeOrder.FadeOutTime.HasValue) { continue; } OrderChatMessage.WriteOrder(msg, order, null, isNewOrder: true); bool hasOrderGiver = order.OrderGiver != null; - msg.Write(hasOrderGiver); + msg.WriteBoolean(hasOrderGiver); if (hasOrderGiver) { - msg.Write(order.OrderGiver.ID); + msg.WriteUInt16(order.OrderGiver.ID); } } } diff --git a/Barotrauma/BarotraumaServer/ServerSource/GameSession/GameModes/MultiPlayerCampaign.cs b/Barotrauma/BarotraumaServer/ServerSource/GameSession/GameModes/MultiPlayerCampaign.cs index e9d0dfbe0..accb5e13a 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/GameSession/GameModes/MultiPlayerCampaign.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/GameSession/GameModes/MultiPlayerCampaign.cs @@ -575,57 +575,57 @@ namespace Barotrauma NetFlags requiredFlags = lastUpdateID.Keys.Where(k => IsFlagRequired(c, k)).Aggregate((NetFlags)0, (f1, f2) => f1 | f2); - msg.Write((UInt16)requiredFlags); + msg.WriteUInt16((UInt16)requiredFlags); - msg.Write(IsFirstRound); - msg.Write(CampaignID); - msg.Write(lastSaveID); - msg.Write(map.Seed); + msg.WriteBoolean(IsFirstRound); + msg.WriteByte(CampaignID); + msg.WriteUInt16(lastSaveID); + msg.WriteString(map.Seed); if (requiredFlags.HasFlag(NetFlags.Misc)) { - msg.Write(GetLastUpdateIdForFlag(NetFlags.Misc)); - msg.Write(PurchasedHullRepairs); - msg.Write(PurchasedItemRepairs); - msg.Write(PurchasedLostShuttles); + msg.WriteUInt16(GetLastUpdateIdForFlag(NetFlags.Misc)); + msg.WriteBoolean(PurchasedHullRepairs); + msg.WriteBoolean(PurchasedItemRepairs); + msg.WriteBoolean(PurchasedLostShuttles); } if (requiredFlags.HasFlag(NetFlags.MapAndMissions)) { - msg.Write(GetLastUpdateIdForFlag(NetFlags.MapAndMissions)); - msg.Write(ForceMapUI); - msg.Write(map.AllowDebugTeleport); - msg.Write(map.CurrentLocationIndex == -1 ? UInt16.MaxValue : (UInt16)map.CurrentLocationIndex); - msg.Write(map.SelectedLocationIndex == -1 ? UInt16.MaxValue : (UInt16)map.SelectedLocationIndex); + msg.WriteUInt16(GetLastUpdateIdForFlag(NetFlags.MapAndMissions)); + msg.WriteBoolean(ForceMapUI); + msg.WriteBoolean(map.AllowDebugTeleport); + msg.WriteUInt16(map.CurrentLocationIndex == -1 ? UInt16.MaxValue : (UInt16)map.CurrentLocationIndex); + msg.WriteUInt16(map.SelectedLocationIndex == -1 ? UInt16.MaxValue : (UInt16)map.SelectedLocationIndex); if (map.CurrentLocation != null) { - msg.Write((byte)map.CurrentLocation.AvailableMissions.Count()); + msg.WriteByte((byte)map.CurrentLocation.AvailableMissions.Count()); foreach (Mission mission in map.CurrentLocation.AvailableMissions) { - msg.Write(mission.Prefab.Identifier); + msg.WriteIdentifier(mission.Prefab.Identifier); if (mission.Locations[0] == mission.Locations[1]) { - msg.Write((byte)255); + msg.WriteByte((byte)255); } else { Location missionDestination = mission.Locations[0] == map.CurrentLocation ? mission.Locations[1] : mission.Locations[0]; LocationConnection connection = map.CurrentLocation.Connections.Find(c => c.OtherLocation(map.CurrentLocation) == missionDestination); - msg.Write((byte)map.CurrentLocation.Connections.IndexOf(connection)); + msg.WriteByte((byte)map.CurrentLocation.Connections.IndexOf(connection)); } } } else { - msg.Write((byte)0); + msg.WriteByte((byte)0); } var selectedMissionIndices = map.GetSelectedMissionIndices(); - msg.Write((byte)selectedMissionIndices.Count()); + msg.WriteByte((byte)selectedMissionIndices.Count()); foreach (int selectedMissionIndex in selectedMissionIndices) { - msg.Write((byte)selectedMissionIndex); + msg.WriteByte((byte)selectedMissionIndex); } WriteStores(msg); @@ -633,7 +633,7 @@ namespace Barotrauma if (requiredFlags.HasFlag(NetFlags.SubList)) { - msg.Write(GetLastUpdateIdForFlag(NetFlags.SubList)); + msg.WriteUInt16(GetLastUpdateIdForFlag(NetFlags.SubList)); var subList = GameMain.NetLobbyScreen.GetSubList(); List ownedSubmarineIndices = new List(); for (int i = 0; i < subList.Count; i++) @@ -643,83 +643,83 @@ namespace Barotrauma ownedSubmarineIndices.Add(i); } } - msg.Write((ushort)ownedSubmarineIndices.Count); + msg.WriteUInt16((ushort)ownedSubmarineIndices.Count); foreach (int index in ownedSubmarineIndices) { - msg.Write((ushort)index); + msg.WriteUInt16((ushort)index); } } if (requiredFlags.HasFlag(NetFlags.UpgradeManager)) { - msg.Write(GetLastUpdateIdForFlag(NetFlags.UpgradeManager)); - msg.Write((ushort)UpgradeManager.PendingUpgrades.Count); + msg.WriteUInt16(GetLastUpdateIdForFlag(NetFlags.UpgradeManager)); + msg.WriteUInt16((ushort)UpgradeManager.PendingUpgrades.Count); foreach (var (prefab, category, level) in UpgradeManager.PendingUpgrades) { - msg.Write(prefab.Identifier); - msg.Write(category.Identifier); - msg.Write((byte)level); + msg.WriteIdentifier(prefab.Identifier); + msg.WriteIdentifier(category.Identifier); + msg.WriteByte((byte)level); } - msg.Write((ushort)UpgradeManager.PurchasedItemSwaps.Count); + msg.WriteUInt16((ushort)UpgradeManager.PurchasedItemSwaps.Count); foreach (var itemSwap in UpgradeManager.PurchasedItemSwaps) { - msg.Write(itemSwap.ItemToRemove.ID); - msg.Write(itemSwap.ItemToInstall?.Identifier ?? Identifier.Empty); + msg.WriteUInt16(itemSwap.ItemToRemove.ID); + msg.WriteIdentifier(itemSwap.ItemToInstall?.Identifier ?? Identifier.Empty); } } if (requiredFlags.HasFlag(NetFlags.ItemsInBuyCrate)) { - msg.Write(GetLastUpdateIdForFlag(NetFlags.ItemsInBuyCrate)); + msg.WriteUInt16(GetLastUpdateIdForFlag(NetFlags.ItemsInBuyCrate)); WriteItems(msg, CargoManager.ItemsInBuyCrate); WriteStores(msg); } if (requiredFlags.HasFlag(NetFlags.ItemsInSellFromSubCrate)) { - msg.Write(GetLastUpdateIdForFlag(NetFlags.ItemsInSellFromSubCrate)); + msg.WriteUInt16(GetLastUpdateIdForFlag(NetFlags.ItemsInSellFromSubCrate)); WriteItems(msg, CargoManager.ItemsInSellFromSubCrate); WriteStores(msg); } if (requiredFlags.HasFlag(NetFlags.PurchasedItems)) { - msg.Write(GetLastUpdateIdForFlag(NetFlags.PurchasedItems)); + msg.WriteUInt16(GetLastUpdateIdForFlag(NetFlags.PurchasedItems)); WriteItems(msg, CargoManager.PurchasedItems); WriteStores(msg); } if (requiredFlags.HasFlag(NetFlags.SoldItems)) { - msg.Write(GetLastUpdateIdForFlag(NetFlags.SoldItems)); + msg.WriteUInt16(GetLastUpdateIdForFlag(NetFlags.SoldItems)); WriteItems(msg, CargoManager.SoldItems); WriteStores(msg); } if (requiredFlags.HasFlag(NetFlags.Reputation)) { - msg.Write(GetLastUpdateIdForFlag(NetFlags.Reputation)); + msg.WriteUInt16(GetLastUpdateIdForFlag(NetFlags.Reputation)); Reputation reputation = Map?.CurrentLocation?.Reputation; - msg.Write(reputation != null); - if (reputation != null) { msg.Write(reputation.Value); } + msg.WriteBoolean(reputation != null); + if (reputation != null) { msg.WriteSingle(reputation.Value); } // hopefully we'll never have more than 128 factions - msg.Write((byte)Factions.Count); + msg.WriteByte((byte)Factions.Count); foreach (Faction faction in Factions) { - msg.Write(faction.Prefab.Identifier); - msg.Write(faction.Reputation.Value); + msg.WriteIdentifier(faction.Prefab.Identifier); + msg.WriteSingle(faction.Reputation.Value); } } if (requiredFlags.HasFlag(NetFlags.CharacterInfo)) { - msg.Write(GetLastUpdateIdForFlag(NetFlags.CharacterInfo)); + msg.WriteUInt16(GetLastUpdateIdForFlag(NetFlags.CharacterInfo)); var characterData = GetClientCharacterData(c); if (characterData?.CharacterInfo == null) { - msg.Write(false); + msg.WriteBoolean(false); } else { - msg.Write(true); + msg.WriteBoolean(true); characterData.CharacterInfo.ServerWrite(msg); } } @@ -730,22 +730,22 @@ namespace Barotrauma { // Store balance bool hasStores = map.CurrentLocation.Stores != null && map.CurrentLocation.Stores.Any(); - msg.Write(hasStores); + msg.WriteBoolean(hasStores); if (hasStores) { - msg.Write((byte)map.CurrentLocation.Stores.Count); + msg.WriteByte((byte)map.CurrentLocation.Stores.Count); foreach (var store in map.CurrentLocation.Stores.Values) { - msg.Write(store.Identifier); - msg.Write((UInt16)store.Balance); + msg.WriteIdentifier(store.Identifier); + msg.WriteUInt16((UInt16)store.Balance); } } } else { - msg.Write((byte)0); + msg.WriteByte((byte)0); // Store balance - msg.Write(false); + msg.WriteBoolean(false); } } } @@ -897,9 +897,10 @@ namespace Barotrauma { if (map?.CurrentLocation?.Stores == null || !map.CurrentLocation.Stores.ContainsKey(store.Key)) { continue; } int availableQuantity = map.CurrentLocation.Stores[store.Key].Stock.Find(s => s.ItemPrefab == item.ItemPrefab)?.Quantity ?? 0; - int alreadyPurchasedQuantity = CargoManager.GetBuyCrateItem(store.Key, item.ItemPrefab)?.Quantity ?? 0; - item.Quantity = Math.Min(availableQuantity - alreadyPurchasedQuantity, item.Quantity); - if (item.Quantity <= 0) { continue; } + int alreadyPurchasedQuantity = + CargoManager.GetBuyCrateItem(store.Key, item.ItemPrefab)?.Quantity ?? 0 + + CargoManager.GetPurchasedItem(store.Key, item.ItemPrefab)?.Quantity ?? 0; + item.Quantity = MathHelper.Clamp(item.Quantity, 0, availableQuantity - alreadyPurchasedQuantity); CargoManager.ModifyItemQuantityInBuyCrate(store.Key, item.ItemPrefab, item.Quantity, sender); } } @@ -909,13 +910,22 @@ namespace Barotrauma { prevPurchasedItems.Add(kvp.Key, new List(kvp.Value)); } - foreach (var store in prevPurchasedItems) + foreach (var kvp in prevPurchasedItems) { - CargoManager.SellBackPurchasedItems(store.Key, store.Value, sender); + CargoManager.SellBackPurchasedItems(kvp.Key, kvp.Value, sender); } - foreach (var store in purchasedItems) + + foreach (var kvp in purchasedItems) { - CargoManager.PurchaseItems(store.Key, store.Value, false, sender); + foreach (var purchasedItemList in purchasedItems.Values) + { + foreach (var purchasedItem in purchasedItemList) + { + int availableQuantity = map.CurrentLocation.Stores[kvp.Key].Stock.Find(s => s.ItemPrefab == purchasedItem.ItemPrefab)?.Quantity ?? 0; + purchasedItem.Quantity = Math.Min(purchasedItem.Quantity, availableQuantity); + } + } + CargoManager.PurchaseItems(kvp.Key, kvp.Value, false, sender); } foreach (var (storeIdentifier, items) in CargoManager.PurchasedItems) @@ -1264,41 +1274,41 @@ namespace Barotrauma foreach (Client client in GameMain.Server.ConnectedClients) { IWriteMessage msg = new WriteOnlyMessage(); - msg.Write((byte)ServerPacketHeader.CREW); + msg.WriteByte((byte)ServerPacketHeader.CREW); - msg.Write((ushort)availableHires.Count); + msg.WriteUInt16((ushort)availableHires.Count); foreach (CharacterInfo hire in availableHires) { hire.ServerWrite(msg); - msg.Write(hire.Salary); + msg.WriteInt32(hire.Salary); } - msg.Write((ushort)pendingHires.Count); + msg.WriteUInt16((ushort)pendingHires.Count); foreach (CharacterInfo pendingHire in pendingHires) { - msg.Write(pendingHire.GetIdentifierUsingOriginalName()); + msg.WriteInt32(pendingHire.GetIdentifierUsingOriginalName()); } - msg.Write((ushort)(hiredCharacters?.Count ?? 0)); + msg.WriteUInt16((ushort)(hiredCharacters?.Count ?? 0)); if(hiredCharacters != null) { foreach (CharacterInfo info in hiredCharacters) { info.ServerWrite(msg); - msg.Write(info.Salary); + msg.WriteInt32(info.Salary); } } bool validRenaming = renamedCrewMember.id > -1 && !string.IsNullOrEmpty(renamedCrewMember.newName); - msg.Write(validRenaming); + msg.WriteBoolean(validRenaming); if (validRenaming) { - msg.Write(renamedCrewMember.id); - msg.Write(renamedCrewMember.newName); + msg.WriteInt32(renamedCrewMember.id); + msg.WriteString(renamedCrewMember.newName); } - msg.Write(firedCharacter != null); - if (firedCharacter != null) { msg.Write(firedCharacter.GetIdentifier()); } + msg.WriteBoolean(firedCharacter != null); + if (firedCharacter != null) { msg.WriteInt32(firedCharacter.GetIdentifier()); } GameMain.Server.ServerPeer.Send(msg, client.Connection, DeliveryMethod.Reliable); } diff --git a/Barotrauma/BarotraumaServer/ServerSource/GameSession/MedicalClinic.cs b/Barotrauma/BarotraumaServer/ServerSource/GameSession/MedicalClinic.cs index e9c23978c..e30b1148f 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/GameSession/MedicalClinic.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/GameSession/MedicalClinic.cs @@ -154,7 +154,7 @@ namespace Barotrauma private IWriteMessage StartSending() { IWriteMessage msg = new WriteOnlyMessage(); - msg.Write((byte)ServerPacketHeader.MEDICAL); + msg.WriteByte((byte)ServerPacketHeader.MEDICAL); return msg; } @@ -181,8 +181,8 @@ namespace Barotrauma } IWriteMessage msg = StartSending(); - msg.Write((byte)header); - msg.Write((byte)flag); + msg.WriteByte((byte)header); + msg.WriteByte((byte)flag); netStruct?.Write(msg); GameMain.Server.ServerPeer.Send(msg, c.Connection, deliveryMethod); } diff --git a/Barotrauma/BarotraumaServer/ServerSource/GameSession/ReadyCheck.cs b/Barotrauma/BarotraumaServer/ServerSource/GameSession/ReadyCheck.cs index d7e547b2b..13411d051 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/GameSession/ReadyCheck.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/GameSession/ReadyCheck.cs @@ -17,26 +17,26 @@ namespace Barotrauma if (client != null && !client.Spectating) { IWriteMessage msg = new WriteOnlyMessage(); - msg.Write((byte) ServerPacketHeader.READY_CHECK); - msg.Write((byte) ReadyCheckState.Start); - msg.Write(new DateTimeOffset(startTime).ToUnixTimeSeconds()); - msg.Write(new DateTimeOffset(endTime).ToUnixTimeSeconds()); - msg.Write(author); + msg.WriteByte((byte)ServerPacketHeader.READY_CHECK); + msg.WriteByte((byte)ReadyCheckState.Start); + msg.WriteInt64(new DateTimeOffset(startTime).ToUnixTimeSeconds()); + msg.WriteInt64(new DateTimeOffset(endTime).ToUnixTimeSeconds()); + msg.WriteString(author); if (sender != null) { - msg.Write(true); - msg.Write(sender.SessionId); + msg.WriteBoolean(true); + msg.WriteByte(sender.SessionId); } else { - msg.Write(false); + msg.WriteBoolean(false); } - msg.Write((ushort) ActivePlayers.Count); + msg.WriteUInt16((ushort)ActivePlayers.Count); foreach (byte clientId in Clients.Keys) { - msg.Write(clientId); + msg.WriteByte(clientId); } GameMain.Server.ServerPeer.Send(msg, client.Connection, DeliveryMethod.Reliable); @@ -55,10 +55,10 @@ namespace Barotrauma foreach (Client client in ActivePlayers) { IWriteMessage msg = new WriteOnlyMessage(); - msg.Write((byte)ServerPacketHeader.READY_CHECK); - msg.Write((byte)ReadyCheckState.Update); - msg.Write((byte)state); - msg.Write(otherClient); + msg.WriteByte((byte)ServerPacketHeader.READY_CHECK); + msg.WriteByte((byte)ReadyCheckState.Update); + msg.WriteByte((byte)state); + msg.WriteByte(otherClient); GameMain.Server.ServerPeer.Send(msg, client.Connection, DeliveryMethod.Reliable); } } @@ -72,13 +72,13 @@ namespace Barotrauma if (client != null && !client.Spectating) { IWriteMessage msg = new WriteOnlyMessage(); - msg.Write((byte) ServerPacketHeader.READY_CHECK); - msg.Write((byte) ReadyCheckState.End); - msg.Write((ushort) Clients.Count); + msg.WriteByte((byte)ServerPacketHeader.READY_CHECK); + msg.WriteByte((byte)ReadyCheckState.End); + msg.WriteUInt16((ushort)Clients.Count); foreach (var (id, state) in Clients) { - msg.Write(id); - msg.Write((byte) state); + msg.WriteByte(id); + msg.WriteByte((byte)state); } GameMain.Server.ServerPeer.Send(msg, client.Connection, DeliveryMethod.Reliable); @@ -88,7 +88,7 @@ namespace Barotrauma public static void ServerRead(IReadMessage inc, Client client) { - ReadyCheckState state = (ReadyCheckState) inc.ReadByte(); + ReadyCheckState state = (ReadyCheckState)inc.ReadByte(); ReadyCheck? readyCheck = GameMain.GameSession?.CrewManager?.ActiveReadyCheck; switch (state) @@ -98,7 +98,7 @@ namespace Barotrauma break; case ReadyCheckState.Update when readyCheck != null: - ReadyStatus status = (ReadyStatus) inc.ReadByte(); + ReadyStatus status = (ReadyStatus)inc.ReadByte(); if (!readyCheck.Clients.ContainsKey(client.SessionId)) { return; } readyCheck.Clients[client.SessionId] = status; diff --git a/Barotrauma/BarotraumaServer/ServerSource/Items/Components/DockingPort.cs b/Barotrauma/BarotraumaServer/ServerSource/Items/Components/DockingPort.cs index 607149e26..b5349e891 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Items/Components/DockingPort.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Items/Components/DockingPort.cs @@ -6,11 +6,11 @@ namespace Barotrauma.Items.Components { public void ServerEventWrite(IWriteMessage msg, Client c, NetEntityEvent.IData extraData = null) { - msg.Write(docked); + msg.WriteBoolean(docked); if (docked) { - msg.Write(DockingTarget.item.ID); - msg.Write(IsLocked); + msg.WriteUInt16(DockingTarget.item.ID); + msg.WriteBoolean(IsLocked); } } public void ServerEventRead(IReadMessage msg, Client c) diff --git a/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Door.cs b/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Door.cs index 3edb8ff4e..6f980eab7 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Door.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Door.cs @@ -38,13 +38,13 @@ namespace Barotrauma.Items.Components bool forcedOpen = TryExtractEventData(extraData, out var eventData) && eventData.ForcedOpen; base.ServerEventWrite(msg, c, extraData); - msg.Write(isOpen); - msg.Write(isBroken); - msg.Write(forcedOpen); //forced open - msg.Write(isStuck); - msg.Write(isJammed); + msg.WriteBoolean(isOpen); + msg.WriteBoolean(isBroken); + msg.WriteBoolean(forcedOpen); //forced open + msg.WriteBoolean(isStuck); + msg.WriteBoolean(isJammed); msg.WriteRangedSingle(stuck, 0.0f, 100.0f, 8); - msg.Write(lastUser == null ? (UInt16)0 : lastUser.ID); + msg.WriteUInt16(lastUser == null ? (UInt16)0 : lastUser.ID); } } } diff --git a/Barotrauma/BarotraumaServer/ServerSource/Items/Components/GeneticMaterial.cs b/Barotrauma/BarotraumaServer/ServerSource/Items/Components/GeneticMaterial.cs index ff82cc9d8..6951f65c5 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Items/Components/GeneticMaterial.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Items/Components/GeneticMaterial.cs @@ -6,14 +6,14 @@ namespace Barotrauma.Items.Components { public void ServerEventWrite(IWriteMessage msg, Client c, NetEntityEvent.IData extraData = null) { - msg.Write(tainted); + msg.WriteBoolean(tainted); if (tainted) { - msg.Write(selectedTaintedEffect?.UintIdentifier ?? 0); + msg.WriteUInt32(selectedTaintedEffect?.UintIdentifier ?? 0); } else { - msg.Write(selectedEffect?.UintIdentifier ?? 0); + msg.WriteUInt32(selectedEffect?.UintIdentifier ?? 0); } } } diff --git a/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Growable.cs b/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Growable.cs index 8fd930fc8..8749382f1 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Growable.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Growable.cs @@ -37,7 +37,7 @@ namespace Barotrauma.Items.Components public void ServerEventWrite(IWriteMessage msg, Client c, NetEntityEvent.IData extraData = null) { - msg.WriteRangedSingle(Health, 0f, (float) MaxHealth, 8); + msg.WriteRangedSingle(Health, 0f, (float)MaxHealth, 8); if (TryExtractEventData(extraData, out EventData eventData)) { int offset = eventData.Offset; @@ -48,11 +48,11 @@ namespace Barotrauma.Items.Components { VineTile vine = Vines[i]; var (x, y) = vine.Position; - msg.WriteRangedInteger((byte) vine.Type, 0b0000, 0b1111); + msg.WriteRangedInteger((byte)vine.Type, 0b0000, 0b1111); msg.WriteRangedInteger(vine.FlowerConfig.Serialize(), 0, 0xFFF); msg.WriteRangedInteger(vine.LeafConfig.Serialize(), 0, 0xFFF); - msg.Write((byte) (x / VineTile.Size)); - msg.Write((byte) (y / VineTile.Size)); + msg.WriteByte((byte)(x / VineTile.Size)); + msg.WriteByte((byte)(y / VineTile.Size)); } } else diff --git a/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Holdable/Holdable.cs b/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Holdable/Holdable.cs index 0b8521700..98c6a0fa9 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Holdable/Holdable.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Holdable/Holdable.cs @@ -10,13 +10,13 @@ namespace Barotrauma.Items.Components base.ServerEventWrite(msg, c, extraData); bool writeAttachData = attachable && body != null; - msg.Write(writeAttachData); + msg.WriteBoolean(writeAttachData); if (!writeAttachData) { return; } - msg.Write(Attached); - msg.Write(body.SimPosition.X); - msg.Write(body.SimPosition.Y); - msg.Write(item.Submarine?.ID ?? Entity.NullEntityID); + msg.WriteBoolean(Attached); + msg.WriteSingle(body.SimPosition.X); + msg.WriteSingle(body.SimPosition.Y); + msg.WriteUInt16(item.Submarine?.ID ?? Entity.NullEntityID); } public void ServerEventRead(IReadMessage msg, Client c) diff --git a/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Holdable/LevelResource.cs b/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Holdable/LevelResource.cs index 3d372c206..bd9a54c1d 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Holdable/LevelResource.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Holdable/LevelResource.cs @@ -8,7 +8,7 @@ namespace Barotrauma.Items.Components public void ServerEventWrite(IWriteMessage msg, Client c, NetEntityEvent.IData extraData = null) { - msg.Write(deattachTimer); + msg.WriteSingle(deattachTimer); } } } diff --git a/Barotrauma/BarotraumaServer/ServerSource/Items/Components/ItemLabel.cs b/Barotrauma/BarotraumaServer/ServerSource/Items/Components/ItemLabel.cs index ad7dd525f..dbcf85e4d 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Items/Components/ItemLabel.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Items/Components/ItemLabel.cs @@ -78,7 +78,7 @@ namespace Barotrauma.Items.Components public void ServerEventWrite(IWriteMessage msg, Client c, NetEntityEvent.IData extraData = null) { - msg.Write(Text); + msg.WriteString(Text); lastSentText = Text; } } diff --git a/Barotrauma/BarotraumaServer/ServerSource/Items/Components/LightComponent.cs b/Barotrauma/BarotraumaServer/ServerSource/Items/Components/LightComponent.cs index 4396628d9..bf7e8e2c4 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Items/Components/LightComponent.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Items/Components/LightComponent.cs @@ -38,7 +38,7 @@ namespace Barotrauma.Items.Components public void ServerEventWrite(IWriteMessage msg, Client c, NetEntityEvent.IData extraData = null) { - msg.Write(IsActive); + msg.WriteBoolean(IsActive); lastSentState = IsActive; } } diff --git a/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Machines/Controller.cs b/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Machines/Controller.cs index dc87c0b4a..8d8fe2933 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Machines/Controller.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Machines/Controller.cs @@ -6,8 +6,8 @@ namespace Barotrauma.Items.Components { public void ServerEventWrite(IWriteMessage msg, Client c, NetEntityEvent.IData extraData = null) { - msg.Write(State); - msg.Write(user == null ? (ushort)0 : user.ID); + msg.WriteBoolean(State); + msg.WriteUInt16(user == null ? (ushort)0 : user.ID); } } } diff --git a/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Machines/Deconstructor.cs b/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Machines/Deconstructor.cs index 9897bc414..91b7515b2 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Machines/Deconstructor.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Machines/Deconstructor.cs @@ -18,9 +18,9 @@ namespace Barotrauma.Items.Components public void ServerEventWrite(IWriteMessage msg, Client c, NetEntityEvent.IData extraData = null) { - msg.Write(user?.ID ?? 0); - msg.Write(IsActive); - msg.Write(progressTimer); + msg.WriteUInt16(user?.ID ?? 0); + msg.WriteBoolean(IsActive); + msg.WriteSingle(progressTimer); } } } diff --git a/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Machines/Engine.cs b/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Machines/Engine.cs index a1f431279..b611a9b7f 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Machines/Engine.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Machines/Engine.cs @@ -9,7 +9,7 @@ namespace Barotrauma.Items.Components { //force can only be adjusted at 10% intervals -> no need for more accuracy than this msg.WriteRangedInteger((int)(targetForce / 10.0f), -10, 10); - msg.Write(User == null ? Entity.NullEntityID : User.ID); + msg.WriteUInt16(User == null ? Entity.NullEntityID : User.ID); } public void ServerEventRead(IReadMessage msg, Client c) diff --git a/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Machines/Fabricator.cs b/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Machines/Fabricator.cs index bd1572c90..c3a383431 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Machines/Fabricator.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Machines/Fabricator.cs @@ -55,18 +55,18 @@ namespace Barotrauma.Items.Components public void ServerEventWrite(IWriteMessage msg, Client c, NetEntityEvent.IData extraData = null) { var componentData = ExtractEventData(extraData); - msg.Write((byte)componentData.State); - msg.Write(timeUntilReady); + msg.WriteByte((byte)componentData.State); + msg.WriteSingle(timeUntilReady); uint recipeHash = fabricatedItem?.RecipeHash ?? 0; - msg.Write(recipeHash); + msg.WriteUInt32(recipeHash); UInt16 userId = fabricatedItem is null || user is null ? (UInt16)0 : user.ID; - msg.Write(userId); + msg.WriteUInt16(userId); var reachedLimits = fabricationLimits.Where(kvp => kvp.Value <= 0); - msg.Write((ushort)reachedLimits.Count()); + msg.WriteUInt16((ushort)reachedLimits.Count()); foreach (var kvp in reachedLimits) { - msg.Write(kvp.Key); + msg.WriteUInt32(kvp.Key); } } } diff --git a/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Machines/Pump.cs b/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Machines/Pump.cs index 125557284..a026feea0 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Machines/Pump.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Machines/Pump.cs @@ -49,16 +49,16 @@ namespace Barotrauma.Items.Components { //flowpercentage can only be adjusted at 10% intervals -> no need for more accuracy than this msg.WriteRangedInteger((int)(flowPercentage / 10.0f), -10, 10); - msg.Write(IsActive); - msg.Write(Hijacked); + msg.WriteBoolean(IsActive); + msg.WriteBoolean(Hijacked); if (TargetLevel != null) { - msg.Write(true); - msg.Write(TargetLevel.Value); + msg.WriteBoolean(true); + msg.WriteSingle(TargetLevel.Value); } else { - msg.Write(false); + msg.WriteBoolean(false); } } } diff --git a/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Machines/Reactor.cs b/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Machines/Reactor.cs index 91f9f02ad..0cfbe9026 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Machines/Reactor.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Machines/Reactor.cs @@ -45,8 +45,8 @@ namespace Barotrauma.Items.Components public void ServerEventWrite(IWriteMessage msg, Client c, NetEntityEvent.IData extraData = null) { - msg.Write(autoTemp); - msg.Write(_powerOn); + msg.WriteBoolean(autoTemp); + msg.WriteBoolean(_powerOn); msg.WriteRangedSingle(temperature, 0.0f, 100.0f, 8); msg.WriteRangedSingle(TargetFissionRate, 0.0f, 100.0f, 8); msg.WriteRangedSingle(TargetTurbineOutput, 0.0f, 100.0f, 8); diff --git a/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Machines/Steering.cs b/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Machines/Steering.cs index 4145c0b35..f618c0a72 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Machines/Steering.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Machines/Steering.cs @@ -100,30 +100,30 @@ namespace Barotrauma.Items.Components public void ServerEventWrite(IWriteMessage msg, Barotrauma.Networking.Client c, NetEntityEvent.IData extraData = null) { - msg.Write(autoPilot); - msg.Write(TryExtractEventData(extraData, out var eventData) && eventData.DockingButtonClicked); - msg.Write(user?.ID ?? Entity.NullEntityID); + msg.WriteBoolean(autoPilot); + msg.WriteBoolean(TryExtractEventData(extraData, out var eventData) && eventData.DockingButtonClicked); + msg.WriteUInt16(user?.ID ?? Entity.NullEntityID); if (!autoPilot) { //no need to write steering info if autopilot is controlling - msg.Write(steeringInput.X); - msg.Write(steeringInput.Y); - msg.Write(targetVelocity.X); - msg.Write(targetVelocity.Y); - msg.Write(steeringAdjustSpeed); + msg.WriteSingle(steeringInput.X); + msg.WriteSingle(steeringInput.Y); + msg.WriteSingle(targetVelocity.X); + msg.WriteSingle(targetVelocity.Y); + msg.WriteSingle(steeringAdjustSpeed); } else { - msg.Write(posToMaintain != null); + msg.WriteBoolean(posToMaintain != null); if (posToMaintain != null) { - msg.Write(((Vector2)posToMaintain).X); - msg.Write(((Vector2)posToMaintain).Y); + msg.WriteSingle(((Vector2)posToMaintain).X); + msg.WriteSingle(((Vector2)posToMaintain).Y); } else { - msg.Write(LevelStartSelected); + msg.WriteBoolean(LevelStartSelected); } } } diff --git a/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Projectile.cs b/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Projectile.cs index 7bf233c95..60cc5c609 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Projectile.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Projectile.cs @@ -25,39 +25,39 @@ namespace Barotrauma.Items.Components var eventData = ExtractEventData(extraData); bool launch = eventData.Launch; - msg.Write(launch); + msg.WriteBoolean(launch); if (launch) { - msg.Write(User.ID); - msg.Write(launchPos.X); - msg.Write(launchPos.Y); - msg.Write(launchRot); + msg.WriteUInt16(User.ID); + msg.WriteSingle(launchPos.X); + msg.WriteSingle(launchPos.Y); + msg.WriteSingle(launchRot); } bool stuck = StickTarget != null && !item.Removed && !StickTargetRemoved(); - msg.Write(stuck); + msg.WriteBoolean(stuck); if (stuck) { - msg.Write(item.Submarine?.ID ?? Entity.NullEntityID); - msg.Write(item.CurrentHull?.ID ?? Entity.NullEntityID); - msg.Write(item.SimPosition.X); - msg.Write(item.SimPosition.Y); - msg.Write(jointAxis.X); - msg.Write(jointAxis.Y); + msg.WriteUInt16(item.Submarine?.ID ?? Entity.NullEntityID); + msg.WriteUInt16(item.CurrentHull?.ID ?? Entity.NullEntityID); + msg.WriteSingle(item.SimPosition.X); + msg.WriteSingle(item.SimPosition.Y); + msg.WriteSingle(jointAxis.X); + msg.WriteSingle(jointAxis.Y); if (StickTarget.UserData is Structure structure) { - msg.Write(structure.ID); + msg.WriteUInt16(structure.ID); int bodyIndex = structure.Bodies.IndexOf(StickTarget); - msg.Write((byte)(bodyIndex == -1 ? 0 : bodyIndex)); + msg.WriteByte((byte)(bodyIndex == -1 ? 0 : bodyIndex)); } else if (StickTarget.UserData is Entity entity) { - msg.Write(entity.ID); + msg.WriteUInt16(entity.ID); } else if (StickTarget.UserData is Limb limb) { - msg.Write(limb.character.ID); - msg.Write((byte)Array.IndexOf(limb.character.AnimController.Limbs, limb)); + msg.WriteUInt16(limb.character.ID); + msg.WriteByte((byte)Array.IndexOf(limb.character.AnimController.Limbs, limb)); } else { diff --git a/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Repairable.cs b/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Repairable.cs index 41d2f5c1d..e4e5845c9 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Repairable.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Repairable.cs @@ -44,13 +44,13 @@ namespace Barotrauma.Items.Components public void ServerEventWrite(IWriteMessage msg, Client c, NetEntityEvent.IData extraData = null) { - msg.Write(deteriorationTimer); - msg.Write(deteriorateAlwaysResetTimer); - msg.Write(DeteriorateAlways); - msg.Write(tinkeringDuration); - msg.Write(tinkeringStrength); - msg.Write(tinkeringPowersDevices); - msg.Write(CurrentFixer == null ? (ushort)0 : CurrentFixer.ID); + msg.WriteSingle(deteriorationTimer); + msg.WriteSingle(deteriorateAlwaysResetTimer); + msg.WriteBoolean(DeteriorateAlways); + msg.WriteSingle(tinkeringDuration); + msg.WriteSingle(tinkeringStrength); + msg.WriteBoolean(tinkeringPowersDevices); + msg.WriteUInt16(CurrentFixer == null ? (ushort)0 : CurrentFixer.ID); msg.WriteRangedInteger((int)currentFixerAction, 0, 2); } } diff --git a/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Rope.cs b/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Rope.cs index 81b46fe2a..11342ebed 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Rope.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Rope.cs @@ -6,25 +6,25 @@ namespace Barotrauma.Items.Components { public void ServerEventWrite(IWriteMessage msg, Client c, NetEntityEvent.IData extraData = null) { - msg.Write(Snapped); + msg.WriteBoolean(Snapped); if (!Snapped) { - msg.Write(target?.ID ?? Entity.NullEntityID); + msg.WriteUInt16(target?.ID ?? Entity.NullEntityID); if (source is Entity entity && !entity.Removed) { - msg.Write(entity?.ID ?? Entity.NullEntityID); - msg.Write((byte)0); + msg.WriteUInt16(entity?.ID ?? Entity.NullEntityID); + msg.WriteByte((byte)0); } else if (source is Limb limb && limb.character != null && !limb.character.Removed) { - msg.Write(limb.character?.ID ?? Entity.NullEntityID); - msg.Write((byte)limb.character.AnimController.Limbs.IndexOf(limb)); + msg.WriteUInt16(limb.character?.ID ?? Entity.NullEntityID); + msg.WriteByte((byte)limb.character.AnimController.Limbs.IndexOf(limb)); } else { - msg.Write(Entity.NullEntityID); - msg.Write((byte)0); + msg.WriteUInt16(Entity.NullEntityID); + msg.WriteByte((byte)0); } } } diff --git a/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Scanner.cs b/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Scanner.cs index 2af1acfea..3b1b85227 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Scanner.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Scanner.cs @@ -8,7 +8,7 @@ namespace Barotrauma.Items.Components public void ServerEventWrite(IWriteMessage msg, Client c, NetEntityEvent.IData extraData = null) { - msg.Write(scanTimer); + msg.WriteSingle(scanTimer); } } } diff --git a/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Signal/ConnectionPanel.cs b/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Signal/ConnectionPanel.cs index a9cffe9ef..7ba476df9 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Signal/ConnectionPanel.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Signal/ConnectionPanel.cs @@ -208,7 +208,7 @@ namespace Barotrauma.Items.Components public void ServerEventWrite(IWriteMessage msg, Client c, NetEntityEvent.IData extraData = null) { - msg.Write(user == null ? (ushort)0 : user.ID); + msg.WriteUInt16(user == null ? (ushort)0 : user.ID); ClientEventWrite(msg, extraData); } } diff --git a/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Signal/CustomInterface.cs b/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Signal/CustomInterface.cs index c1742cfa7..b103e8e7f 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Signal/CustomInterface.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Signal/CustomInterface.cs @@ -72,15 +72,15 @@ namespace Barotrauma.Items.Components var element = customInterfaceElementList[i]; if (element.HasPropertyName) { - msg.Write(element.Signal); + msg.WriteString(element.Signal); } else if(element.ContinuousSignal) { - msg.Write(element.State); + msg.WriteBoolean(element.State); } else { - msg.Write(extraData is Item.ComponentStateEventData { ComponentData: EventData eventData } && eventData.BtnElement == customInterfaceElementList[i]); + msg.WriteBoolean(extraData is Item.ComponentStateEventData { ComponentData: EventData eventData } && eventData.BtnElement == customInterfaceElementList[i]); } } } diff --git a/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Signal/MemoryComponent.cs b/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Signal/MemoryComponent.cs index d99732838..189f07c27 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Signal/MemoryComponent.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Signal/MemoryComponent.cs @@ -38,7 +38,7 @@ namespace Barotrauma.Items.Components public void ServerEventWrite(IWriteMessage msg, Client c, NetEntityEvent.IData extraData = null) { - msg.Write(Value); + msg.WriteString(Value); lastSentValue = Value; } } diff --git a/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Signal/Terminal.cs b/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Signal/Terminal.cs index 9fdd21863..8beb42942 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Signal/Terminal.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Signal/Terminal.cs @@ -101,11 +101,11 @@ namespace Barotrauma.Items.Components { if (TryExtractEventData(extraData, out ServerEventData eventData)) { - msg.Write(eventData.MsgToSend); + msg.WriteString(eventData.MsgToSend); } else { - msg.Write(OutputValue); + msg.WriteString(OutputValue); } } } diff --git a/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Signal/Wire.cs b/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Signal/Wire.cs index 51a0fa393..59adff519 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Signal/Wire.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Signal/Wire.cs @@ -41,8 +41,8 @@ namespace Barotrauma.Items.Components msg.WriteRangedInteger(nodeCount, 0, MaxNodesPerNetworkEvent); for (int i = nodeStartIndex; i < nodeStartIndex + nodeCount; i++) { - msg.Write(nodes[i].X); - msg.Write(nodes[i].Y); + msg.WriteSingle(nodes[i].X); + msg.WriteSingle(nodes[i].Y); } } diff --git a/Barotrauma/BarotraumaServer/ServerSource/Items/Item.cs b/Barotrauma/BarotraumaServer/ServerSource/Items/Item.cs index 32f261856..862478ce6 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Items/Item.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Items/Item.cs @@ -62,14 +62,14 @@ namespace Barotrauma throw error("component \"" + components[containerIndex] + "\" is not server serializable"); } msg.WriteRangedInteger(containerIndex, 0, components.Count - 1); - msg.Write(GameMain.Server.EntityEventManager.Events.Last()?.ID ?? (ushort)0); + msg.WriteUInt16(GameMain.Server.EntityEventManager.Events.Last()?.ID ?? (ushort)0); itemContainer.Inventory.ServerEventWrite(msg, c); break; case ItemStatusEventData _: - msg.Write(condition); + msg.WriteSingle(condition); break; case AssignCampaignInteractionEventData _: - msg.Write((byte)CampaignInteractionType); + msg.WriteByte((byte)CampaignInteractionType); break; case ApplyStatusEffectEventData applyStatusEffectEventData: { @@ -83,15 +83,15 @@ namespace Barotrauma byte targetLimbIndex = targetLimb != null && targetCharacter != null ? (byte)Array.IndexOf(targetCharacter.AnimController.Limbs, targetLimb) : (byte)255; msg.WriteRangedInteger((int)actionType, 0, Enum.GetValues(typeof(ActionType)).Length - 1); - msg.Write((byte)(targetComponent == null ? 255 : components.IndexOf(targetComponent))); - msg.Write(applyStatusEffectEventData.TargetCharacter?.ID ?? (ushort)0); - msg.Write(targetLimbIndex); - msg.Write(applyStatusEffectEventData.UseTarget?.ID ?? (ushort)0); - msg.Write(worldPosition.HasValue); + msg.WriteByte((byte)(targetComponent == null ? 255 : components.IndexOf(targetComponent))); + msg.WriteUInt16(applyStatusEffectEventData.TargetCharacter?.ID ?? (ushort)0); + msg.WriteByte(targetLimbIndex); + msg.WriteUInt16(applyStatusEffectEventData.UseTarget?.ID ?? (ushort)0); + msg.WriteBoolean(worldPosition.HasValue); if (worldPosition.HasValue) { - msg.Write(worldPosition.Value.X); - msg.Write(worldPosition.Value.Y); + msg.WriteSingle(worldPosition.Value.X); + msg.WriteSingle(worldPosition.Value.Y); } } break; @@ -109,16 +109,16 @@ namespace Barotrauma case UpgradeEventData upgradeEventData: var upgrade = upgradeEventData.Upgrade; var upgradeTargets = upgrade.TargetComponents; - msg.Write(upgrade.Identifier); - msg.Write((byte)upgrade.Level); - msg.Write((byte)upgradeTargets.Count); + msg.WriteIdentifier(upgrade.Identifier); + msg.WriteByte((byte)upgrade.Level); + msg.WriteByte((byte)upgradeTargets.Count); foreach (var (_, value) in upgrade.TargetComponents) { - msg.Write((byte)value.Length); + msg.WriteByte((byte)value.Length); foreach (var propertyReference in value) { object originalValue = propertyReference.OriginalValue; - msg.Write((float)(originalValue ?? -1)); + msg.WriteSingle((float)(originalValue ?? -1)); } } break; @@ -189,35 +189,35 @@ namespace Barotrauma { if (GameMain.Server == null) { return; } - msg.Write(Prefab.OriginalName); - msg.Write(Prefab.Identifier); - msg.Write(Description != base.Prefab.Description); + msg.WriteString(Prefab.OriginalName); + msg.WriteIdentifier(Prefab.Identifier); + msg.WriteBoolean(Description != base.Prefab.Description); if (Description != base.Prefab.Description) { - msg.Write(Description); + msg.WriteString(Description); } - msg.Write(entityID); + msg.WriteUInt16(entityID); if (ParentInventory == null || ParentInventory.Owner == null || originalInventoryID == 0) { - msg.Write((ushort)0); + msg.WriteUInt16((ushort)0); - msg.Write(Position.X); - msg.Write(Position.Y); + msg.WriteSingle(Position.X); + msg.WriteSingle(Position.Y); msg.WriteRangedSingle(body == null ? 0.0f : MathUtils.WrapAngleTwoPi(body.Rotation), 0.0f, MathHelper.TwoPi, 8); - msg.Write(Submarine != null ? Submarine.ID : (ushort)0); + msg.WriteUInt16(Submarine != null ? Submarine.ID : (ushort)0); } else { - msg.Write(originalInventoryID); - msg.Write(originalItemContainerIndex); - msg.Write(originalSlotIndex < 0 ? (byte)255 : (byte)originalSlotIndex); + msg.WriteUInt16(originalInventoryID); + msg.WriteByte(originalItemContainerIndex); + msg.WriteByte(originalSlotIndex < 0 ? (byte)255 : (byte)originalSlotIndex); } - msg.Write(body == null ? (byte)0 : (byte)body.BodyType); - msg.Write(SpawnedInCurrentOutpost); - msg.Write(AllowStealing); + msg.WriteByte(body == null ? (byte)0 : (byte)body.BodyType); + msg.WriteBoolean(SpawnedInCurrentOutpost); + msg.WriteBoolean(AllowStealing); msg.WriteRangedInteger(Quality, 0, Items.Components.Quality.MaxQuality); byte teamID = 0; @@ -237,39 +237,39 @@ namespace Barotrauma } } - msg.Write(teamID); + msg.WriteByte(teamID); bool hasIdCard = idCardComponent != null; - msg.Write(hasIdCard); + msg.WriteBoolean(hasIdCard); if (hasIdCard) { - msg.Write(idCardComponent.OwnerName); - msg.Write(idCardComponent.OwnerTags); - msg.Write((byte)Math.Max(0, idCardComponent.OwnerBeardIndex+1)); - msg.Write((byte)Math.Max(0, idCardComponent.OwnerHairIndex+1)); - msg.Write((byte)Math.Max(0, idCardComponent.OwnerMoustacheIndex+1)); - msg.Write((byte)Math.Max(0, idCardComponent.OwnerFaceAttachmentIndex+1)); + msg.WriteString(idCardComponent.OwnerName); + msg.WriteString(idCardComponent.OwnerTags); + msg.WriteByte((byte)Math.Max(0, idCardComponent.OwnerBeardIndex+1)); + msg.WriteByte((byte)Math.Max(0, idCardComponent.OwnerHairIndex+1)); + msg.WriteByte((byte)Math.Max(0, idCardComponent.OwnerMoustacheIndex+1)); + msg.WriteByte((byte)Math.Max(0, idCardComponent.OwnerFaceAttachmentIndex+1)); msg.WriteColorR8G8B8(idCardComponent.OwnerHairColor); msg.WriteColorR8G8B8(idCardComponent.OwnerFacialHairColor); msg.WriteColorR8G8B8(idCardComponent.OwnerSkinColor); - msg.Write(idCardComponent.OwnerJobId); - msg.Write((byte)idCardComponent.OwnerSheetIndex.X); - msg.Write((byte)idCardComponent.OwnerSheetIndex.Y); + msg.WriteIdentifier(idCardComponent.OwnerJobId); + msg.WriteByte((byte)idCardComponent.OwnerSheetIndex.X); + msg.WriteByte((byte)idCardComponent.OwnerSheetIndex.Y); } bool tagsChanged = tags.Count != base.Prefab.Tags.Count || !tags.All(t => base.Prefab.Tags.Contains(t)); - msg.Write(tagsChanged); + msg.WriteBoolean(tagsChanged); if (tagsChanged) { IEnumerable splitTags = Tags.Split(',').ToIdentifiers(); - msg.Write(string.Join(',', splitTags.Where(t => !base.Prefab.Tags.Contains(t)))); - msg.Write(string.Join(',', base.Prefab.Tags.Where(t => !splitTags.Contains(t)))); + msg.WriteString(string.Join(',', splitTags.Where(t => !base.Prefab.Tags.Contains(t)))); + msg.WriteString(string.Join(',', base.Prefab.Tags.Where(t => !splitTags.Contains(t)))); } var nameTag = GetComponent(); - msg.Write(nameTag != null); + msg.WriteBoolean(nameTag != null); if (nameTag != null) { - msg.Write(nameTag.WrittenName ?? ""); + msg.WriteString(nameTag.WrittenName ?? ""); } } @@ -342,12 +342,12 @@ namespace Barotrauma public void ServerWritePosition(IWriteMessage msg, Client c) { - msg.Write(ID); + msg.WriteUInt16(ID); IWriteMessage tempBuffer = new WriteOnlyMessage(); body.ServerWrite(tempBuffer); msg.WriteVariableUInt32((uint)tempBuffer.LengthBytes); - msg.Write(tempBuffer.Buffer, 0, tempBuffer.LengthBytes); + msg.WriteBytes(tempBuffer.Buffer, 0, tempBuffer.LengthBytes); msg.WritePadBits(); } diff --git a/Barotrauma/BarotraumaServer/ServerSource/Levels/Level.cs b/Barotrauma/BarotraumaServer/ServerSource/Levels/Level.cs index cdbd0c952..f9bf125de 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Levels/Level.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Levels/Level.cs @@ -32,21 +32,21 @@ namespace Barotrauma { if (!(extraData is IEventData eventData)) { throw new Exception($"Malformed level event: expected {nameof(Level)}.{nameof(IEventData)}"); } - msg.Write((byte)eventData.EventType); + msg.WriteByte((byte)eventData.EventType); switch (eventData) { case SingleLevelWallEventData { Wall: var destructibleWall }: int index = ExtraWalls.IndexOf(destructibleWall); - msg.Write((ushort)(index == -1 ? ushort.MaxValue : index)); + msg.WriteUInt16((ushort)(index == -1 ? ushort.MaxValue : index)); //write health using one byte - msg.Write((byte)MathHelper.Clamp((int)(MathUtils.InverseLerp(0.0f, destructibleWall.MaxHealth, destructibleWall.Damage) * 255.0f), 0, 255)); + msg.WriteByte((byte)MathHelper.Clamp((int)(MathUtils.InverseLerp(0.0f, destructibleWall.MaxHealth, destructibleWall.Damage) * 255.0f), 0, 255)); break; case GlobalLevelWallEventData _: foreach (LevelWall levelWall in ExtraWalls) { if (levelWall.Body.BodyType == BodyType.Static) { continue; } - msg.Write(levelWall.Body.Position.X); - msg.Write(levelWall.Body.Position.Y); + msg.WriteSingle(levelWall.Body.Position.X); + msg.WriteSingle(levelWall.Body.Position.Y); msg.WriteRangedSingle(levelWall.MoveState, 0.0f, MathHelper.TwoPi, 16); } break; diff --git a/Barotrauma/BarotraumaServer/ServerSource/Map/Creatures/BallastFloraBehavior.cs b/Barotrauma/BarotraumaServer/ServerSource/Map/Creatures/BallastFloraBehavior.cs index 877d0b4b1..671413642 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Map/Creatures/BallastFloraBehavior.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Map/Creatures/BallastFloraBehavior.cs @@ -56,7 +56,7 @@ namespace Barotrauma.MapCreatures.Behavior public void ServerWrite(IWriteMessage msg, IEventData eventData) { - msg.Write((byte)eventData.NetworkHeader); + msg.WriteByte((byte)eventData.NetworkHeader); switch (eventData) { @@ -80,51 +80,51 @@ namespace Barotrauma.MapCreatures.Behavior break; } - msg.Write(PowerConsumptionTimer); + msg.WriteSingle(PowerConsumptionTimer); } private void ServerWriteSpawn(IWriteMessage msg) { - msg.Write(Prefab.Identifier); - msg.Write(Offset.X); - msg.Write(Offset.Y); + msg.WriteIdentifier(Prefab.Identifier); + msg.WriteSingle(Offset.X); + msg.WriteSingle(Offset.Y); } private void ServerWriteBranchGrowth(IWriteMessage msg, BallastFloraBranch branch, int parentId = -1) { var (x, y) = branch.Position; - msg.Write(parentId); - msg.Write((int)branch.ID); - msg.Write(branch.IsRootGrowth); + msg.WriteInt32(parentId); + msg.WriteInt32((int)branch.ID); + msg.WriteBoolean(branch.IsRootGrowth); msg.WriteRangedInteger((byte)branch.Type, 0b0000, 0b1111); msg.WriteRangedInteger((byte)branch.Sides, 0b0000, 0b1111); msg.WriteRangedInteger(branch.FlowerConfig.Serialize(), 0, 0xFFF); msg.WriteRangedInteger(branch.LeafConfig.Serialize(), 0, 0xFFF); - msg.Write((ushort)branch.MaxHealth); - msg.Write((int)(x / VineTile.Size)); - msg.Write((int)(y / VineTile.Size)); - msg.Write(branch.ParentBranch == null ? -1 : Branches.IndexOf(branch.ParentBranch)); + msg.WriteUInt16((ushort)branch.MaxHealth); + msg.WriteInt32((int)(x / VineTile.Size)); + msg.WriteInt32((int)(y / VineTile.Size)); + msg.WriteInt32(branch.ParentBranch == null ? -1 : Branches.IndexOf(branch.ParentBranch)); } private void ServerWriteBranchDamage(IWriteMessage msg, BallastFloraBranch branch) { - msg.Write((int)branch.ID); - msg.Write(branch.Health); + msg.WriteInt32((int)branch.ID); + msg.WriteSingle(branch.Health); } private void ServerWriteInfect(IWriteMessage msg, UInt16 itemID, InfectEventData.InfectState infect, BallastFloraBranch infector = null) { - msg.Write(itemID); - msg.Write(infect == InfectEventData.InfectState.Yes); + msg.WriteUInt16(itemID); + msg.WriteBoolean(infect == InfectEventData.InfectState.Yes); if (infect == InfectEventData.InfectState.Yes) { - msg.Write(infector?.ID ?? -1); + msg.WriteInt32(infector?.ID ?? -1); } } private void ServerWriteBranchRemove(IWriteMessage msg, BallastFloraBranch branch) { - msg.Write(branch.ID); + msg.WriteInt32(branch.ID); } public void CreateNetworkMessage(IEventData extraData) diff --git a/Barotrauma/BarotraumaServer/ServerSource/Map/Hull.cs b/Barotrauma/BarotraumaServer/ServerSource/Map/Hull.cs index 9efc0c125..74ca52bb7 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Map/Hull.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Map/Hull.cs @@ -94,8 +94,8 @@ namespace Barotrauma msg.WriteRangedInteger(decals.Count, 0, MaxDecalsPerHull); foreach (Decal decal in decals) { - msg.Write(decal.Prefab.UintIdentifier); - msg.Write((byte)decal.SpriteIndex); + msg.WriteUInt32(decal.Prefab.UintIdentifier); + msg.WriteByte((byte)decal.SpriteIndex); float normalizedXPos = MathHelper.Clamp(MathUtils.InverseLerp(0.0f, rect.Width, decal.CenterPosition.X), 0.0f, 1.0f); float normalizedYPos = MathHelper.Clamp(MathUtils.InverseLerp(-rect.Height, 0.0f, decal.CenterPosition.Y), 0.0f, 1.0f); msg.WriteRangedSingle(normalizedXPos, 0.0f, 1.0f, 8); diff --git a/Barotrauma/BarotraumaServer/ServerSource/Map/Structure.cs b/Barotrauma/BarotraumaServer/ServerSource/Map/Structure.cs index 1f6f58360..7a5a03496 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Map/Structure.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Map/Structure.cs @@ -11,7 +11,7 @@ namespace Barotrauma public void ServerEventWrite(IWriteMessage msg, Client c, NetEntityEvent.IData extraData = null) { - msg.Write((byte)Sections.Length); + msg.WriteByte((byte)Sections.Length); for (int i = 0; i < Sections.Length; i++) { msg.WriteRangedSingle(Sections[i].damage / MaxHealth, 0.0f, 1.0f, 8); diff --git a/Barotrauma/BarotraumaServer/ServerSource/Map/Submarine.cs b/Barotrauma/BarotraumaServer/ServerSource/Map/Submarine.cs index 9f634bd1d..572ffaab8 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Map/Submarine.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Map/Submarine.cs @@ -7,11 +7,11 @@ namespace Barotrauma { public void ServerWritePosition(IWriteMessage msg, Client c) { - msg.Write(ID); + msg.WriteUInt16(ID); IWriteMessage tempBuffer = new WriteOnlyMessage(); subBody.Body.ServerWrite(tempBuffer); - msg.Write((byte)tempBuffer.LengthBytes); - msg.Write(tempBuffer.Buffer, 0, tempBuffer.LengthBytes); + msg.WriteByte((byte)tempBuffer.LengthBytes); + msg.WriteBytes(tempBuffer.Buffer, 0, tempBuffer.LengthBytes); msg.WritePadBits(); } diff --git a/Barotrauma/BarotraumaServer/ServerSource/Networking/BanList.cs b/Barotrauma/BarotraumaServer/ServerSource/Networking/BanList.cs index 3b628dea4..6ba6dea70 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Networking/BanList.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Networking/BanList.cs @@ -1,9 +1,9 @@ -using System; -using System.Collections.Generic; +#nullable enable +using System; using Barotrauma.IO; using System.Linq; -using System.Net; -using Barotrauma.Steam; +using System.Xml.Linq; +using Barotrauma.Extensions; namespace Barotrauma.Networking { @@ -11,6 +11,8 @@ namespace Barotrauma.Networking { private static UInt32 LastIdentifier = 0; + public bool Expired => ExpirationTime is { } expirationTime && DateTime.Now > expirationTime; + public BannedPlayer( string name, Either addressOrAccountId, string reason, DateTime? expirationTime) { @@ -24,20 +26,33 @@ namespace Barotrauma.Networking partial class BanList { - const string SavePath = "Data/bannedplayers.txt"; + private const string SavePath = "Data/bannedplayers.xml"; + private const string LegacySavePath = "Data/bannedplayers.txt"; partial void InitProjectSpecific() { - if (!File.Exists(SavePath)) { return; } + if (!File.Exists(SavePath)) + { + LoadLegacyBanList(); + } + else + { + LoadBanList(); + } + } + private void LoadLegacyBanList() + { + if (!File.Exists(LegacySavePath)) { return; } + string[] lines; try { - lines = File.ReadAllLines(SavePath); + lines = File.ReadAllLines(LegacySavePath); } catch (Exception e) { - DebugConsole.ThrowError("Failed to open the list of banned players in " + SavePath, e); + DebugConsole.ThrowError($"Failed to open the list of banned players in {LegacySavePath}", e); return; } @@ -70,11 +85,46 @@ namespace Barotrauma.Networking bannedPlayers.Add(new BannedPlayer(name, address, reason, expirationTime)); } } + + Save(); + File.Delete(LegacySavePath); } - public void RemoveExpired() + private void LoadBanList() { - bannedPlayers.RemoveAll(bp => bp.ExpirationTime.HasValue && DateTime.Now > bp.ExpirationTime.Value); + XDocument? doc = XMLExtensions.TryLoadXml(SavePath); + + if (doc?.Root is null) { return; } + + static Option loadFromElement(XElement element) + { + var accountId = AccountId.Parse(element.GetAttributeString("accountid", "")); + var address = Address.Parse(element.GetAttributeString("address", "")); + + var name = element.GetAttributeString("name", "")!; + var reason = element.GetAttributeString("reason", "")!; + DateTime? expirationTime = DateTime.FromBinary(unchecked((long)element.GetAttributeUInt64("expirationtime", 0))); + + if (expirationTime < DateTime.Now) { expirationTime = null; } + + if (accountId.IsNone() && address.IsNone()) { return Option.None(); } + + Either addressOrAccountId = accountId.TryUnwrap(out var accId) + ? (Either)accId + : address.TryUnwrap(out var addr) + ? addr + : throw new InvalidCastException(); + + return Option.Some(new BannedPlayer(name, addressOrAccountId, reason, expirationTime)); + } + + bannedPlayers.AddRange(doc.Root.Elements().Select(loadFromElement) + .OfType>().Select(o => o.Value)); + } + + private void RemoveExpired() + { + bannedPlayers.RemoveAll(bp => bp.Expired); } public bool IsBanned(Endpoint endpoint, out string reason) @@ -107,17 +157,7 @@ namespace Barotrauma.Networking public void BanPlayer(string name, Either addressOrAccountId, string reason, TimeSpan? duration) { var existingBan = bannedPlayers.Find(bp => bp.AddressOrAccountId == addressOrAccountId); - if (existingBan != null) - { - if (!duration.HasValue) { return; } - - DebugConsole.Log("Set \"" + name + "\"'s ban duration to " + duration.Value); - existingBan.ExpirationTime = DateTime.Now + duration.Value; - Save(); - return; - } - - System.Diagnostics.Debug.Assert(!name.Contains(',')); + if (existingBan != null) { bannedPlayers.Remove(existingBan); } string logMsg = "Banned " + name; if (!string.IsNullOrEmpty(reason)) { logMsg += ", reason: " + reason; } @@ -132,7 +172,6 @@ namespace Barotrauma.Networking } bannedPlayers.Add(new BannedPlayer(name, addressOrAccountId, reason, expirationTime)); - Save(); } @@ -168,27 +207,32 @@ namespace Barotrauma.Networking GameMain.Server?.ServerSettings?.UpdateFlag(ServerSettings.NetFlags.Properties); - bannedPlayers.RemoveAll(bp => bp.ExpirationTime.HasValue && DateTime.Now > bp.ExpirationTime.Value); + RemoveExpired(); - List lines = new List(); - foreach (BannedPlayer banned in bannedPlayers) + static XElement saveToElement(BannedPlayer bannedPlayer) { - string line = banned.Name; - line += "," + (banned.AddressOrAccountId.ToString()); - line += "," + (banned.ExpirationTime.HasValue ? banned.ExpirationTime.Value.ToString() : ""); - if (!string.IsNullOrWhiteSpace(banned.Reason)) { line += "," + banned.Reason; } + XElement retVal = new XElement("ban"); + retVal.SetAttributeValue("name", bannedPlayer.Name); + retVal.SetAttributeValue("reason", bannedPlayer.Reason); + if (bannedPlayer.AddressOrAccountId.TryGet(out AccountId accountId)) + { + retVal.SetAttributeValue("accountid", accountId.StringRepresentation); + } + else if (bannedPlayer.AddressOrAccountId.TryGet(out Address address)) + { + retVal.SetAttributeValue("address", address.StringRepresentation); + } + if (bannedPlayer.ExpirationTime is { } expirationTime) + { + retVal.SetAttributeValue("expirationtime", unchecked((ulong)expirationTime.ToBinary())); + } - lines.Add(line); + return retVal; } - try - { - File.WriteAllLines(SavePath, lines); - } - catch (Exception e) - { - DebugConsole.ThrowError("Saving the list of banned players to " + SavePath + " failed", e); - } + XDocument doc = new XDocument(new XElement("bannedplayers")); + bannedPlayers.Select(saveToElement).ForEach(doc.Root!.Add); + doc.SaveSafe(SavePath); } public void ServerAdminWrite(IWriteMessage outMsg, Client c) @@ -200,12 +244,12 @@ namespace Barotrauma.Networking if (!c.HasPermission(ClientPermissions.Ban)) { - outMsg.Write(false); outMsg.WritePadBits(); + outMsg.WriteBoolean(false); outMsg.WritePadBits(); return; } - outMsg.Write(true); - outMsg.Write(c.Connection == GameMain.Server.OwnerConnection); + outMsg.WriteBoolean(true); + outMsg.WriteBoolean(c.Connection == GameMain.Server.OwnerConnection); outMsg.WritePadBits(); outMsg.WriteVariableUInt32((UInt32)bannedPlayers.Count); @@ -213,29 +257,29 @@ namespace Barotrauma.Networking { BannedPlayer bannedPlayer = bannedPlayers[i]; - outMsg.Write(bannedPlayer.Name); - outMsg.Write(bannedPlayer.UniqueIdentifier); - outMsg.Write(bannedPlayer.ExpirationTime != null); + outMsg.WriteString(bannedPlayer.Name); + outMsg.WriteUInt32(bannedPlayer.UniqueIdentifier); + outMsg.WriteBoolean(bannedPlayer.ExpirationTime != null); outMsg.WritePadBits(); if (bannedPlayer.ExpirationTime != null) { double hoursFromNow = (bannedPlayer.ExpirationTime.Value - DateTime.Now).TotalHours; - outMsg.Write(hoursFromNow); + outMsg.WriteDouble(hoursFromNow); } - outMsg.Write(bannedPlayer.Reason ?? ""); + outMsg.WriteString(bannedPlayer.Reason ?? ""); if (c.Connection == GameMain.Server.OwnerConnection) { if (bannedPlayer.AddressOrAccountId.TryGet(out Address endpoint)) { - outMsg.Write(true); outMsg.WritePadBits(); - outMsg.Write(endpoint.StringRepresentation); + outMsg.WriteBoolean(true); outMsg.WritePadBits(); + outMsg.WriteString(endpoint.StringRepresentation); } else { - outMsg.Write(false); outMsg.WritePadBits(); - outMsg.Write(((SteamId)bannedPlayer.AddressOrAccountId).StringRepresentation); + outMsg.WriteBoolean(false); outMsg.WritePadBits(); + outMsg.WriteString(((SteamId)bannedPlayer.AddressOrAccountId).StringRepresentation); } } } @@ -262,7 +306,7 @@ namespace Barotrauma.Networking for (int i = 0; i < removeCount; i++) { UInt32 id = incMsg.ReadUInt32(); - BannedPlayer bannedPlayer = bannedPlayers.Find(p => p.UniqueIdentifier == id); + BannedPlayer? bannedPlayer = bannedPlayers.Find(p => p.UniqueIdentifier == id); if (bannedPlayer != null) { GameServer.Log(GameServer.ClientLogName(c) + " unbanned " + bannedPlayer.Name + " (" + bannedPlayer.AddressOrAccountId + ")", ServerLog.MessageType.ConsoleUsage); diff --git a/Barotrauma/BarotraumaServer/ServerSource/Networking/ChatMessage.cs b/Barotrauma/BarotraumaServer/ServerSource/Networking/ChatMessage.cs index d2a56a792..07748966a 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Networking/ChatMessage.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Networking/ChatMessage.cs @@ -202,24 +202,24 @@ namespace Barotrauma.Networking public virtual void ServerWrite(IWriteMessage msg, Client c) { - msg.Write((byte)ServerNetObject.CHAT_MESSAGE); - msg.Write(NetStateID); + msg.WriteByte((byte)ServerNetObject.CHAT_MESSAGE); + msg.WriteUInt16(NetStateID); msg.WriteRangedInteger((int)Type, 0, Enum.GetValues(typeof(ChatMessageType)).Length - 1); - msg.Write((byte)ChangeType); - msg.Write(Text); + msg.WriteByte((byte)ChangeType); + msg.WriteString(Text); - msg.Write(SenderName); - msg.Write(SenderClient != null); + msg.WriteString(SenderName); + msg.WriteBoolean(SenderClient != null); if (SenderClient != null) { - msg.Write(SenderClient.AccountId.TryUnwrap(out var accountId) ? accountId.StringRepresentation : SenderClient.SessionId.ToString()); + msg.WriteString(SenderClient.AccountId.TryUnwrap(out var accountId) ? accountId.StringRepresentation : SenderClient.SessionId.ToString()); } - msg.Write(Sender != null && c.InGame); + msg.WriteBoolean(Sender != null && c.InGame); if (Sender != null && c.InGame) { - msg.Write(Sender.ID); + msg.WriteUInt16(Sender.ID); } - msg.Write(customTextColor != null); + msg.WriteBoolean(customTextColor != null); if (customTextColor != null) { msg.WriteColorR8G8B8A8(customTextColor.Value); @@ -227,7 +227,7 @@ namespace Barotrauma.Networking msg.WritePadBits(); if (Type == ChatMessageType.ServerMessageBoxInGame) { - msg.Write(IconStyle); + msg.WriteString(IconStyle); } } } diff --git a/Barotrauma/BarotraumaServer/ServerSource/Networking/Client.cs b/Barotrauma/BarotraumaServer/ServerSource/Networking/Client.cs index 63c6ad087..551e32707 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Networking/Client.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Networking/Client.cs @@ -8,12 +8,16 @@ namespace Barotrauma.Networking { public bool VoiceEnabled = true; - public UInt16 LastRecvClientListUpdate = 0; + public UInt16 LastRecvClientListUpdate + = NetIdUtils.GetIdOlderThan(GameMain.Server.LastClientListUpdateID); - public UInt16 LastSentServerSettingsUpdate = 0; - public UInt16 LastRecvServerSettingsUpdate = 0; + public UInt16 LastSentServerSettingsUpdate + = NetIdUtils.GetIdOlderThan(GameMain.Server.ServerSettings.LastUpdateIdForFlag[ServerSettings.NetFlags.Properties]); + public UInt16 LastRecvServerSettingsUpdate + = NetIdUtils.GetIdOlderThan(GameMain.Server.ServerSettings.LastUpdateIdForFlag[ServerSettings.NetFlags.Properties]); - public UInt16 LastRecvLobbyUpdate = 0; + public UInt16 LastRecvLobbyUpdate + = NetIdUtils.GetIdOlderThan(GameMain.NetLobbyScreen.LastUpdateID); public UInt16 LastSentChatMsgID = 0; //last msg this client said public UInt16 LastRecvChatMsgID = 0; //last msg this client knows about @@ -21,7 +25,8 @@ namespace Barotrauma.Networking public UInt16 LastSentEntityEventID = 0; public UInt16 LastRecvEntityEventID = 0; - public readonly Dictionary LastRecvCampaignUpdate = new Dictionary(); + public readonly Dictionary LastRecvCampaignUpdate + = new Dictionary(); public UInt16 LastRecvCampaignSave = 0; public (UInt16 saveId, float time) LastCampaignSaveSendTime; @@ -107,8 +112,17 @@ namespace Barotrauma.Networking } } + private List kickVoters; + + public int KickVoteCount + { + get { return kickVoters.Count; } + } + partial void InitProjSpecific() { + kickVoters = new List(); + JobPreferences = new List(); VoipQueue = new VoipQueue(SessionId, true, true); @@ -151,7 +165,22 @@ namespace Barotrauma.Networking { if (string.IsNullOrWhiteSpace(name)) { return false; } - char[] disallowedChars = new char[] { ';', ',', '<', '>', '/', '\\', '[', ']', '"', '?' }; + char[] disallowedChars = + { + //',', //previously disallowed because of the ban list format + + ';', + '<', + '>', + + '/', //disallowed because of server messages using forward slash as a delimiter (TODO: implement escaping) + + '\\', + '[', + ']', + '"', + '?' + }; if (name.Any(c => disallowedChars.Contains(c))) { return false; } foreach (char character in name) @@ -162,19 +191,45 @@ namespace Barotrauma.Networking return true; } - public bool EndpointMatches(Endpoint endPoint) + public bool AddressMatches(Address address) { - return Connection.EndpointMatches(endPoint); + return Connection.Endpoint.Address.Equals(address); } + public void AddKickVote(Client voter) + { + if (voter != null && !kickVoters.Contains(voter)) { kickVoters.Add(voter); } + } + + public void RemoveKickVote(Client voter) + { + kickVoters.Remove(voter); + } + + public bool HasKickVoteFrom(Client voter) + { + return kickVoters.Contains(voter); + } + + public bool HasKickVoteFromSessionId(int id) + { + return kickVoters.Any(k => k.SessionId == id); + } + + public static void UpdateKickVotes(IReadOnlyList connectedClients) + { + foreach (Client client in connectedClients) + { + client.kickVoters.RemoveAll(voter => !connectedClients.Contains(voter)); + } + } + + public void SetPermissions(ClientPermissions permissions, IEnumerable permittedConsoleCommands) { this.Permissions = permissions; this.PermittedConsoleCommands.Clear(); - foreach (var command in permittedConsoleCommands) - { - this.PermittedConsoleCommands.Add(command); - } + this.PermittedConsoleCommands.UnionWith(permittedConsoleCommands); } public void GivePermission(ClientPermissions permission) diff --git a/Barotrauma/BarotraumaServer/ServerSource/Networking/EntitySpawner.cs b/Barotrauma/BarotraumaServer/ServerSource/Networking/EntitySpawner.cs index 146ae81c0..0b4937265 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Networking/EntitySpawner.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Networking/EntitySpawner.cs @@ -32,23 +32,23 @@ namespace Barotrauma if (GameMain.Server is null) { return; } if (!(extraData is SpawnOrRemove entities)) { throw new Exception($"Malformed {nameof(EntitySpawner)} event: expected {nameof(SpawnOrRemove)}"); } - message.Write(entities is RemoveEntity); + message.WriteBoolean(entities is RemoveEntity); if (entities is RemoveEntity) { - message.Write(entities.ID); + message.WriteUInt16(entities.ID); } else { switch (entities.Entity) { case Item item: - message.Write((byte)SpawnableType.Item); + message.WriteByte((byte)SpawnableType.Item); DebugConsole.Log( $"Writing item spawn data {item} (ID: {entities.ID})"); item.WriteSpawnData(message, entities.ID, entities.InventoryID, entities.ItemContainerIndex, entities.SlotIndex); break; case Character character: - message.Write((byte)SpawnableType.Character); + message.WriteByte((byte)SpawnableType.Character); DebugConsole.Log( $"Writing character spawn data: {character} (ID: {entities.ID})"); character.WriteSpawnData(message, entities.ID, restrictMessageSize: true); diff --git a/Barotrauma/BarotraumaServer/ServerSource/Networking/FileTransfer/FileSender.cs b/Barotrauma/BarotraumaServer/ServerSource/Networking/FileTransfer/FileSender.cs index b79b94e64..eae96b706 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Networking/FileTransfer/FileSender.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Networking/FileTransfer/FileSender.cs @@ -52,7 +52,7 @@ namespace Barotrauma.Networking } } - public const int MaxPacketsPerUpdate = 4; + public const int MaxPacketsPerUpdate = 10; public float PacketsPerUpdate { get; set; } = 1.0f; public byte[] Data { get; } @@ -219,27 +219,27 @@ namespace Barotrauma.Networking if (!transfer.Acknowledged) { message = new WriteOnlyMessage(); - message.Write((byte)ServerPacketHeader.FILE_TRANSFER); + message.WriteByte((byte)ServerPacketHeader.FILE_TRANSFER); //if the recipient is the owner of the server (= a client running the server from the main exe) //we don't need to send anything, the client can just read the file directly if (transfer.Connection == GameMain.Server.OwnerConnection) { - message.Write((byte)FileTransferMessageType.TransferOnSameMachine); - message.Write((byte)transfer.ID); - message.Write((byte)transfer.FileType); - message.Write(transfer.FilePath); + message.WriteByte((byte)FileTransferMessageType.TransferOnSameMachine); + message.WriteByte((byte)transfer.ID); + message.WriteByte((byte)transfer.FileType); + message.WriteString(transfer.FilePath); peer.Send(message, transfer.Connection, DeliveryMethod.Unreliable); transfer.Status = FileTransferStatus.Finished; } else { - message.Write((byte)FileTransferMessageType.Initiate); - message.Write((byte)transfer.ID); - message.Write((byte)transfer.FileType); + message.WriteByte((byte)FileTransferMessageType.Initiate); + message.WriteByte((byte)transfer.ID); + message.WriteByte((byte)transfer.FileType); //message.Write((ushort)chunkLen); - message.Write(transfer.Data.Length); - message.Write(transfer.FileName); + message.WriteInt32(transfer.Data.Length); + message.WriteString(transfer.FileName); peer.Send(message, transfer.Connection, DeliveryMethod.Unreliable); transfer.Status = FileTransferStatus.Sending; @@ -262,13 +262,13 @@ namespace Barotrauma.Networking int sendByteCount = (remaining > chunkLen ? chunkLen : (int)remaining); message = new WriteOnlyMessage(); - message.Write((byte)ServerPacketHeader.FILE_TRANSFER); - message.Write((byte)FileTransferMessageType.Data); + message.WriteByte((byte)ServerPacketHeader.FILE_TRANSFER); + message.WriteByte((byte)FileTransferMessageType.Data); - message.Write((byte)transfer.ID); - message.Write(transfer.SentOffset); + message.WriteByte((byte)transfer.ID); + message.WriteInt32(transfer.SentOffset); - message.Write((ushort)sendByteCount); + message.WriteUInt16((ushort)sendByteCount); int chunkDestPos = message.BytePosition; message.BitPosition += sendByteCount * 8; message.LengthBits = Math.Max(message.LengthBits, message.BitPosition); diff --git a/Barotrauma/BarotraumaServer/ServerSource/Networking/GameServer.cs b/Barotrauma/BarotraumaServer/ServerSource/Networking/GameServer.cs index ce5282fa4..c3bdd614c 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Networking/GameServer.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Networking/GameServer.cs @@ -323,7 +323,7 @@ namespace Barotrauma.Networking } else { - newClient.SetPermissions(ClientPermissions.None, new List()); + newClient.SetPermissions(ClientPermissions.None, Enumerable.Empty()); } } @@ -383,7 +383,7 @@ namespace Barotrauma.Networking character.KillDisconnectedTimer += deltaTime; character.SetStun(1.0f); - Client owner = connectedClients.Find(c => (c.Character == null || c.Character == character) && c.EndpointMatches(character.OwnerClientEndpoint)); + Client owner = connectedClients.Find(c => (c.Character == null || c.Character == character) && c.AddressMatches(character.OwnerClientAddress)); if ((OwnerConnection == null || owner?.Connection != OwnerConnection) && character.KillDisconnectedTimer > serverSettings.KillDisconnectedTime) { @@ -675,18 +675,18 @@ namespace Barotrauma.Networking ConnectedClients.ForEach(c => { IWriteMessage pingReq = new WriteOnlyMessage(); - pingReq.Write((byte)ServerPacketHeader.PING_REQUEST); - pingReq.Write((byte)lastPingData.Length); - pingReq.Write(lastPingData, 0, lastPingData.Length); + pingReq.WriteByte((byte)ServerPacketHeader.PING_REQUEST); + pingReq.WriteByte((byte)lastPingData.Length); + pingReq.WriteBytes(lastPingData, 0, lastPingData.Length); serverPeer.Send(pingReq, c.Connection, DeliveryMethod.Unreliable); IWriteMessage pingInf = new WriteOnlyMessage(); - pingInf.Write((byte)ServerPacketHeader.CLIENT_PINGS); - pingInf.Write((byte)ConnectedClients.Count); + pingInf.WriteByte((byte)ServerPacketHeader.CLIENT_PINGS); + pingInf.WriteByte((byte)ConnectedClients.Count); ConnectedClients.ForEach(c2 => { - pingInf.Write(c2.SessionId); - pingInf.Write(c2.Ping); + pingInf.WriteByte(c2.SessionId); + pingInf.WriteUInt16(c2.Ping); }); serverPeer.Send(pingInf, c.Connection, DeliveryMethod.Unreliable); }); @@ -1475,21 +1475,22 @@ namespace Barotrauma.Networking case ClientPermissions.SelectSub: bool isShuttle = inc.ReadBoolean(); inc.ReadPadBits(); - UInt16 subIndex = inc.ReadUInt16(); + string subHash = inc.ReadString(); var subList = GameMain.NetLobbyScreen.GetSubList(); - if (subIndex >= subList.Count) + var sub = GameMain.NetLobbyScreen.GetSubList().FirstOrDefault(s => s.MD5Hash.StringRepresentation == subHash); + if (sub == null) { - DebugConsole.NewMessage($"Client \"{ClientLogName(sender)}\" attempted to select a sub, index out of bounds ({subIndex})", Color.Red); + DebugConsole.NewMessage($"Client \"{ClientLogName(sender)}\" attempted to select a sub, could not find a sub with the MD5 hash \"{subHash}\".", Color.Red); } else { if (isShuttle) { - GameMain.NetLobbyScreen.SelectedShuttle = subList[subIndex]; + GameMain.NetLobbyScreen.SelectedShuttle = sub; } else { - GameMain.NetLobbyScreen.SelectedSub = subList[subIndex]; + GameMain.NetLobbyScreen.SelectedSub = sub; } } break; @@ -1503,11 +1504,11 @@ namespace Barotrauma.Networking const int MaxSaves = 255; var saveInfos = SaveUtil.GetSaveFiles(SaveUtil.SaveType.Multiplayer, includeInCompatible: false); IWriteMessage msg = new WriteOnlyMessage(); - msg.Write((byte)ServerPacketHeader.CAMPAIGN_SETUP_INFO); - msg.Write((byte)Math.Min(saveInfos.Count, MaxSaves)); + msg.WriteByte((byte)ServerPacketHeader.CAMPAIGN_SETUP_INFO); + msg.WriteByte((byte)Math.Min(saveInfos.Count, MaxSaves)); for (int i = 0; i < saveInfos.Count && i < MaxSaves; i++) { - msg.Write(saveInfos[i]); + msg.WriteNetSerializableStruct(saveInfos[i]); } serverPeer.Send(msg, sender.Connection, DeliveryMethod.Reliable); } @@ -1610,21 +1611,21 @@ namespace Barotrauma.Networking DebugConsole.NewMessage("Sending initial lobby update", Color.Gray); } - outmsg.Write(c.SessionId); + outmsg.WriteByte(c.SessionId); var subList = GameMain.NetLobbyScreen.GetSubList(); - outmsg.Write((UInt16)subList.Count); + outmsg.WriteUInt16((UInt16)subList.Count); for (int i = 0; i < subList.Count; i++) { var sub = subList[i]; - outmsg.Write(sub.Name); - outmsg.Write(sub.MD5Hash.ToString()); - outmsg.Write((byte)sub.SubmarineClass); - outmsg.Write(sub.RequiredContentPackagesInstalled); + outmsg.WriteString(sub.Name); + outmsg.WriteString(sub.MD5Hash.ToString()); + outmsg.WriteByte((byte)sub.SubmarineClass); + outmsg.WriteBoolean(sub.RequiredContentPackagesInstalled); } - outmsg.Write(GameStarted); - outmsg.Write(serverSettings.AllowSpectating); + outmsg.WriteBoolean(GameStarted); + outmsg.WriteBoolean(serverSettings.AllowSpectating); c.WritePermissions(outmsg); } @@ -1697,23 +1698,23 @@ namespace Barotrauma.Networking } IWriteMessage outmsg = new WriteOnlyMessage(); - outmsg.Write((byte)ServerPacketHeader.UPDATE_INGAME); + outmsg.WriteByte((byte)ServerPacketHeader.UPDATE_INGAME); - outmsg.Write((float)NetTime.Now); + outmsg.WriteSingle((float)NetTime.Now); - outmsg.Write((byte)ServerNetObject.SYNC_IDS); - outmsg.Write(c.LastSentChatMsgID); //send this to client so they know which chat messages weren't received by the server - outmsg.Write(c.LastSentEntityEventID); + outmsg.WriteByte((byte)ServerNetObject.SYNC_IDS); + outmsg.WriteUInt16(c.LastSentChatMsgID); //send this to client so they know which chat messages weren't received by the server + outmsg.WriteUInt16(c.LastSentEntityEventID); if (GameMain.GameSession?.GameMode is MultiPlayerCampaign campaign && campaign.Preset == GameMain.NetLobbyScreen.SelectedMode) { - outmsg.Write(true); + outmsg.WriteBoolean(true); outmsg.WritePadBits(); campaign.ServerWrite(outmsg, c); } else { - outmsg.Write(false); + outmsg.WriteBoolean(false); outmsg.WritePadBits(); } @@ -1739,8 +1740,8 @@ namespace Barotrauma.Networking } IWriteMessage tempBuffer = new ReadWriteMessage(); - tempBuffer.Write(entity is Item); tempBuffer.WritePadBits(); - tempBuffer.Write(entity is MapEntity me ? me.Prefab.UintIdentifier : (UInt32)0); + tempBuffer.WriteBoolean(entity is Item); tempBuffer.WritePadBits(); + tempBuffer.WriteUInt32(entity is MapEntity me ? me.Prefab.UintIdentifier : (UInt32)0); entityPositionSync.ServerWritePosition(tempBuffer, c); //no more room in this packet @@ -1749,9 +1750,9 @@ namespace Barotrauma.Networking break; } - outmsg.Write((byte)ServerNetObject.ENTITY_POSITION); + outmsg.WriteByte((byte)ServerNetObject.ENTITY_POSITION); outmsg.WritePadBits(); //padding is required here to make sure any padding bits within tempBuffer are read correctly - outmsg.Write(tempBuffer.Buffer, 0, tempBuffer.LengthBytes); + outmsg.WriteBytes(tempBuffer.Buffer, 0, tempBuffer.LengthBytes); outmsg.WritePadBits(); c.PositionUpdateLastSent[entity] = (float)NetTime.Now; @@ -1759,7 +1760,7 @@ namespace Barotrauma.Networking } positionUpdateBytes = outmsg.LengthBytes - positionUpdateBytes; - outmsg.Write((byte)ServerNetObject.END_OF_MESSAGE); + outmsg.WriteByte((byte)ServerNetObject.END_OF_MESSAGE); if (outmsg.LengthBytes > MsgConstants.MTU) { @@ -1779,8 +1780,8 @@ namespace Barotrauma.Networking for (int i = 0; i < NetConfig.MaxEventPacketsPerUpdate; i++) { outmsg = new WriteOnlyMessage(); - outmsg.Write((byte)ServerPacketHeader.UPDATE_INGAME); - outmsg.Write((float)Lidgren.Network.NetTime.Now); + outmsg.WriteByte((byte)ServerPacketHeader.UPDATE_INGAME); + outmsg.WriteSingle((float)Lidgren.Network.NetTime.Now); int eventManagerBytes = outmsg.LengthBytes; entityEventManager.Write(c, outmsg, out List sentEvents); @@ -1791,7 +1792,7 @@ namespace Barotrauma.Networking break; } - outmsg.Write((byte)ServerNetObject.END_OF_MESSAGE); + outmsg.WriteByte((byte)ServerNetObject.END_OF_MESSAGE); if (outmsg.LengthBytes > MsgConstants.MTU) { @@ -1821,10 +1822,10 @@ namespace Barotrauma.Networking bool hasChanged = NetIdUtils.IdMoreRecent(LastClientListUpdateID, c.LastRecvClientListUpdate); if (!hasChanged) { return; } - outmsg.Write((byte)ServerNetObject.CLIENT_LIST); - outmsg.Write(LastClientListUpdateID); + outmsg.WriteByte((byte)ServerNetObject.CLIENT_LIST); + outmsg.WriteUInt16(LastClientListUpdateID); - outmsg.Write((byte)connectedClients.Count); + outmsg.WriteByte((byte)connectedClients.Count); foreach (Client client in connectedClients) { var tempClientData = new TempClient @@ -1850,7 +1851,7 @@ namespace Barotrauma.Networking IsDownloading = FileSender.ActiveTransfers.Any(t => t.Connection == client.Connection) }; - outmsg.Write(tempClientData); + outmsg.WriteNetSerializableStruct(tempClientData); outmsg.WritePadBits(); } } @@ -1860,27 +1861,32 @@ namespace Barotrauma.Networking bool isInitialUpdate = false; IWriteMessage outmsg = new WriteOnlyMessage(); - outmsg.Write((byte)ServerPacketHeader.UPDATE_LOBBY); + outmsg.WriteByte((byte)ServerPacketHeader.UPDATE_LOBBY); - outmsg.Write((byte)ServerNetObject.SYNC_IDS); + outmsg.WriteByte((byte)ServerNetObject.SYNC_IDS); int settingsBytes = outmsg.LengthBytes; int initialUpdateBytes = 0; + if (ServerSettings.UnsentFlags() != ServerSettings.NetFlags.None) + { + GameMain.NetLobbyScreen.LastUpdateID++; + } + IWriteMessage settingsBuf = null; if (NetIdUtils.IdMoreRecent(GameMain.NetLobbyScreen.LastUpdateID, c.LastRecvLobbyUpdate)) { - outmsg.Write(true); + outmsg.WriteBoolean(true); outmsg.WritePadBits(); - outmsg.Write(GameMain.NetLobbyScreen.LastUpdateID); + outmsg.WriteUInt16(GameMain.NetLobbyScreen.LastUpdateID); settingsBuf = new ReadWriteMessage(); serverSettings.ServerWrite(settingsBuf, c); - outmsg.Write((UInt16)settingsBuf.LengthBytes); - outmsg.Write(settingsBuf.Buffer, 0, settingsBuf.LengthBytes); + outmsg.WriteUInt16((UInt16)settingsBuf.LengthBytes); + outmsg.WriteBytes(settingsBuf.Buffer, 0, settingsBuf.LengthBytes); - outmsg.Write(c.LastRecvLobbyUpdate < 1); + outmsg.WriteBoolean(c.LastRecvLobbyUpdate < 1); if (c.LastRecvLobbyUpdate < 1) { isInitialUpdate = true; @@ -1888,42 +1894,42 @@ namespace Barotrauma.Networking ClientWriteInitial(c, outmsg); initialUpdateBytes = outmsg.LengthBytes - initialUpdateBytes; } - outmsg.Write(GameMain.NetLobbyScreen.SelectedSub.Name); - outmsg.Write(GameMain.NetLobbyScreen.SelectedSub.MD5Hash.ToString()); - outmsg.Write(IsUsingRespawnShuttle()); + outmsg.WriteString(GameMain.NetLobbyScreen.SelectedSub.Name); + outmsg.WriteString(GameMain.NetLobbyScreen.SelectedSub.MD5Hash.ToString()); + outmsg.WriteBoolean(IsUsingRespawnShuttle()); var selectedShuttle = gameStarted && respawnManager != null && respawnManager.UsingShuttle ? respawnManager.RespawnShuttle.Info : GameMain.NetLobbyScreen.SelectedShuttle; - outmsg.Write(selectedShuttle.Name); - outmsg.Write(selectedShuttle.MD5Hash.ToString()); + outmsg.WriteString(selectedShuttle.Name); + outmsg.WriteString(selectedShuttle.MD5Hash.ToString()); - outmsg.Write(serverSettings.AllowSubVoting); - outmsg.Write(serverSettings.AllowModeVoting); + outmsg.WriteBoolean(serverSettings.AllowSubVoting); + outmsg.WriteBoolean(serverSettings.AllowModeVoting); - outmsg.Write(serverSettings.VoiceChatEnabled); + outmsg.WriteBoolean(serverSettings.VoiceChatEnabled); - outmsg.Write(serverSettings.AllowSpectating); + outmsg.WriteBoolean(serverSettings.AllowSpectating); outmsg.WriteRangedInteger((int)serverSettings.TraitorsEnabled, 0, 2); outmsg.WriteRangedInteger((int)GameMain.NetLobbyScreen.MissionType, 0, (int)MissionType.All); - outmsg.Write((byte)GameMain.NetLobbyScreen.SelectedModeIndex); - outmsg.Write(GameMain.NetLobbyScreen.LevelSeed); - outmsg.Write(serverSettings.SelectedLevelDifficulty); + outmsg.WriteByte((byte)GameMain.NetLobbyScreen.SelectedModeIndex); + outmsg.WriteString(GameMain.NetLobbyScreen.LevelSeed); + outmsg.WriteSingle(serverSettings.SelectedLevelDifficulty); - outmsg.Write((byte)serverSettings.BotCount); - outmsg.Write(serverSettings.BotSpawnMode == BotSpawnMode.Fill); + outmsg.WriteByte((byte)serverSettings.BotCount); + outmsg.WriteBoolean(serverSettings.BotSpawnMode == BotSpawnMode.Fill); - outmsg.Write(serverSettings.AutoRestart); + outmsg.WriteBoolean(serverSettings.AutoRestart); if (serverSettings.AutoRestart) { - outmsg.Write(autoRestartTimerRunning ? serverSettings.AutoRestartTimer : 0.0f); + outmsg.WriteSingle(autoRestartTimerRunning ? serverSettings.AutoRestartTimer : 0.0f); } } else { - outmsg.Write(false); + outmsg.WriteBoolean(false); outmsg.WritePadBits(); } settingsBytes = outmsg.LengthBytes - settingsBytes; @@ -1933,18 +1939,18 @@ namespace Barotrauma.Networking if (outmsg.LengthBytes < MsgConstants.MTU - 500 && campaign != null && campaign.Preset == GameMain.NetLobbyScreen.SelectedMode) { - outmsg.Write(true); + outmsg.WriteBoolean(true); outmsg.WritePadBits(); campaign.ServerWrite(outmsg, c); } else { - outmsg.Write(false); + outmsg.WriteBoolean(false); outmsg.WritePadBits(); } campaignBytes = outmsg.LengthBytes - campaignBytes; - outmsg.Write(c.LastSentChatMsgID); //send this to client so they know which chat messages weren't received by the server + outmsg.WriteUInt16(c.LastSentChatMsgID); //send this to client so they know which chat messages weren't received by the server int clientListBytes = outmsg.LengthBytes; if (outmsg.LengthBytes < MsgConstants.MTU - 500) @@ -1957,7 +1963,7 @@ namespace Barotrauma.Networking WriteChatMessages(outmsg, c); chatMessageBytes = outmsg.LengthBytes - chatMessageBytes; - outmsg.Write((byte)ServerNetObject.END_OF_MESSAGE); + outmsg.WriteByte((byte)ServerNetObject.END_OF_MESSAGE); bool messageTooLarge = outmsg.LengthBytes > MsgConstants.MTU; if (messageTooLarge && !isInitialUpdate) @@ -2071,21 +2077,21 @@ namespace Barotrauma.Networking if (connectedClients.Any()) { IWriteMessage msg = new WriteOnlyMessage(); - msg.Write((byte)ServerPacketHeader.QUERY_STARTGAME); + msg.WriteByte((byte)ServerPacketHeader.QUERY_STARTGAME); - msg.Write(selectedSub.Name); - msg.Write(selectedSub.MD5Hash.StringRepresentation); + msg.WriteString(selectedSub.Name); + msg.WriteString(selectedSub.MD5Hash.StringRepresentation); - msg.Write(IsUsingRespawnShuttle()); - msg.Write(selectedShuttle.Name); - msg.Write(selectedShuttle.MD5Hash.StringRepresentation); + msg.WriteBoolean(IsUsingRespawnShuttle()); + msg.WriteString(selectedShuttle.Name); + msg.WriteString(selectedShuttle.MD5Hash.StringRepresentation); var campaign = GameMain.GameSession?.GameMode as MultiPlayerCampaign; - msg.Write(campaign == null ? (byte)0 : campaign.CampaignID); - msg.Write(campaign == null ? (UInt16)0 : campaign.LastSaveID); + msg.WriteByte(campaign == null ? (byte)0 : campaign.CampaignID); + msg.WriteUInt16(campaign == null ? (UInt16)0 : campaign.LastSaveID); foreach (MultiPlayerCampaign.NetFlags flag in Enum.GetValues(typeof(MultiPlayerCampaign.NetFlags))) { - msg.Write(campaign == null ? (UInt16)0 : campaign.GetLastUpdateIdForFlag(flag)); + msg.WriteUInt16(campaign == null ? (UInt16)0 : campaign.GetLastUpdateIdForFlag(flag)); } connectedClients.ForEach(c => c.ReadyToStart = false); @@ -2400,7 +2406,7 @@ namespace Barotrauma.Networking mpCampaign.ClearSavedExperiencePoints(teamClients[i]); } - spawnedCharacter.OwnerClientEndpoint = teamClients[i].Connection.Endpoint; + spawnedCharacter.OwnerClientAddress = teamClients[i].Connection.Endpoint.Address; spawnedCharacter.OwnerClientName = teamClients[i].Name; } @@ -2498,50 +2504,50 @@ namespace Barotrauma.Networking MissionMode missionMode = GameMain.GameSession.GameMode as MissionMode; IWriteMessage msg = new WriteOnlyMessage(); - msg.Write((byte)ServerPacketHeader.STARTGAME); - msg.Write(seed); - msg.Write(gameSession.GameMode.Preset.Identifier); + msg.WriteByte((byte)ServerPacketHeader.STARTGAME); + msg.WriteInt32(seed); + msg.WriteIdentifier(gameSession.GameMode.Preset.Identifier); bool missionAllowRespawn = missionMode == null || !missionMode.Missions.Any(m => !m.AllowRespawn); - msg.Write(serverSettings.AllowRespawn && missionAllowRespawn); - msg.Write(serverSettings.AllowDisguises); - msg.Write(serverSettings.AllowRewiring); - msg.Write(serverSettings.AllowFriendlyFire); - msg.Write(serverSettings.LockAllDefaultWires); - msg.Write(serverSettings.AllowRagdollButton); - msg.Write(serverSettings.AllowLinkingWifiToChat); - msg.Write(serverSettings.MaximumMoneyTransferRequest); - msg.Write(IsUsingRespawnShuttle()); - msg.Write((byte)serverSettings.LosMode); - msg.Write(includesFinalize); msg.WritePadBits(); + msg.WriteBoolean(serverSettings.AllowRespawn && missionAllowRespawn); + msg.WriteBoolean(serverSettings.AllowDisguises); + msg.WriteBoolean(serverSettings.AllowRewiring); + msg.WriteBoolean(serverSettings.AllowFriendlyFire); + msg.WriteBoolean(serverSettings.LockAllDefaultWires); + msg.WriteBoolean(serverSettings.AllowRagdollButton); + msg.WriteBoolean(serverSettings.AllowLinkingWifiToChat); + msg.WriteInt32(serverSettings.MaximumMoneyTransferRequest); + msg.WriteBoolean(IsUsingRespawnShuttle()); + msg.WriteByte((byte)serverSettings.LosMode); + msg.WriteBoolean(includesFinalize); msg.WritePadBits(); serverSettings.WriteMonsterEnabled(msg); if (campaign == null) { - msg.Write(levelSeed); - msg.Write(serverSettings.SelectedLevelDifficulty); - msg.Write(gameSession.SubmarineInfo.Name); - msg.Write(gameSession.SubmarineInfo.MD5Hash.StringRepresentation); + msg.WriteString(levelSeed); + msg.WriteSingle(serverSettings.SelectedLevelDifficulty); + msg.WriteString(gameSession.SubmarineInfo.Name); + msg.WriteString(gameSession.SubmarineInfo.MD5Hash.StringRepresentation); var selectedShuttle = gameStarted && respawnManager != null && respawnManager.UsingShuttle ? respawnManager.RespawnShuttle.Info : GameMain.NetLobbyScreen.SelectedShuttle; - msg.Write(selectedShuttle.Name); - msg.Write(selectedShuttle.MD5Hash.StringRepresentation); - msg.Write((byte)GameMain.GameSession.GameMode.Missions.Count()); + msg.WriteString(selectedShuttle.Name); + msg.WriteString(selectedShuttle.MD5Hash.StringRepresentation); + msg.WriteByte((byte)GameMain.GameSession.GameMode.Missions.Count()); foreach (Mission mission in GameMain.GameSession.GameMode.Missions) { - msg.Write(mission.Prefab.UintIdentifier); + msg.WriteUInt32(mission.Prefab.UintIdentifier); } } else { int nextLocationIndex = campaign.Map.Locations.FindIndex(l => l.LevelData == campaign.NextLevel); int nextConnectionIndex = campaign.Map.Connections.FindIndex(c => c.LevelData == campaign.NextLevel); - msg.Write(campaign.CampaignID); - msg.Write(campaign.LastSaveID); - msg.Write(nextLocationIndex); - msg.Write(nextConnectionIndex); - msg.Write(campaign.Map.SelectedLocationIndex); - msg.Write(campaign.MirrorLevel); + msg.WriteByte(campaign.CampaignID); + msg.WriteUInt16(campaign.LastSaveID); + msg.WriteInt32(nextLocationIndex); + msg.WriteInt32(nextConnectionIndex); + msg.WriteInt32(campaign.Map.SelectedLocationIndex); + msg.WriteBoolean(campaign.MirrorLevel); } if (includesFinalize) @@ -2560,7 +2566,7 @@ namespace Barotrauma.Networking private void SendRoundStartFinalize(Client client) { IWriteMessage msg = new WriteOnlyMessage(); - msg.Write((byte)ServerPacketHeader.STARTGAMEFINALIZE); + msg.WriteByte((byte)ServerPacketHeader.STARTGAMEFINALIZE); WriteRoundStartFinalize(msg, client); serverPeer.Send(msg, client.Connection, DeliveryMethod.Reliable); } @@ -2569,26 +2575,26 @@ namespace Barotrauma.Networking { //tell the client what content files they should preload var contentToPreload = GameMain.GameSession.EventManager.GetFilesToPreload(); - msg.Write((ushort)contentToPreload.Count()); + msg.WriteUInt16((ushort)contentToPreload.Count()); foreach (ContentFile contentFile in contentToPreload) { - msg.Write(contentFile.Path.Value); + msg.WriteString(contentFile.Path.Value); } - msg.Write(Submarine.MainSub?.Info.EqualityCheckVal ?? 0); - msg.Write((byte)GameMain.GameSession.Missions.Count()); + msg.WriteInt32(Submarine.MainSub?.Info.EqualityCheckVal ?? 0); + msg.WriteByte((byte)GameMain.GameSession.Missions.Count()); foreach (Mission mission in GameMain.GameSession.Missions) { - msg.Write(mission.Prefab.Identifier); + msg.WriteIdentifier(mission.Prefab.Identifier); } foreach (Level.LevelGenStage stage in Enum.GetValues(typeof(Level.LevelGenStage)).OfType().OrderBy(s => s)) { - msg.Write(GameMain.GameSession.Level.EqualityCheckValues[stage]); + msg.WriteInt32(GameMain.GameSession.Level.EqualityCheckValues[stage]); } foreach (Mission mission in GameMain.GameSession.Missions) { mission.ServerWriteInitial(msg, client); } - msg.Write(GameMain.GameSession.CrewManager != null); + msg.WriteBoolean(GameMain.GameSession.CrewManager != null); GameMain.GameSession.CrewManager?.ServerWriteActiveOrders(msg); } @@ -2651,18 +2657,18 @@ namespace Barotrauma.Networking if (connectedClients.Count > 0) { IWriteMessage msg = new WriteOnlyMessage(); - msg.Write((byte)ServerPacketHeader.ENDGAME); - msg.Write((byte)transitionType); - msg.Write(wasSaved); - msg.Write(endMessage); - msg.Write((byte)missions.Count); + msg.WriteByte((byte)ServerPacketHeader.ENDGAME); + msg.WriteByte((byte)transitionType); + msg.WriteBoolean(wasSaved); + msg.WriteString(endMessage); + msg.WriteByte((byte)missions.Count); foreach (Mission mission in missions) { - msg.Write(mission.Completed); + msg.WriteBoolean(mission.Completed); } - msg.Write(GameMain.GameSession?.WinningTeam == null ? (byte)0 : (byte)GameMain.GameSession.WinningTeam); + msg.WriteByte(GameMain.GameSession?.WinningTeam == null ? (byte)0 : (byte)GameMain.GameSession.WinningTeam); - msg.Write((byte)traitorResults.Count); + msg.WriteByte((byte)traitorResults.Count); foreach (var traitorResult in traitorResults) { traitorResult.ServerWrite(msg); @@ -2868,7 +2874,7 @@ namespace Barotrauma.Networking //reset karma to a neutral value, so if/when the ban is revoked the client wont get immediately punished by low karma again previousPlayer.Karma = Math.Max(previousPlayer.Karma, 50.0f); - serverSettings.BanList.BanPlayer(previousPlayer.Name, previousPlayer.Endpoint, reason, duration); + serverSettings.BanList.BanPlayer(previousPlayer.Name, previousPlayer.Address, reason, duration); if (previousPlayer.AccountInfo.AccountId.TryUnwrap(out var accountId)) { serverSettings.BanList.BanPlayer(previousPlayer.Name, accountId, reason, duration); @@ -3252,9 +3258,9 @@ namespace Barotrauma.Networking public void SendCancelTransferMsg(FileSender.FileTransferOut transfer) { IWriteMessage msg = new WriteOnlyMessage(); - msg.Write((byte)ServerPacketHeader.FILE_TRANSFER); - msg.Write((byte)FileTransferMessageType.Cancel); - msg.Write((byte)transfer.ID); + msg.WriteByte((byte)ServerPacketHeader.FILE_TRANSFER); + msg.WriteByte((byte)FileTransferMessageType.Cancel); + msg.WriteByte((byte)transfer.ID); serverPeer.Send(msg, transfer.Connection, DeliveryMethod.ReliableOrdered); } @@ -3290,7 +3296,7 @@ namespace Barotrauma.Networking Client.UpdateKickVotes(connectedClients); var kickVoteEligibleClients = connectedClients.Where(c => (DateTime.Now - c.JoinTime).TotalSeconds > ServerSettings.DisallowKickVoteTime); - int minimumKickVotes = Math.Max(2, (int)(kickVoteEligibleClients.Count() * serverSettings.KickVoteRequiredRatio)); + float minimumKickVotes = Math.Max(2.0f, kickVoteEligibleClients.Count() * serverSettings.KickVoteRequiredRatio); var clientsToKick = connectedClients.FindAll(c => c.Connection != OwnerConnection && !c.HasPermission(ClientPermissions.Kick) && @@ -3299,12 +3305,10 @@ namespace Barotrauma.Networking c.KickVoteCount >= minimumKickVotes); foreach (Client c in clientsToKick) { + //reset the client's kick votes (they can rejoin after their ban expires) + c.ResetVotes(); var previousPlayer = previousPlayers.Find(p => p.MatchesClient(c)); - if (previousPlayer != null) - { - //reset the client's kick votes (they can rejoin after their ban expires) - previousPlayer.KickVoters.Clear(); - } + previousPlayer?.KickVoters.Clear(); SendChatMessage($"ServerMessage.KickedFromServer~[client]={c.Name}", ChatMessageType.Server, null, changeType: PlayerConnectionChangeType.Kicked); KickClient(c, "ServerMessage.KickedByVote"); @@ -3330,10 +3334,10 @@ namespace Barotrauma.Networking if (!recipients.Any()) { return; } IWriteMessage msg = new WriteOnlyMessage(); - msg.Write((byte)ServerPacketHeader.UPDATE_LOBBY); - msg.Write((byte)ServerNetObject.VOTE); + msg.WriteByte((byte)ServerPacketHeader.UPDATE_LOBBY); + msg.WriteByte((byte)ServerNetObject.VOTE); Voting.ServerWrite(msg); - msg.Write((byte)ServerNetObject.END_OF_MESSAGE); + msg.WriteByte((byte)ServerNetObject.END_OF_MESSAGE); foreach (var c in recipients) { @@ -3427,7 +3431,7 @@ namespace Barotrauma.Networking if (recipient?.Connection == null) { return; } IWriteMessage msg = new WriteOnlyMessage(); - msg.Write((byte)ServerPacketHeader.PERMISSIONS); + msg.WriteByte((byte)ServerPacketHeader.PERMISSIONS); client.WritePermissions(msg); serverPeer.Send(msg, recipient.Connection, DeliveryMethod.Reliable); } @@ -3462,9 +3466,9 @@ namespace Barotrauma.Networking client.GivenAchievements.Add(achievementIdentifier); IWriteMessage msg = new WriteOnlyMessage(); - msg.Write((byte)ServerPacketHeader.ACHIEVEMENT); - msg.Write(achievementIdentifier); - msg.Write(0); + msg.WriteByte((byte)ServerPacketHeader.ACHIEVEMENT); + msg.WriteIdentifier(achievementIdentifier); + msg.WriteInt32(0); serverPeer.Send(msg, client.Connection, DeliveryMethod.Reliable); } @@ -3474,9 +3478,9 @@ namespace Barotrauma.Networking if (client.GivenAchievements.Contains(achievementIdentifier)) { return; } IWriteMessage msg = new WriteOnlyMessage(); - msg.Write((byte)ServerPacketHeader.ACHIEVEMENT); - msg.Write(achievementIdentifier); - msg.Write(amount); + msg.WriteByte((byte)ServerPacketHeader.ACHIEVEMENT); + msg.WriteIdentifier(achievementIdentifier); + msg.WriteInt32(amount); serverPeer.Send(msg, client.Connection, DeliveryMethod.Reliable); } @@ -3485,10 +3489,10 @@ namespace Barotrauma.Networking { if (client == null) { return; } var msg = new WriteOnlyMessage(); - msg.Write((byte)ServerPacketHeader.TRAITOR_MESSAGE); - msg.Write((byte)messageType); - msg.Write(missionIdentifier); - msg.Write(message); + msg.WriteByte((byte)ServerPacketHeader.TRAITOR_MESSAGE); + msg.WriteByte((byte)messageType); + msg.WriteIdentifier(missionIdentifier); + msg.WriteString(message); serverPeer.Send(msg, client.Connection, DeliveryMethod.ReliableOrdered); } @@ -3497,8 +3501,8 @@ namespace Barotrauma.Networking if (!connectedClients.Any()) { return; } IWriteMessage msg = new WriteOnlyMessage(); - msg.Write((byte)ServerPacketHeader.CHEATS_ENABLED); - msg.Write(DebugConsole.CheatsEnabled); + msg.WriteByte((byte)ServerPacketHeader.CHEATS_ENABLED); + msg.WriteBoolean(DebugConsole.CheatsEnabled); msg.WritePadBits(); foreach (Client c in connectedClients) @@ -3515,7 +3519,7 @@ namespace Barotrauma.Networking if (client.Character != null) { client.Character.IsRemotePlayer = false; - client.Character.OwnerClientEndpoint = null; + client.Character.OwnerClientAddress = null; client.Character.OwnerClientName = null; } @@ -3542,7 +3546,7 @@ namespace Barotrauma.Networking newCharacter.Info.Character = newCharacter; } - newCharacter.OwnerClientEndpoint = client.Connection.Endpoint; + newCharacter.OwnerClientAddress = client.Connection.Endpoint.Address; newCharacter.OwnerClientName = client.Name; newCharacter.IsRemotePlayer = true; newCharacter.Enabled = true; @@ -3900,9 +3904,9 @@ namespace Barotrauma.Networking foreach (var client in connectedClients) { IWriteMessage msg = new WriteOnlyMessage(); - msg.Write((byte)ServerPacketHeader.MISSION); + msg.WriteByte((byte)ServerPacketHeader.MISSION); int missionIndex = GameMain.GameSession.GetMissionIndex(mission); - msg.Write((byte)(missionIndex == -1 ? 255: missionIndex)); + msg.WriteByte((byte)(missionIndex == -1 ? 255: missionIndex)); mission?.ServerWrite(msg); serverPeer.Send(msg, client.Connection, DeliveryMethod.Reliable); } @@ -3963,7 +3967,7 @@ namespace Barotrauma.Networking class PreviousPlayer { public string Name; - public Endpoint Endpoint; + public Address Address; public AccountInfo AccountInfo; public float Karma; public int KarmaKickCount; @@ -3972,14 +3976,14 @@ namespace Barotrauma.Networking public PreviousPlayer(Client c) { Name = c.Name; - Endpoint = c.Connection.Endpoint; + Address = c.Connection.Endpoint.Address; AccountInfo = c.AccountInfo; } public bool MatchesClient(Client c) { if (c.AccountInfo.AccountId.IsSome() && AccountInfo.AccountId.IsSome()) { return c.AccountInfo.AccountId == AccountInfo.AccountId; } - return c.EndpointMatches(Endpoint); + return c.AddressMatches(Address); } } } diff --git a/Barotrauma/BarotraumaServer/ServerSource/Networking/NetEntityEvent/ServerEntityEventManager.cs b/Barotrauma/BarotraumaServer/ServerSource/Networking/NetEntityEvent/ServerEntityEventManager.cs index e587e882e..0bc4f9d87 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Networking/NetEntityEvent/ServerEntityEventManager.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Networking/NetEntityEvent/ServerEntityEventManager.cs @@ -344,15 +344,15 @@ namespace Barotrauma.Networking if (client.NeedsMidRoundSync) { - msg.Write((byte)ServerNetObject.ENTITY_EVENT_INITIAL); - msg.Write(client.UnreceivedEntityEventCount); - msg.Write(client.FirstNewEventID); + msg.WriteByte((byte)ServerNetObject.ENTITY_EVENT_INITIAL); + msg.WriteUInt16(client.UnreceivedEntityEventCount); + msg.WriteUInt16(client.FirstNewEventID); Write(msg, eventsToSync, out sentEvents, client); } else { - msg.Write((byte)ServerNetObject.ENTITY_EVENT); + msg.WriteByte((byte)ServerNetObject.ENTITY_EVENT); Write(msg, eventsToSync, out sentEvents, client); } @@ -499,7 +499,7 @@ namespace Barotrauma.Networking ReadWriteMessage buffer = new ReadWriteMessage(); byte[] temp = msg.ReadBytes(msgLength - 2); - buffer.Write(temp, 0, msgLength - 2); + buffer.WriteBytes(temp, 0, msgLength - 2); buffer.BitPosition = 0; BufferEvent(new BufferedEvent(sender, sender.Character, characterStateID, entity, buffer)); diff --git a/Barotrauma/BarotraumaServer/ServerSource/Networking/OrderChatMessage.cs b/Barotrauma/BarotraumaServer/ServerSource/Networking/OrderChatMessage.cs index 0cb30a078..dbf398cae 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Networking/OrderChatMessage.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Networking/OrderChatMessage.cs @@ -7,21 +7,21 @@ namespace Barotrauma.Networking { public override void ServerWrite(IWriteMessage msg, Client c) { - msg.Write((byte)ServerNetObject.CHAT_MESSAGE); - msg.Write(NetStateID); + msg.WriteByte((byte)ServerNetObject.CHAT_MESSAGE); + msg.WriteUInt16(NetStateID); msg.WriteRangedInteger((int)ChatMessageType.Order, 0, Enum.GetValues(typeof(ChatMessageType)).Length - 1); - msg.Write(SenderName); - msg.Write(SenderClient != null); + msg.WriteString(SenderName); + msg.WriteBoolean(SenderClient != null); if (SenderClient != null) { - msg.Write(SenderClient.AccountId.TryUnwrap(out var accountId) ? accountId.StringRepresentation : SenderClient.SessionId.ToString()); + msg.WriteString(SenderClient.AccountId.TryUnwrap(out var accountId) ? accountId.StringRepresentation : SenderClient.SessionId.ToString()); } - msg.Write(Sender != null && c.InGame); + msg.WriteBoolean(Sender != null && c.InGame); if (Sender != null && c.InGame) { - msg.Write(Sender.ID); + msg.WriteUInt16(Sender.ID); } - msg.Write(false); //text color (no custom text colors for order messages) + msg.WriteBoolean(false); //text color (no custom text colors for order messages) msg.WritePadBits(); WriteOrder(msg); } diff --git a/Barotrauma/BarotraumaServer/ServerSource/Networking/Primitives/Peers/Server/LidgrenServerPeer.cs b/Barotrauma/BarotraumaServer/ServerSource/Networking/Primitives/Peers/Server/LidgrenServerPeer.cs index 4cea49857..51e8c3749 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Networking/Primitives/Peers/Server/LidgrenServerPeer.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Networking/Primitives/Peers/Server/LidgrenServerPeer.cs @@ -1,4 +1,5 @@ -using System; +#nullable enable +using System; using System.Collections.Generic; using System.Net; using System.Linq; @@ -7,10 +8,10 @@ using Lidgren.Network; namespace Barotrauma.Networking { - class LidgrenServerPeer : ServerPeer + internal sealed class LidgrenServerPeer : ServerPeer { - private NetPeerConfiguration netPeerConfiguration; - private NetServer netServer; + private readonly NetPeerConfiguration netPeerConfiguration; + private NetServer? netServer; private readonly List incomingLidgrenMessages; @@ -20,6 +21,25 @@ namespace Barotrauma.Networking netServer = null; + netPeerConfiguration = new NetPeerConfiguration("barotrauma") + { + AcceptIncomingConnections = true, + AutoExpandMTU = false, + MaximumConnections = NetConfig.MaxPlayers * 2, + EnableUPnP = serverSettings.EnableUPnP, + Port = serverSettings.Port + }; + + netPeerConfiguration.DisableMessageType( + NetIncomingMessageType.DebugMessage + | NetIncomingMessageType.WarningMessage + | NetIncomingMessageType.Receipt + | NetIncomingMessageType.ErrorMessage + | NetIncomingMessageType.Error + | NetIncomingMessageType.UnconnectedData); + + netPeerConfiguration.EnableMessageType(NetIncomingMessageType.ConnectionApproval); + connectedClients = new List(); pendingClients = new List(); @@ -32,21 +52,7 @@ namespace Barotrauma.Networking { if (netServer != null) { return; } - netPeerConfiguration = new NetPeerConfiguration("barotrauma") - { - AcceptIncomingConnections = true, - AutoExpandMTU = false, - MaximumConnections = NetConfig.MaxPlayers * 2, - EnableUPnP = serverSettings.EnableUPnP, - Port = serverSettings.Port - }; - - netPeerConfiguration.DisableMessageType(NetIncomingMessageType.DebugMessage | - NetIncomingMessageType.WarningMessage | NetIncomingMessageType.Receipt | - NetIncomingMessageType.ErrorMessage | NetIncomingMessageType.Error | - NetIncomingMessageType.UnconnectedData); - - netPeerConfiguration.EnableMessageType(NetIncomingMessageType.ConnectionApproval); + incomingLidgrenMessages.Clear(); netServer = new NetServer(netPeerConfiguration); @@ -62,7 +68,7 @@ namespace Barotrauma.Networking } } - public override void Close(string msg = null) + public override void Close(string? msg = null) { if (netServer == null) { return; } @@ -90,7 +96,9 @@ namespace Barotrauma.Networking public override void Update(float deltaTime) { - if (netServer == null) { return; } + if (netServer is null) { return; } + + ToolBox.ThrowIfNull(incomingLidgrenMessages); if (OnOwnerDetermined != null && OwnerConnection != null) { @@ -99,7 +107,7 @@ namespace Barotrauma.Networking } netServer.ReadMessages(incomingLidgrenMessages); - + //process incoming connections first foreach (NetIncomingMessage inc in incomingLidgrenMessages.Where(m => m.MessageType == NetIncomingMessageType.ConnectionApproval)) { @@ -126,7 +134,7 @@ namespace Barotrauma.Networking catch (Exception e) { string errorMsg = "Server failed to read an incoming message. {" + e + "}\n" + e.StackTrace.CleanupStackTrace(); - GameAnalyticsManager.AddErrorEventOnce("LidgrenServerPeer.Update:ClientReadException" + e.TargetSite.ToString(), GameAnalyticsManager.ErrorSeverity.Error, errorMsg); + GameAnalyticsManager.AddErrorEventOnce($"LidgrenServerPeer.Update:ClientReadException{e.TargetSite}", GameAnalyticsManager.ErrorSeverity.Error, errorMsg); #if DEBUG DebugConsole.ThrowError(errorMsg); #else @@ -138,7 +146,8 @@ namespace Barotrauma.Networking { PendingClient pendingClient = pendingClients[i]; - var connection = pendingClient.Connection as LidgrenConnection; + LidgrenConnection connection = (LidgrenConnection)pendingClient.Connection; + if (connection.NetConnection.Status == NetConnectionStatus.InitiatedConnect || connection.NetConnection.Status == NetConnectionStatus.ReceivedInitiation || connection.NetConnection.Status == NetConnectionStatus.RespondedAwaitingApproval || @@ -146,6 +155,7 @@ namespace Barotrauma.Networking { continue; } + UpdatePendingClient(pendingClient); if (i >= pendingClients.Count || pendingClients[i] != pendingClient) { i--; } } @@ -155,7 +165,9 @@ namespace Barotrauma.Networking private void InitUPnP() { - if (netServer == null) { return; } + if (netServer is null) { return; } + + ToolBox.ThrowIfNull(netPeerConfiguration); netServer.UPnP.ForwardPort(netPeerConfiguration.Port, "barotrauma"); #if USE_STEAM @@ -178,7 +190,7 @@ namespace Barotrauma.Networking private void HandleConnection(NetIncomingMessage inc) { if (netServer == null) { return; } - + if (connectedClients.Count >= serverSettings.MaxPlayers) { inc.SenderConnection.Deny(DisconnectReason.ServerFull.ToString()); @@ -188,13 +200,13 @@ namespace Barotrauma.Networking if (serverSettings.BanList.IsBanned(new LidgrenEndpoint(inc.SenderConnection.RemoteEndPoint), out string banReason)) { //IP banned: deny immediately - inc.SenderConnection.Deny(DisconnectReason.Banned.ToString() + "/ " + banReason); + inc.SenderConnection.Deny($"{DisconnectReason.Banned}/ {banReason}"); return; } - PendingClient pendingClient = pendingClients.Find(c => c.Connection is LidgrenConnection l && l.NetConnection == inc.SenderConnection); + PendingClient? pendingClient = pendingClients.Find(c => c.Connection is LidgrenConnection l && l.NetConnection == inc.SenderConnection); - if (pendingClient == null) + if (pendingClient is null) { pendingClient = new PendingClient(new LidgrenConnection(inc.SenderConnection)); pendingClients.Add(pendingClient); @@ -203,51 +215,52 @@ namespace Barotrauma.Networking inc.SenderConnection.Approve(); } - private void HandleDataMessage(NetIncomingMessage inc) + private void HandleDataMessage(NetIncomingMessage lidgrenMsg) { if (netServer == null) { return; } - PendingClient pendingClient = pendingClients.Find(c => c.Connection is LidgrenConnection l && l.NetConnection == inc.SenderConnection); + PendingClient? pendingClient = pendingClients.Find(c => c.Connection is LidgrenConnection l && l.NetConnection == lidgrenMsg.SenderConnection); - PacketHeader packetHeader = (PacketHeader)inc.ReadByte(); + IReadMessage inc = lidgrenMsg.ToReadMessage(); - if (packetHeader.IsConnectionInitializationStep() && pendingClient != null) + var (_, packetHeader, initialization) = INetSerializableStruct.Read(inc); + + if (packetHeader.IsConnectionInitializationStep() && pendingClient != null && initialization.HasValue) { - ReadConnectionInitializationStep(pendingClient, new ReadWriteMessage(inc.Data, (int)inc.Position, inc.LengthBits, false)); + ReadConnectionInitializationStep(pendingClient, inc, initialization.Value); } else if (!packetHeader.IsConnectionInitializationStep()) { - LidgrenConnection conn = connectedClients.Find(c => (c is LidgrenConnection l) && l.NetConnection == inc.SenderConnection) as LidgrenConnection; - if (conn == null) + if (!(connectedClients.Find(c => c is LidgrenConnection l && l.NetConnection == lidgrenMsg.SenderConnection) is LidgrenConnection conn)) { if (pendingClient != null) { RemovePendingClient(pendingClient, DisconnectReason.AuthenticationRequired, "Received data message from unauthenticated client"); } - else if (inc.SenderConnection.Status != NetConnectionStatus.Disconnected && - inc.SenderConnection.Status != NetConnectionStatus.Disconnecting) + else if (lidgrenMsg.SenderConnection.Status != NetConnectionStatus.Disconnected && + lidgrenMsg.SenderConnection.Status != NetConnectionStatus.Disconnecting) { - inc.SenderConnection.Disconnect(DisconnectReason.AuthenticationRequired.ToString() + "/ Received data message from unauthenticated client"); + lidgrenMsg.SenderConnection.Disconnect($"{DisconnectReason.AuthenticationRequired}/ Received data message from unauthenticated client"); } + return; } + if (pendingClient != null) { pendingClients.Remove(pendingClient); } + if (serverSettings.BanList.IsBanned(conn.Endpoint, out string banReason) || (conn.AccountInfo.AccountId.TryUnwrap(out var accountId) && serverSettings.BanList.IsBanned(accountId, out banReason)) || conn.AccountInfo.OtherMatchingIds.Any(id => serverSettings.BanList.IsBanned(id, out banReason))) { - Disconnect(conn, DisconnectReason.Banned.ToString() + "/ " + banReason); + Disconnect(conn, $"{DisconnectReason.Banned}/ {banReason}"); return; } - UInt16 length = inc.ReadUInt16(); - //DebugConsole.NewMessage(isCompressed + " " + isConnectionInitializationStep + " " + (int)incByte + " " + length); - - IReadMessage msg = new ReadOnlyMessage(inc.Data, packetHeader.IsCompressed(), inc.PositionInBytes, length, conn); - OnMessageReceived?.Invoke(conn, msg); + var packet = INetSerializableStruct.Read(inc); + OnMessageReceived?.Invoke(conn, packet.GetReadMessage(packetHeader.IsCompressed(), conn)); } } - + private void HandleStatusChanged(NetIncomingMessage inc) { if (netServer == null) { return; } @@ -255,30 +268,30 @@ namespace Barotrauma.Networking switch (inc.SenderConnection.Status) { case NetConnectionStatus.Disconnected: - string disconnectMsg; - LidgrenConnection conn = connectedClients.Select(c => c as LidgrenConnection).FirstOrDefault(c => c.NetConnection == inc.SenderConnection); + LidgrenConnection? conn = connectedClients.Cast().FirstOrDefault(c => c.NetConnection == inc.SenderConnection); if (conn != null) { if (conn == OwnerConnection) { DebugConsole.NewMessage("Owner disconnected: closing the server..."); GameServer.Log("Owner disconnected: closing the server...", ServerLog.MessageType.ServerMessage); - Close(DisconnectReason.ServerShutdown.ToString() + "/ Owner disconnected"); + Close($"{DisconnectReason.ServerShutdown}/ Owner disconnected"); } else { - disconnectMsg = $"ServerMessage.HasDisconnected~[client]={GameMain.Server.ConnectedClients.First(c => c.Connection == conn).Name}"; - Disconnect(conn, disconnectMsg); +#warning TODO: kill off disconnect in layer 1 + Disconnect(conn, $"ServerMessage.HasDisconnected~[client]={GameMain.Server.ConnectedClients.First(c => c.Connection == conn).Name}"); } } else { - PendingClient pendingClient = pendingClients.Find(c => (c.Connection is LidgrenConnection l) && l.NetConnection == inc.SenderConnection); + PendingClient? pendingClient = pendingClients.Find(c => c.Connection is LidgrenConnection l && l.NetConnection == inc.SenderConnection); if (pendingClient != null) { RemovePendingClient(pendingClient, DisconnectReason.Unknown, $"ServerMessage.HasDisconnected~[client]={pendingClient.Name}"); } } + break; } } @@ -292,25 +305,23 @@ namespace Barotrauma.Networking { if (netServer == null) { return; } - PendingClient pendingClient = pendingClients.Find(c => c.AccountInfo.AccountId is Some { Value: SteamId id } && id.Value == steamId); - DebugConsole.Log(steamId + " validation: " + status+", "+(pendingClient!=null)); - - if (pendingClient == null) + PendingClient? pendingClient = pendingClients.Find(c => c.AccountInfo.AccountId is Some { Value: SteamId id } && id.Value == steamId); + DebugConsole.Log($"{steamId} validation: {status}, {(pendingClient != null)}"); + + if (pendingClient is null) { - if (status != Steamworks.AuthResponse.OK) + if (status == Steamworks.AuthResponse.OK) { return; } + + if (connectedClients.Find(c => c.AccountInfo.AccountId is Some { Value: SteamId id } && id.Value == steamId) is LidgrenConnection connection) { - LidgrenConnection connection = connectedClients.Find(c => c.AccountInfo.AccountId is Some { Value: SteamId id } && id.Value == steamId) as LidgrenConnection; - if (connection != null) - { - Disconnect(connection, DisconnectReason.SteamAuthenticationFailed.ToString() + "/ Steam authentication status changed: " + status.ToString()); - } + Disconnect(connection, $"{DisconnectReason.SteamAuthenticationFailed}/ Steam authentication status changed: {status}"); } + return; } - LidgrenConnection pendingConnection = pendingClient.Connection as LidgrenConnection; - string banReason; - if (serverSettings.BanList.IsBanned(pendingConnection.Endpoint, out banReason) + LidgrenConnection pendingConnection = (LidgrenConnection)pendingClient.Connection; + if (serverSettings.BanList.IsBanned(pendingConnection.Endpoint, out string banReason) || serverSettings.BanList.IsBanned(new SteamId(steamId), out banReason) || serverSettings.BanList.IsBanned(new SteamId(ownerId), out banReason)) { @@ -326,8 +337,7 @@ namespace Barotrauma.Networking } else { - RemovePendingClient(pendingClient, DisconnectReason.SteamAuthenticationFailed, "Steam authentication failed: " + status.ToString()); - return; + RemovePendingClient(pendingClient, DisconnectReason.SteamAuthenticationFailed, $"Steam authentication failed: {status}"); } } @@ -335,86 +345,62 @@ namespace Barotrauma.Networking { if (netServer == null) { return; } - if (!(conn is LidgrenConnection lidgrenConn)) return; - if (!connectedClients.Contains(lidgrenConn)) + if (!connectedClients.Contains(conn)) { - DebugConsole.ThrowError("Tried to send message to unauthenticated connection: " + lidgrenConn.Endpoint.StringRepresentation); + DebugConsole.ThrowError($"Tried to send message to unauthenticated connection: {conn.Endpoint.StringRepresentation}"); return; } - NetDeliveryMethod lidgrenDeliveryMethod = NetDeliveryMethod.Unreliable; - switch (deliveryMethod) - { - case DeliveryMethod.Unreliable: - lidgrenDeliveryMethod = NetDeliveryMethod.Unreliable; - break; - case DeliveryMethod.Reliable: - lidgrenDeliveryMethod = NetDeliveryMethod.ReliableUnordered; - break; - case DeliveryMethod.ReliableOrdered: - lidgrenDeliveryMethod = NetDeliveryMethod.ReliableOrdered; - break; - } + byte[] bufAux = msg.PrepareForSending(compressPastThreshold, out bool isCompressed, out _); #if DEBUG + ToolBox.ThrowIfNull(netPeerConfiguration); netPeerConfiguration.SimulatedDuplicatesChance = GameMain.Server.SimulatedDuplicatesChance; netPeerConfiguration.SimulatedMinimumLatency = GameMain.Server.SimulatedMinimumLatency; netPeerConfiguration.SimulatedRandomLatency = GameMain.Server.SimulatedRandomLatency; netPeerConfiguration.SimulatedLoss = GameMain.Server.SimulatedLoss; #endif - NetOutgoingMessage lidgrenMsg = netServer.CreateMessage(); - byte[] msgData = new byte[msg.LengthBytes]; - msg.PrepareForSending(ref msgData, compressPastThreshold, out bool isCompressed, out int length); - lidgrenMsg.Write((byte)(isCompressed ? PacketHeader.IsCompressed : PacketHeader.None)); - lidgrenMsg.Write((UInt16)length); - lidgrenMsg.Write(msgData, 0, length); - - NetSendResult result = netServer.SendMessage(lidgrenMsg, lidgrenConn.NetConnection, lidgrenDeliveryMethod); - if (result != NetSendResult.Sent && result != NetSendResult.Queued) + var headers = new PeerPacketHeaders { - DebugConsole.NewMessage("Failed to send message to "+conn.Endpoint.StringRepresentation+": " + result.ToString(), Microsoft.Xna.Framework.Color.Yellow); - } + DeliveryMethod = deliveryMethod, + PacketHeader = isCompressed ? PacketHeader.IsCompressed : PacketHeader.None, + Initialization = null + }; + var body = new PeerPacketMessage + { + Buffer = bufAux + }; + SendMsgInternal(conn, headers, body); } - - public override void Disconnect(NetworkConnection conn,string msg=null) + + public override void Disconnect(NetworkConnection conn, string? msg = null) { if (netServer == null) { return; } if (!(conn is LidgrenConnection lidgrenConn)) { return; } + if (connectedClients.Contains(lidgrenConn)) { lidgrenConn.Status = NetworkConnectionStatus.Disconnected; connectedClients.Remove(lidgrenConn); OnDisconnect?.Invoke(conn, msg); - if (conn.AccountInfo.AccountId is Some { Value: SteamId steamId }) { Steam.SteamManager.StopAuthSession(steamId); } + if (conn.AccountInfo.AccountId is Some { Value: SteamId steamId }) { SteamManager.StopAuthSession(steamId); } } + lidgrenConn.NetConnection.Disconnect(msg ?? "Disconnected"); } - protected override void SendMsgInternal(NetworkConnection conn, DeliveryMethod deliveryMethod, IWriteMessage msg) + protected override void SendMsgInternal(NetworkConnection conn, PeerPacketHeaders headers, INetSerializableStruct? body) { - LidgrenConnection lidgrenConn = conn as LidgrenConnection; - NetDeliveryMethod lidgrenDeliveryMethod = NetDeliveryMethod.Unreliable; - switch (deliveryMethod) - { - case DeliveryMethod.Unreliable: - lidgrenDeliveryMethod = NetDeliveryMethod.Unreliable; - break; - case DeliveryMethod.Reliable: - lidgrenDeliveryMethod = NetDeliveryMethod.ReliableUnordered; - break; - case DeliveryMethod.ReliableOrdered: - lidgrenDeliveryMethod = NetDeliveryMethod.ReliableOrdered; - break; - } + IWriteMessage msgToSend = new WriteOnlyMessage(); + msgToSend.WriteNetSerializableStruct(headers); + body?.Write(msgToSend); - NetOutgoingMessage lidgrenMsg = netServer.CreateMessage(); - lidgrenMsg.Write(msg.Buffer, 0, msg.LengthBytes); - NetSendResult result = netServer.SendMessage(lidgrenMsg, lidgrenConn.NetConnection, lidgrenDeliveryMethod); + NetSendResult result = ForwardToLidgren(msgToSend, conn, headers.DeliveryMethod); if (result != NetSendResult.Sent && result != NetSendResult.Queued) { - DebugConsole.NewMessage("Failed to send message to " + conn.Endpoint.StringRepresentation + ": " + result.ToString(), Microsoft.Xna.Framework.Color.Yellow); + DebugConsole.NewMessage($"Failed to send message to {conn.Endpoint}: {result}", Microsoft.Xna.Framework.Color.Yellow); } } @@ -430,7 +416,7 @@ namespace Barotrauma.Networking } } - protected override void ProcessAuthTicket(string name, Option ownKey, Option steamId, PendingClient pendingClient, byte[] ticket) + protected override void ProcessAuthTicket(ClientSteamTicketAndVersionPacket packet, PendingClient pendingClient) { if (pendingClient.AccountInfo.AccountId.IsNone()) { @@ -438,19 +424,19 @@ namespace Barotrauma.Networking #if DEBUG requireSteamAuth = false; #endif + bool hasSteamAuth = packet.SteamAuthTicket.TryUnwrap(out var ticket); //steam auth cannot be done (SteamManager not initialized or no ticket given), //but it's not required either -> let the client join without auth - if ((!SteamManager.IsInitialized || (ticket?.Length ?? 0) == 0) - && !requireSteamAuth) + if ((!SteamManager.IsInitialized || !hasSteamAuth) && !requireSteamAuth) { - pendingClient.Name = name; - pendingClient.OwnerKey = ownKey; + pendingClient.Name = packet.Name; + pendingClient.OwnerKey = packet.OwnerKey; pendingClient.InitializationStep = serverSettings.HasPassword ? ConnectionInitialization.Password : ConnectionInitialization.ContentPackageOrder; } else { - if (!steamId.TryUnwrap(out var id)) + if (!packet.SteamId.TryUnwrap(out var id) || !(id is SteamId steamId)) { if (requireSteamAuth) { @@ -460,36 +446,42 @@ namespace Barotrauma.Networking } else { - Steamworks.BeginAuthResult authSessionStartState = Steam.SteamManager.StartAuthSession(ticket, id); + Steamworks.BeginAuthResult authSessionStartState = SteamManager.StartAuthSession(ticket, steamId); if (authSessionStartState != Steamworks.BeginAuthResult.OK) { if (requireSteamAuth) { - RemovePendingClient(pendingClient, DisconnectReason.SteamAuthenticationFailed, "Steam auth session failed to start: " + authSessionStartState.ToString()); - return; + RemovePendingClient(pendingClient, DisconnectReason.SteamAuthenticationFailed, $"Steam auth session failed to start: {authSessionStartState}"); } else { - steamId = Option.None(); + packet.SteamId = Option.None(); pendingClient.InitializationStep = serverSettings.HasPassword ? ConnectionInitialization.Password : ConnectionInitialization.ContentPackageOrder; } } } - pendingClient.Connection.SetAccountInfo(new AccountInfo(steamId.Select(uid => (AccountId)uid))); - pendingClient.Name = name; - pendingClient.OwnerKey = ownKey; + pendingClient.Connection.SetAccountInfo(new AccountInfo(packet.SteamId.Select(uid => (AccountId)uid))); + pendingClient.Name = packet.Name; + pendingClient.OwnerKey = packet.OwnerKey; pendingClient.AuthSessionStarted = true; } } else { - if (pendingClient.AccountInfo.AccountId != steamId.Select(uid => (AccountId)uid)) + if (pendingClient.AccountInfo.AccountId != packet.SteamId.Select(uid => (AccountId)uid)) { RemovePendingClient(pendingClient, DisconnectReason.SteamAuthenticationFailed, "SteamID mismatch"); - return; } } } + + private NetSendResult ForwardToLidgren(IWriteMessage msg, NetworkConnection connection, DeliveryMethod deliveryMethod) + { + ToolBox.ThrowIfNull(netServer); + + LidgrenConnection conn = (LidgrenConnection)connection; + return netServer.SendMessage(msg.ToLidgren(netServer), conn.NetConnection, deliveryMethod.ToLidgren()); + } } -} +} \ No newline at end of file diff --git a/Barotrauma/BarotraumaServer/ServerSource/Networking/Primitives/Peers/Server/ServerPeer.cs b/Barotrauma/BarotraumaServer/ServerSource/Networking/Primitives/Peers/Server/ServerPeer.cs index f70f77724..a00aa7a17 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Networking/Primitives/Peers/Server/ServerPeer.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Networking/Primitives/Peers/Server/ServerPeer.cs @@ -1,39 +1,41 @@ -using System; +#nullable enable +using System; using System.Collections.Generic; +using System.Collections.Immutable; using System.Linq; using Barotrauma.Extensions; namespace Barotrauma.Networking { - abstract class ServerPeer + internal abstract class ServerPeer { public delegate void MessageCallback(NetworkConnection connection, IReadMessage message); - public delegate void DisconnectCallback(NetworkConnection connection, string reason); - public delegate void InitializationCompleteCallback(NetworkConnection connection, string clientName); + + public delegate void DisconnectCallback(NetworkConnection connection, string? reason); + + public delegate void InitializationCompleteCallback(NetworkConnection connection, string? clientName); + public delegate void ShutdownCallback(); + public delegate void OwnerDeterminedCallback(NetworkConnection connection); - public MessageCallback OnMessageReceived; - public DisconnectCallback OnDisconnect; - public InitializationCompleteCallback OnInitializationComplete; - public ShutdownCallback OnShutdown; - public OwnerDeterminedCallback OnOwnerDetermined; - - protected Option ownerKey; - - public NetworkConnection OwnerConnection { get; protected set; } + public MessageCallback? OnMessageReceived; + public DisconnectCallback? OnDisconnect; + public InitializationCompleteCallback? OnInitializationComplete; + public ShutdownCallback? OnShutdown; + public OwnerDeterminedCallback? OnOwnerDetermined; public abstract void InitializeSteamServerCallbacks(); public abstract void Start(); - public abstract void Close(string msg = null); + public abstract void Close(string? msg = null); public abstract void Update(float deltaTime); - protected class PendingClient + protected sealed class PendingClient { - public string Name; + public string? Name; public Option OwnerKey; - public NetworkConnection Connection; + public readonly NetworkConnection Connection; public ConnectionInitialization InitializationStep; public double UpdateTime; public double TimeOut; @@ -60,76 +62,69 @@ namespace Barotrauma.Networking TimeOut = NetworkConnection.TimeoutThreshold; } } - protected List connectedClients; - protected List pendingClients; - protected ServerSettings serverSettings; + protected List connectedClients = null!; + protected List pendingClients = null!; + protected ServerSettings serverSettings = null!; + protected Option ownerKey = null!; + protected NetworkConnection? OwnerConnection; - protected void ReadConnectionInitializationStep(PendingClient pendingClient, IReadMessage inc) + protected void ReadConnectionInitializationStep(PendingClient pendingClient, IReadMessage inc, ConnectionInitialization initializationStep) { pendingClient.TimeOut = NetworkConnection.TimeoutThreshold; - ConnectionInitialization initializationStep = (ConnectionInitialization)inc.ReadByte(); - - if (pendingClient.InitializationStep != initializationStep) return; + if (pendingClient.InitializationStep != initializationStep) { return; } pendingClient.UpdateTime = Timing.TotalTime + Timing.Step; switch (initializationStep) { case ConnectionInitialization.SteamTicketAndVersion: - string name = Client.SanitizeName(inc.ReadString()); - int ownerKey = inc.ReadInt32(); - UInt64 steamIdVal = inc.ReadUInt64(); - Option steamId = steamIdVal != 0 - ? Option.Some(new SteamId(steamIdVal)) - : Option.None(); - UInt16 ticketLength = inc.ReadUInt16(); - byte[] ticketBytes = inc.ReadBytes(ticketLength); + var authPacket = INetSerializableStruct.Read(inc); - if (!Client.IsValidName(name, serverSettings)) + if (!Client.IsValidName(authPacket.Name, serverSettings)) { RemovePendingClient(pendingClient, DisconnectReason.InvalidName, ""); return; } - string version = inc.ReadString(); - bool isCompatibleVersion = NetworkMember.IsCompatible(version, GameMain.Version.ToString()) ?? false; + bool isCompatibleVersion = NetworkMember.IsCompatible(authPacket.GameVersion, GameMain.Version.ToString()) ?? false; if (!isCompatibleVersion) { RemovePendingClient(pendingClient, DisconnectReason.InvalidVersion, - $"DisconnectMessage.InvalidVersion~[version]={GameMain.Version}~[clientversion]={version}"); + $"DisconnectMessage.InvalidVersion~[version]={GameMain.Version}~[clientversion]={authPacket.GameVersion}"); - GameServer.Log($"{name} ({steamId}) couldn't join the server (incompatible game version)", ServerLog.MessageType.Error); - DebugConsole.NewMessage($"{name} ({steamId}) couldn't join the server (incompatible game version)", Microsoft.Xna.Framework.Color.Red); + GameServer.Log($"{authPacket.Name} ({authPacket.SteamId}) couldn't join the server (incompatible game version)", ServerLog.MessageType.Error); + DebugConsole.NewMessage($"{authPacket.Name} ({authPacket.SteamId}) couldn't join the server (incompatible game version)", Microsoft.Xna.Framework.Color.Red); return; } - LanguageIdentifier language = inc.ReadIdentifier().ToLanguageIdentifier(); - pendingClient.Connection.Language = language; + pendingClient.Connection.Language = authPacket.Language.ToLanguageIdentifier(); - Client nameTaken = GameMain.Server.ConnectedClients.Find(c => Homoglyphs.Compare(c.Name.ToLower(), name.ToLower())); + Client nameTaken = GameMain.Server.ConnectedClients.Find(c => Homoglyphs.Compare(c.Name.ToLower(), authPacket.Name.ToLower())); if (nameTaken != null) { RemovePendingClient(pendingClient, DisconnectReason.NameTaken, ""); - GameServer.Log($"{name} ({steamId}) couldn't join the server (name too similar to the name of the client \"" + nameTaken.Name + "\").", ServerLog.MessageType.Error); + GameServer.Log($"{authPacket.Name} ({authPacket.SteamId}) couldn't join the server (name too similar to the name of the client \"" + nameTaken.Name + "\").", ServerLog.MessageType.Error); return; } if (!pendingClient.AuthSessionStarted) { - ProcessAuthTicket(name, ownerKey != 0 ? Option.Some(ownerKey) : Option.None(), steamId, pendingClient, ticketBytes); + ProcessAuthTicket(authPacket, pendingClient); } + break; case ConnectionInitialization.Password: - int pwLength = inc.ReadByte(); - byte[] incPassword = inc.ReadBytes(pwLength); - if (pendingClient.PasswordSalt == null) + var passwordPacket = INetSerializableStruct.Read(inc); + + if (pendingClient.PasswordSalt is null) { DebugConsole.ThrowError("Received password message from client without salt"); return; } - if (serverSettings.IsPasswordCorrect(incPassword, pendingClient.PasswordSalt.Value)) + + if (serverSettings.IsPasswordCorrect(passwordPacket.Password, pendingClient.PasswordSalt.Value)) { pendingClient.InitializationStep = ConnectionInitialization.ContentPackageOrder; } @@ -138,13 +133,13 @@ namespace Barotrauma.Networking pendingClient.Retries++; if (serverSettings.BanAfterWrongPassword && pendingClient.Retries > serverSettings.MaxPasswordRetriesBeforeBan) { - string banMsg = "Failed to enter correct password too many times"; + const string banMsg = "Failed to enter correct password too many times"; BanPendingClient(pendingClient, banMsg, null); - RemovePendingClient(pendingClient, DisconnectReason.Banned, banMsg); return; } } + pendingClient.UpdateTime = Timing.TotalTime; break; case ConnectionInitialization.ContentPackageOrder: @@ -154,25 +149,25 @@ namespace Barotrauma.Networking } } - protected abstract void ProcessAuthTicket(string name, Option ownKey, Option steamId, PendingClient pendingClient, byte[] ticket); + protected abstract void ProcessAuthTicket(ClientSteamTicketAndVersionPacket packet, PendingClient pendingClient); protected void BanPendingClient(PendingClient pendingClient, string banReason, TimeSpan? duration) { void banAccountId(AccountId accountId) { - serverSettings.BanList.BanPlayer(pendingClient.Name, accountId, banReason, duration); + serverSettings.BanList.BanPlayer(pendingClient.Name ?? "Player", accountId, banReason, duration); } - + if (pendingClient.AccountInfo.AccountId.TryUnwrap(out var id)) { banAccountId(id); } + pendingClient.AccountInfo.OtherMatchingIds.ForEach(banAccountId); - serverSettings.BanList.BanPlayer(pendingClient.Name, pendingClient.Connection.Endpoint, banReason, duration); + serverSettings.BanList.BanPlayer(pendingClient.Name ?? "Player", pendingClient.Connection.Endpoint, banReason, duration); } - - protected bool IsPendingClientBanned(PendingClient pendingClient, out string banReason) + + protected bool IsPendingClientBanned(PendingClient pendingClient, out string? banReason) { - bool isAccountIdBanned(AccountId accountId, out string banReason) + bool isAccountIdBanned(AccountId accountId, out string? banReason) { - banReason = default; return serverSettings.BanList.IsBanned(accountId, out banReason); } @@ -182,16 +177,18 @@ namespace Barotrauma.Networking foreach (var otherId in pendingClient.AccountInfo.OtherMatchingIds) { if (isBanned) { break; } + isBanned |= isAccountIdBanned(otherId, out banReason); } + return isBanned; } - protected abstract void SendMsgInternal(NetworkConnection conn, DeliveryMethod deliveryMethod, IWriteMessage msg); + protected abstract void SendMsgInternal(NetworkConnection conn, PeerPacketHeaders headers, INetSerializableStruct? body); protected void UpdatePendingClient(PendingClient pendingClient) { - if (IsPendingClientBanned(pendingClient, out string banReason)) + if (IsPendingClientBanned(pendingClient, out string? banReason)) { RemovePendingClient(pendingClient, DisconnectReason.Banned, banReason); return; @@ -220,52 +217,61 @@ namespace Barotrauma.Networking } if (Timing.TotalTime < pendingClient.UpdateTime) { return; } + pendingClient.UpdateTime = Timing.TotalTime + 1.0; - IWriteMessage outMsg = new WriteOnlyMessage(); - outMsg.Write((byte)(PacketHeader.IsConnectionInitializationStep | - PacketHeader.IsServerMessage)); - outMsg.Write((byte)pendingClient.InitializationStep); + PeerPacketHeaders headers = new PeerPacketHeaders + { + DeliveryMethod = DeliveryMethod.Reliable, + PacketHeader = PacketHeader.IsConnectionInitializationStep | PacketHeader.IsServerMessage, + Initialization = pendingClient.InitializationStep + }; + + INetSerializableStruct? structToSend = null; + switch (pendingClient.InitializationStep) { case ConnectionInitialization.ContentPackageOrder: - var mpContentPackages = ContentPackageManager.EnabledPackages.All.Where(cp => cp.HasMultiplayerSyncedContent).ToList(); - outMsg.WriteVariableUInt32((UInt32)mpContentPackages.Count); - for (int i = 0; i < mpContentPackages.Count; i++) + + DateTime timeNow = DateTime.UtcNow; + structToSend = new ServerPeerContentPackageOrderPacket { - outMsg.Write(mpContentPackages[i].Name); - byte[] hashBytes = mpContentPackages[i].Hash.ByteRepresentation; - outMsg.WriteVariableUInt32((UInt32)hashBytes.Length); - outMsg.Write(hashBytes, 0, hashBytes.Length); - outMsg.Write(mpContentPackages[i].SteamWorkshopId); - UInt32 installTimeDiffSeconds = (UInt32)((mpContentPackages[i].InstallTime ?? DateTime.UtcNow) - DateTime.UtcNow).TotalSeconds; - outMsg.Write(installTimeDiffSeconds); - } + ServerName = GameMain.Server.ServerName, + ContentPackages = ContentPackageManager.EnabledPackages.All.Where(cp => cp.HasMultiplayerSyncedContent) + .Select(contentPackage => new ServerContentPackage(contentPackage, timeNow)) + .ToImmutableArray() + }; + break; case ConnectionInitialization.Password: - outMsg.Write(pendingClient.PasswordSalt == null); outMsg.WritePadBits(); - if (pendingClient.PasswordSalt == null) + structToSend = new ServerPeerPasswordPacket { - pendingClient.PasswordSalt = Lidgren.Network.CryptoRandom.Instance.Next(); - outMsg.Write(pendingClient.PasswordSalt.Value); - } - else + Salt = GetSalt(pendingClient), + RetriesLeft = Option.Some(pendingClient.Retries) + }; + + static Option GetSalt(PendingClient client) { - outMsg.Write(pendingClient.Retries); + if (client.PasswordSalt is { } salt) { return Option.Some(salt); } + + salt = Lidgren.Network.CryptoRandom.Instance.Next(); + client.PasswordSalt = salt; + return Option.Some(salt); } + break; } - SendMsgInternal(pendingClient.Connection, DeliveryMethod.Reliable, outMsg); + SendMsgInternal(pendingClient.Connection, headers, structToSend); } protected virtual void CheckOwnership(PendingClient pendingClient) { } - protected void RemovePendingClient(PendingClient pendingClient, DisconnectReason reason, string msg) + protected void RemovePendingClient(PendingClient pendingClient, DisconnectReason reason, string? msg) { if (pendingClients.Contains(pendingClient)) { - Disconnect(pendingClient.Connection, reason + "/" + msg); + Disconnect(pendingClient.Connection, $"{reason}/{msg}"); pendingClients.Remove(pendingClient); @@ -279,6 +285,6 @@ namespace Barotrauma.Networking } public abstract void Send(IWriteMessage msg, NetworkConnection conn, DeliveryMethod deliveryMethod, bool compressPastThreshold = true); - public abstract void Disconnect(NetworkConnection conn, string msg = null); + public abstract void Disconnect(NetworkConnection conn, string? msg = null); } -} +} \ No newline at end of file diff --git a/Barotrauma/BarotraumaServer/ServerSource/Networking/Primitives/Peers/Server/SteamP2PServerPeer.cs b/Barotrauma/BarotraumaServer/ServerSource/Networking/Primitives/Peers/Server/SteamP2PServerPeer.cs index e33afdbb9..70976272e 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Networking/Primitives/Peers/Server/SteamP2PServerPeer.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Networking/Primitives/Peers/Server/SteamP2PServerPeer.cs @@ -1,21 +1,20 @@ -using System; +#nullable enable +using System; using System.Collections.Generic; using System.Linq; namespace Barotrauma.Networking { - class SteamP2PServerPeer : ServerPeer + internal sealed class SteamP2PServerPeer : ServerPeer { private bool started; private readonly SteamId ownerSteamId; private UInt64 ownerKey64 => unchecked((UInt64)ownerKey.Fallback(0)); - - private SteamId ReadSteamId(IReadMessage inc) - => new SteamId(inc.ReadUInt64() ^ ownerKey64); - private void WriteSteamId(IWriteMessage msg, SteamId val) - => msg.Write(val.Value ^ ownerKey64); + + private SteamId ReadSteamId(IReadMessage inc) => new SteamId(inc.ReadUInt64() ^ ownerKey64); + private void WriteSteamId(IWriteMessage msg, SteamId val) => msg.WriteUInt64(val.Value ^ ownerKey64); public SteamP2PServerPeer(SteamId steamId, int ownerKey, ServerSettings settings) { @@ -33,23 +32,22 @@ namespace Barotrauma.Networking public override void Start() { - IWriteMessage outMsg = new WriteOnlyMessage(); - WriteSteamId(outMsg, ownerSteamId); - outMsg.Write((byte)DeliveryMethod.Reliable); - outMsg.Write((byte)(PacketHeader.IsConnectionInitializationStep | PacketHeader.IsServerMessage)); - - byte[] msgToSend = (byte[])outMsg.Buffer.Clone(); - Array.Resize(ref msgToSend, outMsg.LengthBytes); - ChildServerRelay.Write(msgToSend); + var headers = new PeerPacketHeaders + { + DeliveryMethod = DeliveryMethod.Reliable, + PacketHeader = PacketHeader.IsConnectionInitializationStep | PacketHeader.IsServerMessage, + Initialization = null + }; + SendMsgInternal(ownerSteamId, headers, null); started = true; } - public override void Close(string msg = null) + public override void Close(string? msg = null) { if (!started) { return; } - if (OwnerConnection != null) OwnerConnection.Status = NetworkConnectionStatus.Disconnected; + if (OwnerConnection != null) { OwnerConnection.Status = NetworkConnectionStatus.Disconnected; } for (int i = pendingClients.Count - 1; i >= 0; i--) { @@ -82,7 +80,7 @@ namespace Barotrauma.Networking //backwards for loop so we can remove elements while iterating for (int i = connectedClients.Count - 1; i >= 0; i--) { - SteamP2PConnection conn = connectedClients[i] as SteamP2PConnection; + SteamP2PConnection conn = (SteamP2PConnection)connectedClients[i]; conn.Decay(deltaTime); if (conn.Timeout < 0.0) { @@ -103,7 +101,7 @@ namespace Barotrauma.Networking catch (Exception e) { string errorMsg = "Server failed to read an incoming message. {" + e + "}\n" + e.StackTrace.CleanupStackTrace(); - GameAnalyticsManager.AddErrorEventOnce("SteamP2PServerPeer.Update:ClientReadException" + e.TargetSite.ToString(), GameAnalyticsManager.ErrorSeverity.Error, errorMsg); + GameAnalyticsManager.AddErrorEventOnce($"SteamP2PServerPeer.Update:ClientReadException{e.TargetSite}", GameAnalyticsManager.ErrorSeverity.Error, errorMsg); #if DEBUG DebugConsole.ThrowError(errorMsg); #else @@ -118,36 +116,36 @@ namespace Barotrauma.Networking if (i >= pendingClients.Count || pendingClients[i] != pendingClient) { i--; } } } - + private void HandleDataMessage(IReadMessage inc) { if (!started) { return; } SteamId senderSteamId = ReadSteamId(inc); - SteamId ownerSteamId = ReadSteamId(inc); - - PacketHeader packetHeader = (PacketHeader)inc.ReadByte(); - + SteamId sentOwnerSteamId = ReadSteamId(inc); + + var (deliveryMethod, packetHeader, initialization) = INetSerializableStruct.Read(inc); + if (packetHeader.IsServerMessage()) { - DebugConsole.ThrowError("Got server message from" + senderSteamId.ToString()); + DebugConsole.ThrowError($"Got server message from {senderSteamId}"); return; } - if (senderSteamId != this.ownerSteamId) //sender is remote, handle disconnects and heartbeats + if (senderSteamId != ownerSteamId) //sender is remote, handle disconnects and heartbeats { - bool connectionMatches(NetworkConnection conn) - => conn is SteamP2PConnection { Endpoint: SteamP2PEndpoint { SteamId: var steamId } } - && steamId == senderSteamId; - PendingClient pendingClient = pendingClients.Find(c => connectionMatches(c.Connection)); - SteamP2PConnection connectedClient = connectedClients.Find(connectionMatches) as SteamP2PConnection; + bool connectionMatches(NetworkConnection conn) => + conn is SteamP2PConnection { Endpoint: SteamP2PEndpoint { SteamId: var steamId } } + && steamId == senderSteamId; + + PendingClient? pendingClient = pendingClients.Find(c => connectionMatches(c.Connection)); + SteamP2PConnection? connectedClient = connectedClients.Find(connectionMatches) as SteamP2PConnection; pendingClient?.Heartbeat(); connectedClient?.Heartbeat(); - string banReason; - if (serverSettings.BanList.IsBanned(senderSteamId, out banReason) || - serverSettings.BanList.IsBanned(ownerSteamId, out banReason)) + if (serverSettings.BanList.IsBanned(senderSteamId, out string banReason) || + serverSettings.BanList.IsBanned(sentOwnerSteamId, out banReason)) { if (pendingClient != null) { @@ -155,9 +153,8 @@ namespace Barotrauma.Networking } else if (connectedClient != null) { - Disconnect(connectedClient, DisconnectReason.Banned.ToString() + "/ "+ banReason); + Disconnect(connectedClient, $"{DisconnectReason.Banned}/ {banReason}"); } - return; } else if (packetHeader.IsDisconnectMessage()) { @@ -171,7 +168,6 @@ namespace Barotrauma.Networking string disconnectMsg = $"ServerMessage.HasDisconnected~[client]={GameMain.Server.ConnectedClients.First(c => c.Connection == connectedClient).Name}"; Disconnect(connectedClient, disconnectMsg, false); } - return; } else if (packetHeader.IsHeartbeatMessage()) { @@ -182,12 +178,15 @@ namespace Barotrauma.Networking { if (pendingClient != null) { - pendingClient.Connection.SetAccountInfo(new AccountInfo(senderSteamId, ownerSteamId)); - ReadConnectionInitializationStep(pendingClient, new ReadOnlyMessage(inc.Buffer, false, inc.BytePosition, inc.LengthBytes - inc.BytePosition, null)); + pendingClient.Connection.SetAccountInfo(new AccountInfo(senderSteamId, sentOwnerSteamId)); + ReadConnectionInitializationStep( + pendingClient, + new ReadWriteMessage(inc.Buffer, inc.BitPosition, inc.LengthBits, false), + initialization ?? throw new Exception("Initialization step missing")); } - else + else if (initialization.HasValue) { - ConnectionInitialization initializationStep = (ConnectionInitialization)inc.ReadByte(); + ConnectionInitialization initializationStep = initialization.Value; if (initializationStep == ConnectionInitialization.ConnectionStarted) { pendingClients.Add(new PendingClient(new SteamP2PConnection(senderSteamId))); @@ -196,51 +195,53 @@ namespace Barotrauma.Networking } else if (connectedClient != null) { - UInt16 length = inc.ReadUInt16(); - - IReadMessage msg = new ReadOnlyMessage(inc.Buffer, packetHeader.IsCompressed(), inc.BytePosition, length, connectedClient); + var packet = INetSerializableStruct.Read(inc); + IReadMessage msg = new ReadOnlyMessage(packet.Buffer, packetHeader.IsCompressed(), 0, packet.Length, connectedClient); OnMessageReceived?.Invoke(connectedClient, msg); } } else //sender is owner { - if (OwnerConnection != null) { (OwnerConnection as SteamP2PConnection).Heartbeat(); } + (OwnerConnection as SteamP2PConnection)?.Heartbeat(); if (packetHeader.IsDisconnectMessage()) { DebugConsole.ThrowError("Received disconnect message from owner"); return; } + if (packetHeader.IsServerMessage()) { DebugConsole.ThrowError("Received server message from owner"); return; } + if (packetHeader.IsConnectionInitializationStep()) { - if (OwnerConnection == null) + if (OwnerConnection is null) { - string ownerName = inc.ReadString(); - OwnerConnection = new SteamP2PConnection(this.ownerSteamId) + var packet = INetSerializableStruct.Read(inc); + OwnerConnection = new SteamP2PConnection(ownerSteamId) { Language = GameSettings.CurrentConfig.Language }; - OwnerConnection.SetAccountInfo(new AccountInfo(this.ownerSteamId, this.ownerSteamId)); + OwnerConnection.SetAccountInfo(new AccountInfo(ownerSteamId, ownerSteamId)); - OnInitializationComplete?.Invoke(OwnerConnection, ownerName); + OnInitializationComplete?.Invoke(OwnerConnection, packet.OwnerName); } + return; } + if (packetHeader.IsHeartbeatMessage()) { return; } else { - UInt16 length = inc.ReadUInt16(); - - IReadMessage msg = new ReadOnlyMessage(inc.Buffer, packetHeader.IsCompressed(), inc.BytePosition, length, OwnerConnection); - OnMessageReceived?.Invoke(OwnerConnection, msg); + var packet = INetSerializableStruct.Read(inc); + IReadMessage msg = new ReadOnlyMessage(packet.Buffer, packetHeader.IsCompressed(), 0, packet.Length, OwnerConnection); + OnMessageReceived?.Invoke(OwnerConnection!, msg); } } } @@ -249,59 +250,67 @@ namespace Barotrauma.Networking { throw new InvalidOperationException("Called InitializeSteamServerCallbacks on SteamP2PServerPeer!"); } - + public override void Send(IWriteMessage msg, NetworkConnection conn, DeliveryMethod deliveryMethod, bool compressPastThreshold = true) { if (!started) { return; } - if (!(conn is SteamP2PConnection steamp2pConn)) { return; } - if (!connectedClients.Contains(steamp2pConn) && conn != OwnerConnection) + if (!(conn is SteamP2PConnection steamP2PConn)) { return; } + + if (!connectedClients.Contains(steamP2PConn) && conn != OwnerConnection) { - DebugConsole.ThrowError("Tried to send message to unauthenticated connection: " + steamp2pConn.AccountInfo.AccountId.ToString()); + DebugConsole.ThrowError($"Tried to send message to unauthenticated connection: {steamP2PConn.AccountInfo.AccountId}"); return; } if (!conn.AccountInfo.AccountId.TryUnwrap(out var connAccountId) || !(connAccountId is SteamId connSteamId)) { return; } - IWriteMessage msgToSend = new WriteOnlyMessage(); - byte[] msgData = new byte[16]; - msg.PrepareForSending(ref msgData, compressPastThreshold, out bool isCompressed, out int length); - WriteSteamId(msgToSend, connSteamId); - msgToSend.Write((byte)deliveryMethod); - msgToSend.Write((byte)((isCompressed ? PacketHeader.IsCompressed : PacketHeader.None) | PacketHeader.IsServerMessage)); - msgToSend.Write((UInt16)length); - msgToSend.Write(msgData, 0, length); + byte[] bufAux = msg.PrepareForSending(compressPastThreshold, out bool isCompressed, out _); - byte[] bufToSend = (byte[])msgToSend.Buffer.Clone(); - Array.Resize(ref bufToSend, msgToSend.LengthBytes); - ChildServerRelay.Write(bufToSend); + var headers = new PeerPacketHeaders + { + DeliveryMethod = deliveryMethod, + PacketHeader = (isCompressed ? PacketHeader.IsCompressed : PacketHeader.None) + | PacketHeader.IsServerMessage, + Initialization = null + }; + var body = new PeerPacketMessage + { + Buffer = bufAux + }; + SendMsgInternal(steamP2PConn, headers, body); } - private void SendDisconnectMessage(SteamId steamId, string msg) + private void SendDisconnectMessage(SteamId steamId, string? msg) { if (!started) { return; } + if (string.IsNullOrWhiteSpace(msg)) { return; } - IWriteMessage msgToSend = new WriteOnlyMessage(); - WriteSteamId(msgToSend, steamId); - msgToSend.Write((byte)DeliveryMethod.Reliable); - msgToSend.Write((byte)(PacketHeader.IsDisconnectMessage | PacketHeader.IsServerMessage)); - msgToSend.Write(msg); + var headers = new PeerPacketHeaders + { + DeliveryMethod = DeliveryMethod.Reliable, + PacketHeader = PacketHeader.IsDisconnectMessage | PacketHeader.IsServerMessage, + Initialization = null + }; + var packet = new PeerDisconnectPacket + { + Message = msg + }; - byte[] bufToSend = (byte[])msgToSend.Buffer.Clone(); - Array.Resize(ref bufToSend, msgToSend.LengthBytes); - ChildServerRelay.Write(bufToSend); + SendMsgInternal(steamId, headers, packet); } - private void Disconnect(NetworkConnection conn, string msg, bool sendDisconnectMessage) + private void Disconnect(NetworkConnection conn, string? msg, bool sendDisconnectMessage) { if (!started) { return; } if (!(conn is SteamP2PConnection steamp2pConn)) { return; } if (!conn.AccountInfo.AccountId.TryUnwrap(out var connAccountId) || !(connAccountId is SteamId connSteamId)) { return; } - + if (sendDisconnectMessage) { SendDisconnectMessage(connSteamId, msg); } + if (connectedClients.Contains(steamp2pConn)) { steamp2pConn.Status = NetworkConnectionStatus.Disconnected; @@ -315,32 +324,41 @@ namespace Barotrauma.Networking } } - public override void Disconnect(NetworkConnection conn, string msg = null) + public override void Disconnect(NetworkConnection conn, string? msg = null) { Disconnect(conn, msg, true); } - protected override void SendMsgInternal(NetworkConnection conn, DeliveryMethod deliveryMethod, IWriteMessage msg) + protected override void SendMsgInternal(NetworkConnection conn, PeerPacketHeaders headers, INetSerializableStruct? body) { - var connSteamId = conn is SteamP2PConnection { Endpoint: SteamP2PEndpoint { SteamId: var id } } - ? id : null; + var connSteamId = conn is SteamP2PConnection { Endpoint: SteamP2PEndpoint { SteamId: var id } } ? id : null; if (connSteamId is null) { return; } - + + SendMsgInternal(connSteamId, headers, body); + } + + private void SendMsgInternal(SteamId connSteamId, PeerPacketHeaders headers, INetSerializableStruct? body) + { IWriteMessage msgToSend = new WriteOnlyMessage(); WriteSteamId(msgToSend, connSteamId); - msgToSend.Write((byte)deliveryMethod); - msgToSend.Write(msg.Buffer, 0, msg.LengthBytes); - byte[] bufToSend = (byte[])msgToSend.Buffer.Clone(); - Array.Resize(ref bufToSend, msgToSend.LengthBytes); + msgToSend.WriteNetSerializableStruct(headers); + body?.Write(msgToSend); + + ForwardToOwnerProcess(msgToSend); + } + + private static void ForwardToOwnerProcess(IWriteMessage msg) + { + byte[] bufToSend = (byte[])msg.Buffer.Clone(); + Array.Resize(ref bufToSend, msg.LengthBytes); ChildServerRelay.Write(bufToSend); } - protected override void ProcessAuthTicket(string name, Option ownKey, Option steamId, PendingClient pendingClient, byte[] ticket) + protected override void ProcessAuthTicket(ClientSteamTicketAndVersionPacket packet, PendingClient pendingClient) { pendingClient.InitializationStep = serverSettings.HasPassword ? ConnectionInitialization.Password : ConnectionInitialization.ContentPackageOrder; - - pendingClient.Name = name; + pendingClient.Name = packet.Name; pendingClient.AuthSessionStarted = true; } } -} +} \ No newline at end of file diff --git a/Barotrauma/BarotraumaServer/ServerSource/Networking/RespawnManager.cs b/Barotrauma/BarotraumaServer/ServerSource/Networking/RespawnManager.cs index cfa43ea1d..6d0acea10 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Networking/RespawnManager.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Networking/RespawnManager.cs @@ -8,11 +8,6 @@ namespace Barotrauma.Networking { partial class RespawnManager : Entity, IServerSerializable { - /// - /// How much skills drop towards the job's default skill levels when respawning midround in the campaign - /// - const float SkillReductionOnCampaignMidroundRespawn = 0.75f; - private DateTime despawnTime; private float shuttleEmptyTimer; @@ -444,7 +439,7 @@ namespace Barotrauma.Networking } clients[i].Character = character; - character.OwnerClientEndpoint = clients[i].Connection.Endpoint; + character.OwnerClientAddress = clients[i].Connection.Endpoint.Address; character.OwnerClientName = clients[i].Name; GameServer.Log( $"Respawning {GameServer.ClientLogName(clients[i])} ({clients[i].Connection.Endpoint}) as {characterInfos[i].Job.Name}", ServerLog.MessageType.Spawning); @@ -561,7 +556,7 @@ namespace Barotrauma.Networking { var skillPrefab = characterInfo.Job.Prefab.Skills.Find(s => skill.Identifier == s.Identifier); if (skillPrefab == null) { continue; } - skill.Level = MathHelper.Lerp(skill.Level, skillPrefab.LevelRange.Start, SkillReductionOnCampaignMidroundRespawn); + skill.Level = MathHelper.Lerp(skill.Level, skillPrefab.LevelRange.End, SkillReductionOnDeath); } } @@ -572,20 +567,20 @@ namespace Barotrauma.Networking switch (CurrentState) { case State.Transporting: - msg.Write(ReturnCountdownStarted); - msg.Write(GameMain.Server.ServerSettings.MaxTransportTime); - msg.Write((float)(ReturnTime - DateTime.Now).TotalSeconds); + msg.WriteBoolean(ReturnCountdownStarted); + msg.WriteSingle(GameMain.Server.ServerSettings.MaxTransportTime); + msg.WriteSingle((float)(ReturnTime - DateTime.Now).TotalSeconds); break; case State.Waiting: MultiPlayerCampaign campaign = GameMain.GameSession.GameMode as MultiPlayerCampaign; var matchingData = campaign?.GetClientCharacterData(c); bool forceSpawnInMainSub = matchingData != null && !matchingData.HasSpawned; - msg.Write((ushort)pendingRespawnCount); - msg.Write((ushort)requiredRespawnCount); - msg.Write(IsRespawnPromptPendingForClient(c)); - msg.Write(RespawnCountdownStarted); - msg.Write(forceSpawnInMainSub); - msg.Write((float)(RespawnTime - DateTime.Now).TotalSeconds); + msg.WriteUInt16((ushort)pendingRespawnCount); + msg.WriteUInt16((ushort)requiredRespawnCount); + msg.WriteBoolean(IsRespawnPromptPendingForClient(c)); + msg.WriteBoolean(RespawnCountdownStarted); + msg.WriteBoolean(forceSpawnInMainSub); + msg.WriteSingle((float)(RespawnTime - DateTime.Now).TotalSeconds); break; case State.Returning: break; diff --git a/Barotrauma/BarotraumaServer/ServerSource/Networking/ServerSettings.cs b/Barotrauma/BarotraumaServer/ServerSource/Networking/ServerSettings.cs index d39451492..3a997b41a 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Networking/ServerSettings.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Networking/ServerSettings.cs @@ -27,20 +27,26 @@ namespace Barotrauma.Networking public static readonly string ClientPermissionsFile = "Data" + Path.DirectorySeparatorChar + "clientpermissions.xml"; public static readonly char SubmarineSeparatorChar = '|'; - public readonly Dictionary LastUpdateIdForFlag = new Dictionary(); - public UInt16 LastPropertyUpdateId { get; private set; } = 1; - + public readonly Dictionary LastUpdateIdForFlag + = ((NetFlags[])Enum.GetValues(typeof(NetFlags))) + .Select(f => (f, (ushort)1)) + .ToDictionary(); + public void UpdateFlag(NetFlags flag) => LastUpdateIdForFlag[flag] = (UInt16)(GameMain.NetLobbyScreen.LastUpdateID + 1); + public NetFlags UnsentFlags() + => LastUpdateIdForFlag.Keys + .Where(k => NetIdUtils.IdMoreRecent(LastUpdateIdForFlag[k], GameMain.NetLobbyScreen.LastUpdateID)) + .Aggregate(NetFlags.None, (f1, f2) => f1 | f2); + private bool IsFlagRequired(Client c, NetFlags flag) => NetIdUtils.IdMoreRecent(LastUpdateIdForFlag[flag], c.LastRecvLobbyUpdate); public NetFlags GetRequiredFlags(Client c) => LastUpdateIdForFlag.Keys .Where(k => IsFlagRequired(c, k)) - .Concat(NetFlags.None.ToEnumerable()) //prevents InvalidOperationException in Aggregate - .Aggregate((f1, f2) => f1 | f2); + .Aggregate(NetFlags.None, (f1, f2) => f1 | f2); partial void InitProjSpecific() { @@ -56,16 +62,16 @@ namespace Barotrauma.Networking property.SyncValue(); if (NetIdUtils.IdMoreRecent(property.LastUpdateID, c.LastRecvLobbyUpdate)) { - outMsg.Write(key); + outMsg.WriteUInt32(key); netProperties[key].Write(outMsg); } } - outMsg.Write((UInt32)0); + outMsg.WriteUInt32((UInt32)0); } public void ServerAdminWrite(IWriteMessage outMsg, Client c) { - c.LastSentServerSettingsUpdate = LastPropertyUpdateId; + c.LastSentServerSettingsUpdate = LastUpdateIdForFlag[NetFlags.Properties]; WriteNetProperties(outMsg, c); WriteMonsterEnabled(outMsg); BanList.ServerAdminWrite(outMsg, c); @@ -74,21 +80,21 @@ namespace Barotrauma.Networking public void ServerWrite(IWriteMessage outMsg, Client c) { NetFlags requiredFlags = GetRequiredFlags(c); - outMsg.Write((byte)requiredFlags); + outMsg.WriteByte((byte)requiredFlags); if (requiredFlags.HasFlag(NetFlags.Name)) { - outMsg.Write(ServerName); + outMsg.WriteString(ServerName); } if (requiredFlags.HasFlag(NetFlags.Message)) { - outMsg.Write(ServerMessageText); + outMsg.WriteString(ServerMessageText); } - outMsg.Write((byte)PlayStyle); - outMsg.Write((byte)MaxPlayers); - outMsg.Write(HasPassword); - outMsg.Write(IsPublic); - outMsg.Write(AllowFileTransfers); + outMsg.WriteByte((byte)PlayStyle); + outMsg.WriteByte((byte)MaxPlayers); + outMsg.WriteBoolean(HasPassword); + outMsg.WriteBoolean(IsPublic); + outMsg.WriteBoolean(AllowFileTransfers); outMsg.WritePadBits(); outMsg.WriteRangedInteger(TickRate, 1, 60); @@ -103,16 +109,18 @@ namespace Barotrauma.Networking } if (c.HasPermission(Networking.ClientPermissions.ManageSettings) - && !NetIdUtils.IdMoreRecentOrMatches(c.LastRecvServerSettingsUpdate, LastPropertyUpdateId)) + && NetIdUtils.IdMoreRecent( + newID: LastUpdateIdForFlag[NetFlags.Properties], + oldID: c.LastRecvServerSettingsUpdate)) { - outMsg.Write(true); + outMsg.WriteBoolean(true); outMsg.WritePadBits(); ServerAdminWrite(outMsg, c); } else { - outMsg.Write(false); + outMsg.WriteBoolean(false); outMsg.WritePadBits(); } } @@ -174,7 +182,6 @@ namespace Barotrauma.Networking if (propertiesChanged) { UpdateFlag(NetFlags.Properties); - LastPropertyUpdateId = (UInt16)(GameMain.NetLobbyScreen.LastUpdateID + 1); } changed |= propertiesChanged; } diff --git a/Barotrauma/BarotraumaServer/ServerSource/Networking/Voip/VoipServer.cs b/Barotrauma/BarotraumaServer/ServerSource/Networking/Voip/VoipServer.cs index 4fcdc6f73..f4063a8d1 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Networking/Voip/VoipServer.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Networking/Voip/VoipServer.cs @@ -55,8 +55,8 @@ namespace Barotrauma.Networking IWriteMessage msg = new WriteOnlyMessage(); - msg.Write((byte)ServerPacketHeader.VOICE); - msg.Write((byte)queue.QueueID); + msg.WriteByte((byte)ServerPacketHeader.VOICE); + msg.WriteByte((byte)queue.QueueID); queue.Write(msg); netServer.Send(msg, recipient.Connection, DeliveryMethod.Unreliable); diff --git a/Barotrauma/BarotraumaServer/ServerSource/Networking/Voting.cs b/Barotrauma/BarotraumaServer/ServerSource/Networking/Voting.cs index c21a8f293..ff031da8e 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Networking/Voting.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Networking/Voting.cs @@ -254,7 +254,7 @@ namespace Barotrauma break; case VoteType.Kick: byte kickedClientID = inc.ReadByte(); - if ((DateTime.Now - sender.JoinTime).TotalSeconds > GameMain.Server.ServerSettings.DisallowKickVoteTime) + if ((DateTime.Now - sender.JoinTime).TotalSeconds < GameMain.Server.ServerSettings.DisallowKickVoteTime) { GameMain.Server.SendDirectChatMessage($"ServerMessage.kickvotedisallowed", sender); } @@ -328,66 +328,66 @@ namespace Barotrauma { if (GameMain.Server == null) { return; } - msg.Write(GameMain.Server.ServerSettings.AllowSubVoting); + msg.WriteBoolean(GameMain.Server.ServerSettings.AllowSubVoting); if (GameMain.Server.ServerSettings.AllowSubVoting) { IReadOnlyDictionary voteList = GetVoteCounts(VoteType.Sub, GameMain.Server.ConnectedClients); - msg.Write((byte)voteList.Count); + msg.WriteByte((byte)voteList.Count); foreach (KeyValuePair vote in voteList) { - msg.Write((byte)vote.Value); - msg.Write(vote.Key.Name); + msg.WriteByte((byte)vote.Value); + msg.WriteString(vote.Key.Name); } } - msg.Write(GameMain.Server.ServerSettings.AllowModeVoting); + msg.WriteBoolean(GameMain.Server.ServerSettings.AllowModeVoting); if (GameMain.Server.ServerSettings.AllowModeVoting) { IReadOnlyDictionary voteList = GetVoteCounts(VoteType.Mode, GameMain.Server.ConnectedClients); - msg.Write((byte)voteList.Count); + msg.WriteByte((byte)voteList.Count); foreach (KeyValuePair vote in voteList) { - msg.Write((byte)vote.Value); - msg.Write(vote.Key.Identifier); + msg.WriteByte((byte)vote.Value); + msg.WriteIdentifier(vote.Key.Identifier); } } - msg.Write(GameMain.Server.ServerSettings.AllowEndVoting); + msg.WriteBoolean(GameMain.Server.ServerSettings.AllowEndVoting); if (GameMain.Server.ServerSettings.AllowEndVoting) { - msg.Write((byte)GameMain.Server.ConnectedClients.Count(c => c.HasSpawned && c.GetVote(VoteType.EndRound))); - msg.Write((byte)GameMain.Server.ConnectedClients.Count(c => c.HasSpawned)); + msg.WriteByte((byte)GameMain.Server.ConnectedClients.Count(c => c.HasSpawned && c.GetVote(VoteType.EndRound))); + msg.WriteByte((byte)GameMain.Server.ConnectedClients.Count(c => c.HasSpawned)); } - msg.Write(GameMain.Server.ServerSettings.AllowVoteKick); + msg.WriteBoolean(GameMain.Server.ServerSettings.AllowVoteKick); - msg.Write((byte)(ActiveVote?.State ?? VoteState.None)); + msg.WriteByte((byte)(ActiveVote?.State ?? VoteState.None)); if (ActiveVote != null) { - msg.Write((byte)ActiveVote.VoteType); + msg.WriteByte((byte)ActiveVote.VoteType); if (ActiveVote.State != VoteState.None && ActiveVote.VoteType != VoteType.Unknown) { var eligibleClients = GameMain.Server.ConnectedClients.Where(c => c.InGame && c != ActiveVote.VoteStarter); var yesClients = eligibleClients.Where(c => c.GetVote(ActiveVote.VoteType) == 2); - msg.Write((byte)yesClients.Count()); + msg.WriteByte((byte)yesClients.Count()); foreach (Client c in yesClients) { - msg.Write(c.SessionId); + msg.WriteByte(c.SessionId); } var noClients = eligibleClients.Where(c => c.GetVote(ActiveVote.VoteType) == 1); - msg.Write((byte)noClients.Count()); + msg.WriteByte((byte)noClients.Count()); foreach (Client c in noClients) { - msg.Write(c.SessionId); + msg.WriteByte(c.SessionId); } - msg.Write((byte)eligibleClients.Count()); + msg.WriteByte((byte)eligibleClients.Count()); switch (ActiveVote.State) { case VoteState.Started: - msg.Write(ActiveVote.VoteStarter.SessionId); - msg.Write((byte)GameMain.Server.ServerSettings.VoteTimeout); + msg.WriteByte(ActiveVote.VoteStarter.SessionId); + msg.WriteByte((byte)GameMain.Server.ServerSettings.VoteTimeout); switch (ActiveVote.VoteType) { @@ -395,14 +395,14 @@ namespace Barotrauma case VoteType.PurchaseAndSwitchSub: case VoteType.SwitchSub: SubmarineVote vote = ActiveVote as SubmarineVote; - msg.Write(vote.Sub.Name); - msg.Write(vote.TransferItems); + msg.WriteString(vote.Sub.Name); + msg.WriteBoolean(vote.TransferItems); break; case VoteType.TransferMoney: var transferVote = (ActiveVote as TransferVote); - msg.Write(transferVote.From?.SessionId ?? 0); - msg.Write(transferVote.To?.SessionId ?? 0); - msg.Write(transferVote.TransferAmount); + msg.WriteByte(transferVote.From?.SessionId ?? 0); + msg.WriteByte(transferVote.To?.SessionId ?? 0); + msg.WriteInt32(transferVote.TransferAmount); break; } @@ -412,16 +412,16 @@ namespace Barotrauma break; case VoteState.Passed: case VoteState.Failed: - msg.Write(ActiveVote.State == VoteState.Passed); + msg.WriteBoolean(ActiveVote.State == VoteState.Passed); switch (ActiveVote.VoteType) { case VoteType.PurchaseSub: case VoteType.PurchaseAndSwitchSub: case VoteType.SwitchSub: var subVote = ActiveVote as SubmarineVote; - msg.Write(subVote.Sub.Name); - msg.Write(subVote.TransferItems); - msg.Write((short)subVote.DeliveryFee); + msg.WriteString(subVote.Sub.Name); + msg.WriteBoolean(subVote.TransferItems); + msg.WriteInt16((short)subVote.DeliveryFee); break; } break; @@ -430,10 +430,10 @@ namespace Barotrauma } var readyClients = GameMain.Server.ConnectedClients.Where(c => c.GetVote(VoteType.StartRound)); - msg.Write((byte)readyClients.Count()); + msg.WriteByte((byte)readyClients.Count()); foreach (Client c in readyClients) { - msg.Write(c.SessionId); + msg.WriteByte(c.SessionId); } msg.WritePadBits(); diff --git a/Barotrauma/BarotraumaServer/ServerSource/Networking/WhiteList.cs b/Barotrauma/BarotraumaServer/ServerSource/Networking/WhiteList.cs deleted file mode 100644 index 0e6d43c44..000000000 --- a/Barotrauma/BarotraumaServer/ServerSource/Networking/WhiteList.cs +++ /dev/null @@ -1,207 +0,0 @@ -using Microsoft.Xna.Framework; -using System; -using System.Collections.Generic; -using Barotrauma.IO; -using System.Linq; -using System.Net; - -namespace Barotrauma.Networking -{ - partial class WhiteListedPlayer - { - private static UInt16 LastIdentifier = 0; - - public WhiteListedPlayer(string name,string ip) - { - Name = name; - IP = ip; - - UniqueIdentifier = LastIdentifier; LastIdentifier++; - } - } - - partial class WhiteList - { - partial void InitProjSpecific() - { - if (!File.Exists(SavePath)) { return; } - - string[] lines; - try - { - lines = File.ReadAllLines(SavePath); - } - catch (Exception e) - { - DebugConsole.ThrowError("Failed to open whitelist in " + SavePath, e); - return; - } - - foreach (string line in lines) - { - if (line[0] == '#') - { - string lineval = line.Substring(1, line.Length - 1); - Int32.TryParse(lineval, out int intVal); - if (lineval.ToLower() == "true" || intVal != 0) - { - Enabled = true; - } - else - { - Enabled = false; - } - } - else - { - string[] separatedLine = line.Split(','); - if (separatedLine.Length < 2) continue; - - string name = string.Join(",", separatedLine.Take(separatedLine.Length - 1)); - string ip = separatedLine.Last(); - - whitelistedPlayers.Add(new WhiteListedPlayer(name, ip)); - } - } - } - - public void Save() - { - GameServer.Log("Saving whitelist", ServerLog.MessageType.ServerMessage); - - GameMain.Server?.ServerSettings?.UpdateFlag(ServerSettings.NetFlags.Properties); - - List lines = new List(); - - if (Enabled) - { - lines.Add("#true"); - } - else - { - lines.Add("#false"); - } - foreach (WhiteListedPlayer wlp in whitelistedPlayers) - { - lines.Add(wlp.Name + "," + wlp.IP); - } - - try - { - File.WriteAllLines(SavePath, lines); - } - catch (Exception e) - { - DebugConsole.ThrowError("Saving the whitelist to " + SavePath + " failed", e); - } - } - - public bool IsWhiteListed(string name, IPAddress address) - { - if (!Enabled) return true; - WhiteListedPlayer wlp = whitelistedPlayers.Find(p => p.Name == name); - if (wlp == null) return false; - if (!string.IsNullOrWhiteSpace(wlp.IP)) - { - if (address.IsIPv4MappedToIPv6 && wlp.IP == address.MapToIPv4NoThrow().ToString()) - { - return true; - } - else - { - return wlp.IP == address.ToString(); - } - } - return true; - } - - private void RemoveFromWhiteList(WhiteListedPlayer wlp) - { - GameServer.Log("Removing " + wlp.Name + " from whitelist", ServerLog.MessageType.ServerMessage); - whitelistedPlayers.Remove(wlp); - } - - private void AddToWhiteList(string name, string ip) - { - if (string.IsNullOrWhiteSpace(name)) return; - if (whitelistedPlayers.Any(x => x.Name.ToLower() == name.ToLower() && x.IP == ip)) return; - whitelistedPlayers.Add(new WhiteListedPlayer(name, ip)); - } - - public void ServerAdminWrite(IWriteMessage outMsg, Client c) - { - if (!c.HasPermission(ClientPermissions.ManageSettings)) - { - outMsg.Write(false); outMsg.WritePadBits(); - return; - } - outMsg.Write(true); - outMsg.Write(c.Connection == GameMain.Server.OwnerConnection); - outMsg.Write(Enabled); - - outMsg.WritePadBits(); - outMsg.WriteVariableUInt32((UInt32)whitelistedPlayers.Count); - for (int i = 0; i < whitelistedPlayers.Count; i++) - { - WhiteListedPlayer whitelistedPlayer = whitelistedPlayers[i]; - - outMsg.Write(whitelistedPlayer.Name); - outMsg.Write(whitelistedPlayer.UniqueIdentifier); - if (c.Connection == GameMain.Server.OwnerConnection) - { - outMsg.Write(whitelistedPlayer.IP); - //outMsg.Write(whitelistedPlayer.SteamID); //TODO: add steamid to whitelisted players - } - } - } - - public bool ServerAdminRead(IReadMessage incMsg, Client c) - { - if (!c.HasPermission(ClientPermissions.ManageSettings)) - { - bool enabled = incMsg.ReadBoolean(); incMsg.ReadPadBits(); - UInt16 removeCount = incMsg.ReadUInt16(); - incMsg.BitPosition += removeCount * 4 * 8; - UInt16 addCount = incMsg.ReadUInt16(); - for (int i = 0; i < addCount; i++) - { - incMsg.ReadString(); //skip name - incMsg.ReadString(); //skip ip - } - return false; - } - else - { - bool prevEnabled = Enabled; - bool enabled = incMsg.ReadBoolean(); incMsg.ReadPadBits(); - Enabled = enabled; - - UInt16 removeCount = incMsg.ReadUInt16(); - for (int i = 0; i < removeCount; i++) - { - UInt16 id = incMsg.ReadUInt16(); - WhiteListedPlayer whitelistedPlayer = whitelistedPlayers.Find(p => p.UniqueIdentifier == id); - if (whitelistedPlayer != null) - { - GameServer.Log(GameServer.ClientLogName(c) + " removed " + whitelistedPlayer.Name + " from whitelist (" + whitelistedPlayer.IP + ")", ServerLog.MessageType.ConsoleUsage); - RemoveFromWhiteList(whitelistedPlayer); - } - } - - UInt16 addCount = incMsg.ReadUInt16(); - for (int i = 0; i < addCount; i++) - { - string name = incMsg.ReadString(); - string ip = incMsg.ReadString(); - - GameServer.Log(GameServer.ClientLogName(c) + " added " + name + " to whitelist (" + ip + ")", ServerLog.MessageType.ConsoleUsage); - AddToWhiteList(name, ip); - } - - bool changed = removeCount > 0 || addCount > 0 || prevEnabled != enabled; - if (changed) { Save(); } - return changed; - } - } - } -} diff --git a/Barotrauma/BarotraumaServer/ServerSource/Physics/PhysicsBody.cs b/Barotrauma/BarotraumaServer/ServerSource/Physics/PhysicsBody.cs index 0b03fe680..04abe986f 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Physics/PhysicsBody.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Physics/PhysicsBody.cs @@ -11,8 +11,8 @@ namespace Barotrauma float MaxVel = NetConfig.MaxPhysicsBodyVelocity; float MaxAngularVel = NetConfig.MaxPhysicsBodyAngularVelocity; - msg.Write(SimPosition.X); - msg.Write(SimPosition.Y); + msg.WriteSingle(SimPosition.X); + msg.WriteSingle(SimPosition.Y); #if DEBUG if (Math.Abs(FarseerBody.LinearVelocity.X) > MaxVel || @@ -22,8 +22,8 @@ namespace Barotrauma } #endif - msg.Write(FarseerBody.Awake); - msg.Write(FarseerBody.FixedRotation); + msg.WriteBoolean(FarseerBody.Awake); + msg.WriteBoolean(FarseerBody.FixedRotation); if (!FarseerBody.FixedRotation) { diff --git a/Barotrauma/BarotraumaServer/ServerSource/Traitors/TraitorMissionResult.cs b/Barotrauma/BarotraumaServer/ServerSource/Traitors/TraitorMissionResult.cs index 2f90a016d..6fe640c28 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Traitors/TraitorMissionResult.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Traitors/TraitorMissionResult.cs @@ -17,13 +17,13 @@ namespace Barotrauma public void ServerWrite(IWriteMessage msg) { - msg.Write(MissionIdentifier); - msg.Write(EndMessage); - msg.Write(Success); - msg.Write((byte)Characters.Count); + msg.WriteIdentifier(MissionIdentifier); + msg.WriteString(EndMessage); + msg.WriteBoolean(Success); + msg.WriteByte((byte)Characters.Count); foreach (Character character in Characters) { - msg.Write(character.ID); + msg.WriteUInt16(character.ID); } } } diff --git a/Barotrauma/BarotraumaServer/WindowsServer.csproj b/Barotrauma/BarotraumaServer/WindowsServer.csproj index 07f7633bd..319a53b07 100644 --- a/Barotrauma/BarotraumaServer/WindowsServer.csproj +++ b/Barotrauma/BarotraumaServer/WindowsServer.csproj @@ -2,16 +2,17 @@ Exe - netcoreapp3.1 + net6.0 Barotrauma FakeFish, Undertow Games Barotrauma Dedicated Server - 0.19.1.0 + 0.19.3.0 Copyright © FakeFish 2018-2022 AnyCPU;x64 DedicatedServer ..\BarotraumaShared\Icon.ico Debug;Release;Unstable + true ;NU1605;CS0114;CS0108CS8597;CS8600;CS8601;CS8602;CS8603;CS8604;CS8605;CS8606;CS8607;CS8608;CS8609;CS8610;CS8611;CS8612;CS8613;CS8614;CS8615;CS8616;CS8617;CS8618;CS8619;CS8620;CS8621;CS8622;CS8624;CS8625;CS8626;CS8629;CS8631;CS8632;CS8633;CS8634;CS8638;CS8643;CS8644;CS8645;CS8653;CS8654;CS8655;CS8667;CS8669;CS8670;CS8714;CS8717;CS8765 diff --git a/Barotrauma/BarotraumaShared/DeployGameAnalytics.props b/Barotrauma/BarotraumaShared/DeployGameAnalytics.props index 7c7f3bac4..e4818697e 100644 --- a/Barotrauma/BarotraumaShared/DeployGameAnalytics.props +++ b/Barotrauma/BarotraumaShared/DeployGameAnalytics.props @@ -12,7 +12,7 @@ - + \ No newline at end of file diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/EnemyAIController.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/EnemyAIController.cs index 7ecbbdaa3..1708c86da 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/EnemyAIController.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/EnemyAIController.cs @@ -3847,7 +3847,7 @@ namespace Barotrauma public override void ServerWrite(IWriteMessage msg) { - msg.Write((byte)State); + msg.WriteByte((byte)State); PetBehavior?.ServerWrite(msg); } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjective.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjective.cs index 1a14bd206..cb7523470 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjective.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjective.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using Microsoft.Xna.Framework; using Barotrauma.Extensions; +using System.Collections.Immutable; namespace Barotrauma { @@ -529,6 +530,15 @@ namespace Barotrauma } return canEquip; } + protected bool CheckItemIdentifiersOrTags(Item item, ImmutableHashSet identifiersOrTags) + { + if (identifiersOrTags.Contains(item.Prefab.Identifier)) { return true; } + foreach (var identifier in identifiersOrTags) + { + if (item.HasTag(identifier)) { return true; } + } + return false; + } protected bool CanEquip(Item item) => CanEquip(character, item); } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveCombat.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveCombat.cs index 34fed7024..625a177a7 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveCombat.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveCombat.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Linq; using FarseerPhysics.Dynamics; using static Barotrauma.AIObjectiveFindSafety; +using System.Collections.Immutable; namespace Barotrauma { @@ -967,7 +968,7 @@ namespace Barotrauma /// /// Seeks for more ammunition. Creates a new subobjective. /// - private void SeekAmmunition(Identifier[] ammunitionIdentifiers) + private void SeekAmmunition(ImmutableHashSet ammunitionIdentifiers) { retreatTarget = null; RemoveSubObjective(ref retreatObjective); @@ -1002,7 +1003,7 @@ namespace Barotrauma HumanAIController.UnequipEmptyItems(Weapon); RelatedItem item = null; Item ammunition = null; - Identifier[] ammunitionIdentifiers = null; + ImmutableHashSet ammunitionIdentifiers = null; if (WeaponComponent.requiredItems.ContainsKey(RelatedItem.RelationType.Contained)) { foreach (RelatedItem requiredItem in WeaponComponent.requiredItems[RelatedItem.RelationType.Contained]) @@ -1028,8 +1029,8 @@ namespace Barotrauma if (ammunitionIdentifiers != null) { // Try reload ammunition from inventory - bool IsInsideHeadset(Item i) => i.ParentInventory?.Owner is Item ownerItem && ownerItem.HasTag("mobileradio"); - ammunition = character.Inventory.FindItem(i => ammunitionIdentifiers.Any(id => id == i.Prefab.Identifier || i.HasTag(id)) && i.Condition > 0 && !IsInsideHeadset(i), recursive: true); + static bool IsInsideHeadset(Item i) => i.ParentInventory?.Owner is Item ownerItem && ownerItem.HasTag("mobileradio"); + ammunition = character.Inventory.FindItem(i => CheckItemIdentifiersOrTags(i, ammunitionIdentifiers) && i.Condition > 0 && !IsInsideHeadset(i), recursive: true); if (ammunition != null) { var container = Weapon.GetComponent(); diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveContainItem.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveContainItem.cs index dea08ca34..8a5c606b3 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveContainItem.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveContainItem.cs @@ -1,6 +1,8 @@ -using Barotrauma.Items.Components; +using Barotrauma.Extensions; +using Barotrauma.Items.Components; using System; using System.Collections.Generic; +using System.Collections.Immutable; using System.Linq; namespace Barotrauma @@ -11,14 +13,14 @@ namespace Barotrauma public Func GetItemPriority; - public Identifier[] ignoredContainerIdentifiers; + public ImmutableHashSet ignoredContainerIdentifiers; public bool checkInventory = true; //if the item can't be found, spawn it in the character's inventory (used by outpost NPCs and in some cases also enemy NPCs, like pirates) private readonly bool spawnItemIfNotFound; //can either be a tag or an identifier - public readonly Identifier[] itemIdentifiers; + public readonly ImmutableHashSet itemIdentifiers; public readonly ItemContainer container; private readonly Item item; public Item ItemToContain { get; private set; } @@ -61,9 +63,9 @@ namespace Barotrauma } public AIObjectiveContainItem(Character character, Identifier itemIdentifier, ItemContainer container, AIObjectiveManager objectiveManager, float priorityModifier = 1, bool spawnItemIfNotFound = false) - : this(character, new Identifier[] { itemIdentifier }, container, objectiveManager, priorityModifier, spawnItemIfNotFound) { } + : this(character, itemIdentifier.ToEnumerable().ToImmutableHashSet(), container, objectiveManager, priorityModifier, spawnItemIfNotFound) { } - public AIObjectiveContainItem(Character character, Identifier[] itemIdentifiers, ItemContainer container, AIObjectiveManager objectiveManager, float priorityModifier = 1, bool spawnItemIfNotFound = false) + public AIObjectiveContainItem(Character character, ImmutableHashSet itemIdentifiers, ItemContainer container, AIObjectiveManager objectiveManager, float priorityModifier = 1, bool spawnItemIfNotFound = false) : base(character, objectiveManager, priorityModifier) { this.itemIdentifiers = itemIdentifiers; @@ -102,7 +104,10 @@ namespace Barotrauma return containedItemCount >= ItemCount; } - private bool CheckItem(Item i) => itemIdentifiers.Any(id => i.Prefab.Identifier == id || i.HasTag(id)) && i.ConditionPercentage >= ConditionLevel && i.HasAccess(character); + private bool CheckItem(Item item) + { + return CheckItemIdentifiersOrTags(item, itemIdentifiers) && item.ConditionPercentage >= ConditionLevel && item.HasAccess(character); + } protected override void Act(float deltaTime) { diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveDecontainItem.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveDecontainItem.cs index 047c1b636..a41303c20 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveDecontainItem.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveDecontainItem.cs @@ -1,5 +1,7 @@ -using Barotrauma.Items.Components; +using Barotrauma.Extensions; +using Barotrauma.Items.Components; using System; +using System.Collections.Immutable; using System.Linq; namespace Barotrauma @@ -13,7 +15,7 @@ namespace Barotrauma //can either be a tag or an identifier private readonly string[] itemIdentifiers; private readonly ItemContainer sourceContainer; - private ItemContainer targetContainer; + private readonly ItemContainer targetContainer; private readonly Item targetItem; private AIObjectiveGetItem getItemObjective; @@ -127,7 +129,7 @@ namespace Barotrauma RemoveExistingPredicate = RemoveExistingPredicate, RemoveMax = RemoveExistingMax, GetItemPriority = GetItemPriority, - ignoredContainerIdentifiers = sourceContainer != null ? new Identifier[] { sourceContainer.Item.Prefab.Identifier } : null + ignoredContainerIdentifiers = sourceContainer?.Item.Prefab.Identifier.ToEnumerable().ToImmutableHashSet() }, onCompleted: () => IsCompleted = true, onAbandon: () => Abandon = true); diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveFixLeak.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveFixLeak.cs index a2567e72b..3e5531d20 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveFixLeak.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveFixLeak.cs @@ -177,7 +177,7 @@ namespace Barotrauma TargetName = Leak.FlowTargetHull?.DisplayName, requiredCondition = () => Leak.Submarine == character.Submarine && - Leak.linkedTo.Any(e => e is Hull h && character.CurrentHull == h), + Leak.linkedTo.Any(e => e is Hull h && (character.CurrentHull == h || h.linkedTo.Contains(character.CurrentHull))), endNodeFilter = n => n.Waypoint.CurrentHull != null && Leak.linkedTo.Any(e => e is Hull h && h == n.Waypoint.CurrentHull), // The Go To objective can be abandoned if the leak is fixed (in which case we don't want to use the dialogue) SpeakCannotReachCondition = () => !CheckObjectiveSpecific() diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveGetItem.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveGetItem.cs index 853abb82e..407b65230 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveGetItem.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveGetItem.cs @@ -21,10 +21,10 @@ namespace Barotrauma public float TargetCondition { get; set; } = 1; public bool AllowDangerousPressure { get; set; } - public readonly ImmutableArray IdentifiersOrTags; + public readonly ImmutableHashSet IdentifiersOrTags; //if the item can't be found, spawn it in the character's inventory (used by outpost NPCs) - private bool spawnItemIfNotFound = false; + private readonly bool spawnItemIfNotFound = false; private Item targetItem; private readonly Item originalTarget; @@ -32,8 +32,8 @@ namespace Barotrauma private bool isDoneSeeking; public Item TargetItem => targetItem; private int currSearchIndex; - public Identifier[] ignoredContainerIdentifiers; - public Identifier[] ignoredIdentifiersOrTags; + public ImmutableHashSet ignoredContainerIdentifiers; + public ImmutableHashSet ignoredIdentifiersOrTags; private AIObjectiveGoTo goToObjective; private float currItemPriority; private readonly bool checkInventory; @@ -93,8 +93,8 @@ namespace Barotrauma Equip = equip; this.spawnItemIfNotFound = spawnItemIfNotFound; this.checkInventory = checkInventory; - IdentifiersOrTags = ParseGearTags(identifiersOrTags).ToImmutableArray(); - ignoredIdentifiersOrTags = ParseIgnoredTags(identifiersOrTags).ToArray(); + IdentifiersOrTags = ParseGearTags(identifiersOrTags).ToImmutableHashSet(); + ignoredIdentifiersOrTags = ParseIgnoredTags(identifiersOrTags).ToImmutableHashSet(); } public static IEnumerable ParseGearTags(IEnumerable identifiersOrTags) @@ -558,11 +558,11 @@ namespace Barotrauma { if (!item.HasAccess(character)) { return false; } if (ignoredItems.Contains(item)) { return false; }; - if (ignoredIdentifiersOrTags != null && ignoredIdentifiersOrTags.Any(id => item.Prefab.Identifier == id || item.HasTag(id))) { return false; } + if (ignoredIdentifiersOrTags != null && CheckItemIdentifiersOrTags(item, ignoredIdentifiersOrTags)) { return false; } if (item.Condition < TargetCondition) { return false; } if (ItemFilter != null && !ItemFilter(item)) { return false; } if (RequireLoaded && item.Components.Any(i => !i.IsLoaded(character))) { return false; } - return IdentifiersOrTags.Any(id => id == item.Prefab.Identifier || item.HasTag(id) || (AllowVariants && !item.Prefab.VariantOf.IsEmpty && item.Prefab.VariantOf == id)); + return CheckItemIdentifiersOrTags(item, IdentifiersOrTags) || (AllowVariants && !item.Prefab.VariantOf.IsEmpty && IdentifiersOrTags.Contains(item.Prefab.VariantOf)); } public override void Reset() diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveGetItems.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveGetItems.cs index 0587b597f..e6d81bd12 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveGetItems.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveGetItems.cs @@ -25,7 +25,7 @@ namespace Barotrauma public bool RequireAllItems { get; set; } private readonly ImmutableArray gearTags; - private readonly Identifier[] ignoredTags; + private readonly ImmutableHashSet ignoredTags; private bool subObjectivesCreated; public readonly HashSet achievedItems = new HashSet(); @@ -33,7 +33,7 @@ namespace Barotrauma public AIObjectiveGetItems(Character character, AIObjectiveManager objectiveManager, IEnumerable identifiersOrTags, float priorityModifier = 1) : base(character, objectiveManager, priorityModifier) { gearTags = AIObjectiveGetItem.ParseGearTags(identifiersOrTags).ToImmutableArray(); - ignoredTags = AIObjectiveGetItem.ParseIgnoredTags(identifiersOrTags).ToArray(); + ignoredTags = AIObjectiveGetItem.ParseIgnoredTags(identifiersOrTags).ToImmutableHashSet(); } protected override bool CheckObjectiveSpecific() => subObjectivesCreated && subObjectives.None(); diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveIdle.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveIdle.cs index 4d5fbb243..72afb8181 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveIdle.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveIdle.cs @@ -259,7 +259,8 @@ namespace Barotrauma // Check that there is no unsafe hulls on the way to the target if (node.Waypoint.CurrentHull != character.CurrentHull && HumanAIController.UnsafeHulls.Contains(node.Waypoint.CurrentHull)) { return false; } return true; - }, endNodeFilter: node => !isCurrentHullAllowed | !IsForbidden(node.Waypoint.CurrentHull)); + //don't stop at ladders when idling + }, endNodeFilter: node => node.Waypoint.Ladders == null && (!isCurrentHullAllowed || !IsForbidden(node.Waypoint.CurrentHull))); if (path.Unreachable) { //can't go to this room, remove it from the list and try another room @@ -290,7 +291,9 @@ namespace Barotrauma } else if (currentTarget != null) { - PathSteering.SteeringSeek(character.GetRelativeSimPosition(currentTarget), weight: 1, nodeFilter: node => node.Waypoint.CurrentHull != null); + PathSteering.SteeringSeek(character.GetRelativeSimPosition(currentTarget), weight: 1, + nodeFilter: node => node.Waypoint.CurrentHull != null, + endNodeFilter: node => node.Waypoint.Ladders == null); } else { diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Wreck/WreckAI.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Wreck/WreckAI.cs index 25d23300b..ceeeab73b 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Wreck/WreckAI.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Wreck/WreckAI.cs @@ -444,7 +444,7 @@ namespace Barotrauma #if SERVER public void ServerEventWrite(IWriteMessage msg, Client client, NetEntityEvent.IData extraData = null) { - msg.Write(IsAlive); + msg.WriteBoolean(IsAlive); } #endif } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/Animation/HumanoidAnimController.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/Animation/HumanoidAnimController.cs index e8c70509d..02bb65dd5 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/Animation/HumanoidAnimController.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/Animation/HumanoidAnimController.cs @@ -331,39 +331,41 @@ namespace Barotrauma Collider.SetTransform(Collider.SimPosition, Collider.Rotation + angleDiff); } } - - if (character.LockHands) - { - var leftHand = GetLimb(LimbType.LeftHand); - var rightHand = GetLimb(LimbType.RightHand); - - var waist = GetLimb(LimbType.Waist) ?? GetLimb(LimbType.Torso); - - rightHand.Disabled = true; - leftHand.Disabled = true; - - Vector2 midPos = waist.SimPosition; - Matrix torsoTransform = Matrix.CreateRotationZ(waist.Rotation); - - midPos += Vector2.Transform(new Vector2(-0.3f * Dir, -0.2f), torsoTransform); - - if (rightHand.PullJointEnabled) midPos = (midPos + rightHand.PullJointWorldAnchorB) / 2.0f; - HandIK(rightHand, midPos, CurrentAnimationParams.ArmIKStrength, CurrentAnimationParams.HandIKStrength); - HandIK(leftHand, midPos, CurrentAnimationParams.ArmIKStrength, CurrentAnimationParams.HandIKStrength); - } - else if (character.AnimController.AnimationTestPose) + + if (character.AnimController.AnimationTestPose) { ApplyTestPose(); } - else if (Anim != Animation.UsingItem) + else { - if (Anim != Animation.UsingItemWhileClimbing) + if (character.LockHands) { - ResetPullJoints(); + var leftHand = GetLimb(LimbType.LeftHand); + var rightHand = GetLimb(LimbType.RightHand); + + var waist = GetLimb(LimbType.Waist) ?? GetLimb(LimbType.Torso); + + rightHand.Disabled = true; + leftHand.Disabled = true; + + Vector2 midPos = waist.SimPosition; + Matrix torsoTransform = Matrix.CreateRotationZ(waist.Rotation); + + midPos += Vector2.Transform(new Vector2(-0.3f * Dir, -0.2f), torsoTransform); + if (rightHand.PullJointEnabled) midPos = (midPos + rightHand.PullJointWorldAnchorB) / 2.0f; + HandIK(rightHand, midPos, CurrentAnimationParams.ArmIKStrength, CurrentAnimationParams.HandIKStrength); + HandIK(leftHand, midPos, CurrentAnimationParams.ArmIKStrength, CurrentAnimationParams.HandIKStrength); } - else + if (Anim != Animation.UsingItem && character.SelectedBy == null) { - ResetPullJoints(l => l.IsLowerBody); + if (Anim != Animation.UsingItemWhileClimbing) + { + ResetPullJoints(); + } + else + { + ResetPullJoints(l => l.IsLowerBody); + } } } @@ -1489,17 +1491,17 @@ namespace Barotrauma public override void DragCharacter(Character target, float deltaTime) { - if (target == null) return; + if (target == null) { return; } Limb torso = GetLimb(LimbType.Torso); Limb leftHand = GetLimb(LimbType.LeftHand); Limb rightHand = GetLimb(LimbType.RightHand); - Limb targetLeftHand = target.AnimController.GetLimb(LimbType.LeftHand); + Limb targetLeftHand = target.AnimController.GetLimb(LimbType.LeftForearm); if (targetLeftHand == null) targetLeftHand = target.AnimController.GetLimb(LimbType.Torso); if (targetLeftHand == null) targetLeftHand = target.AnimController.MainLimb; - Limb targetRightHand = target.AnimController.GetLimb(LimbType.RightHand); + Limb targetRightHand = target.AnimController.GetLimb(LimbType.RightForearm); if (targetRightHand == null) targetRightHand = target.AnimController.GetLimb(LimbType.Torso); if (targetRightHand == null) targetRightHand = target.AnimController.MainLimb; @@ -1628,7 +1630,7 @@ namespace Barotrauma } //only pull with one hand when swimming - if (i > 0 && inWater) continue; + if (i > 0 && inWater) { continue; } Vector2 diff = ConvertUnits.ToSimUnits(targetLimb.WorldPosition - pullLimb.WorldPosition); @@ -1680,14 +1682,15 @@ namespace Barotrauma targetForce = 5000.0f; } - if (!target.AllowInput) - { - targetLimb.PullJointEnabled = true; - targetLimb.PullJointMaxForce = targetForce; - targetLimb.PullJointWorldAnchorB = targetAnchor; - } + targetLimb.PullJointEnabled = true; + targetLimb.PullJointMaxForce = targetForce; + targetLimb.PullJointWorldAnchorB = targetAnchor; + targetLimb.Disabled = true; - target.AnimController.movement = -diff; + if (diff.LengthSquared() > 0.1f) + { + target.AnimController.movement = -diff; + } } float dist = ConvertUnits.ToSimUnits(Vector2.Distance(target.WorldPosition, WorldPosition)); @@ -1714,7 +1717,8 @@ namespace Barotrauma else if (target is AICharacter && target != Character.Controlled) { target.AnimController.TargetDir = WorldPosition.X > target.WorldPosition.X ? Direction.Right : Direction.Left; - target.AnimController.TargetMovement = (character.SimPosition + Vector2.UnitX * Dir) - target.SimPosition; + Vector2 movement = (character.SimPosition + Vector2.UnitX * 0.5f * Dir) - target.SimPosition; + target.AnimController.TargetMovement = movement.LengthSquared() > 0.01f ? movement : Vector2.Zero; } } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/Character.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/Character.cs index cdc68d100..dcb2deff3 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/Character.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/Character.cs @@ -2969,7 +2969,7 @@ namespace Barotrauma } else if ((GameMain.NetworkMember == null || !GameMain.NetworkMember.IsClient) && PressureProtection < (Level.Loaded?.GetRealWorldDepth(WorldPosition.Y) ?? 1.0f) && - WorldPosition.Y < CharacterHealth.CrushDepth) + WorldPosition.Y < CharacterHealth.CrushDepth && !HasAbilityFlag(AbilityFlags.ImmuneToPressure)) { //implode if below crush depth, and either outside or in a high-pressure hull if (AnimController.CurrentHull == null || AnimController.CurrentHull.LethalPressure >= 80.0f) @@ -4776,7 +4776,7 @@ namespace Barotrauma { foreach (TalentOption talentOption in talentSubTree.TalentOptionStages) { - if (talentOption.Talents.None(t => HasTalent(t.Identifier))) + if (talentOption.TalentIdentifiers.None(t => HasTalent(t))) { return false; } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/CharacterInfo.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/CharacterInfo.cs index 8c37271bd..f2d68c7c8 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/CharacterInfo.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/CharacterInfo.cs @@ -809,8 +809,8 @@ namespace Barotrauma } HumanPrefabIds = ( - element.GetAttributeIdentifier("npcsetid", Identifier.Empty), - element.GetAttributeIdentifier("npcid", Identifier.Empty)); + infoElement.GetAttributeIdentifier("npcsetid", Identifier.Empty), + infoElement.GetAttributeIdentifier("npcid", Identifier.Empty)); MissionsCompletedSinceDeath = infoElement.GetAttributeInt("missionscompletedsincedeath", 0); diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/Health/CharacterHealth.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/Health/CharacterHealth.cs index e91b9d77e..58c1de0d0 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/Health/CharacterHealth.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/Health/CharacterHealth.cs @@ -1146,14 +1146,14 @@ namespace Barotrauma activeAfflictions.Add(affliction); } } - msg.Write((byte)activeAfflictions.Count); + msg.WriteByte((byte)activeAfflictions.Count); foreach (Affliction affliction in activeAfflictions) { - msg.Write(affliction.Prefab.UintIdentifier); + msg.WriteUInt32(affliction.Prefab.UintIdentifier); msg.WriteRangedSingle( MathHelper.Clamp(affliction.Strength, 0.0f, affliction.Prefab.MaxStrength), 0.0f, affliction.Prefab.MaxStrength, 8); - msg.Write((byte)affliction.Prefab.PeriodicEffects.Count()); + msg.WriteByte((byte)affliction.Prefab.PeriodicEffects.Count()); foreach (AfflictionPrefab.PeriodicEffect periodicEffect in affliction.Prefab.PeriodicEffects) { msg.WriteRangedSingle(affliction.PeriodicEffectTimers[periodicEffect], periodicEffect.MinInterval, periodicEffect.MaxInterval, 8); @@ -1170,15 +1170,15 @@ namespace Barotrauma limbAfflictions.Add((limbHealth, limbAffliction)); } - msg.Write((byte)limbAfflictions.Count); + msg.WriteByte((byte)limbAfflictions.Count); foreach (var (limbHealth, affliction) in limbAfflictions) { msg.WriteRangedInteger(limbHealths.IndexOf(limbHealth), 0, limbHealths.Count - 1); - msg.Write(affliction.Prefab.UintIdentifier); + msg.WriteUInt32(affliction.Prefab.UintIdentifier); msg.WriteRangedSingle( MathHelper.Clamp(affliction.Strength, 0.0f, affliction.Prefab.MaxStrength), 0.0f, affliction.Prefab.MaxStrength, 8); - msg.Write((byte)affliction.Prefab.PeriodicEffects.Count()); + msg.WriteByte((byte)affliction.Prefab.PeriodicEffects.Count()); foreach (AfflictionPrefab.PeriodicEffect periodicEffect in affliction.Prefab.PeriodicEffects) { msg.WriteRangedSingle(affliction.PeriodicEffectTimers[periodicEffect], periodicEffect.MinInterval, periodicEffect.MaxInterval, 8); diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/HumanPrefab.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/HumanPrefab.cs index 1e041438a..e3d7bedf4 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/HumanPrefab.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/HumanPrefab.cs @@ -85,7 +85,7 @@ namespace Barotrauma public readonly List<(XElement element, float commonness)> ItemSets = new List<(XElement element, float commonness)>(); public readonly List<(XElement element, float commonness)> CustomCharacterInfos = new List<(XElement element, float commonness)>(); - private readonly Identifier npcSetIdentifier; + public readonly Identifier NpcSetIdentifier; public HumanPrefab(ContentXElement element, ContentFile file, Identifier npcSetIdentifier) : base(file, element.GetAttributeIdentifier("identifier", "")) { @@ -94,7 +94,7 @@ namespace Barotrauma element.GetChildElements("itemset").ForEach(e => ItemSets.Add((e, e.GetAttributeFloat("commonness", 1)))); element.GetChildElements("character").ForEach(e => CustomCharacterInfos.Add((e, e.GetAttributeFloat("commonness", 1)))); PreferredOutpostModuleTypes = element.GetAttributeIdentifierArray("preferredoutpostmoduletypes", Array.Empty()); - this.npcSetIdentifier = npcSetIdentifier; + this.NpcSetIdentifier = npcSetIdentifier; } public IEnumerable GetModuleFlags() @@ -183,7 +183,7 @@ namespace Barotrauma { characterInfo = new CharacterInfo(characterElement, Identifier); } - characterInfo.HumanPrefabIds = (npcSetIdentifier, Identifier); + characterInfo.HumanPrefabIds = (NpcSetIdentifier, Identifier); return characterInfo; } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/Talents/Abilities/AbilityConditionals/AbilityConditionDataless/AbilityConditionAboveVitality.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/Talents/Abilities/AbilityConditionals/AbilityConditionDataless/AbilityConditionAboveVitality.cs index de5597011..e3997e128 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/Talents/Abilities/AbilityConditionals/AbilityConditionDataless/AbilityConditionAboveVitality.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/Talents/Abilities/AbilityConditionals/AbilityConditionDataless/AbilityConditionAboveVitality.cs @@ -1,6 +1,4 @@ -using System.Xml.Linq; - -namespace Barotrauma.Abilities +namespace Barotrauma.Abilities { class AbilityConditionAboveVitality : AbilityConditionDataless { @@ -13,7 +11,7 @@ namespace Barotrauma.Abilities protected override bool MatchesConditionSpecific() { - return character.HealthPercentage / 100f > vitalityPercentage; + return character.Vitality / character.MaxVitality > vitalityPercentage; } } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/Talents/Abilities/AbilityConditionals/AbilityConditionDataless/AbilityConditionAlliesAboveVitality.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/Talents/Abilities/AbilityConditionals/AbilityConditionDataless/AbilityConditionAlliesAboveVitality.cs index 55a640a17..92f7af301 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/Talents/Abilities/AbilityConditionals/AbilityConditionDataless/AbilityConditionAlliesAboveVitality.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/Talents/Abilities/AbilityConditionals/AbilityConditionDataless/AbilityConditionAlliesAboveVitality.cs @@ -1,11 +1,10 @@ using System.Linq; -using System.Xml.Linq; namespace Barotrauma.Abilities { class AbilityConditionAlliesAboveVitality : AbilityConditionDataless { - float vitalityPercentage; + readonly float vitalityPercentage; public AbilityConditionAlliesAboveVitality(CharacterTalent characterTalent, ContentXElement conditionElement) : base(characterTalent, conditionElement) { diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/Talents/Abilities/AbilityConditionals/AbilityConditionDataless/AbilityConditionCoauthor.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/Talents/Abilities/AbilityConditionals/AbilityConditionDataless/AbilityConditionCoauthor.cs index 50c650f1d..b368fad6c 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/Talents/Abilities/AbilityConditionals/AbilityConditionDataless/AbilityConditionCoauthor.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/Talents/Abilities/AbilityConditionals/AbilityConditionDataless/AbilityConditionCoauthor.cs @@ -1,7 +1,4 @@ -using System.Linq; -using System.Xml.Linq; - -namespace Barotrauma.Abilities +namespace Barotrauma.Abilities { class AbilityConditionCoauthor : AbilityConditionDataless { diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/Talents/Abilities/AbilityConditionals/AbilityConditionDataless/AbilityConditionCrouched.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/Talents/Abilities/AbilityConditionals/AbilityConditionDataless/AbilityConditionCrouched.cs index cc44ec6ac..e15b36dec 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/Talents/Abilities/AbilityConditionals/AbilityConditionDataless/AbilityConditionCrouched.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/Talents/Abilities/AbilityConditionals/AbilityConditionDataless/AbilityConditionCrouched.cs @@ -1,7 +1,4 @@ -using System.Linq; -using System.Xml.Linq; - -namespace Barotrauma.Abilities +namespace Barotrauma.Abilities { class AbilityConditionCrouched : AbilityConditionDataless { diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/Talents/Abilities/AbilityConditionals/AbilityConditionDataless/AbilityConditionHasAffliction.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/Talents/Abilities/AbilityConditionals/AbilityConditionDataless/AbilityConditionHasAffliction.cs index 68c46cd12..8470362c8 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/Talents/Abilities/AbilityConditionals/AbilityConditionDataless/AbilityConditionHasAffliction.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/Talents/Abilities/AbilityConditionals/AbilityConditionDataless/AbilityConditionHasAffliction.cs @@ -1,28 +1,22 @@ -using System.Linq; -using System.Xml.Linq; - -namespace Barotrauma.Abilities +namespace Barotrauma.Abilities { class AbilityConditionHasAffliction : AbilityConditionDataless { - private string afflictionIdentifier; - private float minimumPercentage; - + private readonly Identifier afflictionIdentifier; + private readonly float minimumPercentage; public AbilityConditionHasAffliction(CharacterTalent characterTalent, ContentXElement conditionElement) : base(characterTalent, conditionElement) { - afflictionIdentifier = conditionElement.GetAttributeString("afflictionidentifier", ""); + afflictionIdentifier = conditionElement.GetAttributeIdentifier("afflictionidentifier", Identifier.Empty); minimumPercentage = conditionElement.GetAttributeFloat("minimumpercentage", 0f); } protected override bool MatchesConditionSpecific() { - if (!string.IsNullOrEmpty(afflictionIdentifier)) + if (!afflictionIdentifier.IsEmpty) { var affliction = character.CharacterHealth.GetAffliction(afflictionIdentifier); - if (affliction == null) { return false; } - return minimumPercentage <= affliction.Strength / affliction.Prefab.MaxStrength; } return false; diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/Talents/Abilities/AbilityConditionals/AbilityConditionDataless/AbilityConditionHasItem.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/Talents/Abilities/AbilityConditionals/AbilityConditionDataless/AbilityConditionHasItem.cs index 4407fcb18..04d7ebf62 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/Talents/Abilities/AbilityConditionals/AbilityConditionDataless/AbilityConditionHasItem.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/Talents/Abilities/AbilityConditionals/AbilityConditionDataless/AbilityConditionHasItem.cs @@ -3,55 +3,43 @@ using Barotrauma.Items.Components; using System.Collections.Generic; using System.Linq; using System.Xml.Linq; +using Barotrauma.Extensions; namespace Barotrauma.Abilities { class AbilityConditionHasItem : AbilityConditionDataless { - // not used for anything atm, will be used for clown subclass private readonly string[] tags; - private InvSlotType? invSlotType; - bool requireAll; - - private List items = new List(); + readonly bool requireAll; public AbilityConditionHasItem(CharacterTalent characterTalent, ContentXElement conditionElement) : base(characterTalent, conditionElement) { - tags = conditionElement.GetAttributeStringArray("tags", Array.Empty(), convertToLowerInvariant: true); + tags = conditionElement.GetAttributeStringArray("tags", Array.Empty()); requireAll = conditionElement.GetAttributeBool("requireall", false); - //this.invSlotType = invSlotType; } protected override bool MatchesConditionSpecific() { - items.Clear(); - if (tags.Any()) + if (tags.None()) { - foreach (string tag in tags) - { - // there is a better method, should use that instead - if (character.GetEquippedItem(tag, invSlotType) is Item foundItem) - { - items.Add(foundItem); - } - } - - } - else - { - if (character.GetEquippedItem(null, invSlotType) is Item foundItem) - { - items.Add(foundItem); - } + return character.GetEquippedItem(null) is Item; } if (requireAll) { - return (items.Count >= tags.Count()); + foreach (string tag in tags) + { + if (character.GetEquippedItem(tag) == null) { return false; } + } + return true; } else { - return items.Any(); + foreach (string tag in tags) + { + if (character.GetEquippedItem(tag) != null) { return true; } + } + return false; } } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/Talents/Abilities/AbilityConditionals/AbilityConditionDataless/AbilityConditionHasVelocity.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/Talents/Abilities/AbilityConditionals/AbilityConditionDataless/AbilityConditionHasVelocity.cs index d54fd0839..b6abddd3d 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/Talents/Abilities/AbilityConditionals/AbilityConditionDataless/AbilityConditionHasVelocity.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/Talents/Abilities/AbilityConditionals/AbilityConditionDataless/AbilityConditionHasVelocity.cs @@ -1,7 +1,4 @@ -using System.Linq; -using System.Xml.Linq; - -namespace Barotrauma.Abilities +namespace Barotrauma.Abilities { class AbilityConditionHasVelocity : AbilityConditionDataless { diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/Talents/Abilities/AbilityConditionals/AbilityConditionDataless/AbilityConditionShipFlooded.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/Talents/Abilities/AbilityConditionals/AbilityConditionDataless/AbilityConditionShipFlooded.cs index f75f98a89..a8d33433a 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/Talents/Abilities/AbilityConditionals/AbilityConditionDataless/AbilityConditionShipFlooded.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/Talents/Abilities/AbilityConditionals/AbilityConditionDataless/AbilityConditionShipFlooded.cs @@ -1,7 +1,4 @@ -using System.Linq; -using System.Xml.Linq; - -namespace Barotrauma.Abilities +namespace Barotrauma.Abilities { class AbilityConditionShipFlooded : AbilityConditionDataless { @@ -14,8 +11,14 @@ namespace Barotrauma.Abilities protected override bool MatchesConditionSpecific() { if (!character.IsInFriendlySub) { return false; } - float currentFloodPercentage = character.Submarine.GetHulls(false).Average(h => h.WaterPercentage); - return currentFloodPercentage / 100 > floodPercentage; + float waterVolume = 0.0f, totalVolume = 0.0f; + foreach (Hull hull in Hull.HullList) + { + if (hull.Submarine != character.Submarine) { continue; } + waterVolume += hull.WaterVolume; + totalVolume += hull.Volume; + } + return (waterVolume / totalVolume) > floodPercentage; } } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/Talents/Abilities/CharacterAbilityModifyStatToFlooding.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/Talents/Abilities/CharacterAbilityModifyStatToFlooding.cs index 29d1fdf3c..d17d62b98 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/Talents/Abilities/CharacterAbilityModifyStatToFlooding.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/Talents/Abilities/CharacterAbilityModifyStatToFlooding.cs @@ -1,7 +1,4 @@ -using System.Linq; -using System.Xml.Linq; - -namespace Barotrauma.Abilities +namespace Barotrauma.Abilities { class CharacterAbilityModifyStatToFlooding : CharacterAbility { @@ -22,8 +19,14 @@ namespace Barotrauma.Abilities if (conditionsMatched && Character.IsInFriendlySub) { - float currentFloodPercentage = Character.Submarine.GetHulls(false).Average(h => h.WaterPercentage); - lastValue = currentFloodPercentage / 100f * maxValue; + float waterVolume = 0.0f, totalVolume = 0.0f; + foreach (Hull hull in Hull.HullList) + { + if (hull.Submarine != Character.Submarine) { continue; } + waterVolume += hull.WaterVolume; + totalVolume += hull.Volume; + } + lastValue = (totalVolume == 0.0f ? 1.0f : waterVolume / totalVolume) * maxValue; Character.ChangeStat(statType, lastValue); } else diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/Talents/Abilities/CharacterAbilityUnlockTree.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/Talents/Abilities/CharacterAbilityUnlockTree.cs index c76b7fb01..e8d0ad788 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/Talents/Abilities/CharacterAbilityUnlockTree.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/Talents/Abilities/CharacterAbilityUnlockTree.cs @@ -1,8 +1,4 @@ -using System.Collections.Generic; -using System.Linq; -using System.Xml.Linq; - -namespace Barotrauma.Abilities +namespace Barotrauma.Abilities { class CharacterAbilityUnlockTree : CharacterAbility { @@ -14,22 +10,19 @@ namespace Barotrauma.Abilities { if (!TalentTree.JobTalentTrees.TryGet(Character.Info.Job.Prefab.Identifier, out TalentTree talentTree)) { return; } - var subTree = talentTree.TalentSubTrees.Find(t => t.TalentOptionStages.Any(ts => ts.Talents.Contains(CharacterTalent.Prefab))); + var subTree = talentTree.TalentSubTrees.Find(t => t.AllTalentIdentifiers.Contains(CharacterTalent.Prefab.Identifier)); if (subTree == null) { return; } subTree.ForceUnlock = true; if (!addingFirstTime) { return; } - foreach (var talentOption in subTree.TalentOptionStages) + foreach (var talentId in subTree.AllTalentIdentifiers) { - foreach (var talent in talentOption.Talents) + if (talentId == CharacterTalent.Prefab.Identifier) { continue; } + if (Character.GiveTalent(talentId)) { - if (talent == CharacterTalent.Prefab) { continue; } - if (Character.GiveTalent(talent)) - { - Character.Info.AdditionalTalentPoints++; - } - } + Character.Info.AdditionalTalentPoints++; + } } } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/Talents/Abilities/CustomAbilities/CharacterAbilityInsurancePolicy.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/Talents/Abilities/CustomAbilities/CharacterAbilityInsurancePolicy.cs index 3ea78fd56..982cb2371 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/Talents/Abilities/CustomAbilities/CharacterAbilityInsurancePolicy.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/Talents/Abilities/CustomAbilities/CharacterAbilityInsurancePolicy.cs @@ -1,10 +1,4 @@ -using Barotrauma.Networking; -using Microsoft.Xna.Framework; -using System.Collections.Generic; -using System.Linq; -using System.Xml.Linq; - -namespace Barotrauma.Abilities +namespace Barotrauma.Abilities { class CharacterAbilityInsurancePolicy : CharacterAbility { @@ -19,10 +13,10 @@ namespace Barotrauma.Abilities protected override void ApplyEffect(AbilityObject abilityObject) { - if (Character?.Info is CharacterInfo info) + if (Character?.Info is CharacterInfo info && GameMain.GameSession?.GameMode is CampaignMode campaign) { int totalAmount = moneyPerMission * info.MissionsCompletedSinceDeath; - Character.GiveMoney(totalAmount); + campaign.Bank.Give(totalAmount); GameAnalyticsManager.AddMoneyGainedEvent(totalAmount, GameAnalyticsManager.MoneySource.Ability, CharacterTalent.Prefab.Identifier.Value); } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/Talents/AbilityGroups/CharacterAbilityGroup.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/Talents/AbilityGroups/CharacterAbilityGroup.cs index 656e5d751..bd4b45998 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/Talents/AbilityGroups/CharacterAbilityGroup.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/Talents/AbilityGroups/CharacterAbilityGroup.cs @@ -15,7 +15,7 @@ namespace Barotrauma.Abilities public readonly AbilityEffectType AbilityEffectType; - protected int maxTriggerCount { get; } + protected readonly int maxTriggerCount; protected int timesTriggered = 0; @@ -88,8 +88,6 @@ namespace Barotrauma.Abilities // XML private AbilityCondition ConstructCondition(CharacterTalent characterTalent, ContentXElement conditionElement, bool errorMessages = true) { - AbilityCondition newCondition = null; - Type conditionType; string type = conditionElement.Name.ToString().ToLowerInvariant(); try @@ -109,6 +107,7 @@ namespace Barotrauma.Abilities object[] args = { characterTalent, conditionElement }; + AbilityCondition newCondition; try { newCondition = (AbilityCondition)Activator.CreateInstance(conditionType, args); @@ -210,8 +209,7 @@ namespace Barotrauma.Abilities public static AbilityFlags ParseFlagType(string flagTypeString, string debugIdentifier) { - AbilityFlags flagType = AbilityFlags.None; - if (!Enum.TryParse(flagTypeString, true, out flagType)) + if (!Enum.TryParse(flagTypeString, true, out AbilityFlags flagType)) { DebugConsole.ThrowError("Invalid flag type type \"" + flagTypeString + "\" in CharacterTalent (" + debugIdentifier + ")"); } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/Talents/TalentTree.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/Talents/TalentTree.cs index 0d6c08118..e3379314f 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/Talents/TalentTree.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/Talents/TalentTree.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; -using System.Xml.Linq; namespace Barotrauma { @@ -19,7 +18,12 @@ namespace Barotrauma public static readonly PrefabCollection JobTalentTrees = new PrefabCollection(); - public readonly List TalentSubTrees = new List(); + public readonly ImmutableArray TalentSubTrees; + + /// + /// Talent identifiers of all the talents in this tree + /// + public readonly ImmutableHashSet AllTalentIdentifiers; public ContentXElement ConfigElement { @@ -36,16 +40,19 @@ namespace Barotrauma DebugConsole.ThrowError($"No job defined for talent tree in \"{file.Path}\"!"); return; } - + + List subTrees = new List(); foreach (var subTreeElement in element.GetChildElements("subtree")) { - TalentSubTrees.Add(new TalentSubTree(subTreeElement)); + subTrees.Add(new TalentSubTree(subTreeElement)); } + TalentSubTrees = subTrees.ToImmutableArray(); + AllTalentIdentifiers = TalentSubTrees.SelectMany(t => t.AllTalentIdentifiers).ToImmutableHashSet(); } public bool TalentIsInTree(Identifier talentIdentifier) { - return TalentSubTrees.SelectMany(s => s.TalentOptionStages.SelectMany(o => o.Talents.Select(t => t.Identifier))).Any(c => c == talentIdentifier); + return AllTalentIdentifiers.Contains(talentIdentifier); } public static bool IsViableTalentForCharacter(Character character, Identifier talentIdentifier) @@ -54,6 +61,7 @@ namespace Barotrauma } // i hate this function - markus + // me too - joonas public static TalentTreeStageState GetTalentOptionStageState(Character character, Identifier subTreeIdentifier, int index, List selectedTalents) { if (character?.Info?.Job.Prefab is null) { return TalentTreeStageState.Invalid; } @@ -66,12 +74,12 @@ namespace Barotrauma TalentOption targetTalentOption = subTree.TalentOptionStages[index]; - if (targetTalentOption.Talents.Any(t => character.HasTalent(t.Identifier))) + if (targetTalentOption.TalentIdentifiers.Any(t => character.HasTalent(t))) { return TalentTreeStageState.Unlocked; } - if (targetTalentOption.Talents.Any(t => selectedTalents.Contains(t.Identifier))) + if (targetTalentOption.TalentIdentifiers.Any(t => selectedTalents.Contains(t))) { return TalentTreeStageState.Highlighted; } @@ -83,8 +91,8 @@ namespace Barotrauma if (lastindex >= 0) { TalentOption lastLatentOption = subTree.TalentOptionStages[lastindex]; - hasTalentInLastTier = lastLatentOption.Talents.Any(HasTalent); - isLastTalentPurchased = lastLatentOption.Talents.Any(t => character.HasTalent(t.Identifier)); + hasTalentInLastTier = lastLatentOption.TalentIdentifiers.Any(HasTalent); + isLastTalentPurchased = lastLatentOption.TalentIdentifiers.Any(t => character.HasTalent(t)); } if (!hasTalentInLastTier) @@ -101,9 +109,9 @@ namespace Barotrauma return TalentTreeStageState.Locked; - bool HasTalent(TalentPrefab t) + bool HasTalent(Identifier talentId) { - return selectedTalents.Contains(t.Identifier); + return selectedTalents.Contains(talentId); } } @@ -117,14 +125,14 @@ namespace Barotrauma foreach (var subTree in talentTree.TalentSubTrees) { - if (subTree.ForceUnlock && subTree.TalentOptionStages.Any(option => option.Talents.Any(t => t.Identifier == talentIdentifier))) { return true; } + if (subTree.ForceUnlock && subTree.TalentOptionStages.Any(option => option.TalentIdentifiers.Contains(talentIdentifier))) { return true; } foreach (var talentOptionStage in subTree.TalentOptionStages) { - bool hasTalentInThisTier = talentOptionStage.Talents.Any(t => selectedTalents.Contains(t.Identifier)); + bool hasTalentInThisTier = talentOptionStage.TalentIdentifiers.Any(t => selectedTalents.Contains(t)); if (!hasTalentInThisTier) { - if (talentOptionStage.Talents.Any(t => t.Identifier == talentIdentifier)) + if (talentOptionStage.TalentIdentifiers.Contains(talentIdentifier)) { return true; } @@ -170,18 +178,21 @@ namespace Barotrauma public bool ForceUnlock; - public readonly List TalentOptionStages = new List(); + public readonly ImmutableArray TalentOptionStages; + + public readonly ImmutableHashSet AllTalentIdentifiers; public TalentSubTree(ContentXElement subTreeElement) { Identifier = subTreeElement.GetAttributeIdentifier("identifier", ""); - DisplayName = TextManager.Get("talenttree." + Identifier).Fallback(Identifier.Value); - + List talentOptionStages = new List(); foreach (var talentOptionsElement in subTreeElement.GetChildElements("talentoptions")) { - TalentOptionStages.Add(new TalentOption(talentOptionsElement, Identifier)); + talentOptionStages.Add(new TalentOption(talentOptionsElement, Identifier)); } + TalentOptionStages = talentOptionStages.ToImmutableArray(); + AllTalentIdentifiers = TalentOptionStages.SelectMany(t => t.TalentIdentifiers).ToImmutableHashSet(); } } @@ -190,8 +201,12 @@ namespace Barotrauma { private readonly ImmutableHashSet talentIdentifiers; - public IEnumerable Talents - => talentIdentifiers.Select(id => TalentPrefab.TalentPrefabs[id]); + public IEnumerable TalentIdentifiers => talentIdentifiers; + + public bool HasTalent(Identifier talentIdentifier) + { + return talentIdentifiers.Contains(talentIdentifier); + } public TalentOption(ContentXElement talentOptionsElement, Identifier debugIdentifier) { diff --git a/Barotrauma/BarotraumaShared/SharedSource/ContentManagement/ContentFile/TutorialsFile.cs b/Barotrauma/BarotraumaShared/SharedSource/ContentManagement/ContentFile/TutorialsFile.cs new file mode 100644 index 000000000..a2409d954 --- /dev/null +++ b/Barotrauma/BarotraumaShared/SharedSource/ContentManagement/ContentFile/TutorialsFile.cs @@ -0,0 +1,16 @@ +namespace Barotrauma +{ + [RequiredByCorePackage] + sealed class TutorialsFile : GenericPrefabFile + { + protected override PrefabCollection Prefabs => TutorialPrefab.Prefabs; + + public TutorialsFile(ContentPackage contentPackage, ContentPath path) : base(contentPackage, path) { } + + protected override bool MatchesSingular(Identifier identifier) => identifier == "Tutorial"; + + protected override bool MatchesPlural(Identifier identifier) => identifier == "Tutorials"; + + protected override TutorialPrefab CreatePrefab(ContentXElement element) => new TutorialPrefab(this, element); + } +} \ No newline at end of file diff --git a/Barotrauma/BarotraumaShared/SharedSource/DebugConsole.cs b/Barotrauma/BarotraumaShared/SharedSource/DebugConsole.cs index fc7e77728..ad6fcde98 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/DebugConsole.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/DebugConsole.cs @@ -965,16 +965,10 @@ namespace Barotrauma foreach (var talentTree in talentTrees) { - foreach (var subTree in talentTree.TalentSubTrees) + foreach (var talentId in talentTree.AllTalentIdentifiers) { - foreach (var option in subTree.TalentOptionStages) - { - foreach (var talent in option.Talents) - { - character.GiveTalent(talent); - NewMessage($"Unlocked talent \"{talent.DisplayName}\"."); - } - } + character.GiveTalent(talentId); + NewMessage($"Unlocked talent \"{talentId}\"."); } } }, @@ -1304,102 +1298,7 @@ namespace Barotrauma } } }, null, true)); - - commands.Add(new Command("upgradeitem", "upgradeitem [upgrade] [level] [items]: Adds an upgrade to the current targeted item.", args => - { - if (args.Length > 0) - { - int level; - if (args.Length > 1) - { - if (int.TryParse(args[1], out int result)) - { - level = result; - } - else - { - ThrowError($"\"{args[1]}\" is not a valid level."); - return; - } - - } - else - { - ThrowError("Parameter \"level\" is required."); - return; - } - var upgradePrefab = UpgradePrefab.Find(args[0].ToIdentifier()); - - if (upgradePrefab == null) - { - ThrowError($"Unknown upgrade: {args[0]}."); - return; - } - - List targetItems = new List(); - - if (upgradePrefab.IsWallUpgrade) - { - targetItems.AddRange(Submarine.MainSub.GetWalls(true).Cast()); - } - else - { - if (args.Length > 2) - { - targetItems.AddRange(Item.ItemList.Where(item => item.Submarine == Submarine.MainSub).Where(item => item.HasTag(args[2])).Cast()); - } - else - { - ThrowError("Argument \"tag\" is required."); - return; - } - } - - if (!targetItems.Any()) - { - ThrowError("No valid items found."); - return; - } - - foreach (MapEntity targetItem in targetItems) - { - Upgrade existingUpgrade = targetItem.GetUpgrade(args[0].ToIdentifier()); - - if (!(targetItem is ISerializableEntity sEntity)) { continue; } - - var upgrade = new Upgrade(sEntity, upgradePrefab, level); - if (targetItem.AddUpgrade(upgrade, true)) - { - if (existingUpgrade == null) - { - NewMessage($"Added {upgradePrefab.Identifier}:{level} to {sEntity.Name}.", Color.Green); - upgrade.ApplyUpgrade(); - } - else - { - NewMessage($"Set {sEntity.Name}'s {upgradePrefab.Identifier} upgrade to level {existingUpgrade.Level}.", Color.Cyan); - existingUpgrade.ApplyUpgrade(); - } - } - else - { - ThrowError($"{upgrade.Prefab.Identifier} cannot be applied to {sEntity.Name}"); - } - } - } - else - { - ThrowError("Parameter \"upgrade\" is required."); - } - }, () => - { - return new[] - { - UpgradePrefab.Prefabs.Select(c => c.Identifier).Distinct().Select(i => i.Value).ToArray() - }; - }, true)); - commands.Add(new Command("maxupgrades", "maxupgrades [category] [prefab]: Maxes out all upgrades or only specific one if given arguments.", args => { UpgradeManager upgradeManager = GameMain.GameSession?.Campaign?.UpgradeManager; @@ -2362,7 +2261,7 @@ namespace Barotrauma { NewMessage(msg, color.Value, isCommand: false, isError: false); } -#if DEBUG +#if DEBUG && CLIENT Console.WriteLine(msg); #endif } @@ -2547,7 +2446,7 @@ namespace Barotrauma #endif fileName += DateTime.Now.ToShortDateString() + "_" + DateTime.Now.ToShortTimeString(); - var invalidChars = Path.GetInvalidFileNameChars(); + var invalidChars = Path.GetInvalidFileNameCharsCrossPlatform(); foreach (char invalidChar in invalidChars) { fileName = fileName.Replace(invalidChar.ToString(), ""); diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/CheckAfflictionAction.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/CheckAfflictionAction.cs index 1aca440b3..953d6f31f 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/CheckAfflictionAction.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/CheckAfflictionAction.cs @@ -1,8 +1,6 @@ #nullable enable -using System; using System.Collections.Generic; using System.Linq; -using System.Xml.Linq; namespace Barotrauma { @@ -20,6 +18,9 @@ namespace Barotrauma [Serialize(true, IsPropertySaveable.Yes, "When set to false when TargetLimb is not specified prevent checking limb-specific afflictions")] public bool AllowLimbAfflictions { get; set; } + [Serialize(0.0f, IsPropertySaveable.Yes, "Minimum strength of the affliction")] + public float MinStrength { get; set; } + public CheckAfflictionAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element) { } protected override bool? DetermineSuccess() @@ -32,14 +33,15 @@ namespace Barotrauma if (target.CharacterHealth == null) { continue; } if (TargetLimb == LimbType.None) { - if (target.CharacterHealth.GetAffliction(Identifier, AllowLimbAfflictions) != null) { return true; } + var affliction = target.CharacterHealth.GetAffliction(Identifier, AllowLimbAfflictions); + if (affliction != null && affliction.Strength >= MinStrength) { return true; } } IEnumerable afflictions = target.CharacterHealth.GetAllAfflictions().Where(affliction => { LimbType? limbType = target.CharacterHealth.GetAfflictionLimb(affliction)?.type; if (limbType == null) { return false; } - return limbType == TargetLimb || true; + return limbType == TargetLimb && affliction.Strength >= MinStrength; }); if (afflictions.Any(a => a.Identifier == Identifier)) { return true; } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/CheckConditionalAction.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/CheckConditionalAction.cs new file mode 100644 index 000000000..cd9087d16 --- /dev/null +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/CheckConditionalAction.cs @@ -0,0 +1,71 @@ +using System.Xml.Linq; + +namespace Barotrauma +{ + class CheckConditionalAction : BinaryOptionAction + { + [Serialize("", IsPropertySaveable.Yes)] + public Identifier TargetTag { get; set; } + + private PropertyConditional Conditional { get; } + + public CheckConditionalAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element) + { + if (TargetTag.IsEmpty) + { + DebugConsole.ShowError($"CheckConditionalAction error: {GetEventName()} uses a CheckConditionalAction with no target tag! This will cause the check to automatically succeed."); + } + foreach (var attribute in element.Attributes()) + { + if (PropertyConditional.IsValid(attribute) && !IsTargetTagAttribute(attribute)) + { + Conditional = new PropertyConditional(attribute); + break; + } + } + if (Conditional == null) + { + DebugConsole.ShowError($"CheckConditionalAction error: {GetEventName()} uses a CheckConditionalAction with no valid PropertyConditional! This will cause the check to automatically succeed."); + } + + static bool IsTargetTagAttribute(XAttribute attribute) + { + return attribute.Name.ToString().Equals("targettag", System.StringComparison.OrdinalIgnoreCase); + } + } + + private string GetEventName() + { + return ParentEvent?.Prefab?.Identifier is { IsEmpty: false } identifier ? $"the event \"{identifier}\"" : "an unknown event"; + } + + protected override bool? DetermineSuccess() + { + ISerializableEntity target = null; + if (!TargetTag.IsEmpty) + { + foreach (var t in ParentEvent.GetTargets(TargetTag)) + { + if (t is ISerializableEntity e) + { + target = e; + break; + } + } + } + if (target == null) + { + DebugConsole.ShowError($"CheckConditionalAction error: {GetEventName()} uses a CheckConditionalAction but no valid target was found for tag \"{TargetTag}\"! This will cause the check to automatically succeed."); + } + if (target == null || Conditional == null) + { + return true; + } + if (target is Item item) + { + return item.ConditionalMatches(Conditional); + } + return Conditional.Matches(target); + } + } +} \ No newline at end of file diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/CheckOrderAction.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/CheckOrderAction.cs new file mode 100644 index 000000000..8413b6746 --- /dev/null +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/CheckOrderAction.cs @@ -0,0 +1,59 @@ +namespace Barotrauma +{ + class CheckOrderAction : BinaryOptionAction + { + [Serialize("", IsPropertySaveable.Yes)] + public Identifier TargetTag { get; set; } + + [Serialize("", IsPropertySaveable.Yes)] + public Identifier OrderIdentifier { get; set; } + + [Serialize("", IsPropertySaveable.Yes)] + public Identifier OrderOption { get; set; } + + public CheckOrderAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element) { } + + protected override bool? DetermineSuccess() + { + ISerializableEntity target = null; + if (!TargetTag.IsEmpty) + { + foreach (var t in ParentEvent.GetTargets(TargetTag)) + { + if (t is ISerializableEntity e) + { + target = e; + break; + } + } + } + if (target == null) + { + DebugConsole.ShowError($"CheckConditionalAction error: {GetEventName()} uses a CheckOrderAction but no valid target was found for tag \"{TargetTag}\"! This will cause the check to automatically succeed."); + return true; + } + if (target is Character character) + { + var currentOrderInfo = character.GetCurrentOrderWithTopPriority(); + if (currentOrderInfo?.Identifier == OrderIdentifier) + { + if (OrderOption.IsEmpty) + { + return true; + } + else + { + return currentOrderInfo?.Option == OrderOption; + } + } + return false; + } + return true; + } + + private string GetEventName() + { + return ParentEvent?.Prefab?.Identifier is { IsEmpty: false } identifier ? $"the event \"{identifier}\"" : "an unknown event"; + } + } +} \ No newline at end of file diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/MessageBoxAction.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/MessageBoxAction.cs new file mode 100644 index 000000000..1577c7514 --- /dev/null +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/MessageBoxAction.cs @@ -0,0 +1,116 @@ +using System; +using System.Linq; + +namespace Barotrauma +{ + class MessageBoxAction : EventAction + { + [Serialize("", IsPropertySaveable.Yes)] + public Identifier Header { get; set; } + + [Serialize("", IsPropertySaveable.Yes)] + public Identifier Text { get; set; } + + [Serialize("", IsPropertySaveable.Yes)] + public string IconStyle { get; set; } + + [Serialize(false, IsPropertySaveable.Yes)] + public bool HideCloseButton { get; set; } + + [Serialize("", IsPropertySaveable.Yes)] + public Identifier TargetTag { get; set; } + + [Serialize("", IsPropertySaveable.Yes)] + public string CloseOnInput { get; set; } + + [Serialize("", IsPropertySaveable.Yes)] + public Identifier CloseOnInteractTag { get; set; } + + [Serialize("", IsPropertySaveable.Yes)] + public Identifier CloseOnPickUpTag { get; set; } + + [Serialize("", IsPropertySaveable.Yes)] + public Identifier CloseOnEquipTag { get; set; } + + [Serialize("", IsPropertySaveable.Yes)] + public Identifier CloseOnExitRoomName { get; set; } + + [Serialize(false, IsPropertySaveable.Yes)] + public bool IsTutorialObjective { get; set; } + + private bool isFinished = false; + + public MessageBoxAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element) { } + + public override void Update(float deltaTime) + { + if (isFinished) { return; } +#if CLIENT + CreateMessageBox(); + if (IsTutorialObjective && GameMain.GameSession?.GameMode is TutorialMode tutorialMode) + { + tutorialMode.Tutorial?.TriggerTutorialSegment(new Tutorials.Tutorial.Segment(Text, CreateMessageBox)); + } +#endif + isFinished = true; + } + +#if CLIENT + public void CreateMessageBox() + { + new GUIMessageBox( + headerText: TextManager.Get(Header), + text: RichString.Rich(TextManager.ParseInputTypes(TextManager.Get(Text).Fallback(Text.ToString()), useColorHighlight: true)), + buttons: Array.Empty(), + type: GUIMessageBox.Type.Tutorial, + iconStyle: IconStyle, + autoCloseCondition: GetAutoCloseCondition(), + hideCloseButton: HideCloseButton); + } +#endif + + private Func GetAutoCloseCondition() + { + var character = ParentEvent.GetTargets(TargetTag).FirstOrDefault() as Character; + Func autoCloseCondition = null; + if (!string.IsNullOrEmpty(CloseOnInput) && Enum.TryParse(CloseOnInput, true, out InputType closeOnInput)) + { +#if CLIENT + autoCloseCondition = () => PlayerInput.KeyDown(closeOnInput); +#endif + } + else if (!CloseOnInteractTag.IsEmpty) + { + autoCloseCondition = () => character?.SelectedItem != null && character.SelectedItem.HasTag(CloseOnInteractTag); + } + else if (!CloseOnPickUpTag.IsEmpty) + { + autoCloseCondition = () => character?.Inventory != null && character.Inventory.FindItemByTag(CloseOnPickUpTag, recursive: true) != null; + } + else if (!CloseOnEquipTag.IsEmpty) + { + autoCloseCondition = () => character != null && character.HasEquippedItem(CloseOnEquipTag); + } + else if (!CloseOnExitRoomName.IsEmpty) + { + autoCloseCondition = () => character?.CurrentHull != null && character.CurrentHull.RoomName.ToIdentifier() != CloseOnExitRoomName; + } + return autoCloseCondition; + } + + public override bool IsFinished(ref string goToLabel) + { + return isFinished; + } + + public override void Reset() + { + isFinished = false; + } + + public override string ToDebugString() + { + return $"{ToolBox.GetDebugSymbol(isFinished)} {nameof(MessageBoxAction)}"; + } + } +} \ No newline at end of file diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/MissionAction.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/MissionAction.cs index d4d95ebbb..ff3d4d9bb 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/MissionAction.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/MissionAction.cs @@ -145,9 +145,9 @@ namespace Barotrauma foreach (Client client in GameMain.Server.ConnectedClients) { IWriteMessage outmsg = new WriteOnlyMessage(); - outmsg.Write((byte)ServerPacketHeader.EVENTACTION); - outmsg.Write((byte)EventManager.NetworkEventType.MISSION); - outmsg.Write(prefab.Identifier); + outmsg.WriteByte((byte)ServerPacketHeader.EVENTACTION); + outmsg.WriteByte((byte)EventManager.NetworkEventType.MISSION); + outmsg.WriteIdentifier(prefab.Identifier); GameMain.Server.ServerPeer.Send(outmsg, client.Connection, DeliveryMethod.Reliable); } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/SpawnAction.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/SpawnAction.cs index 5250521eb..3bd798efd 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/SpawnAction.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/SpawnAction.cs @@ -57,6 +57,9 @@ namespace Barotrauma private readonly HashSet targetModuleTags = new HashSet(); + [Serialize(true, IsPropertySaveable.Yes, description: "If false, we won't spawn another character if one with the same identifier has already been spawned.")] + public bool AllowDuplicates { get; set; } + [Serialize("", IsPropertySaveable.Yes, "What outpost module tags does the entity prefer to spawn in.")] public string TargetModuleTags { @@ -115,6 +118,12 @@ namespace Barotrauma HumanPrefab humanPrefab = NPCSet.Get(NPCSetIdentifier, NPCIdentifier); if (humanPrefab != null) { + if (!AllowDuplicates && + Character.CharacterList.Any(c => c.Info?.HumanPrefabIds.NpcIdentifier == NPCIdentifier && c.Info?.HumanPrefabIds.NpcSetIdentifier == NPCSetIdentifier)) + { + spawned = true; + return; + } ISpatialEntity spawnPos = GetSpawnPos(); if (spawnPos != null) { @@ -145,6 +154,11 @@ namespace Barotrauma } else if (!SpeciesName.IsEmpty) { + if (!AllowDuplicates && Character.CharacterList.Any(c => c.SpeciesName == SpeciesName)) + { + spawned = true; + return; + } ISpatialEntity spawnPos = GetSpawnPos(); if (spawnPos != null) { diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/TagAction.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/TagAction.cs index 377fa8eb0..208a7fbfa 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/TagAction.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/TagAction.cs @@ -1,10 +1,7 @@ using Barotrauma.Extensions; using System; -using System.Collections; -using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; -using System.Xml.Linq; namespace Barotrauma { @@ -36,6 +33,7 @@ namespace Barotrauma ("crew", v => TagCrew()), ("humanprefabidentifier", TagHumansByIdentifier), ("structureidentifier", TagStructuresByIdentifier), + ("structurespecialtag", TagStructuresBySpecialTag), ("itemidentifier", TagItemsByIdentifier), ("itemtag", TagItemsByTag), ("hullname", TagHullsByName) @@ -100,6 +98,11 @@ namespace Barotrauma ParentEvent.AddTargetPredicate(Tag, e => e is Structure s && SubmarineTypeMatches(s.Submarine) && s.Prefab.Identifier == identifier); } + private void TagStructuresBySpecialTag(Identifier tag) + { + ParentEvent.AddTargetPredicate(Tag, e => e is Structure s && SubmarineTypeMatches(s.Submarine) && s.SpecialTag.ToIdentifier() == tag); + } + private void TagItemsByIdentifier(Identifier identifier) { ParentEvent.AddTargetPredicate(Tag, e => e is Item it && SubmarineTypeMatches(it.Submarine) && it.Prefab.Identifier == identifier); diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/TutorialCompleteAction.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/TutorialCompleteAction.cs new file mode 100644 index 000000000..9544f9371 --- /dev/null +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/TutorialCompleteAction.cs @@ -0,0 +1,32 @@ +namespace Barotrauma +{ + class TutorialCompleteAction : EventAction + { + private bool isFinished; + + public TutorialCompleteAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element) { } + + public override void Update(float deltaTime) + { + if (isFinished) { return; } + +#if CLIENT + if (GameMain.GameSession?.GameMode is TutorialMode tutorialMode) + { + tutorialMode.Tutorial?.Complete(); + } +#endif + isFinished = true; + } + + public override bool IsFinished(ref string goToLabel) + { + return isFinished; + } + + public override void Reset() + { + isFinished = false; + } + } +} \ No newline at end of file diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/TutorialSegmentAction.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/TutorialSegmentAction.cs new file mode 100644 index 000000000..a7e6a7658 --- /dev/null +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/TutorialSegmentAction.cs @@ -0,0 +1,95 @@ +#if CLIENT +using Barotrauma.Tutorials; +#endif + +namespace Barotrauma +{ + class TutorialSegmentAction : EventAction + { + public enum SegmentActionType { Trigger, Complete, Remove }; + + [Serialize(SegmentActionType.Trigger, IsPropertySaveable.Yes)] + public SegmentActionType Type { get; set; } + + [Serialize("", IsPropertySaveable.Yes)] + public Identifier Id { get; set; } + + [Serialize("", IsPropertySaveable.Yes)] + public Identifier ObjectiveTextTag { get; set; } + + [Serialize(false, IsPropertySaveable.Yes)] + public bool AutoPlayVideo { get; set; } + + [Serialize("", IsPropertySaveable.Yes)] + public Identifier TextTag { get; set; } + + [Serialize("", IsPropertySaveable.Yes)] + public string VideoFile { get; set; } + + [Serialize(450, IsPropertySaveable.Yes)] + public int Width { get; set; } + + [Serialize(80, IsPropertySaveable.Yes)] + public int Height { get; set; } + +#if CLIENT + private readonly Tutorial.Segment segment; +#endif + private bool isFinished; + + public TutorialSegmentAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element) + { +#if CLIENT + // Only need to create the segment when it's being triggered (otherwise the tutorial already has the segment instance) + if (Type == SegmentActionType.Trigger) + { + segment = new Tutorial.Segment(Id, ObjectiveTextTag, AutoPlayVideo ? Tutorials.AutoPlayVideo.Yes : Tutorials.AutoPlayVideo.No, + new Tutorial.Segment.Text(TextTag, Width, Height, Anchor.Center), + new Tutorial.Segment.Video(VideoFile, TextTag, Width, Height)); + } +#endif + } + + public override void Update(float deltaTime) + { + if (isFinished) { return; } + +#if CLIENT + if (GameMain.GameSession?.GameMode is TutorialMode tutorialMode) + { + if (tutorialMode.Tutorial is Tutorial tutorial) + { + switch (Type) + { + case SegmentActionType.Trigger: + tutorial.TriggerTutorialSegment(segment); + break; + case SegmentActionType.Complete: + tutorial.CompleteTutorialSegment(Id); + break; + case SegmentActionType.Remove: + tutorial.RemoveTutorialSegment(Id); + break; + } + } + } + else + { + DebugConsole.ShowError($"Error in event \"{ParentEvent.Prefab.Identifier}\": attempting to use TutorialSegmentAction during a non-Tutorial game mode!"); + } +#endif + + isFinished = true; + } + + public override bool IsFinished(ref string goToLabel) + { + return isFinished; + } + + public override void Reset() + { + isFinished = false; + } + } +} \ No newline at end of file diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/UnlockPathAction.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/UnlockPathAction.cs index ac2b2fe9f..a69ee509a 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/UnlockPathAction.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/UnlockPathAction.cs @@ -55,9 +55,9 @@ namespace Barotrauma foreach (Client client in GameMain.Server.ConnectedClients) { IWriteMessage outmsg = new WriteOnlyMessage(); - outmsg.Write((byte)ServerPacketHeader.EVENTACTION); - outmsg.Write((byte)EventManager.NetworkEventType.UNLOCKPATH); - outmsg.Write((UInt16)GameMain.GameSession.Map.Connections.IndexOf(connection)); + outmsg.WriteByte((byte)ServerPacketHeader.EVENTACTION); + outmsg.WriteByte((byte)EventManager.NetworkEventType.UNLOCKPATH); + outmsg.WriteUInt16((UInt16)GameMain.GameSession.Map.Connections.IndexOf(connection)); GameMain.Server.ServerPeer.Send(outmsg, client.Connection, DeliveryMethod.Reliable); } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/CombatMission.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/CombatMission.cs index 9e2e4c921..4812d5085 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/CombatMission.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/CombatMission.cs @@ -109,6 +109,7 @@ namespace Barotrauma subs[1].FlipX(); #if SERVER crews = new List[] { new List(), new List() }; + roundEndTimer = RoundEndDuration; #endif } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/MineralMission.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/MineralMission.cs index c4a787a40..d0a99fe80 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/MineralMission.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/MineralMission.cs @@ -3,7 +3,9 @@ using Barotrauma.Items.Components; using Microsoft.Xna.Framework; using System; using System.Collections.Generic; +using System.Collections.Immutable; using System.Linq; +using PositionType = Barotrauma.Level.PositionType; namespace Barotrauma { @@ -29,6 +31,25 @@ namespace Barotrauma private readonly HashSet caves = new HashSet(); + private readonly PositionType positionType = PositionType.Cave; + /// + /// The list order is important. + /// It defines the order in which we "override" in case no valid position types are found + /// in the level when generating them in . + /// + public static readonly ImmutableArray ValidPositionTypes = new PositionType[] + { + PositionType.Cave, + PositionType.SidePath, + PositionType.MainPath, + PositionType.AbyssCave, + }.ToImmutableArray(); + + /// + /// Percentage. Value between 0 and 1. + /// + private readonly float resourceHandoverAmount; + public override IEnumerable SonarPositions { get @@ -39,8 +60,23 @@ namespace Barotrauma } } + public override LocalizedString SuccessMessage => ModifyMessage(base.SuccessMessage); + public override LocalizedString FailureMessage => ModifyMessage(base.FailureMessage); + public override LocalizedString Description => ModifyMessage(description); + public override LocalizedString Name => ModifyMessage(base.Name, false); + public override LocalizedString SonarLabel => ModifyMessage(base.SonarLabel, false); + public MineralMission(MissionPrefab prefab, Location[] locations, Submarine sub) : base(prefab, locations, sub) { + var positionType = prefab.ConfigElement.GetAttributeEnum("PositionType", in this.positionType); + if (ValidPositionTypes.Contains(positionType)) + { + this.positionType = positionType; + } + + float handoverAmount = prefab.ConfigElement.GetAttributeFloat("ResourceHandoverAmount", 0.0f); + resourceHandoverAmount = Math.Clamp(handoverAmount, 0.0f, 1.0f); + var configElement = prefab.ConfigElement.GetChildElement("Items"); foreach (var c in configElement.GetChildElements("Item")) { @@ -92,27 +128,28 @@ namespace Barotrauma caves.Clear(); if (IsClient) { return; } - foreach (var kvp in resourceClusters) + + foreach ((Identifier identifier, ResourceCluster cluster) in resourceClusters) { - var prefab = ItemPrefab.Find(null, kvp.Key); - if (prefab == null) + if (!(MapEntityPrefab.FindByIdentifier(identifier) is ItemPrefab prefab)) { - DebugConsole.ThrowError("Error in MineralMission - " + - "couldn't find an item prefab with the identifier " + kvp.Key); + DebugConsole.ThrowError($"Error in MineralMission: couldn't find an item prefab (identifier: \"{identifier}\")"); continue; } - var spawnedResources = level.GenerateMissionResources(prefab, kvp.Value.Amount, out float rotation); - if (spawnedResources.Count < kvp.Value.Amount) - { - DebugConsole.ThrowError("Error in MineralMission - " + - "spawned " + spawnedResources.Count + "/" + kvp.Value.Amount + " of " + prefab.Name); - } - if (spawnedResources.None()) { continue; } - this.spawnedResources.Add(kvp.Key, spawnedResources); - foreach (Level.Cave cave in Level.Loaded.Caves) + var spawnedResources = level.GenerateMissionResources(prefab, cluster.Amount, positionType, out float rotation); + if (spawnedResources.Count < cluster.Amount) { - foreach (Item spawnedResource in spawnedResources) + DebugConsole.ThrowError($"Error in MineralMission: spawned only {spawnedResources.Count}/{cluster.Amount} of {prefab.Name}"); + } + + if (spawnedResources.None()) { continue; } + + this.spawnedResources.Add(identifier, spawnedResources); + + foreach (var cave in Level.Loaded.Caves) + { + foreach (var spawnedResource in spawnedResources) { if (cave.Area.Contains(spawnedResource.WorldPosition)) { @@ -123,6 +160,7 @@ namespace Barotrauma } } } + CalculateMissionClusterPositions(); FindRelevantLevelResources(); } @@ -151,6 +189,28 @@ namespace Barotrauma { ChangeLocationType(Prefab.LocationTypeChangeOnCompleted); } + if (!IsClient) + { + // When mission is completed successfully, half of the resources will be removed from the player (i.e. given to the outpost as a part of the mission) + var handoverResources = new List(); + foreach (Identifier identifier in resourceClusters.Keys) + { + if (relevantLevelResources.TryGetValue(identifier, out var availableResources)) + { + var collectedResources = availableResources.Where(HasBeenCollected); + if (collectedResources.Count() < 1) { continue; } + int handoverCount = (int)MathF.Round(resourceHandoverAmount * collectedResources.Count()); + for (int i = 0; i < handoverCount; i++) + { + handoverResources.Add(collectedResources.ElementAt(i)); + } + } + } + foreach (var resource in handoverResources) + { + resource.Remove(); + } + } GiveReward(); completed = true; } @@ -237,5 +297,27 @@ namespace Barotrauma missionClusterPositions.Add((kvp.Key, pos)); } } + + protected override LocalizedString ModifyMessage(LocalizedString message, bool color = true) + { + int i = 1; + foreach ((Identifier identifier, ResourceCluster cluster) in resourceClusters) + { + Replace($"[resourcename{i}]", ItemPrefab.FindByIdentifier(identifier)?.Name.Value ?? ""); + Replace($"[resourcequantity{i}]", cluster.Amount.ToString()); + i++; + } + Replace("[handoverpercentage]", ToolBox.GetFormattedPercentage(resourceHandoverAmount)); + return message; + + void Replace(string find, string replace) + { + if (color) + { + replace = $"‖color:gui.orange‖{replace}‖end‖"; + } + message = message.Replace(find, replace); + } + } } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/Mission.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/Mission.cs index e26735cc3..497992319 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/Mission.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/Mission.cs @@ -41,7 +41,7 @@ namespace Barotrauma public readonly ImmutableArray Headers; public readonly ImmutableArray Messages; - public LocalizedString Name => Prefab.Name; + public virtual LocalizedString Name => Prefab.Name; private readonly LocalizedString successMessage; public virtual LocalizedString SuccessMessage @@ -276,6 +276,10 @@ namespace Barotrauma partial void ShowMessageProjSpecific(int missionState); + protected virtual LocalizedString ModifyMessage(LocalizedString message, bool color = true) + { + return message; + } private void TryTriggerEvents(int state) { diff --git a/Barotrauma/BarotraumaShared/SharedSource/GameSession/CrewManager.cs b/Barotrauma/BarotraumaShared/SharedSource/GameSession/CrewManager.cs index 421af50e0..8671f08d3 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/GameSession/CrewManager.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/GameSession/CrewManager.cs @@ -1,4 +1,7 @@ using Barotrauma.Extensions; +#if CLIENT +using Barotrauma.Tutorials; +#endif using Microsoft.Xna.Framework; using System; using System.Collections.Generic; @@ -348,6 +351,9 @@ namespace Barotrauma private void UpdateConversations(float deltaTime) { if (GameMain.GameSession?.GameMode?.Preset == GameModePreset.TestMode) { return; } +#if CLIENT + if (GameMain.GameSession?.GameMode is TutorialMode tutorialMode && tutorialMode.Tutorial is Tutorial tutorial && tutorial.TutorialPrefab.DisableBotConversations) { return; } +#endif if (GameMain.NetworkMember != null && GameMain.NetworkMember.ServerSettings.DisableBotConversations) { return; } conversationTimer -= deltaTime; diff --git a/Barotrauma/BarotraumaShared/SharedSource/GameSession/GameModes/MultiPlayerCampaign.cs b/Barotrauma/BarotraumaShared/SharedSource/GameSession/GameModes/MultiPlayerCampaign.cs index 32fbcd28a..9e1e19aa6 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/GameSession/GameModes/MultiPlayerCampaign.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/GameSession/GameModes/MultiPlayerCampaign.cs @@ -10,8 +10,6 @@ namespace Barotrauma { partial class MultiPlayerCampaign : CampaignMode { - public const int MinimumInitialMoney = 500; - [Flags] public enum NetFlags : UInt16 { @@ -294,14 +292,14 @@ namespace Barotrauma private static void WriteItems(IWriteMessage msg, Dictionary> purchasedItems) { - msg.Write((byte)purchasedItems.Count); + msg.WriteByte((byte)purchasedItems.Count); foreach (var storeItems in purchasedItems) { - msg.Write(storeItems.Key); - msg.Write((UInt16)storeItems.Value.Count); + msg.WriteIdentifier(storeItems.Key); + msg.WriteUInt16((UInt16)storeItems.Value.Count); foreach (var item in storeItems.Value) { - msg.Write(item.ItemPrefabIdentifier); + msg.WriteIdentifier(item.ItemPrefabIdentifier); msg.WriteRangedInteger(item.Quantity, 0, CargoManager.MaxQuantity); } } @@ -328,18 +326,18 @@ namespace Barotrauma private static void WriteItems(IWriteMessage msg, Dictionary> soldItems) { - msg.Write((byte)soldItems.Count); + msg.WriteByte((byte)soldItems.Count); foreach (var storeItems in soldItems) { - msg.Write(storeItems.Key); - msg.Write((UInt16)storeItems.Value.Count); + msg.WriteIdentifier(storeItems.Key); + msg.WriteUInt16((UInt16)storeItems.Value.Count); foreach (var item in storeItems.Value) { - msg.Write(item.ItemPrefab.Identifier); - msg.Write((UInt16)item.ID); - msg.Write(item.Removed); - msg.Write(item.SellerID); - msg.Write((byte)item.Origin); + msg.WriteIdentifier(item.ItemPrefab.Identifier); + msg.WriteUInt16((UInt16)item.ID); + msg.WriteBoolean(item.Removed); + msg.WriteByte(item.SellerID); + msg.WriteByte((byte)item.Origin); } } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/GameSession/GameModes/PvPMode.cs b/Barotrauma/BarotraumaShared/SharedSource/GameSession/GameModes/PvPMode.cs index 1ac387dee..4599c3857 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/GameSession/GameModes/PvPMode.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/GameSession/GameModes/PvPMode.cs @@ -1,5 +1,7 @@ +using Barotrauma.Extensions; using Barotrauma.Networking; using System.Collections.Generic; +using System.Linq; namespace Barotrauma { @@ -11,37 +13,37 @@ namespace Barotrauma public void AssignTeamIDs(IEnumerable clients) { - int teamWeight = 0; - List randList = new List(clients); - for (int i = 0; i < randList.Count; i++) + int team1Count = 0, team2Count = 0; + //if a client has a preference, assign them to that team + List unassignedClients = new List(clients); + for (int i = 0; i < unassignedClients.Count; i++) { - if (randList[i].PreferredTeam == CharacterTeamType.Team1 || - randList[i].PreferredTeam == CharacterTeamType.Team2) + if (unassignedClients[i].PreferredTeam == CharacterTeamType.Team1 || + unassignedClients[i].PreferredTeam == CharacterTeamType.Team2) { - randList[i].TeamID = randList[i].PreferredTeam; - teamWeight += randList[i].PreferredTeam == CharacterTeamType.Team1 ? -1 : 1; - randList.RemoveAt(i); + assignTeam(unassignedClients[i], unassignedClients[i].PreferredTeam); i--; } } - for (int i = 0; i Prefabs = new PrefabCollection(); + + public readonly int Order; + public readonly bool DisableBotConversations; + public readonly bool AllowCharacterSwitch; + + public readonly ContentPath SubmarinePath = ContentPath.FromRaw("Content/Tutorials/Dugong_Tutorial.sub"); + public readonly ContentPath OutpostPath = ContentPath.FromRaw("Content/Tutorials/TutorialOutpost.sub"); + public readonly string LevelSeed; + public readonly string LevelParams; + + private readonly ContentXElement tutorialCharacterElement; + public readonly ImmutableArray StartingItemTags; + + public readonly Identifier EventIdentifier; + + public TutorialPrefab(ContentFile file, ContentXElement element) : base(file, element.GetAttributeIdentifier("identifier", "")) + { + Order = element.GetAttributeInt("order", int.MaxValue); + DisableBotConversations = element.GetAttributeBool("disablebotconversations", true); + AllowCharacterSwitch = element.GetAttributeBool("allowcharacterswitch", false); + + SubmarinePath = element.GetAttributeContentPath("submarinepath") ?? SubmarinePath; + OutpostPath = element.GetAttributeContentPath("outpostpath") ?? OutpostPath; + LevelSeed = element.GetAttributeString("levelseed", "nLoZLLtza"); + LevelParams = element.GetAttributeString("levelparams", "ColdCavernsTutorial"); + + tutorialCharacterElement = element.GetChildElement("characterinfo"); + if (tutorialCharacterElement != null) + { + StartingItemTags = tutorialCharacterElement + .GetAttributeIdentifierArray("startingitemtags", new Identifier[0]) + .ToImmutableArray(); + } + else + { + StartingItemTags = ImmutableArray.Empty; + } + + EventIdentifier = element.GetChildElement("scriptedevent")?.GetAttributeIdentifier("identifier", "") ?? Identifier.Empty; + } + + public CharacterInfo GetTutorialCharacterInfo() + { + if (tutorialCharacterElement == null) + { + return null; + } + Identifier speciesName = tutorialCharacterElement.GetAttributeIdentifier("speciesname", CharacterPrefab.HumanSpeciesName); + string jobPrefabIdentifier = tutorialCharacterElement.GetAttributeString("jobidentifier", "assistant"); + var jobPrefab = JobPrefab.Prefabs.FirstOrDefault(p => p.Identifier == jobPrefabIdentifier) ?? JobPrefab.Prefabs.First(); + int jobVariant = tutorialCharacterElement.GetAttributeInt("variant", 0); + var characterInfo = new CharacterInfo(speciesName, jobOrJobPrefab: jobPrefab, variant: jobVariant); + foreach (var skillElement in tutorialCharacterElement.GetChildElements("skill")) + { + Identifier skillIdentifier = skillElement.GetAttributeIdentifier("identifier", ""); + if (skillIdentifier.IsEmpty) { continue; } + float level = skillElement.GetAttributeFloat("level", 0.0f); + characterInfo.SetSkillLevel(skillIdentifier, level); + } + return characterInfo; + } + + public override void Dispose() { } + } +} diff --git a/Barotrauma/BarotraumaShared/SharedSource/GameSession/GameSession.cs b/Barotrauma/BarotraumaShared/SharedSource/GameSession/GameSession.cs index bb0dfda53..1b56b6f5c 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/GameSession/GameSession.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/GameSession/GameSession.cs @@ -211,7 +211,7 @@ namespace Barotrauma if (selectedSub != null) { campaign.Bank.Deduct(selectedSub.Price); - campaign.Bank.Balance = Math.Max(campaign.Bank.Balance, MultiPlayerCampaign.MinimumInitialMoney); + campaign.Bank.Balance = Math.Max(campaign.Bank.Balance, 0); } return campaign; } @@ -222,7 +222,7 @@ namespace Barotrauma if (selectedSub != null) { campaign.Bank.TryDeduct(selectedSub.Price); - campaign.Bank.Balance = Math.Max(campaign.Bank.Balance, MultiPlayerCampaign.MinimumInitialMoney); + campaign.Bank.Balance = Math.Max(campaign.Bank.Balance, 0); } return campaign; } @@ -602,7 +602,7 @@ namespace Barotrauma if (GameMode is MultiPlayerCampaign mpCampaign) { mpCampaign.UpgradeManager.ApplyUpgrades(); - mpCampaign.UpgradeManager.SanityCheckUpgrades(Submarine); + mpCampaign.UpgradeManager.SanityCheckUpgrades(); } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/GameSession/UpgradeManager.cs b/Barotrauma/BarotraumaShared/SharedSource/GameSession/UpgradeManager.cs index 59e15246d..37d8c9369 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/GameSession/UpgradeManager.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/GameSession/UpgradeManager.cs @@ -512,8 +512,11 @@ namespace Barotrauma /// Should be called after every round start right after ///
/// - public void SanityCheckUpgrades(Submarine submarine) + public void SanityCheckUpgrades() { + Submarine submarine = GameMain.GameSession?.Submarine ?? Submarine.MainSub; + if (submarine is null) { return; } + // check walls foreach (Structure wall in submarine.GetWalls(UpgradeAlsoConnectedSubs)) { @@ -521,23 +524,8 @@ namespace Barotrauma { foreach (UpgradePrefab prefab in UpgradePrefab.Prefabs) { - int level = GetRealUpgradeLevel(prefab, category); - if (level == 0 || !prefab.IsWallUpgrade) { continue; } - - Upgrade? upgrade = wall.GetUpgrade(prefab.Identifier); - - bool isOverMax = IsOverMaxLevel(level, prefab); - if (isOverMax) - { - SetUpgradeLevel(prefab, category, prefab.MaxLevel); - level = prefab.MaxLevel; - } - - if (upgrade == null || upgrade.Level != level || isOverMax) - { - DebugLog($"{((MapEntity)wall).Prefab.Name} has incorrect \"{prefab.Name}\" level! Expected {level} but got {upgrade?.Level ?? 0}. Fixing..."); - FixUpgradeOnItem(wall, prefab, level); - } + if (!prefab.IsWallUpgrade) { continue; } + TryFixUpgrade(wall, category, prefab); } } } @@ -549,35 +537,38 @@ namespace Barotrauma { foreach (UpgradePrefab prefab in UpgradePrefab.Prefabs) { - if (!category.CanBeApplied(item, prefab)) { continue; } - - int level = GetRealUpgradeLevel(prefab, category); - if (level == 0) { continue; } - - Upgrade? upgrade = item.GetUpgrade(prefab.Identifier); - bool isOverMax = IsOverMaxLevel(level, prefab); - if (isOverMax) - { - SetUpgradeLevel(prefab, category, prefab.MaxLevel); - level = prefab.MaxLevel; - } - - if (upgrade == null || upgrade.Level != level || isOverMax) - { - DebugLog($"{((MapEntity)item).Prefab.Name} has incorrect \"{prefab.Name}\" level! Expected {level} but got {upgrade?.Level ?? 0}{(isOverMax ? " (Over max level!)" : string.Empty)}. Fixing..."); - FixUpgradeOnItem(item, prefab, level); - } + TryFixUpgrade(item, category, prefab); } } } - static bool IsOverMaxLevel(int level, UpgradePrefab prefab) => level > prefab.MaxLevel; + void TryFixUpgrade(MapEntity entity, UpgradeCategory category, UpgradePrefab prefab) + { + if (!category.CanBeApplied(entity, prefab)) { return; } + + int level = GetRealUpgradeLevel(prefab, category); + int maxLevel = submarine.Info is { } info ? prefab.GetMaxLevel(info) : prefab.MaxLevel; + if (maxLevel < level) { level = maxLevel; } + + if (level == 0) { return; } + + Upgrade? upgrade = entity.GetUpgrade(prefab.Identifier); + + if (upgrade == null || upgrade.Level != level) + { + DebugLog($"{entity.Prefab.Name} has incorrect \"{prefab.Name}\" level! Expected {level} but got {upgrade?.Level ?? 0}. Fixing..."); + FixUpgradeOnItem((ISerializableEntity)entity, prefab, level); + } + } } private static void FixUpgradeOnItem(ISerializableEntity target, UpgradePrefab prefab, int level) { if (target is MapEntity mapEntity) { + // do not fix what's not broken + if (level == 0) { return; } + mapEntity.SetUpgrade(new Upgrade(target, prefab, level), false); } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/InputType.cs b/Barotrauma/BarotraumaShared/SharedSource/InputType.cs index 04c8c9239..911fc6a4e 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/InputType.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/InputType.cs @@ -23,5 +23,6 @@ namespace Barotrauma PreviousFireMode, ActiveChat, ToggleChatMode, + ChatBox } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/DockingPort.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/DockingPort.cs index 405b6a22a..4952f01f9 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/DockingPort.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/DockingPort.cs @@ -1191,7 +1191,7 @@ namespace Barotrauma.Items.Components //trying to dock/undock from an outpost and the signal was sent by some automated system instead of a character // -> ask if the player really wants to dock/undock to prevent a softlock if someone's wired the docking port // in a way that makes always makes it dock/undock immediately at the start of the roun - if (tryingToToggleOutpostDocking && signal.sender == null) + if (GameMain.NetworkMember != null && tryingToToggleOutpostDocking && signal.sender == null) { if (allowOutpostAutoDocking == AllowOutpostAutoDocking.Ask) { diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Growable.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Growable.cs index bff4ee42c..ccb9ba004 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Growable.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Growable.cs @@ -132,8 +132,8 @@ namespace Barotrauma.Items.Components public static FoliageConfig CreateRandomConfig(int maxVariants, float minScale, float maxScale, Random? random = null) { int flowerVariant = Growable.RandomInt(0, maxVariants, random); - float flowerScale = (float) Growable.RandomDouble(minScale, maxScale, random); - float flowerRotation = (float) Growable.RandomDouble(0, MathHelper.TwoPi, random); + float flowerScale = (float)Growable.RandomDouble(minScale, maxScale, random); + float flowerRotation = (float)Growable.RandomDouble(0, MathHelper.TwoPi, random); return new FoliageConfig { Variant = flowerVariant, Scale = flowerScale, Rotation = flowerRotation }; } } @@ -169,10 +169,10 @@ namespace Barotrauma.Items.Components { const float limit = 1.0f; growthStep = value; - VineStep = Math.Min((float) Math.Pow(value, 2), limit); + VineStep = Math.Min((float)Math.Pow(value, 2), limit); if (value > limit) { - FlowerStep = Math.Min((float) Math.Pow(value - limit, 2), limit); + FlowerStep = Math.Min((float)Math.Pow(value - limit, 2), limit); } } } @@ -260,7 +260,7 @@ namespace Barotrauma.Items.Components { if (Type == VineTileType.Stem) { return; } - Type = (VineTileType) Sides; + Type = (VineTileType)Sides; } /// @@ -310,7 +310,7 @@ namespace Barotrauma.Items.Components public bool IsSideBlocked(TileSide side) => BlockedSides.HasFlag(side) || Sides.HasFlag(side); - public static Rectangle CreatePlantRect(Vector2 pos) => new Rectangle((int) pos.X - Size / 2, (int) pos.Y + Size / 2, Size, Size); + public static Rectangle CreatePlantRect(Vector2 pos) => new Rectangle((int)pos.X - Size / 2, (int)pos.Y + Size / 2, Size, Size); } internal static class GrowthSideExtension @@ -318,7 +318,7 @@ namespace Barotrauma.Items.Components // K&R algorithm for counting how many bits are set in a bit field public static int Count(this TileSide side) { - int n = (int) side; + int n = (int)side; int count = 0; while (n != 0) { @@ -607,7 +607,7 @@ namespace Barotrauma.Items.Components #if CLIENT foreach (VineTile vine in Vines) { - vine.DecayDelay = (float) RandomDouble(0f, 30f); + vine.DecayDelay = (float)RandomDouble(0f, 30f); } #endif #if SERVER @@ -742,7 +742,7 @@ namespace Barotrauma.Items.Components { var (x, y, z, w) = GrowthWeights; float[] weights = { x, y, z, w }; - int index = (int) Math.Log2((int) side); + int index = (int)Math.Log2((int)side); if (MathUtils.NearlyEqual(weights[index], 0f)) { oldVines.FailedGrowthAttempts++; @@ -778,7 +778,7 @@ namespace Barotrauma.Items.Components foreach (VineTile otherVine in Vines) { var (distX, distY) = pos - otherVine.Position; - int absDistX = (int) Math.Abs(distX), absDistY = (int) Math.Abs(distY); + int absDistX = (int)Math.Abs(distX), absDistY = (int)Math.Abs(distY); // check if the tile is within the with or height distance from us but ignore diagonals if (absDistX > newVine.Rect.Width || absDistY > newVine.Rect.Height || absDistX > 0 && absDistY > 0) { continue; } @@ -872,10 +872,10 @@ namespace Barotrauma.Items.Components foreach (VineTile vine in Vines) { XElement vineElement = new XElement("Vine"); - vineElement.Add(new XAttribute("sides", (int) vine.Sides)); - vineElement.Add(new XAttribute("blockedsides", (int) vine.BlockedSides)); + vineElement.Add(new XAttribute("sides", (int)vine.Sides)); + vineElement.Add(new XAttribute("blockedsides", (int)vine.BlockedSides)); vineElement.Add(new XAttribute("pos", XMLExtensions.Vector2ToString(vine.Position))); - vineElement.Add(new XAttribute("tile", (int) vine.Type)); + vineElement.Add(new XAttribute("tile", (int)vine.Type)); vineElement.Add(new XAttribute("failedattempts", vine.FailedGrowthAttempts)); #if SERVER vineElement.Add(new XAttribute("growthscale", Decayed ? 1.0f : 2.0f)); @@ -902,10 +902,10 @@ namespace Barotrauma.Items.Components { if (element.Name.ToString().Equals("vine", StringComparison.OrdinalIgnoreCase)) { - VineTileType type = (VineTileType) element.GetAttributeInt("tile", 0); + VineTileType type = (VineTileType)element.GetAttributeInt("tile", 0); Vector2 pos = element.GetAttributeVector2("pos", Vector2.Zero); - TileSide sides = (TileSide) element.GetAttributeInt("sides", 0); - TileSide blockedSides = (TileSide) element.GetAttributeInt("blockedsides", 0); + TileSide sides = (TileSide)element.GetAttributeInt("sides", 0); + TileSide blockedSides = (TileSide)element.GetAttributeInt("blockedsides", 0); int failedAttempts = element.GetAttributeInt("failedattempts", 0); float growthscale = element.GetAttributeFloat("growthscale", 0f); int flowerConfig = element.GetAttributeInt("flowerconfig", FoliageConfig.EmptyConfigValue); diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Holdable/MeleeWeapon.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Holdable/MeleeWeapon.cs index 74ef0f776..da4e9b663 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Holdable/MeleeWeapon.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Holdable/MeleeWeapon.cs @@ -4,6 +4,7 @@ using FarseerPhysics.Dynamics.Contacts; using Microsoft.Xna.Framework; using System; using System.Collections.Generic; +using System.Collections.Immutable; using System.Linq; namespace Barotrauma.Items.Components @@ -62,7 +63,7 @@ namespace Barotrauma.Items.Components /// /// Defines items that boost the weapon functionality, like battery cell for stun batons. /// - public readonly Identifier[] PreferredContainedItems; + public readonly ImmutableHashSet PreferredContainedItems; public MeleeWeapon(Item item, ContentXElement element) : base(item, element) @@ -77,7 +78,7 @@ namespace Barotrauma.Items.Components } item.IsShootable = true; item.RequireAimToUse = element.Parent.GetAttributeBool("requireaimtouse", true); - PreferredContainedItems = element.GetAttributeIdentifierArray("preferredcontaineditems", Array.Empty()); + PreferredContainedItems = element.GetAttributeIdentifierArray("preferredcontaineditems", Array.Empty()).ToImmutableHashSet(); } public override void Equip(Character character) @@ -387,14 +388,16 @@ namespace Barotrauma.Items.Components User = null; return; } - + + float damageMultiplier = 1 + User.GetStatValue(StatTypes.MeleeAttackMultiplier); + damageMultiplier *= 1.0f + item.GetQualityModifier(Quality.StatType.StrikingPowerMultiplier); + Limb targetLimb = target.UserData as Limb; Character targetCharacter = targetLimb?.character ?? target.UserData as Character; if (Attack != null) { Attack.SetUser(User); - Attack.DamageMultiplier = 1 + User.GetStatValue(StatTypes.MeleeAttackMultiplier); - Attack.DamageMultiplier *= 1.0f + item.GetQualityModifier(Quality.StatType.StrikingPowerMultiplier); + Attack.DamageMultiplier = damageMultiplier; if (targetLimb != null) { @@ -467,7 +470,7 @@ namespace Barotrauma.Items.Components if (targetCharacter != null) //TODO: Allow OnUse to happen on structures too maybe?? { - ApplyStatusEffects(success ? ActionType.OnUse : ActionType.OnFailure, 1.0f, targetCharacter, targetLimb, user: User); + ApplyStatusEffects(success ? ActionType.OnUse : ActionType.OnFailure, 1.0f, targetCharacter, targetLimb, user: User, afflictionMultiplier: damageMultiplier); } if (DeleteOnUse) diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Holdable/Pickable.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Holdable/Pickable.cs index 89b3f95f7..95c40bb0f 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Holdable/Pickable.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Holdable/Pickable.cs @@ -287,7 +287,7 @@ namespace Barotrauma.Items.Components public virtual void ServerEventWrite(IWriteMessage msg, Client c, NetEntityEvent.IData extraData = null) { - msg.Write(activePicker?.ID ?? (ushort)0); + msg.WriteUInt16(activePicker?.ID ?? (ushort)0); } public virtual void ClientEventRead(IReadMessage msg, float sendingTime) diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/ItemComponent.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/ItemComponent.cs index a95f15214..af53b043f 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/ItemComponent.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/ItemComponent.cs @@ -229,8 +229,6 @@ namespace Barotrauma.Items.Components set; } - public virtual bool RecreateGUIOnResolutionChange => false; - /// /// How useful the item is in combat? Used by AI to decide which item it should use as a weapon. For the sake of clarity, use a value between 0 and 100 (not enforced). /// @@ -397,7 +395,7 @@ namespace Barotrauma.Items.Components RelatedItem ri = RelatedItem.Load(element, returnEmpty, item.Name); if (ri != null) { - if (ri.Identifiers.Length == 0) + if (ri.Identifiers.Count == 0) { DisabledRequiredItems.Add(ri); } @@ -816,7 +814,7 @@ namespace Barotrauma.Items.Components } } - public void ApplyStatusEffects(ActionType type, float deltaTime, Character character = null, Limb targetLimb = null, Entity useTarget = null, Character user = null, Vector2? worldPosition = null, float applyOnUserFraction = 0.0f) + public void ApplyStatusEffects(ActionType type, float deltaTime, Character character = null, Limb targetLimb = null, Entity useTarget = null, Character user = null, Vector2? worldPosition = null, float afflictionMultiplier = 1.0f, float applyOnUserFraction = 0.0f) { if (statusEffectLists == null) { return; } @@ -828,13 +826,14 @@ namespace Barotrauma.Items.Components { if (broken && !effect.AllowWhenBroken && effect.type != ActionType.OnBroken) { continue; } if (user != null) { effect.SetUser(user); } + effect.AfflictionMultiplier = afflictionMultiplier; item.ApplyStatusEffect(effect, type, deltaTime, character, targetLimb, useTarget, isNetworkEvent: false, checkCondition: false, worldPosition); if (user != null && applyOnUserFraction > 0.0f && effect.HasTargetType(StatusEffect.TargetType.Character)) { effect.AfflictionMultiplier = applyOnUserFraction; item.ApplyStatusEffect(effect, type, deltaTime, user, targetLimb == null ? null : user.AnimController.GetLimb(targetLimb.type), useTarget, false, false, worldPosition); - effect.AfflictionMultiplier = 1.0f; } + effect.AfflictionMultiplier = 1.0f; reducesCondition |= effect.ReducesItemCondition(); } //if any of the effects reduce the item's condition, set the user for OnBroken effects as well @@ -1070,7 +1069,7 @@ namespace Barotrauma.Items.Components AIObjectiveContainItem containObjective = null; if (character.AIController is HumanAIController aiController) { - containObjective = new AIObjectiveContainItem(character, container.ContainableItemIdentifiers.ToArray(), container, currentObjective.objectiveManager, spawnItemIfNotFound: spawnItemIfNotFound) + containObjective = new AIObjectiveContainItem(character, container.ContainableItemIdentifiers, container, currentObjective.objectiveManager, spawnItemIfNotFound: spawnItemIfNotFound) { ItemCount = itemCount, Equip = equip, diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/ItemContainer.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/ItemContainer.cs index 26b9713d6..7ca37cb5e 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/ItemContainer.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/ItemContainer.cs @@ -216,9 +216,7 @@ namespace Barotrauma.Items.Components } private ImmutableHashSet containableItemIdentifiers; - public IEnumerable ContainableItemIdentifiers => containableItemIdentifiers; - - public override bool RecreateGUIOnResolutionChange => true; + public ImmutableHashSet ContainableItemIdentifiers => containableItemIdentifiers; public List ContainableItems { get; } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Deconstructor.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Deconstructor.cs index d7042894f..1de5e3c80 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Deconstructor.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Deconstructor.cs @@ -40,8 +40,6 @@ namespace Barotrauma.Items.Components [Editable, Serialize(1.0f, IsPropertySaveable.Yes)] public float DeconstructionSpeed { get; set; } - public override bool RecreateGUIOnResolutionChange => true; - public Deconstructor(Item item, ContentXElement element) : base(item, element) { @@ -122,7 +120,7 @@ namespace Barotrauma.Items.Components { if ((Entity.Spawner?.IsInRemoveQueue(targetItem) ?? false) || !inputContainer.Inventory.AllItems.Contains(targetItem)) { continue; } var validDeconstructItems = targetItem.Prefab.DeconstructItems.Where(it => - (it.RequiredDeconstructor.Length == 0 || it.RequiredDeconstructor.Any(r => item.HasTag(r) || item.Prefab.Identifier == r)) && + it.IsValidDeconstructor(item) && (it.RequiredOtherItem.Length == 0 || it.RequiredOtherItem.Any(r => items.Any(it => it != targetItem && (it.HasTag(r) || it.Prefab.Identifier == r))))).ToList(); ProcessItem(targetItem, items, validDeconstructItems, allowRemove: validDeconstructItems.Any() || !targetItem.Prefab.DeconstructItems.Any()); @@ -140,9 +138,7 @@ namespace Barotrauma.Items.Components var targetItem = inputContainer.Inventory.LastOrDefault(); if (targetItem == null) { return; } - var validDeconstructItems = targetItem.Prefab.DeconstructItems.Where(it => - it.RequiredDeconstructor.Length == 0 || it.RequiredDeconstructor.Any(r => item.HasTag(r) || item.Prefab.Identifier == r)).ToList(); - + var validDeconstructItems = targetItem.Prefab.DeconstructItems.Where(it => it.IsValidDeconstructor(item)).ToList(); float deconstructTime = validDeconstructItems.Any() ? targetItem.Prefab.DeconstructTime / (DeconstructionSpeed * deconstructionSpeedModifier) : 1.0f; progressState = Math.Min(progressTimer / deconstructTime, 1.0f); diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Fabricator.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Fabricator.cs index c3a9cb39e..9047d2f5e 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Fabricator.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Fabricator.cs @@ -76,8 +76,6 @@ namespace Barotrauma.Items.Components get { return outputContainer; } } - public override bool RecreateGUIOnResolutionChange => true; - private float progressState; private readonly Dictionary fabricationLimits = new Dictionary(); @@ -647,10 +645,13 @@ namespace Barotrauma.Items.Components if (skills.Length == 0) { return 1.0f; } if (character == null) { return 0.0f; } - float skillSum = (from t in skills let characterLevel = character.GetSkillLevel(t.Identifier) select (characterLevel - (t.Level * SkillRequirementMultiplier))).Sum(); - float average = skillSum / skills.Length; - - return (average + 100.0f) / 2.0f / 100.0f; + float minDegreeOfSuccess = 1.0f; + foreach (var skill in skills) + { + float characterLevel = character.GetSkillLevel(skill.Identifier); + minDegreeOfSuccess = Math.Min(minDegreeOfSuccess, (characterLevel - (skill.Level * SkillRequirementMultiplier) + 100.0f) / 2.0f / 100.0f); + } + return minDegreeOfSuccess; } public override float GetSkillMultiplier() @@ -658,13 +659,16 @@ namespace Barotrauma.Items.Components return SkillRequirementMultiplier; } + + private readonly HashSet linkedInventories = new HashSet(); + private void RefreshAvailableIngredients() { Character user = this.user; #if CLIENT user ??= Character.Controlled; #endif - + linkedInventories.Clear(); List itemList = new List(); itemList.AddRange(inputContainer.Inventory.AllItems); foreach (MapEntity linkedTo in item.linkedTo) @@ -684,6 +688,7 @@ namespace Barotrauma.Items.Components itemContainer = deconstructor.OutputContainer; } + linkedInventories.Add(itemContainer.Inventory); itemList.AddRange(itemContainer.Inventory.AllItems); } } @@ -698,6 +703,7 @@ namespace Barotrauma.Items.Components if (user?.Inventory != null) { itemList.AddRange(user.Inventory.AllItems); + linkedInventories.Add(user.Inventory); } availableIngredients.Clear(); foreach (Item item in itemList) diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Reactor.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Reactor.cs index 3bca94419..4630a0bf2 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Reactor.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Reactor.cs @@ -48,6 +48,9 @@ namespace Barotrauma.Items.Components private Vector2 optimalFissionRate, allowedFissionRate; private Vector2 optimalTurbineOutput, allowedTurbineOutput; + private float? signalControlledTargetFissionRate, signalControlledTargetTurbineOutput; + private double lastReceivedFissionRateSignalTime, lastReceivedTurbineOutputSignalTime; + private float temperatureBoost; private bool _powerOn; @@ -245,7 +248,7 @@ namespace Barotrauma.Items.Components } #endif - if (signalControlledTargetFissionRate.HasValue && Math.Abs(signalControlledTargetFissionRate.Value - TargetFissionRate) > 1.0f) + if (signalControlledTargetFissionRate.HasValue && lastReceivedFissionRateSignalTime > Timing.TotalTime - 1) { TargetFissionRate = adjustValueWithoutOverShooting(TargetFissionRate, signalControlledTargetFissionRate.Value, deltaTime * 5.0f); #if CLIENT @@ -256,7 +259,7 @@ namespace Barotrauma.Items.Components { signalControlledTargetFissionRate = null; } - if (signalControlledTargetTurbineOutput.HasValue && Math.Abs(signalControlledTargetTurbineOutput.Value - TargetTurbineOutput) > 1.0f) + if (signalControlledTargetTurbineOutput.HasValue && lastReceivedTurbineOutputSignalTime > Timing.TotalTime - 1) { TargetTurbineOutput = adjustValueWithoutOverShooting(TargetTurbineOutput, signalControlledTargetTurbineOutput.Value, deltaTime * 5.0f); #if CLIENT @@ -841,6 +844,7 @@ namespace Barotrauma.Items.Components if (PowerOn && float.TryParse(signal.value, NumberStyles.Float, CultureInfo.InvariantCulture, out float newFissionRate)) { signalControlledTargetFissionRate = MathHelper.Clamp(newFissionRate, 0.0f, 100.0f); + lastReceivedFissionRateSignalTime = Timing.TotalTime; registerUnsentChanges(); } break; @@ -848,6 +852,7 @@ namespace Barotrauma.Items.Components if (PowerOn && float.TryParse(signal.value, NumberStyles.Float, CultureInfo.InvariantCulture, out float newTurbineOutput)) { signalControlledTargetTurbineOutput = MathHelper.Clamp(newTurbineOutput, 0.0f, 100.0f); + lastReceivedTurbineOutputSignalTime = Timing.TotalTime; registerUnsentChanges(); } break; @@ -858,7 +863,5 @@ namespace Barotrauma.Items.Components if (GameMain.NetworkMember is { IsServer: true }) { unsentChanges = true; } } } - - private float? signalControlledTargetFissionRate, signalControlledTargetTurbineOutput; } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Sonar.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Sonar.cs index d60aad468..44065d74e 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Sonar.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Sonar.cs @@ -113,9 +113,23 @@ namespace Barotrauma.Items.Components set; } - [Editable, Serialize(false, IsPropertySaveable.No, description: "Does the sonar have mineral scanning mode. " + - "Only available in-game when the Item has no Steering component.")] - public bool HasMineralScanner { get; set; } + private bool hasMineralScanner; + + [Editable, Serialize(false, IsPropertySaveable.No, description: "Does the sonar have mineral scanning mode. ")] + public bool HasMineralScanner + { + get => hasMineralScanner; + set + { +#if CLIENT + if (controlContainer != null && !hasMineralScanner && value) + { + AddMineralScannerSwitchToGUI(); + } +#endif + hasMineralScanner = value; + } + } public float Zoom { @@ -144,8 +158,6 @@ namespace Barotrauma.Items.Components } } - public override bool RecreateGUIOnResolutionChange => true; - public Sonar(Item item, ContentXElement element) : base(item, element) { @@ -396,17 +408,17 @@ namespace Barotrauma.Items.Components public void ServerEventWrite(IWriteMessage msg, Client c, NetEntityEvent.IData extraData = null) { - msg.Write(currentMode == Mode.Active); + msg.WriteBoolean(currentMode == Mode.Active); if (currentMode == Mode.Active) { msg.WriteRangedSingle(zoom, MinZoom, MaxZoom, 8); - msg.Write(useDirectionalPing); + msg.WriteBoolean(useDirectionalPing); if (useDirectionalPing) { float pingAngle = MathUtils.WrapAngleTwoPi(MathUtils.VectorToAngle(pingDirection)); msg.WriteRangedSingle(MathUtils.InverseLerp(0.0f, MathHelper.TwoPi, pingAngle), 0.0f, 1.0f, 8); } - msg.Write(useMineralScanner); + msg.WriteBoolean(useMineralScanner); } } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Steering.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Steering.cs index fc32c5c30..75776f814 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Steering.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Steering.cs @@ -166,8 +166,6 @@ namespace Barotrauma.Items.Components set { posToMaintain = value; } } - public override bool RecreateGUIOnResolutionChange => true; - struct ObstacleDebugInfo { public Vector2 Point1; diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/ConnectionPanel.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/ConnectionPanel.cs index c5d847e8e..3954c06ed 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/ConnectionPanel.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/ConnectionPanel.cs @@ -401,14 +401,14 @@ namespace Barotrauma.Items.Components msg.WriteVariableUInt32((uint)connection.Wires.Count); foreach (Wire wire in connection.Wires) { - msg.Write(wire?.Item == null ? (ushort)0 : wire.Item.ID); + msg.WriteUInt16(wire?.Item == null ? (ushort)0 : wire.Item.ID); } } - msg.Write((ushort)DisconnectedWires.Count); + msg.WriteUInt16((ushort)DisconnectedWires.Count); foreach (Wire disconnectedWire in DisconnectedWires) { - msg.Write(disconnectedWire.Item.ID); + msg.WriteUInt16(disconnectedWire.Item.ID); } } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/CustomInterface.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/CustomInterface.cs index 2cbdc98fa..dc2ae516c 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/CustomInterface.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/CustomInterface.cs @@ -155,7 +155,7 @@ namespace Barotrauma.Items.Components { //use semicolon as a separator because comma may be needed in the signals (for color or vector values for example) //kind of hacky, we should probably add support for (string) arrays to SerializableEntityEditor so this wouldn't be needed - get { return signals == null ? "" : string.Join(";", signals); } + get { return signals == null ? string.Empty : string.Join(";", signals); } set { if (value == null) { return; } @@ -167,7 +167,31 @@ namespace Barotrauma.Items.Components } } - public override bool RecreateGUIOnResolutionChange => true; + private bool[] elementStates; + [Serialize("", IsPropertySaveable.Yes, description: "", alwaysUseInstanceValues: true)] + public string ElementStates + { + get { return elementStates == null ? string.Empty : string.Join(",", elementStates); } + set + { + if (value == null) { return; } + if (customInterfaceElementList.Count > 0) + { + string[] splitValues = value == "" ? Array.Empty() : value.Split(','); + for (int i = 0; i < customInterfaceElementList.Count && i < splitValues.Length; i++) + { + if (!bool.TryParse(splitValues[i], out bool val)) { continue; } + customInterfaceElementList[i].State = val; +#if CLIENT + if (uiElements != null && i < uiElements.Count && uiElements[i] is GUITickBox tickBox) + { + tickBox.Selected = val; + } +#endif + } + } + } + } private readonly List customInterfaceElementList = new List(); @@ -207,8 +231,10 @@ namespace Barotrauma.Items.Components } IsActive = true; InitProjSpecific(); + //load these here to ensure the UI elements (created in InitProjSpecific) are up-to-date Labels = element.GetAttributeString("labels", ""); Signals = element.GetAttributeString("signals", ""); + ElementStates = element.GetAttributeString("elementstates", ""); } private void UpdateLabels(string[] newLabels) @@ -386,6 +412,7 @@ namespace Barotrauma.Items.Components { labels = customInterfaceElementList.Select(ci => ci.Label).ToArray(); signals = customInterfaceElementList.Select(ci => ci.Signal).ToArray(); + elementStates = customInterfaceElementList.Select(ci => ci.State).ToArray(); return base.Save(parentElement); } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/LightComponent.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/LightComponent.cs index 5e4ba1095..32f151379 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/LightComponent.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/LightComponent.cs @@ -253,7 +253,13 @@ namespace Barotrauma.Items.Components public void CheckIfNeedsUpdate() { - if (item.body == null && powerConsumption <= 0.0f && Parent == null && turret == null && IsOn && + if (!IsOn) + { + base.IsActive = false; + return; + } + + if (item.body == null && powerConsumption <= 0.0f && Parent == null && turret == null && (statusEffectLists == null || !statusEffectLists.ContainsKey(ActionType.OnActive)) && (IsActiveConditionals == null || IsActiveConditionals.Count == 0)) { @@ -268,7 +274,7 @@ namespace Barotrauma.Items.Components } else { - IsActive = true; + base.IsActive = true; } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/RelayComponent.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/RelayComponent.cs index 0a0a3e691..5696c6280 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/RelayComponent.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/RelayComponent.cs @@ -374,7 +374,7 @@ namespace Barotrauma.Items.Components public void ServerEventWrite(IWriteMessage msg, Client c, NetEntityEvent.IData extraData = null) { - msg.Write(isOn); + msg.WriteBoolean(isOn); } public void ClientEventRead(IReadMessage msg, float sendingTime) diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Turret.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Turret.cs index d599a3bce..18ab28faf 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Turret.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Turret.cs @@ -7,6 +7,7 @@ using System.Globalization; using System.Linq; using Barotrauma.Extensions; using FarseerPhysics.Dynamics; +using System.Collections.Immutable; namespace Barotrauma.Items.Components { @@ -1151,7 +1152,7 @@ namespace Barotrauma.Items.Components if (objective.SubObjectives.None()) { var loadItemsObjective = AIContainItems(container, character, objective, usableProjectileCount + 1, equip: true, removeEmpty: true, dropItemOnDeselected: true); - loadItemsObjective.ignoredContainerIdentifiers = new Identifier[] { ((MapEntity)containerItem).Prefab.Identifier }; + loadItemsObjective.ignoredContainerIdentifiers = ((MapEntity)containerItem).Prefab.Identifier.ToEnumerable().ToImmutableHashSet(); if (character.IsOnPlayerTeam) { character.Speak(TextManager.GetWithVariable("DialogLoadTurret", "[itemname]", item.Name, formatCapitals: FormatCapitals.Yes).Value, @@ -1340,7 +1341,7 @@ namespace Barotrauma.Items.Components { if (character.AIController.SelectedAiTarget == null && !hadCurrentTarget) { - if (CreatureMetrics.Instance.RecentlyEncountered.Contains(closestEnemy.SpeciesName)) + if (CreatureMetrics.Instance.RecentlyEncountered.Contains(closestEnemy.SpeciesName) || closestEnemy.IsHuman) { character.Speak(TextManager.Get("DialogNewTargetSpotted").Value, identifier: "newtargetspotted".ToIdentifier(), @@ -1611,6 +1612,7 @@ namespace Barotrauma.Items.Components targetRotation = rotation = (minRotation + maxRotation) / 2; UpdateTransformedBarrelPos(); + UpdateLightComponents(); } public override void FlipY(bool relativeToSub) @@ -1632,6 +1634,7 @@ namespace Barotrauma.Items.Components targetRotation = rotation = (minRotation + maxRotation) / 2; UpdateTransformedBarrelPos(); + UpdateLightComponents(); } public override void ReceiveSignal(Signal signal, Connection connection) @@ -1714,12 +1717,12 @@ namespace Barotrauma.Items.Components { if (TryExtractEventData(extraData, out EventData eventData)) { - msg.Write(eventData.Projectile.ID); + msg.WriteUInt16(eventData.Projectile.ID); msg.WriteRangedSingle(MathHelper.Clamp(rotation, minRotation, maxRotation), minRotation, maxRotation, 16); } else { - msg.Write((ushort)0); + msg.WriteUInt16((ushort)0); float wrappedTargetRotation = targetRotation; while (wrappedTargetRotation < minRotation && MathUtils.IsValid(wrappedTargetRotation)) { diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Wearable.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Wearable.cs index ae4b5b1c6..57b4dc685 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Wearable.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Wearable.cs @@ -560,7 +560,7 @@ namespace Barotrauma.Items.Components } public override void ServerEventWrite(IWriteMessage msg, Client c, NetEntityEvent.IData extraData = null) { - msg.Write((byte)Variant); + msg.WriteByte((byte)Variant); base.ServerEventWrite(msg, c, extraData); } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Inventory.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Inventory.cs index a4281fe28..afb94878c 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Inventory.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Inventory.cs @@ -959,14 +959,14 @@ namespace Barotrauma public void SharedWrite(IWriteMessage msg, NetEntityEvent.IData extraData = null) { - msg.Write((byte)capacity); + msg.WriteByte((byte)capacity); for (int i = 0; i < capacity; i++) { msg.WriteRangedInteger(slots[i].Items.Count, 0, MaxStackSize); for (int j = 0; j < Math.Min(slots[i].Items.Count, MaxStackSize); j++) { var item = slots[i].Items[j]; - msg.Write(item?.ID ?? (ushort)0); + msg.WriteUInt16(item?.ID ?? (ushort)0); } } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Item.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Item.cs index 6411b4334..c8fc6f8a2 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Item.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Item.cs @@ -1536,7 +1536,7 @@ namespace Barotrauma return false; } - private bool ConditionalMatches(PropertyConditional conditional) + public bool ConditionalMatches(PropertyConditional conditional) { if (string.IsNullOrEmpty(conditional.TargetItemComponentName)) { @@ -2861,77 +2861,77 @@ namespace Barotrauma var propertyOwner = allProperties.Find(p => p.property == property); if (allProperties.Count > 1) { - msg.Write((byte)allProperties.FindIndex(p => p.property == property)); + msg.WriteByte((byte)allProperties.FindIndex(p => p.property == property)); } object value = property.GetValue(propertyOwner.obj); if (value is string stringVal) { - msg.Write(stringVal); + msg.WriteString(stringVal); } else if (value is Identifier idValue) { - msg.Write(idValue); + msg.WriteIdentifier(idValue); } else if (value is float floatVal) { - msg.Write(floatVal); + msg.WriteSingle(floatVal); } else if (value is int intVal) { - msg.Write(intVal); + msg.WriteInt32(intVal); } else if (value is bool boolVal) { - msg.Write(boolVal); + msg.WriteBoolean(boolVal); } else if (value is Color color) { - msg.Write(color.R); - msg.Write(color.G); - msg.Write(color.B); - msg.Write(color.A); + msg.WriteByte(color.R); + msg.WriteByte(color.G); + msg.WriteByte(color.B); + msg.WriteByte(color.A); } else if (value is Vector2 vector2) { - msg.Write(vector2.X); - msg.Write(vector2.Y); + msg.WriteSingle(vector2.X); + msg.WriteSingle(vector2.Y); } else if (value is Vector3 vector3) { - msg.Write(vector3.X); - msg.Write(vector3.Y); - msg.Write(vector3.Z); + msg.WriteSingle(vector3.X); + msg.WriteSingle(vector3.Y); + msg.WriteSingle(vector3.Z); } else if (value is Vector4 vector4) { - msg.Write(vector4.X); - msg.Write(vector4.Y); - msg.Write(vector4.Z); - msg.Write(vector4.W); + msg.WriteSingle(vector4.X); + msg.WriteSingle(vector4.Y); + msg.WriteSingle(vector4.Z); + msg.WriteSingle(vector4.W); } else if (value is Point point) { - msg.Write(point.X); - msg.Write(point.Y); + msg.WriteInt32(point.X); + msg.WriteInt32(point.Y); } else if (value is Rectangle rect) { - msg.Write(rect.X); - msg.Write(rect.Y); - msg.Write(rect.Width); - msg.Write(rect.Height); + msg.WriteInt32(rect.X); + msg.WriteInt32(rect.Y); + msg.WriteInt32(rect.Width); + msg.WriteInt32(rect.Height); } else if (value is Enum) { - msg.Write((int)value); + msg.WriteInt32((int)value); } else if (value is string[] a) { - msg.Write(a.Length); + msg.WriteInt32(a.Length); for (int i = 0; i < a.Length; i++) { - msg.Write(a[i] ?? ""); + msg.WriteString(a[i] ?? ""); } } else diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/ItemPrefab.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/ItemPrefab.cs index 203d2dbac..ce8d957e2 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/ItemPrefab.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/ItemPrefab.cs @@ -53,6 +53,11 @@ namespace Barotrauma InfoText = element.GetAttributeString("infotext", string.Empty); InfoTextOnOtherItemMissing = element.GetAttributeString("infotextonotheritemmissing", string.Empty); } + + public bool IsValidDeconstructor(Item deconstructor) + { + return RequiredDeconstructor.Length == 0 || RequiredDeconstructor.Any(r => deconstructor.HasTag(r) || deconstructor.Prefab.Identifier == r); + } } class FabricationRecipe @@ -62,6 +67,10 @@ namespace Barotrauma public abstract IEnumerable ItemPrefabs { get; } public abstract UInt32 UintIdentifier { get; } + public abstract bool MatchesItem(Item item); + + public abstract ItemPrefab FirstMatchingPrefab { get; } + public RequiredItem(int amount, float minCondition, float maxCondition, bool useCondition) { Amount = amount; @@ -92,12 +101,21 @@ namespace Barotrauma public class RequiredItemByIdentifier : RequiredItem { public readonly Identifier ItemPrefabIdentifier; + public ItemPrefab ItemPrefab => ItemPrefab.Prefabs.TryGet(ItemPrefabIdentifier, out var prefab) ? prefab : MapEntityPrefab.FindByName(ItemPrefabIdentifier.Value) as ItemPrefab ?? throw new Exception($"No ItemPrefab with identifier or name \"{ItemPrefabIdentifier}\""); + public override UInt32 UintIdentifier { get; } public override IEnumerable ItemPrefabs => ItemPrefab.ToEnumerable(); + public override ItemPrefab FirstMatchingPrefab => ItemPrefab; + + public override bool MatchesItem(Item item) + { + return item?.Prefab.Identifier == ItemPrefabIdentifier; + } + public RequiredItemByIdentifier(Identifier itemPrefab, int amount, float minCondition, float maxCondition, bool useCondition) : base(amount, minCondition, maxCondition, useCondition) { ItemPrefabIdentifier = itemPrefab; @@ -109,10 +127,19 @@ namespace Barotrauma public class RequiredItemByTag : RequiredItem { public readonly Identifier Tag; + public override UInt32 UintIdentifier { get; } public override IEnumerable ItemPrefabs => ItemPrefab.Prefabs.Where(p => p.Tags.Contains(Tag)); + public override ItemPrefab FirstMatchingPrefab => ItemPrefab.Prefabs.FirstOrDefault(p => p.Tags.Contains(Tag)); + + public override bool MatchesItem(Item item) + { + if (item == null) { return false; } + return item.HasTag(Tag); + } + public RequiredItemByTag(Identifier tag, int amount, float minCondition, float maxCondition, bool useCondition) : base(amount, minCondition, maxCondition, useCondition) { Tag = tag; @@ -208,10 +235,10 @@ namespace Barotrauma if (requiredItemIdentifier != Identifier.Empty) { var existing = requiredItems.FindIndex(r => - r is RequiredItemByIdentifier ri && - ri.ItemPrefabIdentifier == requiredItemIdentifier && - MathUtils.NearlyEqual(r.MinCondition, minCondition) && - MathUtils.NearlyEqual(r.MaxCondition, maxCondition)); + r is RequiredItemByIdentifier ri && + ri.ItemPrefabIdentifier == requiredItemIdentifier && + MathUtils.NearlyEqual(r.MinCondition, minCondition) && + MathUtils.NearlyEqual(r.MaxCondition, maxCondition)); if (existing >= 0) { amount += requiredItems[existing].Amount; @@ -222,10 +249,10 @@ namespace Barotrauma else { var existing = requiredItems.FindIndex(r => - r is RequiredItemByTag rt && - rt.Tag == requiredItemTag && - MathUtils.NearlyEqual(r.MinCondition, minCondition) && - MathUtils.NearlyEqual(r.MaxCondition, maxCondition)); + r is RequiredItemByTag rt && + rt.Tag == requiredItemTag && + MathUtils.NearlyEqual(r.MinCondition, minCondition) && + MathUtils.NearlyEqual(r.MaxCondition, maxCondition)); if (existing >= 0) { amount += requiredItems[existing].Amount; @@ -783,19 +810,12 @@ namespace Barotrauma //works the same as nameIdentifier, but just replaces the description Identifier descriptionIdentifier = ConfigElement.GetAttributeIdentifier("descriptionidentifier", ""); - if (string.IsNullOrEmpty(OriginalName)) - { - name = TextManager.Get(nameIdentifier.IsEmpty - ? $"EntityName.{Identifier}" - : $"EntityName.{nameIdentifier}", - $"EntityName.{fallbackNameIdentifier}"); - } - else if (Category.HasFlag(MapEntityCategory.Legacy)) - { - // Legacy items use names as identifiers, so we have to define them in the xml. But we also want to support the translations. Therefore - name = TextManager.Get(nameIdentifier.IsEmpty + name = TextManager.Get(nameIdentifier.IsEmpty ? $"EntityName.{Identifier}" - : $"EntityName.{nameIdentifier}"); + : $"EntityName.{nameIdentifier}", + $"EntityName.{fallbackNameIdentifier}"); + if (!string.IsNullOrEmpty(OriginalName)) + { name = name.Fallback(OriginalName); } @@ -838,20 +858,17 @@ namespace Barotrauma SerializableProperty.DeserializeProperties(this, ConfigElement); - if (Description.IsNullOrEmpty()) + if (descriptionIdentifier != Identifier.Empty) { - if (descriptionIdentifier != Identifier.Empty) - { - Description = TextManager.Get($"EntityDescription.{descriptionIdentifier}"); - } - else if (nameIdentifier == Identifier.Empty) - { - Description = TextManager.Get($"EntityDescription.{Identifier}"); - } - else - { - Description = TextManager.Get($"EntityDescription.{nameIdentifier}"); - } + Description = TextManager.Get($"EntityDescription.{descriptionIdentifier}").Fallback(Description); + } + else if (nameIdentifier == Identifier.Empty) + { + Description = TextManager.Get($"EntityDescription.{Identifier}").Fallback(Description); + } + else + { + Description = TextManager.Get($"EntityDescription.{nameIdentifier}").Fallback(Description); } var allowDroppingOnSwapWith = ConfigElement.GetAttributeIdentifierArray("allowdroppingonswapwith", Array.Empty()); diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/RelatedItem.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/RelatedItem.cs index a74a686d4..04351e385 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/RelatedItem.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/RelatedItem.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Collections.Immutable; using System.Linq; using System.Xml.Linq; @@ -22,7 +23,7 @@ namespace Barotrauma public bool IgnoreInEditor { get; set; } - private Identifier[] excludedIdentifiers; + private ImmutableHashSet excludedIdentifiers; private RelationType type; @@ -60,11 +61,11 @@ namespace Barotrauma { if (value == null) return; - Identifiers = value.Split(',').Select(s => s.Trim()).ToIdentifiers().ToArray(); + Identifiers = value.Split(',').Select(s => s.Trim()).ToIdentifiers().ToImmutableHashSet(); } } - public Identifier[] Identifiers { get; private set; } + public ImmutableHashSet Identifiers { get; private set; } public string JoinedExcludedIdentifiers { @@ -73,27 +74,53 @@ namespace Barotrauma { if (value == null) return; - excludedIdentifiers = value.Split(',').Select(s => s.Trim()).ToIdentifiers().ToArray(); + excludedIdentifiers = value.Split(',').Select(s => s.Trim()).ToIdentifiers().ToImmutableHashSet(); } } public bool MatchesItem(Item item) { if (item == null) { return false; } - if (excludedIdentifiers.Any(id => item.Prefab.Identifier == id || item.HasTag(id))) { return false; } - return Identifiers.Any(id => item.Prefab.Identifier == id || item.HasTag(id) || (AllowVariants && !item.Prefab.VariantOf.IsEmpty && item.Prefab.VariantOf == id)); + if (excludedIdentifiers.Contains(item.Prefab.Identifier)) { return false; } + foreach (var excludedIdentifier in excludedIdentifiers) + { + if (item.HasTag(excludedIdentifier)) { return false; } + } + if (Identifiers.Contains(item.Prefab.Identifier)) { return true; } + foreach (var identifier in Identifiers) + { + if (item.HasTag(identifier)) { return true; } + } + if (AllowVariants && !item.Prefab.VariantOf.IsEmpty) + { + if (Identifiers.Contains(item.Prefab.VariantOf)) { return true; } + } + return false; } public bool MatchesItem(ItemPrefab itemPrefab) { if (itemPrefab == null) { return false; } - if (excludedIdentifiers.Any(id => itemPrefab.Identifier == id || itemPrefab.Tags.Contains(id))) { return false; } - return Identifiers.Any(id => itemPrefab.Identifier == id || itemPrefab.Tags.Contains(id) || (AllowVariants && !itemPrefab.VariantOf.IsEmpty && itemPrefab.VariantOf == id)); + if (excludedIdentifiers.Contains(itemPrefab.Identifier)) { return false; } + foreach (var excludedIdentifier in excludedIdentifiers) + { + if (itemPrefab.Tags.Contains(excludedIdentifier)) { return false; } + } + if (Identifiers.Contains(itemPrefab.Identifier)) { return true; } + foreach (var identifier in Identifiers) + { + if (itemPrefab.Tags.Contains(identifier)) { return true; } + } + if (AllowVariants && !itemPrefab.VariantOf.IsEmpty) + { + if (Identifiers.Contains(itemPrefab.VariantOf)) { return true; } + } + return false; } public RelatedItem(Identifier[] identifiers, Identifier[] excludedIdentifiers) { - this.Identifiers = identifiers.Select(id => id.Value.Trim().ToIdentifier()).ToArray(); - this.excludedIdentifiers = excludedIdentifiers.Select(id => id.Value.Trim().ToIdentifier()).ToArray(); + this.Identifiers = identifiers.Select(id => id.Value.Trim().ToIdentifier()).ToImmutableHashSet(); + this.excludedIdentifiers = excludedIdentifiers.Select(id => id.Value.Trim().ToIdentifier()).ToImmutableHashSet(); statusEffects = new List(); } @@ -161,7 +188,7 @@ namespace Barotrauma new XAttribute("targetslot", TargetSlot), new XAttribute("allowvariants", AllowVariants)); - if (excludedIdentifiers.Length > 0) + if (excludedIdentifiers.Count > 0) { element.Add(new XAttribute("excludedidentifiers", JoinedExcludedIdentifiers)); } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Map/Gap.cs b/Barotrauma/BarotraumaShared/SharedSource/Map/Gap.cs index 291737a4e..a226d5e6e 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Map/Gap.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Map/Gap.cs @@ -25,6 +25,12 @@ namespace Barotrauma private set; } + /// + /// "Diagonal" gaps are used on sloped walls to allow characters to pass through them either horizontally or vertically. + /// Water still flows through them only horizontally or vertically + /// + public bool IsDiagonal { get; } + //a value between 0.0f-1.0f (0.0 = closed, 1.0f = open) private float open; @@ -135,12 +141,13 @@ namespace Barotrauma : this(rect, rect.Width < rect.Height, submarine) { } - public Gap(Rectangle rect, bool isHorizontal, Submarine submarine, ushort id = Entity.NullEntityID) + public Gap(Rectangle rect, bool isHorizontal, Submarine submarine, bool isDiagonal = false, ushort id = Entity.NullEntityID) : base(CoreEntityPrefab.GapPrefab, submarine, id) { this.rect = rect; flowForce = Vector2.Zero; IsHorizontal = isHorizontal; + IsDiagonal = isDiagonal; open = 1.0f; FindHulls(); @@ -666,15 +673,15 @@ namespace Barotrauma { foreach (Gap gap in gaps) { - if (gap.Open == 0.0f || gap.IsRoomToRoom) continue; + if (gap.Open == 0.0f || gap.IsRoomToRoom) { continue; } if (gap.ConnectedWall != null) { int sectionIndex = gap.ConnectedWall.FindSectionIndex(gap.Position); - if (sectionIndex > -1 && !gap.ConnectedWall.SectionBodyDisabled(sectionIndex)) continue; + if (sectionIndex > -1 && !gap.ConnectedWall.SectionBodyDisabled(sectionIndex)) { continue; } } - if (gap.IsHorizontal) + if (gap.IsHorizontal || gap.IsDiagonal) { if (worldPos.Y < gap.WorldRect.Y && worldPos.Y > gap.WorldRect.Y - gap.WorldRect.Height && Math.Abs(gap.WorldRect.Center.X - worldPos.X) < allowedOrthogonalDist) @@ -682,7 +689,7 @@ namespace Barotrauma return gap; } } - else + if (!gap.IsHorizontal || gap.IsDiagonal) { if (worldPos.X > gap.WorldRect.X && worldPos.X < gap.WorldRect.Right && Math.Abs(gap.WorldRect.Y - gap.WorldRect.Height / 2 - worldPos.Y) < allowedOrthogonalDist) @@ -754,7 +761,7 @@ namespace Barotrauma isHorizontal = horizontalAttribute.Value.ToString() == "true"; } - Gap g = new Gap(rect, isHorizontal, submarine, idRemap.GetOffsetId(element)) + Gap g = new Gap(rect, isHorizontal, submarine, id: idRemap.GetOffsetId(element)) { linkedToID = new List(), }; diff --git a/Barotrauma/BarotraumaShared/SharedSource/Map/Hull.cs b/Barotrauma/BarotraumaShared/SharedSource/Map/Hull.cs index 9702e90be..3752320d8 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Map/Hull.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Map/Hull.cs @@ -759,7 +759,7 @@ namespace Barotrauma for (int i = start; i < end; i++) { msg.WriteRangedSingle(BackgroundSections[i].ColorStrength, 0.0f, 1.0f, 8); - msg.Write(BackgroundSections[i].Color.PackedValue); + msg.WriteUInt32(BackgroundSections[i].Color.PackedValue); } } #endregion @@ -994,7 +994,11 @@ namespace Barotrauma foreach (var gap in ConnectedGaps.Where(gap => gap.Open > 0)) { var distance = MathHelper.Max(Vector2.DistanceSquared(item.Position, gap.Position) / 1000, 1f); - item.body.ApplyForce((gap.LerpedFlowForce / distance) * deltaTime); + Vector2 force = (gap.LerpedFlowForce / distance) * deltaTime; + if (force.LengthSquared() > 0.01f) + { + item.body.ApplyForce(force); + } } } @@ -1545,7 +1549,7 @@ namespace Barotrauma var hull = new Hull(rect, submarine, idRemap.GetOffsetId(element)) { - WaterVolume = element.GetAttributeFloat("pressure", 0.0f) + WaterVolume = element.GetAttributeFloat("water", 0.0f) }; hull.linkedToID = new List(); diff --git a/Barotrauma/BarotraumaShared/SharedSource/Map/Levels/Level.cs b/Barotrauma/BarotraumaShared/SharedSource/Map/Levels/Level.cs index 6bb343533..181f60281 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Map/Levels/Level.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Map/Levels/Level.cs @@ -1972,7 +1972,7 @@ namespace Barotrauma List caveBranches = new List(); - var tunnel = new Tunnel(TunnelType.Cave, SegmentsToNodes(caveSegments), 100, parentTunnel); + var tunnel = new Tunnel(TunnelType.Cave, SegmentsToNodes(caveSegments), 150, parentTunnel); Tunnels.Add(tunnel); caveBranches.Add(tunnel); @@ -1989,7 +1989,7 @@ namespace Barotrauma bounds: caveArea); if (!branchSegments.Any()) { continue; } - var branch = new Tunnel(TunnelType.Cave, SegmentsToNodes(branchSegments), 0, parentBranch); + var branch = new Tunnel(TunnelType.Cave, SegmentsToNodes(branchSegments), 150, parentBranch); Tunnels.Add(branch); caveBranches.Add(branch); } @@ -2569,34 +2569,38 @@ namespace Barotrauma AbyssResources.Clear(); var abyssResourcePrefabs = levelResources.Where(r => r.commonnessInfo.AbyssCommonness > 0.0f); - int abyssClusterCount = (int)MathHelper.Lerp(GenerationParams.AbyssResourceClustersMin, GenerationParams.AbyssResourceClustersMax, MathUtils.InverseLerp(LevelData.Biome.MinDifficulty, LevelData.Biome.AdjustedMaxDifficulty, Difficulty)); - for (int i = 0; i < abyssClusterCount; i++) + if (abyssResourcePrefabs.Any()) { - var selectedPrefab = ToolBox.SelectWeightedRandom( - abyssResourcePrefabs.Select(r => r.itemPrefab).ToList(), - abyssResourcePrefabs.Select(r => r.commonnessInfo.AbyssCommonness).ToList(), - Rand.RandSync.ServerAndClient); - - var location = allValidLocations.GetRandom(l => + int abyssClusterCount = (int)MathHelper.Lerp(GenerationParams.AbyssResourceClustersMin, GenerationParams.AbyssResourceClustersMax, MathUtils.InverseLerp(LevelData.Biome.MinDifficulty, LevelData.Biome.AdjustedMaxDifficulty, Difficulty)); + for (int i = 0; i < abyssClusterCount; i++) { - if (l.Cell == null || l.Edge == null) { return false; } - if (l.EdgeCenter.Y > AbyssArea.Bottom) { return false; } - l.InitializeResources(); - return l.Resources.Count <= GetMaxResourcesOnEdge(selectedPrefab, l, out _); - }, randSync: Rand.RandSync.ServerAndClient); + var selectedPrefab = ToolBox.SelectWeightedRandom( + abyssResourcePrefabs.Select(r => r.itemPrefab).ToList(), + abyssResourcePrefabs.Select(r => r.commonnessInfo.AbyssCommonness).ToList(), + Rand.RandSync.ServerAndClient); - if (location.Cell == null || location.Edge == null) { break; } + var location = allValidLocations.GetRandom(l => + { + if (l.Cell == null || l.Edge == null) { return false; } + if (l.EdgeCenter.Y > AbyssArea.Bottom) { return false; } + l.InitializeResources(); + return l.Resources.Count <= GetMaxResourcesOnEdge(selectedPrefab, l, out _); + }, randSync: Rand.RandSync.ServerAndClient); - int clusterSize = Rand.Range(GenerationParams.ResourceClusterSizeRange.X, GenerationParams.ResourceClusterSizeRange.Y + 1, Rand.RandSync.ServerAndClient); - PlaceResources(selectedPrefab, clusterSize, location, out var placedResources, maxResourceOverlap: 0); - var abyssClusterLocation = new ClusterLocation(location.Cell, location.Edge, initializeResourceList: true); - abyssClusterLocation.Resources.AddRange(placedResources); - AbyssResources.Add(abyssClusterLocation); + if (location.Cell == null || location.Edge == null) { break; } - var locationIndex = allValidLocations.FindIndex(l => l.Equals(location)); - allValidLocations.RemoveAt(locationIndex); + int clusterSize = Rand.Range(GenerationParams.ResourceClusterSizeRange.X, GenerationParams.ResourceClusterSizeRange.Y + 1, Rand.RandSync.ServerAndClient); + PlaceResources(selectedPrefab, clusterSize, location, out var placedResources, maxResourceOverlap: 0); + var abyssClusterLocation = new ClusterLocation(location.Cell, location.Edge, initializeResourceList: true); + abyssClusterLocation.Resources.AddRange(placedResources); + AbyssResources.Add(abyssClusterLocation); + + var locationIndex = allValidLocations.FindIndex(l => l.Equals(location)); + allValidLocations.RemoveAt(locationIndex); + } } + PathPoints.Clear(); nextPathPointId = 0; @@ -2928,50 +2932,74 @@ namespace Barotrauma } /// Used by clients to set the rotation for the resources - public List GenerateMissionResources(ItemPrefab prefab, int requiredAmount, out float rotation) + public List GenerateMissionResources(ItemPrefab prefab, int requiredAmount, PositionType positionType, out float rotation) { var allValidLocations = GetAllValidClusterLocations(); var placedResources = new List(); rotation = 0.0f; + if (allValidLocations.None()) { return placedResources; } // TODO: WHAT?! + // Make sure not to pick a spot that already has other level resources for (int i = allValidLocations.Count - 1; i >= 0; i--) { - var location = allValidLocations[i]; - var locationHasResources = PathPoints.Any(p => - p.ClusterLocations.Any(c => - c.Equals(location) && - c.Resources.Any(r => r != null && !r.Removed && - (!(r.GetComponent() is Holdable h) || (h.Attachable && h.Attached))))); - if (locationHasResources) + if (HasResources(allValidLocations[i])) { allValidLocations.RemoveAt(i); } + + bool HasResources(ClusterLocation clusterLocation) + { + foreach (var p in PathPoints) + { + foreach (var c in p.ClusterLocations) + { + if (!c.Equals(clusterLocation)) { continue; } + foreach (var r in c.Resources) + { + if (r == null) { continue; } + if (r.Removed) { continue; } + if (!(r.GetComponent() is Holdable h) || (h.Attachable && h.Attached)) { return true; } + } + } + } + return false; + } } - var positionType = PositionType.MainPath; - if (PositionsOfInterest.Any(p => p.PositionType == PositionType.Cave)) + if (PositionsOfInterest.None(p => p.PositionType == positionType)) { - positionType = PositionType.Cave; - if (allValidLocations.Any(l => l.Edge.NextToCave)) + foreach (var validType in MineralMission.ValidPositionTypes) { - allValidLocations.RemoveAll(l => !l.Edge.NextToCave); + if (validType != positionType && PositionsOfInterest.Any(p => p.PositionType == validType)) + { + positionType = validType; + break; + } } } - else if (PositionsOfInterest.Any(p => p.PositionType == PositionType.SidePath)) + + try { - positionType = PositionType.SidePath; - if (allValidLocations.Any(l => l.Edge.NextToSidePath)) + RemoveInvalidLocations(positionType switch { - allValidLocations.RemoveAll(l => !l.Edge.NextToSidePath); - } + PositionType.MainPath => IsOnMainPath, + PositionType.SidePath => IsOnSidePath, + PositionType.Cave => IsInCave, + PositionType.AbyssCave => IsInAbyssCave, + _ => throw new NotImplementedException(), + }); + } + catch (NotImplementedException) + { + DebugConsole.ThrowError($"Unexpected PositionType (\"{positionType}\") for mineral mission resources: mineral spawning might not work as expected."); } var poi = PositionsOfInterest.GetRandom(p => p.PositionType == positionType, randSync: Rand.RandSync.ServerAndClient); - var poiPos = poi.Position.ToVector2(); + Vector2 poiPos = poi.Position.ToVector2(); allValidLocations.Sort((x, y) => Vector2.DistanceSquared(poiPos, x.EdgeCenter) .CompareTo(Vector2.DistanceSquared(poiPos, y.EdgeCenter))); - var maxResourceOverlap = 0.4f; + float maxResourceOverlap = 0.4f; var selectedLocation = allValidLocations.FirstOrDefault(l => Vector2.Distance(l.Edge.Point1, l.Edge.Point2) is float edgeLength && requiredAmount <= (int)Math.Floor(edgeLength / ((1.0f - maxResourceOverlap) * prefab.Size.X))); @@ -2993,9 +3021,18 @@ namespace Barotrauma throw new Exception("Failed to find a suitable level wall edge to place level resources on."); } PlaceResources(prefab, requiredAmount, selectedLocation, out placedResources); - var edgeNormal = selectedLocation.Edge.GetNormal(selectedLocation.Cell); + Vector2 edgeNormal = selectedLocation.Edge.GetNormal(selectedLocation.Cell); rotation = MathHelper.ToDegrees(-MathUtils.VectorToAngle(edgeNormal) + MathHelper.PiOver2); return placedResources; + + static bool IsOnMainPath(ClusterLocation location) => location.Edge.NextToMainPath; + static bool IsOnSidePath(ClusterLocation location) => location.Edge.NextToSidePath; + static bool IsInCave(ClusterLocation location) => location.Edge.NextToCave; + bool IsInAbyssCave(ClusterLocation location) => location.EdgeCenter.Y > AbyssArea.Bottom; + void RemoveInvalidLocations(Predicate match) + { + allValidLocations.RemoveAll(match); + } } private List GetAllValidClusterLocations() @@ -4015,17 +4052,21 @@ namespace Barotrauma GameAnalyticsManager.AddErrorEventOnce("Lever.CreateOutposts:DockingPortVeryFar" + Submarine.MainSub.Info.Name, GameAnalyticsManager.ErrorSeverity.Warning, warningMsg); } - float outpostDockingPortOffset = subPort == null ? 0.0f : outpostPort.Item.WorldPosition.X - outpost.WorldPosition.X; - //don't try to compensate if the port is very far from the outpost's center of mass - if (Math.Abs(outpostDockingPortOffset) > 5000.0f) + float? outpostDockingPortOffset = null; + if (outpostPort != null) { - outpostDockingPortOffset = MathHelper.Clamp(outpostDockingPortOffset, -5000.0f, 5000.0f); - string warningMsg = "Docking port very far from the outpost's center of mass (outpost: " + outpost.Info.Name + ", dist: " + outpostDockingPortOffset + "). The level generator may not be able to place the outpost so that docking is possible."; - DebugConsole.NewMessage(warningMsg, Color.Orange); - GameAnalyticsManager.AddErrorEventOnce("Lever.CreateOutposts:OutpostDockingPortVeryFar" + outpost.Info.Name, GameAnalyticsManager.ErrorSeverity.Warning, warningMsg); + outpostDockingPortOffset = subPort == null ? 0.0f : outpostPort.Item.WorldPosition.X - outpost.WorldPosition.X; + //don't try to compensate if the port is very far from the outpost's center of mass + if (Math.Abs(outpostDockingPortOffset.Value) > 5000.0f) + { + outpostDockingPortOffset = MathHelper.Clamp(outpostDockingPortOffset.Value, -5000.0f, 5000.0f); + string warningMsg = "Docking port very far from the outpost's center of mass (outpost: " + outpost.Info.Name + ", dist: " + outpostDockingPortOffset + "). The level generator may not be able to place the outpost so that docking is possible."; + DebugConsole.NewMessage(warningMsg, Color.Orange); + GameAnalyticsManager.AddErrorEventOnce("Lever.CreateOutposts:OutpostDockingPortVeryFar" + outpost.Info.Name, GameAnalyticsManager.ErrorSeverity.Warning, warningMsg); + } } - Vector2 spawnPos = outpost.FindSpawnPos(i == 0 ? StartPosition : EndPosition, minSize, subDockingPortOffset - outpostDockingPortOffset, verticalMoveDir: 1); + Vector2 spawnPos = outpost.FindSpawnPos(i == 0 ? StartPosition : EndPosition, minSize, outpostDockingPortOffset != null ? subDockingPortOffset - outpostDockingPortOffset.Value : 0.0f, verticalMoveDir: 1); if (Type == LevelData.LevelType.Outpost) { spawnPos.Y = Math.Min(Size.Y - outpost.Borders.Height * 0.6f, spawnPos.Y + outpost.Borders.Height / 2); diff --git a/Barotrauma/BarotraumaShared/SharedSource/Map/LinkedSubmarine.cs b/Barotrauma/BarotraumaShared/SharedSource/Map/LinkedSubmarine.cs index 3b6aad96f..a1de6a144 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Map/LinkedSubmarine.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Map/LinkedSubmarine.cs @@ -357,7 +357,9 @@ namespace Barotrauma float closestDistance = 0.0f; foreach (DockingPort port in DockingPort.List) { - if (port.Item.Submarine != sub || port.IsHorizontal != linkedPort.IsHorizontal) { continue; } + if (port.Item.Submarine != sub) { continue; } + if (port.IsHorizontal != linkedPort.IsHorizontal) { continue; } + if (port.ForceDockingDirection != DockingPort.DirectionType.None && port.ForceDockingDirection == linkedPort.ForceDockingDirection) { continue; } float dist = Vector2.Distance(port.Item.WorldPosition, linkedPort.Item.WorldPosition); if (myPort == null || dist < closestDistance) { @@ -453,22 +455,22 @@ namespace Barotrauma saveElement.SetAttributeValue("pos", XMLExtensions.Vector2ToString(Position - Submarine.HiddenSubPosition)); - if (linkedTo.Any() || linkedToID.Any()) - { - var linkedPort = - linkedTo.FirstOrDefault(lt => (lt is Item item) && item.GetComponent() != null) ?? - FindEntityByID(linkedToID.First()) as MapEntity; - if (linkedPort != null) - { - saveElement.SetAttributeValue("linkedto", linkedPort.ID); - } - } } else { saveElement = new XElement("LinkedSubmarine"); sub.SaveToXElement(saveElement); } + if (linkedTo.Any() || linkedToID.Any()) + { + var linkedPort = + linkedTo.FirstOrDefault(lt => (lt is Item item) && item.GetComponent() != null) ?? + FindEntityByID(linkedToID.First()) as MapEntity; + if (linkedPort != null) + { + saveElement.SetAttributeValue("linkedto", linkedPort.ID); + } + } saveElement.SetAttributeValue("originallinkedto", originalLinkedPort != null ? originalLinkedPort.Item.ID : originalLinkedToID); saveElement.SetAttributeValue("originalmyport", originalMyPortID); diff --git a/Barotrauma/BarotraumaShared/SharedSource/Map/MapEntity.cs b/Barotrauma/BarotraumaShared/SharedSource/Map/MapEntity.cs index 7ab8451c7..e8489c131 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Map/MapEntity.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Map/MapEntity.cs @@ -338,7 +338,7 @@ namespace Barotrauma /// public virtual bool AddUpgrade(Upgrade upgrade, bool createNetworkEvent = false) { - if (this is Item item && !upgrade.Prefab.UpgradeCategories.Any(category => category.CanBeApplied(item, upgrade.Prefab))) + if (!upgrade.Prefab.UpgradeCategories.Any(category => category.CanBeApplied(this, upgrade.Prefab))) { return false; } @@ -359,16 +359,6 @@ namespace Barotrauma Upgrades.Add(upgrade); } - // not used anymore -#if SERVER - // if (createNetworkEvent) - // { - // if (this is IServerSerializable serializable) - // { - // GameMain.Server.CreateEntityEvent(serializable, new object[] { NetEntityEvent.Type.Upgrade, upgrade }); - // } - // } -#endif return true; } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Map/Structure.cs b/Barotrauma/BarotraumaShared/SharedSource/Map/Structure.cs index b973831de..600a2b731 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Map/Structure.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Map/Structure.cs @@ -168,6 +168,17 @@ namespace Barotrauma public ImmutableHashSet Tags => Prefab.Tags; +#if DEBUG + [Editable, Serialize("", IsPropertySaveable.Yes)] +#else + [Serialize("", IsPropertySaveable.Yes)] +#endif + public string SpecialTag + { + get; + set; + } + protected Color spriteColor; [Editable, Serialize("1.0,1.0,1.0,1.0", IsPropertySaveable.Yes)] public Color SpriteColor @@ -574,6 +585,11 @@ namespace Barotrauma int xsections = 1, ysections = 1; int width = rect.Width, height = rect.Height; + WallSection[] prevSections = null; + if (Sections != null) + { + prevSections = Sections.ToArray(); + } if (!HasBody) { if (FlippedX && IsHorizontal) @@ -657,6 +673,14 @@ namespace Barotrauma } } } + + if (prevSections != null && Sections.Length == prevSections.Length) + { + for (int i = 0; i < Sections.Length; i++) + { + Sections[i].damage = prevSections[i].damage; + } + } } private Rectangle GenerateMergedRect(List mergedSections) @@ -829,27 +853,33 @@ namespace Barotrauma public WallSection GetSection(int sectionIndex) { - if (sectionIndex < 0 || sectionIndex >= Sections.Length) return null; - + if (sectionIndex < 0 || sectionIndex >= Sections.Length) { return null; } return Sections[sectionIndex]; } public bool SectionBodyDisabled(int sectionIndex) { - if (sectionIndex < 0 || sectionIndex >= Sections.Length) return false; - + if (sectionIndex < 0 || sectionIndex >= Sections.Length) { return false; } return (Sections[sectionIndex].damage >= MaxHealth); } + public bool AllSectionBodiesDisabled() + { + for (int i = 0; i < Sections.Length; i++) + { + if (Sections[i].damage < MaxHealth) { return false; } + } + return true; + } + /// /// Sections that are leaking have a gap placed on them /// public bool SectionIsLeaking(int sectionIndex) { - if (sectionIndex < 0 || sectionIndex >= Sections.Length) return false; - - return (Sections[sectionIndex].damage >= MaxHealth * LeakThreshold); + if (sectionIndex < 0 || sectionIndex >= Sections.Length) { return false; } + return Sections[sectionIndex].damage >= MaxHealth * LeakThreshold; } public int SectionLength(int sectionIndex) @@ -1139,21 +1169,22 @@ namespace Barotrauma gapRect.Height += 20; bool horizontalGap = !IsHorizontal; + bool diagonalGap = false; if (Prefab.BodyRotation != 0.0f) { //rotation within a 90 deg sector (e.g. 100 -> 10, 190 -> 10, -10 -> 80) float sectorizedRotation = MathUtils.WrapAngleTwoPi(BodyRotation) % MathHelper.PiOver2; //diagonal if 30 < angle < 60 - bool diagonal = sectorizedRotation > MathHelper.Pi / 6 && sectorizedRotation < MathHelper.Pi / 3; + diagonalGap = sectorizedRotation > MathHelper.Pi / 6 && sectorizedRotation < MathHelper.Pi / 3; //gaps on the lower half of a diagonal wall are horizontal, ones on the upper half are vertical - if (diagonal) + if (diagonalGap) { horizontalGap = gapRect.Y - gapRect.Height / 2 < Position.Y; if (FlippedY) { horizontalGap = !horizontalGap; } } } - Sections[sectionIndex].gap = new Gap(gapRect, horizontalGap, Submarine); + Sections[sectionIndex].gap = new Gap(gapRect, horizontalGap, Submarine, isDiagonal: diagonalGap); //free the ID, because if we give gaps IDs we have to make sure they always match between the clients and the server and //that clients create them in the correct order along with every other entity created/removed during the round diff --git a/Barotrauma/BarotraumaShared/SharedSource/Map/StructurePrefab.cs b/Barotrauma/BarotraumaShared/SharedSource/Map/StructurePrefab.cs index 30c8ae40b..d13d4216f 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Map/StructurePrefab.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Map/StructurePrefab.cs @@ -271,20 +271,17 @@ namespace Barotrauma tags.Add("wall".ToIdentifier()); } - if (Description.IsNullOrEmpty()) + if (!descriptionIdentifier.IsEmpty) { - if (!descriptionIdentifier.IsEmpty) - { - Description = TextManager.Get($"EntityDescription.{descriptionIdentifier}"); - } - else if (nameIdentifier.IsEmpty) - { - Description = TextManager.Get($"EntityDescription.{Identifier}"); - } - else - { - Description = TextManager.Get($"EntityDescription.{nameIdentifier}"); - } + Description = TextManager.Get($"EntityDescription.{descriptionIdentifier}").Fallback(Description); + } + else if (nameIdentifier.IsEmpty) + { + Description = TextManager.Get($"EntityDescription.{Identifier}").Fallback(Description); + } + else + { + Description = TextManager.Get($"EntityDescription.{nameIdentifier}").Fallback(Description); } //backwards compatibility diff --git a/Barotrauma/BarotraumaShared/SharedSource/Map/Submarine.cs b/Barotrauma/BarotraumaShared/SharedSource/Map/Submarine.cs index b5f2d85d0..50e3f4507 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Map/Submarine.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Map/Submarine.cs @@ -187,7 +187,6 @@ namespace Barotrauma if (structure.Submarine != this || !structure.HasBody || structure.Indestructible) { continue; } realWorldCrushDepth = Math.Min(structure.CrushDepth, realWorldCrushDepth.Value); } - realWorldCrushDepth *= Info.GetRealWorldCrushDepthMultiplier(); } return realWorldCrushDepth.Value; } @@ -452,10 +451,27 @@ namespace Barotrauma verticalMoveDir = Math.Sign(verticalMoveDir); //do a raycast towards the top/bottom of the level depending on direction Vector2 potentialPos = new Vector2(spawnPos.X, verticalMoveDir > 0 ? Level.Loaded.Size.Y : 0); - if (PickBody(ConvertUnits.ToSimUnits(spawnPos), ConvertUnits.ToSimUnits(potentialPos), collisionCategory: Physics.CollisionLevel | Physics.CollisionWall) != null) + + //3 raycasts (left, middle and right side of the sub, so we don't accidentally raycast up a passage too narrow for the sub) + for (int x = -1; x <= 1; x++) { - //if the raycast hit a wall, attempt to place the spawnpos there - potentialPos.Y = ConvertUnits.ToDisplayUnits(LastPickedPosition.Y) - 10; + Vector2 xOffset = Vector2.UnitX * minWidth / 2 * x; + if (PickBody( + ConvertUnits.ToSimUnits(spawnPos + xOffset), + ConvertUnits.ToSimUnits(potentialPos + xOffset), + collisionCategory: Physics.CollisionLevel | Physics.CollisionWall) != null) + { + int offsetFromWall = 10 * -verticalMoveDir; + //if the raycast hit a wall, attempt to place the spawnpos there + if (verticalMoveDir > 0) + { + potentialPos.Y = Math.Min(potentialPos.Y, ConvertUnits.ToDisplayUnits(LastPickedPosition.Y) + offsetFromWall); + } + else + { + potentialPos.Y = Math.Max(potentialPos.Y, ConvertUnits.ToDisplayUnits(LastPickedPosition.Y) + offsetFromWall); + } + } } //step away from the top/bottom of the level, or from whatever wall the raycast hit, diff --git a/Barotrauma/BarotraumaShared/SharedSource/Map/SubmarineBody.cs b/Barotrauma/BarotraumaShared/SharedSource/Map/SubmarineBody.cs index f201efb47..b8b2fd544 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Map/SubmarineBody.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Map/SubmarineBody.cs @@ -505,7 +505,6 @@ namespace Barotrauma if (wall.Submarine != submarine) { continue; } float wallCrushDepth = wall.CrushDepth; - if (submarine.Info.SubmarineClass == SubmarineClass.DeepDiver) { wallCrushDepth *= 1.2f; } float pastCrushDepth = submarine.RealWorldDepth - wallCrushDepth; if (pastCrushDepth > 0) { @@ -587,9 +586,13 @@ namespace Barotrauma newHull = Hull.FindHull(targetPos, null); } - var gaps = newHull?.ConnectedGaps ?? Gap.GapList.Where(g => g.Submarine == submarine); - Gap adjacentGap = Gap.FindAdjacent(gaps, ConvertUnits.ToDisplayUnits(points[0]), 200.0f); - if (adjacentGap == null) { return true; } + //if all the bodies of a wall have been disabled, we don't need to care about gaps (can always pass through) + if (!(contact.FixtureA.UserData is Structure wall) || !wall.AllSectionBodiesDisabled()) + { + var gaps = newHull?.ConnectedGaps ?? Gap.GapList.Where(g => g.Submarine == submarine); + Gap adjacentGap = Gap.FindAdjacent(gaps, ConvertUnits.ToDisplayUnits(points[0]), 200.0f); + if (adjacentGap == null) { return true; } + } if (newHull != null) { diff --git a/Barotrauma/BarotraumaShared/SharedSource/Map/SubmarineInfo.cs b/Barotrauma/BarotraumaShared/SharedSource/Map/SubmarineInfo.cs index 898f27b77..426941fe8 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Map/SubmarineInfo.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Map/SubmarineInfo.cs @@ -24,7 +24,7 @@ namespace Barotrauma } public enum SubmarineType { Player, Outpost, OutpostModule, Wreck, BeaconStation, EnemySubmarine, Ruin } - public enum SubmarineClass { Undefined, Scout, Attack, Transport, DeepDiver } + public enum SubmarineClass { Undefined, Scout, Attack, Transport } partial class SubmarineInfo : IDisposable { @@ -49,6 +49,12 @@ namespace Barotrauma } public CrewExperienceLevel RecommendedCrewExperience; + public int Tier + { + get; + set; + } + /// /// A random int that gets assigned when saving the sub. Used in mp campaign to verify that sub files match /// @@ -305,6 +311,7 @@ namespace Barotrauma RecommendedCrewExperience = original.RecommendedCrewExperience; RecommendedCrewSizeMin = original.RecommendedCrewSizeMin; RecommendedCrewSizeMax = original.RecommendedCrewSizeMax; + Tier = original.Tier; IsManuallyOutfitted = original.IsManuallyOutfitted; Tags = original.Tags; if (original.OutpostModuleInfo != null) @@ -386,6 +393,7 @@ namespace Barotrauma { Enum.TryParse(recommendedCrewExperience.Value, ignoreCase: true, out RecommendedCrewExperience); } + Tier = SubmarineElement.GetAttributeInt("tier", GetDefaultTier(Price)); if (SubmarineElement?.Attribute("type") != null) { @@ -407,7 +415,13 @@ namespace Barotrauma { if (SubmarineElement?.Attribute("class") != null) { - if (Enum.TryParse(SubmarineElement.GetAttributeString("class", "Undefined"), out SubmarineClass submarineClass)) + string classStr = SubmarineElement.GetAttributeString("class", "Undefined"); + if (classStr == "DeepDiver") + { + //backwards compatibility + SubmarineClass = SubmarineClass.Scout; + } + else if (Enum.TryParse(classStr, out SubmarineClass submarineClass)) { SubmarineClass = submarineClass; } @@ -538,25 +552,9 @@ namespace Barotrauma { realWorldCrushDepth = Level.DefaultRealWorldCrushDepth; } - realWorldCrushDepth *= GetRealWorldCrushDepthMultiplier(); return realWorldCrushDepth; } - /// - /// Based on - /// - public float GetRealWorldCrushDepthMultiplier() - { - if (SubmarineClass == SubmarineClass.DeepDiver) - { - return 1.2f; - } - else - { - return 1.0f; - } - } - //saving/loading ---------------------------------------------------- public void SaveAs(string filePath, System.IO.MemoryStream previewImage = null) { @@ -691,7 +689,7 @@ namespace Barotrauma System.IO.Stream stream; try { - stream = SaveUtil.DecompressFiletoStream(file); + stream = SaveUtil.DecompressFileToStream(file); } catch (System.IO.FileNotFoundException e) { @@ -748,5 +746,7 @@ namespace Barotrauma return doc; } + + public static int GetDefaultTier(int price) => price > 20000 ? 3 : price > 10000 ? 2 : 1; } -} \ No newline at end of file +} diff --git a/Barotrauma/BarotraumaShared/SharedSource/NetStructBitField.cs b/Barotrauma/BarotraumaShared/SharedSource/NetStructBitField.cs index 964a4a9ca..4885dd27a 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/NetStructBitField.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/NetStructBitField.cs @@ -83,7 +83,7 @@ namespace Barotrauma foreach (byte b in Buffer) { - msg.Write(b); + msg.WriteByte(b); } Dispose(); diff --git a/Barotrauma/BarotraumaShared/SharedSource/Networking/BanList.cs b/Barotrauma/BarotraumaShared/SharedSource/Networking/BanList.cs index 12564a692..e08ff3ca1 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Networking/BanList.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Networking/BanList.cs @@ -1,4 +1,5 @@ -using System; +#nullable enable +using System; using System.Collections.Generic; using System.Linq; diff --git a/Barotrauma/BarotraumaShared/SharedSource/Networking/ChildServerRelay.cs b/Barotrauma/BarotraumaShared/SharedSource/Networking/ChildServerRelay.cs index 144a567ca..8cb93bbb2 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Networking/ChildServerRelay.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Networking/ChildServerRelay.cs @@ -98,7 +98,7 @@ namespace Barotrauma.Networking Task readTask = readStream?.ReadAsync(readTempBytes, 0, readTempBytes.Length, readCancellationToken.Token); if (readTask is null) { return -1; } - TimeSpan timeOut = TimeSpan.FromMilliseconds(100); + int timeOutMilliseconds = 100; for (int i = 0; i < 150; i++) { if (shutDown) @@ -106,12 +106,9 @@ namespace Barotrauma.Networking readCancellationToken?.Cancel(); return -1; } - - // BUG workaround for crash when closing the server under .NET 6.0, not sure if this is the proper way to fix it but it prevents it from crashing the client. - Markus -#if NET6_0 try { - if (readTask.IsCompleted || readTask.Wait(100, readCancellationToken.Token)) + if (readTask.IsCompleted || readTask.Wait(timeOutMilliseconds, readCancellationToken.Token)) { break; } @@ -120,12 +117,6 @@ namespace Barotrauma.Networking { return -1; } -#else - if (readTask.IsCompleted || readTask.Wait(timeOut)) - { - break; - } -#endif } if (readTask.Status != TaskStatus.RanToCompletion) diff --git a/Barotrauma/BarotraumaShared/SharedSource/Networking/Client.cs b/Barotrauma/BarotraumaShared/SharedSource/Networking/Client.cs index ef9030eea..1d7e30e5e 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Networking/Client.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Networking/Client.cs @@ -177,8 +177,6 @@ namespace Barotrauma.Networking } public bool HasSpawned; //has the client spawned as a character during the current round - private readonly List kickVoters; - public HashSet GivenAchievements = new HashSet(); public ClientPermissions Permissions = ClientPermissions.None; @@ -186,11 +184,6 @@ namespace Barotrauma.Networking private readonly object[] votes; - public int KickVoteCount - { - get { return kickVoters.Count; } - } - partial void InitProjSpecific(); partial void DisposeProjSpecific(); public Client(string name, byte sessionId) @@ -198,8 +191,6 @@ namespace Barotrauma.Networking this.Name = name; this.SessionId = sessionId; - kickVoters = new List(); - votes = new object[Enum.GetNames(typeof(VoteType)).Length]; InitProjSpecific(); @@ -221,53 +212,22 @@ namespace Barotrauma.Networking { votes[i] = null; } - - kickVoters.Clear(); } - - public void AddKickVote(Client voter) - { - if (voter != null && !kickVoters.Contains(voter)) { kickVoters.Add(voter); } - } - - - public void RemoveKickVote(Client voter) - { - kickVoters.Remove(voter); - } - - public bool HasKickVoteFrom(Client voter) - { - return kickVoters.Contains(voter); - } - - public bool HasKickVoteFromSessionId(int id) - { - return kickVoters.Any(k => k.SessionId == id); - } - + public bool SessionOrAccountIdMatches(string userId) => (AccountId.IsSome() && Networking.AccountId.Parse(userId) == AccountId) || (byte.TryParse(userId, out byte sessionId) && SessionId == sessionId); - public static void UpdateKickVotes(IReadOnlyList connectedClients) - { - foreach (Client client in connectedClients) - { - client.kickVoters.RemoveAll(voter => !connectedClients.Contains(voter)); - } - } - public void WritePermissions(IWriteMessage msg) { - msg.Write(SessionId); + msg.WriteByte(SessionId); msg.WriteRangedInteger((int)Permissions, 0, (int)ClientPermissions.All); if (HasPermission(ClientPermissions.ConsoleCommands)) { - msg.Write((UInt16)PermittedConsoleCommands.Count); + msg.WriteUInt16((UInt16)PermittedConsoleCommands.Count); foreach (DebugConsole.Command command in PermittedConsoleCommands) { - msg.Write(command.names[0]); + msg.WriteString(command.names[0]); } } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Networking/INetSerializableStruct.cs b/Barotrauma/BarotraumaShared/SharedSource/Networking/INetSerializableStruct.cs index 767c57723..b8e4460b7 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Networking/INetSerializableStruct.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Networking/INetSerializableStruct.cs @@ -325,9 +325,14 @@ namespace Barotrauma Range range = GetEnumRange(type); int enumIndex = bitField.ReadInteger(range.Start, range.End); + if (typeof(T).GetCustomAttribute() != null) + { + return (T)(object)enumIndex; + } + foreach (T e in (T[])Enum.GetValues(type)) { - if ((int)Convert.ChangeType(e, e.GetTypeCode()) == enumIndex) { return e; } + if (((int)(object)e) == enumIndex) { return e; } } throw new InvalidOperationException($"An enum {type} with value {enumIndex} could not be found in {nameof(ReadEnum)}"); @@ -388,18 +393,18 @@ 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 byte ReadByte(IReadMessage inc, NetworkSerialize attribute, IReadableBitField bitField) => inc.ReadByte(); - private static void WriteByte(byte b, NetworkSerialize attribute, IWriteMessage msg, IWritableBitField bitField) { msg.Write(b); } + private static void WriteByte(byte b, NetworkSerialize attribute, IWriteMessage msg, IWritableBitField 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.Write(b); } + private static void WriteUInt16(ushort b, NetworkSerialize attribute, IWriteMessage msg, IWritableBitField 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.Write(b); } + private static void WriteInt16(short b, NetworkSerialize attribute, IWriteMessage msg, IWritableBitField 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.Write(b); } + private static void WriteUInt32(uint b, NetworkSerialize attribute, IWriteMessage msg, IWritableBitField bitField) { msg.WriteUInt32(b); } private static int ReadInt32(IReadMessage inc, NetworkSerialize attribute, IReadableBitField bitField) { @@ -421,14 +426,14 @@ namespace Barotrauma return; } - msg.Write(i); + 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.Write(b); } + private static void WriteUInt64(ulong b, NetworkSerialize attribute, IWriteMessage msg, IWritableBitField 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.Write(b); } + private static void WriteInt64(long b, NetworkSerialize attribute, IWriteMessage msg, IWritableBitField bitField) { msg.WriteInt64(b); } private static float ReadSingle(IReadMessage inc, NetworkSerialize attribute, IReadableBitField bitField) { @@ -450,17 +455,17 @@ namespace Barotrauma return; } - msg.Write(f); + 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.Write(b); } + private static void WriteDouble(double b, NetworkSerialize attribute, IWriteMessage msg, IWritableBitField 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.Write(b); } + private static void WriteString(string b, NetworkSerialize attribute, IWriteMessage msg, IWritableBitField 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.Write(b); } + private static void WriteIdentifier(Identifier b, NetworkSerialize attribute, IWriteMessage msg, IWritableBitField bitField) { msg.WriteIdentifier(b); } private static AccountId ReadAccountId(IReadMessage inc, NetworkSerialize attribute, IReadableBitField bitField) { @@ -472,7 +477,7 @@ namespace Barotrauma private static void WriteAccountId(AccountId accountId, NetworkSerialize attribute, IWriteMessage msg, IWritableBitField bitField) { - msg.Write(accountId.StringRepresentation); + msg.WriteString(accountId.StringRepresentation); } private static Color ReadColor(IReadMessage inc, NetworkSerialize attribute, IReadableBitField bitField) => attribute.IncludeColorAlpha ? inc.ReadColorR8G8B8A8() : inc.ReadColorR8G8B8(); @@ -519,7 +524,7 @@ namespace Barotrauma private static bool TryFindBehavior(out ReadWriteBehavior behavior) where T : notnull { bool found = TryFindBehavior(typeof(T), out var bhvr); - behavior = (ReadWriteBehavior)bhvr; + behavior = found ? (ReadWriteBehavior)bhvr : default; return found; } @@ -589,8 +594,8 @@ namespace Barotrauma return array; bool HasAttribute(MemberInfo info) => (info.GetCustomAttribute() ?? type.GetCustomAttribute()) != null; - - bool NotStatic(MemberInfo info) + + static bool NotStatic(MemberInfo info) => info switch { PropertyInfo property => property.GetGetMethod() is { IsStatic: false }, @@ -656,7 +661,7 @@ namespace Barotrauma /// Using or will make the field or property optional. /// /// - interface INetSerializableStruct + internal interface INetSerializableStruct { /// /// Deserializes a network message into a struct. @@ -743,7 +748,7 @@ namespace Barotrauma IWriteMessage structWriteMsg = new WriteOnlyMessage(); WriteInternal(structWriteMsg, bitField); bitField.WriteToMessage(msg); - msg.Write(structWriteMsg.Buffer, 0, structWriteMsg.LengthBytes); + msg.WriteBytes(structWriteMsg.Buffer, 0, structWriteMsg.LengthBytes); } public void WriteInternal(IWriteMessage msg, IWritableBitField bitField) @@ -757,25 +762,4 @@ namespace Barotrauma } } } - - static class WriteOnlyMessageExtensions - { -#if CLIENT - public static IWriteMessage WithHeader(this IWriteMessage msg, ClientPacketHeader header) - { - msg.Write((byte)header); - return msg; - } -#elif SERVER - public static IWriteMessage WithHeader(this IWriteMessage msg, ServerPacketHeader header) - { - msg.Write((byte)header); - return msg; - } -#endif - public static void Write(this IWriteMessage msg, INetSerializableStruct serializableStruct) - { - serializableStruct.Write(msg); - } - } } \ No newline at end of file diff --git a/Barotrauma/BarotraumaShared/SharedSource/Networking/NetBufferExtensions.cs b/Barotrauma/BarotraumaShared/SharedSource/Networking/NetBufferExtensions.cs deleted file mode 100644 index 0e407cc0c..000000000 --- a/Barotrauma/BarotraumaShared/SharedSource/Networking/NetBufferExtensions.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace Barotrauma.Networking -{ - static class NetBufferExtensions - { - //public static void WriteEnum(this NetBuffer buffer, Enum value) - //{ - // buffer.WriteRangedInteger(0, Enum.GetValues(value.GetType()).Length - 1, Convert.ToInt32(value)); - //} - - //public static TEnum ReadEnum(this NetBuffer buffer) - //{ - // return (TEnum)(object)buffer.ReadRangedInteger(0, Enum.GetValues(typeof(TEnum)).Length - 1); - //} - } -} diff --git a/Barotrauma/BarotraumaShared/SharedSource/Networking/NetEntityEvent/NetEntityEventManager.cs b/Barotrauma/BarotraumaShared/SharedSource/Networking/NetEntityEvent/NetEntityEventManager.cs index 0b154b322..c88d1c267 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Networking/NetEntityEvent/NetEntityEventManager.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Networking/NetEntityEvent/NetEntityEventManager.cs @@ -37,7 +37,7 @@ namespace Barotrauma.Networking //write an empty event to avoid messing up IDs //(otherwise the clients might read the next event in the message and think its ID //is consecutive to the previous one, even though we skipped over this broken event) - tempBuffer.Write(Entity.NullEntityID); + tempBuffer.WriteUInt16(Entity.NullEntityID); eventCount++; continue; } @@ -49,9 +49,9 @@ namespace Barotrauma.Networking break; } - tempBuffer.Write(e.EntityID); + tempBuffer.WriteUInt16(e.EntityID); tempBuffer.WriteVariableUInt32((uint)tempEventBuffer.LengthBytes); - tempBuffer.Write(tempEventBuffer.Buffer, 0, tempEventBuffer.LengthBytes); + tempBuffer.WriteBytes(tempEventBuffer.Buffer, 0, tempEventBuffer.LengthBytes); sentEvents.Add(e); eventCount++; @@ -60,9 +60,9 @@ namespace Barotrauma.Networking if (eventCount > 0) { msg.WritePadBits(); - msg.Write(eventsToSync[0].ID); - msg.Write((byte)eventCount); - msg.Write(tempBuffer.Buffer, 0, tempBuffer.LengthBytes); + msg.WriteUInt16(eventsToSync[0].ID); + msg.WriteByte((byte)eventCount); + msg.WriteBytes(tempBuffer.Buffer, 0, tempBuffer.LengthBytes); } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Networking/NetIdUtils.cs b/Barotrauma/BarotraumaShared/SharedSource/Networking/NetIdUtils.cs index be2a6d9df..e75202086 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Networking/NetIdUtils.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Networking/NetIdUtils.cs @@ -28,6 +28,19 @@ namespace Barotrauma.Networking public static bool IdMoreRecentOrMatches(ushort newId, ushort oldId) => !IdMoreRecent(oldId, newId); + /// + /// Returns some ID that is older than the input ID. There are no guarantees + /// regarding its relation to values other than the input. + /// + public static ushort GetIdOlderThan(ushort id) +#if DEBUG + // Debug implementation has some RNG to discourage bad assumptions about the return value + => unchecked((ushort)(id - 1 - Rand.Int(500, sync: Rand.RandSync.Unsynced))); +#else + // Release implementation favors performance + => unchecked((ushort)(id - 1)); +#endif + public static ushort Difference(ushort id1, ushort id2) { int diff = id2 > id1 ? id2 - id1 : id1 - id2; diff --git a/Barotrauma/BarotraumaShared/SharedSource/Networking/OrderChatMessage.cs b/Barotrauma/BarotraumaShared/SharedSource/Networking/OrderChatMessage.cs index af78cac5f..d4b897c9c 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Networking/OrderChatMessage.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Networking/OrderChatMessage.cs @@ -47,32 +47,32 @@ namespace Barotrauma.Networking public static void WriteOrder(IWriteMessage msg, Order order, Character targetCharacter, bool isNewOrder) { - msg.Write(order.Prefab.Identifier); - msg.Write(targetCharacter == null ? (UInt16)0 : targetCharacter.ID); - msg.Write(order.TargetSpatialEntity is Entity ? (order.TargetEntity as Entity).ID : (UInt16)0); + msg.WriteIdentifier(order.Prefab.Identifier); + msg.WriteUInt16(targetCharacter == null ? (UInt16)0 : targetCharacter.ID); + msg.WriteUInt16(order.TargetSpatialEntity is Entity ? (order.TargetEntity as Entity).ID : (UInt16)0); // The option of a Dismiss order is written differently so we know what order we target // now that the game supports multiple current orders simultaneously if (!order.IsDismissal) { - msg.Write((byte)order.Options.IndexOf(order.Option)); + msg.WriteByte((byte)order.Options.IndexOf(order.Option)); } else { if (order.Option != Identifier.Empty) { - msg.Write(true); + msg.WriteBoolean(true); string[] dismissedOrder = order.Option.Value.Split('.'); - msg.Write((byte)dismissedOrder.Length); + msg.WriteByte((byte)dismissedOrder.Length); if (dismissedOrder.Length > 0) { Identifier dismissedOrderIdentifier = dismissedOrder[0].ToIdentifier(); var orderPrefab = OrderPrefab.Prefabs[dismissedOrderIdentifier]; - msg.Write(dismissedOrderIdentifier); + msg.WriteIdentifier(dismissedOrderIdentifier); if (dismissedOrder.Length > 1) { Identifier dismissedOrderOption = dismissedOrder[1].ToIdentifier(); - msg.Write((byte)orderPrefab.Options.IndexOf(dismissedOrderOption)); + msg.WriteByte((byte)orderPrefab.Options.IndexOf(dismissedOrderOption)); } } } @@ -80,29 +80,29 @@ namespace Barotrauma.Networking { // If the order option is not specified for a Dismiss order, // we dismiss all current orders for the character - msg.Write(false); + msg.WriteBoolean(false); } } - msg.Write((byte)order.ManualPriority); - msg.Write((byte)order.TargetType); + msg.WriteByte((byte)order.ManualPriority); + msg.WriteByte((byte)order.TargetType); if (order.TargetType == Order.OrderTargetType.Position && order.TargetSpatialEntity is OrderTarget orderTarget) { - msg.Write(true); - msg.Write(orderTarget.Position.X); - msg.Write(orderTarget.Position.Y); - msg.Write(orderTarget.Hull == null ? (UInt16)0 : orderTarget.Hull.ID); + msg.WriteBoolean(true); + msg.WriteSingle(orderTarget.Position.X); + msg.WriteSingle(orderTarget.Position.Y); + msg.WriteUInt16(orderTarget.Hull == null ? (UInt16)0 : orderTarget.Hull.ID); } else { - msg.Write(false); + msg.WriteBoolean(false); if (order.TargetType == Order.OrderTargetType.WallSection) { - msg.Write((byte)(order.WallSectionIndex ?? 0)); + msg.WriteByte((byte)(order.WallSectionIndex ?? 0)); } } - msg.Write(isNewOrder); + msg.WriteBoolean(isNewOrder); } private void WriteOrder(IWriteMessage msg) diff --git a/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/Message/IWriteMessage.cs b/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/Message/IWriteMessage.cs index 65377a23f..b5721153d 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/Message/IWriteMessage.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/Message/IWriteMessage.cs @@ -4,27 +4,27 @@ namespace Barotrauma.Networking { interface IWriteMessage { - void Write(bool val); + void WriteBoolean(bool val); void WritePadBits(); - void Write(byte val); - void Write(Int16 val); - void Write(UInt16 val); - void Write(Int32 val); - void Write(UInt32 val); - void Write(Int64 val); - void Write(UInt64 val); - void Write(Single val); - void Write(Double val); + void WriteByte(byte val); + void WriteInt16(Int16 val); + void WriteUInt16(UInt16 val); + void WriteInt32(Int32 val); + void WriteUInt32(UInt32 val); + void WriteInt64(Int64 val); + void WriteUInt64(UInt64 val); + void WriteSingle(Single val); + void WriteDouble(Double val); void WriteColorR8G8B8(Microsoft.Xna.Framework.Color val); void WriteColorR8G8B8A8(Microsoft.Xna.Framework.Color val); void WriteVariableUInt32(UInt32 val); - void Write(string val); - void Write(Identifier val); + void WriteString(string val); + void WriteIdentifier(Identifier val); void WriteRangedInteger(int val, int min, int max); void WriteRangedSingle(Single val, Single min, Single max, int bitCount); - void Write(byte[] val, int startIndex, int length); + void WriteBytes(byte[] val, int startIndex, int length); - void PrepareForSending(ref byte[] outBuf, bool compressPastThreshold, out bool isCompressed, out int outLength); + byte[] PrepareForSending(bool compressPastThreshold, out bool isCompressed, out int outLength); int BitPosition { get; set; } int BytePosition { get; } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/Message/Message.cs b/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/Message/Message.cs index a05e67a59..d4330e11e 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/Message/Message.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/Message/Message.cs @@ -1,7 +1,6 @@ using Lidgren.Network; using System; -using System.Collections.Generic; -using Barotrauma.IO; +using System.IO; using System.IO.Compression; using System.Runtime.InteropServices; using System.Text; @@ -58,7 +57,7 @@ namespace Barotrauma.Networking bool testVal = MsgReader.ReadBoolean(buf, ref resetPos); if (testVal != val || resetPos != bitPos) { - DebugConsole.ThrowError("Boolean written incorrectly! " + testVal + ", " + val + "; " + resetPos + ", " + bitPos); + DebugConsole.ThrowError($"Boolean written incorrectly! {testVal}, {val}; {resetPos}, {bitPos}"); } #endif } @@ -125,7 +124,7 @@ namespace Barotrauma.Networking SingleUIntUnion su; su.UIntValue = 0; // must initialize every member of the union to avoid warning su.SingleValue = val; - + EnsureBufferSize(ref buf, bitPos + 32); NetBitWriter.WriteUInt32(su.UIntValue, 32, buf, bitPos); @@ -140,50 +139,48 @@ namespace Barotrauma.Networking WriteBytes(ref buf, ref bitPos, bytes, 0, 8); } - internal static void WriteColorR8G8B8(ref byte[] buf, ref int bitPos, Microsoft.Xna.Framework.Color val) + internal static void WriteColorR8G8B8(ref byte[] buf, ref int bitPos, 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); } - - internal static void WriteColorR8G8B8A8(ref byte[] buf, ref int bitPos, Microsoft.Xna.Framework.Color val) + + internal static void WriteColorR8G8B8A8(ref byte[] buf, ref int bitPos, 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); } - + internal static void Write(ref byte[] buf, ref int bitPos, string val) { if (string.IsNullOrEmpty(val)) { - WriteVariableUInt32(ref buf, ref bitPos, (uint)0); + WriteVariableUInt32(ref buf, ref bitPos, 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); } - internal static int WriteVariableUInt32(ref byte[] buf, ref int bitPos, uint value) + internal static void WriteVariableUInt32(ref byte[] buf, ref int bitPos, uint value) { - int retval = 1; - uint remainingValue = (uint)value; + uint remainingValue = value; while (remainingValue >= 0x80) { Write(ref buf, ref bitPos, (byte)(remainingValue | 0x80)); - remainingValue = remainingValue >> 7; - retval++; + remainingValue >>= 7; } + Write(ref buf, ref bitPos, (byte)remainingValue); - return retval; } internal static void WriteRangedInteger(ref byte[] buf, ref int bitPos, int val, int min, int max) @@ -206,7 +203,7 @@ namespace Barotrauma.Networking EnsureBufferSize(ref buf, bitPos + numberOfBits); - NetBitWriter.WriteUInt32((UInt32)((float)maxVal * unit), numberOfBits, buf, bitPos); + NetBitWriter.WriteUInt32((UInt32)(maxVal * unit), numberOfBits, buf, bitPos); bitPos += numberOfBits; } @@ -225,9 +222,10 @@ namespace Barotrauma.Networking buf = new byte[byteLen + MsgConstants.BufferOverAllocateAmount]; return; } + if (buf.Length < byteLen) { - Array.Resize(ref buf, byteLen + MsgConstants.BufferOverAllocateAmount); + Array.Resize(ref buf, byteLen + MsgConstants.BufferOverAllocateAmount); } } } @@ -241,7 +239,7 @@ namespace Barotrauma.Networking return retval > 0; } - internal static void ReadPadBits(byte[] buf, ref int bitPos) + internal static void ReadPadBits(ref int bitPos) { int bitOffset = bitPos % 8; bitPos += (8 - bitOffset) % 8; @@ -326,15 +324,15 @@ namespace Barotrauma.Networking return BitConverter.ToDouble(bytes, 0); } - internal static Microsoft.Xna.Framework.Color ReadColorR8G8B8(byte[] buf, ref int bitPos) + internal static Color ReadColorR8G8B8(byte[] buf, ref int bitPos) { byte r = ReadByte(buf, ref bitPos); byte g = ReadByte(buf, ref bitPos); byte b = ReadByte(buf, ref bitPos); return new Color(r, g, b, (byte)255); } - - internal static Microsoft.Xna.Framework.Color ReadColorR8G8B8A8(byte[] buf, ref int bitPos) + + internal static Color ReadColorR8G8B8A8(byte[] buf, ref int bitPos) { byte r = ReadByte(buf, ref bitPos); byte g = ReadByte(buf, ref bitPos); @@ -354,8 +352,7 @@ namespace Barotrauma.Networking byte chunk = ReadByte(buf, ref bitPos); result |= (chunk & 0x7f) << shift; shift += 7; - if ((chunk & 0x80) == 0) - return (uint)result; + if ((chunk & 0x80) == 0) { return (uint)result; } } // ouch; failed to find enough bytes; malformed variable length number? @@ -378,23 +375,23 @@ namespace Barotrauma.Networking if ((bitPos & 7) == 0) { // read directly - string retval = System.Text.Encoding.UTF8.GetString(buf, bitPos >> 3, byteLen); + string retval = Encoding.UTF8.GetString(buf, bitPos >> 3, byteLen); bitPos += (8 * byteLen); return retval; } byte[] bytes = ReadBytes(buf, ref bitPos, byteLen); - return System.Text.Encoding.UTF8.GetString(bytes, 0, bytes.Length); + return Encoding.UTF8.GetString(bytes, 0, bytes.Length); } internal static int ReadRangedInteger(byte[] buf, ref int bitPos, int min, int max) { - uint range = (uint)(max - min); - int numBits = NetUtility.BitsToHoldUInt(range); + uint range = (uint)(max - min); + int numBits = NetUtility.BitsToHoldUInt(range); - uint rvalue = NetBitWriter.ReadUInt32(buf, numBits, bitPos); + uint rvalue = NetBitWriter.ReadUInt32(buf, numBits, bitPos); bitPos += numBits; - + return (int)(min + rvalue); } @@ -403,51 +400,33 @@ namespace Barotrauma.Networking int maxInt = (1 << bitCount) - 1; int intVal = ReadRangedInteger(buf, ref bitPos, 0, maxInt); Single range = max - min; - return min + (range * ((Single)intVal) / ((Single)maxInt)); + return min + range * intVal / maxInt; } internal static byte[] ReadBytes(byte[] buf, ref int bitPos, int numberOfBytes) { byte[] retval = new byte[numberOfBytes]; NetBitWriter.ReadBytes(buf, numberOfBytes, bitPos, retval, 0); - bitPos += (8 * numberOfBytes); + bitPos += 8 * numberOfBytes; return retval; } } - class WriteOnlyMessage : IWriteMessage + internal sealed class WriteOnlyMessage : IWriteMessage { private byte[] buf = new byte[MsgConstants.InitialBufferSize]; - private int seekPos = 0; - private int lengthBits = 0; + private int seekPos; + private int lengthBits; public int BitPosition { - get - { - return seekPos; - } - set - { - seekPos = value; - } + get => seekPos; + set => seekPos = value; } - public int BytePosition - { - get - { - return seekPos / 8; - } - } + public int BytePosition => seekPos / 8; - public byte[] Buffer - { - get - { - return buf; - } - } + public byte[] Buffer => buf; public int LengthBits { @@ -464,15 +443,9 @@ namespace Barotrauma.Networking } } - public int LengthBytes - { - get - { - return (LengthBits + 7) / 8; - } - } + public int LengthBytes => (LengthBits + 7) / 8; - public void Write(bool val) + public void WriteBoolean(bool val) { MsgWriter.Write(ref buf, ref seekPos, val); } @@ -482,47 +455,47 @@ namespace Barotrauma.Networking MsgWriter.WritePadBits(ref buf, ref seekPos); } - public void Write(byte val) + public void WriteByte(byte val) { MsgWriter.Write(ref buf, ref seekPos, val); } - public void Write(UInt16 val) + public void WriteUInt16(UInt16 val) { MsgWriter.Write(ref buf, ref seekPos, val); } - public void Write(Int16 val) + public void WriteInt16(Int16 val) { MsgWriter.Write(ref buf, ref seekPos, val); } - public void Write(UInt32 val) + public void WriteUInt32(UInt32 val) { MsgWriter.Write(ref buf, ref seekPos, val); } - public void Write(Int32 val) + public void WriteInt32(Int32 val) { MsgWriter.Write(ref buf, ref seekPos, val); } - public void Write(UInt64 val) + public void WriteUInt64(UInt64 val) { MsgWriter.Write(ref buf, ref seekPos, val); } - public void Write(Int64 val) + public void WriteInt64(Int64 val) { MsgWriter.Write(ref buf, ref seekPos, val); } - public void Write(Single val) + public void WriteSingle(Single val) { MsgWriter.Write(ref buf, ref seekPos, val); } - public void Write(Double val) + public void WriteDouble(Double val) { MsgWriter.Write(ref buf, ref seekPos, val); } @@ -531,7 +504,7 @@ namespace Barotrauma.Networking { MsgWriter.WriteColorR8G8B8(ref buf, ref seekPos, val); } - + public void WriteColorR8G8B8A8(Color val) { MsgWriter.WriteColorR8G8B8A8(ref buf, ref seekPos, val); @@ -542,14 +515,14 @@ namespace Barotrauma.Networking MsgWriter.WriteVariableUInt32(ref buf, ref seekPos, val); } - public void Write(String val) + public void WriteString(String val) { MsgWriter.Write(ref buf, ref seekPos, val); } - public void Write(Identifier val) + public void WriteIdentifier(Identifier val) { - Write(val.Value); + WriteString(val.Value); } public void WriteRangedInteger(int val, int min, int max) @@ -562,85 +535,67 @@ namespace Barotrauma.Networking MsgWriter.WriteRangedSingle(ref buf, ref seekPos, val, min, max, bitCount); } - public void Write(byte[] val, int startPos, int length) + public void WriteBytes(byte[] val, int startPos, int length) { MsgWriter.WriteBytes(ref buf, ref seekPos, val, startPos, length); } - - public void PrepareForSending(ref byte[] outBuf, bool compressPastThreshold, out bool isCompressed, out int length) + + public byte[] PrepareForSending(bool compressPastThreshold, out bool isCompressed, out int length) { + byte[] outBuf; if (LengthBytes <= MsgConstants.CompressionThreshold || !compressPastThreshold) { isCompressed = false; - if (LengthBytes > outBuf.Length) { Array.Resize(ref outBuf, LengthBytes); } + outBuf = new byte[LengthBytes]; Array.Copy(buf, outBuf, LengthBytes); length = LengthBytes; } else { - using (System.IO.MemoryStream output = new System.IO.MemoryStream()) + using MemoryStream output = new MemoryStream(); + + using (DeflateStream dstream = new DeflateStream(output, CompressionLevel.Fastest)) { - using (DeflateStream dstream = new DeflateStream(output, CompressionLevel.Fastest)) - { - dstream.Write(buf, 0, LengthBytes); - } - - byte[] compressedBuf = output.ToArray(); - //don't send the data as compressed if the data takes up more space after compression - //(which may happen when sending a sub/save file that's already been compressed with a better compression ratio) - if (compressedBuf.Length >= outBuf.Length) - { - isCompressed = false; - if (LengthBytes > outBuf.Length) { Array.Resize(ref outBuf, LengthBytes); } - Array.Copy(buf, outBuf, LengthBytes); - length = LengthBytes; - } - else - { - isCompressed = true; - if (compressedBuf.Length > outBuf.Length) { Array.Resize(ref outBuf, compressedBuf.Length); } - Array.Copy(compressedBuf, outBuf, compressedBuf.Length); - length = compressedBuf.Length; - DebugConsole.Log("Compressed message: " + LengthBytes + " to " + length); - } + dstream.Write(buf, 0, LengthBytes); + } + + byte[] compressedBuf = output.ToArray(); + //don't send the data as compressed if the data takes up more space after compression + //(which may happen when sending a sub/save file that's already been compressed with a better compression ratio) + if (compressedBuf.Length >= LengthBytes) + { + isCompressed = false; + outBuf = new byte[LengthBytes]; + Array.Copy(buf, outBuf, LengthBytes); + length = LengthBytes; + } + else + { + isCompressed = true; + outBuf = compressedBuf; + length = outBuf.Length; + DebugConsole.Log($"Compressed message: {LengthBytes} to {length}"); } } + + return outBuf; } } - class ReadOnlyMessage : IReadMessage + internal sealed class ReadOnlyMessage : IReadMessage { - private readonly byte[] buf; - private int seekPos = 0; - private int lengthBits = 0; + private int seekPos; + private int lengthBits; public int BitPosition { - get - { - return seekPos; - } - set - { - seekPos = value; - } + get => seekPos; + set => seekPos = value; } - public int BytePosition - { - get - { - return seekPos / 8; - } - } + public int BytePosition => seekPos / 8; - public byte[] Buffer - { - get - { - return buf; - } - } + public byte[] Buffer { get; } public int LengthBits { @@ -656,129 +611,126 @@ namespace Barotrauma.Networking } } - public int LengthBytes - { - get - { - return (LengthBits + 7) / 8; - } - } + public int LengthBytes => (LengthBits + 7) / 8; - public NetworkConnection Sender { get; private set; } - - public ReadOnlyMessage(byte[] inBuf, bool isCompressed, int startPos, int inLength, NetworkConnection sender) + public NetworkConnection Sender { get; } + + public ReadOnlyMessage(byte[] inBuf, bool isCompressed, int startPos, int byteLength, NetworkConnection sender) { Sender = sender; if (isCompressed) { byte[] decompressedData; - using (System.IO.MemoryStream input = new System.IO.MemoryStream(inBuf, startPos, inLength)) + using (MemoryStream input = new MemoryStream(inBuf, startPos, byteLength)) { - using (System.IO.MemoryStream output = new System.IO.MemoryStream()) + using (MemoryStream output = new MemoryStream()) { using (DeflateStream dstream = new DeflateStream(input, CompressionMode.Decompress)) { dstream.CopyTo(output); } + decompressedData = output.ToArray(); } } - buf = new byte[decompressedData.Length]; + + Buffer = new byte[decompressedData.Length]; try { - Array.Copy(decompressedData, 0, buf, 0, decompressedData.Length); + Array.Copy(decompressedData, 0, Buffer, 0, decompressedData.Length); } catch (ArgumentException e) { - throw new ArgumentException($"Failed to copy the incoming compressed buffer. Source buffer length: {decompressedData.Length}, start position: {0}, length: {decompressedData.Length}, destination buffer length: {buf.Length}.", e); + throw new ArgumentException( + $"Failed to copy the incoming compressed buffer. Source buffer length: {decompressedData.Length}, start position: {0}, length: {decompressedData.Length}, destination buffer length: {Buffer.Length}.", e); } + lengthBits = decompressedData.Length * 8; - DebugConsole.Log("Decompressing message: " + inLength + " to " + LengthBytes); + DebugConsole.Log("Decompressing message: " + byteLength + " to " + LengthBytes); } else { - buf = new byte[inBuf.Length]; + Buffer = new byte[inBuf.Length]; try { - Array.Copy(inBuf, startPos, buf, 0, inLength); + Array.Copy(inBuf, startPos, Buffer, 0, byteLength); } catch (ArgumentException e) { - throw new ArgumentException($"Failed to copy the incoming uncompressed buffer. Source buffer length: {inBuf.Length}, start position: {startPos}, length: {inLength}, destination buffer length: {buf.Length}.", e); + throw new ArgumentException($"Failed to copy the incoming uncompressed buffer. Source buffer length: {inBuf.Length}, start position: {startPos}, length: {byteLength}, destination buffer length: {Buffer.Length}.", e); } - lengthBits = inLength * 8; + + lengthBits = byteLength * 8; } + seekPos = 0; } public bool ReadBoolean() { - return MsgReader.ReadBoolean(buf, ref seekPos); + return MsgReader.ReadBoolean(Buffer, ref seekPos); } - public void ReadPadBits() - { - MsgReader.ReadPadBits(buf, ref seekPos); - } + public void ReadPadBits() { MsgReader.ReadPadBits(ref seekPos); } public byte ReadByte() { - return MsgReader.ReadByte(buf, ref seekPos); + return MsgReader.ReadByte(Buffer, ref seekPos); } public byte PeekByte() { - return MsgReader.PeekByte(buf, ref seekPos); + return MsgReader.PeekByte(Buffer, ref seekPos); } public UInt16 ReadUInt16() { - return MsgReader.ReadUInt16(buf, ref seekPos); + return MsgReader.ReadUInt16(Buffer, ref seekPos); } public Int16 ReadInt16() { - return MsgReader.ReadInt16(buf, ref seekPos); + return MsgReader.ReadInt16(Buffer, ref seekPos); } public UInt32 ReadUInt32() { - return MsgReader.ReadUInt32(buf, ref seekPos); + return MsgReader.ReadUInt32(Buffer, ref seekPos); } public Int32 ReadInt32() { - return MsgReader.ReadInt32(buf, ref seekPos); + return MsgReader.ReadInt32(Buffer, ref seekPos); } public UInt64 ReadUInt64() { - return MsgReader.ReadUInt64(buf, ref seekPos); + return MsgReader.ReadUInt64(Buffer, ref seekPos); } public Int64 ReadInt64() { - return MsgReader.ReadInt64(buf, ref seekPos); + return MsgReader.ReadInt64(Buffer, ref seekPos); } public Single ReadSingle() { - return MsgReader.ReadSingle(buf, ref seekPos); + return MsgReader.ReadSingle(Buffer, ref seekPos); } public Double ReadDouble() { - return MsgReader.ReadDouble(buf, ref seekPos); + return MsgReader.ReadDouble(Buffer, ref seekPos); } public UInt32 ReadVariableUInt32() { - return MsgReader.ReadVariableUInt32(buf, ref seekPos); + return MsgReader.ReadVariableUInt32(Buffer, ref seekPos); } public String ReadString() { - return MsgReader.ReadString(buf, ref seekPos); + return MsgReader.ReadString(Buffer, ref seekPos); } public Identifier ReadIdentifier() @@ -788,35 +740,35 @@ namespace Barotrauma.Networking public Color ReadColorR8G8B8() { - return MsgReader.ReadColorR8G8B8(buf, ref seekPos); + return MsgReader.ReadColorR8G8B8(Buffer, ref seekPos); } - + public Color ReadColorR8G8B8A8() { - return MsgReader.ReadColorR8G8B8A8(buf, ref seekPos); + return MsgReader.ReadColorR8G8B8A8(Buffer, ref seekPos); } public int ReadRangedInteger(int min, int max) { - return MsgReader.ReadRangedInteger(buf, ref seekPos, min, max); + return MsgReader.ReadRangedInteger(Buffer, ref seekPos, min, max); } public Single ReadRangedSingle(Single min, Single max, int bitCount) { - return MsgReader.ReadRangedSingle(buf, ref seekPos, min, max, bitCount); + return MsgReader.ReadRangedSingle(Buffer, ref seekPos, min, max, bitCount); } public byte[] ReadBytes(int numberOfBytes) { - return MsgReader.ReadBytes(buf, ref seekPos, numberOfBytes); + return MsgReader.ReadBytes(Buffer, ref seekPos, numberOfBytes); } } - class ReadWriteMessage : IWriteMessage, IReadMessage + internal sealed class ReadWriteMessage : IWriteMessage, IReadMessage { private byte[] buf; - private int seekPos = 0; - private int lengthBits = 0; + private int seekPos; + private int lengthBits; public ReadWriteMessage() { @@ -825,40 +777,22 @@ namespace Barotrauma.Networking lengthBits = 0; } - public ReadWriteMessage(byte[] b, int sPos, int lBits, bool copyBuf) + public ReadWriteMessage(byte[] b, int bitPos, int lBits, bool copyBuf) { buf = copyBuf ? (byte[])b.Clone() : b; - seekPos = sPos; + seekPos = bitPos; lengthBits = lBits; } public int BitPosition { - get - { - return seekPos; - } - set - { - seekPos = value; - } + get => seekPos; + set => seekPos = value; } - public int BytePosition - { - get - { - return seekPos / 8; - } - } + public int BytePosition => seekPos / 8; - public byte[] Buffer - { - get - { - return buf; - } - } + public byte[] Buffer => buf; public int LengthBits { @@ -874,17 +808,11 @@ namespace Barotrauma.Networking } } - public int LengthBytes - { - get - { - return (LengthBits + 7) / 8; - } - } + public int LengthBytes => (LengthBits + 7) / 8; - public NetworkConnection Sender { get { return null; } } + public NetworkConnection Sender => null; - public void Write(bool val) + public void WriteBoolean(bool val) { MsgWriter.Write(ref buf, ref seekPos, val); } @@ -894,47 +822,47 @@ namespace Barotrauma.Networking MsgWriter.WritePadBits(ref buf, ref seekPos); } - public void Write(byte val) + public void WriteByte(byte val) { MsgWriter.Write(ref buf, ref seekPos, val); } - public void Write(UInt16 val) + public void WriteUInt16(UInt16 val) { MsgWriter.Write(ref buf, ref seekPos, val); } - public void Write(Int16 val) + public void WriteInt16(Int16 val) { MsgWriter.Write(ref buf, ref seekPos, val); } - public void Write(UInt32 val) + public void WriteUInt32(UInt32 val) { MsgWriter.Write(ref buf, ref seekPos, val); } - public void Write(Int32 val) + public void WriteInt32(Int32 val) { MsgWriter.Write(ref buf, ref seekPos, val); } - public void Write(UInt64 val) + public void WriteUInt64(UInt64 val) { MsgWriter.Write(ref buf, ref seekPos, val); } - public void Write(Int64 val) + public void WriteInt64(Int64 val) { MsgWriter.Write(ref buf, ref seekPos, val); } - public void Write(Single val) + public void WriteSingle(Single val) { MsgWriter.Write(ref buf, ref seekPos, val); } - public void Write(Double val) + public void WriteDouble(Double val) { MsgWriter.Write(ref buf, ref seekPos, val); } @@ -943,7 +871,7 @@ namespace Barotrauma.Networking { MsgWriter.WriteColorR8G8B8(ref buf, ref seekPos, val); } - + public void WriteColorR8G8B8A8(Color val) { MsgWriter.WriteColorR8G8B8A8(ref buf, ref seekPos, val); @@ -954,14 +882,14 @@ namespace Barotrauma.Networking MsgWriter.WriteVariableUInt32(ref buf, ref seekPos, val); } - public void Write(String val) + public void WriteString(String val) { MsgWriter.Write(ref buf, ref seekPos, val); } - public void Write(Identifier val) + public void WriteIdentifier(Identifier val) { - Write(val.Value); + WriteString(val.Value); } public void WriteRangedInteger(int val, int min, int max) @@ -974,7 +902,7 @@ namespace Barotrauma.Networking MsgWriter.WriteRangedSingle(ref buf, ref seekPos, val, min, max, bitCount); } - public void Write(byte[] val, int startPos, int length) + public void WriteBytes(byte[] val, int startPos, int length) { MsgWriter.WriteBytes(ref buf, ref seekPos, val, startPos, length); } @@ -984,10 +912,7 @@ namespace Barotrauma.Networking return MsgReader.ReadBoolean(buf, ref seekPos); } - public void ReadPadBits() - { - MsgReader.ReadPadBits(buf, ref seekPos); - } + public void ReadPadBits() { MsgReader.ReadPadBits(ref seekPos); } public byte ReadByte() { @@ -1058,7 +983,7 @@ namespace Barotrauma.Networking { return MsgReader.ReadColorR8G8B8(buf, ref seekPos); } - + public Color ReadColorR8G8B8A8() { return MsgReader.ReadColorR8G8B8A8(buf, ref seekPos); @@ -1079,10 +1004,10 @@ namespace Barotrauma.Networking return MsgReader.ReadBytes(buf, ref seekPos, numberOfBytes); } - public void PrepareForSending(ref byte[] outBuf, bool compressPastThreshold, out bool isCompressed, out int outLength) + public byte[] PrepareForSending(bool compressPastThreshold, out bool isCompressed, out int outLength) { throw new InvalidOperationException("ReadWriteMessages are not to be sent"); } } -} +} \ No newline at end of file diff --git a/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/Enums.cs b/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/NetworkEnums.cs similarity index 98% rename from Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/Enums.cs rename to Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/NetworkEnums.cs index 8f8e62d55..03712e66f 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/Enums.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/NetworkEnums.cs @@ -40,6 +40,7 @@ namespace Barotrauma.Networking public static bool IsCompressed(this PacketHeader h) => h.HasFlag(PacketHeader.IsCompressed); + #warning TODO: remove? public static bool IsConnectionInitializationStep(this PacketHeader h) => h.HasFlag(PacketHeader.IsConnectionInitializationStep); diff --git a/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/NetworkExtensions.cs b/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/NetworkExtensions.cs new file mode 100644 index 000000000..ee01e2197 --- /dev/null +++ b/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/NetworkExtensions.cs @@ -0,0 +1,68 @@ +using System; +using System.Runtime.CompilerServices; +using Lidgren.Network; + +namespace Barotrauma.Networking +{ + internal static class WriteOnlyMessageExtensions + { +#if CLIENT + public static IWriteMessage WithHeader(this IWriteMessage msg, ClientPacketHeader header) + { + msg.WriteByte((byte)header); + return msg; + } +#elif SERVER + public static IWriteMessage WithHeader(this IWriteMessage msg, ServerPacketHeader header) + { + msg.WriteByte((byte)header); + return msg; + } +#endif + public static void WriteNetSerializableStruct(this IWriteMessage msg, INetSerializableStruct serializableStruct) + { + serializableStruct.Write(msg); + } + + public static NetOutgoingMessage ToLidgren(this IWriteMessage msg, NetPeer peer) + { + NetOutgoingMessage outMsg = peer.CreateMessage(); + outMsg.Write(msg.Buffer, 0, msg.LengthBytes); + return outMsg; + } + } + + internal static class NetIncomingMessageExtensions + { + public static T ReadHeader(this NetIncomingMessage msg) where T : Enum + { + byte header = msg.ReadByte(); + return Unsafe.As(ref header); + } + + public static IReadMessage ToReadMessage(this NetIncomingMessage msg) + { + return new ReadWriteMessage(msg.Data, 0, msg.LengthBits, copyBuf: false); + } + } + + internal static class DeliveryMethodExtensions + { + public static NetDeliveryMethod ToLidgren(this DeliveryMethod deliveryMethod) => + deliveryMethod switch + { + DeliveryMethod.Unreliable => NetDeliveryMethod.Unreliable, + DeliveryMethod.Reliable => NetDeliveryMethod.ReliableUnordered, + DeliveryMethod.ReliableOrdered => NetDeliveryMethod.ReliableOrdered, + _ => NetDeliveryMethod.Unreliable + }; + + public static Steamworks.P2PSend ToSteam(this DeliveryMethod deliveryMethod) => + deliveryMethod switch + { + DeliveryMethod.Reliable => Steamworks.P2PSend.Reliable, + DeliveryMethod.ReliableOrdered => Steamworks.P2PSend.Unreliable, + _ => Steamworks.P2PSend.Unreliable + }; + } +} \ No newline at end of file diff --git a/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/NetworkPeerStructs.cs b/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/NetworkPeerStructs.cs new file mode 100644 index 000000000..6ae0d0e1b --- /dev/null +++ b/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/NetworkPeerStructs.cs @@ -0,0 +1,142 @@ +#nullable enable + +using System; +using System.Collections.Immutable; +using System.Linq; + +namespace Barotrauma.Networking +{ + [NetworkSerialize] + internal struct PeerPacketHeaders : INetSerializableStruct + { + public DeliveryMethod DeliveryMethod; + public PacketHeader PacketHeader; + public ConnectionInitialization? Initialization; + + public readonly void Deconstruct( + out DeliveryMethod deliveryMethod, + out PacketHeader packetHeader, + out ConnectionInitialization? initialization) + { + deliveryMethod = DeliveryMethod; + packetHeader = PacketHeader; + initialization = Initialization; + } + } + + [NetworkSerialize(ArrayMaxSize = ushort.MaxValue)] + internal struct ClientSteamTicketAndVersionPacket : INetSerializableStruct + { + public string Name; + public Option OwnerKey; + + #warning TODO: do something about the type of this + // It probably should be Option but we shouldn't build support for + // writing SteamIDs to INetSerializableStruct; we should consider adding + // attributes to give custom behaviors to specific members of a struct + public Option SteamId; + + public Option SteamAuthTicket; + public string GameVersion; + public Identifier Language; + } + + [NetworkSerialize] + internal struct SteamP2PInitializationRelayPacket : INetSerializableStruct + { + public ulong LobbyID; + public PeerPacketMessage Message; + } + + [NetworkSerialize] + internal struct SteamP2PInitializationOwnerPacket : INetSerializableStruct + { + public string OwnerName; + } + + + [NetworkSerialize(ArrayMaxSize = ushort.MaxValue)] + internal struct ServerPeerContentPackageOrderPacket : INetSerializableStruct + { + public string ServerName; + public ImmutableArray ContentPackages; + } + + [NetworkSerialize(ArrayMaxSize = ushort.MaxValue)] + internal struct PeerPacketMessage : INetSerializableStruct + { + public byte[] Buffer; + public readonly int Length => Buffer.Length; + + public readonly IReadMessage GetReadMessage() => new ReadWriteMessage(Buffer, 0, Length, copyBuf: false); + public readonly IReadMessage GetReadMessage(bool isCompressed, NetworkConnection conn) => new ReadOnlyMessage(Buffer, isCompressed, 0, Length, conn); + } + + [NetworkSerialize(ArrayMaxSize = byte.MaxValue)] + internal struct ClientPeerPasswordPacket : INetSerializableStruct + { + public byte[] Password; + } + + [NetworkSerialize] + internal struct ServerPeerPasswordPacket : INetSerializableStruct + { + public Option Salt; + public Option RetriesLeft; + } + + [NetworkSerialize] + internal struct PeerDisconnectPacket : INetSerializableStruct + { + public string Message; + } + + // ReSharper disable MemberCanBePrivate.Global, FieldCanBeMadeReadOnly.Global, UnassignedField.Global + public sealed class ServerContentPackage : INetSerializableStruct + { + [NetworkSerialize] + public string Name = ""; + + [NetworkSerialize(ArrayMaxSize = ushort.MaxValue)] + public byte[] HashBytes = Array.Empty(); + + [NetworkSerialize] + public ulong WorkshopId; + + [NetworkSerialize] + public uint InstallTimeDiffInSeconds; + + private Md5Hash? cachedHash; + private DateTime? cachedDateTime; + + public Md5Hash Hash + { + get => cachedHash ??= Md5Hash.BytesAsHash(HashBytes); + set + { + cachedHash = value; + HashBytes = value.ByteRepresentation; + } + } + + 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 ContentPackage? ContentPackage => (ContentPackage?)RegularPackage ?? CorePackage; + + public ServerContentPackage() { } + + public ServerContentPackage(ContentPackage contentPackage, DateTime referenceTime) + { + Name = contentPackage.Name; + Hash = contentPackage.Hash; + WorkshopId = contentPackage.SteamWorkshopId; + InstallTimeDiffInSeconds = + contentPackage.InstallTime is { } installTime + ? (uint)(installTime - referenceTime).TotalSeconds + : 0; + } + + public string GetPackageStr() => $"\"{Name}\" (hash {Hash.ShortRepresentation})"; + } +} \ No newline at end of file diff --git a/Barotrauma/BarotraumaShared/SharedSource/Networking/RespawnManager.cs b/Barotrauma/BarotraumaShared/SharedSource/Networking/RespawnManager.cs index 1f1c31596..5aad66b97 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Networking/RespawnManager.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Networking/RespawnManager.cs @@ -11,6 +11,11 @@ namespace Barotrauma.Networking { partial class RespawnManager : Entity, IServerSerializable { + /// + /// How much skills drop towards the job's default skill levels when dying + /// + const float SkillReductionOnDeath = 0.75f; + public enum State { Waiting, diff --git a/Barotrauma/BarotraumaShared/SharedSource/Networking/ServerSettings.cs b/Barotrauma/BarotraumaShared/SharedSource/Networking/ServerSettings.cs index e626f1c23..74e9223ec 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Networking/ServerSettings.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Networking/ServerSettings.cs @@ -209,48 +209,48 @@ namespace Barotrauma.Networking { case "float": msg.WriteVariableUInt32(4); - msg.Write((float)overrideValue); + msg.WriteSingle((float)overrideValue); break; case "int": msg.WriteVariableUInt32(4); - msg.Write((int)overrideValue); + msg.WriteInt32((int)overrideValue); break; case "vector2": msg.WriteVariableUInt32(8); - msg.Write(((Vector2)overrideValue).X); - msg.Write(((Vector2)overrideValue).Y); + msg.WriteSingle(((Vector2)overrideValue).X); + msg.WriteSingle(((Vector2)overrideValue).Y); break; case "vector3": msg.WriteVariableUInt32(12); - msg.Write(((Vector3)overrideValue).X); - msg.Write(((Vector3)overrideValue).Y); - msg.Write(((Vector3)overrideValue).Z); + msg.WriteSingle(((Vector3)overrideValue).X); + msg.WriteSingle(((Vector3)overrideValue).Y); + msg.WriteSingle(((Vector3)overrideValue).Z); break; case "vector4": msg.WriteVariableUInt32(16); - msg.Write(((Vector4)overrideValue).X); - msg.Write(((Vector4)overrideValue).Y); - msg.Write(((Vector4)overrideValue).Z); - msg.Write(((Vector4)overrideValue).W); + msg.WriteSingle(((Vector4)overrideValue).X); + msg.WriteSingle(((Vector4)overrideValue).Y); + msg.WriteSingle(((Vector4)overrideValue).Z); + msg.WriteSingle(((Vector4)overrideValue).W); break; case "color": msg.WriteVariableUInt32(4); - msg.Write(((Color)overrideValue).R); - msg.Write(((Color)overrideValue).G); - msg.Write(((Color)overrideValue).B); - msg.Write(((Color)overrideValue).A); + msg.WriteByte(((Color)overrideValue).R); + msg.WriteByte(((Color)overrideValue).G); + msg.WriteByte(((Color)overrideValue).B); + msg.WriteByte(((Color)overrideValue).A); break; case "rectangle": msg.WriteVariableUInt32(16); - msg.Write(((Rectangle)overrideValue).X); - msg.Write(((Rectangle)overrideValue).Y); - msg.Write(((Rectangle)overrideValue).Width); - msg.Write(((Rectangle)overrideValue).Height); + msg.WriteInt32(((Rectangle)overrideValue).X); + msg.WriteInt32(((Rectangle)overrideValue).Y); + msg.WriteInt32(((Rectangle)overrideValue).Width); + msg.WriteInt32(((Rectangle)overrideValue).Height); break; default: string strVal = overrideValue.ToString(); - msg.Write(strVal); + msg.WriteString(strVal); break; } } @@ -550,7 +550,7 @@ namespace Barotrauma.Networking public bool HasPassword { - get { return password != null; } + get { return !string.IsNullOrEmpty(password); } #if CLIENT set { @@ -953,14 +953,7 @@ namespace Barotrauma.Networking public void SetPassword(string password) { - if (string.IsNullOrEmpty(password)) - { - this.password = null; - } - else - { - this.password = password; - } + this.password = string.IsNullOrEmpty(password) ? null : password; } public static byte[] SaltPassword(byte[] password, int salt) @@ -977,14 +970,9 @@ namespace Barotrauma.Networking public bool IsPasswordCorrect(byte[] input, int salt) { - if (!HasPassword) return true; + if (!HasPassword) { return true; } byte[] saltedPw = SaltPassword(Encoding.UTF8.GetBytes(password), salt); - if (input.Length != saltedPw.Length) return false; - for (int i = 0; i < input.Length; i++) - { - if (input[i] != saltedPw[i]) return false; - } - return true; + return saltedPw.SequenceEqual(input); } /// @@ -1039,7 +1027,7 @@ namespace Barotrauma.Networking msg.WriteVariableUInt32((uint)monsterNames.Count); foreach (Identifier s in monsterNames) { - msg.Write(monsterEnabled[s]); + msg.WriteBoolean(monsterEnabled[s]); } msg.WritePadBits(); } @@ -1071,15 +1059,15 @@ namespace Barotrauma.Networking { if (ExtraCargo == null) { - msg.Write((UInt32)0); + msg.WriteUInt32((UInt32)0); return; } - msg.Write((UInt32)ExtraCargo.Count); + msg.WriteUInt32((UInt32)ExtraCargo.Count); foreach (KeyValuePair kvp in ExtraCargo) { - msg.Write(kvp.Key.Identifier); - msg.Write((byte)kvp.Value); + msg.WriteIdentifier(kvp.Key.Identifier); + msg.WriteByte((byte)kvp.Value); } } @@ -1109,7 +1097,7 @@ namespace Barotrauma.Networking msg.WriteVariableUInt32((uint)HiddenSubs.Count); foreach (string submarineName in HiddenSubs) { - msg.Write((UInt16)subList.FindIndex(s => s.Name.Equals(submarineName, StringComparison.OrdinalIgnoreCase))); + msg.WriteUInt16((UInt16)subList.FindIndex(s => s.Name.Equals(submarineName, StringComparison.OrdinalIgnoreCase))); } } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Networking/Voip/VoipQueue.cs b/Barotrauma/BarotraumaShared/SharedSource/Networking/Voip/VoipQueue.cs index 29411143a..beafb895a 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Networking/Voip/VoipQueue.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Networking/Voip/VoipQueue.cs @@ -119,16 +119,16 @@ namespace Barotrauma.Networking { if (!CanSend) { throw new Exception("Called Write on a VoipQueue not set up for sending"); } - msg.Write((UInt16)LatestBufferID); - msg.Write(ForceLocal); msg.WritePadBits(); + msg.WriteUInt16((UInt16)LatestBufferID); + msg.WriteBoolean(ForceLocal); msg.WritePadBits(); lock (buffers) { for (int i = 0; i < BUFFER_COUNT; i++) { int index = (newestBufferInd + i + 1) % BUFFER_COUNT; - msg.Write((byte)bufferLengths[index]); - msg.Write(buffers[index], 0, bufferLengths[index]); + msg.WriteByte((byte)bufferLengths[index]); + msg.WriteBytes(buffers[index], 0, bufferLengths[index]); } } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Networking/WhiteList.cs b/Barotrauma/BarotraumaShared/SharedSource/Networking/WhiteList.cs deleted file mode 100644 index cb197f3b9..000000000 --- a/Barotrauma/BarotraumaShared/SharedSource/Networking/WhiteList.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System; -using System.Collections.Generic; -using Barotrauma.IO; -using System.Linq; - -namespace Barotrauma.Networking -{ - partial class WhiteListedPlayer - { - public string Name; - public string IP; - - public UInt16 UniqueIdentifier; - } - - partial class WhiteList - { - const string SavePath = "Data/whitelist.txt"; - - private List whitelistedPlayers; - public List WhiteListedPlayers - { - get { return whitelistedPlayers; } - } - - public bool Enabled; - - partial void InitProjSpecific(); - public WhiteList() - { - Enabled = false; - whitelistedPlayers = new List(); - - InitProjSpecific(); - } - } -} diff --git a/Barotrauma/BarotraumaShared/SharedSource/Serialization/SerializableProperty.cs b/Barotrauma/BarotraumaShared/SharedSource/Serialization/SerializableProperty.cs index 0cae07ba2..c78758bf3 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Serialization/SerializableProperty.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Serialization/SerializableProperty.cs @@ -508,7 +508,14 @@ namespace Barotrauma try { - return (float)PropertyInfo.GetValue(parentObject, null); + if (PropertyType == typeof(int)) + { + return (int)PropertyInfo.GetValue(parentObject, null); + } + else + { + return (float)PropertyInfo.GetValue(parentObject, null); + } } catch (TargetInvocationException e) { diff --git a/Barotrauma/BarotraumaShared/SharedSource/Serialization/XMLExtensions.cs b/Barotrauma/BarotraumaShared/SharedSource/Serialization/XMLExtensions.cs index ee27a296b..c2a73e504 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Serialization/XMLExtensions.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Serialization/XMLExtensions.cs @@ -308,7 +308,7 @@ namespace Barotrauma } catch (Exception e) { - DebugConsole.ThrowError("Error in " + element + "! ", e); + DebugConsole.ThrowError($"Error when reading attribute \"{name}\" from {element}!", e); } } @@ -331,7 +331,7 @@ namespace Barotrauma } catch (Exception e) { - DebugConsole.ThrowError("Error in " + element + "! ", e); + DebugConsole.ThrowError($"Error when reading attribute \"{name}\" from {element}!", e); } return val; @@ -350,7 +350,7 @@ namespace Barotrauma } catch (Exception e) { - DebugConsole.ThrowError("Error in " + element + "! ", e); + DebugConsole.ThrowError($"Error when reading attribute \"{name}\" from {element}!", e); } return val; @@ -369,7 +369,7 @@ namespace Barotrauma } catch (Exception e) { - DebugConsole.ThrowError("Error in " + element + "! ", e); + DebugConsole.ThrowError($"Error when reading attribute \"{name}\" from {element}!", e); } return val; @@ -388,7 +388,7 @@ namespace Barotrauma } catch (Exception e) { - DebugConsole.ThrowError("Error in " + element + "! ", e); + DebugConsole.ThrowError($"Error when reading attribute \"{name}\" from {element}!", e); } return val; @@ -413,7 +413,7 @@ namespace Barotrauma } catch (Exception e) { - DebugConsole.ThrowError("Error in " + element + "! ", e); + DebugConsole.ThrowError($"Error when reading attribute \"{name}\" from {element}!", e); } } @@ -438,7 +438,7 @@ namespace Barotrauma } catch (Exception e) { - DebugConsole.ThrowError("Error in " + element + "! ", e); + DebugConsole.ThrowError($"Error when reading attribute \"{name}\" from {element}!", e); } } @@ -540,7 +540,7 @@ namespace Barotrauma } catch (Exception e) { - DebugConsole.ThrowError("Error in " + element + "! ", e); + DebugConsole.ThrowError($"Error when reading attribute \"{name}\" from {element}!", e); } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Settings/GameSettings.cs b/Barotrauma/BarotraumaShared/SharedSource/Settings/GameSettings.cs index 4fc3665d5..4ba71d446 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Settings/GameSettings.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Settings/GameSettings.cs @@ -86,13 +86,6 @@ namespace Barotrauma return config; } - public static Config FromFile(string configFile, in Config? fallback = null) - { - XDocument doc = XMLExtensions.TryLoadXml(configFile); - - return FromElement(doc.Root ?? throw new InvalidOperationException("Unable to load config file: XML document is null."), fallback); - } - public static Config FromElement(XElement element, in Config? fallback = null) { Config retVal = fallback ?? GetDefault(); @@ -108,6 +101,7 @@ namespace Barotrauma #if CLIENT retVal.KeyMap = new KeyMapping(element.GetChildElements("keymapping"), retVal.KeyMap); retVal.InventoryKeyMap = new InventoryKeyMapping(element.GetChildElements("inventorykeymapping"), retVal.InventoryKeyMap); + LoadSubEditorImages(element); #endif return retVal; @@ -288,6 +282,7 @@ namespace Barotrauma { InputType.RadioChat, Keys.None }, { InputType.ActiveChat, Keys.T }, { InputType.CrewOrders, Keys.C }, + { InputType.ChatBox, Keys.B }, { InputType.Voice, Keys.V }, { InputType.RadioVoice, Keys.None }, @@ -331,9 +326,13 @@ namespace Barotrauma Dictionary bindings = fallback?.Bindings?.ToMutable() ?? defaultBindings.ToMutable(); foreach (InputType inputType in (InputType[])Enum.GetValues(typeof(InputType))) { - if (!bindings.ContainsKey(inputType)) { bindings.Add(inputType, defaultBindings[inputType]); } + if (!bindings.ContainsKey(inputType)) + { + bindings.Add(inputType, defaultBindings[inputType]); + } } + Dictionary savedBindings = new Dictionary(); bool playerConfigContainsNewChatBinds = false; bool playerConfigContainsRestoredVoipBinds = false; foreach (XElement element in elements) @@ -344,7 +343,34 @@ namespace Barotrauma { playerConfigContainsNewChatBinds |= result == InputType.ActiveChat; playerConfigContainsRestoredVoipBinds |= result == InputType.RadioVoice; - bindings[result] = element.GetAttributeKeyOrMouse(attribute.Name.LocalName, bindings[result]); + var keyOrMouse = element.GetAttributeKeyOrMouse(attribute.Name.LocalName, bindings[result]); + savedBindings.Add(result, keyOrMouse); + bindings[result] = keyOrMouse; + } + } + } + + // Check for duplicate binds when introducing new binds + foreach (var defaultBinding in defaultBindings) + { + if (!savedBindings.ContainsKey(defaultBinding.Key)) + { + foreach (var savedBinding in savedBindings) + { + if (savedBinding.Value == defaultBinding.Value) + { + OnGameMainHasLoaded += () => + { + (string, string)[] replacements = + { + ("[defaultbind]", $"\"{TextManager.Get($"inputtype.{defaultBinding.Key}")}\""), + ("[savedbind]", $"\"{TextManager.Get($"inputtype.{savedBinding.Key}")}\""), + ("[key]", $"\"{defaultBinding.Value.Name}\"") + }; + new GUIMessageBox(TextManager.Get("warning"), TextManager.GetWithVariables("duplicatebindwarning", replacements)); + }; + break; + } } } } @@ -442,6 +468,10 @@ namespace Barotrauma private static Config currentConfig; public static ref readonly Config CurrentConfig => ref currentConfig; +#if CLIENT + public static Action? OnGameMainHasLoaded; +#endif + public static void Init() { XDocument? currentConfigDoc = null; @@ -574,6 +604,8 @@ namespace Barotrauma .Select(kvp => new XAttribute($"slot{kvp.Index.ToString(CultureInfo.InvariantCulture)}", kvp.Bind.ToString()))); root.Add(inventoryKeyMappingElement); + + SubEditorScreen.ImageManager.Save(root); #endif configDoc.SaveSafe(PlayerConfigPath); @@ -600,5 +632,18 @@ namespace Barotrauma "Saving game settings failed.\n" + e.Message + "\n" + e.StackTrace.CleanupStackTrace()); } } + +#if CLIENT + private static void LoadSubEditorImages(XElement configElement) + { + XElement? element = configElement?.Element("editorimages"); + if (element == null) + { + SubEditorScreen.ImageManager.Clear(alsoPending: true); + return; + } + SubEditorScreen.ImageManager.Load(element); + } +#endif } } \ No newline at end of file diff --git a/Barotrauma/BarotraumaShared/SharedSource/StatusEffects/StatusEffect.cs b/Barotrauma/BarotraumaShared/SharedSource/StatusEffects/StatusEffect.cs index 29f5fe5ba..9c1ce5c71 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/StatusEffects/StatusEffect.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/StatusEffects/StatusEffect.cs @@ -1538,24 +1538,23 @@ namespace Barotrauma { Character targetCharacter = CharacterFromTarget(target); if (targetCharacter?.Info == null) { continue; } - if (!TalentTree.JobTalentTrees.TryGet(targetCharacter.Info.Job.Prefab.Identifier, out TalentTree talentTree)) { continue; } - // for the sake of technical simplicity, for now do not allow talents to be given if the character could unlock them in their talent tree as well - IEnumerable disallowedTalents = talentTree.TalentSubTrees.SelectMany(s => s.TalentOptionStages.SelectMany(o => o.Talents.Select(t => t.Identifier))); + if (!TalentTree.JobTalentTrees.TryGet(targetCharacter.Info.Job.Prefab.Identifier, out TalentTree characterTalentTree)) { continue; } foreach (GiveTalentInfo giveTalentInfo in giveTalentInfos) { - IEnumerable viableTalents = giveTalentInfo.TalentIdentifiers.Where(s => !targetCharacter.Info.UnlockedTalents.Contains(s) && !disallowedTalents.Contains(s)); - if (viableTalents.None()) { continue; } - if (giveTalentInfo.GiveRandom) - { + { + // for the sake of technical simplicity, for now do not allow talents to be given if the character could unlock them in their talent tree as well + IEnumerable viableTalents = giveTalentInfo.TalentIdentifiers.Where(id => !targetCharacter.Info.UnlockedTalents.Contains(id) && !characterTalentTree.AllTalentIdentifiers.Contains(id)); + if (viableTalents.None()) { continue; } targetCharacter.GiveTalent(viableTalents.GetRandomUnsynced(), true); } else { - foreach (Identifier talent in viableTalents) + foreach (Identifier id in giveTalentInfo.TalentIdentifiers) { - targetCharacter.GiveTalent(talent, true); + if (targetCharacter.Info.UnlockedTalents.Contains(id) || characterTalentTree.AllTalentIdentifiers.Contains(id)) { continue; } + targetCharacter.GiveTalent(id, true); } } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Steam/SteamManager.cs b/Barotrauma/BarotraumaShared/SharedSource/Steam/SteamManager.cs index 5eb17570d..f8815e014 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Steam/SteamManager.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Steam/SteamManager.cs @@ -64,7 +64,7 @@ namespace Barotrauma.Steam { if (!IsInitialized || !Steamworks.SteamClient.IsValid) { return false; } - return Steamworks.SteamApps.IsSubscribedFromFamilySharing; + return Steamworks.SteamApps.IsSubscribedFromFreeWeekend; } public static string GetUsername() diff --git a/Barotrauma/BarotraumaShared/SharedSource/Text/LocalizedString/InputTypeLString.cs b/Barotrauma/BarotraumaShared/SharedSource/Text/LocalizedString/InputTypeLString.cs index cfd7c255b..3ae90e998 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Text/LocalizedString/InputTypeLString.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Text/LocalizedString/InputTypeLString.cs @@ -6,7 +6,13 @@ namespace Barotrauma public class InputTypeLString : LocalizedString { private readonly LocalizedString nestedStr; - public InputTypeLString(LocalizedString nStr) { nestedStr = nStr; } + private bool useColorHighlight; + + public InputTypeLString(LocalizedString nStr, bool useColorHighlight = false) + { + nestedStr = nStr; + this.useColorHighlight = useColorHighlight; + } protected override bool MustRetrieveValue() { @@ -23,8 +29,14 @@ namespace Barotrauma foreach (InputType? inputType in Enum.GetValues(typeof(InputType))) { if (!inputType.HasValue) { continue; } - cachedValue = cachedValue.Replace($"[{inputType}]", GameSettings.CurrentConfig.KeyMap.KeyBindText(inputType.Value).Value, StringComparison.OrdinalIgnoreCase); - cachedValue = cachedValue.Replace($"[InputType.{inputType}]", GameSettings.CurrentConfig.KeyMap.KeyBindText(inputType.Value).Value, StringComparison.OrdinalIgnoreCase); + + string keyBindText = GameSettings.CurrentConfig.KeyMap.KeyBindText(inputType.Value).Value; + if (useColorHighlight) + { + keyBindText = $"‖color:gui.orange‖{keyBindText}‖end‖"; + } + cachedValue = cachedValue.Replace($"[{inputType}]", keyBindText, StringComparison.OrdinalIgnoreCase); + cachedValue = cachedValue.Replace($"[InputType.{inputType}]", keyBindText, StringComparison.OrdinalIgnoreCase); } #endif UpdateLanguage(); diff --git a/Barotrauma/BarotraumaShared/SharedSource/Text/TextManager.cs b/Barotrauma/BarotraumaShared/SharedSource/Text/TextManager.cs index 2b1722674..823d7fd28 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Text/TextManager.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Text/TextManager.cs @@ -262,9 +262,9 @@ namespace Barotrauma string.Join(separator, parts.Select((part, index) => $"[{namePrefix}{index}]"))); } - public static LocalizedString ParseInputTypes(LocalizedString str) + public static LocalizedString ParseInputTypes(LocalizedString str, bool useColorHighlight = false) { - return new InputTypeLString(str); + return new InputTypeLString(str, useColorHighlight); } public static LocalizedString GetWithVariable(string tag, string varName, LocalizedString value, FormatCapitals formatCapitals = FormatCapitals.No) diff --git a/Barotrauma/BarotraumaShared/SharedSource/Upgrades/Upgrade.cs b/Barotrauma/BarotraumaShared/SharedSource/Upgrades/Upgrade.cs index c193ba8d7..fc64098bb 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Upgrades/Upgrade.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Upgrades/Upgrade.cs @@ -5,12 +5,11 @@ using System.Globalization; using System.Linq; using System.Xml.Linq; using Barotrauma.Items.Components; -using Barotrauma.Networking; // ReSharper disable ArrangeThisQualifier namespace Barotrauma { - internal class PropertyReference + internal sealed class PropertyReference { public object? OriginalValue { get; private set; } @@ -38,87 +37,63 @@ namespace Barotrauma /// Calculate the new value of the property /// /// level of the upgrade - /// Optional XElement reference, only used for error logging. /// - public float CalculateUpgrade(int level, XElement? sourceElement = null) + public object CalculateUpgrade(int level) { - if (OriginalValue is float || OriginalValue is int || OriginalValue is double) + switch (OriginalValue) { - var value = (float) OriginalValue; - - if (level == 0) { return value; } - - if (Multiplier[^1] != '%') + case float _: + case int _: + case double _: { - float multiplier = ParseValue(); - switch (Multiplier[0]) - { - case '*': - case 'x': - return value * (multiplier * level); - case '/': - return value / (multiplier * level); - case '-': - return value - (multiplier * level); - case '+': - return value + (multiplier * level); - case '=': - return multiplier; - } + var value = (float) OriginalValue; + return level == 0 ? value : CalculateUpgrade(value, level, Multiplier); } - else + case bool _ when bool.TryParse(Multiplier, out bool result): { - float multiplier = UpgradePrefab.ParsePercentage(Multiplier, Name, sourceElement, upgrade.Prefab.SuppressWarnings); - return ApplyPercentage(value, multiplier, level); + return result; + } + default: + { + DebugConsole.AddWarning($"Original value of \"{Name}\" in the upgrade \"{upgrade.Prefab.Name}\" is not a integer, float, double or boolean but {OriginalValue?.GetType()} with a value of ({OriginalValue}). \n" + + "The value has been assumed to be '0', did you forget a Convert.ChangeType()?"); + break; } - } - else - { - DebugConsole.AddWarning($"Original value of \"{Name}\" in the upgrade \"{upgrade.Prefab.Name}\" is not a integer, float or a double but {OriginalValue?.GetType()} with a value of ({OriginalValue}). \n" + - "The value has been assumed to be '0', did you forget a Convert.ChangeType()?"); } return 0; } - public static float CalculateUpgrade(object originalValue, int level, string Multiplier) + public static float CalculateUpgrade(float value, int level, string multiplier) { - if (originalValue is float || originalValue is int || originalValue is double) + if (multiplier[^1] != '%') { - var value = (float)originalValue; - - if (Multiplier[^1] != '%') - { - float multiplier = 1.0f; - if (Multiplier.Length > 1) - { - if (prefixCharacters.Contains(Multiplier[0])) - { - float.TryParse(Multiplier.Substring(1).Trim(), NumberStyles.Number, CultureInfo.InvariantCulture, out multiplier); - } - } - switch (Multiplier[0]) - { - case '*': - case 'x': - return value * (multiplier * level); - case '/': - return value / (multiplier * level); - case '-': - return value - (multiplier * level); - case '+': - return value + (multiplier * level); - case '=': - return multiplier; - } - } - else - { - float multiplier = UpgradePrefab.ParsePercentage(Multiplier, Identifier.Empty, suppressWarnings: true); - return ApplyPercentage(value, multiplier, level); - } + return CalculateUpgradeFloat(multiplier, value , level); } - return float.NaN; + + return ApplyPercentage(value, UpgradePrefab.ParsePercentage(multiplier, Identifier.Empty, suppressWarnings: true), level); + } + + private static float CalculateUpgradeFloat(string multiplier, float value, int level) + { + float multiplierFloat = ParseValue(multiplier, value); + + switch (multiplier[0]) + { + case '*': + case 'x': + return value * (multiplierFloat * level); + case '/': + return value / (multiplierFloat * level); + case '-': + return value - (multiplierFloat * level); + case '+': + return value + (multiplierFloat * level); + case '=': + return multiplierFloat; + } + + return 0; } /// @@ -133,7 +108,20 @@ namespace Barotrauma { if (savedValue.NameAsIdentifier() == Name) { - OriginalValue = savedValue.GetAttributeFloat("value", 0.0f); + string value = savedValue.GetAttributeString("value", string.Empty); + + if (float.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out float floatValue)) + { + OriginalValue = floatValue; + } + else if (bool.TryParse(value, out bool boolValue)) + { + OriginalValue = boolValue; + } + else + { + OriginalValue = value; + } } } } @@ -155,30 +143,23 @@ namespace Barotrauma return attributes.Select(attribute => new PropertyReference(attribute.NameAsIdentifier(), attribute.Value, upgrade)).ToArray(); } - private float ParseValue() + private static float ParseValue(string multiplier, object? originalValue) { - if (Multiplier.Length > 1) + if (multiplier.Length > 1) { - if (prefixCharacters.Contains(Multiplier[0])) + if (prefixCharacters.Contains(multiplier[0])) { - if (float.TryParse(Multiplier.Substring(1).Trim(), NumberStyles.Number, CultureInfo.InvariantCulture, out float value)) { return value; } + if (float.TryParse(multiplier.Substring(1).Trim(), NumberStyles.Number, CultureInfo.InvariantCulture, out float value)) { return value; } - if (OriginalValue is float || OriginalValue is int || OriginalValue is double) { return (float) OriginalValue; } + if (originalValue is float || originalValue is int || originalValue is double) { return (float) originalValue; } } } - if (!upgrade.Prefab.SuppressWarnings) - { - DebugConsole.AddWarning($"Multiplier for {Name} is too short or does not contain proper prefix. \n" + - $"The value should start with {string.Join(",", prefixCharacters)} and contain a floating point value or another property. \n" + - "The value has been assumed to be '1'."); - } - return 1; } } - internal class Upgrade : IDisposable + internal sealed class Upgrade : IDisposable { private ISerializableEntity TargetEntity { get; } @@ -379,10 +360,10 @@ namespace Barotrauma { if (entity.SerializableProperties.TryGetValue(propertyReference.Name, out SerializableProperty? property) && property != null) { - object? originalValue = property!.GetValue(entity); + object? originalValue = property.GetValue(entity); propertyReference.SetOriginalValue(originalValue); - object newValue = Convert.ChangeType(propertyReference.CalculateUpgrade(Level, sourceElement), originalValue.GetType(), NumberFormatInfo.InvariantInfo); - property!.SetValue(entity, newValue); + object newValue = Convert.ChangeType(propertyReference.CalculateUpgrade(Level), originalValue.GetType(), NumberFormatInfo.InvariantInfo); + property.SetValue(entity, newValue); } else { diff --git a/Barotrauma/BarotraumaShared/SharedSource/Upgrades/UpgradePrefab.cs b/Barotrauma/BarotraumaShared/SharedSource/Upgrades/UpgradePrefab.cs index bbb727d01..9ca176167 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Upgrades/UpgradePrefab.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Upgrades/UpgradePrefab.cs @@ -45,10 +45,14 @@ namespace Barotrauma public int GetBuyprice(int level, Location? location = null) { + int maxLevel = Prefab.MaxLevel; + + if (level > maxLevel) { maxLevel = level; } + int price = BasePrice; for (int i = 1; i <= level; i++) { - price += (int)(price * MathHelper.Lerp(IncreaseLow, IncreaseHigh, i / (float)Prefab.MaxLevel) / 100); + price += (int)(price * MathHelper.Lerp(IncreaseLow, IncreaseHigh, i / (float)maxLevel) / 100); } return location?.GetAdjustedMechanicalCost(price) ?? price; } @@ -108,7 +112,7 @@ namespace Barotrauma public readonly LocalizedString Name; public readonly IEnumerable ItemTags; - + public UpgradeCategory(ContentXElement element, UpgradeModulesFile file) : base(element, file) { selfItemTags = element.GetAttributeIdentifierArray("items", Array.Empty())?.ToImmutableHashSet() ?? ImmutableHashSet.Empty; @@ -137,13 +141,22 @@ namespace Barotrauma .Select(it => it.Identifier)); } - public bool CanBeApplied(Item item, UpgradePrefab? upgradePrefab) + public bool CanBeApplied(MapEntity item, UpgradePrefab? upgradePrefab) { - if (IsWallUpgrade) { return false; } + if (upgradePrefab != null && item.Submarine is { Info: var info } && !upgradePrefab.IsApplicable(info)) { return false; } + + bool isStructure = item is Structure; + switch (IsWallUpgrade) + { + case true: + return isStructure; + case false when isStructure: + return false; + } if (upgradePrefab != null && upgradePrefab.IsDisallowed(item)) { return false; } - return ((MapEntity)item).Prefab.GetAllowedUpgrades().Contains(Identifier) || + return item.Prefab.GetAllowedUpgrades().Contains(Identifier) || ItemTags.Any(tag => item.Prefab.Tags.Contains(tag) || item.Prefab.Identifier == tag); } @@ -173,6 +186,83 @@ namespace Barotrauma public override void Dispose() { } } + internal readonly struct UpgradeMaxLevelMod + { + private enum MaxLevelModType + { + Invalid, + Increase, + Set + } + + private readonly Either tierOrClass; + private readonly int value; + private readonly MaxLevelModType type; + + public int GetLevelAfter(int level) => + type switch + { + MaxLevelModType.Invalid => level, + MaxLevelModType.Increase => level + value, + MaxLevelModType.Set => value, + _ => throw new ArgumentOutOfRangeException() + }; + + public bool AppliesTo(SubmarineInfo sub) + { + if (type is MaxLevelModType.Invalid) { return false; } + + if (tierOrClass.TryGet(out int tier)) + { + return sub.Tier == tier; + } + + if (tierOrClass.TryGet(out SubmarineClass subClass)) + { + return sub.SubmarineClass == subClass; + } + + return false; + } + + public UpgradeMaxLevelMod(ContentXElement element) + { + bool isValid = true; + + SubmarineClass subClass = element.GetAttributeEnum("class", SubmarineClass.Undefined); + int tier = element.GetAttributeInt("tier", 0); + if (subClass != SubmarineClass.Undefined) + { + tierOrClass = subClass; + } + else + { + tierOrClass = tier; + } + + string stringValue = element.GetAttributeString("level", null) ?? string.Empty; + value = 0; + + if (string.IsNullOrWhiteSpace(stringValue)) { isValid = false; } + + char firstChar = stringValue[0]; + + if (!int.TryParse(stringValue, NumberStyles.Any, CultureInfo.InvariantCulture, out var intValue)) { isValid = false; } + value = intValue; + + if (firstChar.Equals('+') || firstChar.Equals('-')) + { + type = MaxLevelModType.Increase; + } + else + { + type = MaxLevelModType.Set; + } + + if (!isValid) { type = MaxLevelModType.Invalid; } + } + } + internal partial class UpgradePrefab : UpgradeContentPrefab { public static readonly PrefabCollection Prefabs = new PrefabCollection( @@ -205,10 +295,19 @@ namespace Barotrauma onRemoveOverrideFile: null ); - public int MaxLevel { get; } + private readonly int maxLevel; + + public int MaxLevel + { + get + { + Submarine? sub = GameMain.GameSession?.Submarine ?? Submarine.MainSub; + return sub is { Info: var info } ? GetMaxLevel(info) : maxLevel; + } + } public LocalizedString Name { get; } - + public LocalizedString Description { get; } public float IncreaseOnTooltip { get; } @@ -243,17 +342,19 @@ namespace Barotrauma public bool IsWallUpgrade => UpgradeCategories.All(u => u.IsWallUpgrade); private Dictionary targetProperties { get; } + private readonly ImmutableArray MaxLevelsMods; public UpgradePrefab(ContentXElement element, UpgradeModulesFile file) : base(element, file) { 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; var targetProperties = new Dictionary(); + var maxLevels = new List(); Identifier nameIdentifier = element.GetAttributeIdentifier("nameidentifier", ""); if (!nameIdentifier.IsEmpty) @@ -291,6 +392,11 @@ namespace Barotrauma Price = new UpgradePrice(this, subElement); break; } + case "maxlevel": + { + maxLevels.Add(new UpgradeMaxLevelMod(subElement)); + break; + } #if CLIENT case "decorativesprite": { @@ -321,14 +427,35 @@ namespace Barotrauma #endif this.targetProperties = targetProperties; + MaxLevelsMods = maxLevels.ToImmutableArray(); upgradeCategoryIdentifiers = element.GetAttributeIdentifierArray("categories", Array.Empty())? .ToImmutableHashSet() ?? ImmutableHashSet.Empty; } - public bool IsDisallowed(Item item) + public int GetMaxLevel(SubmarineInfo info) { - return item.DisallowedUpgradeSet.Contains(Identifier) || UpgradeCategories.Any(c => item.DisallowedUpgradeSet.Contains(c.Identifier)); + int level = maxLevel; + + foreach (UpgradeMaxLevelMod mod in MaxLevelsMods) + { + if (mod.AppliesTo(info)) { level = mod.GetLevelAfter(level); } + } + + return level; + } + + public bool IsApplicable(SubmarineInfo? info) + { + if (info is null) { return false; } + + return GetMaxLevel(info) > 0; + } + + public bool IsDisallowed(MapEntity item) + { + return item.DisallowedUpgradeSet.Contains(Identifier) + || UpgradeCategories.Any(c => item.DisallowedUpgradeSet.Contains(c.Identifier)); } public static UpgradePrefab? Find(Identifier identifier) diff --git a/Barotrauma/BarotraumaShared/SharedSource/Utils/IPExtensions.cs b/Barotrauma/BarotraumaShared/SharedSource/Utils/IPExtensions.cs deleted file mode 100644 index e9934ec31..000000000 --- a/Barotrauma/BarotraumaShared/SharedSource/Utils/IPExtensions.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net; -using System.Text; - -namespace Barotrauma -{ - public static class IPExtensions - { - //TODO: remove? - //workaround for .NET Framework 4.5 bug; presumably fixed in later versions - //see https://stackoverflow.com/questions/23608829/why-does-ipaddress-maptoipv4-throw-argumentoutofrangeexception - public static IPAddress MapToIPv4NoThrow(this IPAddress address) - { - byte[] addressBytes = address.GetAddressBytes(); - - return new IPAddress(addressBytes.Skip(addressBytes.Length - 4).ToArray()); - } - } -} diff --git a/Barotrauma/BarotraumaShared/SharedSource/Utils/SafeIO.cs b/Barotrauma/BarotraumaShared/SharedSource/Utils/SafeIO.cs index 1a2e8968c..49b231dfe 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Utils/SafeIO.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Utils/SafeIO.cs @@ -231,7 +231,19 @@ namespace Barotrauma.IO public static bool IsPathRooted(string path) => System.IO.Path.IsPathRooted(path); - public static IEnumerable GetInvalidFileNameChars() => System.IO.Path.GetInvalidFileNameChars(); + private static readonly ImmutableHashSet invalidFileNameChars = ImmutableHashSet.Create + ( + '\"', '<', '>', '|', '\0', + (char)1, (char)2, (char)3, (char)4, (char)5, (char)6, (char)7, (char)8, (char)9, (char)10, + (char)11, (char)12, (char)13, (char)14, (char)15, (char)16, (char)17, (char)18, (char)19, (char)20, + (char)21, (char)22, (char)23, (char)24, (char)25, (char)26, (char)27, (char)28, (char)29, (char)30, + (char)31, ':', '*', '?', '\\', '/' + ); + + /// + /// Returns file name characters that are invalid on any of our supported platforms (essentially the list of invalid characters on Windows) + /// + public static ImmutableHashSet GetInvalidFileNameCharsCrossPlatform() => invalidFileNameChars; } public static class Directory diff --git a/Barotrauma/BarotraumaShared/SharedSource/Utils/SaveUtil.cs b/Barotrauma/BarotraumaShared/SharedSource/Utils/SaveUtil.cs index 6ca456993..8df000e58 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Utils/SaveUtil.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Utils/SaveUtil.cs @@ -1,15 +1,13 @@ using System; -using System.Collections; using System.Collections.Generic; -using Barotrauma.IO; using System.IO.Compression; using System.Linq; using System.Text; using System.Threading; using System.Xml.Linq; -using Steamworks.Data; -using Color = Microsoft.Xna.Framework.Color; using System.Text.RegularExpressions; +using Barotrauma.IO; +using Microsoft.Xna.Framework; namespace Barotrauma { @@ -20,7 +18,7 @@ namespace Barotrauma #if OSX //"/*user*/Library/Application Support/Daedalic Entertainment GmbH/" on Mac - public static string SaveFolder = Path.Combine( + public static readonly string SaveFolder = Path.Combine( Environment.GetFolderPath(Environment.SpecialFolder.Personal), "Library", "Application Support", @@ -29,7 +27,7 @@ namespace Barotrauma #else //"C:/Users/*user*/AppData/Local/Daedalic Entertainment GmbH/" on Windows //"/home/*user*/.local/share/Daedalic Entertainment GmbH/" on Linux - public static string SaveFolder = Path.Combine( + public static readonly string SaveFolder = Path.Combine( Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Daedalic Entertainment GmbH", "Barotrauma"); @@ -165,15 +163,6 @@ namespace Barotrauma return ownedSubmarines; } - /*public static void LoadMultiplayerCampaignState(string filePath, MultiPlayerCampaign multiplayerCampaign) - { - DebugConsole.Log("Loading save file for an existing game session (" + filePath + ")"); - DecompressToDirectory(filePath, TempPath, null); - XDocument doc = XMLExtensions.TryLoadXml(Path.Combine(TempPath, "gamesession.xml")); - if (doc == null) { return; } - gameSession.Load(doc.Root); - }*/ - public static XDocument LoadGameSessionDoc(string filePath) { DebugConsole.Log("Loading game session doc: " + filePath); @@ -391,73 +380,69 @@ namespace Barotrauma } - public static System.IO.Stream DecompressFiletoStream(string fileName) + public static System.IO.Stream DecompressFileToStream(string fileName) { - using (FileStream originalFileStream = File.Open(fileName, System.IO.FileMode.Open)) - { - System.IO.MemoryStream decompressedFileStream = new System.IO.MemoryStream(); + using FileStream originalFileStream = File.Open(fileName, System.IO.FileMode.Open, System.IO.FileAccess.Read); + System.IO.MemoryStream streamToReturn = new System.IO.MemoryStream(); - using (GZipStream decompressionStream = new GZipStream(originalFileStream, CompressionMode.Decompress)) - { - decompressionStream.CopyTo(decompressedFileStream); - return decompressedFileStream; - } - } + using GZipStream gzipStream = new GZipStream(originalFileStream, CompressionMode.Decompress); + gzipStream.CopyTo(streamToReturn); + + streamToReturn.Position = 0; + return streamToReturn; } - private static bool DecompressFile(bool writeFile, string sDir, GZipStream zipStream, ProgressDelegate progress, out string fileName) + private static bool IsExtractionPathValid(string rootDir, string fileDir) + { + string getFullPath(string dir) + => (string.IsNullOrEmpty(dir) + ? Directory.GetCurrentDirectory() + : Path.GetFullPath(dir)) + .CleanUpPathCrossPlatform(correctFilenameCase: false); + + string rootDirFull = getFullPath(rootDir); + string fileDirFull = getFullPath(fileDir); + + return fileDirFull.StartsWith(rootDirFull, StringComparison.OrdinalIgnoreCase); + } + + private static bool DecompressFile(bool writeFile, string sDir, System.IO.BinaryReader reader, ProgressDelegate progress, out string fileName) { fileName = null; + if (reader.PeekChar() < 0) { return false; } + //Decompress file name - byte[] bytes = new byte[sizeof(int)]; - int Readed = Read(zipStream, bytes, sizeof(int)); - if (Readed < sizeof(int)) - return false; - - int iNameLen = BitConverter.ToInt32(bytes, 0); - if (iNameLen > 255) + int nameLen = reader.ReadInt32(); + if (nameLen > 255) { - throw new Exception("Failed to decompress \"" + sDir + "\" (file name length > 255). The file may be corrupted."); + throw new Exception( + $"Failed to decompress \"{sDir}\" (file name length > 255). The file may be corrupted."); } - bytes = new byte[sizeof(char)]; - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < iNameLen; i++) - { - Read(zipStream, bytes, sizeof(char)); - char c = BitConverter.ToChar(bytes, 0); - sb.Append(c); - } - string sFileName = sb.ToString().Replace('\\', '/'); + byte[] strBytes = reader.ReadBytes(nameLen * sizeof(char)); + string sFileName = Encoding.Unicode.GetString(strBytes) + .Replace('\\', '/'); fileName = sFileName; progress?.Invoke(sFileName); //Decompress file content - bytes = new byte[sizeof(int)]; - Read(zipStream, bytes, sizeof(int)); - int iFileLen = BitConverter.ToInt32(bytes, 0); - - bytes = new byte[iFileLen]; - Read(zipStream, bytes, bytes.Length); + int contentLen = reader.ReadInt32(); + byte[] contentBytes = reader.ReadBytes(contentLen); string sFilePath = Path.Combine(sDir, sFileName); string sFinalDir = Path.GetDirectoryName(sFilePath); - string sDirFull = (string.IsNullOrEmpty(sDir) ? Directory.GetCurrentDirectory() : Path.GetFullPath(sDir)).CleanUpPathCrossPlatform(correctFilenameCase: false); - string sFinalDirFull = (string.IsNullOrEmpty(sFinalDir) ? Directory.GetCurrentDirectory() : Path.GetFullPath(sFinalDir)).CleanUpPathCrossPlatform(correctFilenameCase: false); - - if (!sFinalDirFull.StartsWith(sDirFull, StringComparison.OrdinalIgnoreCase)) + if (!IsExtractionPathValid(sDir, sFinalDir)) { throw new InvalidOperationException( $"Error extracting \"{sFileName}\": cannot be extracted to parent directory"); } - + if (!writeFile) { return true; } - if (!Directory.Exists(sFinalDir)) - Directory.CreateDirectory(sFinalDir); + Directory.CreateDirectory(sFinalDir); int maxRetries = 4; for (int i = 0; i <= maxRetries; i++) { @@ -465,7 +450,7 @@ namespace Barotrauma { using (FileStream outFile = File.Open(sFilePath, System.IO.FileMode.Create, System.IO.FileAccess.Write)) { - outFile.Write(bytes, 0, iFileLen); + outFile.Write(contentBytes, 0, contentLen); } break; } @@ -479,26 +464,6 @@ namespace Barotrauma return true; } - private static int Read(GZipStream zipStream, byte[] bytes, int amount) - { - int read = 0; - - // BUG workaround for .NET6 causing save decompression to fail -#if NET6_0 - for (int i = 0; i < amount; i++) - { - int result = zipStream.ReadByte(); - if (result < 0) { break; } - - bytes[i] = (byte) result; - read++; - } -#else - read = zipStream.Read(bytes, 0, amount); -#endif - return read; - } - public static void DecompressToDirectory(string sCompressedFile, string sDir, ProgressDelegate progress) { DebugConsole.Log("Decompressing " + sCompressedFile + " to " + sDir + "..."); @@ -507,9 +472,9 @@ namespace Barotrauma { try { - using (FileStream inFile = File.Open(sCompressedFile, System.IO.FileMode.Open, System.IO.FileAccess.Read)) - using (GZipStream zipStream = new GZipStream(inFile, CompressionMode.Decompress, true)) - while (DecompressFile(true, sDir, zipStream, progress, out _)) { }; + using (var memStream = DecompressFileToStream(sCompressedFile)) + using (System.IO.BinaryReader reader = new System.IO.BinaryReader(memStream)) + while (DecompressFile(true, sDir, reader, progress, out _)) { }; break; } @@ -530,12 +495,12 @@ namespace Barotrauma { try { - using FileStream inFile = File.Open(sCompressedFile, System.IO.FileMode.Open, System.IO.FileAccess.Read); - using GZipStream zipStream = new GZipStream(inFile, CompressionMode.Decompress, true); - while (DecompressFile(false, "", zipStream, null, out string fileName)) - { - paths.Add(fileName); - } + using (var memStream = DecompressFileToStream(sCompressedFile)) + using (System.IO.BinaryReader reader = new System.IO.BinaryReader(memStream)) + while (DecompressFile(false, "", reader, null, out string fileName)) + { + paths.Add(fileName); + } } catch (System.IO.IOException e) { diff --git a/Barotrauma/BarotraumaShared/SharedSource/Utils/ToolBox.cs b/Barotrauma/BarotraumaShared/SharedSource/Utils/ToolBox.cs index e7a38ef78..1f5b69a16 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Utils/ToolBox.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Utils/ToolBox.cs @@ -3,13 +3,12 @@ using Barotrauma.Networking; using Microsoft.Xna.Framework; using System; using System.Collections.Generic; -using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using Barotrauma.IO; using System.Linq; using System.Reflection; using System.Security.Cryptography; using System.Text; -using System.Runtime.CompilerServices; namespace Barotrauma { @@ -161,7 +160,7 @@ namespace Barotrauma public static string RemoveInvalidFileNameChars(string fileName) { - var invalidChars = Path.GetInvalidFileNameChars().Concat(new char[] {':', ';', '<', '>', '"', '/', '\\', '|', '?', '*'}); + var invalidChars = Path.GetInvalidFileNameCharsCrossPlatform().Concat(new char[] {';'}); foreach (char invalidChar in invalidChars) { fileName = fileName.Replace(invalidChar.ToString(), ""); @@ -424,7 +423,7 @@ namespace Barotrauma for (int i = 0; i < numberOfBits; i++) { bool bit = originalBuffer.ReadBoolean(); - buffer.Write(bit); + buffer.WriteBoolean(bit); } buffer.BitPosition = 0; @@ -713,9 +712,14 @@ namespace Barotrauma return e; } - public static void ThrowIfNull(T o) + public static void ThrowIfNull([NotNull] T o) { if (o is null) { throw new ArgumentNullException(); } } + + public static string GetFormattedPercentage(float v) + { + return TextManager.GetWithVariable("percentageformat", "[value]", ((int)MathF.Round(v * 100)).ToString()).Value; + } } } diff --git a/Barotrauma/BarotraumaShared/changelog.txt b/Barotrauma/BarotraumaShared/changelog.txt index 3b27b64c9..1e642870f 100644 --- a/Barotrauma/BarotraumaShared/changelog.txt +++ b/Barotrauma/BarotraumaShared/changelog.txt @@ -1,3 +1,129 @@ +--------------------------------------------------------------------------------------------------------- +v0.19.3.0 +--------------------------------------------------------------------------------------------------------- + +Unstable only: +- Fixed deconstructors and research stations showing what unidentified genetic materials are. +- Fixed fabricator not showing the number of required items on recipes. +- Fixed a crash in Fabriactor.DrawInputOverLay. +- Visual improvements to draggable item UIs. +- Fixed reactor sliders adjusting to the received signals until the received value has been matched, leading to buggy-looking behavior when the sliders adjust by themselves after the signal wires have been disconnected. Now the reactor stops following the signals if nothing is received in 1 second. +- Misc fixes and improvements to Camel. +- Fixed vote-kicked players being unable to rejoin when they're unbanned. + +Changes: +- Updated our runtime to .NET 6, which should yield significant performance improvements. Do note that this unfortunately means we'll have to drop support for macOS versions older than 10.15, but we have taken some measures to help the affected Mac players continue having access to Barotrauma. More info here https://store.steampowered.com/news/app/602960/view/3367025204056277713. +- First version of reworked tutorials. Still very much a work in progress (only the 1st tutorial that teaches you the very basics is close to done), but would still appreciate feedback! +- Changed unit load device capacity to 12 (because the sprite has space for 12) and made them waterproof. +- Changed fabricator skill calculations: the most inadequate of the required skills determines the fabrication time (instead of the average). +- Made dying drop a characters' skills towards the maximum initial skill instead of minimum. +- Added a new keybind for opening and closing the chat box. The default bind is B. +- Added a warning if a new keybind overlaps with any of player's existing binds. +- Balanced existing mineral missions: adjusted rewards & required minerals and required some minerals to be handed over to the outposts as proof of their existence. +- Added new mining missions, including some in the abyss. + +Submarines: +- Added submarine tiers. Higher-tier submarines can be upgraded futher than lower-tier submarines. +- Overhauled and balanced submarine upgrades. +- Added an upgrade that adds a mineral scanner to nav terminals and sonar monitors. +- Submarine class now affects which upgrades are available for the sub. +- Removed the Deep Diver class: the way we see it, Deep Divers didn't have a clear enough role in the game, especially considering that hull upgrades served pretty much the same purpose. In practice, the only clear benefit of a Deep Diver was being able to get through the very last levels of the campaign, and having to switch to one just for that purpose wasn't fun. Now any submarine with full hull upgrades can get all the way to the end of the campaign. + +Fixes: +- Fixed a level generation issue that sometimes made the level impassable if there happened to be a cave right above the outpost. +- Fixed holes on sloped walls being impossible to pass through when you're swimming straight down/up (or straight right/left depending on the wall): the walls are technically considered either horizontal or vertical (depending on the angle of the slope), and you would have to swim in a direction perpendicular to this "technical" direction of the wall. +- Fixed retrying the Hognose mission making a new Hognose join your crew every time. +- Fixed idling NPCs sometimes getting stuck on ladders. +- Fixed mirrored turrets being displayed backwards on status monitor. +- Fixed character's hands getting "stuck" if you handcuff yourself while dragging someone. +- Fixed dragged character's arms not being pulled towards you, making it look like you're dragging them without touching if you run or walk away while dragging. +- Fixed dragged bots slowly moving constantly, preventing them from switching to the normal standing pose. +- Fixed bots having trouble fixing leaks in multi-hull rooms: they were required to be in the same hull as the leak, which prevented them from fixing leaks in e.g. R-29's bilge. +- Fixed combat missions not ending the round if both crews are dead. +- Fixed bots stating the name of the character they're firing at with turrets, making it seem like they know the name of every pirate they come across and magically recognize them through the walls of the enemy sub. +- Fixed chaingun rotation speed not being affected by the weapons skill. +- Fixed crashing when using ':' in item assembly names on Linux platforms. +- Fixed ImmuneToPressure ability flag being ignored on characters who don't need air (in practice meaning that you can get killed by pressure if you get huskified even if you have a talent that makes you immune to pressure). +- Disallow using the "reloadwearables" and "loadwearable" when a gamesession is active because it leads to a crash. These commands are intended to be used in the character editor. +- Fixed geneticmaterialcrawler_unresearched3 producing mudraptor genes. + +Submarine editor: +- Fixed sub editor background images not saving. + +Optimization: +- Optimized affliction that apply other afflictions on the character (e.g. radiation sickness, drunkenness, opiate withdrawal). +- Physics optimization: fixed submerged items' physics bodies staying active indefinitely even after they've come to rest due to buoyant forces being applied on them constantly. Now we stop updating bodies that have come to rest on the floor and aren't light enough to float. +- Optimized AI objectives that make the bots fetch items (combat, contain item, decontain item, get item). + +Multiplayer: +- Fixed "kick" button staying disabled indefinitely if you vote to kick someone and the vote doesn't go through. +- Fixed Steamworks publish tab showing the "free weekend" message when using Steam family sharing. + +Modding: +- Fixed inability to localize item names if the name is defined directly in the item config. +- Allowed defining where mineral mission resources are spawned using the "positiontype" attribute. The supported types are "MainPath", "SidePath", "Cave", and "AbyssCave". + +--------------------------------------------------------------------------------------------------------- +v0.19.2.0 +--------------------------------------------------------------------------------------------------------- + +Unstable only: +- Fixed an item getting placed in the sub editor when you select one from the entity list. +- Made flak cannon ammo proximity-triggered. +- Made flak cannon's sounds and visual effects more powerful. +- Fixed LightComponents turning themselves on when the round starts. +- Fixed "Input string was not in a correct format" when loading favorite/recent servers with an empty QueryPort. +- Fixed deconstructor showing contained items in the deconstruction output. +- Fixed double coilgun sometimes not playing a sound on every shot. +- Change the cursor to a hand on draggable item UIs. +- Fixed crashing during level generation if abyss resources have not been configured. +- Fixed hull & item repairs (and presumably replacing lost shuttles) not working in single player unless you save and reload. +- Visual improvements to Camel. +- Fixed timer that prevents recently joined players from voting to kick working the wrong way around. +- Fixed inability to resize a resizeable structure when placing it in the sub editor. + +Changes: +- Reintroduced separate local/radio voice chat keys as a legacy option. Now it's again possible to speak with voice activation by default and use a push-to-talk button for radio, the same way as before, by setting the chat mode to Local and using the new radio voice chat hotkey. +- Changed reactor temperature bar colors (from blue to red). +- Higher quality stun batons cause heavier stun. +- Disabled the autodocking prompt (which verifies whether you actually want to dock when docking is initiated by an automated circuit) in single player. +- Minor tweaks to the end of PvP missions to make them a little less underwhelming: instead of ending the round immediately when one team is dead (without even giving enough time to see the enemy die), there's a bried delay, a message box and a camera transition to let the players see what happened. + +Submarines: +- Fixed floating light component in Orca 2. +- Medical fabricator now consumes 500 power on all submarines, to be consistent with other fabricators +- Rebalanced Engine Force values to better match hull size. Most Scouts (Azimuth, Orca2, Remora, Winterhalter) are now faster. Humpback, Typhon and Orca slightly slower. +- Winterhalter and Remora are now Scout class ships, Deep Diver class will be removed. +- Introduced submarine tiers. Submarine tiers and class affect the max level of submarine upgrades that apply / can be bought. +- Updated prices of all submarines to match tiers. +- Gave Typhon 2 better stats and even more firepower, to outclass the original Typhon. +- Improved R-29 speed and gave a Flak cannon +- Added Large weapon hardpoints to Berilia to make it a Tier 3 transport. + +Optimization: +- Optimizations to the talent system, particularly when the talent menu is open and when there's a large number of talents (e.g. when using mods that make all talents available to every class). + +Multiplayer: +- Significantly sped up file transfers (mods, submarine files, campaign saves). +- The minimum kick vote counts are no longer rounded down. Previously if you had for example four players on the server and the minimum vote count set to 60%, kicking would require 2 votes, now it requires 3. + +Submarine editor: +- Fixed turret lightsource rotation not refreshing in the sub editor when flipping the item. +- Fixed turret lightsource rotation not refreshing in the sub editor when flipping the item. + +Fixes: +- Fixed linked subs still sometimes getting placed on the wrong side of the docking port when switching subs. +- Fixed PvP team assignment sometimes being wildly imbalanced, even if there's enough players with no preference to make the team sizes equal. +- Fixes to ruin door connections, wiring and connection panels. +- Fixed "insurance policy" giving the money to the dead character instead of the bank. +- Fixed damage to mirrored wall pieces resetting between rounds. +- Increased the minimum width of cave tunnels to prevent impassable paths. +- Fixed deconstructor input slots becoming unlocked when starting a new round while the deconstructor is running. + +Modding: +- Fixed console errors when trying to check int values with PropertyConditionals. +- Fixed melee weapon's StrikingPowerMultiplier only affecting the afflictions defined in the Attack, not ones defined in the status effect. + --------------------------------------------------------------------------------------------------------- v0.19.1.0 --------------------------------------------------------------------------------------------------------- @@ -15,9 +141,9 @@ Unstable only: - Fixed server trying to place all previously spawned respawn items into containers on every respawn, even if the items have already been removed. Happened because we never cleared respawnItems, and because we used that list when placing new respawn items into containers. Changes and additions: -- Overvoltage makes devices perform better, increasing the output of engines, making fabricators, deconstructors and fabricators operate faster, electrical discharge coils do more damage and oxygen generators generate more oxygen. Incentivizes operating the reactor manually and hopefully makes it a little more engaging. +- Overvoltage makes devices perform better, increasing the output of engines, making fabricators, deconstructors and pumps operate faster, electrical discharge coils do more damage, batteries recharge faster and oxygen generators generate more oxygen. Incentivizes operating the reactor manually and hopefully makes it a little more engaging. - Added more randomness to junction box overvoltage damage, and made partially damaged boxes take more damage from overvoltage. Prevents all boxes from breaking at the same time, making overvoltage less of a pain in the ass to deal with and intentionally overvolting the devices more worthwhile. -- Experimental: Added a way to immediately increase/decrease the temperatureof the reactor for a brief amount of time (atm bumps the gauge up/down by a fifth, and the boost fades out in 20 seconds). Allows reacting to load fluctuations very quickly, and to conserve fuel by operating the reactor at a lower fission rate = serves as another incentive to operate it manually. +- Experimental: Added a way to immediately increase/decrease the temperature of the reactor for a brief amount of time (atm bumps the gauge up/down by a fifth, and the boost fades out in 20 seconds). Allows reacting to load fluctuations very quickly, and to conserve fuel by operating the reactor at a lower fission rate = serves as another incentive to operate it manually. - Signals no longer set the fission and turbine rates of the reactor instantaneously, making automated reactor circuits less overpowered. They are still viable, but especially now with the addition of the extra incentives for operating the reactor manually, they're no longer as clearly the best and most efficient way to operate the reactor, making manual operation more worthwhile. - Added a Large Weapon Hardpoint. - Railgun is now considered a large weapon. @@ -188,6 +314,21 @@ Modding: - Added new properties to StatusEffect's SpawnCharacter feature: Stun, AfflictionOnSpawn, AfflictionStrength, TransferControl, RemovePreviousCharacter, TransferBuffs, TransferAfflictions, TransferInventory. - Fixed bots always choosing their "personality trait" from the first 6 even if more are modded in. +--------------------------------------------------------------------------------------------------------- +v0.18.15.2 (MacOS only) +--------------------------------------------------------------------------------------------------------- + +- Fixed crashes on MacOS 10.13 and 10.14. This seems to have happened because Microsoft quietly dropped support for these versions in .NET Core in late 2021, and we didn't realize until this hotfix when we deployed with a sufficiently new version of the technology. +- Fixed inability to use the voice chat on some MacOS versions, due to the game not having permissions to access the microphone as a result of the aforementioned .NET Core upgrade. + +--------------------------------------------------------------------------------------------------------- +v0.18.15.1 +--------------------------------------------------------------------------------------------------------- + +- Fixed frequent crashing in the submarine editor. The crashes were caused by modifying multiple entities at the same time, such as by selecting an entity of the same type as the last entity that was edited. +- Fixed dragged objects becoming invisible if you bring the cursor over a UI element in the submarine editor. +- Fixed a bug that sometimes caused radio voice chat to be muffled. + --------------------------------------------------------------------------------------------------------- v0.18.15.0 --------------------------------------------------------------------------------------------------------- @@ -259,6 +400,7 @@ Modding: v0.18.11.0 --------------------------------------------------------------------------------------------------------- +Bugfixes: - Disabled project-wide invariant globalization, which was meant to address "couldn't find a valid ICU package installed on the system" errors on some Linux distributions. The fix caused issues with case-insensitive comparisons and converting to upper or lower case in non-latin alphabets. - Fixed tutorial characters spawning without a headset. - Fixed inability to bind keys to LMB by clicking on the input box. diff --git a/Barotrauma/BarotraumaTest/CommonnessInfoTests.cs b/Barotrauma/BarotraumaTest/CommonnessInfoTests.cs new file mode 100644 index 000000000..ee85a5206 --- /dev/null +++ b/Barotrauma/BarotraumaTest/CommonnessInfoTests.cs @@ -0,0 +1,84 @@ +using Barotrauma; +using FluentAssertions; +using FsCheck; +using Xunit; +using static Barotrauma.ItemPrefab; + +namespace TestProject +{ + public class CommonnessInfoTests + { + private class CustomGenerators + { + + public static Arbitrary CommonnessInfoGeneratorOverride() + { + return Arb.From(from float commonness in Arb.Generate().Where(IsValid) + from float? abyssCommonness in Arb.Generate().Where(IsNullableValid) + from float? caveCommonness in Arb.Generate().Where(IsNullableValid) + select new CommonnessInfo(commonness, abyssCommonness, caveCommonness)); + + static bool IsValid(float commonness) => !float.IsNaN(commonness) && commonness > float.MinValue && commonness < float.MaxValue; + static bool IsNullableValid(float? commonness) => !commonness.HasValue || IsValid(commonness.Value); + } + } + + public CommonnessInfoTests() + { + Arb.Register(); + Arb.Register(); + } + + [Fact] + public void TestInheritedCommonness() + { + Prop.ForAll((child, parent) => + { + var info = child.WithInheritedCommonness(parent); + + info.Commonness.Should().Be(child.commonness); + + if (child.abyssCommonness.HasValue) + { + info.abyssCommonness.Should().HaveValue(); + info.abyssCommonness.Should().Be(child.abyssCommonness); + } + else if (parent.abyssCommonness.HasValue) + { + info.abyssCommonness.Should().HaveValue(); + info.abyssCommonness.Should().Be(parent.abyssCommonness); + } + else + { + info.abyssCommonness.Should().NotHaveValue(); + } + + if (child.caveCommonness.HasValue) + { + info.caveCommonness.Should().HaveValue(); + info.caveCommonness.Should().Be(child.caveCommonness); + } + else if (parent.caveCommonness.HasValue) + { + info.caveCommonness.Should().HaveValue(); + info.caveCommonness.Should().Be(parent.caveCommonness); + } + else + { + info.caveCommonness.Should().NotHaveValue(); + } + }).QuickCheckThrowOnFailure(); + } + + [Fact] + public void TestPathCommonness() + { + Prop.ForAll(info => + { + info.GetCommonness(Level.TunnelType.MainPath).Should().Be(info.Commonness); + info.GetCommonness(Level.TunnelType.SidePath).Should().Be(info.Commonness); + info.GetCommonness(Level.TunnelType.Cave).Should().Be(info.CaveCommonness); + }).QuickCheckThrowOnFailure(); + } + } +} diff --git a/Barotrauma/BarotraumaTest/EndpointComparisonTests.cs b/Barotrauma/BarotraumaTest/EndpointComparisonTests.cs new file mode 100644 index 000000000..6e588b4f3 --- /dev/null +++ b/Barotrauma/BarotraumaTest/EndpointComparisonTests.cs @@ -0,0 +1,15 @@ +#nullable enable +using System.Net; +using Barotrauma.Networking; +using Xunit; + +namespace TestProject; + +public class EndpointComparisonTests +{ + [Fact] + public void TestLidgrenAddress() + { + Assert.True(new LidgrenAddress(IPAddress.Loopback) == new LidgrenAddress(IPAddress.IPv6Loopback)); + } +} \ No newline at end of file diff --git a/Barotrauma/BarotraumaTest/EndpointParseTests.cs b/Barotrauma/BarotraumaTest/EndpointParseTests.cs new file mode 100644 index 000000000..c8ccb4e43 --- /dev/null +++ b/Barotrauma/BarotraumaTest/EndpointParseTests.cs @@ -0,0 +1,67 @@ +#nullable enable +using System.Net; +using Barotrauma; +using Xunit; +using Barotrauma.Networking; +using FluentAssertions; + +namespace TestProject; + +public class EndpointParseTests +{ + [Fact] + public void TestLidgrenEndpoint() + { + Endpoint.Parse("127.0.0.1:27015") + .Should() + .BeOfType>() + .And.BeEquivalentTo( + Option.Some(new LidgrenEndpoint(IPAddress.Loopback, 27015)), + options => options.RespectingRuntimeTypes()); + } + + [Fact] + public void TestLidgrenEndpointHostName() + { + Endpoint.Parse("localhost:27015") + .Should() + .BeOfType>() + .And.BeEquivalentTo( + Option.Some(new LidgrenEndpoint(IPAddress.Loopback, 27015)), + options => options.RespectingRuntimeTypes()); + } + + [Fact] + public void TestLidgrenAddress() + { + Address.Parse("127.0.0.1") + .Should() + .BeOfType>() + .And.BeEquivalentTo( + Option
.Some(new LidgrenAddress(IPAddress.Loopback)), + options => options.RespectingRuntimeTypes()); + } + + [Fact] + public void TestSteamP2PEndpoint() + { + Endpoint.Parse("STEAM_1:1:508792388") + .Should() + .BeOfType>() + .And.BeEquivalentTo( + Option.Some(new SteamP2PEndpoint(new SteamId(76561198977850505))), + options => options.RespectingRuntimeTypes()); + } + + [Fact] + public void TestSteamP2PAddress() + { + Address.Parse("STEAM_1:1:508792388") + .Should() + .BeOfType>() + .And.BeEquivalentTo( + Option
.Some(new SteamP2PAddress(new SteamId(76561198977850505))), + options => options.RespectingRuntimeTypes()); + new SteamId(76561198977850505).StringRepresentation.Should().BeEquivalentTo("STEAM_1:1:508792388"); + } +} diff --git a/Barotrauma/BarotraumaTest/INetSerializableStructImplementationChecks.cs b/Barotrauma/BarotraumaTest/INetSerializableStructImplementationChecks.cs new file mode 100644 index 000000000..1e499dac0 --- /dev/null +++ b/Barotrauma/BarotraumaTest/INetSerializableStructImplementationChecks.cs @@ -0,0 +1,55 @@ +using System; +using System.Linq; +using System.Reflection; +using Barotrauma; +using Xunit; + +namespace TestProject; + +public class INetSerializableStructImplementationChecks +{ + private delegate bool TryFindBehaviorDelegate(Type type, out NetSerializableProperties.IReadWriteBehavior behavior); + + [Fact] + public void CheckStructMemberTypes() + { + var interfaceType = typeof(INetSerializableStruct); + var types = interfaceType.Assembly.GetTypes() + .Where(t => !t.IsAbstract && !t.IsInterface && t.IsAssignableTo(interfaceType)); + + //private static bool TryFindBehavior(Type type, out IReadWriteBehavior behavior) + TryFindBehaviorDelegate tryFindBehavior + = typeof(NetSerializableProperties) + .GetMethod("TryFindBehavior", BindingFlags.NonPublic | BindingFlags.Static, + typeof(TryFindBehaviorDelegate).GetMethod("Invoke")! + .GetParameters().Select(p => p.ParameterType).ToArray())! + .CreateDelegate(); + + foreach (var type in types) + { + var members = NetSerializableProperties.GetPropertiesAndFields(type); + foreach (var member in members) + { + void checkType(Type typeBeingChecked) + { + Assert.True(tryFindBehavior(typeBeingChecked, out _), $"{type}.{member.Name} of type {member.Type} is unsupported in {nameof(INetSerializableStruct)}"); + Type? nestedType = null; + if (typeBeingChecked.IsGenericType) + { + nestedType = typeBeingChecked.GetGenericArguments()[0]; + } + else if (typeBeingChecked.IsArray) + { + nestedType = typeBeingChecked.GetElementType(); + } + + if (nestedType != null) + { + checkType(nestedType); + } + } + checkType(member.Type); + } + } + } +} diff --git a/Barotrauma/BarotraumaTest/INetSerializableStructTests.cs b/Barotrauma/BarotraumaTest/INetSerializableStructTests.cs index 83cedcc37..e319baede 100644 --- a/Barotrauma/BarotraumaTest/INetSerializableStructTests.cs +++ b/Barotrauma/BarotraumaTest/INetSerializableStructTests.cs @@ -1,6 +1,7 @@ #nullable enable using System; +using System.Collections.Immutable; using Barotrauma; using Barotrauma.Networking; using FluentAssertions; @@ -11,7 +12,7 @@ using Xunit; namespace TestProject { // ReSharper disable UnusedMember.Local NotAccessedField.Local UnusedMember.Global - public class INetSerializableStructTests + public sealed class INetSerializableStructTests { private class CustomGenerators { @@ -25,6 +26,21 @@ namespace TestProject Arb.Register(); } + [Fact] + public void TestBitField() + { + Prop.ForAll(SerializeDeserializeBitField).VerboseCheckThrowOnFailure(); + } + + [Fact] + public void TestRanged() + { + Prop.ForAll( + Arb.Generate().Where(i => i <= 100 && i >= -100).ToArbitrary(), + Arb.Generate().Where(f => f <= 100f && f >= -100f).ToArbitrary(), + SerializeDeserializeRanged).QuickCheckThrowOnFailure(); + } + [Fact] public void TestOptional() { @@ -58,6 +74,12 @@ namespace TestProject { Prop.ForAll(SerializeDeserialize).QuickCheckThrowOnFailure(); } + + [Fact] + public void TestEnumFlags() + { + Prop.ForAll(SerializeDeserialize).QuickCheckThrowOnFailure(); + } [Fact] public void TestArray() @@ -67,6 +89,14 @@ namespace TestProject Prop.ForAll(SerializeDeserialize).QuickCheckThrowOnFailure(); } + [Fact] + public void TestImmutableArray() + { + Prop.ForAll>(SerializeDeserialize).QuickCheckThrowOnFailure(); + Prop.ForAll>(SerializeDeserialize).QuickCheckThrowOnFailure(); + Prop.ForAll>(SerializeDeserialize).QuickCheckThrowOnFailure(); + } + [Fact] public void TestNullable() { @@ -147,6 +177,26 @@ namespace TestProject Thousand = 1000 } + [Flags] + private enum EnumFlagsTest + { + None = 0, + Bit0 = 1 << 0, + Bit1 = 1 << 1, + Bit2 = 1 << 2, + Bit3 = 1 << 3 + } + + private struct TestRangedStruct : INetSerializableStruct + { + [NetworkSerialize(MinValueInt = -100, MaxValueInt = 100)] + public int IntValue; + + [NetworkSerialize(MinValueFloat = -100, MaxValueFloat = 100, NumberOfBits = 16)] + public float FloatValue; + } + +#pragma warning disable CS0649 private struct TestStruct : INetSerializableStruct { [NetworkSerialize] @@ -168,6 +218,25 @@ namespace TestProject public (T, U) NotSerializedValue; public (T, U) NotSerializedFunction() => throw new NotImplementedException(); } +#pragma warning restore CS0649 + + private static void SerializeDeserializeRanged(int intValue, float floatValue) + { + ReadWriteMessage msg = new ReadWriteMessage(); + TestRangedStruct writeStruct = new TestRangedStruct + { + IntValue = intValue, + FloatValue = floatValue + }; + + msg.WriteNetSerializableStruct(writeStruct); + msg.BitPosition = 0; + + TestRangedStruct readStruct = INetSerializableStruct.Read(msg); + + readStruct.FloatValue.Should().BeApproximately(floatValue, 0.25f); // should be enough precision + readStruct.IntValue.Should().Be(intValue); + } private static void SerializeDeserialize(T arg) where T : notnull { @@ -177,12 +246,14 @@ namespace TestProject Value = arg }; - ((INetSerializableStruct)writeStruct).Write(msg); + msg.WriteNetSerializableStruct(writeStruct); msg.BitPosition = 0; TestStruct readStruct = INetSerializableStruct.Read>(msg); - readStruct.Should().BeEquivalentTo(writeStruct, options => options.ComparingByMembers>()); + readStruct.Should().BeEquivalentTo(writeStruct, options => options + .ComparingByMembers>() + .ComparingByMembers(typeof(Option<>))); } private static void SerializeDeserializeNullableTuple(T arg1, U arg2) @@ -194,12 +265,35 @@ namespace TestProject Two = arg2 }; - ((INetSerializableStruct)writeStruct).Write(msg); + msg.WriteNetSerializableStruct(writeStruct); msg.BitPosition = 0; TupleNullableStruct readStruct = INetSerializableStruct.Read>(msg); - readStruct.Should().BeEquivalentTo(writeStruct, options => options.ComparingByMembers>()); + readStruct.Should().BeEquivalentTo(writeStruct, options => options + .ComparingByMembers>() + .ComparingByMembers(typeof(Option<>))); + } + + private static void SerializeDeserializeBitField(bool[] arg) + { + ReadWriteMessage msg = new ReadWriteMessage(); + IWritableBitField bitFieldWrite = new WriteOnlyBitField(); + + foreach (bool b in arg) + { + bitFieldWrite.WriteBoolean(b); + } + + bitFieldWrite.WriteToMessage(msg); + msg.BitPosition = 0; + + IReadableBitField bitFieldRead = new ReadOnlyBitField(msg); + + foreach (bool b in arg) + { + bitFieldRead.ReadBoolean().Should().Be(b); + } } } } \ No newline at end of file diff --git a/Barotrauma/BarotraumaTest/NetIdUtilsTests.cs b/Barotrauma/BarotraumaTest/NetIdUtilsTests.cs new file mode 100644 index 000000000..90bd2dc50 --- /dev/null +++ b/Barotrauma/BarotraumaTest/NetIdUtilsTests.cs @@ -0,0 +1,20 @@ +using System; +using Barotrauma.Networking; +using FluentAssertions; +using FsCheck; +using Xunit; + +namespace TestProject; + +public class NetIdUtilsTests +{ + [Fact] + public void TestGetIdOlderThan() + { + Prop.ForAll(id => + { + var olderId = NetIdUtils.GetIdOlderThan(id); + Assert.True(NetIdUtils.IdMoreRecent(id, olderId)); + }).QuickCheckThrowOnFailure(); + } +} \ No newline at end of file diff --git a/BuildScripts/app_1026340.vdf b/BuildScripts/app_1026340.vdf new file mode 100644 index 000000000..70d3550a6 --- /dev/null +++ b/BuildScripts/app_1026340.vdf @@ -0,0 +1,15 @@ +"appbuild" +{ + "appid" "1026340" + "desc" "" + "buildoutput" "[steamworks_sdk_install_folder]\sdk\tools\ContentBuilder\output" + "contentroot" "" + "setlive" "" + "preview" "0" + "local" "" + "depots" + { + "1026341" "[steamworks_sdk_install_folder]\sdk\tools\ContentBuilder\scripts\depot_1026341.vdf" + "1026342" "[steamworks_sdk_install_folder]\sdk\tools\ContentBuilder\scripts\depot_1026342.vdf" + } +} diff --git a/BuildScripts/app_602960.vdf b/BuildScripts/app_602960.vdf new file mode 100644 index 000000000..f2fca8b7f --- /dev/null +++ b/BuildScripts/app_602960.vdf @@ -0,0 +1,16 @@ +"appbuild" +{ + "appid" "602960" + "desc" "" + "buildoutput" "[steamworks_sdk_install_folder]\sdk\tools\ContentBuilder\output" + "contentroot" "" + "setlive" "" + "preview" "0" + "local" "" + "depots" + { + "602961" "[steamworks_sdk_install_folder]\sdk\tools\ContentBuilder\scripts\depot_602961.vdf" + "602962" "[steamworks_sdk_install_folder]\sdk\tools\ContentBuilder\scripts\depot_602962.vdf" + "602963" "[steamworks_sdk_install_folder]\sdk\tools\ContentBuilder\scripts\depot_602963.vdf" + } +} \ No newline at end of file diff --git a/Deploy/DeployAll.bat b/Deploy/DeployAll.bat new file mode 100644 index 000000000..b7f7b1ae7 --- /dev/null +++ b/Deploy/DeployAll.bat @@ -0,0 +1,4 @@ +@ECHO OFF + +cd DeployAll +dotnet run -v q diff --git a/Deploy/DeployAll.sh b/Deploy/DeployAll.sh new file mode 100644 index 000000000..511cf2276 --- /dev/null +++ b/Deploy/DeployAll.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +cd DeployAll +dotnet run -v q diff --git a/Deploy/DeployAll/DeployAll.csproj b/Deploy/DeployAll/DeployAll.csproj new file mode 100644 index 000000000..72669ffd0 --- /dev/null +++ b/Deploy/DeployAll/DeployAll.csproj @@ -0,0 +1,22 @@ + + + + Exe + net6.0 + disable + enable + + + + true + + + + true + + + + + + + diff --git a/Deploy/DeployAll/Deployables.cs b/Deploy/DeployAll/Deployables.cs new file mode 100644 index 000000000..a83936516 --- /dev/null +++ b/Deploy/DeployAll/Deployables.cs @@ -0,0 +1,111 @@ +using System; +using System.Collections.Immutable; +using System.IO; +using System.Text; +using System.Xml.Linq; + +namespace DeployAll; + +public static class Deployables +{ + public const string ResultPath = "Deploy/bin/content"; + + private const string clientProjFmt = "Barotrauma/BarotraumaClient/{0}Client.csproj"; + private const string serverProjFmt = "Barotrauma/BarotraumaServer/{0}Server.csproj"; + + private static readonly ImmutableArray<(string Project, string Runtime)> platforms = new[] + { + ("Windows", "win-x64"), + ("Mac", "osx-x64"), + ("Linux", "linux-x64") + }.ToImmutableArray(); + + public static void Generate(string configuration, Version version, string gitBranch, string gitRevision) + { + Util.RecreateDirectory(ResultPath); + + File.WriteAllText( + Path.Combine(ResultPath, "readme.txt"), + $"This is Barotrauma {configuration} v{version} ({gitBranch}, {gitRevision}) built on {DateTime.Now}"); + + foreach (var (project, runtime) in platforms) + { + string serverPath = Path.Combine(ResultPath, project, "Server"); + + void checkVersion(string projPath) + { + Version projVersion = Version.Parse( + XDocument.Load(projPath).Root? + .Element("PropertyGroup")? + .Element("Version")? + .Value ?? throw new Exception($"Version not found in {projPath}")); + if (projVersion != version) + { + throw new Exception($"Version mismatch in {projPath}: {projVersion} != {version}"); + } + } + + string serverProj = string.Format(serverProjFmt, project); + string clientProj = string.Format(clientProjFmt, project); + + checkVersion(serverProj); + checkVersion(clientProj); + + Console.WriteLine( + $"*** Building Barotrauma {configuration}{project} v{version} ({gitBranch}, {gitRevision}) to \"{Path.Combine(ResultPath, project)}\" ***"); + + DotnetCmd.Publish( + projPath: serverProj, + configuration: configuration, + runtime: runtime, + resultPath: serverPath); + Util.DeleteFiles(serverPath, + "*.png", "*.ogg", "*.webm", + "*.mp4", "*.otf", "*.ttf"); + + string clientPath = Path.Combine(ResultPath, project, "Client"); + string clientBundlePath = clientPath; + + if (project == "Mac") + { + clientPath = Path.Combine(clientPath, "Barotrauma.app", "Contents", "MacOS"); + Util.CopyDirectory("Deploy/DeployAll/macSkeleton", clientBundlePath); + + string infoPlistPath = Path.Combine(clientBundlePath, "Barotrauma.app", "Contents", "info.plist"); + string infoPlist = File.ReadAllText(infoPlistPath, Encoding.UTF8) + .Replace("{short_version_string}", $"{version.Major}.{version.Minor}.{version.Build}") + .Replace("{version}", version.ToString()) + .Replace("{current_year}", DateTime.Now.Year.ToString()); + File.WriteAllText(infoPlistPath, infoPlist, Encoding.UTF8); + } + + DotnetCmd.Publish( + projPath: serverProj, + configuration: configuration, + runtime: runtime, + resultPath: clientPath); + DotnetCmd.Publish( + projPath: clientProj, + configuration: configuration, + runtime: runtime, + resultPath: clientPath); + + if (!File.Exists(Path.Combine(clientPath, "GameAnalytics.NetStandard.dll"))) + { + throw new Exception($"GameAnalytics was not found in \"{clientPath}\""); + } + + if (project == "Mac") + { + Util.CopyDirectory(Path.Combine(clientPath, "Content", "Effects"), + Path.Combine( + clientBundlePath, "Barotrauma.app", "Contents", "Resources", "Content", "Effects")); + Util.CopyDirectory(Path.Combine(clientPath, "Content", "Lights"), + Path.Combine( + clientBundlePath, "Barotrauma.app", "Contents", "Resources", "Content", "Lights")); + } + + Console.WriteLine(""); + } + } +} \ No newline at end of file diff --git a/Deploy/DeployAll/DotnetCmd.cs b/Deploy/DeployAll/DotnetCmd.cs new file mode 100644 index 000000000..c6435e313 --- /dev/null +++ b/Deploy/DeployAll/DotnetCmd.cs @@ -0,0 +1,123 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using System.Xml.Linq; +using AsmResolver.PE; +using AsmResolver.PE.File; +using AsmResolver.PE.File.Headers; +using AsmResolver.PE.Win32Resources.Builder; + +namespace DeployAll; + +public static class DotnetCmd +{ + private const string DotnetAppName = "dotnet"; + + private const string desiredRuntimeVersion = "6.0.8"; + + public static void Publish(string projPath, string configuration, string runtime, string resultPath) + { + ProcessStartInfo psi = new ProcessStartInfo + { + FileName = DotnetAppName, + ArgumentList = + { + "publish", + projPath, + "-c", + configuration, + "-clp:ErrorsOnly;Summary", + "--self-contained", + "-r", + runtime, + "/p:Platform=x64", + "/p:ErrorOnDuplicatePublishOutputFiles=false", //TODO: fix our duplicate files + "/p:RollForward=Disable", + $"/p:RuntimeFrameworkVersion={desiredRuntimeVersion}", + "-o", + resultPath + }, + RedirectStandardOutput = true, + RedirectStandardError = true + }; + var process = Util.StartProcess(psi); + process.WaitForExit(); + string stdout = process.StandardOutput.ReadToEnd(); + string stderr = process.StandardError.ReadToEnd(); + + string errorLine = $"{stdout}\n{stderr}".Split('\n') + .First(ln => ln.Contains("Error(s)", StringComparison.OrdinalIgnoreCase)) + .Trim(); + + if (!errorLine.StartsWith("0 ", StringComparison.OrdinalIgnoreCase)) + { + throw new Exception($"Failed to build {projPath}, {errorLine}"); + } + + Console.WriteLine($" - Published \"{projPath}\" to \"{resultPath}\", {errorLine}"); + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) || !runtime.StartsWith("win")) { return; } + + // You may be wondering, what is this crap? + // Cross-compiling is something that should work perfectly, because it's super convenient. + // However, thanks to the way .NET works, cross-compiling to Windows from *nix platforms + // results in an executable with basically no metadata, and the wrong subsystem! + // (see https://github.com/dotnet/sdk/blob/375955d3a9de213a01d70eb6180298000dee30ee/src/Tasks/Microsoft.NET.Build.Tasks/GenerateShims.cs#L127-L132) + // Does it look like we're about to modify the SDK itself to solve this problem? Yeah right. + // Instead let's just take the shim generated by the SDK and fix it ourselves. + + XElement firstPropertyGroup = XDocument.Load(projPath) + .Root? + .Element("PropertyGroup") + ?? throw new Exception("PropertyGroup not found"); + + string assemblyName = firstPropertyGroup.Element("AssemblyName")?.Value + ?? throw new Exception("AssemblyName not found"); + + // This is the shim that doesn't have the stuff we want. + var fileToChange = PEFile.FromFile(Path.Combine(resultPath, $"{assemblyName}.exe")); + // Luckily, the SDK does embed all of that data in the assembly with all of the IL! + // We can just yoink it from here. + var managedAssembly = PEImage.FromFile(Path.Combine(resultPath, $"{assemblyName}.dll")); + + // Here's a whole lot of magic to set up the resources section of the executable + var resourceSection = new PESection(".rsrc", SectionFlags.ContentInitializedData | SectionFlags.MemoryRead); + var resourceDirectoryBuffer = new ResourceDirectoryBuffer(); + resourceDirectoryBuffer.AddDirectory(managedAssembly.Resources ?? throw new Exception($"{assemblyName}.dll has no resources")); + resourceSection.Contents = resourceDirectoryBuffer; + fileToChange.Sections.Add(resourceSection); + fileToChange.AlignSections(); + var dataDirectories = fileToChange.OptionalHeader.DataDirectories; + dataDirectories[2] = new DataDirectory(resourceDirectoryBuffer.Rva, resourceDirectoryBuffer.GetPhysicalSize()); + + // And here's something a little less magical that fixes the subsystem + fileToChange.OptionalHeader.SubSystem = firstPropertyGroup.Element("OutputType")?.Value == "WinExe" + ? SubSystem.WindowsGui + : SubSystem.WindowsCui; + + using var writeStream = File.Open(Path.Combine(resultPath, $"{assemblyName}.exe"), FileMode.Create); + fileToChange.Write(writeStream); + } + + public static Version GetSdkVersion() + { + ProcessStartInfo psi = new ProcessStartInfo + { + FileName = DotnetAppName, + ArgumentList = + { + "--version" + }, + RedirectStandardOutput = true, + RedirectStandardError = true + }; + var process = Util.StartProcess(psi); + process.WaitForExit(); + string stdout = process.StandardOutput.ReadToEnd(); + + return Version.Parse(stdout.Trim()); + } +} diff --git a/Deploy/DeployAll/GitCmd.cs b/Deploy/DeployAll/GitCmd.cs new file mode 100644 index 000000000..624c418e3 --- /dev/null +++ b/Deploy/DeployAll/GitCmd.cs @@ -0,0 +1,86 @@ +using System; +using System.Diagnostics; + +namespace DeployAll; + +public static class GitCmd +{ + private const string gitCmdName = "git"; + + private static ProcessStartInfo MakePsi(params string[] args) + { + var psi = new ProcessStartInfo + { + FileName = gitCmdName, + RedirectStandardError = true, + RedirectStandardOutput = true + }; + foreach (var arg in args) + { + psi.ArgumentList.Add(arg); + } + + return psi; + } + + private static void ExecCmd(out string stdOut, out string stdErr, params string[] args) + { + var process = Util.StartProcess(MakePsi(args)); + process.WaitForExit(); + stdOut = process.StandardOutput.ReadToEnd(); + stdErr = process.StandardError.ReadToEnd(); + } + + public static string GetRevision() + { + ExecCmd(out string stdOut, out _, + "rev-parse", + "--short", + "HEAD"); + + return stdOut.Trim(); + } + + public static string GetBranch() + { + ExecCmd(out string stdOut, out _, + "branch", + "--show-current"); + + return stdOut.Trim(); + } + + public static bool HasUncommittedChanges() + { + ExecCmd(out string stdOut, out _, + "status", + "--porcelain=1"); + + return !string.IsNullOrWhiteSpace(stdOut); + } + + public static bool IsRepoOutOfSync() + { + ExecCmd(out _, out _, + "fetch"); + + ExecCmd(out string remoteBranch, out _, + "status", + "-sb"); + + if (!remoteBranch.StartsWith("##")) { return true; } + if (!remoteBranch.Contains("...")) { return true; } + + remoteBranch = remoteBranch[(remoteBranch.IndexOf("...", StringComparison.InvariantCulture) + 3)..]; + remoteBranch = remoteBranch[..remoteBranch.IndexOf("\n", StringComparison.InvariantCulture)]; + + string localRevision = GetRevision(); + ExecCmd(out string remoteRevision, out _, + "rev-parse", + "--short", + remoteBranch); + remoteRevision = remoteRevision.Trim(); + + return localRevision != remoteRevision; + } +} \ No newline at end of file diff --git a/Deploy/DeployAll/Program.cs b/Deploy/DeployAll/Program.cs new file mode 100644 index 000000000..3de060435 --- /dev/null +++ b/Deploy/DeployAll/Program.cs @@ -0,0 +1,58 @@ +using System; +using System.IO; +using System.Linq; +using System.Xml.Linq; +using DeployAll; + +while (!Directory.GetFiles(".").Any(f => f.EndsWith(".sln"))) +{ + Directory.SetCurrentDirectory(".."); +} + +const string windowsClientProj = "Barotrauma/BarotraumaClient/WindowsClient.csproj"; + +Version gameVersion = Version.Parse( + XDocument.Load(windowsClientProj).Root? + .Element("PropertyGroup")? + .Element("Version")? + .Value ?? throw new Exception($"Version not found in {windowsClientProj}")); + +string gitRevision = GitCmd.GetRevision(); +string gitBranch = GitCmd.GetBranch(); + +Console.WriteLine($"DEPLOYALL - Barotrauma v{gameVersion}, branch {gitBranch}, revision {gitRevision}"); + +if (GitCmd.HasUncommittedChanges()) +{ + if (Util.AskQuestion("The repo currently has some uncommitted changes. Do you still wish to proceed? [y/n]") + .AnsweredNo()) { return; } +} +else if (GitCmd.IsRepoOutOfSync()) +{ + if (Util.AskQuestion("The repo is currently out of sync. Do you still wish to proceed? [y/n]") + .AnsweredNo()) { return; } +} + +var sdkVersion = DotnetCmd.GetSdkVersion(); +Console.WriteLine($"Using .NET SDK {sdkVersion}"); + +string configuration = Util.AskQuestion("Type 1 for Release, 2 for Unstable, enter nothing to cancel") switch +{ + "1" => "Release", + "2" => "Unstable", + _ => "" +}; +if (string.IsNullOrWhiteSpace(configuration)) { return; } + +Deployables.Generate(configuration, gameVersion, gitBranch, gitRevision); + +if (Util.AskQuestion("Would you like to upload the generated builds to Steam? [y/n]") + .AnsweredNo()) { return; } + +SteamPipeAssistant.PrepareSteamCmd(); +SteamPipeAssistant.PrepareScripts(configuration, gameVersion, gitBranch, gitRevision); + +string userName = Util.AskQuestion("Type your Steam username to upload to Steamworks, enter nothing to skip uploading"); +if (string.IsNullOrWhiteSpace(userName)) { return; } + +SteamPipeAssistant.Upload(userName, configuration); diff --git a/Deploy/DeployAll/SteamPipeAssistant.cs b/Deploy/DeployAll/SteamPipeAssistant.cs new file mode 100644 index 000000000..e111af644 --- /dev/null +++ b/Deploy/DeployAll/SteamPipeAssistant.cs @@ -0,0 +1,248 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.IO.Compression; +using System.Linq; +using System.Runtime.InteropServices; + +namespace DeployAll; + +public static class SteamPipeAssistant +{ + private abstract record ScriptItem(string Name) + { + public abstract override string ToString(); + } + + private record SingleItem(string Name, string Value) : ScriptItem(Name) + { + public override string ToString() => $"\"{Name}\" \"{Value}\""; + } + + private record AggregateItem(string Name, params ScriptItem[] SubItems) : ScriptItem(Name) + { + public override string ToString() + { + return $"\"{Name}\"\n" + + "{\n" + + string.Join("\n", + SubItems.Select(it => it.ToString()) + .SelectMany(s => s.Split("\n")) + .Select(s => $"\t{s}")) + + "\n}"; + } + } + + private static string steamCmdUrl + => true switch + { + _ when RuntimeInformation.IsOSPlatform(OSPlatform.Windows) + => "https://steamcdn-a.akamaihd.net/client/installer/steamcmd.zip", + _ when RuntimeInformation.IsOSPlatform(OSPlatform.Linux) + => "https://steamcdn-a.akamaihd.net/client/installer/steamcmd_linux.tar.gz", + _ when RuntimeInformation.IsOSPlatform(OSPlatform.OSX) + => "https://steamcdn-a.akamaihd.net/client/installer/steamcmd_osx.tar.gz", + _ => throw new Exception($"Unsupported host platform: {RuntimeInformation.OSDescription}") + }; + + private static string[] steamCmdFilenames + => true switch + { + _ when RuntimeInformation.IsOSPlatform(OSPlatform.Windows) + => new[] { "steamcmd.exe" }, + _ when RuntimeInformation.IsOSPlatform(OSPlatform.Linux) + => new[] { "steamcmd.sh", "linux32/steamcmd", "linux32/steamerrorreporter" }, + _ when RuntimeInformation.IsOSPlatform(OSPlatform.OSX) + => new[] { "steamcmd.sh", "steamcmd" }, + _ => throw new Exception($"Unsupported host platform: {RuntimeInformation.OSDescription}") + }; + + private const string SteamCmdPath = "Deploy/bin/steamcmd"; + + public static void PrepareSteamCmd() + { + if (Directory.Exists(SteamCmdPath)) + { + Console.WriteLine($"SteamCMD found at {SteamCmdPath}, skipping download"); + return; + } + Console.WriteLine($"Downloading SteamCMD to {SteamCmdPath}"); + + Util.RecreateDirectory(SteamCmdPath); + + var steamCmdPkg = Util.DownloadFile(steamCmdUrl).ToArray(); + + if (Path.GetExtension(steamCmdUrl) == ".zip") + { + using var memStream = new MemoryStream(steamCmdPkg); + using ZipArchive archive = new ZipArchive(memStream, ZipArchiveMode.Read); + archive.ExtractToDirectory(SteamCmdPath); + } + else + { + string downloadResultPath = Path.Combine(SteamCmdPath, Path.GetFileName(steamCmdUrl)); + File.WriteAllBytes(downloadResultPath, steamCmdPkg); + + var psi = new ProcessStartInfo + { + FileName = "tar", + ArgumentList = + { + "-xf", + downloadResultPath, + "-C", + SteamCmdPath + }, + RedirectStandardError = true, + RedirectStandardOutput = true + }; + var process = Util.StartProcess(psi); + process.WaitForExit(); + + File.Delete(downloadResultPath); + + foreach (var filename in steamCmdFilenames) + { + psi = new ProcessStartInfo + { + FileName = "chmod", + ArgumentList = + { + "+x", + Path.Combine(SteamCmdPath, filename) + }, + RedirectStandardError = true, + RedirectStandardOutput = true + }; + process = Util.StartProcess(psi); + process.WaitForExit(); + } + } + + Console.WriteLine("SteamCMD downloaded and extracted"); + } + + private const string ScriptPath = "Deploy/bin/scripts"; + private const string BuildOutput = "Deploy/bin/output"; + + private const string appIdScriptFileFmt = "app_{0}.vdf"; + + private const ulong ClientAppId = 602960; + private const ulong ClientWindowsDepotId = 602961; + private const ulong ClientLinuxDepotId = 602962; + private const ulong ClientMacDepotId = 602963; + + private const ulong ServerAppId = 1026340; + private const ulong ServerWindowsDepotId = 1026341; + private const ulong ServerLinuxDepotId = 1026342; + + private static ScriptItem PrepareDepotScript(ulong depotId, string contentPath) + { + var childItems = new List + { + new SingleItem("DepotID", depotId.ToString()), + new SingleItem("contentroot", contentPath), + new AggregateItem("FileMapping", + new SingleItem("LocalPath", "*"), + new SingleItem("DepotPath", "."), + new SingleItem("recursive", "1")), + new SingleItem("FileExclusion", "config_player.xml"), + new SingleItem("FileExclusion", "Thumbs.db"), + new SingleItem("FileExclusion", ".DS_Store"), + new SingleItem("FileExclusion", "__MACOSX"), + }; + + if (depotId == ClientMacDepotId) + { + childItems.Add(new SingleItem("InstallScript", "Barotrauma.app/installscript.vdf")); + } + + var script = new AggregateItem("DepotBuildConfig", childItems.ToArray()); + var scriptFileName = Path.Combine(ScriptPath, $"depot_{depotId}.vdf"); + File.WriteAllText(scriptFileName, script.ToString()); + return new SingleItem(depotId.ToString(), Path.GetFullPath(scriptFileName)); + } + + private static void PrepareAppScript(ulong appId, string configuration, Version version, string gitBranch, string gitRevision) + { + var depotScripts = new AggregateItem("depots", appId switch + { + ClientAppId => new[] + { + PrepareDepotScript(ClientWindowsDepotId, + Path.Combine("Windows", "Client")), + PrepareDepotScript(ClientMacDepotId, + Path.Combine("Mac", "Client")), + PrepareDepotScript(ClientLinuxDepotId, + Path.Combine("Linux", "Client")) + }, + ServerAppId => new[] + { + PrepareDepotScript(ServerWindowsDepotId, + Path.Combine("Windows", "Server")), + PrepareDepotScript(ServerLinuxDepotId, + Path.Combine("Linux", "Server")) + }, + _ => throw new InvalidOperationException() + }); + + var script = new AggregateItem("appbuild", + new SingleItem("appid", appId.ToString()), + new SingleItem("desc", $"{configuration} v{version} ({gitBranch}, {gitRevision})"), + new SingleItem("buildoutput", Path.GetFullPath(BuildOutput)), + new SingleItem("contentroot", Path.GetFullPath(Deployables.ResultPath)), + new SingleItem("setlive", appId switch + { + ClientAppId => "experimental", + ServerAppId => "development", + _ => throw new InvalidOperationException() + }), + new SingleItem("preview", "0"), + depotScripts); + + var scriptFileName = Path.Combine(ScriptPath, string.Format(appIdScriptFileFmt, appId)); + File.WriteAllText(scriptFileName, script.ToString()); + } + + public static void PrepareScripts(string configuration, Version version, string gitBranch, string gitRevision) + { + Console.WriteLine($"Preparing SteamPipe scripts for {configuration} v{version} ({gitBranch}, {gitRevision})"); + + Util.RecreateDirectory(ScriptPath); + + PrepareAppScript(ClientAppId, configuration, version, gitBranch, gitRevision); + PrepareAppScript(ServerAppId, configuration, version, gitBranch, gitRevision); + + Console.WriteLine(""); + } + + public static void Upload(string userName, string configuration) + { + Util.RecreateDirectory(BuildOutput); + + ProcessStartInfo psi = new ProcessStartInfo + { + FileName = Path.Combine(SteamCmdPath, steamCmdFilenames.First()), + ArgumentList = + { + "+login", + userName + }, + RedirectStandardOutput = false, + RedirectStandardError = false + }; + + void addScriptCmd(ulong appId) + { + psi.ArgumentList.Add("+run_app_build"); + psi.ArgumentList.Add(Path.GetFullPath(Path.Combine(ScriptPath, string.Format(appIdScriptFileFmt, appId)))); + } + addScriptCmd(ClientAppId); + if (configuration == "Release") { addScriptCmd(ServerAppId); } + + psi.ArgumentList.Add("+quit"); + var process = Util.StartProcess(psi); + process.WaitForExit(); + } +} \ No newline at end of file diff --git a/Deploy/DeployAll/Util.cs b/Deploy/DeployAll/Util.cs new file mode 100644 index 000000000..6962ac512 --- /dev/null +++ b/Deploy/DeployAll/Util.cs @@ -0,0 +1,106 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Net.Http; + +namespace DeployAll; + +public static class Util +{ + public static void DeleteFiles(string path, params string[] patterns) + { + foreach (var file in patterns.SelectMany(p => Directory.GetFiles(path, p, SearchOption.AllDirectories))) + { + File.Delete(file); + string dir = file; + do + { + dir = Path.GetDirectoryName(dir) ?? ""; + if (Directory.GetFiles(dir, "*", SearchOption.AllDirectories).Length == 0) + { + Directory.Delete(dir, recursive: false); + } + else + { + break; + } + } while (dir.LastIndexOf('/') > 0); + } + } + + public static void CopyDirectory(string sourceDir, string destinationDir) + { + var dir = new DirectoryInfo(sourceDir); + + DirectoryInfo[] dirs = dir.GetDirectories(); + + Directory.CreateDirectory(destinationDir); + + foreach (FileInfo file in dir.GetFiles()) + { + string targetFilePath = Path.Combine(destinationDir, file.Name); + file.CopyTo(targetFilePath); + } + + foreach (DirectoryInfo subDir in dirs) + { + string newDestinationDir = Path.Combine(destinationDir, subDir.Name); + CopyDirectory(subDir.FullName, newDestinationDir); + } + } + + public static void DeleteDirectory(string path) + { + if (Directory.Exists(path)) + { + Directory.Delete(path, recursive: true); + } + } + + public static void RecreateDirectory(string path) + { + DeleteDirectory(path); + Directory.CreateDirectory(path); + } + + public static IReadOnlyList DownloadFile(string url) + { + var httpClient = new HttpClient(); + var response = httpClient.Send(new HttpRequestMessage( + HttpMethod.Get, + new Uri(url))); + using var stream = response.Content.ReadAsStream(); + + using var reader = new BinaryReader(stream); + var contents = new List(); + while (true) + { + byte[] bytesRead = reader.ReadBytes(1024); + if (bytesRead.Length == 0) { break; } + contents.AddRange(bytesRead); + } + + return contents; + } + + public static string AskQuestion(string question) + { + Console.WriteLine(question); + Console.Write("> "); + string answer = Console.ReadLine() ?? ""; + Console.WriteLine(""); + return answer; + } + + public static bool AnsweredYes(this string answer) + => answer.Equals("y", StringComparison.InvariantCulture); + + public static bool AnsweredNo(this string answer) + => !answer.AnsweredYes(); + + public static Process StartProcess(ProcessStartInfo info) + => Process.Start(info) + ?? throw new Exception($"Failed to start process \"{info.FileName}\""); +} \ No newline at end of file diff --git a/Deploy/DeployAll/macSkeleton/Barotrauma.app/Contents/Resources/barotrauma.icns b/Deploy/DeployAll/macSkeleton/Barotrauma.app/Contents/Resources/barotrauma.icns new file mode 100644 index 0000000000000000000000000000000000000000..688e9ecefad9ceddf62b5b942cc750da7f9f615d GIT binary patch literal 3672382 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%0D+v)UaFo!w26slE^-V;(!vY|Ty6lfoA3yP){ecTQ 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

F1L@NP>$$Q^jyuToNbu4gfmK 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ⅅX4} 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≈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


$Y$6ylJnrm=>e43ELSA~l_yBi)4g*d#L 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Д1bw&U8G({XwS&zW>*MaTGEwr!=h*ZcgRVE?=z` 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't~Gk;BC>B^|Lt(r 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

uIGy|HLqzWEmxl6WWpO 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%0D0LNRp@)d3VgwH{R^8m*nUeqnS1+)X*1yTI)! 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

    8?D-N7jkpVNwEK$(fIN3LR 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%0DhC}>(p2Cm|q#ss_P`OKW{@Pd;@Nx-=s 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

    uTGVCjqgz(yLjnR7+;?aSKh-h2aQ|ivW>jf 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ℜ5sYvx46)7RVx%6;g=)g!En52Z|M0)WGvZ!I zU+&R4Y7yuq7{y4|^Dj@b^_cy*O${)7b(+e;dL?$t@+tN+5N`E+7Oq!c3xD}H{|Ee{ zEmWiQHB{Dz+XJ`Bi>J;4bZ@~e(?krxHX80iBatW=Ey`8T$IB54yP-hK=ghTr4~-Vc zw6%qAzWp{TO@IEwKMza0OQDTuHrHQeT?Hs99~xr6{15*R>)VQVJzG~~Wt-Np03nZG zJ`0x`P`&~kd7i%xTTjQ46WLI6J*uU&YOAQJpyLl-rp^m7Dq#i#&X88;XvlX8`Sp47 zBaK1V&iC^j1R#>f)HFJIeSH<}ptw&ip4`*?yriyeB3|MT^iQTkWVK5A#YRZPs4pw|B!ckHY`+@ zirsmQ=fHEKS6$g}Xn*8Ac=hDL0<-dW`AR#yU%8~L5VTG}m-jKs%e0&K!{_~6rP1$O zqsVYnyMLr%SgLdPY^f7Cl7XjV#M&(KA>ZHMdv2u%!<(IRO3k^53`xa=O<9Y49Ui6< zt1=z$&m7!Goi3hDd5ZkNwX)@0jO5|@31oFHjR1Ro$DwRhNBj7bkHfEi^{W`MCBO7f z8ii#=v2E8N^)`knw3b&$@lt52j&nXs%8AB*>(ws0IxUB-9OM+AFA$gcTlJz=SYF#ortHxRz8E^y__m3SWIpYjQTb7@8($dpd$(EE8t^uWsp zuicNyBDvOT`HhVS%xq5p6@&Izu&{%i42HH!{pFN9w!+E68_d)as9SP3Iz10!x zy^BeWQ%94p*HfH0>Y>O{-$Oa&d-!bESsHQQYH?7iN2G#$IuDe+9d~Yor5$SpP)CXH zOgw)c_MT3L?NY$A4Ez31PeLw$zG*{+@LIfS;fQzJSt9Zh{w57rlu!H3cZxa(v@gBt zkh5s5x}evoHw%_ICmp6n1`1Aj#&ud-Pe5I5p7)Z+tAn_H0?5*ZHR9wE>KmrL!`9<) zUDTsJSMqt~u4}C>=#ZZ|FZl!T+4l+n#0Y@;KmF)?EdqFcf{mu=kzR)z`$hsM81ks-D&mW%0PB!L|-;y)VL>0r8160$_&@H>g|NIatO9uiN2hdov@W^;@% zFw`T4xWSZEl$!ggIE;~50E#3-+@F{X7cLG^MDQv3(^Tqzf?>;dYYC-w6L)y#K1|;J z&9g&e@8&7-wSY)@(43nDp5DkLk^n^ zCkG|zkWkeMs@+!O;VP=868&BBrN)P2IF-WFp6!Ot2qri`^NaOj`7Qz~u7wJO0@t;7 zUD`5jVGNIg*LVQi+A^TpL_g@wEo2ii6dq}*r(ZjjTFKkn%?15L*eorRx5j$Ph;0?< zkQuadKZTBcVOK_`P+-W#B{!;!J>4ahAe^J92ny8JCWp9;R0WL8O#v6eKCSNj{yKT^ zj%F1CFb3YM9lo)k zUNYhIp58~p(EC_jSEblcI)$+7`o7{SgOu@kUgJBm9u^jxTB3dC=O4tdwslZ)d(-+} z?+f`)KFt=ti$yvmJ=zTiR#yUrdRXKODqQjjX=)PX)Zy>k59!^g3eWTNr_bZ>RN6d0o{0?SO&a!`rzjLJ z5-9W8S>=EH-I<9u;6Hj$Rr1Wubd8*Y_jDhnPltR=Z-nP14fiA}il^(~=Z2{ZW|_zB z_vQJ59;+xE$9ncS2ey;6=e8r}Eket#Z8Ai5Q6wtxCN7;&XbK*4gS0P^d{=XR$yE)xDS}LTNhEkbCIp>L<+m!Lu-Ui@FQ| zz8VkG#nK#f%@jB65zkQeH1&6e;ScF>;!tof9V|zI< z@=BU862YjCS=ucsXPuAj8BYj#-M1?O(HpkfG^#^6ljzldM?=CzVXs|B!Es08_43L+ z0KiD^D$))jJ9g&iTyu`_?0M1ziNH999(FvB6!!`>#i8y-f7qhn!0pdI3Og8r_9pM? z?~Bm^u3ZG-PZeHul1wHO*Fip|qNevZMWLt!nog9Ab9tdWHv;F-t%|LYTJlXJZYCxt zqVA#WNWh15Z|JmVM!J=^$Rp&5Mn7n5Yv{<6q;0`X=b1dfzP55j1vG(gt*mQOx)JDJ z66sxj;oPE;1z(Z>XlM#_+bUKXuqB+&5eQFw)%{RMkdG#S(DyPzMY-TPH#Jgzp-$mD zsnZzRE%3I)dMXS2%;C_cgYp%T6g8$&PPv}Wp?Z;WTiN2?In-6H#ii_Wc&$+= z4%2Xbe|bovBll3FK6>L>FXyT}k*<6v*IgPGSc(ohelO2AT29(Z&y5e@Khkd+@;1TB zsE2Sbf2Vwxu6$QL*6K?}p-7|t-uF{ylqUVR>*)M^j(U|cO+F@oE+2G{)V0z%^K6+? z>iHE&Dh4YM}Hlivz3}AZ~x(2m==IO0I;ow)p3-aN9e8AF*(H1xOWDfY!4lF z7g>txh5{VgFubdX5}2JOjRt_zHio7|xtGmEg^i7lMt*KotLu2>(>q~ip7g8>q%CnC zYA*MN4fvZLaU*@IsY|xa8I|`~zeRm#*{-?b2<^r7D7dP?K&i}%y8HwwU%8zZ~5_tZVqmE=j% zvBhhpm&=z2qmJ!hiQuRFO6Qj6+4XQ;oSU@jyZTN#2pka*WNz+n z{5_v(vkK^0TvRaBpA(Q_v~o-{;+#8QzcX_hN$GvnHIv>i|NXuJfY=7G@lU_s8UQ1I z^=k}0h@-nZhR|q)i@@0SZkl`!g_fJ3Cq!?uMwOxVj!2LYh(zcRp^=CrD#JEpHiq=O zNe+Pl54YZL2~cH6h2F)LSlv|7oJ|lZmDn^Su7i?-P;kB!Bc=i7fsllOtiOI0S}Bh4 z6cC_-sDVQcy`C3^wY^GrhsVN>9)^F8YQ%_cBhq0k-Z}#+uke+CRm9C<^}u-`WjGRf zF3j491aoOZ6)19dODK^!!Wi1iLBhtS!!|@;LPc2x#0+b;PUX`oMnFE-?OppYaK#G}SP}WE@n%SLAw$JCPv(M!xwyW%a zz<-acT;=iuufuwGZ)fIq@@OPV43d}wKoSIV0to^n0nqPP|JYpK*iUt>5&`^v-_ZT( zPfopUTYsH1_<#)|MTy3Aea0I|Ng{L*1SAD(a5pD}J~A1EU%nvEO`Tp+J8yh-vI>;3 z(L_g5i>XoK+N^K+@(9HU7YyS`_K9Fa#C32Q3_mE_v-X?uLdPSKhN&rE=v!a5?A@6T z&nwEhL^=-#SI)JG=*^qAD2D5{G7_V*D-M7MN$-^qe$|D#v%4y8S|JL}XaFyc7 zFklogdeLcf1~lOgPSr4sAT>OLa@;BEM>ch9o@R`$P z>GT+CXF7&y+YkE|aQ zk47l`gn>Pf0(SoF`Fg#`0S6i!g6o9;NQ@v1eM8{ttZ4fpA|`@Bh=9FF!?tZXE-?4O zON#uPdw2EP)%yIJUKeEzTquF?0>1*E3fDY~f&vbH!bQdvyoKA8x3+(jdZ!zpMGBC4 zSPO%h0EW9@MPZ|C8TQJ1tdk*7o21om^4##l#$(|Cx-!2vuQ3nw(4r@9{STaR5v*Ve z#&E{_yxW}pZ$E0pKK$Ritg+3_vnq~<1}S0<|2A*kQe{Sq!sbZ{IpyN~;55}=M7llv zV|2^r09#{Wlq*rzH3xIL$5f&o+uka7@5d<;d19X&`!jg^N-bSzaQXZXe~8kSs9Y7=8{&#;@cJA3zl{9$q_19n5cRAjX;sN*Yns@iU zTaKPQTC*MCIUY-%PR5A79X^GpF3oX(KmGAf%WwXV|GSKRbG`1neZmYjx9>H&pEJabUV-g^FROd8a0CV=$>ryJiprm*%#90t6`kywgDG6 z_iT(om!3E2XMArk%Khb(4&8rNcK+yt^ejk*+4E$h9XncPZP`$sWgYi&?5tn$*6_C)oeA&2PtcZ8mEruXC1EMwL601V@Y?_OL7Fz$p#jD| z1rmSv90oZlY1Kfw>E1q@F92umUIgSA>*F|qc(obdkyb5noOvU z&R5T%2$MI}xtePj|Ms5I8U|aVay$0CRZbo~kqyYcXCGF@@FU~l!t#}Igd}5-LB2NU z!83m1@hVd>il(l{5tEFN+o`>l?vDShkN%--fHQ79`Vzyx8vn^QToxI1^+L+>mZx#+ zwdiCS&vbgv&^v`SXqTSw~<_4dAUJ9Wt~Qz@+_roIl*G?svJ|-o#t~n;pD|Y69nWF>k|$`iIey7oyxrQ2M*ke_=G^QqvRLGNXedW^@91O)?2JBoH@wlnXJjBr z_ZRK<4zdUA7{VZpr*MYiKiX5D`+fYA)A_#tCV-PCqpWA~Hql^60nm-4BLPGc zN+Kbg1cW&TU`!8ycxoU?fB*Jm4_xgCvoIfstE;}wlIo_r!klc5j;uWT?qOs}TY-U_ z!>BMiN}tW-0rLzBz(mf?n3xsfPFfDnOKKw`nCF&NiDsxJu1fj9K@g7`Zv3>h8q|lgQe~IRkx8jzD{MBFaVh!*q>ivYv?``Qvm+o*6Ioiy446Rc@y& zAqR@as~AMfK>P^wY7|MM5xt-G!2B@1jyE?)jf9YwZR;uXbL_}?BH7Q+41_zxt)5Qo zvsNrEQ&B#mp_ENW_LYmn*UHijNpZcBv!27O)ah!zh=DMO7(ACxor|WBdX^|uvu3B0 z@u`bRk-AjouU}UN1}`N_lMcIQqx^pQLAeoO#dA#{X;P-&!O;1En*OwKevW<#)5-A_ z6|NMLs?a2Mk9T?=rb)0hCDP{xX3yYvpU+y&q4!xQA%@X4I&=@EloQ6>Dh;8x zthEhFOf}ddXu*rJS_O9mD0(7vJ)n6^-E)#b_D(ggzLyxq>+*fufF2a3HRWaz#P*9S?ImmXE^O_N}d>{cK7pM;U{p z&D*}1pTS6>{G;c!QLrdNJ&C&M;b1SHW=}A4X_H`q?^NR;cmR(nU>pm0L)%NwZOUEy ztl~xHVUH;#gnyl1gqEL_5jY7i7!i1>->upEz=G4px!=|c#?{%CeJ02$T=1BZ*_eTc_6-r2BelZyzvhFMQv$w z;8?$5ue^@|;5}%zITG|MAeh0$x~vyn#%1tINpy~NPCN*Wsr_f@cctX$`Qs=W`EMdw zBtDy#RPm>eI!f!2BS*^R3sID=r@`#|{iWyQ{fWp-Mu|$KDvklpqiucLD(^aR@acV5hYf}@?iHDx< zCq8WV7roUw;0_TC%lo*S`8Jd>mi+cJSK@ z2TlR|_0j&1%A>JIHM>qm3#YR8NTcUiK6vn8b-pi)Y?TS~?!oucxq3-C^!A~go|FD8 znFoG{XTyWxJL&n7y=M&X&FKMp08nz^8(LQaKWPn>UK>UqHs!8i}3^&&EWA~cw~5ArO*71cXIrRGPUM`EYse;&`M}kEjC{8B)o<(ZJjOZ zg=aUV)^lZ#k)8OO@7k~)!+Y_DwqN9c&pgj(vK`tSUEd5szZ+=>nStR9evx81Lfw(&9XZ5d+YLG zxfLgXegJsr@RejTWN;4XBOoJZ(X#A=62y$>$*63jdu^Hr#$eHaxDEY1IO#Ng#oNuF z&H)}^NftX9;AP&mIu3{XDdk+brLSyUv9_E#@lAaUnQiaUG&(UD91M7PM9zAiYw+z) zKKZ1k=99U2Nju)L(F(o@SLo325{}qY15ToEP7u#F82^TMqwTuCk@fg=8)yN|_r(zN zJBL`KJvh$^LDw+{>n3yHjr}(~8-KSBG=Z<+@pODJGw=bp3V!rOI+?kWJ?MZQ0&hK+ z&O}ziC--|V9J5aIAUmwD$!$8WVXdC+xy@-pC!s%>H>ZrXn7?^6*+`z^rQYS83`Qlq zGM!wn#NkN-WFv7Ftjo2JqZ>a?R!^f@HqG{ZyW$i*SG)OlZ;E4f#j+ZapO=i@J7+JJ znGsPk2uD*kwSLXIvNWZO=1u;Cm$gjJjA6Mr4VG6Wik$vn_j3&4yx#E6^Pz$C1$g_w zfpRI1*WMl5Q+oTf+&+6IJ&MwJ@KtH8{l#Cc1uV%8uz)Lc4W0iTLvD}2Q;@a|_-6k) zHr3qXga%G$*Ri{nE$dDbz^kuu&AZGW9(#5+CN=o!jg&GLfk(U*9}`Tgx?N-sn)ko* zHt+EaGG}mbuug*vuK4VvgRb=F8H(POZ^p7l{ofeaBJ(fe^q&ztok$;;FzPZbb62kU zXfP!e9aXM6t-#hC8UJXam4pM1`I$FSW*{zJ1|B&TL*^5mAcD!w`J1vn=17bn`H$>~eV- z0kUcRmYRBRo|u7WVWJc@+ljy+j`d+MXHK84!iTT|4-89sD#Vbw_$=qt&Rw@M9gtH$ z)}8wQE4nYoIDW;bDKTwG$$uUqibRf(c~Le;IhYZT_uMtzWzC+gJgebP$UNB4@DAkEirmI%_Xj-d� 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

  1. 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%0DRB9FZoeK3H! zZs%+Si{gLkfWkS_;x#D*R>SqV(oYQ>8jOU$4A;_^d;mkmN_h5+OrelAx<{UYL!nt= z+96JOAH8WR@mUImLS~jOrLf>y&Bgcm?#bUDdZaVOMI(^U^6WL*m=dD$;4@Wh4QFqL zCa6?2G@}sXRdTE*?AB0Ji(?L5g>f_VU^xt_T#cJlxS$co3ou+`L!s#REqQy^F zBS5-0h92G>BbsIt5lkqJPZyzwc(ENCOx;5bkSbj6fd&-wlOGdmXm^NvcsqA~>v&v# zLVkKBmi!+akBV>XrG;EqJR!BJ<`C@^S3HVCM_x`sN@>ZKIC1U0=*STTK<$76ps5i$ z`{u6iMjwUe43*VrE4-w>=bXtT3Yf5Oex&?DWmp)?jK~U5DiV5qGP)@JtmnSI&V)RL z7wN7v)9-iIc2aC=F1j1Lq4yLX1GdNKp>JGc`bpndKNYL*;B_yFTXgtPfK`Ao3Z{nq z`5T-wJy2o+qizW#?#>4n;u>E5+qCH`7@Ui$<&AOSmnQ;|G=@%ICUxlF*IRLar5z5R z>u}D7%ReOz?S*f=k_z6=Opzi}zb)Dv@WJVwe%)!OLz&dZT&*&Eka-;16d zhoTQ}`;K5hjY`AAf3pJ+v2lHU|`wa4*{3GMFDUA*KBR`O4%EzT| z$>0yYRX%V|dAWsDG1jLc;Qlm48tdS@Uxd%gXH$_zpNBEt{gzKyY}w8`1sK4ig!)d0 z55=`h7h~ruuSP#S_Yu!bv=`;-A#h&T(V1xC)r%LR7FZho@T2HDd?bd3hiTv3Nc|Dg z=-{KfQJl{b%Ka4DQ!4L(zU(`4G_{R>>zBW#@LqpZP}}O{Pkt6fYl!3|QV#(%$#RPe zi_y?dN+9b_q5B48LZjL`+c0D;B-q_d1Wf_;3y!`>`cdC-`dfL`h`vX3qj*GnKI>52 zr2VtSnvJv?>%WfTM$2vZn|b87iKud{!uhy5Um1_YhT|VE1R~)6KHP*2G(L|zXf(H)|bZl3!XRWMFT_R>9-<- zEXTf*J@Ly=eud%(&jhYbxlwul^{;=O(qs<@4foMruH?m}zIOliD9d&A`KYDv`k-GLZhZZ~*JErl9|`E59o}^~#;3-UQtWjX%tK9w z;=;fM46bqn)5%oi*qr$WURUUg(G)3!!2 z;uxVTKgq!l?m;W+tLTt*dn}z-wujQS4ixeWmo6l^OP-QsIQID-5mLg4QDf3-jRkf} zIC1qv!ofp_4kx`yWme;X(Z=mLzVIE4BZK{YQHaHI8AW{R z0g40+=^4Up(YDffbOWzj5fX)!5dcyrY%Zt*c0wwi;o1e*Wdz@XWjx)trUFvOiBqTw#G> z_4ksM(l&OF5xkGQ`a)bednxT-h9s`fb5|jk&{(ri&a3}Q<-k2tmq|INl3&2 z1;#y63C@&81rOJzbySP6&+(oKK{+p#P(Rl|<5}X=O8a3YZ^QG1*>VI46;CT<+f6`a z&AF+lID`c~-j^?4#sa=M8LV1>Ed?0Q+v_x9Ii6R7T#tm*c{x8V z6v=%}MDYtH`N#`L@u&|aLOhA0s>f0MmH~`<@}U($M&#`&=zl~!kQ)S-f-fxvb7ePPEvcPN-@s8Ik_(J0SAYh0Z9-W7G3ALp7ps?vRD*wWc%75ksGdI~G%cOtt!YH96Vc@qxV#}R%uQ&1!IB3 za}@^^XvDj0$TU4S&r3s^u%R(Xyb*tvP{uU?UAxko+RaUkPa+8KPpM#89;yPl3VTy$ zbLuy3go+{j4uyI5L8WTl7TQ+cCrSr8sRzt+HOKqbh!u%#=|e~%`Grs4~5;Dav2l9c_R3%_t`4eDLwjcYrtoBq#weIv_P6* zcYtTPEu=`0ufBbK6duB$Pgwt4*~&QbPyQfkj_r(=BYUD0!&w3QIC_69>WeWdKBe^* zg6`;;3gS$3wRN%%!YjeK{@y-Ps)|yL9Yb`b(;8t7=@r&9B~}Uz+9F)mGKAIwFBsuYzAgabvu7{x_uTQQv`_ z?Zs<1!RdUO+4cq;0OUs7?^^o0mFR^`;dGA*C{iWQ%HwE0^+tu;;;8bxFZZ%Ozn9{n zGM4-*8>XC15$I?$}zfOxCySn2#3aag9t#jcJ zHjUPLei-U&aakh++AG~$XF3OIzd6%JYD!D>C_6G5QqzdX z?~62q?Jevt=Ps;RncU*2*{JL!e3~eu_0Z59_dEE)3kj~>m$l&D0_Rl)9O(HiM0QkZ zeFi@F_4kvGLL?4wtnt6I8{ET?@(4Lv*ii|pq87$bZ+}b>C9-KHQJt5r#mx)XB6_LB zzYzlsIJSzAdm{igZ?#H$J}f_*n@YVAQYtqZ0_4Lg_`?IkQOBB6v=mMNJ)cKkc_CHy z_q#3D2*3y;zc&)2rMVTwpQuD&B{Pu9vyuaY>z%8xsL@t9TCuApO3CLp3TpSCd@t65 z!`0tB7~>mJrg})z*~(8rUED96kF)2_k}i;MMXLkoAx7CFD9WSA`@&pLWmo*$zy5zv zdWk6Ij5UBCZ95WuH}XYFUw-lBbgp+W7Fy8T7IP|&>D+<)o=!Rp^;3Wt8e{!{L;DWJ zum1K|$xH2=rJrlz@7qi3;++rPrsefxcoX~`ToaDAZ_G@T7(0L#}J^e}4vtE_EN!qS{kmu@qL}Q1@x;e8t~!R09hkvF6G zkJ9p%vuUnxN_Z@uj00EdTt-xR57+Ygf!E{O__ZYey06~Pxpr?O0*OL|(ka(2oiKvK zYmDwOWulSdwGWpl2EAq>PJDQRD4)DR^QGM{#oHgglcEO1XRXF0@@_~arn6gAZ4(88$i-uzM}C(8^EvD z05JI>IVv&?h8yHC98@GU1Y2M;)MXiATMt;4i|TcL=1@2gf$HjVgiGZ^iG08FYljii zAS`RhXD40YK31#;C}y(=XpSn7^&Tyf^m3|9P0+s}Ez`+T&f(a9QlPXb zh6pIosjN8kh_2yKJ19Dnc_=h0C=A*nPoz{3w&+79u$zLQkk(L-pu{!ydtAV~sq&+8 z>k!E$K-CEE0*Lq0TOe{P_?VL(#+GY z*Vuhjad1dzoU`vK)EROk(&+)nlyQZDS6+D~5f<~CGleKupG%>MMh2*y=vmM}qA|kM z2H{j;$a`nXze0oxse*xp=tO$GGln>NeIgXx!@oUGl{K$d=o02t0DW$j1Mhl#&!Q(P zv<`FmQU!8eA2@a>ZeoaWXoa^MgqB4;L^5E7nTCDsQSr*Ym@3;4?K?WteiTB8ii;@H zg}`Ao_jv@Y89X;zR2YD9!(J6+EYPxug;HVHeBv8#{U$c9EQ;=i7T^rRDZFzo=0_86 zkfII-XuYD2ctZTtfvlYc05DEuL0%c8DXMuVtil>!(r2)>- zwK_ZxheSOSP?s@qRMu2sm?ZLo2pI()4GMnlbt?7J8b?Mq{9DD%_q|TM7p{Fz#^mct z7_!21MoZR%mrphq#`-3r2)JiyAqxHULW-{OneL(V%pzOPQ`k1@z`6v!b{($Q^K_4e zbv^BR1%2&M;d0IjKR#E5!aejH499j4RdD<~^TxT4Nw8ai(D%i9yqEha6H`zSM-;3* zYtQ2DN+$}_<5aaoycBUNbSep-tl<_AfjzBEVTm4#iS+|A|M8aUj-%KHO zeeQw7xh`#`IM^F|qwWvB5sm-R>#=H2E{bn??gO8Pu8+p?qc0*Xt&h`J&!o0atwn7yGC3G$PJJG2l_=Rf_w@h$i^OjGJnIB98k`yCz8fB_amU~IBoy#r*M9+HTPd{WMfl9T%}8j@>FtAVFz@7rBSJ_L)xW0|N7$3Xxl+C*Hw>V zDTjvtG7*R0KN2l}_^sISTW`eb9d)s?0Uo=GbX(|l12p~A`Ojjz(K7SY5kc;N5yjrB zJ+ZuYDZ$Ce*hs>wL1|gy!Lu z@^_1d3NONjh5Wpxr>Q5=AZe3E8M_+&u;sU7?CDs%{r1}lf0ZYd3#6~!PkHcr)ExNu z;>XEAEspJ=R?DS9&K|k!@IiXsV@UPdZ57+%qthQnPp&7W05xuFOnK*aRmkS4(*AP$ zOSJI2nq(pQOcQfaHt>ErihQrMtStSlhhN-u9sa&Lc$Io0L$MQQRl@fr3Z#N>(gD5T z@)r4w@MVN^S9Mp+Jep2)%ykQgetvN8!PK$Cz4f_oz4cb2g|7Wu2i{1^xxA)qOIh>{ z_NDJc(TYTeo)NL-d_E*~R0E!Sq--btx0koad!N4-M-ChTz6xUS=3u%uw+Vv)mB5PeqH|$bj-4*4@t;p8# zm4EljbJBs}dv*kn=8H2%9V;t}k49uDGp#^(b-z6u>8$%KZ(fajw)tRNhD!gzf9Kl( zQUq{C0cQEHXcP?KZT*6P%4}Vnp0dn>B;gm(1pG|Uwx73N9*K(w?sptAPjh@7xmOQ> zq&E?8$72xyEa3Z3v6wd>I+$9Z+y!{dg)FJh0a$u?P;T*FZz!-}72!xc(;EMmomfNCwXScyeYGGmCqqClsi!1q+%49PUKUEnZ;P#{uKbUqTR1Slv3wVh4T zyl-c+Qa?OTI1$R01)Z|d&_W?3tmRbmi#s*K|!TKEX#Blka5~oAeTeXLs3x4G(WOFXV_5QKr>IVx#gKhv6j?| z)?9Ope|(8t+9_I}Y$8&lk6yGGE%3^*{jq}Zn?(xe#1fu}D#E0Q7I;bsxq`Stjl;cF zVR6VbRrY*O1xcpukO^f4;e0Jpi#&c$<-_YUD|BL3T$6bkB?t;he&^zai%D>@m{6uX zsQ^mUgbDLOGY^T%zeD2bxp@{MzLr@D#Ud3$9ek9|R0YgAIcLvMBZkiw*?qR5kC`B% zr^2X$R9zhb#pi1*NL85$LrT@jAEKoIw%z-B@YJ6p1efj*L{J#Iw~U8S&%H`P=7pFk zT8uRm6kCP$Ql>M8F=8j-{_ck`eC5+mV;3nfGr*O`xU=uP6SXZZN#K$|tt?!HphajD z>uRiPiQAuEjOo!^NkF|bi6M#UC{%23s7rmSQ>ZGk!UC{sp~6L4Q0l=_fSX2X%algF z^WuG4AA*f7p~N={upVXMUO~-0cCR#+NIMkjJVWp28M~hv$;3m2G=)je+_N=@%b_pDkl_3pI-29b6H)`{ zsG-rvqDdO}e6IKLM`6#X5YOMU1HIGm-U?2_NTP{}&LQxzK4HV348Qz>)taLbfrw(9 zPc9F|<7o=TP*6yQCyjKD;%erZ5@)0*hTsaPuE*g#G&UFoAU-R=Xrxdmmg%bSXGVuk zj7G`$I+o9Kwz|D^$Sw=kS#Y1S;aP|a*>`>4h$7GG`JwVJZSN%%+IeXGcX&1`9m2r# zbk|T<1v%eOxbOY}cUib^+YXe`Yr`q>#l085=BJ>yT$68q#d-;EwH?*%ky{CmQvHX# zEjlS|)?-mHyG#0$`0C!6TdaZ1>i&M_S**p7_GkqR`<0HU`$wpK))6!4q))o0QFZ{CXHVG1eUV!l_&OP!`>OEm@U28L*r)so;- zSd{1L#gVSc!{qs{P5AWOJoh#ATVf-5kLxM?weqF*X#JCK#qNLn-PnAr6J?*MAiQv! z@P;=Qx5eX4Y$+b zx!2Md1yc>Y8be!ZTjKnc^Ir<8;=epa!>9&v1#|aLPmfA~!`H&iC#OD1H7OQWSa*X8 z&)~!jqNkQA*x0aBE!J@OLAI0~-|NUeT z-LrQuo>mHi!4ovF3=H&>2aciU`b~;y*2l>|`**RLBYFBUUVgTr7UlSiIn40bCUC9r zDaK~HWn?4CfxyQS;mR7Ot$|XombQ{8WlN-YDg(=pRB}A8l+H&ApXaJkRryonTQUGZ zi>5FpWW{LRC*epX)Zg;g#1lDlN7E0E#q_GFIQl>SS5f%2_E7W-@bO6f(YQG`7MsB%d%0g3x=bojWvWG@<7#LErylgzbIav&IQv#a zcXxMua^{mnr=^p^iL}LN5bJme(_1!_CXc%GP#Pny>pd1Oy`Q|r^F6SO&~fOj-!oMF zCZX)|IdMt6zBbSs7bhtO51F>WCj(Gq4`{|m)-G_;OC664~8<@zqm9~?Z{QLCf zQ!#>)_f0w*sCe$%w?ENzEZ=cM#akH8XwH1h$0ro^tFNz5bj%bR zX^zn}@*{b(297LTzY;mr!k`wlwgu_Y7mg)m*%LHyT4bi&?Xca z%d}}7VQG&$_tOq@AUbM0koo5^j9kPqS|4|&?xuZK_cF?%xS}}rw(O(zAr4<~#unik zx%chem*fE9O=Vu=oCRp*(eBqO-V>&!89&_fgLv!I+et2$ZaFVgGX0?maXaiuj0Ra z3cy!v0J!4jM(>vh6wY*g5nQYk(iH2rR8n~ z;pG+p+y?V=b2oqpGVhI8dt?AIU4`OCHr#_3xXOyiH6t(d0l6L7(CVwj+~FbU;kSr{ zGNy`^S zDVn-Ek`X{FxfR4U1jyj+!|ssStO6M7b5tKjSW{51uC4(AEGm^RFs0HXVCe09ypo*X zdw1g|LfA&UAPa+e!$>6rR3`0SPEiHh)P*|~WxG8%ibAq78t}v{;cYKr?R^ycYd*Lq z3PIYn0Olmt-7Oe1R^qu`Lovm*LbjSdnO}Tqh3<$S)F!bP^;L1NTW!hVUgqX*qNFzC~LUE@b`+Al@_mMsZO&a|mnx zh{QhEXZ7{=B_UeImMQ;UtCiks%@LE>s6;BPsR$`>9mM!#M1uGByTV}RvDVX|665tM zpb`ufFs+iFu}sP0hQj1P9|dPPW5bRe620X`LU-nq^eqYm z>Je#ZZH(!sQ}O!0_%C9LusQFkC+q>jS0zHlxnKMub{sw&jR;*I{`9Bu{onun`0TUK z=znb#iiGG{T>k9Sn4F~wFfds`A+LwjX;?LWKjlShb$!0yuZ7d72tg|%3@a3mXo3r;F!_ zFyj86wfmdls!Y~aSSqv%4vrkcLrSOM45Sg_cs5l29Wwqj5AG>UNpln&WsDijD*(ar zsTQA4(=qqkv-WzKwZ)o*0ddedsT|8VghdIwp9!A|sovB3`MC3M}d+ZUB1_dGMaOhR8B*|l~ENJaq|oa@MjLUoq<S)A(se-?yf(pu5?=>juA+@F7B1RhL zW<<)v*}Py|N?83vj71OTC?>j!JVx#%KN41ii{9SeFajuf$yZ^?-?}cgfA57T{ry*> zbZw8eR}V$k-Xru!FNty#lTCQ*9-!ne%p+hf(l;4_-!3W-$%$>>iidV~ zB0hNk0}2hItOMWugZ;6mYfoGpzK{geJxzOJ`oT<`Joz~^r6$2ZQn;WG(ijOXQlsxIuC50u0ypfwDNjMVbty-^F(a=X>u@=GV{Mpmd+}S}(yG6PL zjK|5dCsTxzp882( zrO~O_Q{NF+PhU)D;eRSr@&pAmaYFnOR^@Z9MAijFi#G5lz9!%~bcOhpTQz8A<@UI$KYU0W6xde4w15pfIpV2aWrywQ3* z-5c>{Eu##x_wtW(m(Io2{;P4Y`(UE07LXFZG?)t4Mm!0R8hx$~TupfOyB)t9!w-j( zpe}AJJW89amm-XqFX~?FAymOo#!x{P=LZqw<-xl{s^jetm?GN8hMoeMs5yjbB zE8AjVawu*iHj)+-K>A#q=B{L}SSxd|yTRc^q>+Iv<>0G0MNjX6b-5Pn?&Ihy(r>$1?@m`}*BQ z==j)8YX3051yav6bUwJ1kCt&?vmp(V7GwsK?EQ@Xx+l_jjkn_YBb+CfE?i1*Vyy-5 z^`-H+Y)it6@iF9`FUYqBV%MxpnY^(W+&v@T&(g&*xjQ`is?NapfG7YJd8O_ zkZ!Yb3FQH~z`}#lbNOyI?9OAWQj4KZqvROTBJLSgR)Fl)+R>I2sO3i(J4gp;-GQ@+ z!q1gNY+6GotKH*wCYgu(Aq>cC#A{*Rc`K*5*85A)x9=X0XJ4aW>B|(v{pQ{%*jX1l zkG>iURd{|%i(>DQqcKIa>0M~{I`({v`PF>4VFRgvn<9RJEOKP$(WDUbxY)9`G=BP5 zf1bLFc(#WR&>cX&3(pj{RWNl7_*$AMPi<;yPR0I&hjSOsCVt!7do?*mI!XUIb>?*J zY2HJ~I0cD;bMa|}2o~v;bW?g^+Lx~r9&pdr`qudMPyU=@h}#lAU!S|4_EPV%%D?;I z_2Ry=Sq^&l;fWKeg8z?R{ayOe6X5{ek``WtuV|3f0pmWpzry#s@4lPpq;iI`*r7v* zQXafU7G+cS*dLAO;*0B6o;`K?bbS3)S~`FJX_8Hq^_<6H^6&fL4=UhK=!D>0JL@~+ zDG)j?u2}@83$;VPPm>{nL6K|F)xigkjK;sNIbJXhi7L; z5b2hBn>;`nC)43vlQ?5ar%`7!&_PqdO%d~)GMUMFCpySl-4jOvyn0PfUHbd0`0xK0 z1Atus9wGd=QQ3ks+qWEffcb!=}rHja5=SZ>ZSNy zEr_et>%kDh2$uH}gn$_~a)Jt_?Z*z03k48;em;s_Rn69}-?xWs2tFq5i)FxSYm&u>L zGetfp3<877=;dp%*moQ65mqgT>H_z*+rTP3xf_WHSQsYnscBoR-9n^D9SUhGNHR0OCqXHMQQN=QJ=}e0PdZECRKed+d&BM?%u-<*hHVia?_oIAlg+DR z+cyuzgVnT1Vclmx#?!xhcS?zwXPui7dOjzVZ4R6(24+1s1*g7Kr=kT$U~PcDQCbGE zF2na%P{{AfPv4IF*TD}6p!vu~JEUAll`TeRPrf?79umVNZ3EP{0}l#@Bda@S3Y;Es zhl+@BljYl6?8!6E2x4}9+VAuY9xe6d>zoBxCJqK74M-ogkw`|SM(f7nRVcdJ^^%A}_*iRGTKkFEXe-88M zrJZ{3^iGIR*~s=<z5|4y&_eNY)`4`ud(uS2@x~lQ7 zj=bI5E5KPi`b*UtqMTmwNB*!NXeBmIRDmV+oJ&hDLe z-bUf4-#N;}i|rJBdWvxnMXY)&;i$mh?U`H2_^lyEBdKR>h3N`f4jP4K2NwmT0}ThF z|7KqjY^G)?GRV1+{j?Sb8|QcKlAk*IhciYg!K2&?r{sX zPj;cO|IX`iYW#Av{qYZD6K#)LkME2B?v*;)xg`^1GN9`-y&zdIPImct^6!q7pKLm9W7ntgf4P#V3$x*!#N%1jayH}=QlMp zCC{oMsTSJv92N4s_Aza;wqgkW{PgF@4Roi#c>CF3|0FN*1azpJu0ckaB&1u% zhXxt>ir&gc)CJJsD$O_IORu5d@05^k^1&ROFZKzN2|>>brsRFs|#lZisIsQ;_Ditt5A4_f3^bI8N--HQ6dWm z?vmS$A#3GI;EU)3z2oADZSRgAJC=B&XE!uFlvmX2De{fyT;43-QGQd-QDN86>34PJ zxku6+4QKM&Sq%26+Byn(G8BQ+%4~Z5)k$`??gU?-eHp6WS-K+?qMpL|xRviKOIv_7 zqY($|5618vYAt{lwx(0wb>BWEvhq7${|@=@L-EzZ8mjA0{JHHML zu@|mhOwkP8o!zOPiL^+#zCC$6;jL$>qtp53YNU41XzSJ~#$rAu+{)aTG9)3KJ5(L-0iGdGiR`!pQ%$X+ z(hW&>OvW(OsaIZqB?hkyq#79+Z_6SEG$zYGq_5Hx4fGn`J!|Qc5qs*P${f-%oqh65 z^$hunj%xXk{M7F|9>I%C4z{Pizl#5o0btvA4t=F509z(d0$DJ$B{5#Zt2|&w#%OZ& zc*i^(%1LW%rZN+rUnQa$-e>nqF1E2mHj@7pfsG0Fq(&!{G3TjAHD zfCXE(#OT>GRH^5%uW`u8?imxXFQf?QP;l}vO36o6kW2FeF-01O%76Y3Dn~Ze#g-QG ztqALT29V92?1kvgP(gEh+&Du>lTnp#Pgm2=tbeQwkv>#8=5@FPQ?^fS6 zLPIf-Jfz?sRxLgFg;?Wd=uf{;!u7OG!6+OmGOkgioFi;`3*P#H3s>Uq2u20Mz}C?= z<|##9%zvFlpf>d7!Ic~Fa1Cw4TDMaTmk=a~X)(&gI?ilv5`~BTa!6Pux-$Asa>Jl_`1 zWU6SZ(6~=}IBi{)lp8O=uwG8B26HD>fSuzaTR6XwJV1()^&H&KT2WBgoBmHfi$aK` zA=vIWlcOgvy<9mTf8Koa+f;TYy#qpjz4c+lC`1XtL8VU%umWfj zK!}7Fis*J$%5-+70Dy|Ys@0lqd8U)-|?<-6=RKA`c5^r(9^Hw1ic7+=mP=W(sM@D2+ zLMDv*dG-wdcC1DKpQIp?f{Zxn&=BVN3S-VoMgQ-Q3|@sN*ILaQv(z0!#8jR$+EaqU z+x^{_lodBbuw@Ho8A_Y@{ahDQ>tE9^VO z%M8zC;GRP|L(Wf{KS3muMWi&m%@G07xob!ARM?(NPlLSW5z3ftxmtihi{z;cR8y%ThD8_JRYq$p#I*M)NP`*M6T0ueKH&>U#yLB_w#?iy1AbFlp%07A|w>5T<$KOvbYIodQnoC^@6hLebb&CSI zNx;KMvWEEIaXhdamnkeqCHms=hjHTf{#i_%9E=%4{Ab=i7Y|O4#_|{*jokMnO+J8tYzYjmb(PQ~t|;7)?L=T3lH<7vK6P ze;Riv_OubNE6*eYt<+{A$K!F%t=u|qH5`8t{K*7b}N!JsF8 zi1W0%vNd9T6SUM^o7>fhhjpK#*Nor#3=(gN3{!0CP_LqP=| z+{O8*FRPDpSI)(YJuk+!8}M9csNtT~6?6|FqC`BXKoRk~(ufO}FC^M3?0N2b{XDx} z2%v@=_x9-x+@8X9E$UWLMA6}?2XU_tS%x8x=)c+*b*;H%^eXzIyM=k@_i!r6YxQgy zWu>ww4#`iXJN_sK$;WIbn2pR(=xgho*rR<*IrV?w^U^ALj!L6^$7n5;WkbJ(WARtM zF3rm5lLoeX!?&pg)JM3%I;@-+F_BkF>8&jut5{?*mj-sf>yUPy&U7iHuiEh+Db{0qb*!J=|zRW()+*pO&n}HkYG%{ z_0dNk#m;V0?O1o#G+$^0C4pdyL*Hy;@YMsdQ#7p^#I9g0jx$R6<+LYfc*tbNaZF_Nh+*>9! z3jQWM>zy_g=>600C%PkiYalc=!RLG3tqD>wnU_lS$Cp2*PDVb3=3qD8>S_2Hc%s~; zkxQe+fCi7pa|x#}Uc3}X4;>-=ege43%g94FhiG>=oM_Y4zN?96ia&a#zqbEtgv{Sa za_3Ke_7mjnThYk6-yQdcu1p+hG#aI`CDpEXWv{*7+P!eu<@NQteBm2k zxLl>OwXR*Qq|uC|k!HGQrh_`O*~}Rri9muRNDw3l0$@P&@ArIs+r3-9bnEG2lK?)v z?-R~*&i`c2y*Nco+4-Wp*7nAi`&Gt*jo=c+PW+i_sat zSw>ByRBra4Z^M)FwRqeI*CoDjWR6DZ!Tp!ld9Ds?0DO~e0P_(5Z|(a=4FC%lZj$qK zBVA$-$q;1)feNh`P-VyOD=_u)d)dvY8wbD|Qsoe+*xJiOl}RrauZYU#`qcKx)`3Ml za|R1%{FM+%9j1LI#2ixyPh<7czsrIqQc5IjOLkg@n|8H+>0 zFD@Z3x{N>7rBUD33?sL~>0C4vuaE2JsVKY#Mf4sPbiRN2qvKJuVpSa8zBf*M@JZlz zL#ZYJ1!Y0Scnn6jb`vd5u-ra|$;?2Q>k(?R9)YF!|aE~OiD#8K_@xVVM zU*CLdJvfj0mPgwF06+jqL_t*8n|Xjh0|tRbq5x<>m%kM1s3JU%g18aO?gI*37(J2e zgOLGF1q`;>%fNt)(SZ>@jRn@UZ`YoO$~u!0GOX~ zs6Zz{4r3L72xeOGx~lXD)I2j42nCjxNZ{bQviJH7-`m}jFE}aV(*x{0DtY!DA~hT` zYQ4glH^Aq~n6#|xomBA@B+SEX1TXf3&W42{W#%b@fbc&p(9T&vmU%Y)T0rR#*d<}j zp14lIj}_FNxA(!kyrk3u!W@E~TZA>PB>z!Ho)tAK;B&JWORkSxPlD3lU#P^UbYNR_ z@85%vx)>99Sv8EbZS76_Bxs#Ph`sUM?))yD2x)97BhSy&;!3N68`PJ`1)~uw`@_N-{-P zC2#M(y$FqK$&&9Gnf~BeWXiu@9QQK=p3YT3AoI@vpzjp0YvfS)Xw2{&{XJ>NJ#}cs z&d$Z?0BKW(Y$}ohP}-q#?0%Q5F_aif`36L`*h4WC6kZ%0lWMo3%OSjp+d%vVhy)b^? zd3g^#2hY~$3AUy4iTe|Y56fROLznyOJ(nLV9K9c|&!O?iGccV)53l1Mq3|ks(*63S zn=CeWkJhXzAoK7hBN{4@OY%g4l4tO<5B@Fz72BjvOi>vcp1cP6atB~&n>~4j;MK5E zE6LBp`vsT>wh;o0!DDmf=D0mg7%h9KtlZqVC2rokm7cA!uaoB*p16i|ExmA4%P1Qa z)hOjtiDz!alfH6pDF)&1XW##n)?+7P{FAeB=e-jVCq`o6FW-;(>&Qm_R4h{9YhoIO zye5U83Lw1;(u4adKv#A;7wN#WFRiYKdy7-CJzo|>Mx za_b7u&n0^I+0wLk&-psn0+i7Xx-u*-rn2 zHIl_)%9Tb}Q(97(E`~~ZoKaMn!OhRf4>CR{aCI2c4-qHBnM%K-7^ANDFSTcdel%WM zlSV$78FA%p@)GZ`BSn6&$2w2+%va$UnMDS$@q(oUtTl=%XOk=ix5@kEE9u@djf{Wj z;dg%WR}GVTO0#+UJJOc?4EeU8lFXf+~n}bIiy&)eLq&wuRuF=2c zb>`=4pb%3U{%q|W@14eLm1*~=rx%=t0n_hk7)W{XeBVwyRkc+qG}vx1M&s!jcMXrg zF}01g$>^G*nP#U*lOV(&rC|8nMHW4eXR<49oud`npMwkGcTL6R6k($a4H$A^5`zfF z^$h=Lyw%a6Qqs4xk5P%LxJ`HJZpW4!aqEbpSusbj~EfvHJ#W!{Eb zkJ6HQTm829>AOFr7_-XZ_pv~d$_ zBP4x@mdVfVuL_zN!2+gP+JUl9J}kY7@%+B`Qn}{3oM#q6G0$E18S+j$Y)F4TTb^oK zgI|kl#Pxp0HA$Od6hC8xpb9*@mEN%q{xdShS-17XU;W)*6GeP58koD!{OM1Bn&gN3 z$>cbbTd5+x1~<>y^KQprJu)&JeLdTfY<3-wmLDZ$eFA>v+|@{yj^#F zWkbx)y-JJ-tbZ{^;aK z>GLBLp4Bj7&4JBrn<+?%Zu5-ydq>3t)`D|ST&FnKbX*Na8g87cyw)g?9D0UW?aI~5 z3A;Jx-VMF+qzFvHy{hHwv4P=KNHbSS;pJ;L(si)dwy8)O&8%a!9;`e2FdxxY-AJ@2 zX;|_vv5DB+vyx9K;}?*SzF@0{PIhQfGnoq1yHbi z_>R3V(>891{5yc|z&Y{`d7f=sii!vU;sQ@`X{tH+W*Gf6Ud^hqO2Rxwl7LQL+EFT= zVohxVXll`O2-cE?8)h%}SFzMu@6aMCv5n)2n#J2~82@bwP?SR4Q?^?Hlozj9ovhS? zluaA+MLOmwkk)_VEYb?5PNBQy3A_k|+F$tl&k%(4e#ANpx}&Nj$}Uxm3sA~e67qK! zf?Bf*AlyJ+qy)kGTvtbXhg(EgDa8g~*hk3m#aK8^P8YdU55J)8AA-q3UDG3kdd?Ci z48VB6T6ewqYD^Py_z;WW0&|FRa*_$_E+s-jE0bLsD#^tOX3tRi(`L zsp$C(0Z0o9>Il|R*P#$|Xozq=tBY1AMd_Sj^DLdaV8_o$(+`9>9=gA- zPkMLm*^ss}1A^bv+b!=FV7hiezhGTKskdc#XgK@T^c)Qr@{9x);1Pmb_sidtCRSs3 z$_gAdx8?HQzdO$g76QuG<2il+Z}#pM(+bvmXGq{`a?S13VDYdrqQ)MTu8h`SKOB#D z*2lO1%|DO%ea*4?uC0RU$h;Z zihHgFu*=u-31y$aK;z2Djgh!d3*74U)v=|dhZc9V?t|v;Jj{FaEjBoYH|;(OZEx$= zxI0ZAKRnLxLdZRC5dqOwgSUEt`T_4AiHBbf#Jb_BsJ;Q+et15LMu_CX&^Jl67sZZ~ z66AZ`Q`e+t#d{%;$#}YlDF4rBp&jGnQVs(^9Z_g6Y>5N^@`thc`>(~?eeE$x3(MCJ z{UG{hhT{Rol|vmAFdR4)vnwCO=#!E7RyQ44ZuGA&}5T73Z1inH+T4-0Jeg$4- zjylz|(0gvGnP5p?rcqtm@y{4ar1IJ-;f*DYQHZ<~j6PYBzi;M^%2W4l-%BbTq1&wI zwVkiUPu}@S;$I8!B=_B()}NmEG~I{&dnh`LEX}~XKvU&Gy7$?gZG`U*=MBH+`8Lva z^|K?NrF*GjU|z4@@~zE1@xiAbU=X6%WOHi_(&@mcNCmrwtNELxe2k!UVsvp#+{yF! ztQ$c3=Cl6^P+fD!k=tfRSgo#>9s^BHeytpLSATa8NND{c#-l*`R%Z{pU+Hy z99b`~_2+uFjeL=xxehU&a#3EWQ^5CkZ|&w@lAeKbboDaPA@CuMEAk*Ck=7GsWOpZd zsC#Z2hK6{tjkK{29H#+OUYrV*!g^YXN-AUnX3t#VUM+(~hf)fS>61l^7{p0wx^(7z zzUn^nufTxz1WZ=fkT+gib7v(^9Tg3uoXk1aGwIzghQC=mNk@f|2-Z8X`-#KolqxWr zJX^znv|`N@*Q4@hd*2qEDONYPo(if<;+4(c+7$=?+uw`v_R`4x!K?9PXI=d6Kl|_E zZX=kdxt8dck%ZfJ?bwF1!W1YBgt0!ZO$-w)VybFQ3~)d9Y}-pjNHymX<5J(F>r@YHudpfw*nRL`v`KJq5d z#J=w&N2c@k4yyDi|HVE({nbyCF7e{N7m^XDY;75sIUmuYSKrUc)9cIX>yI)xX6&>N$O#eR2HsalGfP>32*Aa89O;`ENh(o$?u`G>Btv-XWS4T6T^a zT-*b{{=>KaFy8V5HZItj!Qu1Q(w zFiNnp2#nLPAr*p@uO8}tj;M`CY5hhr=W@9`&tuP=^LjdvRjo56Cm*@(9_!4iSXU8O zh=S9Q;hu@jM<0wvuDmrxAy^+`9g)tDNgupJ3u|(-(j45UN-%{rgDm!GEfv$Ti~UY~6aV`MF#s%HxIqy*s_e3$Z1``PWUBPfg>calTc#{(9hX2Q9GSAYwi^hM zo0-A$h~OH%MIj0LkxnCU9^EAzlS8=&QB4uXI8XkP!lnhq?kU3O#+kDKqN!*sr#J=* zT&7%X-P)5Xz&ocltYB6tx454dRz=&3D)W({Bt;Ox>d z<~41=%c-DR4X99%lyD&xR1*C3G}cwZt`q`ugnTXE!(xph*g+W7Jwp2C0Qx)k?vCr9 z(yEE~PFlE&z3Sac$PJ9uTrU~PL#(>j0exjHv_P7jq=1|AP~{; z;Ql%Mtb*DzQ8{xT4N+E6m;`Vfe*SP07S2^GzJ+kUK2+eOBf+Um&-0Wv1RD;Sr$AN# zAv01i3I@E)GDW?Y(xl3|Ma}vzA_yAjdsf1aX&mWnX>Qk z26&DZk`jnyLj`yxN|=g&LsPzbbN7y(R8hJH>;2dW)s+Eddj8FQzJjM<31P3N!e|z2 z2du4IPpd2{kME<(KkE=2@7Yfw7(k5sGDL1xJw`J3>gWU*X8i@_64^fS2Dcuo{S#+xkd-)>O^vr=g+4COEXI|adPxDN?l2Gl~Xmi2wp>Nh?@_H z5`vGc;yF*~u0l`5C@UmQhPGaF*YC#cxsjMUaw#tV`2Fbrc*PR=h zVjg4P62IdacxKLDP$+K|nEJ={c(zq|K?<9zV&fqUR4o;edvky6`bWPObDemSTgsw% zPiJiV-pi~Z7uV))M^y=tRD}4SAG;8{cTn*h8Aat2JcmT>!8;$rvuaRK-RH5ptOMS? zcW1ux^Wfms#QT-WzTZ1~aL2*;@YBCfd!&Kh*1gH7%-zzs|Ji4sCS_=K+3F-CW{Xw~Q8ThMoI$HAY|osGV0V_@_+E_@Q9c@NVazOi}@s zZ(cliF&U4|^S5~H`s&K0SX$v8H(45uElp{!eP+5td^Z&kg+H3AX0+Qd9z(|=yp7U| zbfP?V)b@6PKc*6tsHOA5L-?LNMfu>+*esuxt}>cZj##bV7P#JBv4hIL!?ZCK`iti; zMi&M|=W_4nousrT0|)bJZEZ{PRnNB(T1E-V&y~5ZUq0?URW>vdxE~po^K;5_d8IPm zwRr!GK2=s3c_!a;4yKwIov9L4OhGNb{7JOLu24o&CxP zFSb!uh(YB2ws5r=oKBAsjAy2cXlUKpxHC=+oWRg~jjH#%Q$D@?PW)q0K!}(-`6NZk z_<4DnUn@sEU-v;}`1F}GNl|}sGqne9Qey@lHE{WIQsCVm_i7_)8lHnVNEze4yB~Is zIdkbuJh$z+SfpEn#!YdeMhxfa*B^a>r@pornb8?%FP}}k+B5Tc2lnkx4ofk`!|A-U z!Fh?n%Q4`3mfl70?!FEC;){VV5+?Ibxlb0#%Zj&_uORj2$z(jVuMM;Q&qN72Wk;|JMJn|NaLt0Ia+M;lunS z0vGH-Nz_{OJ;Y4N8LH(bdO;MJT15Oh8#6O`#H<*noJz31&MlC84zZWyP`S(yz!KtP=>{8?51(K-RJ)Xp{*UmZUH;|8&*H@_0<>AqlLpZh>m^Jj3yT;x1G> zqL>PdnOiV%`C9tE?P9vNb`zRO;T4S^r%pxlew4*4gYne%HPZ-O1WHXuQ#@j?Yzx!9 zt1o#EW%RqrC%<)PjJ++0TuUy^LuE?FAyC(fJ9=X@DHalV(sp@s=7rEpVY@8_fEPI_ zAQY)v0$@>fhQd14v3i9@le`CCkRUJ<2r9Vr8mr7XGzvKMIC^%TnF7K+P2Sn`Qy2g= z=V$d6C+`CnGndOHChtf5ncw&KeV?8nKPv-q4gRgC(vZQkr?Cz)RI>bx9!Afiho5<| zU6a5<1t%LSKmv?)fDm(i?1Sys0t`LSf)i=X!hL#nRjdvDQqfk)vDH%%v{Y4#faHAF z)0x42wq2Py_?aczJ$|x=LXev%cElP|7(DbV4Qp}KJ2r{H7qDHpcrir)yz=U+@$t`o zMupmZp+J?cWZYog&%g9S3dOv3^kl4mK6#=T>!54B?Fc!|AGVe-!&*0{F(eguqj9}4A#3Tz4-Hdj$m10 z{@MMM2D}@BH}^!Ni$({}&rnsLA9*>OUHyigIiaXrr$T&L@Iue1A; z3=+@INl%+#Tce4VYw0u#L-kBF9C*IIQ*b7&d%xVTL_5sK`6-lrPj)uGH{CyeSKjYE z5TFV6{hT!6e7#HFMc-i&E+a)!ejIz_XzwIc5%4iX7Z;068vRnWp(;)uIgvgu2=*C{ zr^^&)`@wUu zZmzNCYmq=bo5dI%3NhSRJjke;ci#V5?B97Pn(G0~gg(m8yIMBWChsm@(ZK|k%+>bp zms5~+9l$~bap3AeQc%~eD@pWbzNG73y>@kKrPS3)u`oU-Nbzh11$tec-~R$&^+|Ns zQB>^_YbKQc+O6wxyE;MEU0e=BY+-%J&sHA)Gl&r#^g zND0GXN0E&Oa|h##3rE?zd@uMH`(8*rxRndLP+(4;qT2wxp_z0!`NP4j2U8F6_PX}e zF45;mpMlxqyWNptXwsc;mBS`Vdj6d(QdpZted9^(6VDa?lA zR!|6|VR$c0w_34=;(W+*l}&k)`_@bwR=Zd@HsCcf+DGM3erORl4YXIOFH{SkQVHI% zdnX~RBdKVd3eWOWI+9TBy1TbKu3WhMRR;m9$QN+(eZt&vHk z+}}3>N<&IZ8}%cOpG;W8BAQmsH{Egpe&OFw=-(dJykT#Rd^4AFEe89Rj+R8T@=`tV zHwUhfCWm7rZyRvxsd#C^LVR!i2E6+im+#-9xGSlglNgpabzsyWhkuUROul!4)T3%V zqmLfSOX>W;L_K5quvPrU5}E8$R=CGH2v$G~?uGItja+%O{oc2t?_d8gMjKbh#r7f-;n_n_NC>OANrmS}TEMM1&Yr`Nuzx?axhh8BukyMzIIz~1=jqijZXbi&kUa47&p-c)2kU&3F6_SYoju=)pMUsvx^oA197sk% zm3rSRF0z1kZ(m=cp#%F5B>h8K?RzycxHrG}$zRb04C4rU*l0`hP9ibjFb3L^dP=4%nW zvh$U=b)POd@Ga$%YwW|YyA~XzF66!NJ<7Dsc6bZ<^L}5$hijAXmaL|wHO0q`@|3pp z$Xh?4eNB7x-|A2DNBXi0lK8E!bsH@*SEaSS-1jp2ML}}#XrypYhaL&YS_ z%%RsKEm+ZVnB`ZgWC;|Su`J%EqeS1H?WyAVaQ|Rz+qFGaPFd7I(A-kD*9jC5oku_0^@-}?Z1T7fW~ygLqKTbl}`=w-MG z9c<)26w+&c#Z5XPP`%Q7NYGxYcx}$LIjM%FHndXD0NS3_AjfAkT-Cy4XQ8P>hYuz2 z=DPfucgpi~tmn)po*4sF-~}!2t>^5W^G^n31ZRHju#SMw@cwBSNS=Jo%)74VU*n2O zs&wGK`%ZzJpOZdix~^S%lxh2J@Jaex1=gRZ_k+^>9iNi`8t)cZuHcW}Y(35Pf}SS= z!u2L0$~yhLXJetmtmc6rJMk8b90E+wPe7W0As&?d03zq9;^n()o4EsPc|YEuYe!GV z_0P`(fH9=7X3yVe2vnTEdyy&hMkV+Rd74AoHWc4^_&dHY+f(m@G?)!*HMn1b2o;fx z?`GaI6%dDpAn%=fv(Bap*}CbZg`h>J-ii>J5tMc+%W zL`!XNTnkzrHMGzwc6|aG>)~0&@X{(g(95J@%`*4xO}#09|HSd*R449Ao6 zeEG`d6d~ohO;K>@L9*bI{82-sclF3eAH@#%)yPehtbzXc{LB$jZ0gxRI#f^vUfCl6 zYN=?(z;!WNt0^LgA^7Ger(@#dvr&YS|Hc3HS8?y(y&Ll*6Y+d*TUpo4`bc#_Ndw0 z9ghjIpCIC3&(7!K#thLK7z#Vr(NgdF#aIs*x^VVfY8@*MP(jx7b7Phc9_*c9$9g#C zMn1py1;UVtd?WfszGfKqD2nq3mp;gY>I3`J+~frR;_$!VL~p10>jhf1epONw%Al{I zVcPdSrZ_9KtPId-uWWEldfm)ry>cCoKcTjRV?&9aH8`kf2w=@YF9RIjpS_=yRe^F- zVH2Kryy?h#pQSAJ&RT5H5af;AvGO83Tx$WClX;-Ml6&qs8!o@4V@p!X^&(ru%02dd zMmBza{&UWjjt1<*eT=KK$NOWER-e|f(9mmPIU|oWxR!!@3_JIp`s@PU@etbej_cXa zjGEq~l*^9CDz&Tws9H#K;St~!r-Q>oJ+<# zs=1pMZ57BG9pv55MkT2atwd*zo;k@qqfH^+vr6um?HT2b(wO{79xK0>C-{Abd?IVp zw|NV>zwiaIh3QVIXjWbXev&-bC5VM!UMTsnX0eBzVRjC_7zKK*Lbk~AZ7MQ)tVSj5gyl>ZtKTP*h7MMb# zGL6WL>NQpI9{uZ|EK_8$v4K{CpQd^u)*rFvfbzn-qbFWRrp5*h$?`M#r#!{|>Fc2A zD-lZ@DS|pUdX>V9`{O*38!G;5F%WO0=v^JgKn;=JLqqS~V-4)`GQ}#_pyA;dxH*s0I^CD#cI8SVmD=sH1i0fTlP8Uq!HKxgc>&- z7J*eRd7jD-d7uVcpP@|D*mLd1^;mzPJAM8e`QPH=la(94caS20nBcylaqX91q?Tz4 z4>v-Kkyemqh)QNBgBM8pGxO&)1o-a-n5_cNgVUno0oOI*VP9o+Z!E_UeoZUkb9jY| z02PZ6@)Lxfc~ekzvQP`k%+Frdt3&R)&+wU!>gt+waoun)tpM4-twt$;aCkXVcp(R$ zDzI``0^{-$!iaC*j|YRa$y!~ItmIGUXdi~PUA!q$lqzAz0B@h)80h+nO0+0C_ zJY}?Go0>z3Ak1qKkgxj3PT z`Dn?t#jXA;NpQ|W&~rDYV`VcrOMrm|ywcNnpdQe9;U1xi2fz32I8Dz{%zqS_D!~ed zg_-k|aVS&`)mL~WiyOjS;jJ~z3*tIt9Dd%t60RHXic<0 zn+#Ru+o8he+4)D|tumpqBh&C=2?#tZpC>&z2Q9x2f5)MMq<3FX;6>K^nOWbiTxLHQ z(&Gg4^Rp^6p0U3#)7G%y*Ls!|dI|ua;~qFH0whq9k+=^68pFr+&^S^hcGl_dI6Aj> zr9HHrPyd-qspf>=zczG@N%Idt#lmb}!Swsicd2}JEO*pK8G`=wxpQg$(v3!#DHQ(4 zoC_?Ba3{Q#%)14~tHAQkt>8ZBMbpwKb2B2xwmXRd11|2q^GPhtpj6&}ka9?kNU#-> z#it$;Riih`za4r!=E+evGRER7Dc6d-X(egTMlhPKQ$pPsg!~5Z0 zxVCIKHvvI5PrtuVSri+0cBMQ0=roEF^LW6s{?p+eXQ2E)jef}#clTBBEDe6WIH2=# z7zrVua&M%40lM?aiUW3bQB@!M&qj()V82|SKa=JSpUn(ne$Ktmlz&r$+%qE*90FA5 zl<{Ic0cj0x9x%w~>&+0DYe1_)a9T{v{T93lf>r)CKxtH&eMnsslz)eUw|!T4%(YiV z_kZ!dC~m8d*5dX!edk!bUh;BWoH++?n2T>$y%xVZ^UE}M91f|tPbcR+K;C&D6^<7v z04M-*-qM#!sC#5+|EVj4^KzHmE5rK~+PPdVea?MTeh75k&*xttteIZ#dOy0mXq7ld z;ULzgXQBn(;4?MY${R~q%PD|fBRtGPUCkZsqzqU%vkpa}G8JmmKvIYzvKo+a2M@&T z?THvTej<8oX>_zd3NOLqe)K^+q8?1?812HA){-^?k4K)|7`*)|` zS?kz)EATI}pPu3H5`}YL>Wkv%w?y5W`=autZ6sJXgoVN8NgW%wO;lQYYxJz?!J13N z2wt{w?$CMC?kdg9$L-o<#kJ8IY06587o?e!Qs!@3JY07EK5bI0AoI_~u9l~hUxH2V9V zojgr?lHTNTDgnM%KKR+u&l1mhrT67nRkkYCtnfJk%NdH5$&cg(-ie?5;>RiS&u0kk zeZD;6^UpqyEr3wz;UPxy30ebZA&#LTWAXs_~=%lc+(S&}TWDS2=+r{Th-1>j-zq$DCL1sMkj>zY- zQOTMv;r%V`!mEklu6%7NJ?lpk4{_gB=;V3wBhN&BAP>mj`@EMGp4BT_z8*Ir#V2iv#+#H8oQ7CiC-*{hdr6X#g;S!l(u#yqpiF(nOP< zrEO*Cq|BNM<<2xiS)GvKyx@#4!>|X-On-3&*3?%{5#xBG10z#`x3uW`4F#e zpcaqy3#dFDUH|m07;7$yu7C1YbpB_r#r?)L@#Y`>qo~=}6}w4GdN4<-5qa!}?yp(3 z8YS;ke82nGDb#j1rCyneQL+K04cu8s1m}vPe9aH>onHHS?vwA;i*0m-yzk`kW6^<9 zsWR#vuoi(BY)jXcDUDIe7x&bt0H5dG z+}X4f9qXC6MzP-J+-6c?#uM%}D#bNk zr?{V9@%zY_RnVI9T#va<)j=3v(aEB?v)W1tVRCXjIzyPzph- zgP86CG9N-@vk?CR8~=cdXph?>nDabEb$qrt(+YJ%1qHUI1IR>G{pXM2j|FN8C3+E|TwVi# zJeiJJTJ=4xz~)l6Hm0vp;kTy~%hE&?FRzZ8HFyVT^`&5Qm^Y(gL`74}*4k=9T6^1K znhMq=x!`TVN(y7Hz!JR{0aA?6T|zN?yf~NUAQ5WOvj}4W|0%53tt}xBb0_)Xm($uN zuud!V`?gXQ_B@5Js)#UHO>scO3h@G0Q*dsUyt+NFyc|bAcn>KA;O6rS%+dbb3hbn? z0VZV(Dp4xOD$kyg=ctnBzNuu%ob*_zButa%mg}IZKfR6}?!A8;nQ~*kor;*3V&8s* z9SV&Kf*`_+q*CS3T9^z0SZ-BF%pDf2sO;!G(2qF*7Pc=Q?|5&$A8;euWfT%0&*&_N!abkMJ*N0r`aPTW>%2?GKtlGihY0e z%{OBL+OB6mw74ojoQrFnM6fNejwR^cXc@y|50i%}gWiOYxq9MU#4WrWgb6!TwpSF< z^8`gTcg1HmLhDPtus5D>@F)PJoilb_e`9RcT*!vmgDd9ovU{= zF;CW~2i&L)&(t&UOf!#{O241;JoOw1EFGC~C`F?{r&^OeM->1KFwQSCK=?k-)Zu$Q zR}BzHK0gu)71tn5IgEa>{a+RB3h&Z8*>wvN9j?jGX7uZw6U_Q_`u$vHfDoi=wDVlPGC)8Z zd7%f0MWHp~#(nVI6pG#(_sjH!h9*M30slrcsr;A1|MY|!eUc-@)^rOM9gP95^&Xy_ zM_a0+d~a9GuU(1P15Z`ShWMcW9U`g_$V5dAKN?Qq)m}ywM)|+{Bem(y3!@o>4;@*4z>j-_-fAs#@{~`=l<*$@$?Ge<8+IdBpi5N?=cZ`+o>TSa1}f|+$Z^m zd;Wx?VXNxPqh?13ZIK3}>bdRo9_~zC5sD7?#Ma+=Eh@+ro+zN!M^zaHidL$5mr^rk z9MDO@TEZVUR9BIrTo7%=xfq+gfxIt^ZCiSy1Px?})CBis!MjP_9MeoRAj)$EvI1BE zo_E*$NdN86+`BvX#$)*IPy)TSQ5xs#!O@{qh2MP>9OnS%-PLq>nV(Ebg~hD&5(!>4 zmqV(H$ccQOnVaxIE)??D>!_% zjspR^d_x}W9OO3|AX2&%?{xk0Ned^c%=ixJd=n9n8VXeYS5OCPP3hWvXNEl6Pw4>4 zzWE~(7@*G;Gci`IrGWO zThHEMD7p7TI;}?jT)lf8VF^auPREhW7-Xs_hIzOxs($ZTxD!V@(NBMzwz*}xZqjMN0a^yx&<2nBEyFZG}?Hwug>^lu_#D)78zUppq9mA%^ z8J%uil7x3&+xl9(^XWTDxs>i--SujG^yNokW{4py4Ue2y#aLqHGseXmD^J^dwU7^fS~3ev7_etas%kg3v@2G06Mj6h4Q#k3sB$$HQ$d$-BtAid)$~_GRBKDT3E7lXff9>NlF?H!W-hY&G zy!4MzvMV6YLM%p$c-_qPvdF^}e>XQ_;X|N3xJ)(NJ5(Bf<`FhrM~0^I>F3rOHBX?Qd=C!1lHdlq~8Ckh`{l+{G*BE+Cw!s5?dIAuU~u=9nA@(7`~w$SVE* z$%fWI|ERFIe-eCKYrY7EUf8wdC@oUcVe;-B>Jn_FpvHJQ6MtXjF1Ro#HaV@|{x#V5Ak56`7Wd&zy5XnL^nM?(q9EI<2+>2^oPjmj-Kd7*b_u zy`hX9gielJ#`}aq)3LP^Bi2F!c(xr`!c}R{VIxse*fpN`skH!pK!Lxkr>`aESFea0 z=g$*OQ5V<#_V1$O&>_5&`Fy_#Ky5h;%{980GGO=fHuLTxJl6ei4!5a>x`ybHGoO8m z5$F=tcVK$g@D9{cK^O0<6{i=UVz}8vct0RVa4CQ?UBNREyx)Nq9hsNda9IJDioHX_ zi1Uz<`)|*|d*~fkNEsz@k(Mr=jS7nUr&1{3u@-~FXSw$d3o>a<^*Mdp`qHxnvz|ew zj0)u1JKED3B*P4I^$g@Y8gGmm(V(Pa>+fYF)ga)x)*x_57p_IdoUKQoUr#H~$Lx)% z0fuJ zKMi^Qz5-9h*!4-5&Pf_pP#S5X(ymw4v+$0{yRtcDYuvqOcLMg(wD(j#=pA)0oOc$< zV(7Z{H!`K(dzlT-*ysb#Nd;d6sq^vfxwoF9Mic4Ieb>Nc`hh&lGxDx@e(tx%HVuP@ z%L?i>c3c^_oV_ajZM_MV6N_S5a7zP>{dx`4tidq+xTZM1{a^ilTz))3-I9Ybz3`Cg z?3Zcpg9jWMYa|qT5HO^teu=$1PD*6H5bEHr zL)^v1*jm3ePWGRQ9or~OwMbMBGD03*KwXn@0I~qx&^`++sr(K-9KxtUTPbL4h${H< z4LwjR;aS!Wu*K&X;o*-9pAf;aE}H8$MP1a!af}CL3m7sUF2(TMpU0X1<3~|D3h=!2 zASQltG#;O!#n`!#cyya^Zqm&h@;c|Eax1+GTAj~#zx&-(2ueWhT9*n@-k{xu!pHH0 zzxZEc_Jz)P?O*>&VJlbPW!)JI(G{&NitAV5fqc&)Anw|- z8GiFPMF1&_{Ufb;#_qTBZV=v8y0-`VLgA+;n|lD2jD9OHL%t_jF(J1{J6A~B%-~?c zPUf3?cf=RUG5NN#+xskEkw&DqyYL&|Ee*Y@a`C)>!uGV*Xq{R#V5x;Nis~#BF#9?UOfxVwI&5reCfPYmNj^22$n8Q zbuv`nJFX18a)sI&tfPqNKJ)G`kkVl8`o7)!QtH8~(p6OD&)0qtFSxJr6o1F{O4}Az ztS#C|9fF^yxoFsHsm>vDD9A}im2*Sq(p<8AkyrY=?!CNGtS`Uxoc6Ttj)JuXsmP+9 z_1^AY9EMeimuV>QoEs@r`sJ~sNg}x?GF%mFGI=?s_5yuIFX8XZ(2X zQT*1y--=(6CgATWU)@L39zFN=hW2RP*c!*r9Z!3vAwoPN-xN#8Pc2xu2tOO)dqxj> zh8-=PagsEnT5yVrwjO?QL!cpl5P_+OZVszMfhqXRfQ-OWMQSyIZ>fyda1=;e93j-Z zvY4V!63@eNWPhhG_@6(Q`Fp`~Eje;92ht^I-ISy9Dwee2Q3OMMly9Wv*!huoGEU^e zUBb*^=uaT3`P1ZH6B>E%B<-Z|>O4Z}e~cw6=mGn!mtRR93>k`G-<*FV02~KieKBrK z+#s*@Pz=K$EyPw&i^HP%f|wv*b_wODg8AeCughhH(ZHUJUmJ?H9lcQtP#A>?m2awx zmYyyOJ6**+N^Uj;TZG_ZNm@F5O)|pxw_eRE&PyRYi$|fFP%(>Q)HY#ly?sB0*@K&zZUCq^%%V9n!!ErzRaRLXc6!0+m=G% zcahJgCwq{35AM;iKlzh*%KZ{Z9HX#I8O&>9;%>b0gWtqzd!IBBqCp7dFQ!P?0^a|I z#s-+`a#H^EZkXG@rku7!?71EyLmbU36_`E3BX0Fn1&;filyg9sf<>iIrOq>Q?yjM- z8p|o?=lVQb0gyxG(XSOOGDB-IxUULCL7I%#q0vPF>Di=nfgb#~`>zLCkmOwCF)9T9 zk){L>(x$>&L)6!Y1|J2JLelffXv)txS7}aK_D-xPeZ~1%wYGbl;79asC<+%BZ019?4U)hydrQA}`SKYy~pT+4I+X;C$U0H?AenxEcd`;=)CSU= zMv1!8D^}CAA$gUC;r}WX0+h;TB6ujKw5GidqeEYuzkCiaLN49)mRv3$-VGhN=iZaa z<;et&6xtT1HGSoUmtRhEmM3^;wsdYuAZ;^%?g@a#eH*zmk_5Zw;r?WF)>z+|sw1Df z!h2gV&apoSC^)yeWOXzbHpjci->1+gA^+@QIr1upN4>rYC4%>tm*Ba8$6h#kBF0hH z%D7W;@m75K$A1+U{^viAHRJP9GCCXAJ~$coNAmlXV@>kZ^@PGF;}q+X7M!?-f;_N-6BU;V6Jh%``3TzQlj&e-w$7#cyKRvcI=GqQoQ{u^6kMa z&M18uTJ2dW%ey+rXMN`V^}cJE@~+q-v8$N2!S^nwJ&`YW0wPDpZ3(<88LvJ&XM0}y zH8VeRbmcJeX$=J$u)KH56ZiJ&jVr0ffO)4XI=eRSP9FK=CyuB6-?@Eflopmo;aVaU zSoiPj`<-~_$UA9o4sAOaC(oTs&l3xE)^^2-VLX}4RXO<4FW-#{QmbZ^553o9)lOJ@~->T zl4zmY^;mjl%1?!NY~QydrJxyQW4qZY9SVGZ6$;@3P7Wkp;*VGQFDD+UjL$HV^f*W) zW-z~%M8YgkG;9hUxv7edGS3Xe@+R-9JXAiMVKCP!KgoEb|8^(~9D3%(A%Ve0B}Hd~ z@>4wKvm9CbLwTJ;qoq+iDs@Rgg=S0{lCNh@1$m+K(8xW{9+p>E;MlkyTY9^}Rmda^ zEfya=`24|C>{H{VUcw7_4sFx;fR=|T6$yjAI6%eObG0q5I3ueMU@<@21R5Qx+{mK* ztP51bnU$=|rx19bEf8(nHI4Nams>}4XUop+xPd{l_23Q+iqwUAV^^$uu_xBOwksxx z2z_z)Z^TSBEeRVp$3qN>WnhqEc>2aQ8{+x|I24(C2OMJk6LH-#c(1FSR6Jz<-tK)d zO*(-0O{1p~PQ$}PvAcawe0lcE6w&1VnJ;cMo&3@iDARPjo8FtvHQXmcs+AM+{sVgs z5H-=9LdCu3kBM$jrfBdqBF5iWHjKg>3iWmwxHhTcDUjQ7oZU9-L> zy4MqFu}r&Io~3+I?ugTD$!dhlh5ic(Kl&~eF>#yp)ZW;R;jkgmp=&Y4K*el#4b}HY z&m~&18_0L|eJ9QjT}aBQ%B!Op8h1#?O(jhfI-N)gtBwliuz&Xfc>GL!_~D1i2yhWz z=I=OXJ;km?FK==>fw^3xcR;1rt}?DqL-;#yzny9Xh*`urE0C{6B}H-e{8{98zBa-5 zgM51J1O{*QC^3(;si)lc$=l?&MldM1UfhpSm&jw=_Zcnad%cT^$MBwmeFx$sX&^7{ zc_}_S{#iWt+;eHIMrKIMVz6!s_HAm|6u*4`7hwMObcXe$pA{x2RE%mK&?9?%^Vk<^E99`%?-it+alo5<8)6lP2 z+-J;Do2(VXET(sgWG)a5Nb5l4)k=QPREh&RA~%nI!d+)=0eDErl^0sCvjik_P#JcSrGOqibXMhbbfE0(ZL+nROhcw~jm@>{ZVByH3OI;4 z!{^IkYz>V>7fi+8*S?jQ*aJfGxEV3QMOx-}Z*vJWy*|90f3_E0ur330DBQh#8XlaB zLR99E+PWcFBuX!umG~9DGHsPdnV14kA)_Zx3yu|06}}#}L?e(bp#_uH-bIMYu}Br) zb-3|u`7?P1B^H2RKrh(oYgEqNKu=DDke5`ZC&dglamzE67e{`q~^E*(glo}=$npnA3%X%b*VKzf$mZP%s%_4l&*q?bMW zUt0&@`O4Mwl>qVb*-KPNpNNs6k@P)N7!2)o_e{k(D_d0Pqq&&h`8Mq&tyEZ4__`=TTN%LBYhPsCM)%(Aq8x8y#1M{xt-SO#Z`cOAkyH{!$}5W#RyM%uK?Pjeue=X z<)LD0hZS-X;=K>vO~2=S?xDC?7sco38MEl1bMt2!f_#T_H`i63vt!E+qWIQFOJfeh zJ+%k;Jqs9GxONe5kf{Mzu3d>2cD)#%9{ZFct`t(`IX>^o-7D#A4)z>Gye`EjUwoX5 zu%2NR4vMQc2cxH9YuuU|OY^^eghFYLi7GP~EpV)~%v#SRGZ`QINdDDmZ>Nr5q>= zpAC8c{}kClP3zUuy?-oF3nZ?zLSUBei6< zAICAYj%W(*kM$Ysa8g%SA8i}j=x{=G$LRHh#|tsoRFzl7@U@|&!-nfCf1Glb*JW|>1n4&Y5_vY~K!|~on? zXRop<)|PI>FY*3v!aF7Z2x?X?oAJ-%XwHUMYNaStu7iE`u z_wMud_1ojb;EC9?cQ1VGi&WddX9ySX5G^b1I$vdK7i~+=44fscR}4;dd2|s|E{t01 zs_CK_dA`2dZ}YDX%Xy%(fGXI*Z3=4D04Jm`>q<~QSr9s^qgR9?I+^kPOK*kX5v}pVEbiyKJJaF7XqBji)v`H`{-qM=;6&gdnyd> zUzS6y=S;7W9Ak0T>=}GMU@W)u>inl%Fv8r zF{f3aoeUdb%xrk6b1is7t`4So=moccj|!3=)US*rfCw#&D*X<(w_Xa}Tye^r)^O+yK8qa_K`-$1ONA8Cp{lxq4yLm~-XwbQJ z;X+jNdn$tNfz^NSLj&t3C~v2EN7Wl;h?K>mjLuLw zHB?dtp4urf-xP+4;CBt4r^;fckV+G_>GLc!Zg}o0g#K}_{G9Vw`E-sxSEX1Wpc0)a zl?u*GS(FyCkqmtB8I5xqh@?Z$(;-v$ccfRJ>$^Nh1-!~^ro?6;s2ZiD^-UC(nS+s! zQk-#h*&2YKZ8vEP20u}`Pf-axUm%+ST4_4H6FT#A8iE9Ve%|}N0>j=!A$`SnbjS3^ zmy+_Ih1F>!Na+jAQ`*r8qCq1Y-aFT)Ax63~cU2JPemeYJ_t*W@*ySDZndZX!yV8}< z)fko(aP~(d&hyVdA16?s`t9=NZkW*UPh$9^Kn%z_a_Tq97Jffft|) za4o2$LEsI%a;9IXFsWd8Pvmpbwdba%&m32Qr8KIsHQk|gD5QWZjTQoRpKm&WVA|qV z-Wl6%wZVJ6FI`n#ac(eQk@_%q;XbW$mFdS$9Lvi;=BNzVSF=CPj-Dl=1Kv*L$|*c( zKFhf}pG@%>!N~f6D4$ysx00;V17=O6GXrPfW8<+MaQu+y6^$SRA03U-2XsWB1#4!I z_C8hClP``k?&#jp6HVl$kBv|$3{Sq5#=Squ=uXxCazf^n&+|l=Sufz}BK4Ip2zfRt zu>#vPU`<8^tfA$lMqO(JB;^($?A|>F5BT2Iq!*Zipt5ZGlLo?-gwtz`(;$)=8F zv`rJ)7-d9hP&?*6{B-OxUNU%qeB8ZPjvG;y;RcO>8rL%3@oaV}EkMtxvcpI-6>Ir| zq29NR?&!%!U-^6T0*$)z8u^(rSbi?fD*@wZpfTsGL|=VT0~i#seHFxpvDr@ z_`GY*N8BLYdZ(r1L$6ZsZxUW#TM@7S?)Ty>-q6RpX`A{_UyqHy`CQb#yen4aYNB~1 zhUfX~c-zNtnlz=T0@G}(@az{MC(jR^!69*t?gjm6zm<1}&Z~%Mz!ak$J#`dJbT-{j z*SV!;3qPe`ERj9Zt#?AYm7csq@_s*Odq3~i%#)c^Y|eAkb1Cl75Tj$jKmLBg*6;`G zZhYs3H&gh3O9^@Z_phgCxewO8up@$Lh`uY^3+cdmME>m`!{wFvzRNw+5OKQybi$%y zSql)#H^eH+Cu!VN5BbY;hY!c@O}k_4A#F#wk3Pq+clSXryz=1OxpR4idQ%rI_|8N< zT~+SVg~4~-02j$?#GD!~lu!QdrTdqnt)VSi*S5qvpS=^?`ubvH6{!MiNqsF`ALX^w zjDasYT$}H0$+bj7ZGAFGYK->W9q55y(Zdko>*_+%?KnnrG0wiW{TK&HC#|RTBXdzU zIq!jM`G_XH=B_~=n**OH=j?Y@e&GzZiupMf|QT{1McKgf`_>+c%y}3Q9 z&Vo?_I(+O};(oiY@{{Qm;A+k_8El|qombyJ@J4DgIC%4Fl9xs}^|kkCWqJUYhVo`sA@1Qn(`{2O9m_MaUnHu7N>Bwp@-G3uLgq{ zak?q#5*A*!W{>AB_A~-#0e&OqVavW6(vKKlm6)JjD>Zm`kzH?Iy-a|+Nq*g)?R&K#iIf7JWK>&UQ z0kDd_(Q9T`4vSnZ1MDW={$+GDpm6YR!HY(mJJhFmvVf8X4GA~}!S`-YaBg^O?o;fs zxt{#f@dN@?2vzj&<3TZ>)2~&aZCT_#spM%Ca=+aFyfRSm6^$s6RLu0ATX@N$R-U!M z%DXBpc@~094K;#DKl^osSmo7y&J?8ohqgD1&hpF?{Qd}#011!;h(!z9cXq^Lura3W zTD(+OcUSM}>FJZs^vTIGJ(En5$zA4Rl8c#}Nlwnm>7Gtc%}g(q>MB>ct6b$BY;3cb zMeHD<4WSjZAOTt+zu)uubvt!V?#7RgEb)Es@+|*-wTi#^B+O+(uZpO6?|fALeO`h+ zU{2yJ4kcy>gY!E_rtB)Xi<2ds%L9~XpQ%^(PTxR+qs)+0Rb3T*J=6h#k+}!HN2YIG z0S!w&U%1;~+e8HR%I9{+-E*BO70CC=41|AaLiTRguYnV#Qe1^}O%edpieokhmnLp^s6jZpW%H9evFu4fY@`Ke#s`E&;nd%*I|5c6zbf@tj*gD>J|;Xzs1qOFKTI4xsxg5aQh=Mw`9c_7XKR znS?pv()7LO_dSnMkMH3{DnDO8@)89IhhvIxYZWG8!}YmV=V@4~d_;I~T_0ThASqH8 zE?!92Ysh#08W9w>UElWF?S# z(2wX$WO|XZh(n%gNBJ^7_zTNU%Hh-|D_SE)$n28v5t^nyYRGbBi*#0{95SLiZv@!TT#>Q zEV?&EQ9t{6Z`-*oDfU+IpPhom3w($(Yn>h znG^{8T>1ApQz-mi<7$#Q{g5HP7)mc)sYaIQ0Vndd7RL~^Hy)Q$OW@UxsQ-uGipNJA zV*BrYGiqMwi0dP?NT&8l@zS;NNzcg?%D)2G8s`}hSd0Z1;#m9hF*Hj!e_00+vWTa^ zpYn{6N)}#|&WVr8Bz|XGWK#pTHEctad>CggpNY>-or*tr^$%07y7QENOV=%|DG#kd zS(6ukc;Z9~Zx_y$JETFLqqrtas>tgo0CA$Zt~uU#>y2cXep<-+FmDYBrXCnwWc1JW z^*iEn-{pii(uEtmPd*}?h$ChqRH-u`{F%5(|3BWd(zt4lADP>h|rTKPbSBVh6s(YMfpX9 z$lplkrHaY0O!AocUC}` z37NrQ(G}Y&cSZRs908Mr*HhGe{rvK{{j-yC{jc7R)t4w(`tu91=@A_(K0KfFmgxZu zkWcL_gjbz2aI8Wm&75`83V%$^L2*oS+^&7Qqx)KSf;l6FvRW(BMRhoj@7O%^l$ zszx#Zl)c>Xl@Ef#aUOiD3*;C-k#xxAa!aEBH zR&xO80?Gic?$}gWkq|+`tl)8vgCQm~R$!eOz1|Z~VT>Z{mxsM0B?7r)()xxaTc8I} zWbAs>Gw-5EW}f`S(^;zd17IMq)pJ);@%KK8RUVe>d2&+j4-%?^2jEdJ7GS*Z>tHZ5 zi{zWmk(1g&wNBQ(vVrhNa!!y4siwR(<$CF5ae8{Z+!uv#l~+3@=>0T@ZO`uAapmHr zXny&5`jHkSrELlQd1HiUF>C>7OFoHHHuRh*U}&*lga|rX>Kkb_Gn`X;0o=`HD7r8~ zh3iEtz9U?g5h6Bt;v##yJhmTsCMnbX^qSuP(lH1Wg*|xBio9I)eBYtRQD)&DE7-e# zB8wQ1DgVCPu;Z0jw`6!;YmvQqyxl6&<9PQ%95~}RUjakle9^qxiehe;TTp_SV3IoBcsHHVNFroS~bX>_q_wu-)jl;OCq zzWQps{rZo1C$P=4Ee=^((;C;_IT_8>^(m}9DR~>M;*9|b;nDuaGWqdgIt?KBI85Vk zs2sYFS=5L3IK*Y63=EH#;H!xG93`@b^orXWBYd_|Mh;;~2IackS3UZkkwTHbeWvS>@n%YDy7BY>r7&ag z(=?k|asox27N*HcxQv;3>TOhI$z3n@}nU7RXF zmlt8U!0YGwT(dt7jZ|btNRnQyM7dA^la8kQIdheIaY*Bn>r?n~m@<>$jQi>E`^4;F zQt973$Ndzx^zQ4)DX$1`Qbse&UqtQ9v=(!TX$-XXJatM~DA* zuiazoB)B%$qyBo?D)NmZP=dN$4HE<%zF*tz+B=WRb_VNv{Z zj;233-*UVz8m4VAM^BSJkc3=dPYlG)#p?JTshCFB3%`t<1}MBfI#P1R75dH6J!%lbm|3-QjW zcZl3+CG}u7+Bdhw$#W;6d!%mF)~C=|m58mCTjR5HpG8MgN0j2VU9(~h`#PFiUWFSoU44o$fpa0uG-eG0vzz{#HVx6=K}{1raBc57js5z zY4k>FA}JL6caEn}7?m8_I}-ybHDnUGrj!Vai7P#k4?N?BOOcWbg!Dh1&nc$;H~XS} zM|;8tOcx#$*g)d{kz17jmmeKmBI>5(5lCf$uT zcJ`yUxMr4OV9JB*kr!F0(luKL$k2Fk)4iG{;!x#OWjY(;iPx%dZrsxpMSJQ}=YD15XS&&hRHG6UJHMZ^ zB0o+Od9}kmGaAV#3qb4tGsJ-!6lN7-*K6*-Ji|GUPTTgFJ=jcZ-P!T6TJ(=Lf`Bbi}jGnta zQCnFX6VnrkS5~7t$R}+T=ikz#H{X0StzZ5ktcaUF-yhSAl;;kTx39B7y03m>T7qHk z!dPu}O@igimoLZffAja_)a6r2-aEMS0P;{S|6BT}@@(b*XTbS$SI$RMV-vDgZ{jVk zp&O&05qQ7&(T}17!;S zgWjxJL-#jiBv^G;P&mPBXVFGCMO^)-a~kuTTI9xVCOmyP|ApBIz-w+4oAVi0tR0M0!Spy z-S;pQOp>sRvOP!C!XpY+7*_w_6I$|t0L56;^xiEpw~9S`WAxg!Sh{sHZM-N5LV=Fu z8%tu>OD|Bl_DbZ{Y>5(pZH8!plHDzYdX+}^$+HO#Rh(2@RYDE_&-O`RQ0b7Fs$|AS z>KKrtR}2Fy#^ThvcW3mEQ$2bx7XgqK#s6BiwvX{_`mL4-tlVIZU6NI|!9$qcW(+Lob&~oy^L; z5Qctv_o>k&15>MH#DMFcvgx z-QJew^57AzcxuQun!^vHb-X!;4 z3%g87qU3s$WtaJRPG_+Sm&06dAcRA`V|sK1L8h3nx3akUA778P%dl2s^f+|rQ0T!{ zXqubO88s9H$4CAi*47gJVtBqSne^V;N@>R~+D2jY5Pl4?6+T?Em6`_)Fa6Tc=q9mK z>CX1gJr+iU8Sis=K7QsIxP}zT(U0erGgUcO5ciA>OO?20kv%H$Dz(Yb$D`a!l}r^< zM(TMb`O14W|;AMpCydAZ^DRk6aHMg1{Hav`)Qqv z%!nf6at}Q(pO-268vFc72DZHqwer7!tCqfLf^&MvuziG$sM|7 zFEQFv(C+7g505E=?;nEU>n`w6GTgAG1(_YocsT+6hlF^bGG?{B~Kofumn zN0|KfZiE?g0j~{Qr?}SI=-9f8RY{Ez>4EcT2>11-4j zzI`s{P@)VsP8}9dD&;ZqLC?ea)i&Va0Y+D`*ZsiEBT^gYH?4}2qdQ` z-Mz8vkA5W{R8oNJr9;tla2JKwR-`;h&u=qrzlgVsi6=zgu;)wJ|H~ITlQ8@`LZ~!J zI2SH7PI^`fC{LE-1%__^1jWHtS_}CLv7u-~e0=8PL}R>9K~bgI)T3OL5T%cdy$B+LuTcPH+quv3+A;aK5XB|u}T zG{aEe{ag3Nwc%??0JFuJVa(1`sx$UzEb$JXrGg_bkp~OArbP(*rVcnyVS5l5Yp88V zogdsI^E!Q}d_?{&ebz(P)7z6G4KH816#L2ZRe)ZKBK?%$J5oy1v&vQxRdRuLhUc!t zqfuxiil_HmLqbop<338y%>4(c4Pbv4In^aOqoLk@z4#CDWUtp40AERXFF%FH?K`+X z&U|z_>f0Nl`}(b<{QEo=*@yF(exTQB1NiI_|4s(Fa^RK<_J+@IAQDp=cm2Y(qyQOh z;Q6Ywd!M{kKJUIf!bqngIy6DS+*#%g&sv^`p$h|wXYKw-tAu&I{YSsgY= z0);_aqoNT5(y9AH;5f>EbyKe8m+cjeo|vaLOLZgdSdsfyL$`EPJe>M_gK8$~VNU?nM%rMw=)1~QR3`Yq7st@4NzS;#s2 zw>1EgoTkwfny690XKn;;+E%xPT?nkMZffeTZM&1gF5H)ct5;C0$0x^@wEf)1CHIBcC`f?E0fzp%c=mB5`_RKG!nZbW>a1 zNwej};>bn{UG8t9s{iCrQp`1;O4pSqG*lircqDrIdysqSQczBpf|GA2S;pr|clK28 ziT6K!AEP6Nfim@@hiPx6fn9j;Jv(7aC*_gDM^Y-N=cISPrJ*I>_}SkjTO(kTox? zSR~TrMzj<*#`_6`D?h=Nf%Xbk@NEb$4 zNOBC0VPRa4KcJWRntwcAv;bs5Qpl}WGB$`25*o0af{I4h${ajD4Vc?-GFUgGys|tM z_q2wJg;1wwbNTreRkiS{g-D-FVf4e8*Srk}ATp-ih}DGV<|@QT!}`HeY}> z2SIreCQwp9wNi38JOI7=5_&h>Iq3a!US)(C4ik0OpAPkq;n=tO~{wrIoasnIfz)A8-Gi?w)uE!&-sT zp%Ma@C+dKk*v7)T4Op(0$0NM(Yv@F<0MnX42&hD;9PPV<(O}0H6?r9YD%pDD=XgeQ zeLc|?xng)vF`!6H(ol{kb#8|?*=8P;$pfT(y~CV;3gE6|y9tAOf{VU)tnv9BEqiM&J4wqftWi%Fa| z;Q#1tTr+Ghp4YbSujmEtBeEVAvY}c_&5FaxL9DFLkEpXc^BuLKU!;+=GAXlQPt6<2ri>X|m-bDYBjIBO>l3tg#z2~P@N zjw}skadAF2(=O{CNpc>ko4Re}}kkSBU z$nMModa{@1N7GA(Oq;}7u!LPz8Sb{(-G+p&EV`|HMQ zhH`3n@W9BOIDhGUY{QtfdL^NbPbsE^GEqeM^Wt(MEfB@;_TP!d>e?8%))m{g0{^Ew z`NQa(yc4wtcT$j#NP{K!V{h$&xc6i- zn$|bK3TV3vUzkLwe!7zOg{Mx(w|BilBN{r1Kx6Op_s6kg)JXtuq%EGWG|LcvdGZB} zhthooPH9LNJoV>q{WQMy$}8!66$)uI$4GAR1`3Due8H#XmE~(HqIa|>X6I+(%xAQB z0$yC>ma;8)c#9H@`M!@aL>h*yA zWFWvJb9Lxy?5fxmADsChwvrlWShzx|cx-R&8&vBThI^n*u1%c2gF>zVrnj+cxGUjA zZ6$rvH&C|$oKUebC)4L>z%s3cTOT;S_i;ZkQ+$}>b`tErmkar9hyWzhXs(U3-AoDO|9$z2rFmnX?KYK($YcC zWLvvU%TS*9Pugm9jn92Vipr;_P9=Q&=%bI4kxc`V&(!PgbEPlN+b94d3&gYCExU2- z5gh~GJkxwIE_Yu}{}yKC3(EJ(Z6`iHktN&)#TVy@spq1qShjcD$g1WEY9e9#3A=WJWu?y ztTIL7Okx-}8qU2|X1;RmN{TkoAnRWGGYo&b-g6@v8J)B5vD1zF^u)6uL>x@uHm+^lH$#)S0sFS3SJ$mJCqE*=JyMax4LM#2hCd! zTu7^4-u7BNE~ai5bf{`WE%ZKD!280PbFsH^C$jXXarb6-Y{!v%{jHPn2xrL9|MO1V z`0+EDzbj-7}oBDFEvZK8wB9f|>}{8v!F$5beldX0My_0m?QR5zb@&vwnkgU)V7EMQ5W<2O}TF193^c&U5vA9Jy<$Wy5@N ze|_~402^PW2;j1%s*YdDm?r|j@FWFIhk}KDl8cH^4gg{qsY7MKjc`0n9_3uS!1MtJ zwhTt~h;W<6Hj0&iB(v}+1q&JT(CN=&>yB;F_p?u;^2j~}OsraLa0LR#$i!rva2$RW_@EMl_>={z76@B*yW%ZUKk+OeGiNe}Q0LDW01laFtU9V}2V z03Hz=2-DtJO>P(-D$EAB+#koPC-nS%MA-5K18NG&QnuviXQxxT+P|p+A zF*i#4h{nno8mBrgIolR|GV-AB*40=>>#|{l&t+xB06)YTKzHBGVYWz}3WG$#q0lDb z`C?$WTY&*)3Pez$QCL>^Pf87!`5cLhh@gi()ntH~dYz2OAu&_1Q<1RJ?kI(%icln7 zrzs!2@C!KbKD~r`=nYjIXpZ|kFW1i;ktJ9+82fg6*QT#giEDuJxC~m>G||b zRYp@M2G*(-PRn%@N}Nii_o`_6cM|ll!X^O^7<7oZ?uiiqhWa=^$I%y##-+|niK+OR z0;@`tmPFyoxwxNtGR>D%2+79+xj2WBg|H;UGYb$HQjR9iOYMb#PZc8tu)_MyF@a*U z3AnLmuX}4gnF6hQAageKF0B*zmcdC}{4G3nU%nh27)kU-soahbsghR&v+21V-}#O2 zqI5lsYagD8J(cx@fc7N5CK0l&7hvJ3>z&uq`c)2#c-|Kt9QMnU z3y1ryAf`eod?_r+TohJ3Q$51MP^PSAv_d$M8Cf$S8{)1*VKJu=|GgI|yU*|456?~I zQbpCXl(;%PZxwU}XO&D1Rtooe8#E%Nnhkhe-FxB9YxJb4lUobZ%OX(HB!20C=2xfnNk>o`tnM%KQHb}Mu2cBQ3^N+nGUJAi$_xtblQ^A( z5ca_R^v5&sT%?=+?c6*MVbQt!PS@#gBM*G1(J0PaLCouogm8F1316i(GEeaKm&fu| z&^Ns0_b66s@iGf$x+Znh2`Cr7cF%;NQLJ)s(A(l+zZJ~ggyrrhbmVmjuc9mEE zE&s_?9v)6hUWPC=|Kwq8|L=Y)rs^?>J=Yvd>FM29MA5%}jZyy0c8bpO973`4z@gHT zQWWjmF~D9fT|+@U_IHv9wThB0ar(@sv8rH2>VS|Usg^uQ>z97jBUqXuqp+#KE3fg4 z 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%0DCZMXZx~I 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%0AJDfgpIt)(?$Mfu78w{I_*TI@& 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 z zUwswPvLPJT3l}e@UY>Uo=hDa5DHPAEAm&EEHY31%RvQx0v1(lAI zLTD4l*`4dx5srnycm7S|VKYB_P8x6uE{&l{B7f`on*vK7RR}7C9+(9V``*j*o`B&tUZ1&s_&dqf_Pin(}??)~!@kRh61cn$z&Jp`ZhS zF%4d`D^yy7oSwPPaSy-O$-I2|t90==sn|Vj>FnXNOxl=@`_xF0j{Iubk06}j(tf6E zv@_bxXz`2O7xC;(jhWsC(x48pz=3DdgM4zo++XE`M#DR`ID23GG+uY>&aE&gP0cOc zRgoHw989%`4yFmZtS=1w)68t6pX-pb(`1KjAj@YZe+|Q&GAHQKXtzA#^J(ZPi=-PP z?`BANUH5M1W{f&yyV31KWDgCJQYnAv5W7Do8SR&El$9w58j3eLBO~!&5ls|0>VS9t z_`;v01x7JSL*GCDdo-M*yp3m*R&;95pF1CV&a=C5>qeZppi)ysQ~K!kN9a5v>70?y zp?f9mW*RcuVV!hN{vD=Peh4`zPw$}=qNc7UB3*)1()=s%>di+tLsv?7_V{Ro*H0Wi znSSz%p9GCcM}h_8fR~=RMxVfjAcNogIU3jkv?CKE0l-PymLC-EA@!SUKLd=hR@f+z z5hm$Opv!ZuF0PI-WfglUeIxZ%14yG!pu-XZ_fF@qZ?G>iM0{T5l(NvT^2Rmfob+r{ zx(~kmfW12x{ICxD!N~ff$BzP3T*7d!-`^0KV9NDnQst z&9*dqyDPQ*^i!Gz?vHVOPyhDIGjr@Tg$9%co`evDP#Fe?|-qdmgya%5MM)o;`|pd9!$Mqgwe5gW&$lxx?=QE zr&U|WG=706W!(;Ru-OF*fLx~S+mptIx$dL2{+(^qO9K{|1!6W|c5S9MRwv5l$~up( zApr60_d4S`*4h|m1nAs#wll7j6noFj{q~%+5&S;uG-N;Duj-HAUdnRct8J!3JcSdX z1FXC?13+EmvINX)YTs3onWnwCm;OX{Qm?4PX`rc{@`)tGx!yXtYehF79j3Y3h3R5KiizC|xo#I*E?U*-R9AaDb92Mjdj7I@Q~X zus!H+rSah2*bBid5`z#r`|gLbSovfofY0l)ahT7iWAR_F>gwvy@$!Ybep>^x-H``g zBadck>PeS!K|ST<;Y7d9p?v@n}DySbXlx z+)R9yJppVmxdu?212DCn;M5eO79TPGuMAz^hpd`oFAf2qy-+@}C-$VNtgZ?WU=BVX zeJK~8@Oz#45o9J_RoEe(#UgysN_mA@g_i6M;*>3G<0B_@pwtET00s`d1p5a2`$N9u z1E$r$H|L<0M^~=V=b|xW&m{M>z}_a2=*`zS-w`L&vJdo zAuEfNW%U3lHoYF;b8?Wk`WdSPcs8S-w&l=61lxRhG6SqQZgY`L8#6-X%b9sHn{mF) zsHvj6dcX6`d6v-Nd0?PFoLzZA+ShLC>Fr@(0jvQ-wp3DLbmTCO{uK(aXd1`0 z&61W+OVA76+Z@;4MtR}Wo}p9%-|F+oFM=Mc<724~KzX9(Fw$Fa=yo&|U|019q5GCnlg(Gg)_4 z>}3y$yc3{No+$t2JN1qFPKQ^g*=N*$lGc^a{^OQ|FO)Izr1p|~B0b0-2AKRD-=o8= z&Qd1`4Eel{#&fAl3<4=b1x8fRSaf-#BkqC*&W~LmIpaWw@#OijEz@D`$hu6 z7kuz{*`)(E$*RFF%ic++VjpYW}@X zk2SGUt)V;DM>W!ms5Q(LvU~>~2NU9hFH$bzadS>1a&=q`& z@mZrZ{YyV%%uFZQ5?dH`1Cd&zym>1rF?1R3BW0)c%&`zeMzl;BbU!q9R8;Qy9_Gvr zPV}epfBVnU?$?f{l}#Cha14c7k8`79-Mo{LikzqPuu`y`{^o?r;|M&yr)GX07l7lW)xyoRaNQIrAy&F*-3Rh(M1KC$m0qP zOme5GtEchU)3FR-r6RRy(;8ix%?>fOZi1{5mx^z+vx_sXOJf+sj`JHp;OkImoVB)+ zUdNd%ycCj)JX;NlO0-{xPa1D~^q6k3*V7?T)=3-`9XbVuLRDwUGw`3!qT{RcFCVzK z{U}}28!O=#>D3H@0)&Fd284V?oT0bJi_n?xZy`tTXoF}?45WC7f`dpqU8|Ib0Vr-_6a<#cwg=V(;RI#~Y| z7Vn_L^$2v=$^?e4xS#C**3FP=iPijNCnX=Pjj3YWzBD>Z14R^yPN_m$8Z%;`q1d>e zw6`gmM)Ax(r*zRm`de2|R~Xd-kk;b+jPB_KY2-uC>EzGz` zeS0PYLubT>hn1z3QNMWYdd7J-5~_ouQr3|b1vWj~vowpsy)Qud8C|*X3eAzo4)DCp ziZNS2hw@D2nHX2rPv(gHtkbS@r4003m7ND04yGT{A7ESQws4Y+qT6iGT3H=?(=}_2-tQPYs#RlrG?_5lk#}6`sa$Pi7daL=()HU42eXfhzLX8x&)TCj@IBJL}pL#GHox9$Tk?Oq| zmG=6cnb~Qc`Qy$<0cc1^0u~P+GFKY#r>3ShHJ3G~rwdQhM`T*K?}AiAltuZPC1i`| z@9!Ho>`%A*ZU>DP?7dP7G6YIWcJsTE zI74|v*`tBv-uu0@;O9rTYR=ldl5PbfoSm#uS;f9MX<#pW{A6S(B6P1FevQoSkvJQp zKSmoIthFZOzohO-WE=tG2*KyyUnarSK@{DjDneSrj^mR8XnIKB2fu^cIn z3_Uyj8)ekVFm2n8(q=>zmOwZ4HPPw+IoIC;uxy&UK?&3O?U3)jSng&@s-J7NfO5+tJ9o4T%3AU{N^Kle#&3^}+l zMk{8o)!5h+!3-V!_V)I0I4n`|8Uh>Y0QW{-7TAzJy$5wvwuHe9!#!jJP3Nv8+!4ly z5uF6pbs_+d7S0)hg(QJY3F`I&|Frm+VjWKq1P{@o*#e38NEQSltmyydGEQ|_*VPb&+xqEHLr8; z&b|1m9rBzE1T*WLL}gi6I8of5KvI;U^8Mi!y3r$}%F0Qbp5r;lCYdAMd{Nrqj7o5@ zCvV+OrKeBFnVGHQ^7U<(uV9CqjMpfOefDW|7BOmUMnHJ>-0a>#z~tsP--zdX4DeXY z`Rw9z_aST4EAo&ITPYDyopndL%A?v#=PtYo=+vI>+`P>cE=C>RyB{F?Q{;(zF+qS} z99=$#tn<3czH;_>6!~TpxQX*o*Bj^>=IbOfdl?&D=TgwhI&f*llF;q7bn92Y+b-nJehft(S3g^lZ!2QI<6iBYC^0Y=5o(2tIx87$A&Xj;CX z3_|q#TLuz2D*9!NL6>md+9YIAMDv#!iaJ}WHJP%%rcl{k5@>I z2eeuw5Rld_(7$OW4JZ0S0h%THj8)gxMD{^PM`wJNpQ(diLtJl(| zQ4SeYkVcJm3$|KvRso2oEKonlT-oO}`&N)oeIy8OFCI%<)v?;Yv3Pyf5%+z{Gj+cJ z^fpGHuA{$E;E1;=Klqb6uZTJIvs!%X@J@ydRhHMExlL`&yUTfa+YA z`|tAJ)p7ca$|(I`_r)Hi=bT*fBfp_l^qi3&FYC12AR8;0 z1}xE7ziHZvOUKpD|Dvm>5GdA`s0cJ@1P4?SDh%r;bWZ#%qx^oaan=L+WWxy~up0mV z&P{dABlO3*Kr2DDR!DVPU=HfqIB8QjuC8H5$}}Eoj1edr8VjIp)|Ul10Xp176zS%d zHyC|J1PP~3W){^`n2T6jAEFSR7#)wMT@v^DT$($Os$+dw-J$w$rpyp{0dQccz~r+j zBD@&=D0&6HPN=AmDeMIeFzNo?q))G;k(rU0!D_m{j369{Wn^;cS6Nh6aZ z@iz@rK^3F4Dj6M>a|h3bb1b90fB9D-sP{mSjk^z}zSSW{7!{^LYO?44^3$~b;aF-V z>aG#1LLMa|u|x`D7CF`_G6JwV53#=#jIojYPX<`7M{s@rR2pJDTjk-#bhNxB%~0O3 z#=bcXp}IO#E2^>%0lc~#!oQ^%XJ~vhV^s2-E*%Dy-}ScZ5j9g;sI1u9G%giNWmkeRh?-V2uq-9%Gmb5J@xcp@^KB1qvwvk~Z!`aHM^JrYs15ncUCN zFjXM9pGGq0h-5A=+61|aj9H}#d@n*{1tFONr zfR;*m9>j5grh*04BiM-;h36@@eDz$0&|ZZ@?4vE4h4k9ulwbFDO6O9PjJEu z*e8{j{G2B!lo(1CN`Mb>wf;;b>P$L{OwlkhvjyYq-lKbQZ_=CBui03g?)2OZMWnI%fcwy)be}}`YszYg0x{x_dspV@ zL>wnm-~sh=zF$X5nR2W1RtV|+00}zZM(aa(vv1b!6`~aE|MBT(p9WYZjp>ltYe8O= zex-T$&NK0B-6x+}Bjr&WPHcXDoQVLF{Od9gdO}jVB%3 zw)V&A?Kj^FniUZ6ecb>X(uenOqTvMTm6=q2mFS7%C)2HmINF@0GRS{Eqx>QLxi?FM%@UN)?7d@eW2@a-Z(4BNcrvm74!l>;fs--?`6z@8`&` zFGzLWypDb)^l^~BEGaN*P{q9ng!me>#O(P0oyzZ|FFL*mr&K`2X${J_4km}#(Op9% z2Low6M$1tYdJnSgC}RvQ6Zm=&LEZVr5$1c7wLnVvE2qv$_Kig&Hs6l=2?mEAJ_{-)MRx-S4}fZne{Zi`TdZ z^0YvdPOUPk^>8ca0N{4_PFh!#8-Evg^tBrKo{z?{v?G7Zv!1_aBrt4^ys}^`Mx{J{ z@#4i)zOkGJR~ysidzYgbmd3o8;)sqMKY>er$LQ-l6 zI;qJnVbV_@y3%qBYCJJ&HP%-#^jC3?Tk4ny&^egK?vbTPgT9ad)8C|yAN)E^Uv5u* zzqpjrz40`By^WfWml0D4XWOPN!C%slb-e2+n+vBMo;Qlxaxya~JWFFn-?S2;pjHUUS`MqZQQykHPkhv&PN&J zGn&1@U-Gdwi4ME}bZ(Vh_C_)~E&bX{CF}fqT{96)Q_lhyrswLo#%uY#pX1VL72pcH z2bre))tT1u)aFu8+O$pDa2cIec3Bdjb1UGNFs7@jtHOZyeaZx1uYB_QmMBWgI{wmu z%RQ^%+UmS{oQMVZU}+ZPnLtY*7rad1M;_|#Lcego>X6)A8jaz28#y)o+Gq5BU6F3@ zH@sIp?h?qE8X?8G6r;U@$rAAQIJ&F>r%1<8zLdUA>wQ8tfZ!`#)QJ8vmW*qdB_V%1 zX+gS_PvsZog!Jq+wQcQrAW-7->2L)tAYs$(jEGxoAcwKQvOyELX=b>EbAb(Eq!rwnxq z>E_m&A34rcl1Goz_y6qA!j5nsETj42AAX!BJUi?tK^D(Y-6j|^1})4Xn@Wkk>vXCE zwKEJ<8CY57+2{KQLdVXp&7FScO0Z|LeTm!;0huM7Fy*3pXO3qxJIN8?+mLq=yn)uF+tWCi%3c9IWh$Hm zXjzfAuQ3_v0sM~%YS!KEA3KLKj@m}(kPIIR z@+gB@PI<_SeT)>GLN*sx(@S6h-N5J79c&~Uj)@R}c24)GU?Rwl8bGAlD%c0d{$6+Z zDLT5!a`$r!I%8~t2z3R`FUOzITZFQ%k{xO5zP;F9fJOvJNAaaL;Pb3518P760({z^ z^1A^a=|2`XFF&idJSV@`SIPh{^!Vazl>6!*dB-!8Z+*Y7RmW(HY9AOW7woC2sf}ys zU~A*(GitxPmbYz4n;CCtkFF~0vl+n0aqRupH{T4OVHEl-gHGCS-^K@P3INR}k53JrTjN!#Wh*pPI+h4H8p!ur*Q!CFaVwoDd|LOnrcL>q=&JfC z=uM?uv6&Ksc?`Ul0>=7R8CnD0dkPc|!6eG(UVixbhaiJ32qi{M@jD%p`#5WYR8Q}; zr=9ZvU84XK@4OSUj&0U9!>AWi?$)!98c9Y1Y!Xwrml>@4XkJFDohfMN&b^X8`v7Mj z$Hk7OXU~$7i$lE=`cZ+}xJcS?f9AQzWumi9py~TKUk!rndFTx2zzIUw$WKI8$4o%M zf9~ZXd%KDA@;N=TVT^Lq8s|Baz0j0t{dTTZiI#Ky8F*|L4$NkRuXN`gnHoOC>#C{w z7nxl{p*sez1Vhih1Fi{pIut#x@8`8+(5PoPz}I1Tz_Bv!v(bRF-~JYzaj&O!oYe}( zoe`~FC7DSM)`d>dn*o(dPX%hNh-O>+U(LOls%rY%^7yl~VVN59xv6xu{W>Fu4hQ_>|SVC3$(a5(xNn{9BLu5Z$r#Z&cU)94QCxym4f@OGL!Z$9=S-Q z`d++O)VmtKI#7Ecz=*OU4Ce=T(y^viQVwV0x*Ci+j`?|jqm1_1vtbV-esa^^0%|#5 zEJV44Mvrt5Mmz?N(P0&8B5)(G>YyFne>8Q{5Kun$zC8<-(HQry;h`e0+F3=K;fqW} zhO^a?Ql8jNSp&+bwSbz9hFtYqF*arf(&rz4oZh(jW;(O|O#16z|8+Qa@=$$UeJIlV z_wQwZ7xqCQVt>{CRFtYY*iW6;%rJ`3(2{3r>UPr!goZEwknQSMor!4gK0z@|0 z9L0zT@n5(Av6&**5+Y9eB0f@qw3osj!DKj+Szi%g}fx3300$xHHsbmqC~0GSz5 zwjRKrvK)EGzBx`aC_v72c4ug>dOQ3_F}2wW0w}&;eX491Q z9d9`v(;kfOyW}S$DS4bpF8>WZqqZ3u*SPm{ii?WVKyP1~qzPADX=OTH4|vZgwXP4Y zq`Uv|Z_@S=N@)J_$Bc}`xxD{`Oc7FO(W}`S{<6dp#HhZPz#%B=VC?M-$$!tR$5w;`a#B<%?XMQ|=_H=aH&lvC4`P`7&`a79mb(~`&>k+^ zR~{1qre0>Fx=*9@9avtRPS01Da2ScUcXSY>Vxr5*Q>hnQMIf@Ry)8AO%av>D8Ep`G zcA7m~L5EpWzr^$SJD>3xvStbppscz&?Bq@8(s}HT&BzE-%a!5L4-C2JIKU=G;t9exGcuX_zPO9;uq|vz_tmsQOuBK<3y&;?`^wco!<9|AJ5#|X#~bUD~`FoKENCjzvB=Ow#JQva>TWJDoPD209T zWFY0iGrM^IRM(?aa*BXn8$D_$o5pyI(qo@f5KlT*@5tMJmCr26kWQ5w&z{YOjIi&O zGTL)<-~1=v=-~T1vrjEs2|7oHDD%FwwI>20_J>=tOIyTA03q=FKXT73ZhbI+5HPjLZ7hDyW_4Po>GN9R z{Y^FjM1(Hn7JkE10CGu9d5(hoZ70!#c8T_MB48vG1+|23gvUC;O&aaZD zs_@$*Wc;jRl$1`mHR^T)&t0Dvb$BzRGp*76|J2!2sh`@r%?QLIm_}h8>H0*8E|L;w z>Ps$&-V$kgGH?Ou;LmU@*3*TzxM)`z>LVJC115oM1gvbOFTsiW)bi@dsDIx|4UNR= zbGVF_iO!iK>{98D4&X%d+4Iw6A1tG^ULt+(y!Wl>BC8S=+1}YynR4q(00n50NDY|H z07vPVZ+B7!u1qDvgfL*g+|PGk{~a8o%oquyoAz6fF=UpO8b;6z^@QTGd*-Ri(=juY zYF}j6TDtX{PtueB^#^I&4MsVkm^J41f_5t8274ISK{PgR3z1PA4o4VOf-;)=@A-H( zGNx%6 zPY;K%HU(DY;OFdbXb2`2SW@}85Bs(-`@8K{2sDL#4T@uTK9O=p!8Pn{q$vy6r}i_a zldK3zBm`Sxag>LTlU@tWH6e_pYYj*R$^b^gTpwxAg*23+=6x0=SW!ik6DOnUz`^w8 zkA8$voEdqd&{QDKbC3Cq1k{l@`qo=P0~#VWUQzIP&bM*A^5GqMMq}Mb&s1AmT14?_ zh`FB%dB688OlxWeJkc50fiU)Y-B;;&2^!zeUYU+(>YRJ764KC6z|C+?YiVZ?j?ODJ zvYT}#1@(-aXfT;(-g^3U(1>8fD);Fmkk5boV@CGujq7&yQ9DNMoa41-t*hibRYVG4 zYiTzU(Q#zv1`ud@$nqPTV;SvodFD$a%#q!~cs0rg@~E#pNLs%%>v`~T(Xh<>-iK35 zZgcwRm&|&9^<6qXlWxYo?qsCnKmPJ3F-FGsRFqXfrzNrXHh`PIu!x{HbuLC z|6Z!90*v6V4cL>Lz`A z?%t!zd;1tV*??R#+epV&dFt!EKlf6F7r;_pCW_&8JxilE@4WdAbJ3aE&Y8>m-h)Pn zb#RO8Gf{4vI&EFQHT~q;Pr@IRkoS$G$HR}(DWb`D9^YZ!cVmEQ8uU8g zubqD_MvEG)Gz#x^jkF4~2rL@u)aX9hc#;V(c^J^hgPfd@N%FpQ;@KN*l9uc*(1T%Z z{krcLJo5geG3DLEhYy1H+-Lv!`98PzFW@IX8QY~0e;LbOJa0i24L0S1MuAD+PgUa7|bk6A0 zF=(7Id_-gIyk1#Wi5>bP4Ns2HAQHf=sug{g8HIJMmh@)iZ6jF$kAHoIj{TpeOaK0F zQb9lW@t=R5(jWl|Cb`Ve)NkqOJR@*3{d~K@FGomS-MzOZm6e{Quhr1i zU>6wB#`ALx+6Zd9qyv91y%@dE{@y(|I_x=XdwHGpG$mXX0N@x*;WY~R+spmWuB{n7VQJ`R8ee%PSAUOsmuuQDK<&dv^;+L3hZ zC^OpII@6}S{I3mvK@j=e=Qk5cr$HUttwZGb8_ASclwAUIM@}72eaq7cmpW~y z3;pcvUZS*l5v>e)$9_Z;N%l}Mz-#!KJ>5O&lybGNKb~bHdnZU3fZ8JS;|E9(pP5bP zE}oB!6{Fa8uh;p{*^raYo~CCHa;WC`p;U0NKDwyutW;y~41RejJwpB)k+q?u_dNvv z#S|szc$IU@gLj<<)X!&3y_8?xuYGOidA25W<<%>f!$B9|UEuTd0uJ$edjfd2mQRf% z@3sS8&T`LpZ{JMMy3wcXn-c{#!v{lTBAy_~q8_V4Ub<(}lYMZMhi&)o8Ga?JfgT7j zm1ixurB7fJVCl=L0FxhIiaty>Le53r39ji}E)Vo$qmX4dO~Y%lV#f)5nJrzKi%#i@Db=K|61;UW_RKur$m!;)46(qYDdFwN~Hqj8Vi{_!_fYEt5^aQ}K*&*)} zm@&g>;4Ai{YA4KsoZd|)40MUHhVzf@#Pvr3jk5CBuY&qL=%o-y9MA^#Vr@M@Ai!k~ zw7P%~FqgZQ_P={JO)wqn@Z0CpIL+0y|7=JoFeA-ruc!z7UK-Vz5B-AtQ8o;rM|>78 z9$>LLPo5k{Z~HsJeFK^5N_iu@kMfH8NgLIB^n3rlM48KG(&ZP(vfe^gu$jT**pE4U z#s=jgypW}n=nuhrR`6k_>E*Jf4Cb5+raCQ3;K*`OUoYKw5BfOT-ri?+{|%&`C41x! zy5D>7pL*Efu7O_PV+og~oi6=aZNKOPz*nDzM~LOVDQnyVOW4hBokMPalK=pv`2Yat zzu63caq6UYvY|4pO5FpKAY8Ele3c+{6igp>xd|GJ{#^sbG;S4~zprhmiyEhRA^+3y z5e+s1Y5kK(wcTMA?g~BE{sa3XDr=e+zH~$_MbbBc8u|XVyN{yoUnkSlZGnJ|8*p|} z%o|ZS8Urq`UsXq{k;vF_82`EYZ6wM=!4=IG_a8I4o4D-1Ikz|Rk*%x7&a zqTwM;t^^(;V<1BpQ4a8Inv4Mi8h4l$H;_qCx-s3K>PrF7cuG%71=6CK$%F_KBs^?Y1=&NikpBL9`Y zcRmd)Or_@fX7-?urbs2};JzlF5g>riZmDcZmu_B)2%rw<=Lqx)QpId4bMM~W*e@C1 z=+0hJ-^x&UqQJK?e662W$nPmEP3_(7sR~23rR7K%DHVIffgmH^o>TokM%HYvj1+zW8yk1%nCSSn5dH5!>ASam z8m;WnFy$H6Gl?4ad~`Xj4P?@K6d2Y78v)Qz83DZ6S5pL3&Y)I_yZeRF4yFgk6Jd0iIDnYiN5vuECo(srt$|zzQFqPvNA{HLFI0yBuds z-kZWvSjYJf;Vc|(JsQGT0q5&=02Pobc7@hcKc8zo!H`?e8JUrwLE|2&)HT%XJUfQ+ zKSO$zGj%6$N}CaeHWrh=Z_?Co3r2zW>St!b1&t^9Yz)OL?dZ@RK724W96FG06M;NJ zKaQ=)i4oEgtE;P{3-AAcGWWZSGK@<#KN`l#R?@p?ZoT>01B~_|^?fmqeW6SH2I@O?3@==` z5a(Kpnczv7-QV-O)$vvox>sx@F^*01QiuOVhmv_tLAcyqdP;kzPnjx6ja2 zM(+p!hCukazH}&U`BgdL{kW%sK8`>A$*+GB%5}#co5($nGxJ)eHYyi2E;>0ovnNI- zI1A*5nJoe%&!5eu_G`COEB69 zxzuw*Z-N8@2|7dSLFI(~ChYMb4ar~jZ?W`X97jcC!fX$XQ)QLseT;0TD1+gdrQda% zGaa)d(hW^`PWCeKto?k;=RD`~UFB(zG8rBH>>1g-Ntt4FI65`6uhqM&qhX-?FMYNg zXi1)-dZcflFS4yXBMmqk%)W8q^=OQ!%#mL_3u({KwoGL^*>@%Uw_#U4fCp1EaH{TI zyBd5`y1g`gapj8u4d!u(j_zq?B;N$j&>c+_b-=D%xth+OxIpx@H0>P70Q1zx1xU#4!8U@LSGb@&c91~ zQ057cx*y)7a>pzP&p@4HefH2G!4#ZpdEWQf98U+|h@3Jy>u3ucXnflED&#c)fwX5t zUb*qxONUAjL3-Bya0wvz`N}BmG(jFg1|5E7nhvoJuQYEqfPeR%vbKZQ&Zft^f8M*! ztqz$D2eX+5>dkQex#qUw!pMlU*{3VA5THTr1!ZXg_n3A3y+5DVXZPCK*ZO?wKFid! zE9{CdATTt-J#w!`7bocIJpmuAa=u%oI~w*Dqr;w~yEb9a=U`KoZ{3-C?{^@J03_H0 zLA31N$a|iHWfjthU$X#;_w9YjyZ+n8S#>_4Zhhlw+Ov=5why{71gX`=Irh8-VYN@) zN1wy@x}*_xj?dw$B-=#!*W1;TXwdN)kHE0o(Ur9w9OJM zE2I}fPk%2_ahk!_QdWn37FoIgHnoSFW8a6-?`8!q<>aKJ=g-4ybgt(f)uGC=InLd{ z!6O1V8=z<9gHDcg08rVC@b2ILUD{qpWJ_t z*0{e^zBkTO06{>dv5~+Ayj0hGguovouy0TfI*i?cEg?-V&Es$qy+3gD5RIT|s){`% z=qG*8(mP~#>F(4I(CAWT3zT{$v3MO_JgNDwg&*llK^BeuK;(1JNlH|2>r?kv z*mTb*g}|1nIe9cqGM!`rb8vZ)%mhj{q~Qg8h3v}uPy%@S_LkG|t|0Xhy`LpGQoOS` z?WP&`bL{x#+39rdcfXrDdy#we3pse`81`FFe2hB4z>f6g$~xETu?3!uZjcF8O~%1o z%0aHZfDR_eSlC8Jixar2n%O%ZF~5XH(~|`GXzr~2w3nua$^m7R%X3%Go1ItPP@gFc z=h{^-X*=r-dv^MN+F8mU0mLjn<>h7i3G5(PWVyol7-iR-<@5_|^+oQLK<@5Z0O!AZ zKW(fm4PJTP(UJ0?OZU3{gOAe&fLeP%^*T;;JOj{3pFX$u=QYjB3Hg)*K=@JyYP-1v zuv`Mv^1FPPwV!V*q0c zz&8y5%+UnU?vYj1Rgu==A!x{GczT#_hze2kPiB(9mvGLFmWY-p{4_K+;E0R%+MV6m zjBcvYYBy~oHH9l6Ox9bA$Qyaj=d0;<1qhQR2+s(jPM|5nc4n_IB@cAkuDLE#ZD{_> z7!Vv=l$iHyQ^0I$pWUB}Q2u$92)G^3(usff=V|}9&ZZrE_oenFYUHUusXPMO2{I_s zx(mhcdpu@;whOdf<82P2VIw-L0LceYn}sk|=pwr2Gq4A%`Rmfe&fIkTz1LICR+>DK zLhp#BZFKR}ICVG(Zl~V=@QbwU^KvdSuFANK2#3b0>0&l5v>BVuzbpII@3%5? zX76#F%p;^+9-_nasUu;~wYAeRwvlEV7&# zwDr;&sx}VUPNPOkIusHr77f#(v7scIe3sry-$1`O!qHXG-ZvOkeV2|!VfG2pdlc!qI|kw&7rDxd}&d6mCFhr-Hdj_3r&u(fmYm5!o@ zVfO=S{B;_6jRuwq!*s^WzxYK&$p;bsDiguDt$e1b`~`fiV&5-O(=2VcuU^L*<7xKh z#J9c`LUS0UU3lO?I5>_~d`Nc3eqO61r_i(et|{~byho=@#i+6Ey}`glWhP=KoNJ{1_;?AO zW;bTi#oYIX>V~NG)e%(rN`D%L-rw=KmbWZK~z3ap83-^{xp4h=hMizX{m3a2L5u;k_MV1 z3kSvqK+oxT%{`mCE-winJs5lt%F{Z1JLJ1hHg1zXlua5E(vc+#I-%={su=-hSY?27 zewF}8|7d1(r{GpYRYU6T%S5qH)|^Z~|L|u)8`6)?WMgS#>Kf|G09qJ18f@;Ndto+& zG`|@>_WCy3u^wDtNwDpF)4BBFrQeW|L9-oZtIu6wq$viSJTc18W{Whxb3RSw(B+wQ z$r%7Q)B0zgk>$0r9DPufFHgn>BZ}|2KOTM@vQ}B-eOS)qxmE%mZYB-W=(Yxn28CUr z?VI2=l^5Q#2BK%`UTEk%fH$+el6@xk$g>bcc2Y@udmG*S4+Gr(eLSywd#vnOdNNP% z3-04w^|{nG+!plW`Rb$#4*6Buu<@k^v|z?%jCE5my_WQBZLs_(V0`z{-Joqj8lP2g z^l{hYR9{HlDXIKbyQ|WdSHBEiIM8q)^$ZXp=lZt*l#FaBgM4mzM$n|=Ne6iqvr*EZ ztk=-_y;uJQEk6cR&mhr4zy}%B{cC%|^cSYt%#r&1`q9_P$atO(??0S=`RV%+T{DZ| z)rJe{;~SrniA8__`Bq8!#T=>iTWDYYlnFfLdD{SEuce904^r6_y*~c#*XjACJ89-C zz#>G++EY^Yd7n#X+?=dRSO8(bw7^?n`!;( zK(myT-PNR$nnk#{OeW39WEvxKw+86Hfxk~cpOa5W7w5Wj*ds1$#%*j@UCrbo>>5i5 zXE2&gcQ<9+Y^vxgAFrkvF%f?orOE>u7dp>Im{xF(Ee(;b1qw{nFRLh{!R$cT8`7x` zw6tsux^l&+oad!XH*H*JH=Ih17G$Q&$h%o+f(+8E5pDTf1KCKYQBQ#cY0Q;%NCe2W zuXN91Vb~ltn+U+ zjnAds;&nC3-A`X{34zb+@*dRXapvrqE9*1|=;L$aL#`*7QwZN0?6GOs0fH$Ti2gsh ze?P4USTNeG{&|ZWHmSwU5vwPs@YqPj4$IO;H2mUQ^Jlq>~lyXD>D6%s+XU{I%tWl6-UtLw| zc-S79xI_JdcKX-E>_2>lXMxj&BW||r5`TOX{0?<%ZRTaGv2F~8TI+QCQo&EfL$xt8uCN^C;e_fr|jB8b5Hif zz|}0*la_MPCk8}{kb_UhMhQyIq>C3XhFq5p)n`r+TAXB5DPeM>Z(B`f&%>C&K}`f$|L*=Kem% z|0ty-SDQ$glJH;5JbI1}dVZ%5M2`~JG5idIod~GZbgU)xnShnHujRpJf7p-02(smE zQ$yoSSt4UuSy8eRUzZVq$m)d${b{V1#;+Th2mvjtYa&|{(6&N;W^W{ta_vO)k94+% zOxr|;K`~8*1zA(qBt1)>rgAbJLmmLS+VjkSR&i}5!j)-Cb{odH2Ijc|E&Zr*7GLP|Civy?6OQvTGj4} z#XWhZo~QD;uC6|KHV?UGcBML2xhCzolx_MsE_>V=z*9CW&*b$g|4-X{1?Qcm_n8ME0+B%?5C9QAcIkLp1n(|NjZ^dGq^wmq4tfhDV0)CTcuL zF!rbv@XX=w6;N)D7gdjuf821>rjDIF9v&0fFUIRTO@DRMab)I3hwOFwgh+o~eO-*W zS+k!*1Vp3S-pxjr^~O|VfX7x0c=ANYeTLUjFrsMS2N+C za4kT7d(PpFJXjSv{^^gx6o~RoHEp4H?os&3f!_&hRokKa%!#l@bh)qz!%#0Ok>XOk zO{*AtQE`0G8`JW1GFbCxX2LMwE-E1QiZyLT!rPo#3N>#KrL8FqPpDJZDE8iK@Ef7B zwp63fxhY^?QtRr!xvwJ0>l9ed!1D$ndAYVSw_+>A2@L0F^tyh9VqcM+AMXC^KM85S zU`_zT=p?DalNNChTsWUuz>wNgOP_Fl*66RSfuPxY(>yhr9a%L9kNTYOYyaw>g}Kbl zXdDzEEOi=G(ppI`nZj#ontE-%qhjc#cdq_zy1ojo1TQ1fcs9kJ|uP|!p|@KJpTLf&f_rq z9kI)Rb6Ce9*YK!^9<6mYx^xi1qmp19`wp0wT?G0D`eStO84OmWeal^XKe`&{ssb$z zgy4yBx!sG_=Xip4}gsq{Wu&1*#K2K!Q zSlWQlG{wudJQ^#LWP}`ea zdWACcg1s~CPr*EhQjyE&MsTRe5a$rU3ePJT>Sqv|wgNJp+mXpyZDHdb9=miY)B_Tv z5oGy>XCW@bFz0;u`0+>sp1o(`T&24Q%wtzcX>@#Sqf9IGT2Uf~Za$2Lk!vW~gX3)u zLmL!Z8M3KWBwdA<7;P`X=5VNxy5{Yt02|%z1?d=Gg7arLr7YwRkrMb4r$>8yr|JD! zS=r&t@iP$&skgT;&N&*%7_Y9Ss)Xzt9BV39Dk@PJ?rDg3@aCPH@ov0#^}R@gw&Bx= z@&3Nva6W7oY{zG`l~R&~gUHs0(yC1U__5>gfu-nF(13N1Ox3O_sfkf_X;6ELRCq;G{gpyP$JOAj*fm52JDD-TLt7KMR$Ob)mYX zI$XYXIV`2YV>lQ0c5ZPtViYKRbjl5lC$l6}EC+BfR4_m1Aa4<;KxIMtkq1d<@*elb zb?CH`&iwqLmP6t3lgBtiOTwkwm!jiB1I2Y%N~5E~^Rl&@H0u7%uA<~azZ#V)q~61| zv?S=BwVqWN_})>Cew8t4P>?8TNhiujzxp^vS^S;#jmz6a1c>OrKxtBFSE0bXoSKhW zIj+5B%ySffi%!(yT)Yq45Risqn*3^<6YEXmcKaXgOvwqyLc@c z5AMHfijhY4>ghsKk$8b3?)kWO_s7p^^yt9RY2upwy?oE#%X_4kXqdCl(uXPTepa4# zxcP9n(0?JcA%iH`34K#wzi@B88=iw%Ny-KdJZagegN_Z?(cL8;MG{od^D@FJUv_Q2 zPkJ{>tnwlbj5IwwGaSngMkhx@0>i*(Ub~S5w)7k|{=L(l&0BSEfySI3Zax6W3mSXO zTIFvVoH{!0(y>EBtU1vV(^U7h>Syp>`YWpkG`F`6El=_P_kYFn_BzJh?Lv>}DhX zGWz-yg;=^w4bMs0n@$$U2HjjjRvNq{8RbdOBQ<-0&t@k<4Rzew^+qJ?1^D)kO!`oN zX~f$NNMKiWoN*NEm@fRK6QOxu3+02TITGXOR}(-3p?;1~wzknfbQ0x5c)USFa@Xf+mc_DGWsKw(oS^?!9-X_GA~R z?wMib^1ZMzLY5syiUz)O_AV>mJj>H(PRBh<$ph&`nW}Tj5)}hjI$jKPscYzr%0$1d z2finuzjHTLp=s8cs!{L@Rl4F2i+ZUV+<>4SQJS*6ay`4sN}VnCh0CPf?L zN=KDvt<3Uo<<_;o{_Btje_rJ567WooB6-F=oY5Mfu6Lg2)v>lafBL6kgS|L<<}4X~ zvr*Q(D$fb+Z=VQ5@Q>oou25F6D@@++4M&cjz**W8bu#&`@A~5XUxrSC4)QgPeVyFW{#{Z$?hr<}%vAk32&+<6;!gpC_nMI~?%OSD`1|Nkt|HjTo5ZP6=0M{83cRk{n8$&sS86_@5l4Zz)4fGn-XU-6WXyc#5yXhA$xUmEmTpC zyNEMv4^ekBla-nBx;WBs?s3;%u_pQ02DSg|7~RKCp2cbPC>sCjY0{B3_t!f&+G$>8!D0LLp zkyV0|C2fP?*0KH3QOCo{EJ>Ey>_+ZdCg-}I&Qsot91^!BjiBq+BAGP2D>bBT<(+a< zKIlG(Pa(Z&KSq6oxjH|CItCirk$rwoUa5m3HB#VzuE+24$cRVbcjQ^#S>?50_CuV# zL!K&M)c$?N=f6n@K(n>f1>ou3LDEuk<6-ORNDUPfH(4*X!xXHc;UO*&fMgtw zLc$b?tnAD%Iye#$^Rw_uDge>uqjz4V-r6{a=}q>cTwLBtu zDs1xs_7K=E3Nr-t&V1_k0Uxu3K%?ytj7}xmVO^L;TGr{NQ1#>2!&E+LxhTxP``UlU zH1JH3g89Yh7tte+iW5$CzZLqkpN6&{ydKI9wZ=50EC?-QJ?Y(c?hXN~9uFj$iT~{d zlkgmcc*;UA)p^PbTEs6PsGiN}be%-8lz{nVSP1Z!+urnXnq zTEV48QNTtXkKom%W()$`hUhQ+Z~u2_AJ3*eOJC^f=#2Y1M+5+(2(_dxjt?el>Fh!L z0s-Q@bvP)%Wt=K-^R$S1k+%~5+jswMNW(dkM>^yxmr~?)jRhI9mqKOzDp7r-!_L`t z+6qjeqJu`GsHutcC>VhTMRf&6%9YEJiJD4py|MMoGAIoNnN~+(J1C{e2&rDvJ3V)! z5VdxQmxh}1nuuVkpjEMz!5k*->Beok3EIx$BE^}wcuO7ALE zDF;(UD*%f`Q_r41j}kr+g|5t{l$75U6bub5l^biK?P0qCLT zqiD_22YnfDx87*?`1^;xANnSGGz!N6!jrb$`<~(Zp{1cUrf&B3^~Mx%TiqxC zEOXHzq2lFU-hObK4k*Xt-g)L4)lCU9VMw<#s-+OJ-b@3oW@k;vL#UdmBG74ch_TPo zdCE9He&~33?}PWE^J0qU>&aKCvz?rRSKgtLqH(AZC+|JfbTFi$EEq+$^rIF9J&{O6 z15ti0P?g`6&OFN#hj4llvE57g%C+m);=7%T>2fPCP_|j;AhqW5{<8-_6;XjQo3#6GXDzBNZ?W z0UcbLMsx-&5ap8}U%GTT&hJ?Jv2dc}1Z7W8 z!kJd;KG&Z{8Pwj=o~)B+zjZ*k{*^2ZmSl#8G%PKs%vslN^y5(HA)@KoVG>1ni{C%O z=&vC1va~`AGR{S3f|)pSP9t#ZAW=8(O#t?}2wu&_P_ex;eDHh!F--pIMp(Z+5;i}& z5k^0{9-dzq3}YBiela@@P&u-JRLYmh&hlQGO;}ut^O|h8Obo3Sz_PsOuU;gT5czY? zZX#HfWpOR0?3Z$0(?rv2$S9hh!U!gF(6YEx7MvN0&li(QU*|sB0unWpM-^65_l|KO z0B~FgJP4Zs#~c|T+jX1mSXasBItI%uw+f_!IHv_=PmO&Jw z?<%lG$YT{&d5J?KSEJXcqzb-r$Edy89{zpq^>dNFfb-1U|Q0I)~c{*O?yJ9=7=8*|YF~sz+nrMw z#`{KM=4#)Ahm93m}%}us`mbxCteDa6Do} z#}N@;Vm^;SoL!Bh8Ut|_`9KXM9S$kv=G{x}6m=+5?_c7idCr=ex;lfwrk4G*vqL9qBC0+*ITq8{SF)4YyUPR?zZ$GP zI_t9N=J1{K=;~y<63CnQ^mhD+Jkk3m-5s`p!FH?7@9nZBwqo zxrWy{|wqlClFAcT@dC*Cu8=fv>=brsi>nsXLYQ@hwo@_=$McXIZ`D_ z@+LC?emGB;(l)b6ESDw?u|)ebW+YK&g>efO3wpYP*e>MD7Ki zD+VmXlsWfnZSlW&TU3&bvgQKFqd>K%s2eVVzutF;#-xI~x;B}Dsqtnjl;(!U=$Y{X zzrgdNk(U}pj=QnNw$C3Yf&7 zQc6|GR3HRln<7n5r;Cbt0S2J+mx1b`^*l7DWbj4~H8vNw7bBz6z)Tb;!swHcSQgP# zLBDqlm@7A~Mggf{)RV8`IWW{8_e+EH;lm`#wvhr2BZn!&D(8Q%?YBeE)1I)mlsZb3 zR4=Xn_5efhcfb9Q!u5gc;X9|k6C<$JQ#X{-;)e2&l|`I5)STv~Cu^9EP#dw-!>+^0 zIx&01n!cB)gK5suqj(lNB{KVx6c6u)3WiMCmLw_=dPTiEBN#KwC^Ibxx|GLO14jYl zUgdJuz1OdYBN%NO0RB#8Un9*w3h_o1BmYh2B!l%FR`^UhikU*(q4BR$sB=MM#Ao=& ztPJPXhu}Z^&O714haZM*o>|5-AAbCCDC1mw=VKV<0%t5k96?!V<=<6u6f%A9zaO$O zyfu&#{NCS5tGk)|M?d{bBKD+D=~3QTskl{9g0V1-mJ=j&w zjnHp?iNI~Wo*s1tnD5V`B;(QL8&O$p#xvYY>&1q0YCSQ0jQ*>*c?L3YBc3{%j&~oA zQFs-b7};#@jOqHO_x26+MMtFyjCa6$Q(8mH8A_LTOD=k6@n@)7cXB7r;eP8XvEU8Lwa1; z0x_9;DlNP38phIsXXRZ{xH#X~eE>sMqq34t0b_txPN0;l2afWcH{W_IcAU^Tr_dRA zJP_%{XPEt>((XB3{Oq%EUMCT>QBNtw4SLHf@Jx@E9#wR8;(C8IjIDPU&90+!HdM-~=KX>z>PY_TV<+dCxh($VS9o{e|Qd*jcZ z$Lpuh5h0)j9L_S&$$ygubR6b+=eSR1syUB$KYcf57HAY$_GI~x!@XB2&;jH=-+7$G zbI311Sw<(5DoTs(o-dPy_*N)?kr8@+ z{z)jCrz61^55xQ~uZFEVBVluBCR9)Yw=$Zn+jq~DiPd|nBcIX1C$DR!b(TQ_TgsUR zEs*G(sjN5)N^!WS6CB8cmMx9YNSPtK;Q7*O?ECFAM=?Si0{$6Ujd}|FNPQyFKt==# zZOllbdys8;H{j!$iL$V576D+dIt=As`PrnBn8j=2Y7YoszNT!#(_hsMA6N5_tidXlKg?f{FSc5lpH*@mat5l3F=GrjjJ_RiNf zwK@eC2$-akJz}=2`=GI+v&H)^{W;vPl!HcItsdiO=%#xL7y>UV!H5zRZUkp7B`#(^ zxVDtjM#J_A_s;#Xgw*G{9{FNwUH)5rBawch#h$0A{nEO+aWgbD#~Mu=w>%{3#YwV= z&vY)C?bTs$9OVB@Qn)$8Wzxz;QkTBuBZBzKhl-K+rr>+eT(9?6eF2fnd=udonSyK3 zoX+<0M12erSUNdDwnsYpo`$wOWQhOHC>lUzxHf&yCHtJ4V}oZ3>4bxFB`e&K5JkN{Nfi7CXyJL z>U{mZb6#Q(xA;?q1Jt(I`PAZE!2pZ`8A(*#j7(X7((B2L+G;>Acw?3q4|qsC+$O(N8H=tm|xx$nWAo z3Hq)4*9mN@xj0fpMA6A972U@8=G?Taw3`}_@1qpu1#MmnLi>>efE?oV60-o_Uk`0% z(N1~j9*$zb40E>VlY(<&6DMfODeN6mRyfpcEH5$@UI(^@x6WIcmnFH%6KPU>hwSVu zK&b`Bs#qpV!#H)xu-jF&H|)wGTF zdcAjCCxgiOcF9nNskb@|c<4}5xAD%%bD~q6IpnbB<~NRoIkF+vxtI0urn?`1657t3 z=JQKo_7WHrIAa%)e-+44v*4uXbV_xe-W!UgS)QMcN%1J;bFNQX&(7k0qsv$}=l(c9 z>B~LxF3ZoAfe!a2W!R^uBTKlG;s>cSxW+WfgEaPio{m$0FK_pGI$Jy|hkVb{FXv>N z@vRDY!Z$Rc17PRqG037%wk}ld% z{B;3Q4>xd=6#a9n=05*3BI)F={m2 zKNOYX$DoYr!Op|`Xx*IX<2i*nVY?(J)cyEe*z==vVMlj$$e@q!I)w3LdJ@1CTIs=n zj&&WSN)dyN{}V{--uS)v_ZGroXKp^}rgfxI)9K)^KMk9-+|VO$>atM>=TcO{yoeH5 z_cuL91P)sA-xSKW_;_AOZRBfR^kc3BKLC#s9`7s&##V8*CsAm6iOcdaFo+_1LBtV= z>3T4t)aAA3eO4O4RAC|HOs#|u|NDO#TGC6y-Rm#~hKwq&kd!p$(P*Um&y!U_!KjD=EeJdJz$8RWhvsmeDSO6sq8KUK)PZi%`UMQ6i8L`T_3Xwg~7uJ$}MFs9N0_^ZMio zLr*?RsP&{O4l=S=t1wOk-Y%R#88B3ZtLL!}Gd+3oWQ+pE6e6xbE;L{iRIs^03=Gd+ zX61d7VK$)PjG(~FaAZ=h#eb9G?BI8LF<-JL3*4a?m1AG(G1_E8zE^s3zXmX53;Div ziz+ZOH}`7z7W4vR%;ht-2ApA@{@r%;XjBNJ0mx?+tTHu~d!OBha27aegE`1VO$$w+ zBwYRDKMu7=4#$+I1PWO#*&wEA_T0NqiXkNxDBBs7=~NU0&WXTNK{NUk+ZOTP3dvWr zsmuUNBStdNv+T!f29cw^tsMX-A{j5BCsMlcONSj5)LyEHAau-%xJ-nz3q#fVO-pT- z)~LBg@Y;sa{olefzx;eTI>=Odr3Z~E=}SZ7<4-=0`&7HLHuQ}rk)Y$mDP`)L``puv2X zh=~U2{=NId$jnImH@1&rQZ=QN9>;lZs z?gBoerJkBw6bZosrHfN2TYBDo&H^cj8l^_5?KmPRoA=2`nRS#pLo^!YRkkL)g;Q-i z<5jqQ*T}=Gu(!O5a-FTPzkWa9g|zriBgPp z@C7E428cpi$C+(g$5tN4`=H`*tM_&^f^Xcq8M>03{FOWAQUO z9R1n5)4UhF0k9c9{?*4A8ttL3qAncYc`VHAn86X*8|mJ&P~qa^(fBv(=1k+6aOv)) zm__4VZ!2#L4~BZ8QrX_x9zOi&!^j&?96J%qJx+F>BtvB;bk&pM|1#M<$L9)WCOF)w z##3R8jw=yE0S8PQwXL@YZ^iX!0IRG^*E)kHShtFwMw{z&udZLc3V-g7a!kIWgUIX| z>*v=tkc1e%@=BG`!?j0fJw=HQS$tw&h_0+5S&~y4G7GZfdn~oMaN#p#M;Sb)H|zr# za*caoM~^%J`uczQIc@pILgi9gxb+8r9(FuNnY`W`=01HG@=?-XERe}VM%*ls(t}6H z+5>E@zPUb(BS*|a)1Ws3Zq(N{ziY@^J8NXa*X_Vlg5j^zW98{e1e5g6dY)6mlcasu zL`UN^on1^jH)Y!Uq%$`oJtGJVX!()o`U|w%%A}?1dKziL(0MLs-&r`lRQ`*Iz^;$8 zCNd0jko_8Fm88)s-;CM|W|kV3N5)IZFLWwu%qc?*Xh_p3gWoyYDo;7DPT_wW)NuXE zIx`215bGq6X1yQ&Z1#`*)j&r*22V<+>m*5~->cAC2c5=qd2pPXb8z@M<)BV-euHU^d$YT_L zb&+T)G$)^OuBqV~bSmgz*8w0Hqi3c8C7s$i$~9=L_%0)ysdekn6`a`sPzhk4P3KRC z-Y+iW5if|{T}F|s^Y?qgneTo#%2nsDd@EvoePHAigCEEqV%J&OGt)oE0P+6>T z;69|B0j^tl>A6mUw~~IUHS8x-?8(QsqLb<>0$rlo3IPXRYC{!@|AsnclTjnS-A( zyGx#BNvTdm&rzqi7*2D~F#chAwPck>`9PWGp_54?*Y7sBQU_l}7A!!3jqnEPe7S!h zG#^Q()pvJwN9T}^CiVC!_`w!y8vV2PLoQ%*-gD3A(a(P#DvYq_fg6LZ;=@bUKHo2{;M3a z9K-B^40vM|I?e))r6S~-*@ zvk$hR>kWc+ZGiY*{XAK=q4Dpqi$_&$RlHMEBa`9qsUu0<4tv9LV(HjBn!Jxm$8?nY z=x7rokHapa&d(>Fg}TEXw03*~y>MsJNux)0y~@IXM8jMLdnVTGZ(!`JXOIrA4j`76 zcVdevH_+D3RKr8V%dQ;`3rNiWVXzQiW5gDJDvvv z1xYxOT#qu<`=MT;9_i4?=O}O-0a~u(4<5G89V;M1$w2-`{d z;6AQBrQI_QoYhCrF80F;or&yraOA-8FnH?$poGtHMrX$FsWaHILz-2OH85Z%q&k|; zWCMW8#W?su9n3S$fTpSmtlh<7l}jMkyH!dyYCSY&xk($*{@pE!SVGWjaI+=E}#(ytcd&b*+f0!V4@{)sFHky(8|00T*$(9P&1Kj1B_3U?kJ~*8o-Qin^7$ zueyub#7^3KqWqOtyPwKbbv?1gJWu&j9A7TbbMU<7hdS?eHdQA7{Tuk-=m01=yYGJ` z6p`}{JU>2C&;1MnIHkb3AsQwcdn$?=-!ijpBA^G49>U`WcmwUbR!MvL+r$2^8mc>} zOO&bAH7CMQ-%w2V@4MGWeK40Y!KvMh6A-OATwFY#(Ntd_>np#wlE)M~4py z@Uq!OO83FNVb41!Ldk(WE$jzTX(4ghN+19YMq(T-B`Om1TUD@U#x%@hhmP|*z;Bjjqes3p15{{m2o^yj z-^fA;kP6xJdw&(4f7Tyn@L0>J9K|>yOxt@#xrD=>=%NuDu{MQKBKPt;WW4+Tmmi0X zb4?+)4eu&KIgR~WLzqu-VfO>t^cY5@a^Uk-Kop)bGnHunc>bH4FGE{HJ5fB0vQ>7P@_6ws()FtR5&<0K12>Ejxq#1##iy(>~(=BQ(Ni(&b zjGlB;PwgzBqGOaq!7JcR0m{VifKld_P>Dfh`tN9eUyP8;gt8Ed_pe=ppOUtX(Pp~5 zhM4ayh37gyqq*=VBVF zXS@hwcRx}Q9+ec&bBViQJ0I7tL9&-U@GMeFjZ9gTWTQA{OnA;yoMr2|bJXYlB4!Kd z05jsGGh!EWQ#o}XoZA^tEoHe-*q62E`yNFUN@IDhvk>a9_^r#L_VP7z&-al8cnfw z6-7jxW^iSN6F+6#kMe~Fh=h^SCzK>UHK7Q)3a2W9~>n` zlXLL78umIJ8d#VA=3IQ1t>oMr*J(C|f=@?)#=lMw6@2IXcK6%i@;%xvz4m&T1ts{- zy*ts^eYyhJD9;jYU4AFZw!BjzT182L8Dbiwex|9sIoy7DJIV%yq%8tja8yWjAY8w3 zJ-%}W{%bVPIcZSq(A_8iO&7;pMkbtdYB5~>{XdKC*HXfJTMUUx((wQ8Tj2#pKy6VK zA_VLVXgeAi?1{>(86MJ=ds#!~!JceNo98 zL?S9L8jOp%$!LcAb*$+aJ(fv_bu_C}v{FQ=dTR zcPV|b_PDWztPuWBkkh8Brs%NRT?p0#&i2tqL$M~cC_OtAZDxk+?|v92F5V8+%K*oX zE`_1Lz7)3lY3X>A5}SefP?}c&-y#ym5MM?*H;YdrT#Omz{;u-fv;gglpod15byDoD zBg#yfirIHYb)HTpYt6-}sU|Wd9*@}pbM(v3LXpoP1$+)8z~`lg&I65eouYQsF(T)C z69-yCMLWQ4SwyC(>pct7_Q1zqgqM@_Gbj6G3>=fx(BRY1^nPnVYy9WtV-$XAENkG& z4^z>9zo#QWKIeUsrZp&ZDtiYEo+#_QlV3Li!-sO9KCs9wv8h1;h*7@l`h{*8FF@BzRnl+-sB~=n&%DX`o6G+B8OPQGy_jIEJL)!7lBJ(dgGvVoz?3d9! zqjwMjPTj50dXzW5H6d<`jSO%P4@*r802Cwqtd+bp4D@4Oync4dTajFsDe z^i$?$2bCnYllqJMXL*Rv)F{#THw{`qy?oZZN(R$TvT*$O!|WD{jb@~-oF{kUTi~IR9YOf ziks2d%qpIp1mzxZ(B)?UNEhV9^RZ0A^IU-+7Sr{_vZnc^1=^L)p{D`Fmr3a@_ucZ? zK%3&lF`P~4D7j=OmsJ3?_Yi%#wj$!xY#|%+sOwMcZwJ(LoV`!ZFK+0UH1uqiaxZv- z9Zclw(Jq44ig1Rm_D+VS$CRKQY7097xZQh*z*$2LcOSjt*5mlSqTKw@kiY>*08X9P z=(>)OT%zf5j`;p|>;a>tyFCJ&KBeYg5L2-=)HgNw6UZ{p^%?h7KCGiheru2*mN!8& zub|gB$XE!^*?s8Htd9DsTDqLjs-1Ju-jZKAo+FE5>rT$obL3z-GeF+4rOddAgWt&q zy}N7Jb$cjRo*w9@+<;Cf>bTtN*a{Lk_=@jocw6GL#(kVak1cIAOOY!An6ysWln#&t zMPk9}=T1zby~muesB?|7cZ9}S0DyvyUi|6WL&1$2hX zY5Ny}6kWfU&o*nB1tKG3G|?L~gZ=Uxyd)}pn^_R{dFrDNl!rI|!H*)K#@jV-g^N8G z04aPGIy-1*wYnIEt>>&^=EcxxR|slI9t6>KW^N`5Djf|*y1XD7n{#9_d_jAe@8V^j zSO)wHCT}!KrQ3h+YVV4@s}&w9Vh$CQxz)Mo8TV%mpw2Spv1uw{66HAMefNTS=0}^3 z(qk123ienJyPiB5sZI#rHNQGfM}XGw=*eL0)2^{&8#8-NtAJ_rxIW)ilwA}`^YO?M z72Tv@Ym?7RenDSQqCNt!crJQLPn=E&4A1Eo|UXzduOL z`mr#-^*mf2y9KW}904&$_}`oN|hDZ@dxj zi-v*cr_v{Xa8DHe3WMWa$3o8lsOA{L8hSeC6huB_aCk5pXr9Nno4*}Cy75u`j)s`& zZXIMd_^h-0&f)~3%z-ToZ52Ofq~hX9Bq-B`iy zzN}+!9MTwACo*&xja4}1?v78$9B7n>uB7?Gs_N=Tf;q<-} z_BXYLTfe#-PSUb*^YPPAFiX;P&qR3ehkqGX-@6eWe|97E{rrotZj^?WHP4?cL{Q78 z6G_9}JFOAvdcPVdt!DQ{I)gqnUOhY4{$vzTOdN^wGVhQ9fYh*6XXpOTSQe072(AN4 z`U{M}$^?M7MA%H1Hma&|uF>vYvaVXbmAR)dtioERaRPR~b`13Pw9x;-r&{e1U3wmR zbl+66m3{8DM!P__Mz1uabgXa{;^^q?h;yriUNkT@ObkvKQP%j@nDt)jSd-^VBi8Oq z|0x4n#Z~_9NEzJLjvJtG2r#8QbSRU>^3gcfIpH%jh&AH<*}e0wxn>Pod3K^c5%Oc7#=7M1aD5UFkC^t3!U02FT^7o#F zspj5IX~xVCGbiudN!E57ovo|qoG?6BrD1#(I`eF6Z5EyDRQK}l4N5{S5io+ikwyJH z&dQhhl&O%JRKi`+8KHi7o7(;r_Nf!+!v&rCI9UziCHVUx5&r~w+B#<_@0ah|Lb#pJ z4qmzxGB}I5>({BD$qOe521MPK;KnR6Y7^)0BKK+;ho<%VmUIo=5F;fKhVMNHi#KnD z4EUfxqSk#|HYGUm8obH0?j5Yld%cQGT!fC*FS_7YJy*U6%iOIA_S&+d-8@6%)mF*U zg}6R~(8+_bt(yO}4P)^40 z45a}@4S?^yS_|c1A=sg8lR$4U63*aa0LV8fX)yq}j^W*P z0Ns1Qu54iTkfN{5we-Xi=GMjlyDkH$ws8Ua}|FU&mcf6xnl z$m`)II*vS6`6mC6CN<2}U(}bRdGE3r7}A8y#ZFdE?Ef>l&@s?$d#> ziDS$)ERq$vI|HWxSqM5U#A0&DSCtv+KMx-OK+QgD7f3JOch{;s^?8=03g(v@-f#EQ zxjUS*hP}fK3Ndz`fw86&Q@*3V?LOIg#qXx}QNHV*DBB8m(e|;vJU-)__#f;ex&WN{ zW+64G#dW}v@BZ#%{YS9@$V9*5f+(4Q8@-oC(P+5=R@tAM^J)FLw7+(_)nkz zN21jzdU$$E_+4dQB~dU^X}DA}*&-NKBg%!~Mnpg;@ zApA#D#sam0wh1@7@WAh)#G$ zx36CV^*PylSfy?Msn=qfuL{BjOlphgn8s{og%LZ`dOeSMm=ISaf=jtiufOwM=CLEp zfBH!{^;^Fg1&mC*sktfK{(t{H-sD3#E#|_Zqeq~>WJeFdcc$5suD9Qc&K&oA;L$*I z+zdW=Kn*-jHVmFRqQ^rIdZ>Y$44p?n&E+#H6Dm70Rh3zPe#(B=Vnkar<+BvbIVeFH zC?yT;w1fNjMx=4n#;+8|49b10XKmfN6*uM7ri7IHAtBC2a)Oc4I=)_b&G(+3> zAK#BO{iEOf5yfKZq|nUz^)DoM3r}cZ?E-hx33|Px!atZDYa+LoPm~U&4{sS zhJ`?FW*4cfzap(zA*o_-TD*}X&r^fl`*QlgnFy}uoLGHS+;u{>H?@c7C@X$XV=x-y z81eUe?nj=b(R^p@cDzq2`Qo7n#501@Bp>;>=i^BGM!ZyZQ%2|cBj>}N-aDbRsx(aF zj8rgN3UL0+`RFi}7mY8EM{r92O{bn|px&h!_;q^?kp;RG$fI1B_en*}^g;!v2B${y z#;zCa>j3-FAMdX85tR+jKsuL?=!lUYsG#dKhzbR3u*_tf`_ebqhvNq2i2K=4mxzwT zZ9MK1-JNJkC;LhlHkbaH2sn>WP8>cRkkKzqm8R}}PhN4DelQ3ILrM6HfA#-_lWb6-XR|mp4_56eX`6GI= zJqP0hEP_Q8ZDhSNe~mqKm^IgZ02~XHBna#19t@RHquDBZ$_~@-z1u3u?&tX9F@9GP zqhMmm$P1(ojcAR3hpEZ#yLVW_GF6)||J9&zzr7Qln>v*dV@J#=REcJ!0P_4fW&HcI z!|ytLcPgT9Hi0}@TKoF*ysHuXm$|4|t2anT>Q)X7CXIRb%VGO86?X4Y>OC3?&dqm8 zU)~QDZ->uz9qJrD(>7?9bEzY0@b5o-5LrXLHHMgI;HKMa*lPS2(mlqE2lvV688LLe z>I{RAz@lkw{R+%bz8w{L^fvjj`>mtp-1&2%fCxNg(qW~Hj3@#DIyYWBaWaAsA31b{ zIhDk@it8bdeTb~wO@^Z76uT(2a?0HakwVWHOe>csyr%6HaT$lDC~W_>3PMtEgw zhk-WBN(UqFRbN*Y&v6&UKQePo!))xrMGRH;Wi;u4ajy(82>6$lnNC(#Wds0>z|NQ> z;zgut|0B=gyrrWQfM&-jN+ahcLB^-1dzBV^lWjIu@<8&k#{q~vi4bS)(XKvR9Bi@_HWbq7iVwJW|K- zZ-?im(_Xzsy)_Q*i9`KE9%`FYoqftr>2ihA*_!>dZ06q}$k;VWzPY!a>>%`8K@}%% z-lXLsI5FsH+6iW(=e_{PVr1g0t7iJYJjdXX7JPku0_W&-ytndPZ3_d(DL(6Z#1@eU zDKDg@=*)!oxerlx!}n8HSzH5Uv+`btf*A#V&%IKY)OPS^F?ysU<-8*Y8vZ6707(o0 z+5qBK%ZYFN2L9*SUBKx`Q}W_^@jP@r#WF=b#2O<;Lap7^xX;ST1{m$XTtHK4nlT=p z(6gC&#*6@4{jDyo#tUehIs2=tZ0jA2f(FJ`2N4U%V#>F@szvjUP6XCiTu$2wB0_tQ zcZRJN-g&Yq9RJ6^8SPCv5ucCbiAJCkIEzCV&{#jWyATpP&8Gi^$#Ef#X17qhatY zYc;g|vmb|jKYlwbQ(L3~`H~1vo*SM3R_JB0x2!{>DBX8dA4@jXvu4JC&SeG;mPlpH;NEdKj60?v*W zQGsDi0~j8D_c=mYfj|82yP+IU>BINm57iiwMkh02QVNJk=<^lK@dalyi_sve?=hl& zW#X94Z(ZeHz(yD7CIjVKO#IMgziPg}rmW zqm+xh%I0#l6U%_Rv$mYX)`&0Qe_Wes>Z_#gq1gpM9GDA{ zrUnFBZU9yHVK`lVI?TQ#J&#TG^E!-l+GxZos8rl7_wi?)d3bZ2KWSZ>REXSv*b~#kzjyX~7=4zrpajf}#k-;tL8qODzvrgm zdhrtI$I!zW914x4qz^AlgkyC_L;pm7RQC6inr^y&HZ|P7$23rdmhVa=5~SG8#d*1R zu1!H#U0w}xIvqKfue?$^Njfue{6JIEsE!Et%scB|NKf*O0iv5``dClr{`z~3Wbdu~ zL7rpDfamHuoRfRw??u=@aNuAxHax$B)rZ6M>P)zcLZb4p^aVHy@GF6c(ztwrcvcXt z5t+HV8bti@k#MHt432^6=%A68I6v>}7=PY6_7?m#GtNUp%yV#FuEYJ8z7HJ&>!KnN zdLQ*-3?z+r=O^vRQ#|Kkl)L1ap@gzO)?E4y&%-Fsz5A4jK|d9F72*EC{YaN8QQlLt zE;PdA{eJiOzT?qZsbxU+5HE=}+B)UE>z44{ymB?v zmR5urB5Ab+WXO#_3zz==Ps7N6dOr-meori^OmV#Lb36X}xwmQVR^$DzZAqM;}) zT63DpkaXRCCY2#z281*xf6|!sUCwoH4ecx0fA>;l_UkqIQRYFzeomvv%mRCrt7!Wy z_a#*>;9OL;HT+Wslxy2Z-)`6GFtz$Q^wG8-P%r`}MbPsK_sU`Bf_vgzG?q>Mb;v(_ zhvg5c;oeK{5u1nai!tC?%gepLD?}+9UOyZfY29Y|V9(uqVH+c=;pnj_`$lledsfQ) zP3Am5C>nic=dO~lPFc$uIwT6Fd>Z}q-duD}`n?crL@Ad_#1R&ONQVF`?-o&wpugpNsei^DW`%UddH z$q=Hidm;D-xqwvb_!u1>i8|DCc!aHo*JkI!3A**@>@}iWkIa_uF0lS;Wc*%eFq?ZQ zPcgV5uX9948oXhi`8FXRl|4Eqc0fbkwoLY^si`?SieI9a?FOt+oThJm@13YO%v||G zMKTO?pDkTnf+x7QD?Fncy>Ac)Ko0vO4^;k+Fu!f)XPd#t*Xa%t(qabG*w8Rwnr(4S zt}g@mXZDnIYiYyW*f?O<=RlC}Wq*?U=Dx_2EYB72FWL~{Ga z0fD~z58|CxFVz;yFWD8EPaGgPa|>rC^u+xuC?YEsr_gg+uh)=az0Mkzp`Y9`oD^hU zuYg-Hjl(?Af=@u<4xYPvV8B4TEQRhbO{n8Iyz36pF zma@(B@$Yy+`Cs{u^yS!DNo_rW(N`#JI>61&@f-oB82E}xoBIwe9a6@ z`LcBS6kg=_QfqMU)qPyMywD)0JX-$adR<@4OoCVBG*`vhK#P-u)VK3Y<5(HlfU)7@Eic2 zCqx!Bru7nS;ql)MLpR08b`TzH7g1^f2PN!8A`x2X0Py5#(r7x0qP#$jrI`uY7-@SD z2m)3Yy>c|YUmx&6EP@{%GRN%zALimiO1r@b>!Xyfc7se3<0d?au7$#}d zWnCV*6^`sX8c~S#rfJN2(KR%z+Y?D&B`A&GnU3C%AsM~J8(=Pc`XKcD^FIo?J88$r zI!f>~3X0?~`bCOB5>VyAqxd_Ky)C`)vboQzv_5S8pMMgwB#LN}WOl{m<8i>dTEYlS zRfS&xl>!j!C}|I$-~BvZECrq@xjH(WuT1*i{Q19$kxt7cym0;*nI4UoUSXlK=J!-6 zjl@{{zL_O}WKv0fe_=||(qb9C=DmR@ikS$tpPS4GgdsMt!& zDhJkl+Bw7m%?fcf7VR{{W0a7g20q@ddJTx#A=~iW5g-P(EU1chV z0KBv}L~tk5P(}2W7Mw>WtYYioS%sko0lF&7*i3`7dk|7ZMu9n4}t6aeZJ?=QriN~$m8&O*X!{e?w?L1)9a5PIT7A{ z|K0H0-~DYO&xPT`iywyHI`Es}`teQ*I3>+*u7_QN-)OBa!bdkTikM5bzG+j};(7ERN-5blR zq(jgC#?2e?bC>%*haM>bMNuwpOs4(okTCje+fh}A>D`efB|NLIK@q2$x z=GlXgvp`1F%xY*T1~BqkU&u};GK{>hLfI2UPz6z=%n1CR8p>vnQ`YUT5ykRv(??AS z7qHOJIMTTDcFvJ*m7SX)vHRIUqL?{_IJZ|w$0e=T7Qit(2t}3v7GGpNtV^ZuB@tVB zMJk#XAN=M2)S=`SS5bCDmRBgw46nGiD|uPGvoj2Sb|sA4`gM9KeEW^JVhb4{O^0P+kjeh$+b&^uPV>-0*B&CP=9+gpP(C^FF zG**;d4i#5r!!p0qX(7m{!-%bX)3wW!EqhSOH!DD(G zC|cJ|PduDk%uB|MstkH61Ze7Q)jWy0%qo~8 z@;)|-qi71FBkH8kQ_8#(G=DNY`nRil84ji9NE7EIYhEss6DzL+`S@ zNB+Nvar&~1_Lj^iGL=O#$N*D+J^+t-M%12lY~c)OP0)^*cTdhulPSDAY{E~|x#KI) ze>trXGvISII5}r<0H<^xc}UCxf@Z|Skk|5BbiqB5p49(KxEp@Xvyj)=@k-;_dn{kH zg`Qxw%kYs%=L#}LW3f6j~^EwS$nIB{H!W1Q$2+@>MCeBInV4kPNZ+ zei^C`cgNO>YjkkX39lT}Vc^_iS1I1J8wcu6c!4E=W?-3BAYXNT@;<+p8YxGGYgUhN zE~)+1u(uOOXD6WQ@F(v^0vT;-vosll-<*X*nz1ayawK_xe9@otT5D3T`mg`@_V)UY z;#1#j3BapyqOdS(H(DjmI*-}eWX-nTj|jj6n9g&0u$lp2wm<<4QibEtk%M@~lW4>m z^b)^J+YL$$kxB)`c!^-Bs|VJ;sJTK=!=<_aqx|mWC`>C0E5oyG zQ^O~sms>`D9nYhrYP2Wp0s$O_qwn|rIAm*yb~g})WLD~jk95(mxy3Qib&aXHZ&m|1Wx><=+A-y}V1S5@Fq{8a3gd*Es z)D~X!4ToR-uLdX%Wc(5TzGOLBj&$T=Z~hgsEscy8ii3Lc#g& z&~fqz>A@qh^@~cI>4*yUb0_HU{irW`QjKnm&W=Q8=FdmE0j3#d4>^Aoea}wjqa(*l zkQxe&%H1e}C}^(7dUw-RMP`>IkJ6&&`uxI9@` zt5G~ghKMO|FLB;IkSlItxzoI z&Wzu_9S&lIxPRV(Xi(zGRDg>@{2a%fZDMq!v=OORfzl9>j#fCkm@b=72}?;S?Tlb} z?7fPRO2i0`fhtn}$Ell4V_q_P=V-)OhOe{D`{VtX`tYOB@Pi*jhhJk$Q$+Tig9o%7 zK1lBkB64<8pu{Hw1;UhIz4ZA77}F?8Mgl8q$P8ld{j)*zP=2G+O*$|_w)&J3qEGLI zC!bym9Y?|H01PslwBm-nL}zGKW@d`OkKTD5mSuRxO{sSuTyNFxs&J^}P?%hwj7spS z&Qsw^-<4Q1u5s-5Zr;2}uirf=ggA!~p7O7e3GNX0OU30x{Rz50jRLwi7@ajeLp||s z^pD_V;Ta#Cmmx(j#5U5@9|utv**=%#98qUdQZ$+ zGF9I7)Kt_&o~t89#io_F{B% z-!z8AE$Oc53O~E>Gx%O*bP%T^qXQVE-+J?{@bTv#hwP#x{k|%q|1kVpP$m_yTpTLJ z+c{y!B+>7*tY~yE0Dzi~LY_+-tWoOZ?aO?Ui1@-P9cGAJ$`?eCc4)*a_>%@qLCgwi zZD|dy$A5*CkK1%)sZ3piG(3(18;u zmq_!)dl#dF;{4e+V$}8nGG|<;%0xYp=j%7F$IKa(YxiXYrP-1QjZkSkl_AyK+!Xir z?PG6aV4u`=DH^QU$KM%Km|EFQ+@O-%czyG`Na$%5c8x-6{jPnH| zjTjSscY5PKy5>btuf6O3EwHcm!v1jX1;jug3vs>45y)ECowhbnR7%w&9KO?tcrtS& z+3L^VDoaDNsOVv30V((|7nj_bySNtmSvEeqSelKYT%@N2ASm8s*b5D*C>| zsH>O-UmxCw|G$wk{{4*lPzivrM&@3qu)`}fP~6LieemTTsZ6_%o`Vh}_bCMm=)c90 zRCS``BM+Hjdc3ry6QT>fbD-x&s6KHxEU@3-`|dkYS1{%O)albvU+~Tj!w+_{Cjx?* zv1f+L>|?NRXalS)l24|F=O&-d$9S60*a#2rUL*68-tEh;Lf(#KMwL8OyaLzkyL8H^ zyO%CmY3hC6ku^%-1jFp; z?ugOb9OT~9!I4mM5GM{%X;Iimkq>1!U`$(9j>y}0;`Gab$Fv^+zz-wbOayf&8g)cH zVjbsnEAqfOj+16ygp6=rrf)yG2N*U^1S6wa=m*bPlXd&**QRXi^wN>1T(QPmW}uF! zqfQ-7XOr?k=hlIPhoWv`r-xXl&EI>WZ@Ua+Y0Q%?SC>fA=o*HUnX*|JbMiKI8ugLf zd@^!}!E0%4K~I5x!94(x8=ZRtd>{Za2?VB5nu+Hr@};aCfc9`MN?XlcZDf?GGjE2y zWa%!B&4dP`{Ms)Xwgx=p2lDt;9GB_XDH+Uvi!+owH4r^A3V;IoUWa zatK6VbGYv480X%t6X49=N)HqF252`)_NXR98V%vhI?=U<-y)0mZ6cBuDqwB>K_$;0KkA>NXl(JO< z2FX6^4A_1Kb_Cg6bpRG>cMMRjwW~b=e#DE=^%i!^2$_0kj)l9lB{!Iuh7;EA8193a z!VpfRQ)y5JVU(X=#o-*pn@KseqBER-bnVJX@6{Z87E8MMhI*8I1*mrJ9WAa2_H4py z#wo#>ymLG3e+}pPh0D+*HS{-IR=*RMO5@)lUsPw+ zsia+@vtI|U^OHWj&z`3lA4}Xlooy+{u6IM3uF;+vKHnja-vKX|Kbt*hS)Z6f-V6Dk zGFy6ynLXSupP}t)X2Xu!($wSrtN)!W0r-Y70OsknxW$G_&@!u(KvU?;yd8THy@=#yT24HOSesL0AJ zw#srt{g2Ow>h6;vQ3iv+0kE>Q7V7{HwH=D!U(fk&tRE=@IUXa!x)bNRgH zu|43(_y|NvWReT!`(@f2uU^Eu*~9w|hd=-6pMMqI>F(+d%~h>{tw{tkWH?X@cmvNG z!-LoOZ|!W0JJB%GE1T z7@BHp-*}B@iG37fcmpQiR8$}S>i_(|Li%02uB2-Y!R%7$ZVG`H7*BeJ1-GM}Kxk=K z(ajEp`2{HSC^*!_hO;Q%hwDNXDM*vVXBnghf{KOvasBr7aJKVoxYK_ZFLFNp*dKls^+Hs{G#^0$We)NW z&v^iy4+Oi8^CL+m3GIa(x7X`xzO0bvN z`Af40iw=fMk1oLwt5K1+!wnRJXiT9fxQ1%Z$Mxy8cFubID!I(-FqOXRcZf1Si3*uu zJrlG-5%GTplvY8e<^Z)a?NuxYhv&YA_jx*R3&piL6i~-L{PamUa{46cf{$WkpcCPG z?aCLFk7!h;(>f5v52ac#9GRmGSDF#Ss~8C# z^^^_J)7L#vIGi|sGW7QKhO-st0IUH^fc^M>)Azz(eD)V{&GRp)S!EAZqI|}=1Lpvt znu&Z(1;#T{nRb76?JN#Yp3Ou)DxLa{GK7)JqIW?cmCc_=b!>>rjc0-?xzUL3P_E@#)_s;j$&S$ zQ%hM#65Y3QPi3gtRl_^sInai4^PCm%n>k5-EqJ4j3h$jMpS8@#`TAaYaa7=Wr!;5l~jp zPSLU?_Jx}Rx8wOoAhc{8Xmr)_{7vU>;91XbAT^U^(Kpu1pNHX%?(;-`#=Y(g z&N|x|P4jwUVA}^+bt+_OG8;Oq1le%op|0^7P zb^+32TbfBZ7^;&6CLnH%;*jG9h>Fs|ZP42re}ulu7iC;wQ(@v}un-WIjlt#6-* zSt0g-pMp*rDidLTlt>xIoiv-2KT}`HYS-nOqziejGH-Zj*k8w?Z17ytF)B3LRSX@T zsnL36gx_~Q-WU0$cR{_$;o0g`FhgS)`K;mX^P~lNg#6e)-bw#Wmb%G_$Zw&Qg{Tu%f8rV5_o>f;Hk&svBumiyp#^9aj0RL za%T80<+Dy$`J{I=<<#(*siE`IQYKU3rA@!Hh%VLf{Wl>N!256}4?Y?Uk3ao1iJ_T1DVeZPT*X(H=wr)jbIs3)|)ex6?Q zBhjGqtfO%cFGx9MEPZi*S1|rGMtq-69q+9BB>j07cEK^bFlIk+K4KJ@jp1I{-c&yG z5}J;s0Ngc$MjC0-*-o5X^R$MOCbr3bdQp*&PP9yVdwtBDXhzp^KA!0`2K5YlZ3}+n zUdq>&xYJpjomedLc;!Y8{7}8mi0wA}V|%pzzy9m6b8i(G8apFjeDu?wlV1Kflpfq4 z_hk(ItQJ~xpCYaEES=I~k62>nyQF>BGL8{8)z=%=S-+|O*?evdewB|LnSR|40$rAR@np3)?nWH5^Gz);C^mv z&sF4BUCh3k?ISY)*_lsgfqh2~lim-YvUJGV8;JD#@)FA;Q)34iNam;e&C@%in3F`26h)C@5GiIV=U6#(byaWA zOwVH4GZ?Rd9jsyd&KG-Oz&E}zV8DO_Y`|ELcd)yYdU~p>(^Rffl~l@Eq9`%voJldu z&vU-|ddhuYKHXJPk>B?Z=e+UvrqxVJcyowE_mCwvk?66LloQgNdlR;2k-f~APUOO~ zFRoBhg&Y`Td?4rHGJ|6pc`FDo@vJwrTsRqe$bPCur#_}MW*dM*8s&&{j1Uf#du26O z#xdz;KsfFjQj9e0_)P%-mrk^PfHFpzBmXAv2QkIZ7}PYY#)$dBgNafg>Ds;9vdKFb zN?A>Hq`l`4Iz#2D9H8T?W^9R^{1mFPslg_!1lZ!2A z=7sO6|D*jZ80d3*Kc_#Kl^_o)w`}0)(nm~YqsMbbzD7`m-&I#90x^D0JH&v1`bt^n zp91a5d9P^zPT4B$%k%!DEp2wn_n83@0f6s217PtR|-!E**HAl;q$H-JF`;W;9BH9+d=3m8A-Ui zp1Rz{p-_`s9{%+2U^XJ-0DG@x|o zRVpsgUzLl|FW=Mi&JCE)V6@C#FxJHr;=<|C0D_5>WW=|_2Etq$_%uL`{4!shdrzAR-`xy7s#f9IX>gg>V+?46k^a&E_5Yf>Zq1DG@eju@RkOs0T8 z(-_HMuND9XDtYF~4?hiij$tTpjv6_WWET`uYM|k@o4u^5sfjcpdg^(*3Nc_z$E!I` zlbl;OnTo*Z7@m9b+BIqr$(%q)dc8%W8hN0jLqw1Y`S}q_Df-|~&+6@>0}=6c3a=vmRRS4g|E3vh~&F&XTI(=$x-bs5dnh%z12>;>;v!W`!pfUJo#`ta6=aUY?MxKBE+(xJROJT)BaPE{!KlXao;lSaxk(??qBS^$k4 zCsiDcIMZ(JQ=lwz&)shoyYD33>OiD3KD2XylxTi0jcYtgyDD6t`{u1%@p*J6JYPQ} zO6~Q0CVyT5O{l2l+lXXyW@qT=zk@MJJwv?!i!`^(pbrR9l}(!SIH|-&fhtacS@-5p z*&*sc6A?)HM;#!t-vKS0Ao6hi_Vv&Uu<_G#KMno!1M&T1e+^`*GQel`S$r-5h@;g< zY3BKu5*bFj0xW2ZSLRhxPShKIaQ+98*Nqw6#dTS z2wqLm+r@pgoXE(Q{H8MZOgzVP6=l{- zr(X`;lym*?%nxJp!RpHDSeI|@s78fRs}yY;|NV;>;Am@aO>Hv==AK$C<$3K!|Z#~6|ysk{H<<9H^KVmB`AT`_nMUUmIpZ?Y?0>71JO|Ifj2xr+I;T3JI{)(3nX_ji zZRq^#*ctiNxr&A%4!sdb-^X?E5aUCUL!PTYPcE-3UwBRBqVmjVayfm%h`(pAL8}9) z%=0=LyV0qKKH3hnMcMwl>p~Mgs|NeMyZ0hEqJf&vm@uDT8(~ic=RsCxG76?4D}dq| zOYinCFi4=zQ3hKEpltCy%?MCF`EEY1I!nDP54vaH1x*B}loirYeN$t!_m)WCO(%jn zgHs}y5_=2u4MZo=Ooa#_DEquW_N4N{_t93 z&e3#&S9_XUqHR`#tk-x~7MjlP?-p=GYXw1m^~+F3M#%DG>@A}0F89Ur%qqwWJLxym z{^_+)`s#_00?(9eqm~%j^}O5*X+oRKG=IT6pGAJrrg9H_ZtWh=&F`r11Y-P*rL+;i zVlU%@9LqSP5i$}m^g~Gn*|l@h`#b(ANbXCD2i%1^Y>IIk(Dk@vHomKO@% zDa)i6%M!Jp#%VxYi@mTLev-C)?iFO7(RJn7`EzuVhd-2qgM60*pbnl4BA#^-oA(8} zE1hRkmix~rx(H? zKw%bkg8>8OOAd|j<|b);N_Tw$g%|M01~k1uB>dbPuZAwleOumsDU74@m--Ump68ks z=_)}FiL)WHOB6aCHk}m^g{MpQmNBY2KXhNe6>{qU6v!s=tR1gCIX)38;XA=I<(=b8 zcj5R?68NzHh%}Q?LP;<@QAi0#5!ua;x;w%u@3*IzI(U4rb`prBq3k60~Y20kjX>p*s=a0Xrwhf`0Sgo#aP{~rFk;>mKim< zpSkt$DmK9yV64sW1PuhUv~RU#O_)JMzs?DRWj|*CM`8{=ODKd2t8ul9UfIeHoc1rYT@tUqY zWKR<0&}Q^~)g#iVfQ0*?AL+BXcEj_bqA>pb`}kJ`0E#ZOey>dcmpUK-Hd4VX!D(1J zJJMz|Hor41S9DS)QxS{)=aXi$fRH!cW(Fl=io^oxxdn%7!~Q@2QJBpENW(Z-&jv}y z$;~{%sJsR`S+c=&-3X~TUPh-xXmzgbpqb8`<=I^7`pb5P${l;cBhpoRpLUU2YAPYyoP+#4Gd8TnF3+YnHN9qUL)3qSB@?}X>s>D+%B zr;tc8(ISGz427%C)+(meio@uQv$P_zYMRlkzY@iLxCeOQb@y*UwrV3DA+V)jvhK19@3=BadUpR{b@Un-)J~N_gmrW^{c*0kioofVKH68Gj|3j4#-?G zy^8PQ(}z)cT3gnDvErH9CqU-Y`F!J*HyD*h`aRCFMzzbi?J{XwTU-2$&tvy?BM9!V zV&Q4$({Q`vPADKHD-A>N>F3vI;zHE1Za?E`TEo~BX{_7Q;&);iE9DFea|`iVHLm(G z$~Qq{*9u7g#MxZpxlXPwuNSwr2(fFU@d{sK#DC<;=inFi068G~lAWRnf=~+m_FHn@-06RbW!#@n4 zle)i(59=#UL4X%?y~?NYUC;W2T}6oZfGE{ z@I2N)nW3)W^~BoKA-Z%6k4-nRHD+UwEq-` z(d&9mJK=lgf&nL*PlQ_!Zp9RFdFkD@cf-UQ&&Ru;sX7zxb>EA$EX|ur>z)gg`2C~| z^L)(;@cv2T)99YGB)>d(@-Xt0{aK=+wQVi5cejVOQo3SK^@n4v06fEeOp#!`YIR*` zA8e0uLW5Gi(q;0!-Jb*1j15dlj3c}Jkc^uOGHdwx%gshIm;%GI2tGulo#%9~^NQK) zk>PN-?r`jFpsfDj;}2rbjoXiIhyA7d!^dBL3?NFs2Cj7+kf8usz5}CvmeHH^uMgcf zA7LNl#6BWVpI|iQri6`(9pT)C*U?Xz(DqZrD^H3{Gn%2iau3}DferU>Vre2qX_N=* z59{kSnB{*JzI3R}5lEU(P4p$%O_Mxz$nJV%C%of#eK(t7?u5oPE}}z(W9;ubhdQGX zWoqrdJv9+{F|F1!)94m7I8k~cbc}Vxvy`6>lphR_dLG4wrGtDXroXeV^#FwK!|{p} zj9VR!j!ea_^6<&kPr~U#C&KjbSoryW_^VKsUJ&{iZMI31vYrpGhOLJqVf8K}cPX2B zF+we5uZ}kn!Ed{sn~IqVqTuXy9k0Pr99lB@jF{QvS72W!-j#I3b^dMKY1C?dnQ@-T zwne~y8}sQfN_&pm@_YNKH8p?`onCa|1mhf|^G~3EI}UtxRdpEd8A{Zh(iF5}&p$Wf z(}C5|aipW&_-#hFgT{}GTdRPahbfPg2E3IPiSIEN!{uY!36pk=>Q~G zQXlwiF7>KTsMpsamY;RXq-+1KbFLHYl5Y)$NUPsulhS3ey=0&?6qCrjglvyDS2JN z4X+zVAOa`|T=?J0YW2SWi+pOPi&1k^(3OkY90C!JvUHCGBm9})mCwzL@aNu7d$6Xa zCVpNpQ9xjbi2)I8z}9in2k9yt2fzsbcfWM>UD}wwyS)m=AATT1WYU1Vn#VS$bE1rKLu=jR?pQxy{GSE zU_s|YXWPH~J3nhGy7Z*nFj^{ayf9t;+hug$RZnXAKqvc#zmrb%Sexki96>c~-m#Gc zof*k4XxT?!fWf$bj#IVlteqf0I(o+C-l^+0*(ddZvhMK%8YFUmOAiHWCwGM*vABEMgd1CkFckZv>bad%>W)jdj@eFB|A=|xxR56aRN&V zf&!$O?>N~IS}B=*fuCY3_r+IUqC}x0zSqnspw~QSMP|Y3>{86CwBK0!Z@vzxr1Y{cqiIB>&h2M!!r|j764V3D5Iz*APoxu1v_f_aZku111<+A-cf|h_+@LnuUXa{ zeau#L805(z002M$NklQ-%FDjqgJy2J$iu z8+;3Tn?^71g!c^+tRS;8kbl{XW?doBJk@JZWHRAQs88r4XFzZ1dQcy!3Vy1zgRTjIs zmOnau$V@C{;WF6^xeXQZy5GmYepdp(8)SbUH}IMQ01}HSJjF%D@Eyd>5*6FnNX+Fm zU01|32PfGm>HJIrC2|uKasmT7RNMB0UX#9m_N{lr7Ipn;RVCs0fB7eoV7J#&C!JS7 zqlZgj+h(%nBqa(C3U`T)?xXgWCSR@f2pQ^li5&0ZK$ajD4LXH`Q7%y@6}n1D=SiaW zuoQ-Si2&}T>#+@})|r_q+EbKP6dO^Qd0+~&1R_YFfm@HlwO&&tmjV+!?J752EGo89@-XpKc1p&HF>;c4~79GQ!8d{io2- z)EEia2z)9EM>Ceu{^!x60Z2EikixV=nfv1pe;eNV!4G0OwMK%<-)rjV`m87FY49`L1C1n_8wDn289oARll zpmCxwly`Lg6=*i2)BrHsq6LFiUY|j6$YbucQEzMDr5PRAxyS9H65~N5!?Fq^8#AEt z2VQ$Ef-Ltx|2&jXhxG)sx4N2iK@6w%t5-uADV)U5DYMxMjbss}bLgYJL%%b=j2t3pXC!2p1b( z3e#&-ymJB-*5EmD_(ZsR<7#;C+`Dw~tq9leUk`tF?$5&L>e%m$5D{;U68Cm~l}@kl zLPjcvBheup+C5~#%u)}iF>dOcKU0ahKT%Pq0BUd^@`Q3m0L*$x5q3Z0UV7dFmiDaB zAeV3a&hXMuRHo9xm$$!+j;3{R}iKs-c z-D9c*a#EQhf2f!>QkI!XoQcvrwC5m=hv@OZ?{vO>79A3S-p#blu&c*D#i;HyT7GbRYP=;I{K2#e9B?yx$@T^Fba$@ zj{p6?3$-Pc;lcm)v#?{DOsP-rhIN~Wt-c_gbtU2=o`nvm`{S7ziJTyP)MbyG4Gdxd z?iKhcjnQY0n@!0RxRefdZF+ejM=@|0~2=?C+-QYY%uWK~+HqK_bsq`K=Du5j{?3m8rQ& z2iwd7`Bd6{>#euqpMKA4`JCRJl~3>e=)DN!xi9JlOBDQ_`yhY#8NmX7Ef9bzs~s-Wl)~K*<5=o=uFR_UR#}F-Mr7}*+mCi9mjskr@dW0UJ|g124l7G z&muNKJst7+y_rhZn;X26j-;taM8XA64f0F?M4ECx4egKIx<{GZVtg;NCT7v=x%+m9 zR3GUb-72rS1j=W)JQJrOh6^s8P3cM081GJ=_;Y+T;9ovNbAVQhWe(^`^zh_$zQZ(;ZZY^EN^u*w!xKE zMg*oIm&|&T=B1Y+dZ3h7R}ygRM+Y+&xC-!U8zo_YNW=IE4aW|L?#nmAD)s)uWW^0p za!KVNASr$Vdc;+_vp5VgBDJb%f5<^MEs()ndZrm$mfkq@^r|7Nw|{6L%meuPT}%A- zvM=`Yaz#g!{ZUp8cRvez&XS@}0O)XIOVp=xy^J}n$L~SL$am75C9CqR|6R>_ZsXaf zkSX=ApJR`P@d4=T063ak%Jhd929ao7*gZ_p0-26|nhqTZe!I#5W;~-ZvJz$id;12_ zcgXr~?34|ry*Ty4Ah0E_0#-)!O{3R7lqX%r}RVF;CToGuB&OYy>Z?>00xM>7}?UPT9_RUNB)bSpd3iw-Ax0o+OuqMRTxfV zJ}T*Z1I+ghqcleuoQUZq9&}us-ZUeJntpgO6z!*elN8_q&=(D4m6lPI=6%gH(xUbQ zLOfV?FkHR~8V7?&6nAh$G}c$QR>HNLSECW^bNL=2(-g{t@g}10;hEY|NJ_D@l>J^_ zRz4+;%nmOs3+GS167Jr*8kVnq>)d~PxQ(E+=!O`*T#ovU71<4wmg6caU@$Lo&KH8?*4 zAD*3Z0Es|$zryQDqdHT9FGgfE9Br!D)!!8jOdWFhSK4vUZg<>{0D*?`zTJ$-A}dPy z?DMzmZ^14~An7+L|B-)H!~&x#(w6#`IQnXOb2>&{1q9Z3P9w<`S=&ire;(@hB~qe? zyE?;KS$??u&FA!tX$FU@4maqIZx)w;)w{>v1;Gp98i3lPk%YW)r0CnPyp1hQDlYfc zFiO&rkrVmJ^YT5as;c8Y`rnD^DAZo^cO4%A$kwV>W^QlBJ{Lpiqq{`K&YU|NQ?aG> zg(YM@4u{5wAj-fB-LNr4tOxyvfB1(u2fVVpDwLojzrOhu^t?N?wzNgMkxsIB_jL@T zl$DKe`L~~j1Aq*>2v4T=5~c5+4m0#cNP9*~{vZv;R_Md?>Ag^p!D!HKBI7OrO8&3W zEnsQqd^6W9({mX?Ri0VPuQN6|JQ3?74JeOzOd-rOI z27oDKA#CEX?mFHS7TDuW=DgR_3~wA8WEao6M9ObTHtzy3KG@Y8pGkVt`FHtzKBqET z9#pQ_6Ga)Ie3RCaPO+aC4AHUG>6AZ=7W;fr7Iyc}-KU6+o!JR*>w1Lac2XhbU0tfO}ib>4N_j2;gR4n+QSf8|G)&agZ!SStA7 zfBVeI70ViUPv1{DX4KgCG?T(>cn@j2x~4k*>GyTueGixW6eH9;x1gUqt&ODoHCnHO ztJB}q+!W{Q4wvrCxF-)=(kO1(bB+s2=Oju%;J9ID2j3Kww zf%mC7*Vd{kr)f6jo#TL%X*}!Z0N`&!T|EDJZ0g;OG+Rl{9? zpQ|ZhAE2+ipl$9s+Ay+qU+wR}=jiZq|6;(I2^vGM_tMh>x>@0QpCdQz&oV=BD}}MK z8|kT($L#_fp9$NMZL5G-+BaTv2|IUnekq)N%>W6dH^{WZ$Bu-aJMD2Fq*)z2Gvf?e zNHfxkvdTS|)?E4y7%C9}He+1yN1bQpNHP6D3Te8yg%8(_U33_LY8*OkI?KppXwLEA zX6lUrw#4Zblx=UvR$d{fx-kLx$32^oGdkt+jPgAR@G5tD;d7UElDZ?6XZ0BclLa4? zZT1|~788_L&m{W9HAY)RdNX@m8ufd=mo}U|jsyhM*=9~F#}hY7jEps_%d>HLp4wK9 zy!}3V0Fb(~vaR@H+xK1q(6GNg3Svi8I9J%0^U%jpB-=@~)kxUaSPMfS=rWLI80Z@q zD6L08oWHHvt3rX*zji(>mSlt*T@OjwfmpXD!srUl$u^YDG7VBl{a?7(6V}G(Vk&*y zP5vdCosZ(MX~g^v>aj|h%UccuLO5e6MMn@iTF8x$2ImS43sI}^_cF)25X8^Ofi+Mb zs8Mc5&)Jx1A55yzqY^)f0=RqkF2*em`9N=sCaS2Mt6W{WFI;_cl{DfFnvGl*K)E{X2YbpFpEg=yvE2VvtY3|Wv%mqtM?!e|a=(D^AT-xZBn#{%k%Di~B$GR5|@ z`@@m{=3j<)|MkD2QQ5C!v%!lk7egBLpiX4a2r%lb;d__uPBSfW0V;#+HWYkeRC1Ki3~Y84Yy1&T0rrj~a2J*&6nO zHl^7_j8_suwjZHz5A=GH?1O5Ii^a92aQoivcuhN?>g-7$@4ozAc-qHkugb%uDQ$)) z{T-pQmM*$9``dUnM%Vd-k>;4i2GUubUB5wnt94CFoV~`S4vneLOOyemGLw90lBRv^ z$2O4R?Fb#Cc^eqE@4WSP`0O9w50y2wq320Qs6aX1M(k0y&rx48Fl=m%Rw)PPo6}{jpNLa9njo@ z(b*Sv6RAnF2@i^|p|L4~Mbq%r;xnAZ`o{R&0u`ph+S|a-$rqiR^CZTxBi@$N$vmhl zAwy>{G@;nrZ{CmepQwdSG{&;QsLR^XaZ)u`aX6ACF{Ud^U%vMeHOzL5UAX!*EP#CP z-B%T|_t0nvIkQLv)yxM+VA`?QD8%U0STrI}FOUBcPggTU2L z-atLuOlZYH9U2{qP8^lDG2=-Ze)jBXlw&F*M^bt%|L*yC2Fq*9u>q5r81`-W;>s71 zj|4WKXHYu_ofwTNh3`~gMwtZy{JsBeHjBJJK!Z1xoq)r+ljmZVgrKPWb)dQ}W-EO8 z<(JVxm2bSaUC(WR=l68prGKyAL)p_#$}E(JIy8&x3!$~RHS|yS$EdlV^S;uP4w|1+ z?h4GLF@8(=TYysa_rB+Y2Q*xSAI%QX@X}auGKkRw`ObIm?&}T@09&oU7f|%Rd-AA% zogN8i4xXWOgzN?6m2%e1FGu@q(tBo+{~r7X(C9OaRo*okQrJ7`b(Cx!s0+ma(~k$A zlBEE>PEEx0%cmpH;+`FVwoRXwPc&wR$AKW`AQhu z7>mx3Jf+Mts-R3;z;MzK(5Pyl>?aSv$&8X&`af9y;;7moXhCP-YqDbYH#WoxFYo{6 z7vaqLvl002=%SRZXg4+TiK#mGZ{1~ttd1_AH%sZ zGi`RX4}+KWg3LD4`0ZQJ+u0jIX`L3G|NU+C$gl30^``TmS4_kdJHYHTBk6HeF4xfc z-^Dn-BBD%vL{EQz>3j*cNfYvk2ILEjReK5*H0%wF=%mej0JWM@8aR@1f$U$w37cd@ zZeE5dq(txwNWtt)M4hDbNDtgdei3}tsWp1618Mraw5#6G*;Hmo*QVqrm(g(@X*=%w zd1>3_&y1qGug8ubi_fiLX+ylEBj{(fk?ab8Sf9b~3IrsdHv$cO z-}F*-zx=Aa)X`AK`VR6^a>-MIVd_Hf``vf&Gl?ur&I5Y)J(4SV4WCmZR|i|U;X4Rc zcwP5K+roF#`4g0I`HbCw)s}4eS%C)~aetdt=s3 z9oY(I223EUoT_5x#q=l{S}iu3COZMAI8S%LGE8{dphGVDq8xoN#QwA%IutV&n-3mje-foB+N|>CGv2{>o+bJ{PpQc) z?`oEpysP6M1`^=N;iCzDok6Bm?k58Q=h5j}YxDzA9y&eCOl9S?&YWka40lO;BTRI1 zEm9&iPuKn|G7!hui!371g>^NdfM(w#oPpCw=6N6OPRpF-lY{6Ld3uqu#btt`mXA9A z`S~~{fBW~v5tvl~r(t_GjmSf&p#))u-?^7N=#y4dUq!#CZ0rE~*#PD)lhGyLN4<%z z_Wk7{_awQ@WQ-XOl##B`;~+L+9h(Y;*krleDHkE5CW8qBTj11L+1%yVldU`0~?6; zivXXpMZVRB(XMcB)SVl-fM|8lJI`VR=t1m_a-Q?q*I$PWbfy8E&d2R!WzgFKdf!Pv zb{vqVFo#S>kZEoa&q~|EvcL$00xl>!d^Ty_rQUY=IiF8}Q9IqtOy%|j?;G~Qg8a|MAJ&%_fK1s5G!#<9&FH>@D(cx` z;0%a9lPGoy8#YN)c#X(^&tHESHW{yC_fZv*=|&RL^CeJ7h&8jdGOTg^Qld@QiNv?z zfQZUSlnOExh7Ii!>EP6CkrpVTqmr?6umo9CQymXarQ>*riY#W(Q)`)yQWoh^F-u4i zmjXldd2o6tv{aMgJTV*wx_cQJwKsHpb)AU^I5HU0f(Z33G^CoCinUorge4@`^Le_+ zA_PnKlaiE8jU~-w4&@yQxB708^0b8UIZ9su8s0F9r0?%O4J|8+ zy@l+xQQ3K%QJsHRB~D@yLTS2^NYW3Eg_b{gGd!8?iwJQU`;k?U6`dUoEB8o4*31KY z9Ozsf$DvcO%S0L?4{=0|HVK&MlL@br!s*jN(6y6%EvAGU0%G%dCFZXK|nH0xohWL;5U^H#2qpCvW~y7@Zl74CU{S zRUZqZ^Nb^d78N=&wubs^CteHpI_^gS;&nSmJL8#a6zI%pz(=9My|YL$(?C~<8VNIV z;oO;XvHscX4bKo6fOfO<^TGk2Jc03ObUP?+wE^@pj9%+pmVn zI7XVCur&~jE{=0fZ@l|%JOhQz7JJtSaH0ZRhc`;$NqNY7D?mk7Me^lUg{TqD4M3h! zc*;HSEZk>*XS%*hTppjBv~w&CojC6`coR`i?Iwx~1-QL>Z>R$^`O!8~91uz}5qN+UB);f++L({#p z>o2bmc5G&l#&;(y;c!3FS}9CU_iL<&X3K(P|@*o|1^j_OV7eR5&)BaG(vUw zjKJ$S_K)^QBSjgL3!S^C8WN`Ldp7b@baF9poN?>Es~B5qTf+OldOz-ov@Z|-{O3Q9 z842DW#*Z|uSRo}H2VN?3~;g%PVG4#9*xn&?$a9~bl4CGkCasaEfi4;JBU0grb!h?6HTU%5zl~0 zzQ3bLn<|K`FN~48I!_a>?l63Zo++eAj@*14Hl7TJOd|b5|Le~~6Vd;nU)>Hf_j{O* zL;5Y9@|CTgp^<%~)jHia&#bIv!h=peMyE?%5)I*H8khl`8KqCb;a-@aCcPjto>#%n zf;f`bcehr5C-tn3_l=FUmS`FXz&QfQ_T80_F}Z_!en+Y;QG05`EgRRm%&yb1a|ui; z!(B#Uq!D`nrRQexoRe{~PU>!S1HEi^HB`m9?sFK8;qgRBB@?JPod_T$57Pu6(ix9c z447_uxjZL5dRECL$mLlJbm@5OsOp%@OWGDXzZ!u_hfIf7fX2@9I^jm%rCpua7{!I= zlR8Y=bqVY$%f7pGl6^;QC;80fwM{v9c|DC#oy4T`Z(kK1T%8*Kbg8qIfj+0sze~f@ z->ZA2HQz-WBfrC+2SjVr<5MY+qUG9&v z$T{8K%QJKDjA-|C^$>|oIIqf%v*#(lpz)Z1Q`{2;4oi?wqd1f2(Q(#pxqJIg++)Eg z<*v2ySFc=+QE>0!vl(HxRyP?T_Z_t>JXb+w_s@>&I%4jVYbh@^tm3>EkPTpoiTmH* z+ZTa#ySgjW-BHNEVHh~s(u~{8D{yO#APGgrVK=nL#^c>|l2fWf1#A84k^TWX~-7@C>=T z1D)sIu5@(JeV)t&bb!5j3XvVlIK&IsV1NE^|800kwtzZJxu<-bfv*;?JP2og@}n3m za}2RrA<}Z=K|o4CB=w}UXmh^0y8Y~N;=Bwj9X@w9+9fxxT_?cM7OJbOW1vVqV&g#R zO&iRzVfWZ`a*uW5%r<=V#pmXFQ?fvbCeLFD$2j1`?%bUrebr2ftuWY6aHEM}34KSF zXh^D!5S{a{IE2G?^YoE$oRD*8id09BJ$+r#S4jIf0b zbJZ` zWGXt$GfZD8*~@jtDS3nrs1o z0H!`&=|sL)L_0$pHMt#5k(*aYzVD*;%3Iuz@Wk}n~lB~eXl z-yPFsq+l8$=IqE!6u1!t8b^5siA%cL^X>vLB?iiC^-Zs z1IIsgp1Iji6OD}y9B7LvW-3iLw4j)VBWIf)I}8Fr!|>Wb=u>8dI%jX+cGV!aFk zNrushbZ+#K#-lL;?V)S%dPvRGpZ5=<=+f7s&{A;eFzTFm;Q27Uj)%@pYbEu`AixV7 zI3f^8m?8D-?lT%FF?tB$=$g{NV(qQQ*ur6V$+)7lGk_cGAf;7rpAH?t2O{%7GuV`;eBem~aa9084u%{vCDy@YU0#i>9ji}D)*)mbrWxUT}oy<}&+ z-v&(7NW|9KnbKmiJP>+1A4W<4xbcs}les7Hb2jOc;Wh02rxk$j4hi+y zI$$!i3~u9%9E8@Whlqv(@RhhDjmd7%x+Ptfzg} z`7E42dY&;nLt3w!I>B&US~_Prnha+_)6BFVj${yDxUeHhndNMpvzE)TIrL zq0AadF=EunN&=Pa?d&r2684iayG(~x)2X&0yjG#fzFW6QL(Y#qC?5UnXQ8O6k?f8I zqJ)Xm{oV)dVTyFM6!uW3VGYAi;p0>U&#;6)p8?VwWS?x9^2VEQM6ktu(~wpG>ik>@Xyv9D$EDA+ff-={5?!SEtC6k!? zU^mrmAkAiS_*^>D^%&(EPtOsy(vCG@&oQd^9X}H8|NNI>&&js%Vv$-fqKndl#*#IB zGvm`yv1fy%FEYBUXcu*Oq|D_~b`j+bPKS=Q%EENW%}I<^9H=g4<%-~E5Cv$fJwONi z9`9^Q*n%^GRHm%{waVU-zDCQ zY!SXI{pV%pg*Thu3?E$jASxH<%~!F9-p@#s3P*=t-Y_En0MO(FAf2+Usj(@_teB01 z;bZNc@<(}~lM)>o_RX_boNe1HbAp){+mAwvl*Kqch`10DVK2$3(O!VJ)F>V{G>eAi7eSsLNt*75f${=1UkoO=>dU*Wc|Mr6uh2$>^{1$8kRbr zO*p5@R>3i&e2wLeVHX))>&T6Q%$!g{P3kDJvisJ9P`rk-db1;B4+8)_8xLb2-3a+Z zq+NDX2j4|%EAJ{$mV3wgqQEpMr#)^lf=AbXE_oyeaGQdk)m_hgd28>U+} z_v%jo30ss8WDs^8=s+*9tmD+FSJx<0l<`KaO-c9XX8FbRa?VNFqhssubyi%-tcds@ z{LA!M=|qE0T`Mp9KK{2(y?>Xt{fxiUiI&!t(Y}jI=U3h2`)M%RLm~yeqbzXK{Ji^P zTD0_&T)!XP_va->WL7~0AToAnu)PdfHSp!{6&y?k!3t3mAZMLDyW z7;~yUWCT=tHR5Gzw~;`B2qVz)N_66R4tZ2C!F!gMS48=zQ|2C6;*eZZWQw@QzTf|6 zK`WMpQjZuTq}mo3u`&86ttM^D7|}!=nF+&GCIQgEb zWK%8DU&!%4yU$;{Fea`H;rtcCQHCcKt^%Lcwa~6oj7+EF!?cm z@6{M(>|iCe=;INDGU`5q!=$5Q-vB`+ZD*%E1c3B=U7gt03Epy&iW5P~0TPN2&`F+s zk_YbL$d^-oGy3pR7y%qwzyXy0EcuWRd&n@zL5C;@mHSVhJ;iCh$N0Az`e{82{eTjU zWdG=RDG!tj>ameQG7A8gaySQ_d`ljSxaJr%0b|7yid5|I;oEmeS$`w6e{_ivel-02 zmgby1l7d`3a`XsU$n*!Zbl5^OK+?FE9D;ms?93_34Ld^VF#u~acekD=BHYrwa>b^7 zyT~xkqP$><-VdYLr`g!b+v}=mxY$oA+G;30%48qx^kr>kn%^1G|NS)%_?DlR9iAg| zH&fsN(&ba&uT^AC4j}EyA{k7Fn*ltK1=xFODfG|44|1tnwYBA4<%TpTnCf0hyZSiF zYBM;@G;~=yHbsNh1~Pi9$R_K**&ddAN8^Ny$;VIV4Zt;_I~)MAlPSl-_H23mrSLqJ z8hWxm$7onxva>YoE5hc4X6*|jpUbC?-PTU`Im{eL@~%FZyrE6)^JpLV8M70X`7^VG z@;ZDU1ZXJc{u!0@J$dpZ>dUHu-b@W@%g=49X0)xN*?i~0q* zs(h7h1m5g5B#7v~sB4uG(xP%$dr0}^=Pi2`_!GoP@~;`q${zs^!39f(6D1GsB{npA zq_~9VhVW85Jq&B1IYj@FjYIZOx zom3qhIyvv5ex~D_+aZO>!3K`ChNw|OBb07*&d&UhS+_f6HxV^OQ8i&WUwuIIL?wms zqXU1a_F$Npn}|_en*pl$a&z+-AGjXMvdY3dbufo(4~L@6qVRO+X(XhI!V0>Bl75d8 z)POkEd@6i({VR+;YLXDB8s$@@p{5mVi-a#hrGc;w{MBbs8JmHi@mfS({&P@So&Rd0 z{dT^UFl7o?2>{7z8>yk^&V<^0kn4?62y2}B7L+h4Iqm<;&uErKvkxLR3p{syQ+-&Z z=4eMzVI=H!P{Aw!7KNO~fbT8C*ZlO=Fn4%YXn2p>c2Z*wVrE$`A-Y|Es?Y`ylir zLpu3DB@zu_&cz6z4pJ?OOXl&O3ja3_y%ApENM>Xvl)Dai4T@mk+mT_?jHv$=qJ)W5 z_7H22&!NNwD?H=g(cXvx8cooc)EF@e;B$ZQ(J$g;f~(iAhT-**Fqbk%w3>!oMC~p6 z5b@O**Vx(4O!(0$x+rs&He)hUS6WdTBXl-7dkP?M=jmNg?27Q1QUIGJ_FTFN%9DuX zc%B+mf>+ZEGf_y7k{Z}{xGfq(M%e70nopC)7o^2Lz=6>zazB@dcC16Iv!Ktl=gw0z zzZikDRgBWg@(P4MBcE`VZ45aL_)&$C<#*%zDg9!akKl?N~YS;hv zZ=*8xtQC+7(RkK?GdF+xTM%IO>Go|yZsFqFZ$qEcp^xXHn?o45b363Ir>iKnlq1bt z=TPVx?hgCNU>Kfc?-^y5Ll(gDCe2uAlCz!2UOLYA!W2p$Wt&$5a6;sM7Mj{bu`J?n z3EYjMK%a9qP85jgQz&=#%??!bAk*Az`PvL_KKaA zp?j=1qWuc>9t=+F3+*gBHi6Pa@o3EWjHaQxr`}iDBz@~hKI@@#H9s?oBW+5rNn=Js z!y0dw-`!uaKinF)6`jYI55AlzYsuTqcvHJyQ$C`SJ$@RR?Tbdrg^M)D#7ULbb#hE8 z|KjT}!=Ik|)6hHL8>34qK^qk6l*q?|MLHYOdMqd5PYpJIcbG`cV|d)(30BD4(u&}b z%FB^{_FG7flQbh|fsu*Q-|NR;4+Uu$V4I5()1>6hsL%BVxG@B4KRbVdGs zk&l5CDF4}xGcq;yHjC2e)|yCW@dX+Aa%6wIwJXTCcn2+B7b zOsPkV7)Qs5{n}r&KV;MJ>E6J-sDCtMlrOt-al%N8bZqAXdR5G>&PIK4un5B?*GOzm zEN4;9Svt~(yfM2-hsnl%%8D28nGTowz(}Jy@7A5`;l`I&;z+Tbo0;M2-~T2&{>RV4 z`1@akxm(>~mT1w;Z?A``cA6p0Zib(zC+sa{5WJGRGcTV1@(R;FC>z+ZyD(+~B-8kvx??t*Jmxxhf~h(1ybb$o zkhaD(qzlt+rB72Q1vYd}1V`iv4SL`C5WvKJjDJ@SjRE~93!|`!S=Wg6XZsuKqtl&yUY!@6Lv@=5Ytre}ney4Cb#09` zfLFhtjF9V0YWVu6j=X!~XJQr;@93HMbAb!Lm$XrgTpv7ihzROHl*#U=O#odQ)Y7ti zNI*bGVEvy5}o-h#~IHT~YsV(15lw1PDEG(Zvi?3D5OENCN9!kDN%_p_0n za0J~Oql~_<@0whKDgvL{naL&1>6myA^@;D({j@Wb9V8obeTfm%hoW(=ong6$o#H(= z<&c2`Bg}$<8#piWu#vpRV>pcupN7q0I{5>JX~WK8%Yhz6I`-a{ehMOac4lGp)5H=I zh>mwYPOJBFUma6v>5TjkGfH?j_rmWb&skbZ0B&h9vrW*4%mrIpT+sFC4hE_^VA+IhE`Hi0fvxYr_d*T=%Ez$ z&iB>6TgQPZL_b`oT;-M5Ul08Rt6s1#TUY7%K-16XJfrs>`Rc2%lfAQ%pTJBOa;=0c z-4tX&YC%q@rc~9vv_}k>BV`9oq3ilJWX}{%IA=m;%Qompc{q=p+|kyC1Iwf_=-cHP zPEJlF8aSg9mN}zbbmuyIX-4fDd|QIEW+0@M?-sL{H$T9($!A11`d)sq>8Q4zWljUn z`r~yiX^MP9`JVe-U0EG}g-0wMQhrhQ3?hQmd=WNT%1l_kWQk?P) zvVK=ar$aq`kGi@5Uf{Dp-Z@}faZhkG!r!Z%70G)3@pK0Ii=-cgCOp5$8a1OSb|?> zBwxN1WPJ4KvF3i<$E2+F`to7&Pi>xLTD-PiE@iV@WPoRqMfRMG=SG5)o$3PU4`ED( z1(SW?^}JllqL2}0gK1YSK`-k}ta(AOSsP3`QHDgGL0_v^_A^c2YZJiLp0PM{U4zA?^KZ>ktj|HXnf`>QgC)Yo zN?|adh>y_h>0!2? zF&uQYTm@W^=#ou*6cHK=8T-qK$W(?^MhmL+6yP4Z2Kv-OqTBW97E*5byG_+hjg?Sr z@Ks;KD4l)?eTxYEE;^=<^oGyB{wyj}jdU5xZu8d1S|8>3GX|7Q1i zc=~_5AF5~5!-H#gqr!HCj$P-CG^c?s4%6VsW!8nG>vW!dr%*{_w>MhD#lQHM;VDkq znX=Q&)t(3yG+9hbNy8BBi;lp%jqip_k1oX#cn9_$2pv6%aZ|G^bK%Y1Z-&{dL{l#J zTBk`xud||pZQI)x9z4B|0gy}C#r3eiwKWPM4ZA~y)O@8g?gHhcpw#iv_<8x%%bRq>=MfDbl&KE74!?p$ zMpqab&CzM`o~I9;ih|!R>^l28Z7N}(t1OS2-WQ1y7HOm^t11Ao#JWK>T3A{b>swj++NwxuV zdqL~v>892;&IiHDv(=tF9JW=LhBUG%#-GoG>ZXQJP4ujb(P;(yQS1m`jl9a5>S$2z zEGovqClg>dU6?V%pFMgI(f|Sqb`^%j;epV6>=@}@BjM#Y-lPFjYN&5+iH`LZBGQv8 zFa*XLd{v0S5~JjR8@q8JdcV0ErlD;!G4e`^!Wz!#{7`?`LiVf^eKZQI0qi@g@SHnt z!yo$r=)lMqHdeHLExFtazt@dn_hM`*Onm(iAmBbmQfqiRL-R072zJtk!c3A3c)piC z++SH2oE`63$0#HF*s`~U+P$p=$_#Jx@Hri8Bg6+Q4$|=RML5xLJhaucQR|qPFtMj# zPv{-)P4FuZR9#vXE?v76yM0eCPer+B1i8ApI^I{_6IfFIoH}(nDi_N-j0CCZCz(@x z;>gKxv-f5~u7RSv7e~neQAx@h{^M9D`6dZoD8o)xp9n*Y<+}mM_THO64in4`He08x zpe%g!$#25Z}tg(r1ZaR$%bmxqBxxH#UcMWK9$4n`1=S9$vl{%2LQC=^PI! zPshWJzx>BA_tDL;d8LE#DS#G>g4Wal11dS5%!qs2!9-S^@2PB*A5)2_s(WnqRJ;d$ z^KG9DXg9!HDEDTQa5N9qVu7xBmHG zf(|;e>e%f#obrob}8;5oPiWCRe@oi^-qNjK`CWYj)k&k@;1cj!F$-vSF4E?$W8 z$Vj=yv`)FSXi0-51)i@N5x%Q`_Zj@Yve3`Elta>t`pV2OZKBeOvSd;kDI07*naRFWtYox~z|teimWg*|Px zAq8+Njgm0|n9fUIhT|{45;Gq)*4uyetI&octgUK#xd4g#WYe$>bYbcoPR1N#!?qVi zKqUE$f-cgZ^d12U9Ht~)_?brb-s|`df-pK@0xLS++8(vYh(-1&>6G~$$18hXCj+Tt zwejRF`T7Vo|8t9T@ywRUbi=5l=N4HpoR9RqnVtd|2@nPEuJPPyyuSd#RtnAun|?gci3{g!+-%e7D#jMOem&^5GKfF4c3iCW;Z+tJ55N~Qdn*Hj%F08aBg17xev zDgrh15;$1rOpc#F8@kD`++I$p;@xXu;vplH2|%sTRCMxNp52Y!+5p7u1DvSf?*hid zj~>R1ggyK0Ym`X4UqpwTef5YN(Sy=Gs=c@bblwPe9Q9i%v51D9@aI_x14f#`Ta* zV1pSLlvR-K&bjPhKMg#%UT`*fG#?)A=#BrqI+n2Um%2v6)G8C5D18#JHUll2eqSkh znPhwcFtQJhs!j5wU`^S=p*S^}MtjOiBO!6#+)RyB{0ezAT-0ABTB>hpMvjkj^%)12S!`5iTV=B8fj?IQU`zm9+RO5f_Os9H=jB6Xh5-}T8a$Z4zZ~%406m`Q zMTX6pha6o|PUTUXPZp9v=2A*_QUR*uLuvH|{X(jX0kn`iW(*4|C~G#5^Mbg_VjX!$ zI$E~j{RBD%H>EQ(dy-3sUEXyM<5Hop{JsEz*Y$fznJ;}ABv5WEpOrbvPM5%*?@(RC z)ClM|SpuL8^)nfKR?sS|t}K53`}kJ`01D5xe6Ik&LOZqO-y*K2ohZmnv(lJ~V_keR z_C&ODc@E+rm2i`qo6VbA+pG`>Ii7~s_+%SHt183_?_b1;?PG#S;o;YwLidx+6&>c8=po3mY5aXqC@^p zC!@K%naCk&DJV5lj^^(6{PWo&8{^L*mRP67Z$zY3zLEKJ(nI#?hEUkb_#fVJ^7(Km zPsb+3;&gsxQ zH4={OKN9YC--s!gWz4A_92tn;*C?OdnvBd@TU8tO@W1ITgeXGAYb|Br5OF`9VIA!F z-uzC7-X?GNasJ&i8B(+{Y4DqV_Xt2lA?#ker;hU5TeBBX<@1ZfOa8q@u~*7+mnW7M;M9p?_FY^??j9v_H|=%u^Tlt-*&S9nLAH5GoX-+r$gm*=F#*|DHyF$he+ST>d&}KqWXvowc7~H=Ac$0~6 zUtJ(l(%KyMlahPqpMDc|K+|?s9vlJX#_+U5sr%;$%sJBAO=V8SaoL6vGn>NHeHDO0 zO5?+SoF1_kr%YqprGWJPR=zciIsu8Y5yZZqQQp0$j}xH*IAA}E*q>>X?ARpHB|_s_ zjWlMNqf0K4hF#Q!t#1**gT`;&ycy18I6eLPaws9yuY!k5+t=|ffeN&lD<=+m! zY77|7R$;236!g*PTt#S&EQOI9583y{&~kx37!&=Wbw_L1%wr_s-lp&oGw4sBIvo+@ zWBZPUOV=-jLej`Jv?B-s9TpcCC6whI`Xd`dNtglo4$K3_-G_81Esx}Ys!a5YL0{sWOD@YPMwOGG#AehX&Uc~B?z%e z7JH#A)Hu)xmzQHN2Xr03M{Yp^vN|WcCXj=fdW_;mjYtjT27lC}*^eqoG6h4d9daKS@N{)OpLmtXG$x z+#?Nf&*mVRWY_Lo3n!XSgzJnr)cLTl!PVD(u_k~HE{V|PJGgAS60fE)2%0siihN%ILp+@*!Lt`HOsiChygx?cq4@Y5;P#v*> z*x2wGpJDbqr87F03yuP072wnh47kray=DO9l3Fb9Pw;n_^34cmRz_Bg?ry_L*jLS% z**(bB&aQYq(yy}4ef3OTKJSiQMAk5p;!5Y=%@{*_3b<%0Y5uvSRyX5FkX^Nx#;kz# zIjJ#ASk`UubJW>U4>d;`QAWBn7IC=WlAipHojLhc(nR z?0gUPxz1G$j>r^y4D-h8Y2bRDr1S3&bv)JIuIifV$VbwNnT3K3rr`@h81?pkepfjo zFRQC!RC-%VoVKt7hdB+S)}OhKpEw?#Jbpqi4zi)3eLwFt{Qb6c0AZfX>;%u)cl6o) zovH3#Up~|km$x-|)eXsv1m%;u&ddb?5&tw&9~}YS$Gy;TNWQBy?><}l;57xXO@9@@ zkk-6!62!4@fI7x|=@6(}VpNxR^XCv+bpDGe$#U;}Cuu?>IyMbU!JdJ>7HQ08?XF$f zb&!>($}P`My?4&pqF$pX6`$$e-)P4s<3a z0o2#m$B4hzb&kBYxDLt;nLCWE3Kalprc29eH{tUnerociq2YXmSu8x5zW)^7mb2OKEot;>f$p?3?^G zh8%9;J_dLG;3q$c;PR=Hr=tC+ZKmC1sg_RIB(`T&UQw9r=%<$w&Tqm$3x|#|zK_v- zf_%FOP?T2iS!7aQXK$pj=={eM;$LfY1cG-n3bw~Roa&@`FZz0Mg5DgY#P8r8QZfnP z5P4qPT*HR2k zd&qZlX7EtTR(7C~=@VDN?v{g0egb4C<=u=F_uA=R25CH7^CMLlu%N#cWe|w*HlWmP0Ap(_+FXH#pXoC5iG83JDmv)4Jo^nr6 z#sHkbInOi#_&DeC!v?%;4>fyknRTKwF5ODb&*^=(NZ`aW*Hu8*Ozf5g^kV2?ipJT) z(I%0mEkm*?q~jKyT(;T8R4M$=UB#4tARk=HD%12W0f};n8z^fMy;ZmmG$cVY>;~;+E`}mhr0Ct}HegS}`r-QKsK%uO%baRZ7CLKai%Itg$1U5#LE;5D6 z9zihNKSX4Z=2_nw0jAaVk5IjtvJ#H}=yjSot%V~chr$G7xw1(8oF(n3i)Mi%MCt5u zoR2|Z_JEry!)Sy}fRavQwDc{T76rnKa zR2rWz4aK8US|MdJo%!`fTwJDWxom>5UcNoN^auX}q&6#D`|Sr|^}`2Y<)epT6?9jI zbp~>Yt%xxpu`QC}J3C2>@Dw|?A zcF$i_(6iHVJx;XqM(>SC1J=1W!RQg(;4=~QAtS?7J{8^9w=c)#v19J8+V4I+vL{y+jIC$vUHHre>+NBjpI^UmrK7isHOv6WKH^HY$3IkxEe3Es*)0 z2O6lKPYDly`|D74@JQNg zy^8FJlC02h;y_q~eizu2S%8iz_R8o*P9}gHf_*3Nu}tQ`B1X(8X<78+COvW^3}Nu( zBM`GQL0oy(5^Jy~CuoGWMExd>vxv~{$RZkzqh8+H7Sj$Dni_-BtOmde^jrqd`F{S) zkuf?H(y!4pfhrpc4cxsIvZ)mwqpYL6h}5{gL{^Ljmqx9feT(VzuMuflv_Id86EaU{ zTuX8u-^a;fxgR>JuB>%3mcH%?BNzsg7{Jd9=m<+@#|AuAQ@bw|r_d>uS@uIT0Tui* zOG&^&Ai)U&IUxJe-PqK4q%CQAp3(wA$D?gWV|GH!_#iFXNR=h1i}?ycHa zneDaqm+cStpU_~BJ@#4TrRn)Z_L9cu7hil40YD9t%MUNd==j^Gen9pNX|*F=5wOwO zAK=-1R`0K(_q*Fr)|o^+yr$=-VdDH?pHq-dV$&sK^hA(MPYn0 z5joZ{ktXb4A&>gpMyyP!69`iuXgGg!?@E+sXE9DwpuLJhMt^mU#Znp1_W3i$IUNBE z-dh^eDINLw$tNF&fA!A43Jo6N9|00r~Pg?dHiH-3|gRJ z$oXBP-qkwGt6zK>4jpG!doPCC)-s0k0DDjgT~U9FZaZ8`Lr+o?Iy>4KOGji5$A0Es zSGfJZ{Z+^z(%t_*|1EN#6ypcb?|?>H2?iBl6^7UrQ7RpTq~nxyxID+^wq~Z@eA_sW z@|ZQc;JfD4JW|OUCW`HTjUF}`*=Qdv}My3iFnNplfri*Efx#)G9%G$3- zUNgfcX+-dNZqFpp5fYGYQPtEamsIuFvJv?Z_B0lMw3s|>j`UVMS$l|nX124LC3 zbEc2Hb1_V>1BN0K5O|dC(C?;`zBDv8++e!EVjoV=B5B+hy+u3d9l~eiAC0wmZO%sB ztl<-g}>kv~Y=n2dWA{ z6CnD(Nfdy@|9|G1W8U+gbE>LiN~Ff7vP6Al8&(-Y0tS9YM_eF(jrmTbJouiT zIpvG`F3}C3uD&kb*Y8A|gU@+SY5nfGL>h#1amZ3YUSfQoJ$E*Yjf}-Pa&BUJ!mH_Y z?^*lFXrnfVj6V0w5u)+hL_07^Tod(*!|ytGvK?F}fftJ@$CL?Z<^mVe%@e~kR1I+F z;GYinrm}r=4?w%Uj@mgpVFY{AwzQMjHG3HQeMF&;vTp8M9buiTUgpk<^)>Ybdax&_ zD16&mUK3KLSE*@1O&UJyFgmZ@;+_-G^>^w1%3R+;-TJ|gK8Oy#9hL+ZoM-owYkc+E zRlxGT_+HMP&VscB1aXwdg4x-~fm)u!9Cqd3BDD6Z+N!wL!#zaWnNtDmyWiZ6z}68` zXo_Gv>;NrxzKyY8vpqMfhsCX*KYtdTHG8)o1=twIW_XR~ zn?-l$!vJwU)IkTFmC( zpg)r`xWM&Jo;kzbO9{gOx$phUe;InX_YQgYg`~L713v7qX4+fRy`-XY#sz?fdEPg! z--rw|&+Mb0{B20mnMHTn!`>p2gFP=oUH$RU`{R$|`Y5+5>Ts?Br^aCsAE8FmK0v<= zTJ@2IDrI-Lk56KYXu~SQ96Gxj*a=xMk2e8*v~kyQ%yXHu(guMFfc$f(u=}i8mO+G^ zRJ?%TwJ~Qkp zF!&;*)z*cjhtIiQ22AC~Xw&GsSQp8??eLj(TubmjhVYd<)1EOwdu>~tVE--{?Ymi2 zGmG=0Zt@!bo55S>z&TMC3XbQpkFDOXF3{KWvwlwMe-iS})HdbuGIOikajy#kcu#!{ zon)`64X5n(xzwjVgPn{DS_#IrG(;Ny^y4R_WMjLaXLl%I>Akc$r2Z>^ryf5Fjp&+E zioB-pBoQ1gjJC#MtrCD}_ON?GIS^$4n_h6jVe49-N!vtOm^izBPP@lpaLLcu$;G)* zzUs8=>o|YS%`H)emX{y;0{Rr{7ePk@ANsk<0)G}$)Z~=`uZ4o)x+UNX=}LqU;Xc~_hxGHVO3d+C^oeo$3bMSa4e;##rBHv z4u}8Im_0ZRFmaz^L2fXOANIV^s9{=<{eGX*_DwtGxZCAbb79>!9b> zHpq$2hV#Osg|>pWFf>PDNS?|4I%j{Rb72ZPf8`nw;O|j zf_p?AG*B(%Q+NJcTzL2H01n_jPLW2%KIc*g)N|pyC=^{M(R~%QX#jr5(FDL?b^pYB zS;=^e2xU%lS*SgQ@FHK%0#Hp9jag-#XDIU1)X)?SHhZY+@Cz=LRAL-ZAf}!w!}c4t zinDuen$KUkd?h?VxLX}|h38&ipA_eTo>N#Sla`e_itd?B_F79@YZ$;7d+pLCEz>X# zCA}3xQO7#*F7A^Q&c&j}Dfd6h`68J+q(QZt>F+`55E;W5$j`}-`Tm(X^qj@e+M<4l zv}TJhjd4aDiB^IBS%=$5mCmIOWmJqqv*9Q$I5SY}&oLI)hzh?3m46jNpshO70qjP` zMx#+=^=kLz#g2=?y>68F>C0!obBe8b;rX(4ll4YY_}@?e<4?o2YuBQ|e7@~`Fyj85 ztKY%Vd=QNv*G}izHFr-bw=8n$S@j$$Km4;wRpj{+DK8J7K8y(e6uD+Y)K75UG_<|| z#1vfcdn!PUchA|#6or-ey9&_#;h9%iUuwA=eoFleDgFWqDtMnkC7zZ;9Gwl)xcvO*pMM^&akB1Is6R$4Bfv(VtBgv%FZy3ZhskUBy=9mXCp%7t z&%XLR-XkIBy^b=;^P@wka`(Lj6D%&JlGcC|;M*sfT#S={?-w72Ms&y)(Mq2Unn=h$ zPraF%64Gag3h=Yjr%uIpuw9`k9mAxlq+#&b#<72h8W-HN0q00Pr$JMlPjzfkq;wDp zd4CxfQV@#)wVfktE}T9|5Azf%esj(%3rI(qS|GjR6CzT5p)n;l^w6Gf=kZAB`UyrV z?fO=3cZZ|9v@K)rCL)W{Wi6a*)qPXHEF9*zc3 zKwDdT{Ol1Z?&b|I&n(4$;p!`m5J5^oNvlTd4B92bAzeBvgW_lX!;w1K(*-S<&;Kq; z%$`wpcpjCP$C01g$gvU5uaS*v9G6v6H1@YSO9j+)S;pA`C|X!w3dhf%31fic8wD9u zc2;&kEr!*Uo6lNMEV}OAOG7fD7X(8zRQ6nS3eqdf zjS_1V`+Y%cSpg2O;k&rc5{_bwpcfU!b=J^~PAi{nJl+`3gJ;A0DbKxUWW(VYsIZJM zzyJOBBLL_9)#*l=EdJ!a^?L#iQqgr_qaluiXmLIx*3PZ6Ne3VnM)aD!2L-yc+d& z?=_<*dV6}KQ>!7p&HWQ2i->W8)u_GZd;r6mdW8y$S-k z7rVQ<f*uzpOX40jO`mzhl@9?lBpCrtfWWP9^{$ zwy~8mu~F0+wbZPr#VMT!@bO&QBJFTr9EUI~^{>#JZ6Qtn+a_nWNg*Ad%AOY+n zYnT*<)J=+NVt1>vMn(w0y5EoiEiKJaE*UJ+`PV-6e0z2*qNqMrRtX52j;5UOy!)9c z?93W~op=Uc?OC7QsJ+8zy*-%YBpa^r|Lx)F5p3sKezyBWZUtEaEVs^Ayf zE|T|j*#5!%VyomI<-Hz4pS7q&SuvG9muPbbVmtPapCL3TSi$?cIYfo4>#8EH)ckz~ zwLgzQ1jbu7%6%G2*w!4V*LrFg`Qm=0s!LN8I9Xp_iw4}{8ipo^L8HNlvOtKAxw$c> z1|0gK9+=|dWKrdtjx|>*|O|Zl0y#-*L3z5cK4{t?Ey{NLo4Z6a-+lyVQ zm20X(@Idr2k2()3H`^sCyj8gV@_QN@4W$hzlEVt*uE`j=wHnVJY7GSqe~lvl-aADO zJHkrG!Jj!77FLW1BnMjrP6Yhrix=_Vd=?L*2lqbCln%VlV+7WJ^BG)6Tj2Oi!#M2C zjV-aAmLQKt>!T-+h!mAZ!_hf$jXl`)_4V;u(wQATkHSnwfzM;VbCE!Y=_ew6D(RZs zTB3T;h%?f{gP;9lXk^}dHJTab^=(j(A``)D-kY>@!5$MzQbumsz#_e@ah8uI zrBKB>C3Js%EBxLc{ZW{PK9&rSW)9Ze6cm1(3D-d*Hy5K%VI|5cWwM_4Q^*KD3}C3t zfyf%YQ}`&1N7?UlD4bU2%02G+@x2EDbfz$7hnY*;J~p0$aX|MAEBxCM&q7BsSL^`M z`;aQVM4D8Zo*$VL4?+7YQPvj5D+fq0s^#3t0uUfDdi3aLKMz;F_q{`5%bc%1fL4C( z8p3=aB(Z1BL5=;EF|hq^9{Wh)>%QA#zdHY008HhqQQVU}zs9rgt^w@(StYjP^r^53 zt-lOpeH&wSwr?yN$2vFyL#~HPQ}9Yh-;qymd)xmkEJ3a2**u$mM&&3yU7%(gP-o&l z-U)@+2($Meh6mmELQz{i)cWPvw^jsNS)x30{~5h5L+(6y_8`hf_gFQQdJBrW-`)GE z^u3)U%I2|@^Yl(UTUMwR zc&o^+2pd$;c7A+b-_?6O#o>Mb%zLpieVMS?6Z^-BcT+R!azO?$TT=UjMJZvr@0^Qd~^7|Mv~oU z&tG=MdIuU%)}1h4|A&`;6lV5j!fQF_!?7B394UN;A$%GZ!|>=(m;-dnBwDmbF6SDl zYQ@P%!&emW%bRCkb&ZGn|MqV}_y790p^^4fiw~iqj*!l#@yY*n9-TAi#5L5(5=7Tv z+2DGKF*!%eHE8guu*sOF$U;a&1=XuYD2&$Hiccoe2EPjF)S(U>crg%lkjxn6k)VRc zitA})Rp(5nHqyHRO*F)uQ`cFYlbjA1&u1J(4b@>3W>;1fm77T$SfdL_ep40Is|x`T zE2+;h8j|_U0oN;lnKShBuTgXuKos@cUR4ou1_eeJLK?=gsXykysuvyZ1J_%5 zb>edNFU9ivu)p0TwW5lka~k)q655O6mtqr*7Zf2g;-hf!7MN*lz_ zYZ%K;)amnVDqqyW&XJ$f$W(Saq;I=kUC+B>^vyZbf!3+hNsSSI&Z&Fa;kmLiu!*+TJ=il$d^Tr%1tCeM*UEkFqi(-^@R1R7!YiS7}f;n)H`i$;T-#aqh z04W>-3Q@-L=S15=ffe_aPS!;z;*ZcJ>LAa~I@EB8bcf(8!J;knjW$DMBC+?RYA;a( z#|USfBlNE8@AC?b=wP`1?hR#=EDir%c7gNivj`NO>^u|pC^$Bc%mhIW$`$PkE0OCQ zZQ=A>L@#~#Z~o6veu5&mckfaaouanLUUTQSnY-o3$b`N_MyBuTs3sEc+&T|3B)q4f zjB}%%=N$THhx1exg05T-aK>1Y5z++m>?`U@+0b z&h8q{pXb@ga9R!^DS@){2qY zxYnEt0OUQvGv+Va$IP2fllG(UsU9gPz`kdWTu-U|H{SU!45Kbm9JwBUHziSk$9MDd zMw0!!I?25*MShw6o5a4k`{8dx33{p$r__|PSw54^T&@faQu_$zAlI{QK`{>Jg&%wm z`{N;nh-qz$?cts`7u{#xT4IeSR^s(#zzh+bsH4l6c7-)d4%olZ24FvG$0h232oNiy z^3bDFyQRbXUVcwI(;ka?uvt?=R~SGfgE?88OYQek3JtDuj_1~4lE6^dPQ!VEjm4s}R|!t$m4#$jV6K6C z$Kif=sOyy*i=0j8*WvuSF52qKF6Y_w8Ce4kzpKsV@ZDry>IWsR?OYy3M`-67I2HW! z9B7{jw#fkSGs*x#W974;qs8`Q6*y;Am4|ZLbn7|5EkEy2*Jz(R|DB}c9l`FhrLK(V zxfg(8JlibiQlN(eL`qr_thEe+7yaRY!szqZb*6QCPj!>Qjak^IzMuL2I_O^C-wO-r zR>ZqUACb8cl<_-)UOtEKqfPDb`FB`@I_x6nS$VB)QFaP)$XJr$rOv;M?JzQO7(`OG zIRu*3N9tMc;k+i}g9`dOuby#b>oV8+Rsn$h{mqnb8vvMp0wRh+YCMjCAX3R<&CIaK z2w-XdsS0HTyJ)aQL>AaI`&7X+ztHKDrs&X!7eT>`!U@_4H~*VIB{DORq*XS5!q*p<{P75VU>1nFw?{Vtnsi^SZzV>!(WAWtK6Z&624ey?Rj}~sZQAjBa+^{+aDoYQC0xwek z+0Zen$FnFnJSYltm96wo>Bt^NbL)Tpn_om@QNgD|5lr!bsgPAp?YZsYLEnRT7*z1) z9eZsLnTN5iye_7Wcz@^F^|^8RIuWLka1jSpFvrh&pfpO29;?JPfZc;SwIbZ+NqPOx zKL0dUK6mYXPT$XKt4K9`q9MV1Xb_1eS`fu&*4dY0?%qT3KrWyp5?t22F<0- zbgdW(rHxd=haxt8hhDDq%$7M|Mb@9K6@Dfm? zoVgxG;byV6%NUhuIQ{Rw^KPU^J3r3-K1P|5@JF0CLxL)g4GfF{-plqUgDCQM{^U=> z*SEfo(Z8i%enMM8_D-Y41fjft`e`U;zxjMRVGe2W$*h?|RZ5kHM-9&+J4WPr5My$K z{Z&Tv(cHQvK$oLXBG;c2*@o_Uuzg6ibk1X^0M4F;fyRbuC#Iu@lHFN51QI-#DMW%b zreq5U5*d9_aL>Mke!l?dm|cXENBb{;yA|?2r`f}uZA2^54%<4qKN~9RF(?ION@CRd zS0DZ=o~J9dS7P+$W&ca|RBEWJtBXoT#Ziyq>Fw(ct&OeWumA3^) zd~qIJ$7j9I(2s}tcJE$&Hxv^I@_Y!Ad6rZ-GIo@6BKM{VxX%TOzH|M%toLf9a(8ui z#g=^*K=pik{ylr{b)ED#&yo*1&<*Z-Sg^{U>-c#7KV`jCk`~WQ0BRi#6eA)EoqH@N z0&W^7?vL9qZ-=qjv3Ty3`M-1AN)KBC3fwt&M$moEZ6Y5UXDV8sM`Pc}gi%e;m(dOP ziP!RX^YZ+DKLt*&m%kl8>i;NgQ3Igw|N2!t^Ez{xq=%)o)P|0?u7thZbOO$Y;N?(1 z?YuAw&DVX1;VGbNuWl8;azN0~D9L_Si0`~YeH8Ut2W<<7X9mI@+E$%y=?Li*O-iAT z%Y&bP95zW;8~*K`kW0J1QUHLj{_S6dx?{zWJu~q5C2hATvI#|0nO;O!kc1KHdDR)s zrN_9&q4fX6Xn&2g2xR_=PSPZv^@eOZ;4Bf9TETEUAj)KQ^3-&UGzx+_+E2A33#vo^ zi~d+hX<`QFkb+^hq?JaTTUrqH^%^uwWs9wCjZzADFd=cTc^#jl>1+q*3P2FNWIy*P z#@=E`g=MjtLj3^FTt!nI?XPyj#EWh~d%A8QFAH<>!V#SN`G+qt(n%|tz_IjoU@KU| zAfX41w(0z*qtgXgAqPazTw6j%S_fEXN}9YZGb7F#zK-bpXJtg{X>?|}sB9yhe|3S* znUOCm?I+}Jq9VJFuF)VJU*|lB@0sGHPSt5k`q5*TkW1FoFYS z`>mtw`8DLW*HRZx^1k)RVRgDrX)^lF;?ut0Eb^}m`fwV~&@ezqQxokuad>72CqiR0 z!HCu6Lz#-caOA)ovj&#*=mZs98_yIGQ&9wavT^*hT`Zm~5a*tBugV?(hKa=%-6v7r zQ5(zDH-YID9Q_oSZpzYqel9~M(%Culo};tp&qhEfkBaJ(uq1bO*TYffd5isl;0*O0 z7CnmM1-HbZBr z+x9rqYXDdq++Q%IO2Ce1%Rx7qW;K9}uqM?!HkxgV_xN)b0E=f)TT<55CUWJ-7ExVf zO$4csX@$&*mH&1A9nH}0Z4o>-Js0;)V_Or934oL}CbF)GAVLl44l~%I*`$Bi6@fy| z$Pb6VLe#XlZe+ep5o{!IBeOFnGb`G> z8x&F9;>@Qbcjo{schT$H6t@f2#S~m7GRw9KVQC|>Bz{7oMt4hy-OdZ!io52HVJqu+;`^gjWTp_w*D@A=MhppHP(7OUs$_AZ( z9dP%qGNlALVQ{Y+@YEvi$|9rw$~#k@|tL&>hWbZtBIr&&N-Hwojq^k)MZlS;Jp0SH; z(dPHs${-#1)17Cq_xqzf_Pv!ko^Xnp!Tm44wYIlKri}W)^d5DvzOD9)y7UP4qCkL5v}FD*lfsAJ*7#3F z0F#r&v%ZyaWE~nbc{A%!Vs{aKTl=(9p_ou{H3b2wczG65Y`YP1RG@{3s&tD{W`)(*APc9z{Y9d!MeSMdR{JbX43Ub;s&r zMRoJCMDOmAI51~CLwaytJG9jXKxXf@=|KKm?G5aqq~_-mZ^saUuYNfCy= zdVmE*R0JAd!T{9yceqb2>|$HMe>&y{dlC3N+o!if)Aef<1)6~R3*`#OJP!j}=X(PM zVgy_#**Q&N9coc5Izo?d{8sr2BDc>Q%3!aMHDD~hM$l-hQU&dvg;NE?Td(&qf;`tl-{JmSZVuyfi&Xa;yXL*A&GC4yIBW*!<0qN2>%elw0 zLUYq0GHX=Dy{ueFJ*o_73bTti6WB=(ou(ObJO%W;pJ1E6yYJSZ0WQBFf;>Qnj=%hS z&U0s|qlU+mNvPfB)STG1#phlqraj!k+F|6de_$Zec-?njKK_z|H;d7^7dRZ~?~m6O zHP(o}-hMr%yu9T7Zd@TH3MWv%YvQ9=$W_IX%(G#ix>OwN|xT`;$Dy$8^#=)=MN)KIs``eKG z97nMW*2*Rk2I}QJ`}J*5?}LyE!)IackdE$NQ)VhBcJ?v;krP(qw;0;)Ci)d)H31yv zqbsb&KY&rG<7{!=8M;{%Qs2dD{IS~wpn83CJx(gEjre!xYHUbq{z0VqPti;IU;`tN z?^k!y$)E~HK}Go5b95}p24i1M^ z!qrdJ4YaEr7>uCEJW)OkUQ@AZ8*z@H{1#xO%6^but)1hrwVt+vHI%H5uhCzE4K)*K z=C9h<@wpQ0jf`w+9PsZ8fC4fGn%c<0#h`Y+%qw?JeI~)cGURwU2D3Thf;2|bHMni9 zdV<<9!~KH*sOd2(zs35Ueyua=vvkr;GP#c+@cQ-!pj1t)+HMiHbyA`PX$y&P`@W|2 z?Xs5}+nQncz*a&o?GO;s`cA=kHsUWhtAk=~nH9h(0dhw%?>L1+uMGbGjwJTjaSDsA zChsxdhwQkXmp!p-iTgykS%o~)E);-VV?8pEE!ueYC*R}Wx6#S{r0+NcG&;|A!bZZV zXO4Gu;K5;bIL|u&X@F9DIO_8_nF+_k{jC171-A7~meKPLpSSr$TigS(9d!OP04sIA zOrJHvpOFjWXl09<1Tb~DzRXa;aG9VE*@}WZtI0&I_lRmT=NI32J=&Xs7z5b3ftI1! zE%otT1<(XcmFrgHAL;6fOaSjWhW=q9LN$6xhg}^%jUK-K`@bIx@-q%8Kg zbpfmn-`3g|b%^rVXsa?_y`;0>ivDqJ_xMgax}}7e z9N1r5uL6(r%L}k9=AyG~ds$OH7boUIQdxFLhDEh-ubX@*clKE2jD`$l%cP*kNs~QqZMR-aWw!4 zfR?QU9kLYmk+VCzYiS++7{SF&?9Q4-Qe$wO(<$g&0c*v8&l;c-TPVto0=ylGj^=3A>XJtzhz!L3<+ey>HLEmQ&x>6gQoAn`BYrNYs?=Z(a?ePpr04DRu zrtFF;0(Z+jKvde4`~a>(#9GD6=|K{);O>T z;2S6Z4B_yt0RT%V#7z2XuFVngt}6#NqG}?}?cn4HLL31E`nFB+qGWPyj9`}6fZEf- zr=AU@BGjQazfnWRB4;hl6j-2bMn-2nEdldz+-Xm?H;<8-O=Z(^zyRnZfC1*>ROf@f zy%=OM4u!l%s5Fq?C*7g=wdQdA#`&m(RAyGmj%{F2)S~wqx;pO)G#w;q@f`>z9qAZ> zM%cvY5>Bm=R#^t-skY>{Q0(N89y^FK)=<^ix0RFCU#+C6p)Gw%Ccz092us}~p(2g^ z%~z=sI`C7YQ?X*N=+(0a&!S-8Bl2s6!(uNRM2zPYD7>20omD=gC^RDgBjjcJ^UB&v zkm*?vFj{G0P-qZ!{O9k7tutkz^XAn^U(_hlAh_LqJLZE+k5NGCoQcQ_*x0Jh$W}Lk zy}qF#3SA9zb1F*Cjqxdr&h`V?0gh3)|I?65OEo`gI@Y&a& zg)3LCM3AMiv@v}1@Ecl{)P~z#x1+MwXb|9VZ3PN!!)JuwHCEaB-ifHC_qW~Jqo)re zgTgiMM)A4k0t7Myj6Bz|4|HZ!uztpQkrm*2=p^~B{{0W${DaUvMm1jysRE1-E74DV z{0))4!`y9+1pCiQ;oAiGG9Pz`^Wi!=q>Gw&S41RjF^w)6EzO~$t({+O&^jk#l-p?c z8t*7|&cZ#admSzvpD%y&8x$1<1~Ficq*Hx#d5)A~3h;p$4@o7V`fP1obUy4ItkL5AnlW}%E=ee?1Lma^hKbIz zsAf5z^E0Lg*tVzvr&Oxg0E~fS7=26Z(*vXF80OAt*RTIEG@U<(L&3`sxjbIq6xUbf z=o|~asP1$ET}QzejRn`jx!3q`@8x4;`0v&tk(qIq^obn=@4MgsK91`^xcYnF4=K6S zoH#<>*vM$uf_f}4WHiov*ff9#9a67pU-Lp7)L1N(YUDGtK1({16e(RABt|wI0w_6v zbc_9SVU08XkontYoh#dFA{#(wcJlzE1Nx;7!yBD+z$mK;LlYQ205^?w6a@k_dO}ef z*TQ{kPOravR(}4gUxe3SyR1+!Qy`^}{kR83y_~iB8fRKIf@_;dztR|V?qxaoyYr_p z>(7<50-2qSXTzN*cOu(Ks{JrdvV{g`Ru8FgC7k!M$??b%D8{%_Hu^lCBSACwzkB6? z>c;|47Ws2cI*xb5)FeOa->WN;#mLQ;re;zDp2qX&n*HgiKMfC-9>mDRC`P#DW1Ij0 zKmbWZK~$YawkZil;Y99r^pz*d0E-Bj=Hpp*z8*Y!5R2?6=VdYY9L}42<7~m%aDU)I zsOP-8H}i4+8ta>5b$as_`|dvp<9BE?1%OgP3)Fr9Er{Nse`78*UxURnf#C|}`_1|{ zF`Q{Bg%Nu$egY6_JNbVXU2kNYbp1M2tict}H+Rb-MQ`{muR3%L8)zxnrJ>gS(@ zW3xLUePAv;|GSSu#^_qeTG@}il}`~d>_X0)yDN=fo#fDgIf1?$9vCL~wI$Lwjo#y4 z$NL55x%Ffl`wChqvduj^kN!-I4V)+qf8WuRt99D<9mN=$HS&)&<$7tLSiG+o{an^S zI>Z|KvlcooDPB3pDK( zM2CGFL#wHkp4d3nTi6+u$BCG0SR*uYOXxK{NsS4pxmJFcE$GkY$0-!XoUF~masYV9 zz#!Wp7q^&pVDr?SibA#GIALw30_fTOu6q(ZSdEQ>qn}VfKCP=m<&jP4?&z|+bU!0IMS(luXE&j zrvl!3{S2Pb$hzqwwr#7vbRujVp-u46Kn!MB1X#Ucgmn1Ut&oIluSB*O?X%#mHr_L2 zj*K{g*EQ1eHkq>nK#48tR*Vk8-o*J3Jle$3(&@VS{&&JaPk%_`8Fr~VQv~4X-l<|w z=|t*?Ials^TLQ;t$0?ge-zWCbQU1Pxu1XY)c3mRdgnKF1H=($fS64(C8B=_iN5R&l zqd2BXTj3PXZ~y?Y2slxWo;EF{^E=-O<(%!8=#U!TZM=_)>d4&D+qXj+dUP8ZbCu61 z@0YQeuD|h1*^`G?mTy&d%p2Fc@>Vn?ibUeyxJJURU{N#6bvEXqma*0gdOQFal zbJsUG81?u0x890?h%8$3&$Z9;kh}Bf_wJ8AB1o4>RsLSi3jhlGYXcB*8;7a2y(8TH z@n4dnc-WTB)D-1n3xKV5t)TNFpiL_F#Qux_BrD?t^PhzCUsOpUKU<=*ZIq+d22!sH zxT-s2VcP4L!z|~om@_;(2SWoVF$H^kYZD-Wi2ro|SmLsWziY>Ey_6!HdG@(c?WdoA z5_VXFTx9>+=mbtLOj+!T;_5Q)OEr3Avu&hTICojdyzyrQ3^z!tV_j?CphzhDVTSgF z8?=&6A`0C=py5ak&NB6FHf5Q%(aMu&TjxB*cI!Cl%1?pjgJV=@+JezW`{r@>dbX^P zmxH0E6PZb|bb~L-sWVs3#d=cN^<`m+fY|gJ0StvV@2jkh2OUr=3rBtxy^)T*n>Tpr-o2J4715f1R_4zP=o_&MBu_UAk@nYst-)FDEq?Xx~bEdUbe z0u%~hCH8e=RVZ(5z+OhCk&ZSvI>dMJg#cJ$SBJ7J1O?2^A!^OHi3{miU1F)c&!qV&e*m3j7R%FW&o`3&fD;&jV&1XJl2;>y9KPE`ks)QZ4V!8(G zzdc$FA1tDen+fKkTjuCQk;*(}74xn;Yazd$U>$nsTN?rZ`E~*L78wA^D9%Nd4#r+7 zktQ9Tk=u{ict|RgGAj_$%W`nw$Ol1i8~IjPT4|WtSI`d^aWcr6CmLd5Kq+bIm3gsB zeM)snm{^}B%6-^RR_b15eq}hG)f#%1dcy*_jmfj*5+#vqj-g}p-RM;r$jUm(Y@oj@ zWMJ@|Zax#EaQV3?e;h&cL?1!bjIAcvWI7ZI_&i#Zs7y9NpfoBKEDnuPol9xe!wbW4 zgBp#r=!wp-2Jg$Bm$BP`k!=5bvGpQKI1PlJ0$g9x`xM(@mI}=pvld2ltSzm^0)olV zxehp_4x?o;GNjFev)Fi?io7T+sftFS9^HNr1&qetu{83A5Yh`MBdLuk)%hXoZKBm3 z)#Onf2``>^QF=iN8|_~ZqE%Iu(aALmuJbA#NylOcf$Wevr7`aNcwM7|b5y)lF#9tV zqD%=LA026tW4kG6#OwGQjq`f80Xg4!Ar{~pz;MjL8PORp%LA2%ePESg53jLXTd{_wpSrAmje=b7x!5M(1T@+z2C;Qu%&EZbO)$ z6`tQ0C=ygsNk|Dz%1Vk(Ol=V@-BQy+4@ULUFTajwVjfh~`#a}W@^%OU`J6`W-v8iz zisca@BYLq&tD3TF=XtL~Dycc0BmeLZR7q_;j1caU&&U0*-nbEqR4kP!EOv8owNncNi4{dL|i8z*y+{hwcSXdoOxE|^2N zjiOlMzAdLuMcSBA0{4kPM-oEa6rlz7`8r11NZ$bI6SEkvyD@t3^qX%$o3~@c&{`M0 z-`okOF2I!e@+*q?WW@ECifSDY*TeO4J#~7eCA!w5pw!2&z%U^%d|?aa%GupV;pxwUD}9G_obkAi-3#WbSvlUd^gNkAX2CXF7s|%5HKBW72iQGn zB+Bz4D0P|ICd)gA6^i}2XQ{cCoKGSarMaba@)!(PIAbo`~o7m{zjyhmZZ ziW7jgnIR{cD*tQb(9hu%K!Meu^PFlx={PF)G=w~h@g7yppx6{|;(j{nh72rxJqqM}AJQ z?(2L%o67P_Q&hhuFLSbIBu4DU=_b?u{ntb3+15}26V0MgU6bUj9yTo>=&V` zq%u4keiAZ~wNn)EeEiAR;RI*=^Z)Jt2vsS0p=@q1JpNz)U3mM<)iCt+^Dsk7oNR-A z6#oiUqZ2*amHS4*1ib`n>oHEG-Wwed@O7AqVSc5>agB7E>ahpIZWj5W(JF|ivv1)l z!P}yW;`qHh96|x=)mgruh2_UR1e0^CivYTyVz$(UAK{dd4mUiC0XP-bacWIHTEnqgrf^s2TMQHTyF&AY*TS@g0!PN zhP_aV0on7MymHpfvBnv!YitPP)<+=Xw~5^O?g#H72RBGzoR6#y)AynSPCt9kiY!b2 z?$G%!t;ZgNh2TANsr@iJOr#FeV+orp4JXF)qN8r~&e1?bZkQC2%BI@5cUQTm4!}NV zE{Qd=y1KGp7pL6&6cQ0LlDE4K-L{m1ZrF3mu{mUCQ4JA&0Fxx_lzjmnqV>Z7u{u%$ z8$MSAdbsaVo;ph`S&gf#T?#VA_Or?vqx^!jrJR+izrPJ2k$+gv%8N6N?(LGA3jB~&zzNnaNx)!%2=d0x7CH~dSm!@IDZKHWo1q_>QR|Zz&cvEb$`JL( z(lm8}0HEG{>w38VHSJe9XI0g-NgJdUvGW38{e%DVKMSJ-0%Ro!s1LJWWNgWZmHl$| z+O=@^tFHjNE5jT%L>gdvI_p%!99VlMc68!*S!A~1T^JmSY{3!&aXr|=(+?hm5{d%v zq9ay$r(FUiDg4=#l`U+L_doa`vP!iTEi719SI4s)iNI}w9lHFI8dU6a<+?#Q!G&Y6 zvz+5qbmaLruSZ&c1m@R?@UjP8!+h+}lPAf+S5|Sq#^$D&z9>7x>C5JROSecrWDA$F zPi0^f}<2H4gB0_y0N5J4#H67~1iG`aHF#)YuHhQGQW3L5G- z=dcw4i2|V58ZwSzP0`s-0g%duiLr&fki%M}!|>Vw5ZeL-IFgyo-k@+ZHvAIbT_*r> zK#sqHyhf$}C2F9ADk%IooI7)e;36A6>I5Cgt?cA5N5F2KGn$O8vO9JN%o)sDBi+j= za>z^xGkxPBr=0eC1P!C(&kR&I5=hbMCY7O}sWO7%&desyUx3`J06ZVOOC1I3wQS?_ zn8sGa`8Nf)h%>tQl6TBG2KZe^jTZEiekx3qt)cmF`i%<|l!Qr$J#IIr>h`7x9F9DD z9(H*D!25)8c*Uu^QJ*b59t=5v=v&lKa%{6tc9_3u9ctw4EP$E7kcDVXxpD24P43Zr z?8H^}W|_7;AVCYiPogh(9^;$gwA%)|g`%=DbuFU4i=0XV04N4f8sq$Kb10);fkEJP zyI!#wPx{kR)eMzyQ{!9LLP}{)XfEpro74pO<5Xda6=?L@(ryFvvkSGNkg?K(md86&_V4MtD_x0tNQHf60cFzNk^! z!tW{yBVVUFPLVhIDBS2okk6A#%KwrvqL!h0PyON^#tbhy5_-5ar8 zO-FqjiXk&PNEX{sai~BgXWo-e@I3Eu6l6L%n@A#g z>vQbuL5(1;*Z69`PqO#1qGK+8Gjrf~1yG#pT#R_-y~vGjsvH$ z?fw#&@qNreG;dGvC<6tVhqA0Jr==k8vBepg1kl-EBae~qjA0;;a8661Bf3wESVQ;l z4C{XJ%9Suo(I2Dp^#E6%FN+`Ex&2K{@$h|0nrp+*2CWOJvRih%E=-fh#(|6T<9XL8 zxpDJGc=G5;Ov@1%F@{3n0{JqSRlb{J#6mQ#WI4%%0Jg)Du~Vd(-_pjB%+a-V`Pli5Rk<-20y4v5C=8mR}ZzCWm5;jS-M_>ju1c{k<4nm_(NS^cVjjoIgc- zx?ws+u&4S)*=K-*Qj<0Olzq~c1yXdR9Ri&iZe5(s*(D4Xh7oq>A%dAaQ%79~?LDEn z^Ne$=bCI&y+}s?W)$`E-;Bc(q5UeysNS2MjVRd13csj;DW{CXDpqfvf3-6u$UYMi% zi|-}Fz|RYOynOlMcj-7oAo_xF$^#iX8ttBI<;cUQ52EpHORO{HD0>RQn(Mp5y5;V2 zelc!FhcO^9LQ<)H(!DtouAX~`zY}H7D<*2WNg7ud&M!UVr-#EJj_=O!Z0P^+cG&v5 zI}|P)gz5Vj#CN*G%O8Id&-eI?!El6#i|tyE!Y0XPAFGQTc}1KH)_jHtj=Dt|J~7DN zdo@m9JVTpE3V`AyTIGBj-FOVc!RVf~avCwr7FG`Hhhz|ekp5f9HO%ineU?J5kGr9t z8~KNdjv<})|YDRoC7WEIU`<6hmPwW_sl880Rm)jBq6_&QZOXZ4HGbH z>R|az<8&IqrWFV}3(%iYXT*wX-09HO3-XYK)Ibn)As8BFh9;pCa}T2a2S)mF`Wz>a zHG6#Ee?`6Z`D6m@GC$^m8r`;rLmtmK@SKX;6j43Zc{&1J+j~%U zp;t>;l@7a$6LtWAU|#16>uz4~I)Y;!MZ%ZpHr(*Tbr_9t0Q75=p6DRxG00l5zf2eKIUK352r_UMa!J!uZb^;Tp+<>>rj8bv71Ued zUOIqBa8i06cg5&@L2+TMs9psiE7-9@zOcp8jsiGl0+i@@8!29+P?pqxfrbc7#GCRT zuCLRn^Y3$)RZ~D2S+y{I7%ep_DQN2&_&$3$_<{r#)s=Cs+fJPbvlKXO+|d;Q*5xtw)*5pnb58q5 z9koxrk@AjaKoWp3baD+&Xd^B0lpo3HCS{qQt3dXRAhXht$0GzR)PwI35&z=jPhuBx`<z5a=9VdhpBX#YSZ8aKb(7_wqqhgh(oGKf9=5h? zWC7TBKKNmHj4ig0&dz2Yv|Eoc*GtIFBHmNS-5`hs)IR(0LsH8QixUc@m!fMbu!W`g z51`j~(B~a*y&df)bwL{S4BD{W1bkBoE*Jp#>M#Bx6yT^^bzM6^J5Z3>dO-d@hfXTO zPME@Zvdh!(Km3N)e=T7ayQ&_$u>ogqiU67b+WO!i&Mi6zTSSmQ8T}+9!FO9`UzM@{ zP31F9s~26h^0bSy-x?N)@U8*QS<$}~29Yg>)fu*F&PBE+_HYIf>*>{{2s-Q&w6rC+ zsZ~eO*I7r>i5eZ4c0P4;j9z zbI$565UeP|Zbqk*cF=nI zEUBIZV*r~^cM_n2g|ma5S51I=iCRGF!3-);X(&PsQt46byQt7sDcV(Y`EEBs7R+dEZ41Bs z=-07`PD_1jSRsmb`eY|YOHyxK6nkQ5^qT9uS4O|)@16*+{qy%@pIakO&v>76 z_2NASMANBg_;?NJaSD^; zHS|*MeGxxzAvT>Tl~H3EIb-8P@tx}HLF^Df{o@01S}oEc6G4ziM{ja^5;i~!a&134 zlU8=G&8meuDpi@@pBPCpEG8Fe!NdQ|N35)JjYywh~H1p;Ez|`1mMne1wj+f_`mw@zY2qk z!;xLkUU-Tkof!AU2chf#{!1#(6OF|=(U4j@vKy*lh7_HF>dm{%bABFu{8c!ZqO-#T zoW_?^;aCr?w+ zQal~`P_X@TX>D0dEwLz7c@+hSa2zwTar|My=#ULxB$P zKE`U&7P{MsOezq1el8|drB(2&YT6VbWXkIX+Q>bhG2-)_~`uejJC`= zl5$v(*xuv2P=D1grb5)$li%MvNVWG4oDF)O^V~<6t0jzU(<4^_XB@W1bB+Zib(Vbw z+Xm*d-WDyiU%6n5&*ZPjGC*$S;|%)_&gYHqycKJ{=sXJy7?_BxG13|AEM(0P^|v63 z>6;GgI4xk4IA+ly7EE4Yk2^;?;5w~3zScH~pab7)z+iVD&5}mo_3RSkoOrKdbeivJ z<#|&Xq=B1vFYq|{k!(CP-oLZdq$RJILScKHc{7F zyh|B2)%_eM4FxWdJKIF>!{p&U(PoH66#cgGK?H&_43p z$V6MGS-U~!y97DuzMDhdTlK#jT{Mo&Z#~-?<+JkJZU@7keoEB4A+DXD@B8GFsM`y9 zzS?$zYP_>G4wM7hPcp^?Cp_;u?N@&AeynZN^>=?CX0S8WozCerdIV*_`xEuW_K;QK z^%t3!I_{T-t)Pu;ao3KHb^ztRP($!wh5c2?TI`_zl||mejz(;fSY%FSj0N82iE z@iqG?x`;VZ7agPlE|PY;1u&uv6_hpVYzuAct85ct&w>7)2C&+C>1=p<=MId#j+jO= zEkldX*o7%GjZ_lW?Qmefvu{BIBMp2R-(-ukw=;!oVx10l_oMBh&f6ErL_K7{Zm6oP z0koi_3U-j-$1=46!Zc@-kwn1q03VsWD2f2$9CFW+Y+9vmlFopyaP`_X7#^hSaF%m$ z{%4UBJFl2T0`uN84aeQ0nbXL$#s+FPkg`^#%m7&3!Uq$mm7ydHsFrk;=|O<>bZRzb zX5rLMLdkCcSmK<*U{lvO)YMb22o_5F$;hmk8XQ9=rpFYYoD6000;#8mJ`EHs<^#`j zaU~2tr+yg#-r^7pD4uIy{fHlwf-DiZ+5zlnLEg;(1ZCixSnzZLhD5BVBH+Wl^8i9+ zlqO>b+lJCLSfTnq3mNKoC&5=ij1AHsGLi8+*w1s=x~Bgq114ds9pH=?<`jhTeEbc9 zs9X3?n*b^M0LANor>8r3FP=4<^uA1ha6!XNbj${y5sY8pdI#(e=#MC{REP(#^aOb~ z5vJ@5(|xSJvJP;(yR;s`rVaL$vNj)9xdjT{kFq?n0cEyH(^GCHp@%aXS>tbML;xW7 zO52|ybiXwQzy^h|+yF-NJ@^W}SdE#DZV?t+fEo3O5em>|72+P7z}~|ix+IX=h=_Bb zpADGJ5Rf*3*>fvPeJGL)1FH9s{Ytago24DhfowoYLb#6)}- zh%gtR@QcpT_KixY+fV~l@|~wnM<=zewl3!VbiJTu7RHQ%%slupoF0Xk6~Lc7eTpHK z6^$J$Qd`hRgIz$U}GQn= z9x6p0e~sw}4<1CNCsJ;NTc=9EMle7@YJTyf7mq_u4Mi>Zd3h00KMSm(0CXV6#;lOr z6hALJz}AmC4uA5UKM7wx{3`zZ=9Qbswe=w2qVuVMe9BzwTCY7hVk$2jF^$X}s)HM!!V_!^2{^Na!>7B_LtEXrg~qx)VUCq~wZoG3sa-MUR7p7!wc z_I>)huF!(4by>pYlH39^ejMz^-p@%Yi*?s80#g;M{ zpw`ULI4%QmO#+!V3OK}`$mI<8K6yekk%BQet+oTK#84C@^PGAOnGdTtk~8d`DSoZ6 zSHJtiA4V#>ZInzYaqn9w?8V*N;q7Oj=M%waBl;{@OW*EaM~TA{Y-mIDbO&py_oyiJXaNH@2B^|F^t6LfB)-n z4kpRN=TAX^p+V*n5d$z1sLJHM=7{`Hug-*1?ewBYL2D4V9dD!1S7l^*>`@m&1GJ;0 zBmDVie;$$xNOwUd8nv;ArSIrjuug#UMrGrIXz*S>dpXQ=mft!5PUsr!B5F*E6LM{6d@x3OWWAU+BzWVT4~`8+V{{H? zfWV6~(DPxHa*dHXo<|mt`$uC<8mG>3eO+B>E@?hwHW1aYP~yt|3PyNOsN>%>y1y_* zi}k(Je+Pq&)Pbc@WY4{5P(6A2B!ZW&lg{XEYJvRg>;GeTJo`9YK7EDg5XSA^LKs07 zJ$n2oe9-oX;mbup#PW+_XkjRXUit;+6dy(p(UPkaIO;IM?ZkI>0EVvPvUwi3p&;EE%3L zVy6tKZG?44dq!Iv&ae;K+fG7_r_dtK#g)rfV;eLJA6Y+VmVIj!%r((Tv|yQqc(*Vt z+o1Ids=EJ`p`IZPZugbv*k^EUbo>*}zl^b1pMbq#jU8oC?3lrOo7SRT;96PNM7C8d z=H`1Q0r&#~n36M%&a&6E4xY6wYO4W;xwm>wMu7!^eO{e!9VKbm%9&>LhV4~lP+6o- zmXu(EAf&*BmDDo;SjR^&92wTRaow!@VFx4a0*BR_tzBUccCRV>&ig7eWsYgg*45O- zt|6(&Djm%8=P$%uey`(j&W0%@DEr7Y@t5oDP>yIPnLd<`U6D*bQy)7Arf#`L7K~HA8-4ZN^RU01XTd<(Nk*z%A4lAG=n$i# z>K|EV8rwS2w!zcZ5O68sd$tSqxpmZCQ=eVNkOdF_>CgreK=qk?Zk<9?8Fls@R@xTO zwBt%l*CR?+Tv&{42kY+PV+>+yn-JOWzW+2-M9{TY)0?RsVs{OkSOJw}?8-&1@XAJXzTDqB|JHZ1?W2qX zN20SuWmOe6GWp-gN$(>7W$?oH)z-8-O%nfey>__v#VeP>!`ly{Z0PImjdSkxbp8#n z#1vAUNLp#_Rn*_wQa(_QMxAp?eNA#%$ zl$`^iiUam$WQTEX-KR#N)l2KlT?YF?xjzTsz(oNcVRSF z`q~w2kT8QC4FgJ0%C&T^mjz&v_bWJy7S5Z(*)1SqYYKp%>y|PPn|$o~6LQ!A2$*Ya zUyEof=d4FGIymf9AI>>;+SS+J2qOquZ6Q zvPIor`WFIy%7!H5gy45#SQy)RR<@ebtq-D1k^#ULjzj&W2fRyAvx4jA5`3~4^&&FK zV$TMQv=KMC$K|&HE3p~(kRKfvaoU!f$Q|W1VdnTw z%BzV{nB3@j_k=*Ub+8OLxTdBVSunkTG;u*C8Bsp3deI?BSi_!O0?6CtXYH)5Dbu^` z5$nhZIJdP^ypx{^Bv({XbdkNd%2{X2MIGz;HznJ>{Pv;8-4oqWLAF3=*RWN{xS`Iq zo(mK6lkxpj*pD7Q1Z^Z2ivuW)SHom-6}lt;W`s}&O69L$PlF|}O)F5@kydQEQcY302PbFExa4yfhZx=zZA} zS{jdsLKJcTK!4n98ebX>R&uRxtP5X!`FS*8?Mk47EqZ&l`D}PGfKuSk8uS`@3Sxh0 zG(>@mpw$>uq5A7t_p@lM=a6t2$OIEu#a$r$jUcwG%Zb9@>w%A7mb!)KI^f2Qe7`1L2hjuD01Pj7{DmFL28 z@?oLFGsS1Z)8VJlDKU>t=S0OL0$f*D7h5a&XO*JVIPcfO{?lP`PpY(LP;L*qA4X8a z=TP}{w9?Xs0wE{Mpuiuj!umKJ9z1yv4IdHFarQ}5F)1uN2lG;#_Uzr6D9!;yZUedmgU6PAUWn(>(YA5NfOU3$7S> z`0^(|iB)qoAQUvmGHE}B5YIfC5e28!XrxxgXcqw52GNg=g_&^v2k((TR!U?H!3rp6 z3V;QcYy>8=lbd7RU#yvd)M0D(netBK--H!Yg0+g>LBuM^lb(s!oAl2_;D;?C^O@izx-vq zo`#8OCLE)GgzUP-vi9vTOb>#Xer_`vYyhE}zm znx2VZqzsyk0JzJ#(P(SFnO=6Y*LX*{?;m09b!4dGJT5n<0wNpeMx$EF1nUC$`=RlKKD81xQ3xX|8eQ(wVZh65 zz=o5si#9Rjc1bguf~x7T2fE;)GF;>A(1E0o66+yYq+E?Z2UVd}WV& zz(30#OI%O+trOrravlAZLjN@)A>K%d^|eK zrpCy)u~v_AL_^hk`1x1`n&MR&xG>Np?>l`WU@Gv2|Crj-|RFwrLUZS4bH5r%;>DUhy9#D zh0mq~@9)ZI4SBm-*p@Ip3uj--x#@^T!~LG`BuJrAs{Ts+-Bwkuk!e|p_cs{h^X~KP zwhGmT@H$3<&!a!OySig*GaWUrsqC<5tM6-Cg70PPGl9DaWURyIkCAz)I z-h?5hgDHC|&N-hK-0?YL3trBS4v}_|)z{r;0{?9O%hW>}oLPtY$?8KyF;q_cQzwbIk zr-18Q8^QhNd!J+8b*x>>rsGZV>>17XdE;P>62So5tO-0gtSMod(AWrPnsIj#|VNATG5uH0S&fbBq+Jo&4?4J|is zL{LhH+O?lV_tu|%Ee0P}dV64Fl>%A<*s=~|FSeW9Q(Nu8K3B9KZZTC!8tt2-m!weI>pwt0`d{WW8=c&--E>Brf7 zu8r)o7CIm8;&g5zhllPEJRlGw807x2*kTQKZ^uc3bg-eMt+yd(l}B^0m@R4S!7W&O zX_cj67awG63RVi;Pe!TBR0FX8vik+}_ro;fINAJX3(XQWhjYS{?nweiD$f__K1gojJE&Qxf_jaUKK!oClvteGug#XIr^H z!`{`lF#4|T>fGz(CLyn6k9y674EO%(aQBzjQm-hB1sV*@{_g!@HU*fMOh9DQDEs6D z?js}4UN|3a{p{zooCI`1w(es8ZSbsh%`NC+s`?k;xD%Dv-q1Gp*%8dqnRi}1Q|ZVD z<$>Z}nXSwd*c2?5$s?faIrVwmN7|{%a0{ecm{?uy+4l?!V*45WT4kv6-gg{CZY3k9 z1d`(o_^&ptbMAcDPTTo)J(Nk_%X=t`{EYJ1+8i0*W*fl$eTo2*0`P4D0P93V%yai8 zRgO-UMxie(AmIEclthVAp?u^L_0;jPSFus{1L*A@5Dgpiqg5oL=Q9*dSzII<{MN;g z0{uzq&U1ve(V$f5gSAv}ug<9m-Oy@_Hc{XlutN~yl@Mh?N}KAaz*rVGONfXOX`h$} zlt2)B4L8V34(gMxC*jhGOE3g*oN!t#ie>S*Prv>wMzG>$X9uN_+hx^zhX(lRhST9m z?~`!z^v$rkzZy51bajiPh+=7&$^@t=C2wxlqBXQFdo~dEXkF;Mh*VGG?AV7{x|n&A zkbDjuz;wV19SEF|e2VutC)?0W9O*=t3P2}CWg z+usweouRc1730S+Y&FI-z>IVaV{E>2>AO(1cEZzM*DN#U(kBGP0?v;ISf)Tt3HiOl z{ZVLmkfo36JZMC!q`aSkMB%4_si0S()YsQXTGQ9}zK(ritMmR}+TJU;&MQywJ0KAl z01!kVL4YJK0s$frU?#;VwbW8eJ>5O2ceg#|aygW%Tssf0^25CQ$!~tLU2A)4t9E9~ zGgCFw-P=iONfae92N6sFLFAlsA^`&Q?{_XgZSOpfPB#VM-Y=Z+&yk`Zlf&V&d!GS6 zRndZe{qgk(j}igb(NuFJ))tW9$P}upYGSdn_ba|n!MwCl;bO_f@bj;K9+5af+?JM> zNc1X;*rT4d(1GHnU@ECo@KqskU|!dh~GN{R5Y@kVel8KdrL9 z6JWg94=l zb&~1=c<;n};rZb6C~O(>?>?WbKN(uPTJhEZKL}iUwEX-f-UV@5 zc=a>!>3rS!(E1$MV+x5@-EqKAwg%>4oq%L~Q|Cp7g-`g@0+t-CMW9pZ(EK zLw(KR*h*0)y@vFgaq{AN@kT31`)>DAeD;|yX`Sb@WTpxddKNt|an*DyTNbK33pc{9 zeY5)q`eX0oBN*LQNINLoMzqjCdpL9KY}~7V`u)#C7IjdzDYT3Zhqh;rLf`W)iUr{v zMe$zvrZZG+(ngOqb@G5X7O2%SPZ768j61Z)S|GfCb^zgm$?eERF-C|q|8NB%#ynev zA`3zG^z~r<-=L@$hF>C@i1!bTCz?>Y)1FYnxPL`0mEiU2nfB#)BQqWbKUK&a_F)#*FJ8VF`uqCh=ki_03&Icw*GQ!xyl|3e z28-9F_l^Q&z=Cws?llf+m;#NoTLo3RA`EqPcSYWyk|I89tat9d!+c&p7oNOVp0B{? za6f&P#%62&SkPDgDJ@q}QaF=m2}eFpIvk@XxYzageuc9{`7tfXR5f8w<==2#6B13Z3`O z!DHNC1#xM*`(nh4MzjU$UF2|1-8eYBU-?m5q!Cf0iRY|>A^-5*2_7qRX+%<3S5fhN z5?=3mlqDR+bi-I6LTJy4miU|@a7bQe^?SX~@)BuwH+YaZPJ|7k=3;~xaGQa=`ryl( z_*_U)y?Q4Nx4>C6yr9HMvoy%`boaz}sx-J~4vpQOyYq1k^PH`Fs{uwBanEfzE$=Xj zR5;) zg!%4Y{WcUM7iiScaG|U!UwVooq`JB)?(c5)vHjCeDQ--Sl#ULfnud|1ndk5BP*VX1 z7ET0>UgD-HFoVby1B3mvSv*WM@l>Qu%An(KYW(cT%!zoEvlZhmh45A>rZ{ifT?Mtl z5XR-fo4{}ElEH>+fYaD--uw({zWKR?kRx9g;M~)wf8$qF_4bDNzO=vnfFRh zm1Fddk977?co~|AJdsIQ_$u;!MZuo1b&&$7Jl{Q$KFD)DFL|j&6Q#Gwkj@EH!f2xW z`&};184Z5YB8~c5`aK`zx+3N)zBqh_Yn4{`d&0!w6ti*V(1M(5aa z?ycxpvcTUwH01^GG)q*~Y%4{>NtY5oqZ}P+7EWQ{NPKhNm8n#OKj)Ab+Duo{nCg)3 zJEVVJuMx#ME=C`&F-P}CnMot8MUAbKrOuS_&_v$x8FJ{fVPQSu!?S1Yk&mcP$+x6S z$$KQe%G2tEo|7_;xV_~-k&pUr#wJ|=3NE}c0B~3y;=lAih1fZmh{MGufagXEL^1`D zSPQV;3j6+Q$&3Z^U=aRoNUg)F&4!I6425C>A@$BlA~vbO4G>r%as%KNkjk?5h2hoV z$V7VXd=p*{QP2kBnJ@#125y?LMyPi2(L+k!?R?|JPOKxq!e}iC02K z`vQ;PJOAtd9P*A;g@(GLVPX-(fZ;nZ*Q1TpAs8NvkF3R$BGXZ*5TKjun#0#OzYae= z_S4Wk+Z{HEjF7-;wRheAUdi70doo051-F5r0gNP#;mY+Z(E@oKi?2CGp1s10&ld@1 zs6gxce6PespqHRrYQ99yFG}4=H&GVTk*LXRENFME;%K;b|62S^q;@{%>dpndlFms% z(RnF!mJr6fNs&oIL2a$3QuDK){45sNF$dEkXn*|SAIDS=@9m?Lfb;No8L|SsNV%Au z_Lv9*R~}u7-3Ao8gkdeLzDr~uof(Y+!|BG;VPcj7h|EPnM4@MUKClZxsls@5Ds_sS zck;$jydShb3R`IPk%I@gY-4-0h|0`W9#tk+u==VT%`XuyPtL2BeDPzEJf*b}!t{%Y zc);MrrbgV5kh+J?&3*O#tKh~uLj5NDpz+K-^O_Cd7JxcE6ucN~ zxZZ9(T$r~aW3c#>RiEd0o{Vgu3jqk?dJ-kVKFsd(G+t(?Z#Y2cYcz5p>>JLiBA}<( zu)ad}WhVku7wIGl00+L2M+intL zK~ccr@bwp0!oPa=->{y&@q7T8DD>!AQTcQI_Bj5Ab29H$SQ6*lH}S;!7BajPOjWOp zjH@P96CPuT)#xMrQ<<09mB1+5I@^fCAd+bB@$hVf!gRp45h9+e0*~_*PRfgEDarr* z%oGUU*>bog+`4-UFMe~30`gklXBe$C$6?{oB7|y%5DSZ0M~2m-?yk>@iNZB(e+jw=RZ&SpO@WCz5$wwZX2{S19$*>ai`aC^)7nX6rys5&>m-|!u zNn<1Rg%pqWjy8&1?m|F8IU`bLkd6T5g!!*gN#6)Ab8}Vd*QujnzIi2ilzqLuXj|#G zlpUaM0j->3>reF%P+A4SHJZ<_kZKg0sX=T_tX~uJ@VV3~#2VN1fU3Z1kWiUdd9%(( zGAz8c{UC-~j0h85q=Iate>il;{gO7TgezdlKULzSL+-P*LR?nS7q*4jd1!~ql<#@_ zop-1y@l6!+RFECbEfhV24v3=)feMH6RPo7hZ#|pByudUGMmzNN^hM!SBU7SWN)H_t0&_i%!zd8Lgnc^fPUJJ=JdrU> z7f|_E5SGU4>Gm3VfSw@3P)%PG560fCqila!!n5JAuF-jEoUrYe&(JWb0-qRK zib{&&=S!S#lBVDqz1QoUQvo^r@+8+A!~C5q{~V?VI2xK7BHn8NkPfL}s~EeV4vj8J z*9ret(RMz{VXn_}7w4tZ?!7$D;odbgrgN<|Oh;o7^d-KZZT0+AP#vDJa8XO`8b9}1 zy?nxPGUQQF&VybiLoc>-(Lmw6HI6zw^T=G23;hXx=;@BR?ChyZoXWoj7UvF%Mk7E| zb5q2NZ*S#u=b=(9yl61>`be+&E`gDZ-6$J{ROcq*R0Tk<{1WF}j&Wfc1NRo_VB4p^ z54)j}@;v3fufF;!jI`nHhrX!rnCHK6`Xu(&XsK7Bf#d8#rM>1JZEbAHl% z@!dUBrW6kx;+Hf~h03#c?>uLX+(sPsboIo7v|}hfcK>)uM3SQr$I$BBO6;c9(9#gk z-Wms{rjg7Rmf=mc>`(vmPNFLcB2Uf)zH|bK=lLm8)tHO)!05i07-6zm?@=N+oSXAh z?wNq+7$uX#JR$lq`cRnbfQPIy*JAjx`>Ww(9$H`l;64=o3}h_fXNq-fOQm9Jp5IA} zyx*D#!hQz0E#Fys1y4lA_5A$1`Q7iu=-3H(i#4NqA3VStobDi?q9)Cemt-=hz3kHn zvhal;eiS41HYohJf<9pD-WPA$Y^KO{x2DD-DYh1IE z5U5R-wPPoRFsXO3wnF*=#swlkGBMhka+*t_Ila&tn>04&5~wY4ZFE$c&Qih=yo&&77uPe|fJ1iMBCyy1c4wCLQxil00=+FN&^gp9+)3d=)PjrcL zY^2}dsr1P?YBbY%G(m)rL;CITI`Q1X*BW9R)@n#-qBKU`NSVs>@x3ai@?iJA8Hb1b zwhv>CG|un5$A~xaN}es>_sliAzJiwe48K#Z7B|E*E{ppq1&Gh#r}x-lq@cbs)KT1h zj3}!tp0xv7WCW@E@{+UF2(*G zoy~c3AnS`%eC80N8z=Hh|w@4S>0)ebM8m zK&bcDMY+K;XB9dbfjMEjC}yHyVKr9;7=;|Y{(ip|1!of__Z5bKv~?*>9FLtn6{dF( zc6#Zpkb}?_g=r36FHz@Mcg&x^hxhCNR@kj`dXkk`>Eud9W;b91Q`JQl} zit>i2M{5)cin&30ne=)bE<7CiC;FmbY?z@0MsJ%$N<~kAn*`bX&Pt~WU&pGB#j4jb zCxsim9Sy05FuO1l!%_`Xef;!E3>!0qG>?`XuW9{ZQ6fjn$)jO}0%S7O|AGl_6GO@tWhb z?<2Pr@5%t4xvQUj9-0u~g#(ps-|aK?p!j|f_t`SH%sJ=_(~QH1c>hVzSb1Ctcj zfrt&M^r6(~?N9BmpckoOG$_pM^`Qca-mTJGelV@jOK_ay&;E!y0}ro9A=-8L-g~Y0 z!a74nYRt3p9#N_NPze!4xb2P(_=A;!O+6o9l7B`?)mU! z>TwhdDl03a@)Zjp@@!Z|47vKC@&}=P<{A0?M<5_n`0pGIqf|9@4-MN_sZ@Y9%-yJ% zx`w*w72IFGKN4ee+t$ec+m8Y=+SeW4`{=_MU7&!ywzNq9@N{ItI(t&azAGq7v|@Au z`?rg85C=4xMNj12yR;uUM*r1AQRq~OG)HqEdG|7U4N(gaxgu&593%YRC=Dymesk+4 zmfPY;=Xd}^5M^Luw=e%Nc6jKyhW)U(We zA69S$7<(LhmbKt>b@FcJ@fEOqP01b?%COqqW7K?86Y_tY zxgK(9rBM-QTFyqVvusc6z3^{3(oT$ockkbYPQkP>_{^=(#WqgDyG-_Q#o<`J8nBM% zVzh|HOF@7DX-!vi-dEQZ`&Pq&aa1W{?Gpie0GGQ znb%?DA3qN-f7cOe%MOHYs^;4!&Aqbyr2U^0@0-Gy=~-+l{GWV;Z?%{SFZ;Qp%o$q$nB zFTI0?OWIjOVMF0tVL66Bb7tlNA0&cDIygKy96jFdtwXPn?Qh2?NMS%QU!iT@?AT<) zI|Y?8Qm;H0e^)^gPvyVzLqkvXvKuDpfo6h}?umG{6`WHUHdkK5frbQ?2o+J!G=XX7 zAe<&f0O_a7gnZU(d`}Xl?{&hK0+T~{w6K+)B!^0^^hvmtAE+>^w3@czP>EFe^q=d{ z$slh|j8gLSTQ_gTYyFS7=TOl#f>1^I#Hkb9JDslkgV64tIK*XhjHO!^1=LvYn)Q~d z#G95P?M{pr-lGvfSkee!F0x92L*?H+NcPBQ>jl*lr=aPcy9T2re4cycT78%BmkbRA zrg20?oAZ(Wcs}Bn`{G$70AE0$zw?jxu%GLkrF-YItuG)>n?LMa-DeFAwRN@85M-*L z3bVPb4(BXyN|fgKA^$l^s+wW&dIjCJ$e*76w&nw8Mh36ten#Z zzkUhbT?FqeNT$WW&ET82H^Vj+Q{}tq=aY zzX+`;=5>c^!_z0!O+blK?ka$Ws|cD>agg(^s;b7|mlNreMlsJ^TBX<3XblzG8EA#P zTvew=1_X$2Im+Ib3648;1TF&LfY=2ED%)ZL?ioHt&Et5F$=Z6I!Akz`$dH z#7x@KjpI;AYHjHttD(!7t;l!o!Ev#HJP5vNfc2cxG!OZ3lXNCzfxYlU3-3j_VQo1y zoI68wW=5Fl84Bm#z6c*DeFB;)5!0ynl6_jRMd%C)G_w2(M&U&a@+W`%QCOtt>=q0Q z>yzndXO(AbGG!N1CkK9CMmpKOU;mm^VZz)eC|1YwVpIu-?OBPJ?vKOs^gN`qI{1tl z_HSW4QT~;?{aYQ(>(sBTL*Y7AQhl~*G%C1Wr%V=QWN<0cYOd3OU|R1%!rHAZ5~ER| z&FT#*$l`><=V{=}$sy$#obsPI>3)g>>K;WzR?KH^gtn)Tqfu$`YI{s|b)KWt7ux~< zleSq5bp_*~1tT}0gWI#vZ7_&vbanmigApX|xqr(i+)ID=ETosNR~lv1lKfKr!RR$V zGdj!nL<0zOS7-IQ$g_Z5;mUW&gQS7(oBTk7q3KAIS2(rnAbr8Hl)?057#97JC`-II@^ZpAkMD&`fAnEIG%L#5La&OD?t$@v zNOaoz+QLUIABKJ^M~e*Rsd-=#AOHk~EIrJXm6fqIgr1Mt6~f54rm_^E%-oLmtB5>W zs}z$bh%lk>rsezW;j?rcpiKmM{9A{}sV7{>F^-p7E2KSull)OX&&eaK#wwlksTKH2 z5lFRg#XL~H*AhNT*r}oN8+e*){`E&8vwSyR%T+voBVi|&$&RjPQP?xQF?#!Nkn_*= z)fI=ZP8NnQzWyS-LrX;aWlLBk1g_iPMV1q_2uGwth!_e}8Uy^-a-b#jPp8B1?SU$C z_rWOc!&rX!lON*^?1hMoMukA(L;^2Do~k_^ItM%Hu#v6C3U z-c!6MJi*d_;`s4MKvW)7{`2!NV8G;j)^pmW8K$FwNw^bPW#oG3RnYg9ltv|JKhI9W zg;YQ-n5I=dMtIb~#GgHgLYBlZ8hO|ky?dsYJbCscTt0o7)+lqKd!RcqHkF(``Lv$d zplB264VyWe;dH|pl+$!nf#LQRCz7bF1E*KpuR;_F-OeYkF@IYay4My;GcYV6lq)#P z@G^49e}eG7f>5p_7?~=g5~QG`XT`AcA(S0Tv_=I>yi!nGfO(c87qC+12&`s5QT-KU}~<`-K) zMGvOL@&)fO7cm1xv3~$13`Q$)w>o_nXOgN+#jr*dNT0jNxp=>OZ`#Z;j1Ce=1<+wa z?}g=B6#gN+_01G@v_8nEfAb&0pa12*4XyVdgstShVIO5}8{zSl&(%h#l3#$Qy*bWD zVn2bQLR{2PT5y?6^0oZVaBYuKlS2NzLH=Qxv9U;r+PP%uqlmJHgdt%k}JImVkP z$6Kgn@G>I|KO;XpBRgc^y;?xPEINSqj0mC116nW4p<&R?d$8p^!N ze||9n3rb_+so71R=+$|IHLg!aWevspy1L_^3OO=^1uO14re21Lzx_Hg)@WdKAUK4iAdKH>f{PbpZ_I5_* zXiHUswIky+dPm0OwLZ^hh}WkoPK77EPa@uXwyBEBZ_|fVP88NmcREB=fcF|M|LS!* zWZ7qUCPr%r=O<2{2xkh@GBQvuTu=dRwa_}L;fR^jheF3cXh zkEt!tb|-1^q1LDOLney+R+RE1WtAakY9+M&;)~Gs_rDLl|NGw{iHA^~QyhAKd!1;G zwD8bG3d)`G@j`xQGwGqt*6=$O7YC|@);_ej^yWA3X{p_9STk=K`P~bpD4c? z0;KhcQVDp+?^Fa6<<)0Pt5k}ew?+`<2?eNrlm`Va=jXh-A84_5sRzwQ&jey*(kB* z)G90J+1EG|2kTOnF&)8srAZ3HN%*O25O*wg=vd$Q&)@mCxF_v*{P>T59O2&iJDi^~ zPOO83g6RIJ$O{`fHxh4~@aEq8&O>#i<{`Ao%cV6AzY~t+dwuY4KUWA>b`b`J756DQ zU(YV`wO8xW(BeG0*)xZR3}I1kssg$O37rKRD3Z$e@+{|OuD?bS&&xBEUpRb!26WTN z(1DKLkiUmc8Suag9-(z8~gXD4x!}85IFFto~+|wkoRpXJcsDj^2&bV_hvL!JD`K)9t(>^qBS3WHf z`3Y~aD*3lVn(}72F6Fj@gA^qs3g9IXMmkl-F@WzuQSO4*?%=F<68^8TeTws4fCj%{ z?Zx1_^;Kqp59xt>^@4x(!2T7KZ41l_lMdnX6>B;AXFm#Ge?sjg>gzavaoTp5eaIGl zL}YCtY<->QWy1%g2O9f~6g$SA8twDs@#CmW2}e)c=^qb%80leK>!-*u72uWc)Ig`R zA>NO%VFi5myJ-yG`&q}19XrFbhpjjc8lzk{PgVT=S)}rk29b0}u*&~|8k_}hYLM-r z!_uI6^}tK4;9hrt=e`UlFPw|?Xcb&j`IS#>N7mVi_j#fXxd$9ur~Ak*it~{~6qZS$ z%tBtAMHVlsBO;fMR@Jnlo|G+)LW2PdSXhc@Ao}A$b@rcEa%{m zei)Hp@kDW7!c^!Ia6Wq zCXuE%U|ungqSCT3N2E;#1<}QCaY=)rjxwDtItooaR-Q-<%HqGUve0jHilRo#kERg5mAWgCT4~z&w;&1JQaBtynL~ zjUAe$FkfkT`1pVOcToAY80MizOY86}-l<~KM+NNqAH5qg?Y~Zy&cj7io+l6GQRm}$ zXabE&(qhJ9s41!m(<{@VVShs?%r1;Ax>PcoYg(|F60!*JkBkhXAfF63?%xQhR0>65 zAu5R~q#6XQXs^(1Ui0-E*I|m)v~=1Tp5DA0GDq>`52OW(RAo9BF7f`jPy4Guat#Ck zpOs2&le9!QxOrc@_EMP??~zt}nWv1fzNIOw?A#g(8&aY2U~TyP+Lh1ZKokUhP$;!>FFpc`d2JTAJ4krfR+P`qCr{~( zjWM426tRbT_a%6r{qh%5yKwBp$pWAtld2X-3iFLzt7w{-m*2Lbhy|?aD zEx3m&u2kX9+!?lE49KS_kKy17J_|fAi~1qucnoZzSBODiRs4iM81^QdXl!sDQNU$S zoL8a@*g8<0vkOWxlESF|?YdMRgl!e*H55(Lpo-?Pl7D=S+_&M-h=Of|hUa;=u9VOzqCYd*M%-{v>qHbVg<`1hl%ZL@!?)Tjf^`-UUX6w!95zu085yCT7XT$J3g_aN!^&Xh7y~^G;9i;ok zYm5Rp7|WIx!t?fy@X_TTgnZ^Y+doEUg^$DO6qT93Y7G-#JO~f|{V&7vCwD{E2!@+& zbhV)7!aVKsjA)2n3eHS}ghsVx^78-iOyYU*z3o;HHxX)$B5i9vjRNNA8*(e$mSU_m z&(_Ed`^YDTo89o13R;l)d<~lsmlYr|-W(^-Q=v&?kDYHkpQH-D(K(41LPbtNKJf-h z{qQ9%id$!4Z^sacn_d1N!upMDCEa)nX$-~79e=0yJy!p3=28BsI zFgtj*#`q*^;LKTS7Qm;Zr-q|j_d$=7IPLnx_fvRa6}nUi6Gd4giC*VxUtf#fV(F@i zsiE=;aT+#Mxa1G=)+BX8K~b9GaD7S0xclq#lUg|Pl2m0Xu0gnUc(2O8UT2F6I$zhJ z((9ZRe3f@Jfc&9Cs$%G~RNgg=Nwa*Wkv6vPN)$!kVdRbbtZ~BmsQ@cnCx#!546bvT z?-E0c_c?O5=fsE}QzjJh|M~asgYPoxN8A^$mA!gppBH8`asC*dosK%QBY`cS)5?J!H_yQRQEo}12Aro+K3=yUCD=Vzb~OB-KVt5( zo<7gRe@1>JMhWlzcBI)ujKVN7N7zb+N{Rx#xRtYy2v8gsn|NHCPaKOf!s%0|!zy@c z+K1Qqa~c{b-BUJL124>lw_TkIjmDR~yyMpASE=a)F900GeWO!^EBS!<7Hj#SsAvEX z{^S0$=MLpw*WvyfRU`gsKuL^z`$^}}Fm7~E^!8IXO&qixqisR$8nk2gPUb>N6lp#V z3yH4LNhG(jER;Z}Om8%2-E%#B{CI>_EBHSqZ@z$atN?d4N1DPr@4OQ}L+KV*#5>n~ z=G^&kAESYhf4*0`zX0#3s3G5;wKd@E=m#g3q2DW4ABXiF7&qZB(xFx4q6(Y?2a!8m zpKFZC*&+Np0;8tKV4<|keo@wX1V z9y@k4hR1L6{B7X4aI%T4JaxA-zE60ms;?&Ma98ZIqT=uRR$r3xge+3X-mPpUI#NU2 z(t6mszc5A?Zejg~_N!o8xK$&Rk)E~U0VbXHtY=`HmoUNQzJ!D z+z`3_Oq|pVItd-Zp#h!OFtEyg9=mXX+6bgb*u4SAsk}n^txV@R>e1KXJc?{24V;{O zQzHjlGa6Qhf^tnX>@x?~>%K^r{ORA)FO5CopL2D;ll8gBQISXKS9a0?XnMEut$QVn za7gnUu3i4AAxj}j`qy5TExSh9dQt0LEt< zMnF;MY3*pGvV2Q?k2&hcE04!K+dPEOZi;S2M$MXR-?vK6sfTUIyOtjbn+&p{x`Bv; z2jSfmidG(#C&@Rq3h8J!1)HuCmWVgXFjEBBalgS(ux92qDnD5TOiB7TF{~T5=7|mLQ3o5*JfCGz@sJR<-`I{%^xMC2)y? z?f0eGr7>^WJ+SAvb5-Ch+(w_{S7~c#^mg(b!_1Br9}QFM(-AQZQMM@7=T|HlO{y1x+?6iOu;k> zr9wGdCI`>6I8>L;HTA6ATZyM*jBv48VD2dEO$=8O>7Ltn!k$zro`+0)8OEsBKt`8` zV!1|9rgwk#v*`If*3^O`lZD5g+(h16Mpuz`q9G;_m=}m@k`ZYQKFIUho>Nfm{qKc5 zq9aBZVKk$Q;n;g`fx~3#L%$Tr9MUe8Nox#fEV9qA_^UzEvrUFYMXd$0uY%ehFt(W2 zMvj_ZLFtx7+_Di8mLK+q=l}3&82sWIg2k(Fw7fcWK6)BM(3Z)Yv?Z06^+0~;u3bfh z#Z%lTi(Io!3VFehS_fJ~6X`%2x5Njn=i<5WB5aF?3Sr`yxF(Kxow>PQrzg*|lwPYy ziE|nY`-foMXpnm5rSam21xJN>Y0Sgt4w_2=2$RPc(n~09EnQefmqw#;Y8?hV@~kJ+6$3-hdc&6f>Co}>FT&#ep3wb& z{6oNu6b65Vm!C5s2r3Fy`Gn^hF|`W=uxGzK&-t)TMrrttHA1f)dk>bzs0DM5w^Lm4 z6_Hm)0V%}vKgZaFXWaW#+J!IoLJz+ilc^A4&;qdX=GwO&C5XO(P)ji|J8kJk?k&=%|Dad_Zpe2xmb^w<60 z%s_^QZyb34Jn%!!8TzSf$Z{+g=&jr4sGCj7IRR4E6VZ*BwJ!dAINX=cAz!gNeo-6vy)Y z7=>A@&(RC**{Q(xE37(Lutgw!ZxWecRGxyV`=_#JG(w_qo73$x42Rdar7vhI!hk=&omIjQsD zwZgpb>Fw@~^VpF`9S976xZlGZ9g}Q_XO6B4^64|QE`~1XW%oQ2?|;0J|ELK2F8NBL z{Hx@-2Y(2gb*EdxVs2J=>-~4aLv#A^CSU*k?@@G1@KATNKE0>KRB|Up5!lnKZ8Xe7 zoFdg%uvnlBE@dz59I|5oHTz0Rf(oQFgX`wt_aJOI|8M_Wq7#ZE?)nT{`^`WDtXY%6`&ZyI7RA$>EPgAW3GaGS zrK$3kJmjbsOfDJ=p&6dJyhz!gg6IV4)eth*K6C)j!zjisq7y2BpHgH>QxG>MD6BX{ zJ5c^tT~QSlR~G3SMms=Kp(^Ss!w4b!?|$@Nlz%j`pE_|Wbde6G(BCD z9MNGd(6`tb34S3Q30LmPwyoKL5@4a@0S1dDXzH-_BgVrzuzTQ011SrH#N%X~1s>%0 z(pqWV0(_vNY=6i_)|e!^3#$_8ecW@lC2XrC<%jM|c7Dmk%f0-ZXdUQKO!I|bC;T;u zwD7#;#qw48xpKFovN9D7rB#*b)LHM7m%DfJZAbDfVZpPKmaBAYwDWh*!!$Gvp30d< zZpImIlV>H)q_=b-a9)lQjS zcvkjxxc04EGub2S5vA#;YflQiHljxepTgb}G}`Nv;WOM1d53kMhfY8(56RpSn3shbO2n5Cr3;-jvAK92$4cXK>$fRPl9v?%#b3lNF2|}_A zQR2G!BpjHvt{}KtOiMsjNL3h}nV5};E>POtV54eJC_UR4-g@V~@C8n|tIFQWYpPjSRY%X|zG7PI4fcnF<#-%s5vV{qk>2b3Fc#drb2Geq>fP|-b-Ks9 z;q5o?-Ha&)t}y~Ip}G~RRM@){g&dX z%WwFV%C2yK;qV38xD|!Ik={sb6l^UBCp=38v>um1#9BL_L`CPta|%Zh(kFqBLJP3I z`leV-ehI~$*rR2QV+@6FyGs}v-SWLlVGQf3&#cGOUW4b(vr?#VFRDecnaNi_QS{^078+PMnmCF(l_UwVXOYAALkMY^ zz|PVj0tAHk{U850!eIp#_zk=WPww2Ic-w3GPd}tzx3k4`m z{yx}7s38WzwAFl(Hh)AmQJFvYEa7G=SjLGK*?};)OmQKV1oJ$jat6bchV8+qH%9(p zRQ`#g+(qwcmB4cH6YZC)0$Ei@PB8m92kldkRe%*X-8;|hr5!+KNPW8UFg*I@m5@)( zfbD#A>)Q2boVe6X`_gfYN+^tXI_^f{NX9DuSVy977=s${XgI5kXp#Nb%cdZu&~N)K zjVL$2{wjR%&PO3TBP(?Ebw#Fj<`^k1RONOq!kD~O zfAr{a3_&$4t_y~4B!Tc}IBrV~HB>gHLrosxk<BOUfqNvRc0+^Ywa@`^NQKgn>tiR56aL;7 zg>97+VMF}#9QFFUKRz$^bmn`9Ve8W0M49q?l|bPs3ZU#slG~gpr_xZ3>k49V4)9{v z;Pb^}9vB5QJxR_(x~F2OS6g^e5vr)H_%<3!LA>KxM^w}muoTJ_`1BrIC{cx013?>W zbFZVo44$jp+6vT^hGZDU;Qsm!z0$r5X~S@yy^AQQ3gMI^>ZWBjh2TpZEK_bivvN&ewf1G9$j9Is2JIBZb!{Mjy}H z;ZKbL?x#i!=Mt3w)*rv;9*5`XoIE3k^K!q8j))N;tW6rHXE}i>l^!Ez7KvP`Zmf-X ztZ~)-@=UGWU}Rj3yn++)3=Q)Njc5N0AZb{ zw=P}`52;s_lk1jF&U8GZ+sCO`Aat>_AB8X@){Su= zy+#>CVuPZzfo!-&x?0$P{RCW@>9|5oTIgirb3!c!-)R$TTtP z;*A_-vDWRR)+*l!`}277d%7_AKtGHywe|2c#yIk4Ls@l-1D-5|)8G4E$jHeGLtR8lk^-=aK};S&j!A6uYxgW^f$O&OSJ7^a zRlshFwGAL+EmOB^mDIV{Sa5Bto`aF$6*7YO;~qJb-_)z*tqysc?G&xUZuYAbsBA?L+py6A7>^n8~`VNhi z4)M?DdmcVZ+Ii$C5v#k>sWtJUf8qb2&td?GDF9o(vlM{M!KoO|nBENXRyceWJQV=L zC1qqW=L=<5p%>dxI@cfJNiU~DhswM_w8FtCgE!<=z28wasIs|Z>)-ucKO7tqJjs$^9&NqgoVyk*m)Q5x2r`P!?^#yi9*k5J8 zidI1xi+R{8`OiB$<3VbHb{-y@o)p(*h>)Wmh0CH=bF{UyKEPX4t8eRV`xcNye3hW= zTs++fY5OrsWK1uI@vk2sP+BY`jers%Tj1C?T46-bzhf(*{jb-ss?$Dk{f&^C0})ek zPKqJfCU9GAdB{6n6`syfbcYbjJP39L!2f>r`=M=w@P4e+8WB1mu&z;IXOfn0dR5!H z+hRKr6>fz&k=y)Tf3~)_Mo<6y=jfA8)Wn4&7sBMiM6{Z_-b#?pye=#GYiYEoi;T9V z`e-QKzL)&rr{Vme^I_&?I!Eka`N7cour(?kBBE_|%r%lZ7&1RLldimP=(YRr*&S~> zPCLCl*paA#0F0Q!Y_S)S(0>YXc?bwsC}!w$^s>!n&c*Z#nZF8$VYv#a65;#g4J#N( z;8f6khlr{7Xz@k5D2PJ2$ZU?gj8e~0`EIwTAkkHl+onXtdtFUZ|5jo!_w z1C`;<{X4XZY!1B?cIn2mFtIQdP9rq*lLJ5f<&Dr(K`|=qIWm63ViN&SW^Wpd!>Aa; z&&1(6=Wt;Ogj@!BeIM4^KgWj7 zqzdelU_$I(vj=+QtyfW9RTVvQnc&F8@@!~6eJWaxj~_i2iM7Q4GQ|1u-P?r4<4sqn zAndCVV}wxV^g(7CYmdNH&dp)DV{q9M`wDhTxS_JpIr&h?u& zViBr+Fjb9_Mmm+EoL;^2MW{JI#6rLm1YMsR9S*mDb0t({?Fut@QS|P0hpkV?!svha zRj4ei3Z3NX;_BaS`Q!&zJEnwE@`R? ze)Om!H|h2F%%$atH`43PF)V^!c&2*w#fh6YZhor(CB-FG!c7ZNuu&;c`FB`I*N7dX zDWumvTiEnE;Yts>o~@~D1b=XG99S$X+7pc&(p$Y74r{bT#gI8TqA(YKW1GNPdzZVf ziTByBRC1-88dp?ae6LDz4s%s$G>t$-SGp)(9ffuZKSl{Cw27}e0~8FsPP(OHr;$J< z%QOS=Sb<5exb)CDdapvMIB5vKMh1;2iDIcx<~V@yO^1VY$ou497Z5U4FfBTq7);{D z{6~JG0%^)Y=kw0^euZrDti7$BH9=>1R}yNU7&naiaz6fak2FBIHu1xKJaO{mw|&~3 zyR^^GRV)+ZiZoFLD5;s?`8l6N5!O(n5y?GC;M@1RXI%E}NZKU2UiV8yGZyRO*~%-P zg@U#FtLNQ0Xk5`_Cf@r@jRy|j>GOS-yhON53>6wze2&Hy_gAAxAKrM+z&WN;ssCbs z6XS~eD-O6n!iaK}Lb*A`?yr2$c_hP->}hyFpca7h7nZ$OgRw){;|qSXpeiW_&@YXt z(tOwEkT(kx7U}xdfGUsUEQJ5{d|FNyQ9Kc&=5FN2B@7a#AsOnf7dscjkg|x%f{Nv> zfB5@QcII>x=wnpSS6_l8z$7xr>jjFVwGYJ{VGDysrJm{eZr3ZFl!rKf_cWd#b95iP zHZiXJ;U1U<<{IYc24ef#A|p*P;{9Q|lIQsv1=IGh7BJ1i=e-id`J;)q} zq50YS%cJ){6K9q(k6zY3_;EHgp$J@P=Gx7DcyEy{tzl%%uPrD@w$y&|)mLE#M@8>* zB1)9mwx?6nR1~{NJwQ{91%0PfZkgxXfA*(g8ChczJa^wT;4OAz=tt(rC(2?_ji!dM&W2CY|X>eI#kJRj>PlpmyEF;Qeyb$F|%2~%f%*+c;j z_VhvII9h0b2E=~ktA}ALb+rcJ=~+f+vDdaHc6hEvqm&?D8M!ewI2@**_md=#ld6Qs zGvKX;g3g%*r0P8E2<4<9v=Lb-Tv`*$=u7E!7RvM1J%wQnd8qQzTVd*HXQ?f-1FeV_x#dJR z?WPWeI-yQtm1S!HY!Ws6k{Svyw%D$D8*sMB8j7-alCt@Nh|SrE=guPzwm=#x-F1v& z^zbZQleEfWeZ9yZ4pS4-Mrb;iFi#`RlRf0Hqs;E!+V(FF_SZSOK6O1EiHVUyLm-U2OU* zR{Nb9018%U#RP*>7;s}G?B*z0X){(i#A>? z|ChoP6`03cI|0tLMaTQ&pqO6mrBh*sjsiu5X6jMBk1`~HTI@w)Ei*E7Uk|W{ErUOt zIvmcHp9wRY7$P{Z>JqBcqJ)Vc5&@CtE{ccOmZ9+28c-(g=Q0m1Zhw;^kXq6hE zT4*0g9tKc|DOi;ZmH%9X^1|Ikv=IXd7&~^Si>IhGxS#fnw(yj>Vb2I#va-M4ha5tO z=5j#J##Ctf-UU3AL=|AYw`kKZzWk?1m=y|&^D&mN=X%Km$XdLq8ejZfK|#cD9SS3c zS`RVz=H})|Jhm5Xk6!wKS?@K2>ukpQ_D0<_2{kgG@@+I=Ye;^r^Hg;N*8gPzvN zh*b>rD(H2TVEYdD-}$I86tQ-z3p*DT(NlG&X`%NZGB)RF=#g{uoNYn)v`sHh6#^bz zC}1G&xzAf?|3zwz1ooqs*($6m^k}f~`6{6z?CImc1YuX!FpzL~UJ^I|St!Rehsdm1 zUw&bJNEM{Q)9xqH^DkqnKY*b8Vj)!JR)ybQ{cRMEWV$L%?#uMzObm;bNHrX22pzrc zA&;}X^v8c3hOX0}oR%>TJq5Wii>S1y$3sw37`;YSJXnkS8bbzAN;1m{@uS9pO0JB- zv;%XT-5cMjz`LFOG>mEqeEi_U55p~b{!X$#>o88JblAmwB)qmQsyTc(^md`>f-~mU zX*r*onh5K2DCrhNB!WP1;W$G1BIoe<@gpqW?+}vyMaY3z&*RM<<1AM>(>|DgW7827 zD{{LrQ0VD#?==qgbN>tiI#PNlL0Kq8pm5GAF<#eloKy`6^)3i&4*73`-#kr6G>{u; z-j!8|Hx*1dx6!^n!ng@FWexR>jd9&8;ITrm0%;k_zy=;(L(B46mr9f8K7k@=l!R@C zggNIX{7KaB-MSqX`MC_E9Ys(XfGNuWEGnk*--@^03du%P7!@Ks^>sW8KlSyV=){Zur(?wD>vOeV8^aB z(^nYtT`HM+lcZC6lwXkR7$#^f^JFLt{rWc5sK-JfB&GLOYj{BfQT37P@c;bkufws^ zCuo(qC3H{phPwQ^@aspv4ht*v+O0)FTS^z!GD1a#UK*_8ByKe~9Esiy8Jw_kqUA*R z-6y|`M#Jc}VSf}3@^ zbRNYJG8j7Vw1(az9J3{dUbzDa2tZ?;V*wQf`y74LzCV(J759qJ&i!M>2QTTV> z8lhA~^bRJKu@mLrYwhv86A!&P_gNU6t)XI(%P9)>*-^pIFTQs<8bmX5(&8Q z`HfMH+%qv8KeqYH1V!jvJ>JK4)6&RQi*g*z#rW=eow8(T3+=TsyWChQ^Y*$Ag`y6i*tzJjo}or=Y~ zh=jTEC>@r}_lW?a2Sc1w$(IhQXvzaLC@3_FGYW7j!s4gv(on48r&6fmqSrX#8Ghz` zq`j`$_XzJQ0#PAiV#1Z*N$2c~E(}XQU5nrOEcZ->$j|jA`A*m6I`yQeOnRStt&pyO zrMEsYoC*(qE{*s7Dz>JaIS1FQvaCXw3?tg)NzPMx>+@8?r7yliT51TqL%h=fSye5+ z>5uY)@6(W@@+tq5mWUTB^(rOG3-Uy1i$mpAUZO(mTHSN6QJK>isW&`P5Pg;cf7}y< zN#~~#K|bO>sOURKuk$ROyO97!A1H9E7&tfg&*!^O?u&*K_uDxdt)#r>^Bg|Q;*j!x zjU@`R?u7=hzMkGFFFb)CI-IA^)F5c*hJS8c@m!O0@fj*TD!IbOC?0TSL=9@bUtXIG zJJM{$Gq3k-5gPr1s2!s+lOY@!HD+5z?-MpvI`jxSk~vGme75rtwxWFE1?=O#<{J1< z6(Qj@p##~i_6U)5$RxFO)YgFiyMN+>&lDb}+4oh>*P_%GVjYHlW%KE2p9>bp(RF3!519Tp~^$l zo0ym(^_9qnZ5VzyV|hzOJ)!HgydK31y%Rh$%zh3&@fuvP4d5EMV9UM*;7(i?zcoNg zKin@3bDQjyG|Uc6(ZJ6hYB0|SX8nATvk*SyY2vAoa^vt~`?o7Q>R@>5t+(R3bOebH zZNN+s@5+YXo+kZJMN9njI~_AsL?IYSpkZeo9bzAJNk!8k{h4BZMh)t;5MNbhXLS~E zRy(0x&!MR~MBu$7dUl!UtMy?D_|Z$_DKI*JbYWr`JX|9ZA=F@eLjK)C9fGmeXAw@FkNB=!Dy;h+ z|A|Y&y!1nQq8>1gVN^KpWG@^lrXRfjL4;@b*?n}Vw0mx*s7bFK!n^u`GKQqa5x?UP zX~h6^&*8m3%hazv&fIxPGvrx*Ck+!WtVQCGW@>bn*GEJ0PRuG8JI2AeOwP>+qM;#L zPjYsbfAS-WG**Qij5|xrbqE@3%g9CQQ)$G`r$DoGF5*XgI#J-@tVZ-f;KO-YW5`tF zqtJ&T3Jkg*;(r{h%T|1c(RozztE;Objr4g&;%T_|TA%4TI(Lo9?xXsSLxVx2BRngU z^IL)rNKZTmzKz#N<2|c#)~(@J8sgkMx0w3H9-lpPHtIj(+Z?cBTKac3UXub)bfM|5 zUXx1rUA<)F-jnFPwo<(zT(-Z`gPliclDQU1HSG9)_EIENP_wdE=ZeMOE9MFBUlDrfDc3kgCR3jM(3Kxpsm2zybC`yRK4 z%`TY3i*%1^32Yo3(yC!!C3)eHMe}$^Nm057vjyp0-Nf_+y+%jEnL}s7KmPU~qoS(^+0d9H$n%a z(1isQXM!M|rQpmUdEgse1_GgFhhv1 z*L~RhVHljJsx$~Lp^$*cghVWnMq(|&FlX)Kk3XiG^>hsRmSMds@n7XBEq`thn`}ORU%dTT%U;SJdUQ0Qt**hSe&6b zQnm~9eP=7rhE8ft2tBS#LaT7uGu$0cojesi`lstp$HHY6sru!ozYK4`{dSz&<(A9g z>$_ja+&P5+-?@e&@RG1RbD!(?9tnMmw0^{cc_0H}tA8j8R4Of%bqLl70$Tg^P-G(v z2^Z%48D^Y~cYw|`Vf{4*7YLVYv@n)+GdxR$9+`t{D1+Gu$8D^uthN@Wnj3149u3D~ z(9TQY)53jy5c5j*a^GHZWVv5qt_r5Oh&Or}Jkf}vfvT~&1*S@5ghm#WlO^`B24-z; zU?)Vlkh6QqXGW(ec&k`+-MU3X#B`XijNAK7C8JZ1u z{`w!n#sGo=-VMVEO?#SJr@t=yXWr-Q9YhxaYs4kQw4R?F|4I1x#_ysve?P{|HTFt{ zL63n(kSXekc($H}u;!W!KeRY#E@!JT&Jg;N-Fw2r_D6UNPlO{S&7mQ`F^q1c1(LEYAp5ZZ?+z4HN{ZC=(+T$?u$ZU-6jXZ8LcJ$pQc_a|LdGAW9s(jWN}%1#M2Rm2aA{3X0; zlx{52o=F7A8H{)4+P>VtqX@q`+)^Lm%T}y<+|1oH3c%=&WGE;Znyio_<5!7RdGn{V zR2sQui*11xqw?>4G5-~XK#$2N%7n`AA_8y% zf~_*^xk&T36GFX=WyQbAcL*zV)lrESeuNi|-NLhTQel#I3zy=A0*gFA+*RS#^X7=5 z^AJPNTw1PB=lt{_dk(^AS`bPrb-v56W(^4r;axhY2VVo2?~nIju#jFQim%V`pYu^M zkydLsP;rXF8n~n3T?N*m(kwqvF?SxGtLrd=z@hT10Y+M%)H(2Tz1{Lpc~7FKYJ~KD z1!3RocRo`d71xi9ry%=-AN(NhozHX)KF2eW9%<+iJ~iMJ!?P416QMQXJ3iC>)nVdi z-s7A-8+lEVj^XEC7X?W8hih@qRosPD_rP~K6g=HCB~tUOU4wge`SPVG%nCO~IXI*p zu31l>XX5_7kzb?G>-nnW2{Y0~&%?Qj`~C0=Wf9-&xoCLP_|tTRqL0v}y860k;7cL{ ze6LJYMMgfREMY{X1`9v;d)FzvIAU}raBWSKS446qLzr>imDQDelo6FWl@9AOSZhQ0 zdH20{qjAP4CSk`Re8?N3k^|4HCk3d7G`y`88SX)5#DYk%yK~_t;s3TVu7yv^r;GrZ zzJ?qF@5|#19JaO77;4z=F7|EPHd2rtJYf;=6^f1Ok@q~^OX+|^92B2CH|0rbzeVL7 zD)z!y#Fg5bc%A!_80ZWUx0t9o|JEt7#)xT1+lVGL^~e^cF;$dTDo2m?VSN9ScW_`) z^c46|W)jvK8=Jr}ik5Mf0B%5$zv83s+XOx`;9KIMIsRSk)KcPa>3Xaz5C67Eps=UG z%E+ZoJ~Q>mHMsW<&u;-dkSBK##((Pk`4}PQ{zroW?DZ2SiPqUF{~MfXp}6J2fyuLBX_f zEPEfRAdtdiZ=DW9z>O_rONjnkwu1~q*c2zRe8(CrD@#PU%rE0KDhjWVGw}D)dJ(#Y z^J5!lF++>MSDfdG_b!H+{4FTHgpXgj6JGSAlruHykb5M&DXaM}(tX||4rw@%URZ?A zcAW0NP7QHax+Dy0%xjSPdsLoDdTiB7tNkg2YBg)F0r@U^8vyL4(pdo>N_v>`D*bYD32CNMZ4Y1#@ zBVIWFVT^jc?CoCm@nBU78ii2;`6!jQhg2Jk@W}caO`Na1MV?|E2;oS$HI3C}2z#!h zsp&{Gz&kG;74BtHPsTkH&(z&w)E@H|)|I6W5>?RC(;LrJUM|ebt0OIQfjnC{amd@% zTl{eU{_=PZu3tSR%C4MaqNk}3I*de+9vVq0&G^nE0P^2D{8t%Uzq=HGqzIq_PYO$$ z;iOi%UPEv!#S*!Ir$<3bMRpHGvCIWA)Lo$Qpc2oR!p~N6XO`%hfJ!;Zk7)!R5u4)ljpy8d(fMBM(bZK}I-8OTT42T64c?jf7Ps`u5Ox{|gW!i<$$= z+qQ&;%H}Y?LAW;zY!b$0JH8iN2ss4l4F8TykNF8OGKJPht>Fwc18hfUhXAj!9p3yp z)j1)8_O#b(Y*^fp$|IqRVu8-v7JLfa>9E)Wys3ooQ6OYtd^)V)-QD&oy-tCB4~%S) z0!{}HrNT58;3*6vaWHqoQR^^%Opm{*a!KB4iu|7>#PQWQ1djDBbKf*A>h{!BVBnxX z^88fz;h`UfFCTvyEl{hkUxWiY_J=DsuSA46clKQP__L3rkW*Vz8x`AQ)d>3(IjbnH zApH416MVh$dOv=2>PLj;;E{x}X_3`aBho1_WMro;g<9?F8ydouZ?43%kQu1_drj;8 z`!MVGK)`)*zeQ;G+r8=P>WoZD;v%85K;hWJSUg8_+YM`z$d&Cai@8J+uqjd*Zlh>s z72pvDHX6&DLT3Kf_%6K^5(kmdc`CT7ELk1*8BDJLi>+aSo}CumBc(^e=kyidUrh_I zW!A{K)N%eNDo=zP-&~Kx%`k9bVu8FZI}{Wb7sY4F*i=-qfZZ}uUknARKzLNB(~x4G zbrnM9(9%fkWp8_!;RkJDxo7lSh9tvYp;#as4dr2b+&hIe^G6L0Uqg}EjzXLP93N_K zj6#t0K^bLl=eceIq5tr?^P&6R-OvQ1&ZUKn__!;VoIHfJT`=P%=2DF1*|ds2A{feH z64Hsz$4|m`6roud>kEjI>pegf^%3CPoPS4UWxBt#`DJCi+dOVP78*$U*`xlpc4!<# zPN5Hix950$C_M?z63RX~f+9}-xU|nTsjxkJ{w(f?3U*TPF&BIj7ZmjNr7%h!1fEcC zx8`gmL>1bF;<=N`&q)Znq2TVN%wEC4QJ*5LjwmQo1!nK}hPf}EhHWU*Pku>jysOv3 zZoIdZhimCzayzsfJ{Aj<%IJm`2*m>ie3sEmKHG?>T*B(5apK86a94rQ5ZQ|T710BK z7q8EspZjU}kPhF|WA8o{l@*f;k&YVLd`a3_DMimPmMSQiQZh-KC`0_4DRw#9H%yKpsW?Sc z!G{09FC*iZH%&ovt<0^Et=GainAYYnDnNxyfmp%Sf}PSX1$&JG3TgN5+=~j20#Pz7 zIOkBIG<06YL1UE0E(MZAm{QQOMVapuf5cgzZv=?puZeM28YgX4x!>H5Cwvz@?YU;H z6TSuwlm2S(Qm_{P96nom;C;fJ-u2`=pQE>4p-AN~845nJ@E^w`yh%q?uDstlN{^F~ zDE}&Wu1}@NJ#nv;6&$`(OjVGkOY{8B$Ork5`;!>v zjH+{OdO*K5Oc24~oDxAXzKH(_E6%}vOCjVYYu0$_`wh=mQFot&0r%cLaCjcBPeYM> z_dLp$h7J||WPhad7PQjCF7GmGM7-7T;(5C-@k zoP+xz?{x0T*}b_f?z_)(#Pb7(HKw>1;;y_>xRtgT8KEMh(K;CxuG7=*|84E117v$X zp~M)wUy{1v`0%3-W5l3zO65m`iD?}UqZV9;c;R`;3suI1cX3A8Qx=PcxM`x&zJDPM zzgh}sE?%UYM_su3#no82)bo4t1mh#T#hNmE8XDvC{g3Z+=n*!zxCEGc_}S-J#)uZ( zyPpvKMZ&?0i8PzSsJ1K4C0-BjbuYwoBS!xD-kHPgnF!<36rD6l^pZuPP3ch25mN752m{xyhYaSSC%qGzJ%y5@1I1!|Z_@!tEEP5< zZrlhf$QedasZ6_vv+P;rNzzyzKMt=szcC_d^uT+D!lHX&NVRxoN~VgIic|*Isu=2p zHQiu_>plNrB& z^PPmN*J7yJ$is{K6364A3c41cVA28L5cR`GfF*Iyxtuz4Iu;RJ9m3N;OgbE#eVzIg z4L^Ago`r5fAJ1q7h=fgt_;Xk&u&CJ^o)^bp^aT09b zM`2XV1M_&g1H6Vj(ipxkoFs6Y&?$ck$9}G1PB~P?UIlm$M$T#YkIH{E0suGC;^Z08 zP{X;Hexrd)2bv17x|%#zL$&LbhU(DJu?Z84@|HhU^rZ>zi_xZuOszcVXBrd4AC+t! zV&=o!0ZrWOCFM07q!Z5D7s4oTm`XwSct4X1)2)xfet4ntG-_G+TEx+iwGDpP-WiV9 z90}bRb`04!ydU!M|J*rkLTj& zo=G9}Y|DY7^dr8D|5^mFz#0JGp#dOgjtct=vU z;L?hHYyib}2uqr0vjqmN?Dlyd!_uR*cLzu+BAc7##;#&SC_U9kixZS9a&1csO6djP ziC2yA6*5R?Iq3Ve$7-OE*$_(Aj%BRne3lH~QHs~eoQwbJfBB!ny}>64z7zz3iIh=< zPVcBd;bC9-{qKVoMgCxg0&i7R zkf(R1UMAWfiuf{N3#f>EB7+vHGe^&aPp^L(w@sljKPNw2z4k>odxU2t?(A&citnh7)Qad#mFNRMHM;);6apC zg?zt1d-!Z@QRbQ^=uS|v52k@9x-wOXp>$TJiZxystX)6m8v{StG7{Z^nC|c-GrXmrQ;ro7t#wi$?f}a-hWeUaZrWS^|=Pf6XN8)19 zmlXS>5zSCy=b6X4W#}^)De7RF?yVui5~C4d{MZK{LsAv{y-Gy9@!;Tri)h0%+kFg&JED+JeS?v-0p3;K1<;kGnXv6G7hhcA_L#gP#fz zu1g}m01-FbQ_s=h_(*vF!w*TRAUAsJPAu)cVFe?~vGW(glVAO(&_bkvFn8_m{x1CJ zFaF}&sFZw+7E!4{7@it~e(W!gil54um13VF$XKwa7lx_VLt?LSri|19=c4f{4>*=l zEDDF<{3yl?YYk)oQ$AZkOxTeYX}y&Zc%Nx0!WJ22q-@lYUpW=(U})3y_T5B4Smyj! zv&a|zK0VS$siAQRq5WA;T)z<=KF4Se3r0n+Acnp~x!22MG{6w+(o?;VwFr^a#6V1t^8WUE5Kv#t}}SzptP(n-hetQYU5g8CBMwkAmbSML}hUnuxuikzrY;50%5n5W(^%mGhX&%E&7D}5!?A~m=aEM1K z&gc5QYoYES-7m=TnWYZV)8L+lX;TCom9@02qKCA@E)JL8zKl%9GZZ4=RdbWHw8gM39rIrt z2;eG6D*t*SW$b#MJdX(~JtqpGUJ%3D6J=VSpb(*AAg-#os9YtAoVYG*D$w{0m1GrS z1t8DX-_vcfNEHAsqtJ)&mw^JczQvjvw3`B^N~n>rI-B-rOaB}SdkTNjUU{t{m`;&x#z;P9vb&mobT=FjmAa|ci!VWmP=;&h@A$9Dn~ey`ET zdt>bp=I)s~Z{JZ@TZbS^`VoJ7o*Hd6mTH*L`0KTvz0Yw^{7&UxLxF!ge*BXk$6}HR zY|1x0b7`<^(xB&%|4Gx5ImQq9kIKIh9)9onyYI7_MY8Yo_T`jB@|Hv1tcLMJxWMOA|t>UaHz6fsk=JW&h|{7 znKQi~qQAg?gWWSP_Qjq(J2Ts-yQjNPS68yjp^R;?!DJy&mJkXk=Y%Bo_q!f$k9S@# zmyeP3Ja@RlKSw{)(2&5q@08zcLXS5Ozym0>t6_JQwVIap`~hiZuA5=%pt8qkUq4~? zMBD+38hYIWVf*PX|0U$9)UN<@@a^@{iBN+>ViJc=yq`UZ1{CB%hx?`RGV%QTnNdqB z!_%ZZMmU9LI5hGk(F4judz-tV9Yg;ZsjanmoIM-i?hsK-y$^c7JNsw=Iol9Y?_CK) zL^ISuKPTbqE36x!iRpqmv#j?s4Zl*+^E~sA*Q8nURSUa%R!buzD5o`{0J!XgM_T!R z0weDW=#kM$$J*MW*WG;8ZEh4!y{FWzaj%L1TkP zDAP(-po69hZh|*Cz`}mcQG?Ms1`!oXBREXM^n8!D9L1AQ${Z;q7ENs?a_;HlM-&g{ zbLPI%KNgGbX)u*G*^QwR8AhXT-O*HB+c3P>2+Mwy%hlDz(9(65npPMeDk#{7@n()X zP4#WZ=o*mb35J;4eIyx0oc{)0$(k^rD{w@CN`ByHHwk6+tulw)!lgNvSq0ciH54|389P4}K0mJG&aqyvz zC3%uOOV}~eGp6Qnz5GL&R@qcKvk4xr02exUV)QJ!Utwzv@?hFnHT%h(P|<-N@h$Zl zkT<;FG!4&s9;Lk$5498`tNgU6=1R(nUPgVeu0D z@jLmb4j*yS`MZw|4Wwd74`Or~1-gNE_eK8XFg3>C^||Nnp?ImYOMKD+ksiqA z?4!}k>Wt1S!LhMtW9hZA9~$I*p0d5P$q3cVy4Ps{unpjAHUKQ3$nGJOnagONls)au zk<@Fg5aN(v#iB|WQVkp3Cf8*bL9MQ~E_!rCSdrgDlsR}X3Q6A$9ErQcQFp2touAiEeEWUDL~BRY=!ExZFJy3*v;Jwy*-bk z^75DvWP!wRRu4%5N#qsa?6obCRB$m8;2%Ey2MSQ=-5m=*>iAI@C!||uc&_GLn4%S* zgxvcT2oxR_bY!rz8(6nUkyyh9+xxqZ$;l@CD7TOrViqmJ>Q7Os80t?kDs%p|Sg9yz z_~B_eGU1iRmTKhz(p$CFCFCT(c?`uiera1U%J z_^VHT6;i2GEZnE(*bxyC;-&ICG&2+#>4{oGx@X5Cf$>cL7U>G}$XP9EqZ;eJ=+)N} z=rFXWDP{XQtaJ!&651ztDLosRs%PJbGGwm5d+fUvcn%&u7~VMiM(CfxGlRmXv81i4 zE!=*58^XUHg`L^O*=U88z?f@vcz<L^3$M#F%VA&cz8EbLg*k|8#ttecZRYy$)bB^Im7#Wj z_`7J?hkJxQ@WFFbAX?`cK1V_G`tN^FJC>qQ-rgSf>a+j)Ut>*xP7DNkUuAGc!K`CJ zUz`}FAP`04P+V;9_USMGHFRBmGd#R|H>M2u%m?3m9iC#e)9YbD7YW-CMSW^IJ2`ul zM-=`?kGkXM8uMff=3prpN|?$2jE#rw*_rSz28P~iUxYH? z%=32+3X2;sg9@TRa@ix-U~Z$I`@66vGY}S>i!i2uIE7$RgLlFxkK?S@5XoBbK|B&( zHBLSwIsvO7T31ducKLj`dG8xICW7@MR^UCT*sG#K-cyEwP#7$&fYGfJ=8ixyH9i#; z%OjkF`QP@&j$!T>PU8W`$hkzjL<@Fnpwh7KS$; zg^gYW06Gc`{Qall?yo-yO^55Dx6`3_fd26a=9{}128qU6#3+c5I9$8_72Q#&!7{=A zBUqiPKLgFAec(zur2F8$651N0pkScbz)(4G{Z5$t;(l1T)*a?QqPxQF(J=B)pNE-l zB0U}shQbVbv_q?toPAq-=~>oe;C@>R#K?$E!ZI`QXfI+=Iez*?jHZfV?s!oafRi%# zfx?0HGmM(BvcH1kzHCGLP-xle;);@RxUMEXqqLG5D+uZ;{}r`|VyaqhQ67w#w1)At z(AUyNm^;G7w|LHs_NYgg(t~Qp4oBko^>_356U9|wK|1Ey8JVJDnAS=aDCnM{mxtkZ z(iT0Uj^uojFn5()>6(JBLWy2y`J7Qo4&R}nS!GCJ$Dz<6uE&;o+_M2+v#nw#hLM-R zm;$9kZ=`~X^irYP=Qt0Qc)ikw$l7(_gCBhmjZ}J-6oMUI?>jW~sm!PhNsr`nt|1xH zbBAk|j|-Dt>-}966}?V}2MrMNW^vf-T&Dv2f8Vdt$Q#5thx7NGeV%#W8jXFY_&Z1_NQjxp)Q&`_9jOjWh!V#(hZM={gf*kY}%=?0yJKD)7=Z1#A_4jSoIUp;*tb zh9s3`zkBBhmlz< zuBZYjEa*AcfR=&bd70F>>L${-DAIX=v>s~=INU?m(+r=nIG*?-KlYq0I;Z^QTAjc1 zj_^f&BwG|3x#OHF>JEoZ%s){dCP|?yIdv*J-!@Q$ znRv)&9oBR@=3Poq`0p4BUGzG6+1YS6jFpIHZ2l;V~cNPGH zrSK^W`c*)yglA=shaY|zPF}tezWV(~6b7u1@MBbq-Ms8-VErBW(&!!9+Wrxdq(o~z zV!j0#(6j7(B4?*V9bH^BQd@H@WK&y!Gg-wDDvYa~Iqyx3&GST$z57Gj0^ayGlw9b< z2!#?!KJXq$e|qT@O=*Pg~vzPS2-jZ z(n^gx8ZOm^Tu%;kH$Ic=tr6k7ygxlMcxF-5k7BAp5lV3_wIbl@?tjDilMzmq;Fm8= zky7q`Izs)QA;PhEE_8bF)}ydCf|H0SXz8~9`z~BdJ6w09-N>t^1LgQ-x(%%aN4}aB7hk$lQw|+USA5p%gKcpnw*Oe zrI#cw5Cn~3|M9PM2)kj;T33w-a9BOlJSR6!i^`lm>q!le*)7bbpY!T=LTHExz?yg9 zSbb~(lM?MU(13Lhl?L7{|AX-yxc(s-xuIcu20=tC5`(z3tnL_%~#!}iCfKno&?yo|5 z$79>q-ybrHGD34za~OU$9K)rx+zEgxw{uwF6$&#TNU4L(A*+$T+Y|y^yhEsT`JpHP zcU?Fag=}-buRsJJ-hLQ8SLUmd^c0I$DU?dU?K`XI@MV?(bO0HQL?y1Of@;a5D80i7 zZ=XL7_m@UOF$BuuhelPHAFWXL?i5EIA5Y*?uL!3H!E@7CWay7)F+Tn*5`d@#bDloia6r$;`!+dCznhtx2|Z(vqSEHG z6xQ_ISg3E5_gZhkbG5F4bGB%WR({u|B5@#>eDH;t(Av-%6$zEU9_mdDD03NRSc**BTRpckjlU09DLiA>REO{N@|N>W)%Kr!=lZ;&%U&PeU!1_I4Dp z!O`JRj7K#y7Y{Q;dIO^8+KW-NeTIsB`-v0m!$z9GA?Q4!uktSED4Y#(HX7v&xzcNF zsMZ?7^&V&U0>Y}$ZQYRJhtz982)uOZ%`h?mtY*?ij@ED6gv~3m8yZ#!>=|yRfUwK| zGDKn0{ckyaCJM|7xQ6&IV{AF|;~#}1C{B|^1nlF#j`j}b|1$J^@ntvwA(k;34lRtz zFb^Z72)m2Sc@IHSI8vDRJt|($@IaZH=K1skCz*WidUmSOovK330Rk+^Jp89M2iv5WrkC;)c?rN3SBj4!-Hq{sMGPQ(1PKh zJi8#&P__Tt-+mN6|6l*Nu=NjS*unqm_QBpO&z|3y2)) z#mSQ=V(y+wh+fBRa6$z{*ioQYK~(s4-xcPK#xR^)1ys+b-q5IEGY9FY0=~}@o-`P! zEU4V-ffnwJq>{d={0mzuj6T1ip&@#sRlFQ394bBvKjOQ^7xxGqt^&s7NvmTBQQ(pE zM|@FPQkd~tpP`@=g<)Vx-jw9V8t$#~Dt@V`D&(oCihs#ET(in{;ad z{_+Q}kyiSAVZc4~Zv}DjJcfs|e%~Se^^852D4a82zjt1?XLTgJtPdr^eUtBc_6nKe ziHcdG*!v!Ni2|+973LhmZBqIFB>C)m!t}hmSJFG_j?a@vxDTGM@aVgwm%^JVC`q(Y zjH=*0Ns2)dkzmAwMgs+5VcL1dePIuri{buuj54LC7=w-Ytuc6)g3qh3>KzrakItbH zJaBI{KqNH7dHOD4M|hHUm{Ts^I9lI4O++7eXOh__3 zgQ-V6=z}-Zzz?7O>Q~_q@`C(;<%Xx9eHIRP+EJ%8db+DHjvT}=G15B_a)^H2p~l7@ z^kf@4pTS>d7m_0BWyG}aGx@Yb8>FZ#m_as>gCob6|V!M zG}hRrFa6RT(EClO)IsqGxHitFjOWV9-Ss-=qFwu_S(2O(~gBA2P zA}N1KFIJ=1SBi~DSStN zKLi$`Q$p%9nvXPxvP`UlTX+TlI+X=;?J_g)5?9rS$9O|>C)X+Vm$p#FJiBcyP2>yv z`$_s#o6~Cksu323@mY*&8lf(y2%v63$r+gl$InpF80%6l%pr!8vgrc9-onnDa`wAC z{Ok2k!=Ii1%P{fsImk$k8)214h`{*v*0&LHoMS<0L8vTa4{PaY0CLtN;P(#nMn+&5 zj6|WewG{&5dnV$3No2l3namVvAWo(NsAP*gB8@_p>wZD~1goCkdVC88RuF|>b8|v& zhy>quF&bGEoLomwPfv_Ekl0+Pz7Ve6|D5j#1LavhSHh}cM$4M_c)nII_q;EW`Y=az ze?te2DzG>G+~!;qKn>F|kMoCEepQq$Sm$$`=R*}}*8Uu#cjx|H1ZPqTAVxAg;Wry$ z)a!iz$?B6tbj)InMseAs5Dmn|xed^!P{r)v{?eFkp}-{5cYZRx1q?7Rv+)4Iz>gJD zlxSsyEui33_gF}AX2PsE65Gb1)L8(il76(V(fw6Ok3tq{A%>B?SVtM)9k$(j_fP*c z5`V*!p2D0PfM3^FiIC)8k0XE|ATmY+O9_nC=Q%$G6p8yP3c?hYT65ox6qpA;7HBQ> z9OYZ1fcu;e(z{`;Lw zP6p#M`|vL8XRrKBSVydgzw7xB))dwy@OpD3_6pZs2wW=&RkOUKNKY(tv|!;y3RTS` z;M;!c^wmq@-m}5*qW@XQY^@GO)OFZWm_&(}=_%lTe<-Zm`cvU1dPDJGDAbJhlY#L=`YSo{}n3}K-bTS^;jqR_`0n-IS2GP8)lzf5&#X{CE)x`oRB zfeJi8c)C^C-+t#Eic>vGN2>v}F|-(*SJ@O7g-yNp3islrin@zg0q_Ql5d` zo9`UbVb7thy)6t5494G8=u{Y0_}qJ+r^2AJ;CE@yLwP(C6({r8RSr~wg(1DjsfKju zv@j>Usn9#5VJa3S7=GrcPcm~Kpd!K9<7 zPj8<>Sfbph{3l9sqFAa3x<|?S;{#v)lYHj8qr&)#I7n-~UxS&#rfZUL_> z-T&k)JZHV^rUr=b?xDQbVzr3^=^A{W?^QvS9;qm}ufm`3;d@o6lHuPf<|_8CUnh*i zxg^FN1y|=TTuTR~X&Qq3%y*j_Vr0VihXQv3i|$KeWKj8cex9v$fzn2?P0}0EQ5b%w z2VeSPbdL_ARC{wY5X|Y#1z&uYXXN{>$00mAH}S>&627Gq@;XPug^nF`_(npi%NfM=tOtk5n#{$33`nJ4~`~ zDU^T==-cewk=PC7?D?}1E=(5?ZycVfv|Qd1aUHs1gcdgGXf$*WjfN0*6T^o0*%c;s z9?773H*+((z)=e?oTgBz2AGJCJg@F#3jt+B3BFP`jFhZmKkwYQ9(k2K%q~Fn?VZ3r zDQYNpbMVDIXz(iVCj3g1m6e2tJ>I#-?^PH>8X6j+B4b3#wa>4`6cMBG+&ew5tr$vF zqUNP1C^Ra}K4S+sUt=F?xL>)Y6gg@S`s8z#xptO)%w|8gcy}&5TZ5!HJcEP4IiAH( zV8m|c$&;b`!NaKd&0N0`&ivrLunDddQ{N@81>7S#tpz<{?*IHl*n)@cETs!fc3=## zi%u+3h;q5Tz_Da$*zTJUKJoie7p@J8=-UPd5DOH-+aNH>g- zihSwSy4>?tWLftzF`)Qd^*DL8x}aSyJeTx5NZCG0`UddoHPRsKgD6`|o8&p(Zxod8 z_Z*zF-)q2-?%8#!pt;6veJz6`)|;6nZybBAH2~~KU87Y4ucwSofzvSu0vH8Qjh9b= zl+ozD)FNouN($w5VVhz#1r(I}H$MzHokvh+`zRb$K`X!BXi*Xn1^ReUD=1>AvT$$s zVQ4*bKCEou3FojL-g^+LYY#_;kpZJDM#0YA+6x1peH)3m2b-Chw&Y|XxXh9p|FoQ3 z+9D7fD|n;L`2YYw07*naRBm%~Q_STRm<{VQoJ8fbA(g_2fI@;2G`Tz(S`J~YT_bM< zA$4KjLKFZDzY`%0b$ z5IrvY2q#iu&P4#f^Iv|;buYqT!9pm8_^j_>pa56}+9ZrlL8TJHsFE%biHvoXc44h2 zW5F#$x@DH`iwG{#DnPmihD%8hBsww#z4sCw_e4v&)-(x_NMSC|?c2BGy~2t2D13NM zh8Fp^!d+uyQ)K88zEJWqzVF>P-i^Y)Fd?FztL=&cRTg2wjwld;pkw1>@p(V%`dLiL zaEL!W+!{5a+kQ zxgqp_{)bT6+#CiUJtA-WXe99N>*~lz_@Dp!ufyHDcPZ-B9AVq%jy!xAw(i^sKmF_f zB^tXxp)?j$8&I-HfM`k zzyJHNZ~cS24!n1xqb96ExqrQonHhpO|lE1~VwF<@{rD!-TB zy7XONb8{h8##A6=l1cl~)#>@LG)i&L{S<_}^*HA7Pki_(4O9@gZa)rF4~PI7oDI+Z z@sm(O%f6MrzZGUFbQtET|3GTjJcY4VX>+)aaxL91J5&~ipAHkc+YEdy0Y~F8n#Eq= zoAlA{>%p6e62C=gWeJM875npx3!+!wpVAoVTy-t^v5R=e5U!lBu&rUhee`!jZ7q^& z%D^mX2xW)LW5x0k!Yu7HbFhL??=rkTz8B@cp`|g>NtFx3l9M59`z(bOl@!lZFOcV| zAg<@K1-KIrjRbIwUhf3hUC9#6YaF zt3su4VuV%nfB-)#fhx-ixC&R|f!B)PuFLCPrydk({`ZHt;XXJLkN5Y#m!~A2V)>&2 zl5?`?U(EA{m#MhRhvWSSe8RNvbB~;(eA4y1hd#r7ROn2?UX%Cv42Qf-oQdbd`=!I) z>u|s2mF}GiX5v9gHDEkvpOfc%2J%N?z-L8c5BEzqxIG$lH0rpI?vM1yIje}fW(^qf z8Hd86Yfzt5(*&FTaCPl5y*W%gz;|^r65T&^8Wh9`bfv5M~PghL&sq{p=lGsUTGV(mWVX0 zLH4x1(ld-8&u)E7u~%9;^IqXU7r0cO>LThvV~{n5viWRbY>X}^C(}_z?4uE@u5}xl zYX$x_;C6v$njY76{yeQ>dw|V!q@{Q(F6#NUjq*4S23xqj;9O6>^)`{R8)ikFAuyj-iua@w$Yp-t+}slJe2P8K!hoT?R^QMNJ;bZP=anD)AoMZsNxnaQ{zABS z_f~j`44scLsCttWzfbQ55^2AqziWi>&(cB0v5#&y87SN0dE7^g$Mmm=GDQhWnCIZx zuaUC6pU~A>qH&L)rz|0NY+8uB87B~_xw{nF4mi%6NsqPGk2J)H6Lpk0!2cbb8}*&- z;qe!rQ=t4MkqYfZj!|S4gO0j~kv0c-ULG~TmL|qSYa_}s(T>aTT;VuLMOF68E+*O$ zxhKE!AhowzF#M^$7lqRb_$!zoQaW~ z_27I$zmsQJTu&#M4nTR6^YnQR_cZb~&Rst395f6`d)nSO6&~ICnyUYYDGYrt{NQIl zBbpO>S5TOaY#ReFNdYw#XKx>A0vO9)AZIQ^1Gh2SZ!St(iRzGFBU{;uS$ZfO>k%Ob-_xoS*P5JgM_&#Fw_k2zLwtI!@h3^&+o7j4^q)5=HcN4I=;! zzDW_l*O&sZfv~s;0KWiOMYO~VW1$!YE5q9*wpyH2AaY?gk>Q;qJnm#|$i3ViDlQ)n z+m*$k@!~mRFm@=|N0m#M0DB#WdB_sVKtKAjH&29IDkmN(!V-@swWFmY_Te-~N-x|v z2fn$C=bz$g=8y{P=0FM18T_}CyDxP8#gD1Tek_KYS**nVvqduI@^rOi5y_%`whS>> z%dnW;EWEJ@?>E~CWHxg+ON~DnRMuBH=KDHiP%q54J5VM2D6`=~^x1J4J-wQ}5jy7Q=zzZDb$i96==$Y4?sXT*3l@T6dJdrqQpi!U^G41-G^3~be8UFqs{~;7s z7lz;b{x>0&!dO#Y6~m-G2N7I>;Qqklc;@iy;%R~ zI0`Qcnza!O3zsN*k8m?c;g>6?ug0q4*f6QSJ{1lUYCkQ!52p#cL{%llA=9@o*9#N{ zjZe;_pU`K=7E0D8%G1s!FhbOba2#_}A&8!*>o85ibFq4>@SBg&LwDft_Ip31FL@t5 zY6%qwFH0b-c5fFqH7=RAW-eFX=pd0HC9xX+E==(NLfibar{ORHhN&pR|1Nu74nrBl z5S9;YOi+lZ7-N8ye9fz!RQY*Ihm5P2qq3s0a1fZ8gkc)lQd&|P8cGj`Z$J7Xoam&x z#=h+7XR4+4&%gp15^g}F}8(psh=6-Jor9PlZ8$#~r-Ln7_$AY(ZI{)~?d<8ewCby3O6 z2d_1F2;cHR=QhjpR=E!3hl#Yt=oST5zcX~N3?`7Ta1R49@<~QKN3@Q;lVubNm_>Zv zJJ=r@&kofiGR3Gza0wF4W?5Jq|+)%o`;@PhsuZrF;$wR0~#gPmr$TFR;bL%fK~P#hlp@7 z^naR~CLH9y#%ujdx~rkq4iWB&UPIR-J$&~E@5bV&?*A!_ zF1NqA9q*Gatk7yx;aN{*Z7tqDJgh1=C3K&FHAG?1eYB_WVE;f=tYS_dPjEeY>1E41uq##(8J!@u>Q`kWYbz-I~*dW)sIo{Ko# zcC0Nb7AnySIh(UsFvjqH z_uRdRaLBWSIbqKnc-QCijaEotOXb-0dgj(8(3_kn;678O-}wqx-s?C`9FN|q0N`?^xuGLhAWbZVR_`4%90GV2&p~2_q z`4Ycex5hKQ!4AV_jkIyi-FNPXy4FT=xuGr0Gbvv9ls)(#hxnrLO(j>_wzLNStSO>^ zEn&p)&1H;{+pN>)EKbdZf|C@=B^v7D)hp3}syvlnRu((`sLZ-=!h=zatMJ5&@4OR> z(0Q)z(Hb7RySHwJhW55lo?jH!f!}Qkm5mLLMSiZFp;G1ExmUumu$k;zCyUKBdI&eEA+2*wHj#sgo7 z@hTHK9F1I@pHTqMo(zV3A`t72w@2gN3UJ$W^=w!Gia>S0g73^d8ji=JoSmc{i95NZ zk?m$;y#0zUWYnfHf^vyH&4AzTCsHpHd1bEzuR4|gCrPKn;uCh}Fnkm7rejnb7S1B> z0^|nhMSYPqix1+pYm>(- zCzuMZVNO}gdTB$$LvfER3g}+@Y^(k!Mto&FvjA?p~lV3 ziYv$e21CmJ*YSe*%qgrX0JkAl=AbKVcAkLIl1J%K8MAm*V)@ z$HMCN*M_OJsVEpd#k*8R!K^)$r_wD7F-Uu7+~+&PV%`pUKKn!C zA%x{+l>8OKVh=425G226?osngyWE{WWY@!Q6LG ze0HCZaavLkZoHaJ;UeypaK8X>t>K`xUjkyE&Zi5bD1$G;r8Aepzy9`Lu^>0b^%#2n zt6%>*B8Ite=FlY8c<-0ExYr_r*3q*k&qhVVYeXa!c#EUxHSl){l7=CL0K=UOr?(j4 zvHD}tny=A7hUNT4MiKMg!}~!`t`P%zM{LKDLkN+7E4;pa>Froh@xu8F5!qx`&ljG@ z`FP(KUwjcx9y=L5kHY6!Jn9Mn?vrQdTFt-zkb*RZMk)L}dGaJ8u!`b7ES4H8YO88v zfsxhibV&6H`ko7m&cQrxhx2>){JY`y!`qR_#0sS__*InY-5fj{gj9dsO%Wc5ROKe^ z3+dhN{>A)E(p(f6_VDUSbT<|eW-$0DJXsCCnh^OKV70gfuX-zrEHF8ZvF$JnWpHqS zGoXq+a3R5ah;T5={u#vf#+57KvyVOs=PzA~_-VCc3ETwHIZGI@%+u2XI{4v7q2cTq z-cRT-=ao}Lh5UyPu{>;qBOUE=uT0(0Q)0S~R{s?Qi;8pP6LMY>?-}-U^7gIp!GHV@ z;rj1>i(oVxj+1YgONIMsez#DdoejSJKmIe7eNTk$AzB$->_Vu*7Jmr zzOpd)yU#<@`|n2B_pF|gl2go@g%9f+oJC+0J_ZK*VQiUEFwu~)h|%W|XS&Fq>>y|u z0?C1grmn8YFoZ)r4KnRf40pNw^vsvQZQ)K2WB09FVFRYz>VXZw}Xb z&I-T6xJrUBjg&;lUtP2WYs7qnu%%a~5!kV?VgXFK9*_M1!rD65FJcjgsD->E)#2Pb zS3_PyRhXyHOCIcLg@h(eo{dk?y=rF)XT`UcQN1yKPuaG&4kHfO?T{U zQp5;mYw;s8^nH2(jAot5IE79Tgvq zmJ0tWa|aF)?u%ldkxTVp>Xw)fZxw$Pxc$X=G@)bGwTQ|;co6G_Ky&O%z6+g`IVyZ4 zhEMCESn%)Y@z&_=U!fC#21u1Lm1`Nk-AodJISOTaFQYPaYDqZXV)`7+De<$0op{q5JgB_6pNT@Ha-iU=Qs7Xj_S{saIm#$R=r#5I(p2F~MbLNM{`Phh$~AbK z8yl5>o>9&9OQeV8HY!wPP^|GN)y&gv)1vUgr}8A{lo&5mL=^&kzlH_prx)IJImg79 zp@8lgnKt1_?)P{3qw9A5&Q&4JA#5c|PyB#?{9e3?Ve)vj63@A7PzY90_Bn~-q%b9a z{Z7G$$M{@@Err^|8*deSqX;xQ_`Qm|XW%?-2dH9g)WmZHJfn3qQV44bzrIh!RKD+f zRN!5|JYQH-cy(U#c40uA@cr^!l`)6-k|^lT*F6;1vzWZ&IWz1rf5u;M!vp#9$erNQ!Qhu0)$DZII#;ocar+Hm$EoaNR=RC*gw$sQ0^2{?RpFZ2Y zS1ug*=YN9F(h`_`ynW+($lM|K7-g>u9-=I^P92x1PykaJTEr#SER7Q192&o@QZH;J zsSKX4GMe>j3V}h>Y4eJ3lA#=E6m39()k$IZ6P165=OFDMxgi`leJs2n0&oJ4axosy z{m>fauqtGL+yB@96Arc=jj*Ot-VOg z`G0f@5m~i=AJL5u`y;%WR<{oSIshM|938}Z3;7a034bdl!c5P;-sg-RC{{9{cR(D)b)ELX7@IW~NGqg47F?HpCdNf+n=~|S?BJM@A2b9c zdtm*MZ0M7CC#{h;Tm0O=cQ`Bc64&G!P2bi5Dm|FzUE+>=;*i$xN946W+xaNl$EX}H zV9$(9vI~|&d{>4L=Pg<&{>V3^yBaVoHmLlNtV2gwK}$`%_jUXe4FDw^c|IuD1v?#=(a`(J(+%HKU6^6L(Ts$7&MJl!W6I|(!Dje>(=JLM2A ziJAat7`Ol^at==+@B=WD&nYkluo#+hchj{ z2OvYbXoY9_45NwwtpIxDaBb**jAi!1g-8TMBJ=&V!k6X2AQ0#)N)c4Y=+|CNCHRt@ zaQp7uKQvM4OzR44ucQ>I$Kj@uXlpU5#DzU`>ZRE4<9k9bnaWZ6i=-agEBq#vj9&UQj*WqH%UzkTCCIT&h3b8ACdI9{0rB6O9n= zS@5*;#0lE)*%zI32^8|j2;>vr+^_{hw6qpM40kbJ42_LYJ7Jls?-1%e!l22cTcB&j zEUoU&zkfCC*{Z2HCtA)G!e8d@r}ZL{M7xBUgHzTO_={isMOa~;3g9E)*8)P9XCk5Y zOf}RfxCv_+2sbJv`@!j51eBM+5C;>P#$${@c`)xoD3mh7x88d%dN+jmvHSN!73U>9 zSS-o!ClHK{qELYmRz~={i2J7zrgDIp0pM^yMlA~`uvV0wSGIGGye! zi3~~w?nwO+yyN6%KBw>u9$|$^M;o3KbLoZ2t=%*%#V`2B9DE}P%)5`pC!yu*w82Y+ ze6N$1yT`(?)u&ZRqbC$4Kh=t$ir4MUcP__*fv3+>sT>+-A*-mwOcLHqKjaMxC>=YE z@dyup1`$>ub%g2D=T3)-5u&$HDtvZjjn%<12CgB+Lsu+TwqisCwvSDPJ?Nvf-LU+f zSKSnxqp1xlIPODinF!H!jtWHzYJd-a)CS%55k9S-TY4FQn=F#thdko@o#CWG*ksgBaMof!h-@v62@sHgx(e5T!BR8DN$;@ z#&@YisbKqlJ$7C%Ur=!Ie#3CR&h!RH)8$h!Om*P1n=w+%_eNU6Pv@HmX+}-RoOpFBZc`AX{RZ!`-MuE?DPZEL5Imq|)l$*Mt5}SCMV+sN9QW4e|nM6`}2CmEf zF?UmgwT1z4StZKvPo6#%3-!wDtva9Vzk-_l#e0PxX|m53MhqDh#{8-9E}VFFu3vaE z8p7f4(hBc&9V%b0SHaNxoQLmqcyBViPF!&A@4WjC(M+Tca@M{_&%6dV(<>E(O*L>& zrRVOicq%OVPCs{8L^Ux=xo?hWtU|!|x$;wuOYX4-4|$qKP+`q?rIn4elA-rsUa5g0 z;x=v;4&L|J3#P4oGt zNF;OjbK%%MtvcBp=CTPt#)x^Wr9G@s{Bng5@bRIv*U#<(^Q*HVhl=r;MfqX$m%j{U z$J%3!nWsdnWkSEJq3Ob;^w_maZ#04!U8Z72jk&PWO=llqA|HOc@Yz=wkzdd^o_ada zn_iH4uD5!g7n6~_}?@JtL)XY(aR<`r{V%{SS zb-v2arb@hE|CXo^QT#G5O!W+g<`nHp+3U6w#{%L++&7hfX?;GOAndlI+_Y@%1eA7p z2-JXRWzMo0PdU6h6I%F^lsfT7xE1CddpKHZDym|qvts0$MItT(JT;7`&uSYb-5LVo zuxZX)OVC>A);hd2lQiBdZ(I&580>NXg^ISOFa*D$av+CHyd^blO#4uF)bQY5C+TF; zOuOGK_C6-fla`*>yF)SOoq|W*|NLtr>9Qi8OQRYZQp_}s4?at|Rof z!695Yq$8%XSi3`o-Oq)0_rfSmWh~|LxFD`~ji%l?ggfbt`S{8J>N*Z_#OtMb8n?t_ zbrOxdo~?97ypa}3|4lE@p_1Om^t_y&4pQImvpfU!SLv*OCw0zzhjT(Zeys+8bQb`M z0HSohwg`arzHuyWP%DK)n3Krv@DLBRH-w@~Eur|`6Ja4$6k7kMABTLr{q=Zr3?Gi( zYYwJ>Ln+Q9WQHE~dV#aZ2hDm;C4VZRCL^}dBW$~}qbY0`WZ{i_ffx65SfB{o<8Jza zVp)68*Ar5;%_zlqiU0BUA%B7VO*|GV0RpU^;td5xHoxVMFNd)Vm>*$56{Tfi0Oh|0 ztCZm)9=1jRg%AH15LNU=QV%@I4Ha;0U6xl!RZ)nP?>TfJ-HTcyftE6rgc<~H37mv~ z7bR#39AE6^UHtx5ZF3fnyDi?spjn=ppJ z#Le-y3bs|W^{VZoN9h_$fjzK`@UYr?v4Tj7!6CgCgsDQHHu!&<>fGDISfRoFH3(`E zOr(z1eRl`$MPbFFc>=PGMj=H&HuUu=#LM-}K$zW6E1oMr>iK#+_$1uIOKN0;4D?X` zp>T~(12XzEC_si~i>xUmlMF>LeWt6k@FCZ!VqZ>HhrW=ug7m ze*U*nKLAk`4S>__DFNDTX-G zF)0e%DkM8ZtaN|;Wmx#~cBmm-aTy~9W;@QA)`!)`T;_q z%CqM!A=gW@%bFDuCLccz%fQPVw1 zGDssoz5zblfPL$FZ37 zS%88J%}s{1#G%ls(r1ejg<4H6VTH6_a;n5GO&;o;E` zV8nx-dcEa7%d<44K><4%QE5md7(SHoOK-AJ3`~*Ii>K#wg78mimuICi<4|c;AyqJp z&qmPH%dEnz^c3Jua3VM4m5qNY%i2$qJ3OE*ltP?40+m{;vS*BnXr z=ax3A6v~ghSN`FUhH0cw=y9$J(SGK2nTLwPp;o$DPy}sX1}P@F={9Zg9oDIY0N< z^(&jiHg2yJzxdEs|9GGKEesiT;P7{ceAMrKre_ruedtM|csoz$>ovlobMibC>@`Rv zFkqCTu;+6%E@`wdpH*emuxk~CL}8HDI)6t3hbrYN&F;N0;kt~LQZSZQ=y{apxZfHT zW;hGiq_XB*jmWXjy1$#cp@GnjD0!u%^MD%-4XGG8Y8sBweZsJN>5v}3B*kbS=~Byi zFGB@J!?K*h(ElNd`T7nKPBYQ4CH>xo=NvfG8gj{%FTiI954FvY)k19B;mTIm%D7q%!C|tRRxs z2wNkbq@9(QI%toJL7p?~eext+{^?I+eH-D!G?r7;|9LtH7eImKYHS)@u&+G zZQRof@0|w@gngqZ<~e)Q5R7in$Y|)dMy5q*oif)`WL;}fEi%6?aCSfYqcKyt%=6y` zw#3~Nz|Sp=8*}5&!tpLzZ9@mk^NYj6jUFQUz$2oDIIk?(UAv zhpLVi3Mj(Afhqaek=CXNi+fpt+A>XHyl)g40eN&EjwX1~91#GG=ZUI8Mn-4}<#`9g z`Y^^J`96Fok+Gegd_x&~8o4V6uj&ppytcv7&{`7?q%ic6y0AWv&cz;Y5aH~QkBHMo zRtbMP*F2wR?3Z$q3bHWlFgooDDKNg%5orqFJNzM?v>QP3eX1e#|1rX9T$Ij93&e9P z>zl$N4Uo>*W#RCZlVN3ah-e79QLv|T@PP(oDm~@Wh&AA%4!)5I&CK)fzJ8vC{4u^3 z^)J^TzwoCu0OaeA!~o!W_4w=MSLgCNz4wOM%P)4_{3-;(>I~`MEcV ze5Rb~b;Z)&kVQ>WYxtRux{Js|#iCoD8)W zkK={Q3$0b{VfCd7I2E%Im_~<(Bcj(}P3a#Vpy(Z5NbY~Ruo|YRm&uFSMi`viT#lCQR2_v-P(G@-ZhoDV1WqnvVj+xuayJr3L(VNGV;@l!9>-YD zdbs>oe?d{Vp3q#1g0p{L4D*hmY%m9jqs(0fXn4=HYu6%ziDW8(F$w_Bo8M~~I8a1n z!Tq~2^jsnGWF@)GyGzkvATUe7RT@t=onozhp>GVr4DqNTlyvg?!;n2iYp5KGHi4KD zy`+M-Vf|Kry?5^}5f*#o6H~MUM!xu*mK@~rDjX}kSJS_=8fDO8BUw3y@>`IRkQYLS zw^uP1D9FGFo13)YA)GE!o&9!CXgyFBzWw-GXy|Ar!h#*f+kF1a8)0O8BzlTvgoX=! z2{W|UsOKy2i})%@?uA9^6uPclyb{wDM3&o6Zb!!E{qE!GQ>UYHtP*~u?MnFY%a5Wm z{3a;|>x4NQrtdzAh~IvDJ9<#{;$D99GWl!cv6!Fl)_bjx_5^10#?`A)zz}im+8|;{ zP(8b=ZC7Kc^K%NTWf!E|b!f2ANYRWz;rfjmQNT0Y$)bc+6wZ=Zxc@5uuIUEXm=D!f z-$vdR1?`}aXBy6ge$LK4Ff!!Mox9NsG`mM`G|bfDI-o0|_HbHfvtewP+}nRm=Pmmz6|nZsc7Kf(&>LYk<|0}R-LP$Q zr8g|RIkz4vu)3zOf@dQb>n)MEnX7yM=GWo$TUWz9_KXR^FgLh75{f&9s5M3m3j4nmt{h$9l zDyHJBo(thoA>}FiasKVM!y}A9>pb`L<;&Ewco_G31tFvuCNl-I5}zFhVa(Ose+t-8 z`IiyOj1+D>*E~K)6(x8Ts_nFvWF-zBO{MAz?D4?wj9Il=DawHWj{} z4q%u=P}~Cl4Hd0tudK14_t{)YY18=RI3bj&uv32^T>Rq?h<@k^hr6h1U1Vr3I8NU8 z@-_w;=A%I5+*Ojg&UJ;T^uW~2S#_xVI}Fu#lpG=)951GkCd~*rQ)5%%WY@_s*h@>t zqvraNW2>zf`fV=%hRVMKdx1i$756n-+PUH-v?M@FHo0bpGqi1~!#Qoxwoh7Q)o&F7 z@nxEv-&}aaQNnpmdoo}Da6Lj#8Q!+(wC7Rf-)I;O3JTSUcUnbICaX711?!LhgmCaD zz0qrFc&_K3C`U;+xP8CPqn4*6%w3^C1>A6Og=(3$G{ODTQ|WW`Wa^DlFj9zi$oqsR zpXEIYar_$pSGZOoP>GYandhuCD2RskwsB+wTtTl{GK7(GQI|e+yPiGkB5K~Lp7xzy7?p&5O zkdw0L?u1dj9Ne6^LviS;6cy&5hqYG3l!eO8-0O-e|qgLVz zef~N0pXgBx{qC>yYK!ak7Z!zn))7jsipQ(>>s{rV+;lu$91LH}abDfC_3e4x(A`E(>F;OG|3C{@(U;bVZVeW_#_8AqZ`PBJ^&;{oanJL#VM*J0~yjB^^x;Pf*GpfZQKl6L}igK7VSKZSQ=`T3y8Q2*t8cN`C;;b~z+Gy^j z_!ht8UWYPs>_!GGy2lQA>mZKcSC_=k+-HrSzFV0yNt5thw$Szr>RtajZ`U>@b5pm z8#-&-DTp=@QV<`Na*J(M7F2~|yi$h`l!x($6fb**RR_l40n1!kv6#%#M(ss$F8xAJ zhlBKS_Q3CcdnYoKXH+U*BL}RylwvYpeiQbgAkV-Cx}KBK+Xw55n+s z!nV1_)-pcp__5>BSo2pu`FFJQNrj%lN8x9ke-yf(bw}h^VAR4Xfe~@7Dl6fuI7shK z3IXaZKiP3I^bPby;wo{PM1hkK2rqhig*B~z)*J9ML#kYZ#By`T3gB5$p)(@DC=UaI zZa%vi4&VjYCckX$b~+4G_|n)i0aG#*+V+d9M0r%!(KZZ$!5n5i%yKLHpDz$G)7 zBWxLA;C|e@euJ(D2x$Ej+(K~6E5q7qE**k(Gzfu*T2Ccx_IO>!ORREJ0ArY9&b4^B zS7E}r`*P?XPp;<7TG*di7%FmM-YB4Y1@a<*l$l zK40+xm}ANF>|$dA&l19!_yO@pemV zq)RHY8ebF~qoBi6^jt<-fu~KOy|t}1Dp10O%D0M{|Es8ppT0x7a{2P*bo;Yc^K(Kf zroJ;#cBMn&lS-`KS>aM;Sw%=%siL+Ip;6`S$3OmY%r90T@jb$??{u!-t8%U)=lAZp zhMB$nnWTqMO}&;oiuD zR8UodoQHcVzmvy!Z8TDXtFCbq1B-OXJ@foD%&5p|*zuX}UozYWpX0iGwsW-axVZ10 zX>5;54bOFsDtZp*tSsPAh;-;pcQ4#4hjhc?UTO46?)5Vb2Et|XyK_s<#Ca=QxF(;W z@j}CbFz4T%kzRV?Hu1`<)XOjZUIE@cbY4Ekc{yCCpKC-BZcL?cjY&FF+*972%u5-; zwfLSS1;TSQQX{#>xh6w{i0gO1j6x8X6WBdKN}|8(5b)jZi9;Cj{YD&2PTK_sm;%)^ zDQYXfa1I(7yiOeRd@G~u5KJYH*|B^`0ZK~k6oySRW{Ywhn;#49Erv%!tf??|9`#cg#^#IfXMx=Zalx z0Sq*o6m7-ScERKmJR_% z(n5Q-p?|`k5x=YQBMJoO>=NRQjD4KFe@>`=*L&}TyHC2qJ`6WGc|>K@907JnWgxX9 zvmS3XH3%Nv$6(NdOoBsBdMWNGvxuh}!KLpBO%;NL8+osa_6mkAJR#xaJ8y;OvlP(# z!CRq!l(aO`3f6kZLpkl_7N{qZi>xRPiYuO(uq{nUc$-EB+cHbL{5%e>Ux6m_10HlF z%2JUJux>xp2&$ap{KRdedVQXXw)NGVzmWyfhCng*maa2lp6liZ;K@YkS-T(~8K@3j zPeW=Zw0RTx5X258oc9*{m|?+MYC$P`ICqEMf0cNjYXou=2srL5hP2`ygbgb~Cz(|9IqWq<%6fr6V%O2zN9Pd*OkFJ6pc@uMi53N;Ejv05cc z!<(INhHDS7wgO}a5okKfu;LNYv-~yr()}ax^GuX`^Z1v@1=kWR^2Hohh(RvIs;>{L zBt1qAlT}dP+X4YG9{9gKWF4kN$e5nfH`dDE3a-NgBhgzYQ}z7{cI_A~o{vt1724%2 zl3Q$*)p`_&in_z0d|!3wnRpW3ZhJc{?wHoHEzldCT({vQ`z1S`p0vRDI#<#BCh8u!5D!V>1kIm5g|2%Gj_(W_OEz67o z$;&MAfKZ-WDqGMlGGgk+VU#QhrU)c~m|jcwmRG@6s1WhrXuO0blMz1r&2M54*>|ho z4gcxa|0xO>dNrD`Ui+T=D8m+<=^gD2LlZ;c{kPs1pTo2HXK~&#Hd8+ATilWAAmnT+ zh9C|O4@RX}rPDeGu0sOVRewJ8jrYZHCkeWOhlFKz7D7#~VS5wLn4Jpm9DgS)ZqaWV zL30{m&d}M;){gMczx?NLwe_u-hVapykHati{a=Rr|MGEo@jM;QDm+GIN4kd0SVJzO zgr%S;AErX80$wbI$BoH_umV23s6bHZIuMXD(SVnM*F>!q{V3-qW(!O z`LfW=Wr}5KY*^;}@|Z(pnA8M#PEo}ZmoHHXnn;N}ykoh*3y~oZvCxR(H#ai%o$~+w z`|n3(OuP{@r?TvWTmqz z!c}-fH1Zk#Zg1enk9y*>6_!=b6T$xb%8wU#-loMQUSz%hzDMOwBb{?}zZFCka{W8P zA<9xz?$~$vTVk}(^Cb;cdC-IG+EWdw7=@rx?6aJc>yjoppO@g}Mk$6XB77eH`dZ{= zi9+hW7+qi#j-F)sgK%oNtqS>Dcsw;msA$X6u77ns3NC)9F+wAo?=lL)kr+V48HJl@ zjDT-B|7564*o{G>fY&SFIv@X+#|k&%o9AOIKcDS2?y*Jt)%=z|m4c#0moB*B^aE1QpRR z9KV9SxVktn5Hi3sl>j5cOjmTzz268d4J%80Cme{61@Qd=j15coM?x1|EL2tl?2L>I)6oWA0{$ukOD1h++KLP|+B*^>JT=^E^mo|i zbPgjyJ{95%D`>fhvAOyf@)(B9;U1z{ky%V5&0(Gm4e)&AQ$3YQ+r0|rZXUKYQw34O z#}ZL3*2zkd5@OEs2_kcJYR&xa%W(XIcca`VytV$2$k2cOC=?$9*Wsh>=T1>nF@xx~ z*>DsO_Y_Wtj;>ST*~}zLIEFy@i77%iKK@v(iDI%NL}FH!Dc>nEd2kRQ}~7cAHW8%_~O7U{4mG6M==S zWC7f=8lr!!heb4$HEkM^bMojaBz;dhykx;s_Yp~3NMyi%&S>`#u+lpfvfHYOWFriJ zaV^$_5yu=F)#sj5qYU|HVR{a^fe5r0TXY&i-?%ptn%+7W`mcQ(Hul4BTI<3tHGC>D zP|PC3;-WIQ=8^VlAqwpRhQQ%?XxDf~r4dG+=p5TT??n0g+KPDVF z(HdIb?Fu8$IS*iJ=-%UKuvV|~Uga3yqvKFqcArhN(5s$|G#w{h2;RAf;;KPT2WK=8 za30(8VBk~u75BeS6r!`vD?pt`XsspSA+DG&E%SYtt9F9%--9NO_G_-`(^7_b)`|Z)P5N-8BFP^|)fSFC}#2 z+~Kg$R2&LZ2*C&fdZF76wUB2{$OlY*WMTwHK=n|Vf}3kThQO#b$BjRP_fvrCI(eEL zc=GSCdc7o9r}e1SAk)QxwwK5uY{E-gRT#QDu7=U&r{oe-Kn_A7VD=9U(6_WI)Hjot z!{N<8MTnlKr~^Wmhbi-_I1D3tIuy$3!JSiD942YSCSa`z5CHCR3IY!QzqGwqb6#0` zsJ8%+M9w)89{_>?0Wjy#?CHQBNi#jtlr*Jtq*Lcq`9c?VxqRWW{XcwXyDZ67l6@r0 z(pZ`^LDSQ@n`Ae00uvIEbI!@nvp()Vw6EQ(3k?w1-`;D#>&1!;J9;e)&J9Jw(1`R&(#5~H^+hDS&W_F)1xG!` z=spq#Fi6kUUJ4A?V((?4?^oADHbfv}wq|;CV3dxtXTo3~nF}-vvC)-v{iA&&DCO`| zJi_y~<#e9$A}aM&jF_|em;&GI2%Bd$(Nkc8ZqY8ifi9J_ z`7!FQ`o_ZDzx}^Rtt$*$bqDAqeKO1hJd32|%1l1{{PSoqJi^;~qTxj7Ur0CUC@3Ww z$=U4yKN(7*ysCiP>`a4OWmh8d9j&?l_~yr<<4{Lz)+fV}$#mCshfi*NB0YyEeLay8 zswg_1&FH_zwFD)jtSKYvaj+gCIzS3kQ+Pc1IF@nPP(&kuSZL?&xwSSBlOd++Gw z1?PswhQhgH=fYq8!(Vb;V^qoyA8rpfZ{7^|sVTe)BV1%S-@U%O;o|wrjLlDRGZnL??O!}<2AFWx0?({NXdHD+aDbv3a2HmpWuDB z@Paorq{8smx5L>>?+|I9597>a&%j}~yNS0I=g{!2hhg8&KBh8NhVfs2Mst|*P(&+| zxtAElr8MJ1I6H<Cs<=Mr}=?MkH zpMDyeFJGn$K1Lb_o{pcfJ9ok|JfP!UJo@xLX}@}svZlR|i^Fezi~c81AB58G!@6@q zH{${K!(*SJNL{@4dkA^5IS|UHFEJ(wx>jN8z|o{r=*4HBhO)L+#_KGFlkZ;*OVxSd zKs}Q($YR+Wq=`*)S=gFiqq$Vt*iv~if?_mY_~cPDegys$YjrUw$~63O$SD9beZz3@vlN)WYO$^{K9lPvwQYzRJyHU)~JpK5K>uKTXU*m=6xJV zDSc`bX`CAsPFAWph2nECMy1TEQmD(12H?M@|4ZktHw`rnEaCFz(s?26Yw#onfC`wk zqB=SJo%?+=3N62sx4vnt88P)9Dy?xdY{-la`H+UC*Q(ScOSx8nvbC?S6e}$U-p@pa zY?^nHHRF3p4qlrC#1cLosP~XL`2L4PhW1 z>*Nss(~4tyXWq*Obn;CVHWe=&;=)3s(svj38qsE2XkePrqf=97uMS9;B^^3sJX2Hh z`#Be%Q-M(#;r3b!^ZYe}HOw{ig^Tz1ymipaCxpFOBl2sNTIt>>cT^;KmgoMQ=lO3x zZ^@a_@$~4rv|{W%gi&JryKj|I-`7$NqrkrF7`41+2&wO=K41|?? zQfB*n-`Su2z50n?1_U&SEpgEC;`=Edg};W1M!4sdI0L-BFgF{*dr1@C&$CzN`3#p? z9}gcqjPHue4!{dyicD_p`* zdayos3+K%oPJn4Xt0C;!XpD$su6)XYwi)wRdGrv*7DiGLBaAnAC&qvpMHb%TwR}Tf zEUjw@F0JDjrCh3aus<|<4Rm00vIiK?_K&IKck&U>PdSlFQA)tRypPUz%Sxo_zHe@Z z%Rl@eeEqM#4STHPRfM%NML6YkNmiJmIH7>u!3%qs$2 z8my}rn9~@PzH=Q}d(oMLezu<=nNC&lQCvRM&M0Nl$#>!5r^sfQm|=1T?>NC;w=kSG zfKx$5x{O2Tl=_x^X5#b_XugxIH)&kwp6@HH?984bNM(w-yg>fqnT+8yKlRfe$1^p1 zx998Yl=_irNmu%jsd2zcBQ*MPtz|IXg#g3TC-;ra# zg99|Et`Eci_)#c3(;bddhIE^((Ml#OyubltUjp%H5_xLYo_%u0?vmMyUMgu@24pGd zHoCw60)w0X}il z#G$kc&)7qkp2gl+9>$rBtjX=D4;2kHaT>+K%aO3JC^uL(VrqE88+Dv7;dIe>|H(~FDaq~b*G8( ztmtyB=tliGw`^Fx%)8|i6j?{c#q1I?uvfU>Sbrbo6gU>g=+j1qvf0JjOI40KwH zEoTRP_p6Q}%;Xn3g`5;1?4&*a?s=G{>EFGM55!$@1CmNqE_B%O!2;9F;$L_GU(C+*VYiW@+En22KUQ7 zRGU2F|Nrl?2f*bc{{x&2)c=0gsyzVOtHP=O_D@6Whi@@gydru%mO!dT2>#XhE9}v9 zeVqp-lkspwE7QX5+9;zfCmLbbb{l<3U~4emFiArZnm-K?CG>ETgFSryI9{)FVXA<% zJcK}J!C_vJNI1O#>{LEF4HH|T<_hFme?A(=A&m}=L{E-sB2zHi12BrdNB6_oKmAE$ zXez`%J@&`p`Q$SUETWzWp(8LMl|c=};Vo*EI53&%p>hP!2BSVeR*|Z?DHV>?9tpp? z_3QBd#cMGdI6Vh(pxnxkRGw@yB{9mFpFe*VE*`xUK7IK)N-_o$#L@HFjj-_T%lMwj zs3q%N1(baNn%Yyq4dsSrB^4O?3igwv+Kdm3!n{dq!6@7%GOMv9g4Ym<)FHADZ(^0U4vtes|HB_JvJo@aLaF~&7k4Wumu4B&VTDtj$Y0D{$ zp+~)sqKD4&(@4^jrm&MZJ!|(dh`}TQ__I;?cr9LcQ|VRcRqR{JTIq@KoNoSwp)j8s z#e+3?=0~E!E+JZ@ui^Fz!%JZ(A)15 z86!rETF4q1n@#rxh^ap8)8;d#P`e~}nUUw+THhLe@zF1UZ(dZ=WDvQzMw>Ij#Y-2X z=hcQp;#_yb(J-_$8cK-bzWV&zu-cbalyv6UrCcT6#%c4@+9h0ti>cy8EsWK~ zpq#~!T%a5L_{?NDbM9<3^hUqA6+Zm4e;1zLe?Zff(NK?o9lGiK;D(q&*njUK$_R=? z7KZGDC*kVVx1(Y&{VikIYSeDRyz*iE#gw4*+`hwk(?AL3ZWX0x5oNR`)q)aE6wfAY z2-clE&XkORO_WSi<`g0s2(H+03%q%H|2}01xv{y>L@zXeCt6|O$eyN9m`d=Pw=^_` zZ@&17Ndw2j99b?p4P@q~p=qoazFp$DV95}d0;p);Ck zbDA?(u0*D+Kzoi+z5@)0QGTky0i&AMf7(Dx{I&mtzhA!oZ74a?9-lD`UhRVGGWx5p zdr~Zb^GJtS^ESvc&;QAva6bE?i31Uq*7sM!GYY_s!AVLnn26Fd+!xd6O?6B)r$Rjf zRDmpCoI=p%7ZrrAtCz#`-shB8z(0v%4F9KJg-Q(nS)wTWxtD7T9P@KAdJ1f+P$6q_!GaX$WA#oQ5UD$6S1j`9=7RooN9+vmqf$WmI6 z`%Y0Hzcx}7#x8qQD06HA7}GXUmQANO3ZqggPt$PI05|>FD6D)#WADwSG3!1xGToD3 zDs39PI{JysHn!8e`Kc5l<#Y(c&*ENehpjYlBF?Q z^v~H|nIVd?7P2;|RTuWGcrU)IFlq2Dz$bOa`+Lvb%m6bkRHPEc*w1MwDnEp|#(zwM zXAdqFAOEh=r$XgBMPr=5CAH~Z7vBrIGZkG}3XjA9))}F4<+*rP-cuMTGo1CEyt_uH z`?YD}qlb^YZCpN2g;bcR4EtSN(itS5b)=o}_UtvBjY3=Yp+mu?vp`(*oZYi9NQ_hW ztz6NF_1?n9hQLOFx{szuCB~cZKk3FgW%){Cuxjl2ESuixcu7+4y^pvduDrQ4j>SW9 zMg`H8WOu!Joj?0`_iM?BOId2BlM1Mct9TNPfAj~>$9sDAMhUx*c1Jm<14x-CZo4;m zpt_3bsYxGzH)%%RPyM zzE69X*Vf&o~bL3 zpu`rA@6cLF*(lLn3cN${q1kV4hsH$_J0pv zYjfPg?QLQBo1RFY22b8>oawVqkkWtu?)`{AI-?Q?qL~1u{5yfeva1<%)MSE+pVMG% zZl_+J)Ny&NI)%SeW|UUax8T_TQ?zQBX^)|WzL3G+ci6iPe|3fn>rH5Ah2IG?WziV8 z4YJ{M!0-e9i|C>n)$;Z(9OUvrd6vzbS6({`#`-YMmMMAVUeZ84P8@?0gAX2rvcr_x zY|#OIo<0cEM4HJS*ae67pq+X$B9;gyh`mpHo{$Mx74HAyKZRP1tw|gbAO6>W5wjod zCv$~rfYMf* z-MXOE*hJANt~hBnkhDMcDy`2wz4?F)gYwXHl7L9oPN*elHbLo#QFZYr8jRe>J{~hT zm;PiD`R_w#V-#yD_^eySmpIypg zaY?!)@s=J2^I?Jpg^xe~ENoL|&_M5=!D&h^Ifqv`U5vDElX;g_m>aTj)KK6hB3pDu8yiZ_K=wJ`=;%pVecPgU{X2Yvn}Paaiq8@ z4^Rdf{r5WIAq>Tj{Hn-Kp|Z;SN#IRyt@{zRgTryNupg%qN;sLWkY`|6|cd*^?T{sG(JeC@d~u`wBjr-=$e z6eX1<;nv-6jQEe;O9E5R%lp&3yBi^q#b0 z=N>nS+**&S0I=be@36OSx<5)C4!S8u**P*tFS1DLh_A+$ra1d_6DNl0$fkEI*i~X& z62)=S?S^rPsH|HvtC8k%|4CG6n%)4}lgr`OFFz)-w-H)Tb%dw=z2P{W^%pj1tc4P} z!bp@n7-$MZiKLux1S2_*$ezZVhOf2jdQA01+m%#hNDrrV($+Ppg!;_ENunzVG8LEg z-E?!c0R)%Ijf5W^1rUvjtHi8=Wn)H}qi1up8KaqThV}JKTL2D2+rwNlgYi=t&rJnI zueYPzwsL9Y0$~>JqaKv^kO|y-cn@!2NAw1&Kq(~R)%yRL)L3;@?q-m!J32N>5HdfeksiiS|ECrN|~v2;Ct!RvQdg@fo^Ul^2l?h*z8Pi)|twj(L3V{rBQrbA^L7kn8JQ zkD>Q$xR<7V>`%1!&3v*GKHKM&X5`(YR&@;gJ;M!<=;N|d*R$b9xb&h_Tq zkm~5B30*20z3$m_%Ru3j*;?yqeW%884(D&uSvSP(XR+qc{i(NsXT% z!ee^ZJP{F@=n_VcB^HmKJPteDtB&{6qnk%c`#8d=3}slu=6Kh!kdt*F-2C**(9uei zvHw-X0dXN8!%h6Kqw^ffZ!5~F3Y-E{yy`@l3ukde9uplHIIfIVs+<}*@$;U!=eG=v z>u6fxy9(uvzxu0?1^(Xor+*4X>`#1)_d!Wr=In<#Hy#9za1U@r+ETDAu%BZXX6~VZ zGrfEBW*7(l_3VF?ciTX*vflE@`O{2Ez!0SNaCDHK4+uKz5^aEI!=b%RGCeSwS0<-I z_h~vI-@5~Rpf_vjaQx)+-Et=zKP@A007w+-D&NPC9wSPEQAB#84KfQ3QDZ+bMzf_? zVQiIDLn9(I-CNy+myjCU(AgdpLzSV@V$#bwABCIz&+&dX?^7vVS)}L+C!@xH1(^kN z<7scW{HVB^j>_PJjyP*EPnWPLV|l^~`%-B)qUJJn-}5wrtAQy_MnO&%)SJeO#?ra-=Yoc=yh&ax zPj|%ctHeCJiZhi&+lB%hCyrDTTj=WRiw1Pw<)Y6(j0? z_t`2o$up!~X-mhc(Os35WdDhRW175*Lt?mjjWps)jLu3*?+OkRVHp|@>p0MJXe=uq zQ_1$3Dk4$wiJwB;7@_AKTq^on2G%Pk&z8UWE*;ZyF# z`$fkDbnSUdlN#4LaQwFlp3Xh_g3IU0lYNHg=h9K3Q$=3o_5R*-909KHy!&p<-f}kg zyYIcrJEd_vrf>s44L+YKe&~pB$wN)67OpxVp zCr`xlbniaHrNhH_RPtyjJ!o*Cg2 zHag>!RYw1H40z_sgGeiAy~1AH@>xc=%nE~Pi=t`L1zZ2%+|5YWm;Q-l^8fxxSI7oBe&-=Sq-zNv7XS0N|jIQQz z^z^AHr*HqmKZMlDlfiLjK3ASDj_EuR?&7U`PHaj+?>c>qL|Xfvi*-Bwgbb7= z@R&S zuKjj|j}gp!H<^0V-5m{a>2;0w9RBuO-iwJQ@C^-kW#!Y)J`b6|xmh{yZUm&Yy!}5)Lp$sRwfhze= zHqX$x3nh$t~mrO{~`J2s+Qt)kCQf%o(+%O(9^Jcu}pKDANOr|MdPs8`0gp+^#<1kHwqlYPPxk3YS8V!##PY62k`O2RW zI_Tnp_nDEY4r$q?&J5pCdR8ZpkBLW?Gk9-#Bfkn=N4ufNv?Dy>8<2mb zA9<2IO?;9@<(JAcjepO@cQ;_;cVQA849E)iFHevs2@mCy_i#VHhqN4dhI=|#ncn~R z@&8x?aPj+{01^8%F2w@ZvRlG4hm7jx^W+G41Fmaqj|AJ&6hp>nk!#GQ!Xl zW1;|x9oB6sW$pQ^1x8=-_k7Y|^Hj12X^KUIIxPAKv?v@g~b<})!SGKqLo2iApR z;h4LD{(*3z^-?Gy-FR(pJ>)^0PZ* z3Wo!X&~bzwsD`QsEOMGAas^qz`<9=OQiXI188hV8uL zB=C`_opG-+IyEyH{^HVKgm30(vV>r~a^Xt2`9J+N?x?h9P~@zsr|}AkaM$tfF!;Pb zGNhua5?oZ+9Y)`X$Q{JsAACL#yTb2mA|Q>tRWX{QtAz%Gdtqu2=D@v@l}+TZkF@R+ zr;bMl&G-mju-D55H7Y0~uFN5eMki~%lwoksd7^DaD1ajic==kJnaxg35wOq03!9&f z;eoInKrqQ5WEO`isJDk0YWLwq%(H$mBeY=vRph`VvY~xpgMy}GNMaDi!a*fQqRrsH zdVVL<5hrA_;*!^7a*c$kGONe8cc?ciG7_kbdrY%G*+94T*`dfJ?CW4kxc9M~L`C7t zZ@-Kw-A7WS#cwlHxdM+PDajR8>9YGqFKDV=_GaM;968`p||29Ujj~_W6 z^0E-N`HXvPO-Er=etaiqvA4Azf)+3=PzpSMabp1EFHtsRGG>-&5Q}T~?%fZg)PA4E zvDCXU5(@Sak-GjkmUDPaNt&T4Q`TA=CC~^E778OHTuXz~bOa}gar|(|sVNH?bith@ z?YyL>KCB@)tBarydPq#%e;AH466W}aAB0{!v)OqCG?+aQQW%fcsH^;#S}H@+Xi*@$ z|KZ`G*yzvB{zj+W_Y92p(zR>hF>p>&pJs>@aiC!zN{`I78b#H}b1wLA!?cg+mmwTB zP#P>R*hY~!fbycEYQ{q;&HzggbdK$T?_*@JG=LB8=NbE*L~yO5tXyPNQ6tKb#=d8# z;_g2CZruvGT$@UzqT*Y@?`6I!%U-+1J7vQQRB%jlR#3S236w!I0jiC7*U50xG9!xfwH%%>GBpX<`d z(jlSZp%cV2l^@89grhu8JTk(oB4NZ{#a|^r!^?Z>kZ@^uDwn*U_c2XgN2tbywB??3 zD5x~0UgN3nB93*UG^&s$OMaB_LTSMF5Z^Uk<)8bq_eZ%>bGU`fAB>C%;KM$ZL&`dr zJko#rS!I+NZgdQ| zC-t0!rlb>{Y0B?Jsn)<%2b2a}KG%`O4e+ZSU~jJw`K4>E83#=t_b)#fHio7dDcTod zqg;1Co{#S@oQ0tEW9gnu+o6K9gpW(b=;_^U>EMRQ;P- zAUZZ(T^N3^kZ1NxF^zp1ex6gDo+L6wD!NWqWwOr$m!n>yZeq5YI6sX}wZ(fzT;Shk z-ky2q-EjES=@^s~F4BG7A>;!QaI*_17N_A~;4$Y_ge)<8tQeeI0nf6~K^9+-#izrJ z^nL?-yXcV|Z9(*v5GSuhy?!}sZal~%$GdxQkTL^CXTr>N&`Aj9eZF-8V zU>wn#Jp{5KagAdgMY+ICd86~hwYvx1g9DC~v^>tSbn;D@5~KWv!^D$b8ZB3bF)|># z-liLBd+Xy*(czlufxwtVXroeo#C=b~V{~ZiWVHFM?=NqXE~9gmd&vjf%f$;9;}ig+ z<6b8}*+kY%Qmm-MYw-yUZPAh3=Ne~NghO}|$LE;~=ff!9tLrtE$x?=nHt1zhNDr|M z0-DRqX&!~}iO-dmqu~xtyANf_n;CbO*2Km2`{A($O3h3#_{Oh*S-SMk&zWs&d4W2( zcGV9j7TlP zh|SY7UMW?QT!pD$JO6%oH1;qYpmqxO4P&5#@2#gH^kNX9M0+?I zTOx?5CW|0l`7s1XswAAMyAZaZ)LXZ1h97oa3l9e$#kzANxi@ay49%(L==FO1_z?;x z>5jaQ!nn1T&(n}lf%w%|UqvKzuc=fj61j~4^QqB!^7wJ|9Ep&o5w4>AKA)qm5eC1& zKJ@Np9KevAXCx9eO-8w#p=mnRC?2x7vLPC3h`is%3Rw?ER_HPl z4GPb7gq*gzu#KZ@bBKCSn2{-{8pjf?%9x5oD*{_)s&H1pR@iw~?o&o8^Vw!>$wu#J z7-UBM0St&SG7pTuw0?-csJ17AM5Xu^QDHJ^&9^R(~L9Ed~$h%uUAnmA>nT@doAE@Pb zgGBdRP^dK4#1RGMws7QZ#bXr^6*P@L1?&d+)OPxKY|b~eIzx^8ILZJGn4rnSE!0j{ z*U?+x2^d8!D>Q1x%5$DC934Y;kd(PY)d$1CtvjI{m~NBB<9R8(Okw=ym%ofn$1->y zVIw_@>m}^v05~SS+dxrxtGMe#c#K13Z(}i>`r{8NZ)gtF&}e9+$<%WUF6ud>0}$L+ z_}#mGFDjo|I05%ikWA~BCk6TmXk@MLq-PON;9RtP$taCKUwVg$6$3-mK&FjR@z~NO zQ~paU(`6b@9z2d|y9!~a2B{Lu5FXH(scK%&s>rLa|y)|RxXylvTDsI{#T;8g4-KiL-&z}pg z$herB8x7rO&xOe+eSR$VAF%${YpjPgBI&-JiLQa=dm2fXu6?d@+T}IT*~0t!JZVFC zYA^~T=|Xz-UEf@OMuRNYjss>5lEfk6b>2fKi)r~Toia(3RHv~`wn{lW<+boh5&hGs zOcX$`_xBq5o}$mwagjpiMrRejY(UOwxFpLxYWO7Qo*4hh-;?j2b+SA!gAN*Xo{MKL zzUbgd>f+?7&VAYQ5rCip3AljYef4}7-9ypD&&kk^snJ0?+3d9bPFH_<&3rQdh( z-ky^(Ne6{`hj56_4&Ga%+Gn~SWn%(&9Vq@@`L1(9*)Ol~3{uTFNO4%X2l3TtxI9Bx z`YfN5I8&S)AP*E@-Is9p@9H1&rZ?ddGg+XKgTTx4(mCMoe1RW1BewQGxEz)zW<&l0B^a4BGiE%VOPW(Z5mrgbhwrK0;#XmHN!WL&nzA)Y ztkl22UwcJqa2`hH`1!`OXCwaFk=}h3WBeQFkzU0Gd1N`bZl`$V;owU$SQtT9h_O_j zUlfgB^(tkqF!F4r56?NP9vW_)L~9Mi><~#^pHDj> zb4zHPO+OY2iDCv{??^v&H8iXI*^k2TGwS$TTBClkfoeqDSq|j5Lssd|caIp>Nl-P<@g~O7M-+(u%Ne z9=srk=o#6+MqjmTN~(*=^0e_`E_$OW_R2OnsTl?0 ztGHs&R(g@=xd*>YXSauzJi$^tO919qu!T;x(!Z$&#}38@^0fuLm!7w9>MSZlxaSDC z!cD{S)<#%=^o&x4BVo}DZ?cTFNrbbySZuu8-X7s2KX8A3-X*Uwn_T+xOx=e|*zk{t z_x}4hJn9LVrO_Z~p9Wma4DcMa13g>&&1jceVxzw9{p8JNK*|S&wfrFk4hjR$OP=Sm z4e%L2GFx=a3|bhlx|QSReTK~x{q8x-Q{=hgj?XpdsUG6bPTI<2dc*g&bO01zqz6FO z_tyiU>aEj6fiXyTR>B;$hxK@{ULrv3{(rQI^xa}S+Ptuc(|NcvrtMh2Ekdd2I4k{= zFFpyUP!dGMVT8yE%x0fa%K^NG&jB1YKN7PFlTqOI_9H}-UWNnBjCP`9xy?F0X!;=h z{N_K>^|2&8rB2r7NmZn>E{)P~F25|46Q#D{okp4msrOoCU~y?8wEW4nkW)(P>gG(? zAg$}^2+B6f#|Q6z5PtQWU(p4;3x#krBA9y?VeIZN(%3~l)s%|Far*S>NZ=CYOZKN% zO7E>qMaA=2%kglo{#@vr>x;rJ1H`ee{b&a@WDBJ6(i~*_%co(=>xJa-6Y0=1+nD z)`@j>b%*JByz3}krh+?vbrt7FI%=^+Bm_?y5nk#ULf3!sqp;dR6BbhUXV#e}KqNT> zfj0Ik?Mx5>T^cJ2;~GjIWKb%{3T2f$5nW*-VV>zeNyl~O($dNFtFqr^yGe` zvM)n+;a<3R>zh!Eab^v!HR3kqd)WUN4=vdh71Y2$I77=LG0nb~`nnoYel!9#(5I;- z)3E68r{=ezF&wNt80zvcq}JzRnS=zcXIXEY232!?b9hQ$0-4t7rqkh$-gJJYewZcfVu4YX;>dEzuF+b(I)9GQm|~kPTBa!mq$oFbS7qI0wZ0Q`BV- za9ty`p~C0igmurIJK#k{yq`{3c+Z$fX0JD zD&ZM1)eNPe4gtAWk{ucuMSA+3EAU9l5lC~Nqy~Kgg*-nepL)V(oIjNP;1n>5vIIX{ zBfZgvRI^TTps=rul*nHB4DZr|@>K&)#rKD1OL5TY6f)9t7bQ_+Y8aR=L^_}=F|_KG z1IHruJY&2d(f1Q?y%p}Fn5BqR?bMcq70Opy|L_{4IG=~|R0AG z6NNMUNj%?O$2-0$KT0c2@}m5*f|#XZsnW#EWE{<8DM7NtTi5L3TpR~zmuvCFh>jhe zqeBuyb&Y-!8c>JY4n-U_vM#PB5jF2oOeuK zx=On<$TfJ%;8nN2y%nR`Mzj^+8aUD5^dYQhKtq%NuZ1q+zVF_-`<()zL7>v4BBcWA z{*$GlCT{r*d4o%NBCfb>nwmHOimS>fqbWyL^u>M)rAH1@Z;K&Fn(!)RU(4{FLeocS zSh~mLk3cq-UBGj2Y!qWGFBuhLY}ldWojAQ15lPqX@+La9A7t9W+F~dr{dkReh?F4}VV@ zN%=dCElbBV>Krj9oQ!tC?qiC&^zP5DWREIbNv29AxM4p8SE`wsViZT;K?P5Tu1-pM zSYi}-T~sdFw>)1Z-QF}h95nuY7o++vXHnZE&yodsvH0nkMZ*^yP;UD-d7N+%_rxy^ z@|cp(yXi#op7MR267n%&DK7dRI_Le_lzW#jaxcnxaY?)qXZ*a+5l=k3=$Mcf@jRpc zZ@!-n8Pl^%Ym@q`|nX&0mx|Yf0n11~ASrM<| z2l?OS%a@}wR(J|K;iB>G-g9VzJC#RMSPWL3XEtKNX)j>DXH`0%^m>CDNB@eb|^#T zAIc4_Re19j2N&`amer=Nxv-rpw6I>YCCdMNp;i5aRrAAcOqQ)91un)&A2P!6sLp9A2Fa?UfB z1~R|{W!ADZg&fonfAJ5zFCG4ic;{WRV$1oy$e!2H@e62DSXiDOb$sH?*_hophHh-; znUiTwk+JrG-Un|{3iuSKvdw8N^(?Nc33WKOpA+oZ&vSI9G$1F3ah`8+b|a4-i3s7n zpZsCe!=~WH<=}nl>=`m|`ohxBzd?SGRke*H51l?)^({ESd9Qf(IE<6EkCggi0)!da z-~~ppOV}rJU>#k#lFZDN{YLP~hQhI0oT4Yh-gb=4Z-R^Kz+W9$e09~+$7rd4JVxp> z$-eC;aME~+K2v@4&pJpXet~^0Gu`Aey3ZKn7dwza|NLplA_`ZG43{5@E8?em`|_q? zGse5pFRb$9@mOjrf4uYSk2ssEFgr=v9iMR}MzHeTF9Q(TDAJhsi~I)OAYE;-@7aM- zvR#=)uhRm4P@0befI#YjHTrVVFJ~V@eEc;}vs1kRn@)IRk^!KO>@$t@i_b>fg|T#& z>_GX$(2Td5TYS;E8y!22SPUbXOmo<7XR4Hi3iFqXaD5TEg^i?qD|)HiM6A zNpDTRjk7f(lzal3mU5a4_fHbC_DXa`$x^|HR z@>rXjx(^+U&EUI1OYars49<}6(*c09jUE6v0Pyak6?{J{^DOC{OY@}vr;RlDKs3~> zJIck=RFOef(w(_zP#z$?cxX61j%^U7U*H?jF|w&p^+0T>Pytgl6={uhnjAWd7c7Gm zH2XLJf-Br?cw)VK>fG^g_7C4@tRUl{Af(OA^>DiG6rYD-k?j6!8=cDjaz!@#$6(f>K zcs8DC1ktAvZc`XMt<82nrTl@tnnKx9g4dgURiHHWQj@LmFTyHle1Av53{F$h#Oi1O z06+jqL_t*Z45QhBaHoI$ZOC3X4Q4$a*x3t|R}76Zf~+nIS?gGIVk}RSZi7N@-HuAJ zgkk!$2Gd$5lMXI+g+}V;>Moq3)|Yv$lvOk|kqV5Lc?n_#fT5Uv1$ES~8c`A!i6Wqa zr$ARxaE~Isk#kcwD~qba!{2?y%&XZ@fk%Gyi@V|O|Mlf=D-vB^Se`1HDBF0?BXvi@mv_I6`#s*pC_kJvSI%9D>2eZP%fXg#_xat(Aa!UMEs|;ZE)uhF zmw{^d8s+%nt1sd^UOICrr0|y73{u6a7UN2$can(|&tE*pbGZ^f^QTAtG`v`R&VBYr z#Y_0e)V;4tj7p7>K)>`biqC%c%=IYBuvL<;fBiKhbkg2d8P55d^I>R_jDezb8H0PM zEG$QhqRGnMCY@#P5(Z7*+vh2?2@yv{I5Uq(tOgkdfoa1Eca_g0huXrylP7SIk`l?a zkH5JWN|_Bef)ij0+GuV@06%;f%3w?@^lezy=)H6??lJD0cM^u{?DaFlDBiFPQEgyRg)ug6%?(VzoBg^6CD>4VCf@;9^RD6e`fN_md7(=!~HF z9ySZi0!ACWr^3&3R=E@gQIX_1;=?4$&7L%XvAv9-Ti&H67YD#jUIx8OULdUMqO!5J zyc#-nZVnEGLH2#HoiRH&AL@=B4Y`F(tDr=sqPj9X|Kcm2RS*WKE!-L&iOvayZVNQ` zyMOr?jO^AZe1ub^0R)jhXLu$^wgvDo2i*6ajT8;)_(CZhq7hFP{AKXQO$^G~kVm?I zF)6GmCP@s;PtXJl#|uuT1N42#;W{dezH4l!lk!jpqyI?f-=sf*jrFX@l*Syl6gx9B z%1YzEprSCAE_EI24zDP8a2@GpY$X{4%NQ;z^F&b@o#f<`ZOV+yAaFT@dyvlA@>gLj z4u~%a9hjCb?&u)Z7&KC^!smM?kzb84qn{f8F3(X~Ng}1*LxU@c9>>qZl{DmxekM`t z#3+k5;eSb^FO545G!+sZm(sR);dhq?kk9m7G)ALALXs#xnAAkUOb zo~)#SoxhV8XjID=)D2YZJUg8u(SgD}lk|I^>HUpR>tNAn7Dr7fmAANruX`4ri8AZ& zBaZXkh_v@emU7KVsPAoLDmo6}Sqc8RuO!1jV_iknNO1w^^s2fobN6?JXhb{ zY@$q}_A``t&d{4@9sO_ho4!zpA(~7I@w#YO^La}EH1-`QsLoUjq;r2 z2lz7vKRQIjebU@#vY=N=UZ=kLlBoA8x+(@yCY{pRJ04;QE3_i(Gx$&1dGC+@C8cT$d_p(yh0gTc~NOt8=+SK z8K_(x>giBl4OEUN2>xxGBC0 zlVnNb{=O53w=yv<-ruzaKJM|(XHT6CkAMCt<+fxEFkM3D)Vegy(!pV`l6&_EI$a9o zdW2r3GHR6dkP_nv`HT{q?imOhjGprTuIObUm1Qmm3Z;g2bbFS1F1&2{h2i$&TcNeO zHDnb)Y%q`+m|+`H-g#2xHyCp#;1z@(vMY}+)>{>HB`(_w9W@<{Ih%;-Bi5lEsyP&% z4n2)V!G&g;98UJfgEaL+Bg}hgh@B*Yp9up|_?hm#fmc}vhYCjTSa0+MJ9E}?C#GGg zpuT`98Y$D0SAo&-6i31_YNm!hy#rIXi3YV*Fflv#yR6m9gV8HoMC#p5>l7KiVd@#4 z<}n+AAhbo~W(@Twbk$#LDxnG4u~39SZ8>)|JehbEw#%t0JAF9JX5vVpQQ-UlLI*G^ zL?gn&Xhe3GikQgiN(>_#1|F`*aD4EBF^!W5ib;%n3=F)Wo3Exr-9Ab;{`&72NkbYx zymNbmj=&RhVH9{2jv^IiLE{rjUt)qM?}d?JVoza>Kc%i=n!-COjQ} z8uwt@Om}5h=$q^dx1XTILVzkE!+2RGej6FaT1=RP&H9XpxbL@!XsTGqtW;1nz!R@& zF?)FN@QJd?f1{7Ry*&||k5#fUI?{aFy$RN*E_@QX65`pb| z@+{KbDxSzA?Tqjt{jE}OFiL>?t%SL`WMoA+CVHPfqXvx(8vd4oM(;q!8sQ4ACX}Z8 z7|@sAdoK*!zaJ`zMvF7Ttr^B^TA^Ol4Pd1pkw!e95hBv9DXGcalq5OyqH2M%+e zeHNNO{E%@S4NqY^q>Ja+&Zalw>Gof0-3vd-UVq5{o*3-g=oryCEhgyzNJ9+EHym+*+~3(@J{^mT@?=X&~-hIHftqKLCmH*byFt_(E_R8 zXf)Y4M)%VpI45gA^ga+)U-mK1jdVcXs|sVseN`d6mp50VAw7qq(9u_gjCsq*qYe|t zf)OD1xDVJ1=S29a6sQn-4|(tc3iHvo-;RonB{gHb(;R1PbDm2VFNHh*{4b#vr-&V< z>o|j9{yy;dQK&pbbZ>{oK^XOIWR}!5)1YZ+AT}k8BLq2*tUa1|;anAmrJXp+^|kT7 zz65Qf)Y|B)3m87W{V?|2up!_!QI`qE8dHU52u%9{$ApRsN-2cD$^LE0A&{I1~l8S?SO+2FlYT#SkuF&5{noA&-X2E4b= z@wx6*d6z`EHyLr&_M^+liKk(YCZO{~1y>&-8*uJzWAKAKVfn$Ukb3WY$R_1^a-32s z?pp?ZOh0_YXhzaZaoWw^>!a?K$R36#`c2FXDT6=ipvlhI7n&RCUx0$@`57gZhv^_u zsS$^C_6b+-<^ELGlJW_iB+^psz74E&6lfF)Z)K%My!Z2ZVW87Y!&Jjfg~<#VuTSdq zg_rv{d*)2!dE&9KF`6>a*B_lSIsse}M_%g({#(P?GZ3B{?LOB%cs4F&oIKLf5ci@n z?n=H}T4G6@#-!_mAAS&dw@s>&nt$I$Fz?ql=^jiYp}wM}gA-M@$9 z_+$(~G$X_6Na-H<-#;aCN%<7C&`*h)*&;?zJr8w0`NI3}zaO(&r0M8DVQ=e`qkO}_O)>2~*uPP#4edfVKoCifw?^b4L zjElo7I0rxy#?PJ!8|4M@9Q(icEaV)c#}#}Aj5SJ$ z@6#l22B*Ln?+IRN{JWCuu?$Avi3^sSnHeiiW1oji%AKVKBaSU%Z^!KxAe=+Wc&_xQipyu(RNi#XgDCdkT#*DX%b zyc+yYuk=M4^sinGg*J?2GX~|6mdg5F{;kfXexc*89-bxr$m6AvZJM!nzJ;E|=j0KK z;NdooR&&U(Z1l53-M`(omJ0tSyWXdrclUG2`;#WR$ zAqUta#NEeWFe0aSRq(2md05tR+r&walfZp7@+u0)RAGv`<)u&q)9Cpf z9l-0F!VI0LT}Hv{iDnlx(0r!~gSL~X`+gh&j2v8qD2Hc;V+V3mrz+Xo1c+w}+43MY z8l-_GONH1JlM=jluU1fwNXR*tIv*xiCQ*c%!(EI`4UCU*SR6du6w3;%$93N_Kcf>W z(0U&&YmjIzAG?fFY%_}Sh{Vo7)??)eF_F>E=cd`5IeR7=MlmJ5yNk#wU2`dUSRBAp ziDA7k>TFk1E{UY6H0#}Twy8>TU8AXD80qLT_5yG!fK1TwYrA-pRfxZRd`MB^$cH*SApaw}{?l?jxF_@PYV~C1FYc zDt-wg+{PJDRYs@%MGOsubbqa0fV04kGuuM05J@FFF?dNxhC{T9@BUGs< zt1QRBOhsldA=`AP>mbb%!2zd5{PgXg(uI{&;6@s)^gM`+C6~0F3un%UKAPF6$jLOW z_c7o0wefbS@lg2s=GWmToj(bWMju5b-&80g#3~p%SByT*u30icbO?c}p|!z&Rf;WV zak7KVQe5|M(PM}()hW?J>B62lPb~j^`@wCL^i3GdK)871Vkplo4`Y;q7+F>E+Cv7- zE-i#JmFL38&%O-#j7-^~!QVCl%o@3u&tKvNCqsfpj710@ne`!zCmE)-j*ea1BvZtc z)T(AuHHXGA_P!2XmvP#?&W2D~Gdfm{S5&8pY3+p=OHRztsLFtOts>-0a0cBavY*4> zqk*U5!FgyL3kL<0!a-OnTI?hnn*&1E@&OGRua`NF-@6yqxK7V%2gaxdM=8%#psiyZ zNOQ+|Kj~?DnoIy-Rn30JZ{H3h&{-}9y6>n^6dz^kQ84ff>)7Dh&MUwQKRrQx(J3yJQ0_CgvKU^GLRVd034fRl6@?{Xlq`UYC|@djeP4bV^1w@- zbuM}AIDBe%Xej*X&;LB$Cx{QMuIt;;7QG zp;2Z}w}cUD0BvF!m3DYrDHAQklcAS`asMj)MtqXSmnY7g+H@b`KR^u*AM7rg$TMzGIRIT6>zE2AUQ zlSZt#u0zrhg)WUb6&HB^aI)o{b2zm!P`F63?R&}SvK$<|G6S#&`jHbXJ?DJqlQTc z+1g@1m(-yfd6hneN1X1#GrdPeRmFFPy(#|Q$Mdvjgy$en8y_8y&H+mk+~7xgU){Xwi6C**Ku$;$|I-ecWa5?ibvRpKrc8lo^ z)X^4UK1n3r8uOFqFMwY*3q`R839qqhK zhLqV(2Fk40mPTS7dnq4oBr5`)MW?VjbQaExCG;W?641@15HV4skgTg?3?Z}fx`nv<`CU*eUH z7BgO4@)>pIb@p#y%HC%3gbH|wzn9mlvzig={k=c01U-*hI(FEjYh zX%p%K!qw5=2A*`LD2H@b`+Hfj&lTS43F-?rIsM)p0L2&Dzt=H<*(VqYw!_Gc`AM7r zG>V{ZTc&1uw<8i{HVP7>es)v08G@-A&tN83uf7-h2K%CC**a<&r*%IX2}^sVW^mZf z9^IgxdHAb)aUOVDAf_8Lkz^8T&SIcVjfCc=*08jau0zQNz@~UZ6?A8>Aq9-C&)+@` zGvA`LvW&t@^iddLFq=}9NsVM>H)&z}7;!<}{sP_^JvE1G==@5G_2*xH9*rD@kAmRz zvD2{=wo%SQRfq7{k>Um7?~@@RpcU%AyMk^2B}dP=Mu(1&pI!M`_~_g;96q^j9e7+4FSlq`D})b?HjLKs z43J z@I1!629bEG6F{aog=57@0;`iuptyK3GAWt8>EJ4-%S5tPc>g&RO_do_H)UE=DDnj` z%^Wfs6ehw-p}F*%uR;U$hzeq1r-CZ33(rvmR4Mdh%99F#^r``C6TBP0{cXtP=K_@3 zR_H&smVd~N2@B`8rb)fy=!=Hp5_M^gU4ZFs}7K(os zFg0bdnBUhoAo%!v>LgJVjOPuQu@0-~#RopSFzsEGJeAiIT;n^bNT(2#zN5`S`*1Q; zfHR(zjus8KO`?daTw8@gbp{yTzjr^rm!Dn7VbJ}-weJi}_h*)ZQQ<{Cdm1OlWB6Sz zb%6Oe8(>aRm~WyGPR~q+V&K*D-~l*Evp^KP=7V<8h4&CWX>M(ajUVTii2&1)-{|4; zB$-T;3rwVF4}-Vvglzbx@Ykv0xry5^dEO?%sTn8NRBs;&3e8f%g&y|Z&bw}Gr6Upw zXg%d4y!$vt&OGNOz1+Ra$U)xqAn@FR4^HTu$ zT%gpe3S~D&#Gt}tMt0Y!?x_5@SMh9x$c=`$4pMPnL)2)khO2xwl_Ez6}eb%wqlIvwVwNZX~K1pJ7w4Wn*RdIwE}^l}NAieLO4QO?e@ImzN6{ zmuGAWsn^RFeGiv^mnZAYdvp1|(q!T+5%%I1h!)|m^6B$^PoL?O0C}E#$w<6Q2ZaBY z?v)2dM}@WTFW$NQyG~Adds4#S?~}j#vvebF`%b=xaIkzp1Kp)_!~H1tlV|&TpXIgk zQ}_3Z{kb&a632uJ`Q!K4hr(noo=?=Fm_b78#<49@(A55tikzaO4sq}uFET_AP%aO|04%1fz57;gyMSZB#;C%n3LUf#9_YIpu#ryfMIp|O|LZ5AqqZX&FFw!DAEHUB^4xb4 z|NL@1wlpNZIKI@r6pQe1gEp?}gEe7nfbnbaNCPR#@$VKq#|(i5oPPD^kA%V#?F4Cv zrXw@wcuo^=K0+Wu<3bs%V|*DrNgZyFXT1tMleMoq_w zY8T_QQHP)DeGyWWu04AKOmlHojnk+Ur<>J)~#I3D?wbPVoCryv(e>=2SDXJCqidgS4{mkGAa=D;`wqaG7>;N zOhF;9&{RnKShI}Tn!V6Qv|__yu&PXn{6a3dRZ`( zOHN=&bRQx`il#cHhr-O-Ok|28*Bl zMPWJ8KxE?xso~GUQD1V*)t z;EOA9FYj9d|+jcy4~ryvNQgpgE%(u9!_@)$ojNXOL7E$W7*$XH<7!Rog- zJBH`N$Y=M$jsN98hG9mftUsehvyY}xWP8Mv=wU`L(Zyckz0!0wOl8c*h|claL|?=?jPkCI&5`i+3aT_%8X#dNN{~vwgxxpPAC)%^ z0tI|KLbZ$XgSkyQppsqSS?cuA2q{mQ#=e2G;&EggT`gT<5ux2!jW->Epimtg8Dw1C zbj%3wb21o(w)d$kC&H0g8~*NBe-{nkj+Ty4Ur`@Qv&%3*QJC@KSAf6yFh-k`9Xi$- z%8B~E`s#it0XGt+r^nl7k$OY*-$xOl6g<=I(FKFGM7!^e)LVTZtT-wWJp7e{~$TR3T~JpSynI1=yp z`San{=btl~qAcQsP9l{~;caF?V%Vr?IWo}foDP(%MPQ|Z>I_5Y3(ruN9lur$A9vj7 z0%?|&hYp6G;l6PAJdsen@GGQ7^Ip<{%ZR2a)<$j|-()@9Tkl+@#N$DXLMIJR6XQR- zh!QR`9ULim_r@KjQP>ltF!nr|K$&#e7r!NJcu zA~dR9^1Z}p_gppDl_QD4=`|{RUgzhGh)Eme$nL~(A}*-hc^_e;Vd|MCxZ-uD%!{Y) zL0Bd-$op&5*)&b(fbU=iNs`GTd?FlqSKnJlhPdSCy|1u$iBHm+yg+Y`zGn|{mMZt>Lw#Nub>jn}9H+7P;}S=_zh|K?DV|EhIq*LX z4$sv0OjhoxR>rK(#=b$;+Ut1g~O*#hbPx>&}YChwC?C| zQpOk2Q^3qao9Z=n0H-OY-Yih!**g$n=jVli@D#Une3&UH4%-8OP*B7JaZfmxRT2ru zV082!S@9uxeD8EaF>$R+kK?#T1aRw_YG+0TH;NhrN?0hv`B4R5pd%xtVjR%txy z7&}c9-#EEu2!2jy`7Pw+IQKe5Z>mB96svo?WVW1+XW&S+3Ill1#C~|AxYE&jm>>v_ z!3}VYi1-2Y261YZwCuz5ZHRg(=Vp`N{rlnfoN*O!+9d+M0xd0nh7mudQ#)OXU^a$^ zvY90*oXu-Qpe?^$#;B~KiC;|T=I=VO)XgK`rKvXYImXW6RO(>D&GI}t%yQV&Am`d5 zWVqRB9BAZw!}OVnV{l1ZcigAVn78(4kQK2MO34=1N&k>ZI7t9RUfKQOyCJu_EKd6> z%Pk4@d}R_`l-9&yY2~}c`5ildieMSN09NVUQcCs*G^QP~OR3yJ$`z((aR96>g&+Ln z!_fcDqez?5jQlVz^tk*+GAldlLs@ro97{O*tT*x=&ssaf#@^~8I=qx|%8pbsV|Mv2 z9}`CM3XNvV9g~bRd6?PFQNN5hO<&wJP(BB%XuC`Naf{q`ZUuO#mC{5hu9Kx3BlM&84|#NYT_9%=V}@mt>R zyUTNZe>0RG5HL|rnf2xi3qnBGh-dZ-P*&OL=<^HO(Qn( zcnNU7^pH)jGNbh55xRKp3j?#SqHt(Hu_#74u`YIXm*^EuwJJ8L4}Crw%JOhFV1S7r zBC|wi6S{IT8QT8nUD9eB!ZJp9=i!bpFfsr_q*Fv>$SRPjR4N)8eqJOHnZ~DSki~sO zNHIYIQn1SCoCeT=5z|)EM&0Ioe6AxSyr0<+jd;Mz%PZn&vqDl}k2I$z4phwVVb~AG zGJ=Sx`&FPBIrf|`?uB{OAEl#Al`te{Y=8OD=W)Vftq$@UL1eV{Ze zj3bz45M<|C>Cvz>M5X{`C51I%cy275tGf{T76(z5Fg$SL+`D(5v!95J(QfKSoAvt3 z96GBy!{Y&FvZ8=l^P{mY)0BW^c8TI*vk{FvnS=zb0VqybkJOK|;_?0a;q>vdp{%eh z437^-yf~aX90rC4BEwZ7wE>aL$R;&oD`Ro=lLpJ}`;v70Mp`ZOa9nBJz82FIPaf0x~`bG+tFvnerJZ6|1htV*E_tpZK zvz-HByNbqzgurSPU%7l4WZOK^sj$tw3BrrVN~W{k7<|mli!|UQdvrkmvE4qzOSfl|}0XNQ*M;NH1K&b#;yW zoMRih%HcJYSkrGt@DkMFiElul8PTCIo52%Og0PEBpYQH5PibzEv-SodyH9W22vzKr zig5?e@%87QGoVyVLoV*^C~P9n5}>-eJE-o`>7_1b)smjXb2HyP()~99yyAb7*trs>xp1!B%f>v zrFIh`rb1POB6RKhZ-p%s#r%8MVnwkGsAAX28 zig+j1_i(BK#hyARD4&fO-HUkrk>;GsqHyH&iI7zSO-+tRqiktmi8?0f6fO-PtNfe# zr4glZ5W{0P5XdOSS@bWa08A9V2lCUQdDaP#w=7K3Eda&I0#F*1rb$@8qL`4=NsL&B z9!mF4`qlVz|15kYNT4F_S^M_TSW=1CuyB9$;_40dM?tOe;hA#H{JutrMz4UAhLJR= zq2(ItDNGDT4I{nZ8d}c7p>e38;`~%lU0?sL$3O$Zp=Trcyb5n(*to|D;E+0!iswUK z0;U;sW|+g{FYQW?(G$Vno)P7cbn2X3Tj%6`HBOz2 z-gV`g;ffB|!SikixZigzlJ6(Q=Dd%xPxDmbp zXxRFW9#|CUaoB8%+s^S-a~kER)Us(YA3Bp7+%-U#BzM|^g_>u;4h=dTfI#DPGD z2Agw_$|Q61+R^al^YU2FugaZ@s6U={0S9Xc_*o5bbGH*OzXfx>M>L{&e(x(U)Tk0* z@_VMFxJJn^n#BkijmU9~TfeW2^fRuBJks@-H}*g8j{t)2xz_HT;8+qR;W|i@(v@_p zo+2&!%o_PVgLCvb+?ynQ!MS)Z>A?MUFXKFT-SttPNVoE;WUZZpx{=T3dJ3WmV5kfE z-jVtvk!MRQ4)3kv-Tt#T!huv(=p7ymS1-I8_9*te)HxWV=XQ9WgibU}Uci@<*W=m85g~7p z|C%yt__=aKUS=M9Aq6^@F<@KTs1E~ZB%PE3_#b=ye8{D`ypgQ?Soe{q&*F6rpC5&9 zz5$P);Ex3pL$_p)qEr48HRT6cwix`ppUC%={H6NC#6Q)6*4E1vXHqX6b*G2-Vqt7Du z&RATV_Pb3N&(IE#`Yj9T_N?Cqr)X^!_VD7bkCTEzdTdQ&8gN(v6x=3V!?C%Y-s@@f zY+L#5Bb90kkm$w4Y>X&S*2=eaFv(**hc%>h#faUmK>&bsbdq$F@E&!jU3hFYZF6UF zG%nB54QydO{Pd?kjUbj$c#8nLnZ-n7PEv@jb2uD-|E zO3%4+OXFTZvA37v%bX|Y=vp|8R50?^D*mWFG2~yKXgwg;!Ak#W-jRM5K@s&`*WL7k zIQXK@0*m>{59F2d37spREqR>4ymXbtIq+Gn{o#<0#1v)L-Sl_UY9lDjTpR=FiaJx& zchpIJFJC!##--Mz#&f#in zZ4XO$`G-JuYv@~T$UfDsI0(5Y;S{97dukqIDMkOL!%TQM^pFinZ$eZ4(Qtq4A%}D{ zOgzU6cKZqa=$Aud-I16h?PhMRARs{i_Y(rYkxx6o6ox;WwvP%R8a2CkruO)0CZE6e z?n98M{xJBkJ2Gk!APFcUbL3^MWp9Sf6NJ2`j)q-&r*}Sh6cq;ro~;Ev40@0Kj(K94 z5RP7Tg8Bm# z4|_forvBzL4EA(?dky|g4Ftktk98a;7X<|tnr-J0>RlD(oS_=4p=1h86@hN@ju#2< zIzO+ZVz}(O#(j$t&UXfA_;s`}Vm|_Qu&Tvb&7&x)z$xQq6P=X1zls z2;n{oGlz^Xl}bfrM1#?x&`_|efHYzFs0_;(XUKEiMj1F(P!pc~^~YhE)Q#OcgJIu| z=V9=#{ur`*X9)9tLR82y=>)@}@7C9$`O-@&I!y!Ka9hx6%D9_D@H^@^wi!nPA6)cTJ_gF`W|08r2J>he>66k#Jy@k30&^$+tH= zBaFygQM`_{q^Lemo-+WE`A`cOVKTR}@(KWFx^6IMbGQ~!oGxGh>fNqEY3lv`?+F(~ zPy!yP_^4DzMg~BpP*~yf8i8`(WrWROcTYG9!Y^>*^_O^#w|@Tf2o}ifT~EF4dM*_> zrUx13<{1(gQ0ek}(TmQR`VqoUV5XlalY`8slJ#+a6b!%r)vv-b0L(A`{lAZA)V74P z2)P}ulf!-9e&?O=yWjjKoPX`Lc=l9qWbDl-)1!a}i_CckVWl#uuvCYT7H2@uhXDr6 zrFOqZc+Z~e<(zemNcYG&o?zb|fO;EcVrAfI{wVe;p3-%nh8?5OB}9~z zS4X2s&w%rBp=%GbmIGtZBPj}|vru?xdlhdk-jlM*G*Do~mtBZ;!;gtMVaTX^_SB;6vXw;xv|}RgD|vkUZ3VlXn=o z;ZPpQM{@u~%3FvUf$#2z|JUM0dwTDFSfMjZUT$HGAn-ZdQ|VjOHlxxRu30z9sj#{V~->UeXz4Y0;CJch0M?(^&p^TU&U^~~!j zb{+zzD(22Zok6;AfBjp4N{}PogG=V-=f>+hH=iq|C+g*%DlY|=+_(koAL4(_YUvm@sMA?WB?v-cl{y~opGm;$#;dTJS^q!yX(m<;DE zpLGq~lXeVwQzaeJeMw#VYmaZR_NlXTsa9e_}Cb^Vc2j0Y&z=)`iEn zZ-z`{$_zSRCbHQyh6VU|7WC$R)z;R9rvUQ;+IrJ9N?I?R5BCVUwu?*|#+AI{Fz4Jg zEP#Kwp0@g3ho7t1YVeqsNZnj42{@WBKv(FpuH9K0)*odR7iPs`a*{6ZIA8RdA(`sEd5~!7^uP z2VK4O)QNEa2~iH*WBEDVf_jYxw)JR5Osg;o$Sz+i(1CmS;H!J#1Yq;zP#XMo9gExR zDLjoH#4v@(=M^YaU(u-+mN&!LBjgkw{`pB{53Nz_;GHu#3S-DU-&5wvS6z=R_{8o4 zh5vArd5-e|xYr1OHxjn?^|PV+;&DI)Y#dVS8V**6kuUB=*(48>=laabVEMP}c!>1H zQKAfD)CzOc=$5vvD-zENV957>@$+#19|7A5^DiJpZj-ZQYiF-zI>96@gSUu^uIM1o z{#1SF85xM}F7t36OrsO~%%0EWyj5~f?>#y?5_zkRtYnzdtnsXjd`g5&96Y~#T3H}X zsn@w4K2uJ6iUXV-Z4J{#DzIaGwii6(B6MS#q{i?Rk*4eDuv|Dkb3Tr%`XW-V;f?Z9 zfp+x@9Xec|ITNY&k_VYOxX!)&oO+eC>)K~#8lL}8#auPcqwM4Y0)j>Z`5krVQUD5D z0J;Z)i1KLxhHOB6&%RMX-cOmNY%oRG!k^RAw2tRID0i%_pzKQM!Fj0HZ*b0?v^C*s z>!|&OBT<>?-gtjOTJ16&tO;149FNY!oHP(*?V7Cbv zA{7}0Nq;Yb4;-cGcvE=FS{nYX0i8#Cu5y^9h~(@Pgo|?K;TTU z(1@W?4Ct~;i0&51Yi&m>1{sF$0-?C{p+0n;Q1XtZQ1{BIP)^V4nGKY55Z2`^@)BVT z1po^kG{X)>M)i2PE-EA{x*ihO1kMu~7~&_a%%T8M4R>d8jj;K`Fm&@_SRcZJ`QL7Y zitN%be5W%UCd~Eu{mxiN;4?suttAvb*5C!q^W?GiFg#6Blwv@sObp)r72%J!{}eh} z5u8g?;oXk+!f!tPO*nJdKI-Drplj$FNZjp9S2X=aEK&ZMG};QbXG?Qgyr=3x3W7{;k4DrEO`hZfF< z#`_dP`~>gElm(PLE9~bncj27M4k-q$pmWuyx{yF#@b1;Fc%<8ikGfdw(Am_sE( zLBTMDu|Lb1;XMEFfIX@cb_kR1^i11%};|)A%rO{YY ziCN_thX{k$&{tt}4{m()QF!GSzo7HM(-_&{`i!xkd(2UxbAdF3TIf^oqZ9+&s1Iub zJOyb#jly*YuZsIBprwKCIalCXh)=(sLPkEb1YOH#3Jwvb&DoA%;ginLc>Wxo5~7rP z`$$))31#g2{p;5W+k6%V`Me6hLZmpKyzc&yuuc)vGHOa>qkJjY)>-@ZixbgX=dq)<0#iFO#L<20)HcQV%9l4PLL@NM)8VK3cHfewsEfQwR zivrccQRoSzl^jchyZr5NpAs-K{YpCbKk>S&ylcFvBBoWs_`262s}IwBhvTX|5$Aq4}jo+XI`T_UXR!01)evRE&00ZZ-k3; zQu$B;^lxR0N@Ef!vqAB&LPA290o*MJw#`16qCq9q&`@0;bCz8@`HCQe3aJKZuh<4U95Ax%Uug}+r~r8DJ?yj%la-jjd{(w9+Bo(He%oP7=f zSrtd$*Z2_#cRiewe8Km;uEVon&vk(o4cWxV(%6+Y{GPp`HF`}MQi0RBS0QwN-uuaq zq4{(Vc=u7|SekI|o_qJwdAsguuF(6^IXj%^_~X~5j~_mY-}OGOaojs-G@ha3$Kvxyr=BbK zLK&S_q%jg-?oG1KD$)@=h<8YX&dNE@fb=p*#Ai_>5i5neq2&j!hDnNj{@}{@>0mSz z&a~4z9sZ%yp#%V6k$M$nfX#NRQ637+CVMGAw}^5Q$)f=!Sd>Ix?6lxfHi`&^+&Sub z6^vEa%EJ*dJU9^flzU#yzQ`N%*<0_ge6e=UDrfw`r=Ny0-fwK9js;P4vjE`Rk7^FnrVgE>s`e0Rt;joc*6Jg8u5oUZR6#=k02ZAy4ZxJH zW^%{prb#X0p6Zf@R5!eLg=nr~y(IDVZO-Z*XGU;4ucAEi=&!Heh^Y(~Mjqs>uEL`W zkt5PwJx)0Jejmn_G$rqG9sE0jsqA+a`z6htCWTILT{)&cZOFAX5S&kp$m6pXViwS9 zInhR>Ku5UyH-C$42K>h3oNEEmK|HVIG?Y^FY3@lMXPo*L==b6AP-uPaa^yGelU`iu zR~fD`=e;rrv9E0-Wn+gZDnOyyqj;fNOUm)$=%7;uH0xZfBO~88N@fes`HM{qL867H zC-AD`7&&>ygzdJ?UiiGV zd?R<{x&BtJNGJ070s{oYeWE*}ie~N>1{$hx( z7Vr_<>&+4kJN@ga z_h%c!)p@FmY}a#Es^R_6qC9IqfWstb(ul1VVU!JKmR;OGduS~i2`$jYA{om!BxW}%e zyvm`xbx!hGzbyFceI4?2BMh`BJvaX743KXLICx)&yj7WGx`aH=ln3Ro^Yfk-E7ZOd z`1BfnKY}mJHC}@Ube_JZZ6>hl`h2G;0I>$ZAesJ z@It@X4c)){EMyJMh1t&@h1`L~(Dmz2!qf+!gOK5k|A#L^#TJDZx+g+5hVIC3KMhl# z-w!prd7<;~$+sd8?AgauXy^M=|M4RVAQ3h{kWMq$$5AtnMTTZb{0?F0o6VIW7eo0{ z#RX8E^3dInvAZ@O5lj!`-A4~ljLO4d6zKULs+vPc-*}>nsrE>p_l!e$$*T_{c%XkdDgwLug|%?ki!o1SPATa4uRxHk@mtB5QwG*tZdmAY{4-5%WOr0QA(sm_)J9pj62W zWjHFvGNR-ls`z@iax$_)1_fZUH&K=;)-rLkGps)%fBOIU>oE6Kcc@>>37P$%uB46( z(W`fqaQs(Zd7DTRL+>#L$7nmpzGU+3FHq_lO7Y+~oDTi-gK;h@4;E#!z~HHx_V9-r zA4czxOyT~s`{7zE2J`H2RBUa#XWJ4P)zNxVJ@D#E12TB)B3wIjEmmjNJ8~0a_v*Q; zVSXvyiqi0R1%uD2(J4*%BZHKFeD?c~?}x(r!qEBjajc0^LNS{hda_T@igE6KUldZ( zkxZ`oa5eQIGVvIo%peqvI8b?4QC6u_d0ToqOy&2%&;Z)r2s6~<6cs?`pGquzqg>{GWL9p?;3J83qSw|4(CZq=zS8r*+4iNx?7G1 zz`0m3ayo*1trRIrh3B()lc-nH_LJA?=t8Sb6t~%_bZEG_;C3^~p+%O_DSG=WYSOup zg0?Dt0-JV3F_+Xrf}RU=+E7H5q=NyhSr1<;)8=c@YYIxcTO4@M$;yvTE@fn>Cr^y=_4u3r+JpqEHvKB>a*_f^IM zmRVECJ+Sz#;k_Ec$-4V_*G?KRNB;qRz4Zoaq$MLU4xN|l;WJ57N$9z2tU>K_m{R9H z#47xJR=MulXqcuN{;A-k>*x0q1=V}G|L&h_p8!L?E*&~Y*VZ-jJMOd9vLwLkD7(IHzA)qs|PrH=KQbY zz;ZtF`&X`Ai(%s$-=38rOVSm4Rf|6(3+{q)Ny z6N>G^gPz>E69I}mjHnFO`rr|w5lf-TOD$nvineX=v7HeN+w1AG+H|xj@)!;NJ=QE1 zQq18Od*t6`Jd+(my9rz)|6q&A8FEaC7*C?j6q-Ma7RhSeKODs=)oBT z@Su4>v`IDql|X90pMI;#`u z2r&(4y0<5k!kds{q^6EVd+-3^|IhoNKRz#g`CC3_M5JJ<^eHHi?2$T#uQ?}csM#t| zx>nZ67h}CO=4sTpz)}R0_oNFcMt3?Pt8Fe9t+=mZv;h94~)G-5z=sY;d3D<+dFCE&%}S zHX{JOTL2(ujzUAAQd{)@j4eyjj~%PPqaB8tB0?;7$(1B5WfP??Q2dSReoPH-S7%UB;of()wCh*;)wQAAW&Cp3Y%Zaj|fd0^tBgOBrFP8I^@7 zMtDJ%7s6}D=`TGwKv-69Bvc8}!*dr;;`?vDPf?bG-v~JkgJJS<6vTSRB;2EXzKRxi z(^O}cn0;MFqOfsz04=a0^WMkdvml@f;ZR?HsLL-4*@Sr8?n_~vYNY=)Ex!yIGyh3% zuO2dgwm_pThSI=itOBnB=U&KE7S|TTkN%f`g~1I`b0FU+c_aMwXMe3u7X_(?lEPIc zb@jy6FfmVceGZ{5Gel^aaHzq+Yi~RS+65|x!ncePCYrsyLs2#EVcRs=GL`OU00O8c zzC0feHG%f#AYcx*hvsuv!>mov_stUrfcU}zz2)V68`5}ke0j2fy%Y5=YtREuO zx~e$zk7Im67a1^ai=!mUj?d#dx<;`u8QznI`V_6j=uupIBy@lMDD16~UXh1a6FTeu z=tfu|6fKkdsT7eWoe%HPhA=aXJV20+&V||ogw_Enl~8GRw`4C2ua1T}JeHHQQ?%7W zvBXF>Gikf96oqBv=q05zx(*_Vz1)y-gm+EjbPgkFhc(h@T;T7@y1ForXE?u>qCz}V8A8xpF%5)ql#S!<9n3r3KU&3P zk#n%0=TLDu1Sla>yhpyi#=VGc-!qVDn6S@nRbxZAWWq%-VM$VDRC+WrVijip=38&Y zGba$B7fn#&DzDuq%wFN9BZ)h{Opdz$Z zqXg5os1EvFP?^1TJCw4nh}Hw62TvWt%^{COqeP zS!`MkHWEqnAiVnCdr^=noaC8T5cq5S9Tj2LsGNO&g5r0Au<(zFoRCHnW9|99d*N_v zYd9>;W02|G{GITGZX2^k#gNKE!Iemp$EYlAjR0F@DNIw% zsc`N*dk25qUgt9?I4XM@|BkI)Q=%3Cf-Z!|cPYR~Ed`C?7)IOuJbuQafEv3RRaWBm zZ;e2e56`E{c0vR0r}sa3>f|@xRRz07s0xk4&!`AUs4B@Cb*{0XfeMC3tDu5>T`#b& z>q&G?4v!6`%l#b6I4Q=M2GMad%HRd&NRoLX!DwlIfSmyh`UNGs5_ zb9W#0Bqi+}eSYc4&ty~KU0P9QbK%Id;zjw7`{(+)uYwAKPf3)CpV2sX*eX&*))8q1 z+I21hwHoc7SH12D%{YI75BEt!T^{3n4!rd2`)tn9`+5evmUD5>1X~2Z5@ptC7hgBh z!{J_7TgA`F|D-#;TVCHiPWIH#N{8-&ywS7_L)N45&pFWp?^+w}p&sOX1ojWms@B>~ z2j9DZ4z?DiKffJvS2IFQMJ2ou#hvd6zRVNplTQ@n76slM(|F{YUq+5dM-Fp$)m1#d z%1?*$kdF%x?j5ZP*_EVWeSJF|#t1FIQBjO>qHLag(nb5r1&Y;PioDqG`Mj>J^t1UZ zdl-}p-Mt}`J-vvG5U6`hl-uiXy@@_K8b+TuBn#TJ0A3@VyW}T(#pGQ#7KgnC zy5KZdhw)nvLUS%o1&TyF9OyTnP5Vx~=clh;2u1K1 zol7(9(;j@yGms1&jM^E>ltLm<`$wop1*oxxlkMc|uZ5|{X{XP%SFQyk&T?r3y#|<` zQB9jW_)7-$7ji(ux2b#M5V#l^9Ej)NYaTvKfk4iyse^(LMmgIlA%(oKD4+aZ!`|W9 z(5TIZU(L=CHeXdp`brkX(J}my6}y0Uo^xAL3QF11Z-vht2O!dODBmy7q3tAkcs(_X zd@iG4{f<8lWn?jDz|U%2`?|Fq`rw1gTvHU}Cka@b{!ZEf?BA|k5)pTtGzL4nY5tRseX=^=FUC4|x{jPk68 z&^6Y@6+qAsm~WqcE7*Q6Iry=HKQ#|zoGRZ(4;~Gpv!e)cJT({qrVU&?dm-i)-Gsrm zwX{K4RG~fE66R6Zrk)YqK(4pmFBO;FOrD(|d!?_EDv?2Z!rVea{|WbACO>F{LM0yF zZQ6z?h}?&Tk(qF3>{)n$SAGwM_Iw?$DaL{fT5rFM@aD}MQ3$MTt;F@}LQtw4oNGIa zLQhy!9&KCz5;WFqwWLrM*|+`Sr`JCX9Y;FClfF*oe=>SKmr(Sre;{M7$faK<|NH1V z;nr_c^an=RatV}tWh%V(7e5ON)d#}V3Or^-M(l-{C@AZY=|Ma`?;^9!3{`hWq z{`Y?h)4%x>m1<9f-~H|%LM82C>KmIweN`%~Qc%mV@n$^ws}!j$$}NKC2yf%sDolp_ zdY|5j-srK^_z(=~gQ;Exb+5>-2(_71Or_&O9s6m9FLy%cCrW(Wb8`mQ< z@fj4rBHO(nzMBU&!<7qox(A+9i8d!Z?0p>emF^4U6eVn^Y6?frw2+gC_it()aOgP< zJjElETTTZB*UZQc&y0~J7C}2m3W);O=#j{LHKG7%8jiI@FF-+l0ft0nRGwwL7kCZ@ zSnTtPFp~y-=6PxjC~P-)*3yPl^opyDH8eC(xfsCkJ>D7y0Xxi%lm1myPvZT_<-4x8=UN4; z55Q%G`!uue`P^SV=l=NPXY^j0_qqVR%|hcBuU?JHq6(w?E{_usaeXuj%2_vg>0kVt ze-jHkx)*csuzB`b9&dLC&xGHJDK1nW)@T*1F}g-WV)Fh2(l5vZMbV$=dIFGiG?X1p zh1@!F%~6QH{^ZN3lxToj*;{$hgBQX5NtC_1CeP;)z+Ds(o(b{^?WTs>+y3c`;S1^#Hp^&R0*m&#YnTef1zqVdx zy%gs!UI>GDnKdc}7OGGRRY>E#F>)Zs7=oQBY7z8ceN=Gt{D0e+Rxxrdr8P%1grJWk z+QG;G*Vuh^xc)x7_jQk50|Dy9DD~{Rp01m7_IZ;?4EI69&3%i7;kLFTuTdVTT=^ZZ zEgy(RKG*lY$$XP^jpTX!Ok!xef3CN~^Qti|{iwqTa9R(*B315_x$epEIn;H04vlfw zLb>nrB=hyNDv9-}`nVq!XLZOo{k(JbUV;<;j{45a^>S_8Cp~fkke)$5FBs%G5Yg9@ z-uw!FdmM0_cE32TiVm=cfOI~; zyjYq^jDKk`4)!F6{B5H#lf3c`bl*bq$BnoC(JY3-2XL1+=$BFY5pR za;7o@r(qYeU@?Q}p;u0X9CW|FuI{k?cr?s^Ndy&+x^G6BZKREVUaY|R_5$5UeM)fG zjz`g}%9+f^Xr34vi?zQ-$40`jE2KE|JjF$hPF#VPmfBPTX9=%K?qRDztU=N$vO+1{ zvGM^`XF5p<k9?!!Iv4f8P$W z)Lozea^JJibiM=LM@nf=Z#-uwFPsUZ%hUy7&a14$e%O~a5Ii&L2euTN1vnlOXEr+&6*^(7E&r+mA9XiAYcmd^7mdx$2;B z=xoV?@5Zr?$WR+Qrv>K%aSU!H0HTRj)#S8!lyZW7JeBXq31bFPbBNc{W~!q>+451 zL(bG{n7rAAv6>EFtQZY&CK3BolpEM$R0V;GQveSxS0iBaNR zfvAeIP*U%bds_m7MrkXG!h-|4!Mfp`x4_{R1x>7qnoa2J`XXU!5T%7u42iN5CCCS# z%?R)QyMGmKJiZ%^f-RJ{V@<8$AO7Jt2-MD4?8ax(Q>Q{Ns-@6f-4M~vq5a`AQU@rC zK|3)kNvf!N*TqRDqFLDAKi)aa+L1qHWTU?MyD9WVF<^gbLD6 z%q_AHvCOiZ&v!lTipr*Rbh7zWxOwMBy!Yn5&2WV1gRjRsLm6ohllOaKsHTwsGW|F_ z3xIPk=0H}B7{TCB(0jh(AWf(A5G|KzUD%3JrD7sOoq)k@lFz!z{5->_Kx0*SCvM#e z-}~h+!*fFTHdyD&KmA!W_N@zG@^KD@+Dc$4&WYm`O+f%&)}dLJq=hDUz=K`3u; z!+;))3fk-!UxsqdkNf6*&axh!%TGW3G#c6oGTZyvXR)Z!LQfCRM4LtSW`Ih>MX3}3 z3I%<5ZIQEFg>m1D;cxpr!#q_MRfaU0pQ7O8qnJzIPcW3r`K|(N9z`dc^%m9Du#%R1 zJpxP2dmZ8FIrep*&AIA1@p*jhJZm%#i132F9bq1EAZYc*%fF>qk5 zRJ5{QtgS{vvaYrcFpnZKoL%{+*BvCv;uP!I_2h9F#504`jNpfcxdx8UrqVirVK~M! zGyq_fq6mUg#JMYU1SAxmDggaluZ(%iqs$%6Lpk<3D!slo#WRfae1}*=0S*;t_tkar z8Kf=uXpue0VI8BuYy{5!=nEa3HNh3*AxR=8i$!Sc{{=^Qm& zFy{8Fj1aC)T8}(-m2)UhHrID@25$(!r-f3V_w>cO0J|t#&22|xn?Tq4;+2cx_LsL} zSnVnRa^D~YL-E)-7mEgJ=*Z(*T2Wj8F*UyB&+^?=Ln<0q@(N!|qEOsV4c#QK-{+QZ zdkulGgtz;7WuO0cXvhn+X+Z1ojfN|0CvS3%JX2@SosHMkIMhhNwS`m71)63;RKjz&$akAM=V!llmOd2kK_3mW$Bh0kde zf&1&;x<`hNx;M_*{ZL6$d5llYemQ(TucaaG*@#9RA8huPI&0Q#72NpJ0M#*3VeD*0u3^Ng9Le8C%Y=ADPV4 z=hi4shUd~&eO}x3bv=A0haf}(IC;J`-W|@t_q>7CwW#S-{P6A{_|K-EfMN`N+X$voq`6?|rgL?v zJpRE4v^A#V6F*%5vE}HOo?6qIOm!FoU{JBQYsw-t(oQW8jiF5(EHk$rhGp(!3p#n_ zGEtD~N86mG3hpW0tD{-N!1@~kk){WhQ?#z3IURNLf)=jcQ15IRsSsm>WARx8J61NA z!)yl8HpTgo4p@dzm|qb3|Ni$Om&)<-4r%1}-~F9U*`Y&thqOzS-{IqJq-fIpfc3c# z_-tC3^ynF~-clCtDbGqc8}h`F-rm^mb{)R%>#N9xMfRc%pkcVLFBSmw{7fSIIH+{l z%89^$(LpDWF#?gEDchpSTN?nep77ZWWaQ;{e-yi4Ssd3Q)2`9d%1k&2e{jDtchL3ze})|sDoKHy7)(b#<&^-W;K)!O6yS}Q zS8M^or2s{G9s@L!#%T)RAYTz@(eC%J{^K;Bh*kZ^F;eH)%^`djJ@ zIqA^mvbr?-p`8r!Qq>{1hPJBxeIbkkn&WNXBwSx$Y?)|)LQ;^|(8)aqSwz3A7i5G~ z`|+^4N%3KL!3?Pb+kicyICWW3OIDKfz%|s#Y?bkLSa&fF5e$T-&ABx3z}e zQKF;q@EoG(dHpeTK)|4qGshx-sK_UZn22gq1q5`Yed|hitrF4zVsTUCkHSe>(sq;Q zM42ui#ISgt^zFIUAWw0RMbda1FLuCd;9r0T<3l6Z8R?YhVQh#Uc#v|Vv9T$hmoZYN z%aILh!;_%}hnh61jpP|ibaT0pI)LwnZ`S_ZITKb{@UAbkT*0O!>N~&>g0tOmMn;&Pcl;TFH2$6Bcp`wqXZ?!iA-1_ z8bk9ywJdIzt0G6ikW=la=zTrLQj#l&z|8|Ojt9Hta6EA4qbtY`l~spB`zg4#4XU1x z(mIXja&Ril{o_N3XgLZ2nV}nc<;rD>l~slnoRfv8Fe>Re-GJgWf{`Kus}R100c0lt zl??@WYszqF!tKog=P-G26lgy?{j>1t{ZAuP)R2?VG?-P0uO7b|zWn;jaH;(gUiIbh z_19m6iV`l50wh?`P?`!Ev^Q*P=^*r&wlROa8K})vi%-J)7k)~?vUCsM ziZZG!gJ!AJb@z0K3nwmwukL^Kjc0lQMDK@Zei#O32BPwK;newXqJe@YWzp_SQD81gX2pH(>1J*V~j z%5YRLq&byIjX0GDnTv`{RQAa2dohUeyH4S;yU)X||NPs~_xmry%=O1%;E!L0oOM_U z5hGc2nlLQ(3`V64O~KI1x>Qo^XBkwtqvdpHt~wf?jr7EOsvIxTE>SdCCOZrotF0#o~dXR(sW>trEJ!dEbKBn(Oa%^$1u9X8F-0_UU3|b^>5u ze)37ICT#xwC_*C#`k%v7(f$|zJnn&v*Yk1+MZvIhE4s@Z2LPfpK4qYNUw#?NVDc8v zG3-pkMdKgNYC>12X=g8>pC0aQmFIQNs)BrpYn*@Mjd1;se+-u}pq#fJPz_t}siNxj z76JB(xc-?dSK@v3*y}-f#2Q$W!ujlnjvUTcFk+qiXK)YCynH|-{1ne{m*=g8HkJ_r zEeI4t+fT2Gbp%KlwCXNUE^QSsq6ZU(0GFIH~hovGsF{y z*mIxZ0BhZfLb{02;(4^4l;^>HxcSMaRAhb-3XkJ`Uq#8vgLf=qkg%slFsYc#Q2aA0 z%_wEtC`qP4)il<|;y%_5a14(Op{S}@zf_{s>R%3x6oD`!V>J8YPF>&5#+yUxv_oOH+sos)au{hUuUnpp?eR(>v>E59RX;u&Qg z?!!R;K%7J3<@R^t?elv^ei)kXyrgphSUp@8oYTnCxOS*~MjpjH+#i7jX~1*mZ)rlW zy!V#|1Pc6|JllEsn(|a7R9bVm{|@Dkw3B$&eLg?0F>XYH_m*xQf|t^eLmrZN@|APZ zu;;wS->i*mkbn*99xARrf3lZe!}}zlN@D!`y2HqU#EYHKfX^Cfg8RfXz-_GmVJ#u~ zp88NSqR~>69WMO*2VszcY&r{GP>&{Oh4e>&XdOk_th;oQjA#I$2aZ$O+;e^a9Z^st z3$SyDV$sguv!&wik0}i9QKU20^8m6?&?Qs?{?JNK9qs0|9EG3z`6su& ziWU5y0SL4pj}65)dPV+akyd4c?LsrzqsB95B7c&$&zwIW``KHt_5ACvhcS43!?9zL z&fU9V_Ir(MG;pSkrs!ggp8+74hTt{zE<=XVF{2DLock%~Is^G&D7HL!2i{o0GmbOo zLl~Ho%hYvZDd#`99`e?Rm=pjyeB>KiEUPB{fX)dPfYsY?`mHq-VjDhymh$GqMEI2e zFp*CW0Ar-8q3>Ao>;V86wuZ$7?LxNS$lhWieEEDe&$}>{25(*8UHJ_FRol^HVesZ7 zQt5FT0aEVKeW!|Q|EtjQT3IH53sJi0SLG$N6(=8`L_dk9K+6v#`jA~5V8OpPv92Ky0 zV{}9)hviN3DP>Cp3AvZLg3)!#2>JEZYgZ}hMtzdZEwZ;ak!hSo^rKW`Q<%eMGmQk4 zF3P1TKxSirW|3c&N9pSIq$@O+9|=A89!KELh(19Qd07M}(0Ss#kU3V>*TL(1>IIHz zbnRu%yY`+skam=5uC9l2#q;WGiEPzaSLc_nyO$_1Y0v??#&tAre-~aZ-%aje3Y-zT z1O5FG{8lb07fng9wcypOS0nf--_^)hb}3_=uezPQ-wq32TOM4CzUG{?DZOXnT!{uh zvd7_TQ9hu9f2RPz9w`82*V?|*6oAFY1BB0`$m5w`URVkxmFb?;hC2=R4xqHqyYVn# zPTN$y1bwqDSuqDR3KGtyf<>cMhQGlfO-2!Do(1Zx&}qJuj8t#C6&+O$%zIA+wINn2 z%=zRG6*kv~!b(~tl~%?>*ERAahNaY!yEP62Y%zzcpPZ6G>JGrPQ!p)wP%p}J!aPT* z2*1-rj#D{N4S4=vIgC=h4)MXHRboV#+)NeihE!v?b?c4sP&2XdhMm$tsc77QZ za6S2kpJ{;BK$s$`McGAR1><#v5FnL~S6+EFRFm(d$N0jri!oe&VS_%f*?8&j9FP6) zAI8J%x*P!f*d%PKuscrf@dR)<#k%OpjjXOMp12WiJvhG4AB4+G;=iY==RGZa~KACi#P z*cOoUQ&UgzM8e7P5grl6Eo;JTjtMb1=x1BEmdO6-XYcL(OIQmzqXn6*qlgL8BVMa@d*qX?iC=r?+` zIm0R?3bzIn(-_9i8fx^I(@hcEYzOILH5M^f@+FJ$TttSN2v+GYE z&r{3X^lbW^E6lZ#dwC7PgzF!D6e~#2VAxf0PmyU~S0KqN?xJvJWo3qm4?ZG9^;9_7 zb}~Hu;tT4I5a9%EzWL@GF~Vk%bFmAcSPOVGg~8p5=UjoIq2hHkNEFuc5zgtKYs$?z`vIfuu(YjoQE;s=a|+-;7ct{-HOjC>N09S$`}7B>>_6 zSlG~UhCMPu!E>cd{r2!4iLsg(>w3HeZ8b{VYf~ij`l~4F+4C9+9e6FHE0jU5i>Vg^ z2}V;y`s01U4%gH9dq3yr@IJ|B{I|-YYiT5f#<<^?d5sUxJx2Jd_C2WigQz$R+hL{ z?w8-wfc81uTVM0qrk9vDVkoS0^3V_co|9779M?aGcL-)P5 zph>cqddQQahu@|(Y22{=gofQGJ;lBzPjOyx>?4dFUhO(LyqKib_{T4LzT)8e9#H&kb1$i3>MlE{HD1g4+ z<76$Q7oWp*_xY2vsqAih|BX;{jmWd!Zh-ln79F;;%l!(;7NWhNW2Aq%Hegx-^of%N5zneIZK_Q!OrJCW&{k~U+K>X9{1Z+ zguFsh0g>r~L(2f~>Za@DnZH;9INwa~m-_J7z-YXVkqFAGPza!Y#At-Q@aCWYd3XX) zzQEd;ZmHgs5%$ICz!w^B7_AjGwV@lC)bZBq)OjN9V;+!{bdb|O`EhvitG^5TD$3)t zO+W4oRRCP3***KihhdAe=y~^^8tS|7aPXm~w5GGdH2JK%v7LRoZ{H4k@ICd)=>3OIH2!Ch!TY%1GQ0p3h?cW+)C?#m zs$$HVbzwg(7FV84guIz`THVfvDx4QF1%w(3OGIE?re4wX>{RUd;#nT(9-t-+&KV3| zq*~bKb6JGv?_!kg5@BHrH)$oN(a~b|Ko&I@@=41B47TIeB==qDrSlOju8kHcz_8T; zFv9#QXm4l%WmA=Bo&uuc6s&Bh3ooj2!x7pJc75?>DB52T7D+AL)&Af<9aqi+6uj&zwM>kuN$ht1Bv@ed>E5myKepgciD=JtbP0RNb8{T8IOpy`(eGSYix& zUX(@hIa>j$BWS$(x_amu@x3{2|dg!PP zU`b?2aPEk>J2j}GZgd128&^$+zPZ4S@5;FWZ(eJ0=4p(?LT^B4y$Nkpl1?)&O|XH%@2}y(%#{Q%!ix>7}^= zTBQb(aex*L98e3YsZ5%uUS3m?R+uPI<|qf*o54uik4JlR2SJm_G>|$yluMwfZ~pMj zFo43hP6*8|y*I6_syDm@WzJ1e@E23aEt7Ddtd>LcNX-u|Imf~mPd*E^DBu=bxL9-{ z%x4lJ%pn?h)D;TpTCj*gGy(A_Fh#=csePpVM98L)OclmvU1=>ei(yny0xEqV5}FFE zo9lsGqiSeJQwK#&GQ;rVFh&2!OXpf5M|KWS;nwIFK-reK6qdXDNd@4Z5`e;0g=u0D zL=<6u_tBkjsGh#)OABE)e;<{yr$Q#F4w;h>ARgy6n2KYTdB*|MG`wv7<-Z%qOES-U zZgMsne4|4Y1c8`UKo_&O!}0fD4?B3Vn{!%1=j_8c$Ah3(&cnm1%tx6I!OK@hD+P2=#J8$|g6{1*7&+v!OAoF^u!S38FhxxJ)0h z*pVo$=)BD00UlA2N7F+Z@*4>^%L`xM`#M~1zY;DLTnqo{^S>mNnh^SFTIS`~hNXQ7 zAoh0)1#0ynxrBtO`FtwEGQ?cYg^HYCZe6J~s z=O8#NzOvlg8zTYiE?_Ra>nX2MIdwm^#snJ_I2w2=W}Y>#VQ=Ai(BZ=f5&u08axFiZ zfzB;NU*wyYl`|5v-4hplA zGVb2E=JGi2SIuW!SB2U0{^ubNL9GXP2wGTMSq?{_H9dizUGKTV{14$p??jnY2==l^ z!+KTHD;OU&(cYgE((w1IC<;9k%6Vy{M@+>1e0}PpGTBH^TN_tYP*7mB>wnn0% zkx3tR8JX+nIZ?4oMiTC>q7;o|pM&rEj2iYT0q&E(HCW}3i8oc_Mel*ii(X9W(0ltm zpGCvYGa4fRkRbwrdVsx;#+HVLg|Ixo?zvv0wnmJ@=$tG?&{Ii_;pPLJQ8oc3as;REgfgh0-Tcb{OzHUEO4Ng z$n|lpTsQBjvS%%b+h5&|z?17H&v&ie-*?}AH`1*9z|TvE4)3Wx;xqMjQ`n5XlUALF zd_`m1qIoLd?tP?RL0g_hV?9|LujPGwU1QOC`b>$TZ@R-E5r)!>9wz01d*M3xS^svJ z=kIzcdsQC2XEKhq9F24GeeaPB?`x!u9za0>Q#+0yKNh1;-0S%B(y*70xdyiW60kHn z&pJg8jY8j-&gC~6|A`Ww(1aZTl;{%$~LYo-oUUl&nQw(B62A7_E_k&Vys>Ftvmp-hL2{pQ7*_#`)n?eT>ALox})Y*tRqo z?y={p;`}k{zw}#>io$yR7^oDgWq&4+MH!q~!Z87FA3?4P&I%?PEm4nA;`KFN^vs{S zKsp=uE$8#{f7nxulG%h#SGjig zXXo1Yz89W-@@Y8!8ZEbZz8BDzk*r5r$csmB+M-rdu1>ZZ)D(~qD~GUYlKfjcZIZQZU&G8c-bANP&H>#dFZ(@T5S=)VV(#9z5b@* z2);L5LjKV~YOeyIb%%nV64; zt8_g{1j~`*&0(T@D73Yo4AU#fp7H_;Yg5z3y`M$DVm|I&QBGc1nZUz6f%A$E0(zqR z|MKIoP(wGUV??;%*~gxzz$8x90xICM?z@22OMIsQV?P(i+4!dqiRc?7@{}mQnU&CW z^B$1`@C=AvIU&DNp65_g$Fn1!609;}P#Z-MS>QAZWcFBN*x`AUkJ{mDktp0PICotwo*n9{xkQ>Ia!np% z+PQS#8puQCKk_rz$=~julTgM_AzMoUk|UpkzLk0ERIaDI&eU|T6Qjj=F6o6!#%B;* zQ&#wFQ8p0O;CWtsKS>VZBpbj& z#Ga?*z-Xi!t|=kK{9=%@H9{4wGRD=kbAEgjh=_;U_bjzEUKobw(-6y9MgMFO-@z0*7`)a0YFseYs{CvmZj__YT z_%G48@OcI>XfC&04$p?3vETc`#q$?q*pyJL&0 z+v`VZl_&snfEG}Bbzv(jU3^OALxalPsyp}YfZh=z3ls1V#rc9ZKL#;3jM+SEl|F@* z!|%UtbbrcQ?6krUtA(h?p#eh}Vhcq8=8^x_4=TUXH$I*H8i9-`3Z z=V?&Hka7;c`8y4%RBStF+J(sM;kvqbaI^4SS65Ysk?|11tKM`uI#fB03%UPA%- z>Op8f)DV9ASAP?lYg2?+Plrmv#l`@NcDc4;N7cDCF|c>5Kg9n zOc7O~@uQOLb1q^G(84$>uBHeyG&Dqk5OY>1Ft&D9LrLl|tppEa9MCfyCU07Yd$fcC zr$EnP-u0w=xYyI{y-acj<4*7R6++Ovp(Wp2M@f(wevW{!>hN8{5Y5>)-A5E&(CHM# zie^z3Rxz^dBYO{zxc!SA&p!BlH~|RaJr36$j>@UeprWNGqJr>Fg<4L@_7MWLrrS~7V~&#a2x zYn$GLeX6ylzn^%4K z!aMJv#O8#@obw|nB_i+U{(CLY*Eq)80nU)h@*$MD#5hras?eH3(988+@Y_67L|Ihg z+{>W{4+yKQ!=pJAhHl;rS%6xu**LsrmvzkKS=}4?k=NIdn}XI$S>FWdo(HVF@&+w` z*tZ?_P~$=6-?|sJcC0y)im$mgrSLH$KCD||`?Ux(a+X`$JL29bbbGH8P1D{Ub4x|P z^?@9<^Z9v)&bDSWkGu>21FNI5SJ@Exl`c4Hd*?m9#?} z97j1!S4-D;kRCkO-gk@~&(jyr0Mrm!V)q&Bh%CEbU?dqCB-o*`Sw)(Z-p^PKn%y6uOs+v>P2Gk`>d|JLyxMopBS}z(WUz&9YA2gXV6pSP>EB9#*lZ` z*k^T4_rAUt-*-_tE`udsxhQF%-EHsXyr<`jGbQneP*4uAI zP~7K_1|WBmm%7I8rDsk0QGfAo&tg;tNIR~(^U!n_{nx6fk;P!FMACYX4f{UXW;#! zoZ#7|8EY3|xknEp?NF%mL1f-0DUPgPvbN4ie&Mx@M(`TeB`P8Hb1`c@Tzc;Z%x^UO zh{&@Az$rm=3l~?kx5YCjKL>OqNdXr zaik?pfA$F;e4G=s-Cd)azh}`=TTdDi`)Vzw1XT3(xg`KxB3K1W))vx*9jyhhvBlo$ z;DRT4uB1u7pM8?L1(#b1IcW%|-?$q0c^-rDSW^oI=SEoX>y54c9{lC6!ojxV7!R4T z?Q#PJtNWhb3ytr*9>$ku!rb$ounmu#$H=Zk#?Ccpy7 z-G|(f-?`=xPdsxLHIx?`%I-d^4_2TTooYQ9p8a2c2rJ`rF=EFxR{s+4-89D^JHn#Z zbG$FFtsz>%8VnlgIvuNO4~NyMiLj2ovqd4)oCfr4beXB1!8k|HgnY&`G&M9v8$@c% z5G64F9NA3t)D}(>Ld=Lnz<48k-{E&+^x+U-!;2kcJ?*hiH-!ysm{Uz{q5reH@pJMq zd4hWQ0$sZVBmjIsgTH3cy;iu+7AbATfYHV9BK5j#KD3CvVt1>ed{RaLsI7^ivuQRT zFFkyAxxW`Mgt{t3G#o$<8a2Byk39u%kcZF$2c2t_s6Nt2yT?KaMbC$x;w&M$+O_pF z>eH^FKYG}82)T#ORo-N3hDNUXhdjc;7RBNB<-G@JHN8=ajHxXQ=dK`o?%oTf=svUX z;X~}HI*U<|B}7z|mQ$09YfjiLcX4=4f4;d9H}pI!f21WH57MZ# zIEF1J&+&QG$-P&qAr*mo<(8m^U_vu8z~`|5pZq|6DG!Xr47t9~avo=nx`vLBlP6C_ zd9O|^eajCMP~CH)UgY(PK#a~|?#e8At^CpXIRq^okO@vhI=}GTeqTLOe(iS> zelNJ{vpc^;))--tU0)He@tyo-MFP-RQNfgGkJcWg{)geS`(jwk zCa-5^Liil?Op5#s-@%}!8vO(ci3i2d#_dcF>3TW@Wj_S~8=7gUHa#0oU!o`XEO}50 z_m?RZGT?=Qsqpr{{qF%6&W2xq^6T(s!|S1I29y{fWT>3P{rQ)lMG!>Ky9H#5^NXW! z>+S0c*DhTP{e%6{c#*kyuvBmbGbDV8+t+Upy5@m;()%QO_hdkRt{3Cq1MT5m$*}4u zNIYvK(x-wTB51*wZiKNti&gAYf@@(orUx{#Pxk3OTXs79=Ci+#O2bLKKKnSV;~4f+ zbM$sE&ZUszV(4EP2m^Rl2FS7c;h+C9ECJ&5ER0h%w=VQuzeyYs{_bVGGCYH$>d2v( zGrJCInF;VxLU@?@^GB#S{^W7m0}IQC0K*^7iJxeV=!N-@`+^4^bo~QKZN(Ns$yO>b`9GlI>&?Cyp~oW_Bk) z3v{sUqCkJxANw~H=nq9(Yzr)kY0+*6({6WWGu|Y&lh{tI*w!sk2k-m7@B8TM^?dd5 z3XA=5JdaJ0{PJ@=$NN5yvnIlWX|1@1cV-d1S=m~}Xf_LjN$&%cFO;HK&8@A3F<>4b zBz=O865z!)3bV?%VNvFBN#Hzp&kZRnY;di6A(QdkgeQ$B3ffxYYfrZ_7h2>%K)p`m zLMJ#B@s@k_IJFTmAOY38sh3;bM?$lRt7N@9o_ zbU>Ud2Cih_GEEED_>8DVjxrtb`glV_yjHxD8kW*H{C`HbRw!0;5xY*&AGxb~9|qNmpD zREQ@L76*U*5uHp(rvOi6E;5?9e+Xe27&gSyO@!AU{`sGWo_qJSzJ&?|*y+wLifR^9 zh$kmZfj>FS%}{+AoL|`}ij64clfU{T)Ly$1&uosp-9pjMhc;BRS1LG>X>qT#X_Wm^ zxKd!!QzqVO6-jCPEW(Y#r%Ijhm@xM^kr)4HppfQ)n$aNQeGZwv#wqtih015E z=&4vMJPN0Yr(AlO&{NMsMNefykG&oU=cKVkCBplhheZH45PZk+I^`kUj68i3a)F8U zk;$-*H%wSc=Bq*_9=ca5f-iey{mkq9?mQAhg>Wcd$AO@$(cNdrio8&s?D+^s;=3^H`MIZw zmp0~*qV)O<=c3cVC4oR*^Yqj^C)ee< zYQ&KDYP3msjh`76D4p~g-{CO5!DtcRr##~RC($DsW;}cOkDvQ2LuHKuN>UnphOi;; z)!?Gws#i?-F~8L`2j})pp)0O;Kin(d?S4l?1fM60z3G0DR&%!Qw|gx-yJzn228w^v z&1+%h2uep4^2VdiFna$f5kXC%m+vb7i9yEsIh1+aPlb7DvT~OZDbhQ6Y%KygyMyUQ9Xq3hOJsX_60+VLdPsyyaVO4{Kc{YloO6;SI~9Y*dgKSqQBGK1sdRg1l%a0>UPukycj05bSbqfYK23)a3!bE_!{#c#BR znc~&Z_VYgpkNSxwM6TP#u{J$47Iu+|E1{t(YR5?(8^ifDPi>}4|MUaW74C$>=6ar; zk6nRck=L(<9tt*}z?qSSOn8_Gr(+dIL&uk2W6&szIN9^rXQ8@{qKwf0W@xmvXH@cY zz#)0q3HDe%=2^%32K>FEp)nf$ZCS0nItcy0dQImR#j}A|^Qt`)_lB*?2B- z;7r^nEu#(vatUM0v6e=RKp1_eNJ(iVtpmDf#I1^QRsjZMj8UP9PEhRW78U>dfBkj( zIs7YbM4JEN(aXqIhSeLTY5Tlw(ko3}ut0e>hOM2Mbg?~otMtlLtx@K;JGmH*u)E-C zNi&{g==d7Z4A~fTb=>UEr)fo^fZ8QZgW%*Sa^4HtEG=|H651$#5biyT6fkaW7-@)f zYYCZ7z9cX5cWJVY+H#&@(RJH>9~?&>s5ud7-?Frcv&sNJRya3xv;}C}%oxrh;Khj2 z9M-c(1nN$w-NMrJ){V00wcP`pgGTf?c(>6Q%4;hBR^^wb$$yLj(3n0jFc{kb4-b#T zxhjiFUo~PoG;T_dTyHdXvR>(zbV^<DW=`prI zLv;*GZyfHEw9rVw79wiqkOg#F3xD!I@xp6;k2Ms$UO1O#*(E^U@4AFPd4kt1GPitS z?OPjr|0o84Z3sC^xOrQ(H4z|dQ0@(LQu%jCpjON`28fTJB)1x?mxrE40K!Q?fEMyU zEmC5!CV|$7f<^MG%?p!h3ZMyNmC-4Ld6-8ba8`MDRDhg0RNc%wUl#`FM#3VL9g2fRbjI#K(G-fpPMEiXE5+RG zFS?AfW(cvuiJcKFOlM&+D}FYn8c?7zBeQgUed`eCR~y2s=Uxks7l?T=s9@dO2$&MG%P2c*?Ef$ZksNxvHsc9czze=HNTkZ#dJHqy zFl1hvhNf*8OLjhjI0U++vNRIH1=BH591i(+;Q0uQ-aBCoJtH z!p7KCxYk6t{s>`xYZO-_O+g~3(5L{S@}I&oJv&OB2dv$;j+_IoEJ$Rocq|@B%f#jG zQEJFQn6Ucq4i1EyfBF-8>{7Az?YAR=G$lh}Ql>Y=`EfWTLKo04H?7=gsF4twLZATj z6lHMrk6(sM?|nbQkLNB-NTBzj0R<3gbMWg?WS@TWNvMJ$3r{jEi*FtPGYV<5JWIv+ zC_mdr`1HGPhC9FfWjM}#Dq|K>9O>wYp>12xg&LkC(}{4*^$Ny=;P5{1r2r=^3zO27 z3It(=9^un_`kAx&ZGI*^MyA1>8_u4MdujxL*DAoOBsqMh#S-%%^sZZiKL-v?u|KO2 z`ok#pTK%_nFff#&xZusGMtJM#qPlf$1#MjYbe}n zFx@D0!T8D>i5MVS!Qy}Jr!@5_xEBo|?1}Wm98&jg6x`IqR?iw-R|)gp^xV9Ty^$6v zJc!2@ViW&-zqDYQdv|#D2^g2>w}K#7fj8eaQ0FgSj*Qf>TJLpVPH?6c74&!0E~FRk zr+D4*=ur$YmJzx(->H(|IoPsMV~F!R3_Y?lLjlUY6`1Sr#+@Uw>&f#+As0qst5b)$ z{{wirV<;f}+dkVW|K-(qT`>~WVZ?p@Fm1&1dh>7#%ZP}ffRx=93Muxg@@9y#QC=Do z6hKup^*Tpkgt-_-=vnLiSAkZL_xv4Rmng?7ZBf}%mUtl$UVr6!R8Up6RQg=Eyet|6 zfDM&!VNpd~<;Z>WyL;)i;)8;Rd*-vF_Yj)sIV-$KZ>MMzMdB)brfFUE)tylF%GJ=? z)Pg~h$hh7#e-me=y?%Kn3PKusRjfT%l`-d_Fe8kqr2MCbMxG7Q`kc4>AdaXwC(5h} z_RII`QIA3r*Sanhd<8kZ{|dnFo$GL@7+ASq54Pu`pyym(R&>2i!Os13?Vgb^B)t0h z%R}WcF)RpIK2!SS*(IU&UZ135$kQCIEg4C=M)JG!7e6#s3J(`9>g|LUa^B80iP{jS zRNSpIVd%R1>s}@EQK0l}HI}#^N#uyn@LJ^@&)d1W9~urcPB=Wj2xt84-a7nUxyVQx z4e0V{Va)mw!gCT`k*vr4b9ipf#rwT3iSmef)(GIzL=6Y7Svs?Yur6&5HKif15#<1S zL4H$cKYc!?O?KYzh!F>R+@)oy`n0m|z6ocp*|T@=T)X+hDlqHd#4Pfeqpq<&uEq8G zxkGq&I0xY^g9ss8A1@uv4>j$rvEEV%k)!5BHv^*m)CJ3kpetVNW5nv{-{W+ zlp3NQFcj=T<0n<1G5Y3^9^l?4G}$%k1+FZ?;Q`HXUX2&d(S_$w>xN=3tWw3lr^G3I;37896Q8c z=i|Jk59&bDgh;!A9c2>v#>cswA*XcXI`e;-ft@C68u9M%v}3bc!tLHe&*~@ zZZr)=1A}L!p~L->7wsUA#hMDh0iH#1Fs!!yR7)hrl~*b9g;#kA1#fbMe(3auSCKGp_Yc4SeH45J=Ap6SNYJ%j zDfr7=ig>@kA)vi_<(2U9rym1=C!$hm-iu+?BAUvS9=Ovbr^B7jI}z{;2@TTXyP{$Y zfuSaD@L#RMdeb6<2JQ}1Fl3fufaZ20&|IC11VRRL^R1g0 zg+?P{i-61YQ*{p&7%vizeVTbG7#hy20AZEX#}6K1g`Nr5E~ET|u#Y+(hf5bO(JqHp zIY(%vLkL{ghqqwnt5FaW>GcYFW>yr}^I-n)9Q$gnS#A;DU{Y9&x{x6iBOt3h^!3uh z@KhZ|x5(q+ZyL2!5`=vPZF_Tn^6|$AIke`2&^T-fH_v{z`Q&C;`1*O6`t(6499#nNFH5YAmbJ8|O`^6=@h0GvL!dygWXC=(Di^ItuCy}_+8 zc(SVE`5JmHY{*=?QHIA6NX`&`MFMwJG8B5Wx~fnM6J`9oh<8Q>yooQX{R?9Xqbfuy zpBDJjORf^FVEgF*{_9ZMbSiXx^igO8)?~m6EyCP^!as0=L>w8x49wBcSB3gfj1}jY zON3o;w1@YM@l}f;V6OTWuyOzlS2K?s@Kd@pieP(`dH4?D+#wu_vxdW8=lvQOT#MK5 z0mI@>6!P(M^D;vC%xhMmTMSo#eZ#&^wl{^o`LVE;O<1hlK8IsMxG2cyI?iYdX6AbJ zqWf$W1M@WRefcGd7e-Y$jRLeqmEf8&&(g?@Jn+xCy3f)j_u08<2yhNw(}p0|gHo;` zXNNUc!iWv&bgw5(KVZ({u?$y6Y2j3~ns5?3|{)72lyK=cv{x+ z&+$GL9Thv_M`cb0M#HvBxSkH_m;#Bzy>f_S3S_=J=05KND-3^+$|E#Sexrdkr=%#f zUB48jRxyAOT5CkdAfCT16tfD9l9aeh;~YYgu;YG9vu$OnBB)Wr5fw5#@zPkm%+h7w zr(wYPJA|u5L6%R*8vPmR1xQ* zK=xuURp!lk*C^oLc@_%s8Vqc!C=GBv@4WlYH>m*%Y|=oZC=@~sF;yw|9DIhjq{l|S zE`5=f{KrE)i02C(bf}!GFgQo^Of{Hzo{2)OpsHa+Iw<~my)YCF00@1arNcdp&tRY8 zI{D0f7U$i&L@6+AUc7WqjY6?@fqL@~U!8?3R(k9nx|c>HdBzqQwZLu@ z)!`rCeiX6_Nj2s7qjcA?#+5Lra_E_Bh^aw#n8DCaMd9%FfALS~B1G4p(b;e+|5)hx z%~zqe!nW8`QQi?hY%jaAG!wG8zMSy(YLx#0cyc!K%o$Si2Koj<5%4hH(SfYmk1>!4 zQ{Z}*2%t^)eQ7n(6TpsjbfhBtz-WDQON66`I8xT21?yiw4wrxUz1XF}v$h70X*PO| zAAI}~X+;h3cjb2RR(#eNAkW?z83~2(0O^s+jmoJC*~8C24~K!vO1@OmDjMoz-31^B z+Cz;kXnq|^_~f&mv>_8`hxM+e7YL!}`LU?=3m9Ep!uW)fMp^Il^$THkZIP}pq+lTL zN()pZeg7^>`j%<33*aldMOizME@Ok?{CD4uxS$d}4UJ22?xrnlYk*k7po;7^ar;>~ z_r^8a4C3J?YNJ?QLm2!Lt*gtbNKM|M$Sp0Rtpy=0`Cf5HI(__fJ@U$OXwcCF4-(ET z5J<5fXbi?y=;<7}{fl=fdVIVzI!s@G{k727)f?C3GL;oqF(Oft2}OT948wEZCR*_J z$G-~Y;7cKV=2T4zuRoDw(Am0}p7FwH#?Srz>GsRc$JEK`nQ7L%iR=x`!+)(ObO|{` z!=U`dC;)M36@1ibrbk_QIy+SnYR|WZ37kL~%H}ERN5CUYXwOn+3*OTP#CkU5DLUhjTO1LY~=oqWL|Uh3#E`kk=e z_}RDe&;CC`1V9e?(1vOnu4M>F2Exa#;WCVvp9#Wh6mYa4bQxAA!kQ1I$JI6-Uaw$W zTZ=-ag$mD%o^yMpmJt4;@_*slg)r1T7{hWj3KZeF$wA4r>a~TP9F393^sM zo3>iy4porX-kgoVJ=YtqH@zCli;hv*m4a)uFGQjwZ=Og4h@V1<0;z{INsGbdY{HBw zzP5rvp#mb8Isr04kP{(LfIC@+0<*ptni~kYLparHBvH__Euhw&OhH6@BSUEh0QFiM zKCO~q!5PDg1UNl(Q|nXVIab>5U88b3x%qD$gSnOw-bpXr@lLGyR7M^C`bm6$Tx>41 zjeMxenxnK}BizRJH#|!v&!K>;z$CLt82-W&!lEj3!;vd3;k?ld_iu&sX9=I<{R$Wg zc&<-|FA%pN#4Bi6^z1Nsq|dvaM!X5b-mIhg zBo^csg1t(W<2VJ)_GxEUSzHnFGxEdOBM98|YUus=tB^N9%gaaPoFN+=TgwU4Upx(q zw|hhWdTyBdno#d4j55}Qc-TuTH~PU+cc7S>11p_Wd!JYd1GgT94De0CJxRsc+N0ll zF=34;Ma2lr$Et->lnaE8T7)hIMT;3(O<5SPEx0jwyb3QL|*HZZcwJm14} zF|79qMa4eJ!nghIZA+(7&^ccrpIT4P18}kx4~CsA^olzt>3}e8Sn2}vI)PC@CLnE) z(CZmn1uj**gv$vO*h1jWs_NpAb1Fqxs^vPzEOWINa~JrnXY0;~|4*oS^BTReABLv4 zZiG{pDI`j?jf`tg21?avfHwY~2@_FCR_R(|9cM3HiqDJ;kKdUTd80R>Kfospe2)2E z#-k%MO`+^OW6#Y$bY6$pU+I!(DYHXr3Fp~=J@bagskB7pj{Wo;7H$*f$n%RhTk%aQ zE`ybUX~>!4{W3anVU7KQ3u8r3_Ym&y>f+3)#!d8s@AQ6g+BA}Vo+ASmpC5iot4LsB z0-@1bAo(ajhCHu8H=Kj>sbOzzd6kF3auFu~>i51w?F)q517<{Su5hEL(C=e|cwE6n z3j_(z@*_LcI5H05eS}YGD2;TQc3zI@IigKal(R|yi3J9|7DY{=VH`nATBzsPdmOGM z87h8W_XNX5R4@=|6Gb_>MkViMkGT7%Vl180`>3Gk(1;O*n6qgi#?WkOx5|$Sxx@E) zpU+4Pvl><}UcUmm(ZK=U*mC7^m>C@jRn(ZtB2r?OJt@Mtq{6S_s&JUhCsA6Hymytg z#E9YFBAoDE*N_-7oJV5B5cf1*sF)?|P>S<&N3v()jWj7ybp4yrNg4;tAvHx~5jvvb zNX1NL&V6^t2ZVRw!RHD`QNTqZwD_a@a2o~A_j)!j8z}Tn`d*cO)8a<(N+rX0NSDeh zE21*p)14MH{k!L%7%@Cg&q03bxk+oh*E#52)3{-=z{H5*zDX~{IcZ5uG2r^-xfYof z_B~hkEL~e*DZKlgcfVz&NTK+yN3JEp2xN!`C&NLD_rflWEW zJ@a>%b_h+CRJ=dTbr`yc9+F1yLU*Kpb*yO?+G5=r;VPyLAS>80W*Vj9fcaf|^NmQu zra6x)6g*p}^$b#H<17)W)a@w*--eL8mL6f`zzH)qMT8yaAK{z*t!qd{V2(2)^))BC;Ey1d(*J7e@|D z>w83(Aq?jej~^i`Y=oQt+0VmzSzbt;C;S*0s{e6EC?+Lt8Jr$?^eEJ0l$|D(?KlSS z3eLtzMbi!{s0lPpL`EaDz`8jqc;b^G+&l0V@!P8J$2p%lJk3X->&krH7;`P^W{A0w zPhz4*TX|w7pG(sqQAdc%zaI4*1wQFF-zC9xTAG;!CV_zpitd>{ygW&f zJm|Afqv1{@V9TK%jx4l$&7S0=6nlZxkgnA;?27oPcdLs;KIE;$lGWTL! z$SB3b-*hr;WbPp!G>5w#4`aun*t(DB2|vz9_+8h5L;K7@Y7NxfydEZKdEHEuLSH8> z72#>>N%DBtA8v|fUd97%lqf=p|Dhe zRD`SYE~5{e*Nui7w0G+X&-0<c*4$|kMIm96>iFvy=vlfp89nA10PES>c8DyD z7zS>kDFNBJ+$U_#&_64D-+yo~rVNN2ryEQ?SPpHc+hXBE!@Xs019Rz!1J~lSB#bvN z-wgeueGz#Su#?ZVls&;(JwOpV3;ZeUDV(-9wucfzSx+9T!Qk*LTBDtV;XD#}37i&Y ziHXG3Vm`iG1Z+pxQ@N9P%A{S#2=i6JwW!DB4ELbi9@)+d8bcD{)Vwmo-z=o10ic2W zD=Ub{a71N&l!%=*a^X?--NVcmR(}-?iyvvwGX3I!>&6DCDojLyDHH3acjLAtMKA~37u=$Y6j z_srrs8t0s=9u^gC&vv+*wuiK{wu>SLfRh7vC>G#5g11Lu)@vl4kPxd7dM3?pCx_@!>0L+!%$jK=W-^~z|}Tq za*0Tf5`+MSOW*wjAxvRUquCl?wxDX}Iko|{qsAD9!s7ES92$b+>6XZ}g$KJ3$n1(S zmQ^oKaw9G6dishw;WT7Y!%w zvCq{2auV-nC&Iw@zyDsWtKi=L@P|JPPcWE`vmRkg*pY6lB#Q5&F!UYvqT$lzxG(OX zbWBETihy~b2hcnBsRV(#5tul_SuLQbXyM<+Uy(eO-TPf&la9N z-vYi0S^H7;Xoj_AmZU?hJqv{uy_m}@tI@-6+pZl17F)fp5CVLViy%W?jnikyrzb!6 z6#1{xC_4(&Qo}=I!ps~>4Y(=3+cMB%n7QDn{3IhUGb%ww23Q|MtGq?PG+IaR>I+13 zFI9pyEQrI7@``koe-)FYaGMI2igI#|o@ZfE#aAU+fl)r;Ub@$jAHH~=o?(?mJr4>^ zK1+|cFzcEW+>P+?OB_~-G;P6s8ifbtPz11+7K!5X3c^KUP98Wj9J>H`2GSQ~?r-L% zS6Ene)YsRC!NI}!T={ik1c-m+A9=KfOuvg~&Rd?M0n9lIJO1okR78b~WGHAU)Ee^b zez+!$1`23CD>3f6XTq&YtqOMHwb$dLQel*Vil6)IT+ChddKFl&PlkIZ9rJt)%@^P8 zAYg}=|I{$T$<&P`4Io|vgLVy`nRw|MJxAv#-S*j@qx-7R>{*%*t}?69H@RN=q=6#| ztM?fy^8VfL(mmxC4GXSC<<`#=V}wx=4hyQf7L5hT-@Hz`ml$5$0}U$4u>GMhB0mxS z#9{X?Dj1xR;jiB7oIFcuoPw*@dA{!3X^agso8T-Chs`_+gHZ%+^ieHB^Cf@vc?-Qgm|_=e^tVj98zgPw3avouT~>n0=eXcSXv z!m|e`LolVo<%gr7KRHNEB0SkD;AIs@kW@~q;+L>j_Zr4f0+Sux7;D6-4!!`oqxqNp?Q;qU(7{YbyW-&Ud_J-b5~FYNX( zFiaN#&OlkUk7BwtSLopM^f|mb4YOyU)q@?6!x@bE(lz;|c&#zy&PN}G0dUiOJBmy! z&FHy%k7&mxXa`mArN^9c9dt}MQ64#s+~uCGKtBMuaF}^(o3YLHF=$m3cA+~P(EeiJ z**)9dB?San&7xI77F~!&Y5AzEnm7xKD)<@rG_BYaU!51qSn*lNQWGzBd|fz)SH(Sy_6fu~PcJ15H)u(SbU{ zIVewwr_JqcVXG3S6!j2}FlRew86tlkS!41sDUF83qnH<-Z;H6Q3q70%f5tv1sIvX z6ljN$Qqo@|x-@*~OjQ>3KIdzdeff&UMr(d>1abWdU-F#Y6KSrsQjA29Z$(Aj$vgNa zpLMR%H`}ATudc`1BpPEi2nYw#1HY0vn6?mWxbO_=sOvH{#VAa56X$urXWwQQfQ$no z07^{($jr=7ujn8CU)uocsduAf>Iy9a-o%SsH3bO^wYcF5{F~&Vq=zBI6VZaM!r-Ah z+%%OTJsnoEH@v!nd}R-(7-Ug6m^557ErZ2-j38)4Y0J(e+=9@XIuNAvTz#0!+M%Mh zp1>|qt`umSU(If=sxA(&6)1C-)hWzWzT7h9%rQMt}bIcspCD1TZ ze+pv(1xK`eX=y#(d^!@?oZ91|;m?RJfan~sZ>td3srkupt?pV_&rIi)D)2ZbnWJ9o zwnh~F(ZM*sfA-yf7CwFSX6Y0p<*Hf;{GimuHrT z`_J!(>uuMgHO?^I>ld!aJif0`oVpS^-XIRjKk{2otk5 zM&f}?lmeesj)i`lkYx=y))?^p!h`$x&475=zRY$Zdgx+Q0aozlmZr$CEka~9e_K|) z+!-P>*F1Y*-jAqHuMcAc0;zcJGsV{@Psl&S7^5Q4L-a#a!zo%VwS~oO z#C$5@u49<9nymthg0^SpxhbFuL!Q?YA`6gOLIVPYL{m7>U~vlJLxY*#;pNfcaPG?0 zFdqqNIxJb75(ig+!>g~q9+mL~H&sqYdwR%QC0q>pBQaM=sbJ0;kG2sQynlfAwDDe_ z^8_L2Ej${ZB2a?7AsZom`oV*66vg-mMulOFA6T?vG(!(R8>;VpuE&B(r6_E+Op>0I z0-yavF63jRnd#{bdEn~W4*7=X+hX{-btUXiEJHp4eXx*CO(l76yI?J0Y$^aM<0~+# zCGbf4x&aO}0IPNdaE~-3R-=@-|I!-qPlJTGArn+cS!LZ8bQH!^ChX2|7@F;K+o3@! zmD1>ejwghb7DSv|fmY8TShgTA%A6HsI==jpb3j33|BtcGi=T)0w5@OOno zl`Vx9hkF$31t56DoPO}i=Q&h#6h2Nhk*^EP7~$l5{gQ{=yLT_zEgv$pD9eqvsK!K3D4A_vZ=x@ zZ&ZMHkDaG;@@LP^xoA9B*b~Qv3)k&+iGt|5% zKIERN)TosEnIYKTiZp$FLH+Blk~!KOH$L!?@nm3{8f0e zKe=g3lZ2`76^79Ay*H_8@&vZ%+;tsQ*<=os5m;# zUpOCmi~E%f(>T1ZnVLrC3{O+kER#af2MF?ZmeR=OxjQ_UO~R=S6Avfx`k{p1AQkI3 z|LR|batx$;o@X%3_IF?uWj>dvk0QU?LtbcYJslNgyTMqCXas}M(A~QfS)-jaGN|j- zNOj|#o1vUkgc&^T`4}@dhjFOOnnx=tjZEdbAwuRV(b zWn`&{TuM)Li!rlPimQF9Ai6h}9JO=*EJA}&~u z#&kewiZy1G|K_3L`QQi)Da^C~8NiSHNXLaVq1>SkN6-UC~enA*N z#kKL$i&x^HGK&t0vSWB`f#>zbHPQvBxuQq>#i&177Z&ZvL=B_tA`0sv#}_r#M&sf% zP8f%@(s$2MAIY(cZn2MyxkP)}0}6Rl03e>h4k7D~goitaUGR5<7KV^sw(vkML09b=xWJvQ}&P6hjV>B;jJIM7rLGi?UMznM|Ud{%Qb^zlpGkK2Pf~0FkX9!0+A(k^xw%alC@f_vin^Qo_Hhds0=$# zBLPyWRMd-vW$`O|>$xuvdSDj-d5MN`d9?;{oe&P!CLPrIl+bq98Q~Uq_Iii(V;4Fs zK8lC(Bn<=7F5hP)nBVDCiJ+}3;cp_dX6PsosjhBWv z+!3syKMk90F(ew2_uss$aowwDMMfV zU7^X)2tz;&=~8I&9ycUSC|_&?_@d>{gEh3z&^;AHt2KL_9#+GF4i)9bUZE0&whLGw zyU1$=>O9yR**w%l3e`T5LYo3##%;El1R8zD#M)~Q)VkynuETFQn)G6 z!V;QaOfkffv_RqWRQ}ER?uTfsP?a_li>Jk~EU@S~tkBkGq-ZC+^Zo~TNnlJ64jKMh z#(G4mvuD`1uICi3qBa4aJJ$uOON;C>&Xr6GnjyF}l{QgtfeNXdx7Sz%ED{8e#JwoX zC%3*NUED+hrQrK~h(a{1ck5s)Mi8_gZ4bA*2n&CKh&Nxq840Hdrjj-`MXM8pnX1YY z(By*%7kX0NU;i!w8l~W~&!0ONPG_GEBWoiOksmyK6bsip?0p!+BAuTEs45?Y<9-)? zV#&37(RR|*6&dKjbBGxuD*q6$mq%?Ay~trg^m~i$X&9@lK1zjG1ZxzQ(&L0KlfRaXoZ{SYoN&TP z^7s<`N;RcIHzATG)PJzBrj`7cR}iL{Zw89L9X9mxSa8VqmQ|*E*KeY^z*&zx1WTHSI&j3qtJ&%h<`nuEQZIT#n;Nu;?U01r{Mtnkl=2DJH_CQ zFgcF^x5_(m5WpreF5LL;cf$S8KgDB@Ck`A~0FNqB09BkfFr<_+r$%5!WIPJ)9giN8>O+(awD160SOP7PewdCCE!gaz z%0VYWn1vM^F=R+@G&D}}S!qo*pg?FKd$!IQSuI;;xx&wX`Op7(EWYQy`K(s(NTErO zkOfUG=F^AZR>=N}b35#Q>2>ZqZF|1X_IjNvXV^wZt^3r_w)BH};ru^I*Eb<2h1B?Ek^@l1#K_>~D zC4MG$xkzxx@6tbqc&0!gjkL&TY%vB+R*`f6>@*|Jjt`~Vp~ai{M_7sy4Gdg(XE~8~ z_;(csy}l|mMjGjPav${gngZca33ezT$e$c4b}GFpvU;_n*ZakF{#_5Yc&1@m1<>o< zPidok#Pb!`9MaTLyr~-5T!=#g76$bjtO*e%G9M z>XNm|Qyr=LR8$^)kH!bzEzNLFiDK`y$`!s>n3*T+Q(;hAq+;yfyvO2_4q@K#dC$xA z3gJ0XL^a+dUU~&I^2HOT$le#Pn7HQ`a_D+H7yXhjnGM8z@mNAbnb9u!*8rx zVXLwj?$2k=FB%7t1&+Ml8gfq8hW0C$!d(>E+Oy{(tuYFz6(iR${Qfx4Rv8$8)ZkqS?-nkvy>7Agc-&jw7Xxs+|?)8OKLn<9j zgtuRTUsy}zD-HP-6yO{uEkY-P{Jg|&LbJ#j&=z6!Slx-RREQjt3;n}bv=1-Kmlu^& zCk7>9w%63rMb>nY)^>w97Oo;!;SI*Hv4qj@(tFpaPPxUJ_@<; ziH(7NQuYSIo8SEtYBH3CJOAdF5Itx%YuLi*IdY5WH0Wz>eJV`CXX@csBi$%c@ZlQx zp9+w8E?$^2x6%i{050qdAWfTM&sO=n%D-!Wj1hSV-n=Reh6WV@PezXwvY*O@c62h- z-2F8iy_olEBva{I2F8Z}fK0nYJrel1(S_1uQ-Ak2DZoe6q_DhB{Q`$Ij2xz^Nmq;# zb{t^Htt1jC3x|rG8zvV>%S67hzKylTqzl5cGUhfl9IXA6i!-CTt%beF31zh>kk_b% zLwdyiHt8eamcv?El^7I;sX;aN#qF@(H4&DlSm%o&{c?>O?c^!$&(ah!&J{W^*zLHUW>_k|kmH8S5+Q!Can;YZt?@i!GsZY$(dxGP){o&JImykqeBbEN*B7MrkhyUpfQKjIk~w zQ1jT@4dO&be^31Lzr zPG0?SFaLJN!9PL`fKA%VnX4tC_n=!_Pe)IQ%C(G8i=#uqDpu>~ItltL2rP5;a1>?~ zDq0cX6Xxte%6PrTN|hscZWFJpA>s;z(;$(#*S2|(Xvk!$5Go}ABee2+^XDIg!L70I zaNu!7)|{$CX^W6p@%yl(fH!TPeYRCFKc*8&h81FsbaxQ%M%MVdcCcmAuNhq-Ko0T{B1idA?A2RSEte>{HjIELlum36*a@)f}K z2z0{$>ZO zZ+;W<%ISOnqfwFcvj>kJL`$ARenlysJ7y5kez@ zMGl1*4PO@F+yL%PYf$i(5SC;f3a46|DfChtdVv%7U)Zo!%j}~^p$bAd@b%Zxn`|Mx zq2K&A)Sf#Zs?MJcYeeBp&5nmN=PrbYAO8*|rZ6%@qenDU+<5;-QBmH7kVl0FK}RpJ z!kMj#4iMm~_}PBXjhD}b^7fX{KQA^8PYl? z?%#{y>}X#hxA9cCir^!@$_R}5aNNIhCswal!H}r?-JJg9c`E-hQt@^cI5rn<(!6(` zW0XxPUc&(tZ0BH0Kbi0jpX+(wg;tf7rt{zX3C}!qq%gExY{y8nPQDx7s;*92oSuw= z^CljqZK5=q>uBW!Vt4m+N5--aBWk>GA?~{Z+Q`Uo^kUiVLnfo3yM$1e$8%)r&Qk#; z3b`n*juY&Mt^CB5ZJw9HL-QF?4(+T{Aw~tqdo;Rf;8AgNpVkqImRZjNjCYScc=OFS zqcWEV?l$lYy=l&A8Uf+@kAF;CS6U2WP>=nWNXcpU0s; z7dQhAF471i7d$(Km!6Kt;f;6RiNc$B;Jj2g`*`Lmv~Yn4s3=@Wm=0r0Sw|EOc%OLadG|c+#+zOi4bJv3j)QxvpkrQBib5iz z*AQguIbk@7>`A_-Z-VC`TqsoNHP@T3GOq_zzGkkrhTmi)*CoG8+q~XksJrw|xJ(QJ zFDvJMj;k^h;DM?{$!L4yb&8jL3XM1xiVSmr77X4}P_b4p-rLq}4 z#VCx94}SbXG{(3F&srr_;l{mlA2dYheOBrAOubicz0Y;t(hxtBE-MI{&tBhHA7M`A z&(GvBD%}p@P9CYzH<^=XscfJiud*G(E4fzVg?Q|HG{%@qz6gJIXvB~fXfV(i;In*& zLnT$-=e^1)8UlQ;UK*8muNQ};bIKsfC`Nfm6MeUZ`Q*E<@y2U6C?xtcKG!ohl`)I^ z6=pqqm2QV#dGB-oeXk0+_e(4Eg1dKKFRw|A9OAZ0viCZ?MmST}@%{2j&qD#$yjWo& zalj}jyB-Y?&LOGOAdParH5eqRB;x-DQCg@8F%nnOq?f zjht%)aXob!a5WC z(-!ID8gr1o`BjHOs-C&((Hp@~s`9_}fSN2fZiLyV$PtZ%7DHcVo)3fxitA!ojAy3& zA`UH5sBIrvOa;TvR&(?{U#G2{M)g=!7g@2Sh`KZ=HAbHb`(1!~}BpnX}X#0B&+QhoP^&42|%@ zg=qvR1U6QHL-}K3T*Rjw zX27T8(DZrUT~Kj^;?1NIfFrNG^?De^fOG2IYhjSiDhEWCg>lx+yp&ai+hhpm@-bl` z(j#gUWTATqS5xe}a4$?cPw9w5!->(V(xt6Mj1hE>TCrX8_#|YS?jJ<(mbcJ84_UQ@ z6yM45;jlqHs^fGa*e)g199p(OhY8z7k9QFX2b{<^<@pZjg+>x-m-N~9Yk-qZc#g{H z!kNmg^EY+P2mr?nddCEj5!KAml<7n8E^$;E@fi6C;u|ia^k?v&PK(h8_d^>_h%9U- zqaWR-kR(P5&O^mre(l~!2gF)%QtOW{XF-aVH7`8M~HmlT%@B8uXC>Mg@yq4O$4c^ zK>z6JiL!{13J!7Axi|;c)F^Ie0K@*{`nXodukZAF_ir3{^BoS~?XxsO?;R_S zpM4wuWFBM?0q`w%0a)vWX+ywk6~qCuCr=RM0G=wsl&lHhrphb~A(5%>=mB9Psvuel z1uEMXRd7QS%Z`AecgMr@u(gUN!j&}urVu7&I%`{4$rlkaxK0F>;k(HT073yC(o8CC z9zJyE ze68}+DROI1P(?mPi28UedMH9W2N|zO?L9J`t4&wK;wF|Y<{{zgkT1*vqJ38?y5|;myvp);#B``<4`gi~P|09Htdc!((4x)7lS#Fz!cfFc$?P z(LyFFqZYxU0t&;FU>U-zm&}L;y($t!k;yZ@c=l3Ef4Fw~T6o-pQb^qab7MdG)vrPW zLW6`rz}FM6kw9Tyg6#coTzH)pja1u)NNbhTU~oVxg!54__A@>CMo;KTGT-cK>os^X z$V)_nMC9G`@6ww*U2#}u>V03Ml>WsJ{vwRcjZ?jJ3m9mj?!lq(#sB!fhXQET5kj#f z0EX*3vU2HukeeKA?+aA^7K^^QI z2&Z7|!j<`678#QGAbt~dl^Y{JuF@Lq9wCGYxWsMgq8?* zuc7?)e(?pZgfJ+vpCj{BJ14E;^37Mn06EWF2v!r_)DS@^F->Ra+0*D97bk@wnV{p4f&&S06p81ZL@b-8y6?7rW8w^DK(H3(cJ6gIJBJC7-hB1g?==+W|b6$%WvKY z9iROUmr8VCn zJIKC^$+}?%ll?m2lUn(y!M}C0xZ`_;kpZJ#Q6H zJ2fNCXzV&fPDsH4RIpQe{KB;QskOL(~&bz4LWM z&lYfDM~j!w(({*>`s~Co;Pu|`87s`XmgIc=oAh5{(Y5$DhwpZOTu&6H*=p&G&yM(s z(ZYE5h)OI#zJecVh?<1vEV9-W6x@1vi1Nz~6nVR*6hj;J zFb^VgS$9Szu2DkSL^u`~#7n!y9BFBeUP+bWWnle0Q3YLp`)g7cDMW@+ZB(5`a~0OA zT3XXWOH9SosPx)f7zFkF!=v}tQ4}CQI%(Ydkj@Ff z);j0n-tGZ6=8UgFL$@%N%`!jJb)r`rqjAgCOCgU?@I%nBx#K{k}m|6}KI3UU}5H~k9hcABnTROfRkH$pLtoP~D(8eAKQ_o1hT<7`wz*!kMC4OyT z&{+Z&XEFHIG&B&7Pr4sxcz`_npZ|-05qX4Njm*6kUj~S>*nQ9+e)!+~m(+{89}S(O z;JR?Gv9nBB7`a^-&!v+>O)j$I;AE_gW9vjy8INJWoP+P_tVof1EMB02h1badG+qmvVnlgp%G1|l( z1~UGMS1-~%>M5x>gtHUXTU&oR3{rqJ!6 z*P|^x)}X7ww~h$9`9sLa7tet!{S;a*WZgu(fs>Oc!d1xd4ryywPgktjBh5I9fhv=3 zJjJvxT*UCHLjqDC>63F%hY&u5GmU+5aDktx#PdV23!C)Rcj;M|R;WW7{x5DuBRijI zpcg-+UwYG5p!?#Md{G%n=c@4N`(2xR>=`7fW2O}-7g`9rggsDR(~#;j>;xc>mah7{ z&z8|E6YCfjjy*%?mhfI-VV^y+zLA81W3fRG%dmSbU{(yxE-MaQ z^W%gS)AM|d0(pdhd~y2=CXz|@eh3#~xSPEw3J@+RH*ZRND-b%=;dOZDx!!)Y8V6Q4Y~i?% zSG6%J|M`az=m#h;SzHhakc8ey0wZB8e(4w=#sG(o({}z0Q3F_7v4&SS*vg39Lzqu2 zq6woYH5?HGfbgSWqJhDv1HBi9E!z6X;eLpRo|z2BVJglHZ6@at%8nexTE2^NR7p=* z_J0=PVH`zs8^vE`UV{C~4}TD=IoGA?!>!N$Ko5CpOJD$)c=8N50cY{r8J@n+{n85= zKn~|G;gzvIV;|Qcy0I!WYZ$mkn<50vJ>YnWVn5R`#ZxHnOE8>6L?>7)#CDa(5YBBW zGmf&W=lK4e+jIe1LJ%5^o@U`exWF1kZeI)U+l}i~kX8X+;OhwU(A%xRBQe*2x5{4R zgPW5Wo~$V_hEXCPLCN-)(zE`7{xA++G$Ifgb|wc}b$u`m8J$HgZ@%*`hOcMTML0ub zPIhd2su5=%gNS{78)!AvN#6V}p@X~R|L?*)Wnwu9ulwxR;t0hod%D9LKYBlU5aN3= zh^de~Bg&27e;jB-FLvPV-(^X39rBYI$b!@MR+v84Rm$ILXJ`3 z<17>+49oNUbND(y0NiD-^ycrP2&?o7QwkIcauzz&VlQ(Pzg31z#aQI$0`N2o<+cW# z_gYgVPC-|?*(X(3adeZ>&D-|GnLyPN~;yX;c7lTbcXR*(|I=A|Ix;O9~ z&v_Skibf9J>pJZZU3s>ZuSSd<(2fe$G&vguzy5CM{EML>(^LRQtT6+9F~8S>veHtA zt!oowYA#{7p2sjD%nJ31!YQ9q5K=&tsY^@!S*6qK#3PkC*CoAEAduEY{Nf!d{qj2L zyZ9syNOSZm7<#C(FE3KavEu#fZ@eBo6TbHy&bFU0UB?QF!3w$2r@ljq3JUvW{x(M4 znwhU2h5THMMes`Lhu&_VW%Pn0QU3keNCWpb`7BW!6^@K*GrU*fSH)cehKi58*7ZAY zX@~1pdDgI@!Ns8$+V#sHlC%idCER$gLY+hJxci_2Xq^K0L*-8ciLt{_cK5<{3*Q=-^}Z`~CJM9)q{5vM z8!Fqb(e(?58Zm|C#ABZn0E`9AP)gkw&r+|qG|%T~F!vdHhCKT?N6tF#H~d1J_I%y1 z#A~li;@Vt)6g+`71#IV;?5V8~eTVQRj=JwJ4{4vcsGKCtb8K;D$5P}<6OMf1-AkeT zJP``KcV!5H{Qh8ApTg7EI~Zjw=c+7crS7Jd=IEU_(m}X(O|gX;e|IGCZ}f!kbVyI7 z6Yjr8Fe5=db7cvQHTFc;Sg!IfPb=lDEK+8LeGMlUuU!fq9go5it^bx5X2J;gzrj9~ zkPluAUGllYncs!=49;bRxf!A9{CtmI#O;R?5e zoqM5Z58UjT2*o+1TCo3dFgMT9x!Mv~x@k(Cx$CxRGs5Ul?th33YP>=O!nxYefMPfV zuWSR4y1F{U#;pfo8LzhcG6H?x0G|%npM1_wV~zCi8WA?WcL(KlpYxW+WMJek#KCm{ z&&~u+ymoJDCNy2VPO8GQ@aok!DWYh^DwX7+3n!qh>%gsE>S5@GG;p|6 zj2n$uMHIk1MZ5Pa3n)0-%Fm;rov5z`)@0#rX^)-6?CNDVh_Sm*!fQV#jDCnT24sg_ z>Y!Aeq<+r}qhmJ8{oW47T%umU=#Aj)EIyMJ4Ds`4NuA zXAO_SjpyT+L!6kHnF>Xzt;Tqd)O;D*ak;A%T$NGHVD$*|ATik?`q?B_&{zeGEaY~dGI-T;Xa+Rx8z8k*B+JJ*Y$kW+8 zdzKm#D}%Ho_q%T@UJtPlbAopj9#5V+!&2kt<+1u9}35UX=R#*i}qXJ~aRR|Lv zjLg&=D~EqCgo&76=^=}>TB3^x#XfWXY$QYq8x~{H+oQrA0RrJ`m0av%6gMr~Nujr5 z!m_qG%p*q-_{V<$Q^?afb}|YT-s_MlIF=4ksq)S95Q4_=wEKCua_S;Pe>Vb| z1ZQ}H)_NeIUMz(Xg+v+m$k<4@eCjf31bB8}K)3M>ci~y9#u~c3kH-SQvEOZT9r=>m zSkzJIQf0InDaZ_W{^pmV?|=G#L+uz2%WD6ItSt}2Y?>jQ zD5WcSN^B+Oy;&s`8yq3el%helK9U$&kz9|XeaW4#9!QJZn4hfj?>WWl>oC9t&d|Rn zmHGALOE{v(3#+i9`mv}C2Vo(?`KkGs4xsXX2t(DP=Z_F#G=Ml*({M5x zu3roD2=;o@H^DJ;((8b|trhSG94?`N=NiJX#q-2F8Qvm--hdts1RP;?RWCMhC4o<+ zQc*xQ3PqyqJ0-?`Re?V;_8KhHG7{l+mwnd*B3@S^@OxbfOSJR12&ZT19v|nP9u#pI z_7s9?)0HdXz4zV=&ta(UiC#j#n@9S9mSvU9y&wZ4=`3N(Q;Xq9{$X+~hr)Ni_royI zOBf?`XyKDD!&)}Q!Ro+O_IDixB#(Vis4!&ScgvJASVI(;Fh)2paV3v=iletFXlN0_ z%LtMx&BBpu==}V1LTKyb**bp(0ryWPs-eLA`z_AXlz~0oqj1rWSBMv+4V>-maUc8H zqZIq2vDf`{pK91g4IxwD{w()sY>}xt$2``dqBSc_aaOhnU4<^z@H_<~ab1Ie?^BTx ze^;UDhjP+Ie!Taqzxu0CaT-MhfuNCnwmX8}gMQA=h=Vy8{p+tW zh6P=*MuvHe!4`ykN;C|WC;@)F92ppqF*Z3=B!vq-F3C_y^X#0r%D+md`|sWxnr$Ac z%A{*E;zFfUd{u#SUQtotj3Q2hs}4OYF=d169bTUd*W08K>t8o zb21;l3t#TH^KcE(kj=ijSAH%GYpC>$#BrktUT&k9D8u4=;zjp*L;Dp#g)56Ix(})P zR8*FX%m2mpdX4Y*vuHd}j^#_mOIgQ#^WEO(nY(X(cc106 zQR(Ae;X_<>ybMR~sq#%+Gk?>w<$H82h+7&>^l%Cn$$EW86l9^RzE8zm{MXxl45eyv zWGplg?mU@~CmfiW@8}8Hdxyf};{k6CXWD3^n2nK@JrD<+t8idwzC))+F*HazWC(dO zJX>*0r8^qOxXuvV#5m?2ID~g)KO;8EFfKQs1kO;%*)z?>7>AwxoAa6+n+Q1-1E=hcOa z(W5-W&!&_a68!+zjxP3qx zDmuf!1V9$TwV!@38hEOS7PIiRN?#o46HDVWp`3aTYn_833q?4GF#ZB+Cy@9V@^><5 zt2r9y6pXcov--h=MK9nNIR6d z@_6(5_+mJP{51UBS{11<(>)l%&{9|-GFVzKy(@=y4FmT+_u@r6L14i08Pc5>!+FIB zA%6E~`G&*yE3YX-R5Xxcy+n!+yfXAHhI4=Ze$;=={r6c$;%e|*L$1kzx75|A&_mF5 z4&hXzPEkWSE57Fv^;AF_~r0i3*gb_`ui^D;q$Zj-SsyS4Wo{t9-__`os#f8 z>ALetj1PXU@-7`V&BA;AvRjz+Q_sJVZVq8WJ`rgiu&@9R)95Dd`flMRKA&sr>(ezU ze3msYa#HEYjrgE{=zk8Z0q|<;f6Gp$wb_5@7x26diU8v9jE608^dPltE8t1wlFiX` z>(2?3h#?l-?;!~&9^5R1R7<3u1(||MxD3*I0iL@dxV3~PTiy87>E@VE8U=6^T*q+) zHVc2Wo^B0g#fNFB(i6V>U;jl|&L+Gci>bn!0A(K1Iz;dY1S*B+Eq|W8m|^mqAh?Nu zCO}0-TUi)tfAA`i2DLGVb#<3^7OdmW{kzc!uz<(MkQxPE1wgBRH#9Vc3KYv--wV?i z9HG4q;fM7I!g|=Whz<=8VRWEp{OoY_SQJ5cA9WB;Nq_o@55Ekr961#_vHUrTiDWPj zeT+H?dj0Kly)>0ZI6eLjL(+OXyT2)*vQ6HnBPoDoB!(Uy8O~Y*L@`nkTFqRI45jK&Rp^_<>&6-d=x5zjKu2)5IG0|>#v_g4 zP)WMYp^BW0SZ|C-QE)HZS~ysURnmnwg`)n6!6I2 z=WgLFRlQ+CTK63D5O0HQ|H=FB(PtD6r%?>FKcWpZKFPpNx8} z=o$~a&$<`p=qE$?lR=6{5~O`15~9%u;d}!nxtNX;5;1Yi_nA{?=wf^ZL@d9=Fi66} z5Oz0-ATT;1!jz2YFumbvO=HMo5;__MQgAVw>&i*3$%3f6hlT^HJg#-%3E}MRy=*00 zi^mKD>vpR!e^lXW?6`RXfdacKkM4$S9=fBBc;_y6t}VGjm! zBt;z#gpuPlwP9j#jDl}ZF(6=-Eg+;7rn3w4a*Zk)v!8wu8s2#;RwrKQ>Cu!-{#+>) zb<^$C6tHDT!mdibuqrc_QTbhlu5oFb-wy-V<~e`)>8H_qKCV#MmSBQK3II?^nqe5Bm{f*VwB|%uzg3c^+aP^AYC!d53)k zIbyYam8&gqcH%4&Yq1lT)Yy$3R$Ct{|= zq7dkLx`xYF2ziB6=n*QX~ z(DAQ-jdd0UH=8;Hkc%~VjQHk04ubCqoasqdE=$&Y`RbJj&*GlB`wn5+_e%3zn|tZp z6@=X*X|*&ud8YGsO%AylFVnZAb)a^HX+wC|S!V^Zr)RE1 z=L#~&(CB!$c7{3x6bD{KuGITj*OdAXh5z9H?#bFbsbaJZo`I&996`AwZ9!$nR>>!> zw}(B_isq>HZixRLF!BHM_GZC#rssj)M-U`PtRx5m#6}ztAV7lPPBzKjyQS{7ByZ!< zlq(tg#wk0Mo8&ULsZ_3WH@B%u%9ELlG_oDbwz?%ty{R{n%^d_tVh6GBJ3xTQ^SpdFba9HBVg|L9Zd{$b43TgrK_v(`EG`~)~K zfT7g_vPMq9U{XDG0ZgAWcUgRjqS)MLd$L39k8rgD9?fz_gV1`F)Dig2s!Arj3?PYU zF6q17T;vmvydS!~g_BO)G-BmoC9-^JN%XJZp$^gd6WX9sUulgLUg>bu34>*n z7;U4d^6$_vp+RDcD9ZW1(KJhuz53Q>BD`qnd>EM!7*ko#8^?&wZOR4A6z|4}iF3wD z&JjI-xWSgNM4RlRE#+dq_Lz7f{;ipFPo%~HiU|%s#!+^i2!)BIkZqlV@am87Ec|8) zpZCi@Gp~Cy5d?i0;Epw-Bop1|_0sH2@ypiZXa30NG|1|Zcaw-AoGr06+jqL_t)0rOqL|Wb|C)jcfE= z#IgJUAsI$pl%F8o6DQYR&Zx4Z8KWB=dmi^v7@1<4;LI9$EDc`+jxN9QYPxs-9(Y-u ztY1(xPZa3DSa|5AnbpvAbMdv{MTkGYWeTt~TE1tRP$=xo(X_HGxW-m`c8>p8Mgk(iP$6D7YqF)wtmB9?#D9gJEET-grh1aoNJD z?&%!HGxxZdPD~Ni&by^w8dIE)`^kjjK4IPV!2X$ad$4v|E(aVUpU2=!Bjuy;p$lUe zMX|T(J2U`n8v*cA+jrUqaIKHx25f+evtEBgIx?%4n*t-J!+*2m1;Gn18FqN=qv03KlYKhj`*FdWk56Li#=s9iAY=&X~DpNAvQS!DO-A|vS z()LC|>=9Tfj#mUT%~dz2VF>c^hE@)Y!b;>1%?(iSV}rJ2grV8FKmdyId?k$@Dol0f zJ0RFpMkODqfC4W^Au=jo_P~^BSeez3GxIu(a@fPVR%*^7!%{)&`Rjj5^Pk>NgCE`w3vByIyjT5Lq48d+a2g7w z!a~40Muw{JUh}9RuvYzdD10f%p1w%Lz}N(B)6RwxS4n=3R$VRD^Gg)Z=%Db}KC1ne z?M^j^4nv6hg2-P-2oHgXJCgEz-`W_>1*@OWce+A1&?7DmBYd3F+}U;g%2!C1Yw zp^Ut{@c}&e1A*}7__ZHtPdEE-M#z>#LHKYD!!Q?-Tc)g{;QQ`AxC&52Ce;)pu&w2*EawiPJU%l_2tp6x zKT%bmzW!hT1Hw`*A>=Sg7@Z>&XB6=SZ;OimgvNWGGA~2vt0)L*p&xUdj-6`d{88#R z@WkEfPRn?48{6V0aX3dGs^~_KX&&Chu*9^=VAVwP9(* zdwIP5cnHIRizqt^D-P2NN-656k;Z4L@JQekGF5;arUk@4Z=u-ny9{U5+&gIBbNbnq z)Er0$>5MRjQ1X=X)N_0gf-HQ^AUFUt>H zC6P?aAHX--5|zVf>Q3gvL^ok_$1dV6{Q7n(t*K3w&<6$22#*GK4+B5W@gO*3WP!!# zsvyFRDAW^o$n8VGdkUjHN@$@<^e_UJ1qY=u-j^{dnbb32^4Qg@LB#c(U%YZ9nEabC zX|MCg7JuF+yz4O+j+$V$3Y%6)<_iokm60M~=(S!zYo*-1b(c0(7%-q)D?=lx1) z&@!>U+xf_rSKod+bz@Aq@ak(3MWYh<l+(F2`eor1rK*c zTh(T2p^Pt5Wm-HM($kU8F*Mz2oq8&I3+yp%6>kfBWgRq(!l^u5NeveA0x{hEe+`u! z&qkq3LBeNS5Kjfvp=Vj8&Nf1N)-r=*^Reb{6y{8k6n?x`flxu^t+(GIc);A;qk?D^gUrc6Kw$d%m>%^C#Wr>Fry09)F>1B1Xb_KiSzyfuVRpQSP6+rvU~ zt|xn!hCk0z@1ObkD$ELM4&lTQZoRL$7l-d~&I*vi zhwJv4uEBQ-OP*1L{co(tJXN5wD)`?h%B&~oDE#@x|M?;5rBP|ym4fS_F zz1Q#e63w!w5f9z+B;Ql)5X0>93Uqmz6vC0YbovDO{OqOka{qjWG|s;I$Tk+g*^C*%ZW8UOk65-h3nWLgULff<5cDkm6w9K=46j4kJ&5 zCEM3&&~R)PKTq|qQF(j{JOF-7{Tzm#>wR9t$e>&~jDgm3JPfV(`IpIaSH2Jr$AClE zqLT6S#!bxiDTPPV++hW(@{_M(8^NB*i^>}b+S^vfJ7t#^vn6aDdYvBtzT!d|hGI<-uK#dCaS0BUZunRcXxp!zc^25!c zxK24+7_eJHhTD5^P8>ldvyN3Z3Q3nULeu>eu7x4;8c0Q~Ax!>Jq*aU)RaprRudv4| zlj4B-h{gZ5R)|Wg#|Vt9wwLtRG9or=F$7Go->b+y!fMV|$QlX`VyIzncCQe5RZJ%X zgb>pl+?Nc$rAH3wvpgvCaN9<1e+_kR9`~f`dSn|4FV8~nzdhVj75(G)8_$=Qc zPxX6$H=@$#i?gm}#DcTXLnAhwvwT7ve;Xcg{rZjI1Agv2HH;d0E6?y*@>lU#eaeva z^T1&i0VZ7^TN+7+aICt=bDw^lO3*P>kc~3jgF#Q@q|deJqsCXfdf{MQL}w~uuT1?B z=fuCK7`NRc>7;Uy`e3$anKG;#u9MGw(37q+&j>zg-!ku!Zg@`UoCIiSC!ktb@BVeqhWE80m2VvUu z1C90Wmv|LMC}7(?{$}{H7!(6+Z3+FvHCO=9y>|^6jkB$=_~bnN&Xf_;>I$L7-_<~r zS>Ju|S_csTG_d@Rh6aFgg)N54LU!0W4o}7-@fN@pYAnLyp-qCI0;bkphX?K^+d@Vn z>!vAmn3J^!Caj>QmDZ3Ag^Xz|ts8j!tm3ZKvJpiH6JQ{t`M{C4!CV~s={0|db{@N{ z3De;~#t0?aUr~awfg&p~S&IYCQayUwE&~IE^l?odStue1uoV)TU5u4xu4ps0HlR36 zkEBag6cgLM5+UOr_T{R}X=NWRO8}N7a!_mQ>(ZkqkJIbNUQZ({qal#hmewQm($ecQ zs*M*BTDXMAsAo8J{nICD{>$!E+(%g8XI-@YyPK-_lt-w3b!|1)V61@IfFP-?Rbn9@ zc`_0?-TM#H-xcNY97@#SQw;?WROK_SoxlR=n5W2zMXeN$?%cjhg;@X^Bg&%&)$5HIV16i*FGbKs8Qk6zngDClZ0q&|$0*Q)p3s1$MM z83w9n%dlLc43^hW26pclCziCq`ffs z5tJ_GZpVOaixWY!c2USLmmVhY) zZvu;jFzsdV={&;Fty^CQEUBCoe_&dPavuL95(G)TL%G)#r|i;q8!oKy=2%0OjQ!mD{; z&RJSv3dgMvKTKQhJ^OXI87~EA=l%W+lOizA{2H*>Pjk(7@00ZQzx}u2ku%&(VZQ={ z#{z~6I1>VJB^96Vq|O%}@^XY);lw#TMETVK5y}bAG*UrN#8cMAWYQGR&*yp%rb`$v zmYAn|-b_Ts42*Z;v(HjhXJ;ycsn5|Rq4}M6m}|aRo5IXY7m)?P{fRda*x57bx3E^m zI_9D0+wAQoIJ?6-Pit&oZ)fh^ORxO!hv~zg{ftf%6zoD#7Y{5ZXlS1>G>LK1{8E)P zBQV4X@mm36hBcLQ-Q++1IvsoMTI{b1?h<*bwO6i2)$AICA?Ko?^b{J>!k+sMnfMS@ ztxNF;4in049S6;Nn_Ul6Ma!{tQ&4_(!XTp%OV;Mk&-9+?84m9+=VN^gg?8zvO4%gg(Q{O-HtK8%VaA#b6?C4M z#<;yQk}sU(yY=AuK0WdwO!Jv(3<^5JunMcVmI=I`xja|lRb!4r<=xK|PK8_0Ghjo7 zRwJKt6h9RxT~{U(hzr82v_o&dpZmQ+Qx+-FiYM23DYWV#Z3c(Trx(u@p@q%KlVP8-Fz6oI}iDrh6{ybL(^5_-4l%lQGkxK z5?1w4X}}S7za0^f<+#dcJr_r=8849ZfRTOX@6OG2OPjpL^A?UgOW&0lTijEx7~;;Ba|L>KMMR(z?8Q8Y={4P-UlceS5$Y10>v|_?R&4JDfq=kHHM z697LNkqY3IdgWHA46kx%8(LvSe6w|M!V&Z1|Ng&AJ&$^5`+F9{$O^@4F)jeh>(H<_ z{`5~%FU4Ig0O&jIQsY{rdn)-%be}XHXuNxFG15{L*vg}IbdWiN{6V4X zf;|x;-r9yi0{DOU%lFd{{_3yN9g3w+(PFQxm2<_weu#A*gg*@N?p_q1{p^W#Z7w0N zY25Xkrr?3kaS#pm^+lwYXRb1A)N0qKpQgR++XU&DC!n_)GPC?@@l<-O{9)L$c<5(( zouv(WLNSk|5}bGQzrID0N9qWWifG|sJ0X=(H$eH-2+X|GWrWX&MuE-}I}!yI4;-!x zIltu?-GIQW-8gOLDEN2${8{8olu;ZXgJ0jFeeY3fFo2&J45TyGu5vy&x5Jyix=s4Z zFe$shmU3qa{OiQI&V<>I_SV!8AlhW(<3}7b5iG?AB7#)fA)cFp5wz&%=dLq9Z0RG+k&_~%DX+zLQ4GQeFd!->j+Lwj+`#zs7FEGN&GxSFq zS%V?Uf2Y6+WdLnJlE3*FJVXAkAxhrjJKP&nd*rLaijm3BpzFmgwfTF#i~l|+1)%&2 z5dhWz@Ql8LpY36Cb5P(7Q*tA+;U)(_a7GT5c!64rOa1_sxs7sq29!8{$WJ<|gR^duY41 z17fz*6L|$9@LKunseio}feh~hp>IVfIJ;*cMiBZ1!f^$@3m48K^pNAi|7OX#^0V#d zYw6mFbLk&{{?pV*b>(g5vyEqdamyUu()7_kevm4Q$YUHK53#zI{+_o{G&tzV`E>u2 zPgC!&ucwMB3Pju+N_YRaze_W}ypf(gnn>F{qp4|E8U1RzQ&Tks_XZFYQQ{Ytv4ldr z98K-4$AT#p*m3~I6&TRLBb5Q*BTt4?4+xs211OL=&Rw~Xw(&-vJxlvA!p3_EZQ4PQ zID(Km{NQowTBm<{XKTJMEY)PsK->*aZ6YnA4khcxgB$5n6q?u0zCjx`yD=<;lAwSj zFM^Y1PvL_(l&*ku!IKk zqu|@-C`SnS?4zOd^m=!yp}%h-+P26VeP-G7sF8rcKlo_CEsW58RL@YV&5fU+hQQu( zEY(<%wN$U8_^bR|0B8k)Oh5!rmNSwlpkLA^U zweXnMRa=i8AoV~GX0C}aGCW4M@zX2Wbd0~L%p3+D&RE>gvZ#kh;xB<(p_W7xi$rD< z*KC*L&?u&0vAv0<8iC4iW?KU4DW4-!VRi~!BJ#oXl)VUR;-1k2#pL>XhFMAisd3;Y ztqf7XDro7qANbru5yc4#^BF2EA=aBc*VmtFQShF^EZR^6-^Qc;1cl!7cAh?8nE2$^ zzb2xAC<~aG3}OSK+y)$K*?s3v{)9Gpk12dOmDWF|z#{1pWhgKT;4Am;hth7u!V`oX zt;)xF9}h>6EQ&eXy3epHL!8~q2PpCDFqL+c;05+fhPVety1?`I5PhU@VX;4%NZ|{( zG#vj6Lh83+zEv3k#riE zp9BsR?2GD-#Jb0Mh6;xUfTuhoN9gLQQ=P$NCiF0YAMTfM645fAGxS!0dX(zUN7%0k zl;nLdTJzxxVS3JU0A(AbNuwAPgcXeo z5b1I%gcOvM8RGyX-5^rMf`68l@q z=i<5V&E<0O425!OL@CdnW)2DbnM0^K^nz#XFmHvDM(B(JjkxZ6ClF9)p(oBw#=60o z&U-(w#Dl@>GQ3`w(x6O#X#ua*Myh}5OyJLRYN41C(^&r^A08C9;FR$0=Nj%*J~Wmp za9JC`-qafCtW0j}P`!bBipYltCWSHQrUI;j?EF+T_4vC7!bj$%R#86boWng4 zmJAJ7K#^|wnM2+w-Bs}OxhjO2K|Vn3Z^6TV!MwT9W)*ak4G>ZslYln6&TOY;TdEF6Xi<^+rCHPF!RjEh5W~}5*A#0 z=CzjJdDgBkZ~@vWJW0dc1No;>0m6^_Dz9^I6}rV$=j~am>`QZn^9)`*3zeb=;BF?6 z%8R|<9C*_Vi>Md#{eS)Y>HZgAr;R!k6%^7@j6%86s`TJDU!>D5r_!UlU9kk8?{GhS zpU?WX(ZcVH^3=0y@vMKje)nEM{@nRTwjVGKHwC>tXzEw1V=b zpIhfeda5kpzqT+OKsmPfpV1ArMXo+nl{ROW(n?Q1hVE6`xB^$65lZ68QzxS`y%Cp2 zvt;c;rS%pOoq$Kz{otikM@4$uyy}s~w3j@;=~iRh$N9UVrypWM!NR(h}BdrT-EX_DEfX7F9wAhN0Ir@B(@D0X+Zm ztA^(0Fb1@pIU9VwLW&p)TYGG2ZZSPg~dOy7F{7h!BZbNN#0!yvnR?K#D*DNIa6 zhaP>SA&qF&SZE>Rh88OMzo?&ZqT@s!=QfBuJJp|tS9$wDB z0Ov*xbz4Sn!NX|9ci{rwWjYABHgVEOkr>G8yNXE}gx<|z@SK^MNE3A9nct<;<$0Av*Vd!@nd zk#iF7#bseox-896es*Zc_wS6(N-v~GzRTx0{LJTyPmW_4B%O!ORdLDTwJPD#2H`&x zYn0AIDB8*#HD_rzh+)lkmnx*KINqK<9VXfo=N5Dipi9sC`qSArNTs3uw8s9u$ab60 zkVkJIBj8vP=Jnt!e>t3^G$7Up94a44`_vDzd6^#Q&_F%_Z#AR<- zSAJzZwpLc|^z-w`Sf+*fT*LO8o2g~=;+e`4@&tzl26>wXZjF`7y3%b80U8=TSB(m$ zuSN<7c5y1Am0U(z4yZ_H#a;euKjBdQbwhBN#gyVTIU>B?~ z;i4TfH5s~l?O}*WTAw5&^4yH+2tejv`@EwF6cT0`zKV>NUlqS?ffR44mKQyhRu5HS zS3t8*e@12a$7$h{?r%0| z1Yy8=t`nM4O&`^TPpMu#wVIy1|3%u>J(0ftpZ{IzeV^*vDDIOelk;Eoq&>6@dHgpY zrn#SfkVbD%Z51Rb`}%2m^gsQ_bhMxFyubM>l|O;G-yTXUeJFAZv@M)pODB#(tWn4e z0gs-sg&Zmj0spTdAnhxNG>YLTgD5+B zi=sv99C}i$dY=l`QYCrDyHVf{;9ZqrXi&M=1+hcGm2enVeZA{?y3l+v{qoaa22ska z=n^x}R-!C2*}^08Zy;z|G(~EG-ZQoZhKL~H`+zVz!^N8pHl^BKq*b{CJmZf>7uQe-2DJtm5BH&Y6mGF+^S_ z7lI{wb>i$vs(BKIM4o>r=KQlw1V9V~mqm)a9j2|#V9!7pa}3kh<8RSQTaGngXjzz@ z55aL^CLa+ab9ApPl%y9!hPMmvgGLH-OT#iO69iw(S?Yb%8$!1Nb8#u5;mk|r#VYrD z&rhE{6IN;KKdAg`kg#Q>-ZYE0C~RwSKaQ1EVyrcOWqu_JOUi_X@kmw@>0l8-jZF6E zouW{aIBM_L*{*@K0TXS+D0kSp#y}f@)RQdc2&A5Y;sbQuV{Mj>CXA*^9zlU9=K1WNbnYE1!D~!hq*3oSA0Q0)9X4 z=?(_2QlkKEIGDz$!!X$9_7hQ1EVr}r3&HF&txPr9tEjj z<_My24boz&)0aR0Iq_Qsah-Uix7-dHM$-)Nz9tlXM=8&A?Q1Y8tLH0lC}>y&v4ZuQ z3w{`ZVin<_8rti5`rdLF_XUg_&O?EJO_~6+lZI!!8)6T?JTVI*GST zy5M}pJp};o|Ir`+aeDu6|2B*YcJEMeSn2Oi6|Bdzwk71XfAuGE-!z7VMi{+9h{}qB zfT4c!hTZJ-2ET8yhpW7=k@YQLfT>{JMtiAbOCNd_C|GkDbjNvkerK;;P0irL8t`(M zXHK!^TnJN>>5u;SkAg9Go;#C9m+&H$7pEHNdiTADq4c?ilV>{+97pNWKuUv=IN(?3 z+0NA8-4}eOrL8r*RMQAq8VSUAJ=3-Z%Z5GMrBC9o{K_FrNiP&E94e41;(F1=p=|iK zUTTNoj0%Usl>&?faJ@$*D--&Bm%l6IS(tQ_FxKW*uR>cU(k|d&4n=1Cm$%5zr7+Pn z0v!m{qOu~ut&xY%8T`G?5g-Wh`Locw3xgH;ff}RC!&Ho=_UJlbLoKL27`ny7~3Z%lZ zb8$Z+{1+M$ig$Ls{E*?b!n^AW96&%->GwIA!fx@|O!@a7_dGK;_-xmx3=-ZQFJSmw z6&bzudbfR6UQWT#>i~{49=K=O{8gyjclXwUvhI^c0O_?bAq*)%YV`4)?y39ka6X1Q zd!6{>UQ0v$*L#FDQ@mDieXh~hd-4FO6wOuX$RV6CUx7CR$Wq7+?Z_SX?%a(tlWr)Z zX;3v9#Cf_G|8g9JE(-sCZ;FZ$7s87BuOZ#fJ$Hu@E8>B2o@bknAON@EIa&08h6I1l zj62V^@x+1$8m^TKU3264c083GM7C^3uK!*X6GNd5Q9j<9Z<8xMa?kWcD|0H7+@Nkt z=fw-@{_Wezd5_<_M+IF{3gBnoCsIjVaDU&%IK2tYaqsN*5inHOkTyuWTfRL20_Tl8 z!bKBd{&#QOjaneKtur4x>&UaXyckCF)KQf-$|;5l{dKS8hbX6=epZMzU+0d{cT~dDVeg3U%Al%8frD@ra2TJeM8vU-XuP<;d zzJEdQe71be_c-*hiz6B}U-=OR!i{+xOk<=h)R8JojSTQt}D#Ow>*J1jEBU`tHQiWsbx}Uk1h0sK0I%@~0 z-Yb@>BUlL>lp#duqxEG9M>Ln3|=rjO)3QN;M}A) z!ZF*&e2epY%QcQ&{4e&5KdoIQpYn`dtNg0Htv$}wl%4$875i)&fajo5BKRQp$u~U% ziw8PiX|w0z^Oe>2G#!5NjPKx|FaTUR@txKHn0IF{i#TB%hvq<-2gjsNWzX@aWq3peTS4sF=% zrL`H%cJw!Q)6AoM`@G&K2$2j6R#^DNQ4f(6-1Kq?C^B{x&&sMw(jSJ>xy$F%1Nwbd z)Eo%Ih8A*b92gQ<+jxX@fP5IB0QK@~FQ=ga@`Pwp=XJQpqdl7M@g8(rs1 zAc|nxBBV^j9|>t^LudN(&X++LYRhV=EM6ZWKnGaYV!>iq2R;8MeNRH6@OK4L6*#S$ zB?tsQ$Im4ie|hOI)5Cc>GMv6dC^Z#vAyy;9!|AJ!KS_V_dw-R#Kf0bSwqHzlx^BZ* z@ye9JkcrpdBAoYL&)rl&@wFou1l9&8Q_aCVVU@AhU}+zEG#CXJ6<(&MAlL|RhW^WV zOr;fZg9&LI;Qto-Gt^9_*}tpm4@Wz`8uRhzu%?st5kwvZ-sqG=gwPK^q41+^3@PxU zHD88kIC3irhQgx);Tpyrg~7P^>Jb%EnrZIC+67pWBS^fbjYpAz6?4B0@%vbCu9H!<2;|aa?$_(4)CgD)o(6 zWfdsI_xY)5qEzzX^eQoP5L5-4(SEGcD5TOHnN1g7@InZ!LaelBsJkb1oH-i|0Otd3 zG4D~(l8Wl&yw+Sgm(E|g9IcXaP0ex6T7!k{fuH?6J?ESv_wMoIP}~P#+(ztWfned8|ZqRue46#Q-#ER)>zU(sJ_-_ zVSg9&V3qY$!z_C-1}t#?;+uv^tMUs2Dh<*NqoXE2`6L}>FT^>S+>J3p;Z#Ov zU4@5t?!-I9Q9rW{>LLu=GZbfhrM5fK>B zbMd|9<(ETxn>Z9OC5V_%E2gSu$w(u zg)z^J(Jqa4o6}GFsb);a4Pew1Gx5SM0UEiao1?>drC2&3uB&j@A8o);0X}jjc4G1G zO~V#huf|!QB|PX|_HTz?P7RGJ%YLSklYOT$=pJau@T@|if~R`E=2hRjdoN(oy~vb* zpQ&Q#*?G?<#<@bf-H;;Gh$1>TG8`4LYZ{=p<+STUz*7+MTz$97zeD<|ly*9gxJVMJxmzg7No&AEUR6<^^`I_CTxdN94t`OCwlUBXaAM1Yq8 zA9%3*E+QaMD!o5b{@q9K73O`m&l4scD%}dp(h>K@dALT63eL|Fa|3R&7J#0QLq%7b z=#R>)L)fz}MCa*FU=AZaBQxZfMqpZo@5+XIsRCLYe0I4&RZ%jelEv=Iqr=scRBG)iqtzL{4GY zz=Qnc(c|=#)TlaW$2}BO&sqW7^Y=LqF%B;9dlh^@T6zlQMPs;WQqphvk8>9WrB^rp z;UA#4w2*_JP7RNwa_G}x=+-0BH4(@nFx)= zNDHjLjpBnAg;iFJ{NycDIS5C`;J(2c_LQKc0V6xWQvqFmc2Mjzp6-<5ndILxXsw>k zQ*9?OR&GSGTvH{c;9D2rdp#Hq%;}bvTEtpdE7(oGJ^Q5*U=2xOz$^dY&;C3Oz$>4z-^WqH@AKUb^5_>rXLQZQeX8FRKWv0&x^;2R(#NpOqQ3;#Rq9# z;2wq?;aU9fbN4{F4;h4gvH+?$Q`uabcFKyQmf7aQDraR*`mVsw%zwBXG`N%qiOxeuNdw61Gp@mC zMbmP2@jtdQ=BGi_c{?u+`@)%fXpIMzMUu8A-+~`DUatV9wzB;6N?&G0D zq>Qp|`KIr7__;<1*P>A`zosLx*UB>v_g^{I{a2s$9CcpgnsFk&fFtFYE#!^jV?+Ra zS7VzLfQl>MZ3KWd0FYW^2?DDCC$n}F+(1K91X2N72H~blq^qj(2cXhxZ*;vtnXy1% z*Qk&w^oFm`03Z=BKJ+D z<%dIQH$}|W9*w6%E95=?{42bZi&XtyjKiK(@#Ef|O~F}!hL98b?U=#(YOhhfyjF(Y zm_ooSg5ub(M&+Med*N(ugd9c+GfB)O77knJWkR0?Zl-6nNWJg?pSLYLSp5a7~%0X3WNYH(Ye%iIZe_= zM4%R7_5OD@cBYZ3kwD7fso~gH@4x-mwcM2^|Se)SgI3N{*z}U2EZe+>d2bKNah!xW7pe z8gN7*>gh1Wh&b=*$!S9S=x9Nq96k2pf`Z>1R(}@&MK4hvTC>au>WpGQyWiJM@TyrixeDIKHkbKc46(5zLee9vk&3QZ4Q7$ZyXw-lL z$P%dzu5DlOz977=dxfZiy;$R?31vKVl>BJkCDVQS`R9>?X!^(Gg9qvK>#s*W2pN=g zLb@;u6V;~f{3Ngv+$qBKTV8sJ0*kj&DT=nl)X%*}!9xX4qk#0p&%Q(vKMc|J_paZ3 zm|D-CP17iR70?#*LgyZLr%LkuR%qebNbAIfXRG9pPY_8mnI3)k5mx(J+DWyAmH6WC z{~&eu&|(e(zXWbcuY7KVgYo+;dwP&L8P&1^(-}kv9cK+Cz^+WhYlZ11E6~Eop7Q=8 zKAXhokwXA*Z)GSJR+83TzIrv?x_&)8|JKS7H|7w~E>Ryqn%H#lLg0}`1alXs*hjq# z=F?BZ=uUKYrb8!Bq^|2XBKO}Mcq|!-o6`(*SOK8_VHbIqhf^XQ&XSU@i&fSQ0?qm_=>*xcE%>LB;QOT$DzkcTgh>@^g|eU{z_@ePK&jGhYg6}K1yTGH zHmu{JVC+5eD+~U4zJ@@$4|@N_ca0tHh1W^LyhfTP?6@`!gW1T85x&FyQehUpoQp$+ z((Ap?`G|YcQH4#71R9t8dt`{T5Qgh^eMb2BKIIbmnZwWZ5^9W>*}3l;1ys}>&M~Wj z5FfnwkMnXU;Ai3P3Zkyp&$8jV`OAWl)^SnkH;{H1y&p4vJp7aK9 z%!E~OOau+QBhu_S)%_pNJtbOe7KOJVJqJcN?u=1aghF2xL~&sh@mbE%$egI*z`Hc^ zcqZ zVDI7u>T^IZ@&*5%N84Nr^ExzW?5fy{=5R0_y>L3}%^Zh!6z(oedJ zmGTRqjqdRlxW6Xd0Co>yKrkxo=1>179l!iaT7mBllcuo+ygbJ^Qi zOKWCvwvK@seU9Xy7p`)OK0{zBkYpib$h8(At1Z-H5C_ z9Q4n3NJEvQ)=StY-nT=<$6?ZU)eTJFwf$nqa$GB13csG0Lmcos_dt4~yep2#E2SrE zo9H&ABkVQ@nG}|NM8t|~;;MKd{EK7W8~X+i^O=DoJj3gBUif@@sC3vlNTXC(P3tjt zUbyz%;{6HetTZcAl4I_?-e-D^X)-r%-U#L1YdnXF*7~${h}4UZzeop>ZR>GhDO*^d z>1gZm2&Wfco#!m;%0c&~T6MWx>ifyZY4}lJ7^K7K#pgy0N`LZ$7cc@optlyZ*lM6b9p~J3f z(#zN@p6O7B(wOFcnhxRK)^mPQu$u3sKkmEpkWLvnknu|8HHYa9rcj8F>WS6>aIVTP z*&I#FHJvqoM%Jb~5>Zg{DCh0oc>YGP?`y7!=YA*u$wvTuw+4W13Jg^tV1*?HVZ!iy zH^;GtARHDzwHA7rP6agiF-4+{3I5x_Rgew~=|BlWx zv>++RxxMK6LmHVNP8TcUoa^-MjC-8;GqCu}FP`CGN4Mo9PW3TZH0X zAdF^YJUmh6^-oUXtzgQAq`D_Ev}XY8GeXO@H>AQ;NIrc$81)#Q-WVE5>Z(&gXI9cuA;mkRgO|_`?e|e zX@fIarM2J6gC{VUd?-*^C4?TMO~GFB+Q{S6V`Yml;lMd6j2dxa-kJ)pXPDsm8j4nC z_?*4pTO$0KnvsXiF}#Puy-^t|{I;soxHFA$z!7N}{3{_`K)7-!OxUY@^o7SkAyi_u z@WOMikZw4vZCbKnQ4vFCtt6~a<+UpRbq$0FgL|2`N#);k0KL}|NB3ASy~@NSA^khR zgKM+iz$!%ug;m4;Er=%msQkxZtz$!@q$FS<;Ce%$O&{1m*qj@nh#o}&XSu%=VQLiR$bQ+oMN{y5fDi(n@+>iNlk zPDPy2Fv8Wvm#)N`w|JHea~#9uDU=pl2uV+u`1{Pu_pkl<$FVjUU@%PJdx`lr5aD3xyao*SyBvHrZ`P2voB!^APbH_@$#JX?L3R%~ zses^ng`*ji_+1L7tXE-Y6oZB-7Pdo_cY0RRh#hD{2|}g9h>YH6*d=0$Iqv6k-@S~G zboz}qFm6Dv;Su5@%ppL{_EZY!(isJx84N#d(B1(;nfD?bD|^{-#ng_`k>OO&`Dmz- zcW9ixgK@;dMByl`VNkyVg&S; z&!*?pr_uOTR&p?Hpb%AT?ha366W+WK!g;@EAsnduX9f;wS2#;}mN@NxsQ7s98j9rm z!iq2*Q4f5tT%e&ynDKnvZzDIX0pMOLySSGb{A(!k9{0r0jT}*da<80=1)N*So7V`C z8B9`rX{x?N^bj~w$-FE0ktTcg3e>iwJ9gq^8i1~t|EvMqeHLb1hu2(!UT*=1(i-W@ zAlDv187Ks|q*W@S;@LL5V3{bQ{lGv?`9aR(NP6(ujd1q#kuqvzsdC?iOSDJBD4=oI zvn#EGz7P^kVV$&x_I7)KvwrCHEO6%9b|G8o9h?L&1RAfbX2jc5co$l1 zDk1`P7xLOF`&dde>mgub>fXI{4&LdSrPr`honqk38j}wZ*Yw( zD5UeY{qPV|`^Jg7tN_M$?`G}L@lob|40%k0tvI;^zj*xz zKL`cavlBm_U|==k%JyjTHD$r4Pe({uBW0AXP8-Obrd-TYQ{~#p3v`k}&H|42k!q@( zRYZ3cX{e4n#~bgyi4nJqGeYiI%qx1rU1lgcME!*#-aEHUv>-I@AoBcl*8tZ8_dM5g zR_}0ZdH*tU)&K)?o+Q_qBZzdYQJ(RjZ!;n8E24fz!$0M zB9D@{O1p$1;lj^cw|g(%#(UUjhkvX5pJUISQ%mg9t5>7;)563|bRiJ0Jh$Lsafe4l zmmPS!_@&X*`D=i2gwc}sxYvH}J~*Tg8qI}O-zPpA{%*aBY>0pU*gn*`if0< zR=#yVG9_Go;oi7b4NvZeLWb|K28b;|tq~xs+X)~`Q3}N!I-c=@{Cp{B3oIJ}DZP^J z3D?p{-s*muo7UnQz0Nfl+5BC00f2FR z_gw&%ACE*Xu^Z(97`E@w+ai!F36@axuRUIL;7=z1i`(^v)082_aYD$dtA{TKXU;WiVTFwr3Y?afoFI1CsUw z002M$NklN<6>K8OpuT%?NtzRpRJ1QdbCtoWqx~gJ5mVrXwBde z6WB9FE(i=t-S7V|{{vn^EWSH)sRrwodFh`Ie4bvbe=U99{dp+i3aBEc#ZYn($j&+x zi@y8m%IPb39Vep#ydnFZoka8MnQLimVLUZfH4;9QSL(I;`%a5-{9ix&4?!R*V8jZ+ zi`xrP7%*dU5)VgxO?|2=sY-*RgIKXQ(ieBWNEgpt4A1j>&F`h5)#3EYu~*ZRNeaP% zSVyXlq=(%PBVSGhp|kmPdOY|fLVSYALNxyH`#(xOgy5|{py(OJ1Z(ghJRQml|F*-6 zwjor^f4+&en(+2I6mpsC4t+JEI1zB?85KhCT1*O1&N=56*;}Irju4C2VLm|kyUX^y0f1?r>q>}tp+nzxsSYFzE==Z0MCXVd(#^9C_e6?N-~Ow?@}Ok2-6xeYA8;p!DSR>eizX# z3bgynio-DCHJQcUds^|PYqhmbg~HJ~40z89g)w2YC5I7|@jh5I`WrD^z=zoftIZgSZ7q=&#j|NYyk5ZYh`bwd=Ff#($pGB#law~);O=Q8#L!R_l? zSjJldj%6mjFt9b4fy(DJ^PGc-kNxJuboQNh!1s-yO)^}CPic&2ZM^~KHI87bfnth~ z)ne|~*tN)dOIW|5lbhf~FXv=s=1Phm-A5_45TOP<=d{S)o<;Z@!hqI#;zaD11#e`2 z=FchADo8BczMYPqJsas#L%@LZsK+Q|w}A84u0dOu(>&CY%BZgnJZ`t-xli=-krnwS6>Z*$Tg_6EBxr4tz%DnzWg!_ z8C^t%RPf$al-V`*c^#Pe0mhRhj4zWsa^H28>uqFC$AZyZJ#pT2iL zRiC9J0{30|;d?|U+{c(jRo}|Pgv*u%zJ>A+N`&P>U}snhr00Hj;J3JJuC)raRlz;? zJ^Ki&9nX7F^LIcep!J3cXFSYxN++e+;$jFuFL+XRj{<@??@u;7XBE;+krNlZ*Zp3{ zsJWYhw)mjZxofmz!=T=N@p2l!aVLzNDtsy$@`y~p%ATA3tH9%)`@D#>gIRi?%C5!% zg*kbg_sg4A=!FG&it}(d@3@vV`(0)L&~qvOR7sa^b#!**QvhDP+-v>*+rtP6l|nffKY2T)I(iIh4KUZ;8fXjHYbkw~Nf0RSwJYL|h{43@P zZFa4Gr@_eeE1+u}G5SEmfUubj=ajA4z4Tq4u|po``~2H;)XOP8ILB+ z-h>a+K~z2>VuNS82G=i4I~U={eTh8=CLHn-&roB;@t4n~*?knPrLdYUqDOE%=nUwB zMy_yOHFR~A>zteGaz8oh5ZtryaNn0$PHT~ z!|55cczJv#O%PUo<@Cig@Mr*9QxS#_CLRWM3xH}2623NzDH_T-l;SKZhR0bbaTEG| znCP6noOwMo%stpe*S86hQUmFvpk|G}RJ22&^W|L#{` z2EWp{?B1?I!`}SEKTHEu=HCWR*Oje-rAFxFH1z$_g-hw?KYx%;|M`#8o-3!)=sM{` z8yLKqe|5=$bh5QA-Tm~F)Oz7U7!wwt7kF@>`*{O~72zA0_d#g$tzZ8d&pfG5&~BsP z3gNvP+nay|_uN9g(lKGof`ePow*?IUJHH)FqZk=%*GoJvvMf{ksDNhuf|9XJ>2OZOUJ64(l(I?(in&DjM@mm zitwY6NE#sT){r9|P(gIP4(aeH`1FjZ(b4Hi6l8P`S~)AD2;0rcm>6MN+an*aJ8$Q?1n{&;PP8{#V3Aw^G z4HTPPy#0uf;~H?hnVJyDS+#Yc(AIO_GxvMaUSvQG(?j>@N|wuofnb#uy5-M{-~m;E zQ`RH0_LlTqBcU|Gb(BIYjYzSkgzLFNG>JS?xx;zekwAG>$Dp#d@{y^-Cr;p?Kw&ox zOd2U2G028||Dbu^BMj99m;+`ny=;@bFv{Um*V}M;8qyt{($oPb{ z&wN+#W}Y90SN2c(EnTo}x@*X>2k|ZpTN*cmFG3HUyVvf67Gyk7N0yEV_rm%o4pVTw z*15S3jrg{a|4zFA?AQh1r59ZQVj92u|Cjh{qCy`2gtz

    *0Hkh0QRtD{w3Q&N0386HiKqheM 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

    DmO|Lm1n(PohwFKxgUJj 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 z

    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

  2. 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

    `7_A{^7l_M`^$gM#tL@xoHf&LK^qgRdLD% zQ4VQ%6WnmUdkDKwh_YW-1`Sg;U)vN)^J!{{vD88|($wk#(y*IQ=J!^q#pnC-7Ux&r z)DRjk(PXU;XGbw<>Kxy=hZDnrs|+KHtOFFl98xQZk%Z9~y+nw!4MW|7lNaeKyMPmv zR>1q5Cu~m)X-8U;=a?ocY{hHwZ5M-mlYP?=vY&~y<_c@;|EIO=9jYb_xsnK??nKr#0`dH&Ru_h20*?hGRMcrDz=y*c;U*SGRo~m&+$g6dn z>G<^6*U5$1P)|e6nSIWQZzXEFFcAvLAXznSud^fk=wJNv@a)C2sH|d^j z4dZCzjAIk|^}h`}1!N=fY#rR|j~+$CNV;=hi%{O& zV`KS5w@Yer{Rcx7uUb@33R?4$QH#QBt8D|(@=5hOe_&G zdqhWv8F72;`MtaMV#?tm%5D*SMp;qJTt|C3j*Q5IhVQkj*J1>Bbcm*QXNhJrhq6+; z-8aS~N9|rd)7u|*UeFhzGMkbac?0#??)ic#<~%E(9vpTrFQn$&=&QBoi#Wif|5^+J zd4=?+;-iApP9$67+`4s*-YT3B?v;@u)B001Ubv=V7J*qZW(+hoH==lvx{2X0-b)km zreqMSWXUUho;c|`}W`jxcmk)k{F{YgBk@ZIngj)x31|BM># zQufh|(E@nA2Gr2QhZt(bZ%Pk;LbTqJfKf7tlvmxCuY@P}zYHzNQ{}VtCC)l3_+`UruYW_GE&dL+4-PJK8hjC?y^-#3ykyfkWko`Fw|f4A6Yd0m>n8BW?mYam<5>`4AU61OodT+cw zLe-?EY%d1)GTlenr>+zOD#)G$8{upKX%6S7{KR3CL^BYy&6E}5!uj(w)0G}{2sn=C zmVJ@UaCdEZSiVsQ06N4s?*ORYqyC=Fv;m#K6%hoO8)2iDxT&mMz^LTPm_=G^Dc$^J z9Qj)U5pZcpWTsQ4UIEshsDS8+G3p@E_+!Hzg}zFJo){6$W`81<5rJ+tMB;Ii?M|JH zIEhFkG5z1~7-8^!){c3k%m@(+m2=ZkT8X4PH@$8m_a4G98LkqZhQ11eFmS_Nt7|s0 zZ<>qucRi-lcpsa~RHGbDfv6&~$d|maDkTc%v~HW<=*X}RH;twy&bNjzO-+$OnX)C~ zshBAM^(4MMWE{d?BR{(b*_tY0q4DlLbQCyeuXQhEZfRsPnK!9e5`7{f_s#v5IJ}3% zdMeYzFx}}oXMVj-9IMP25&UT%PYixVxde}Wx8dg}} z4nO&=r2PQ5rP*u-fI>LS1hQ*#zh$=0E#Z!ai!cyg3CCT#499i225~{=@0{I#@!n|F zYiiZg@Sf2@Q&}A5ca}oq2e;`6ekMHnKmRUF*%*k_@3%)8&Ej-ch|lhk4jkbpOr7U@ z7-{0AbJD5yHa#WfLgAX`EVC58Dpu00H0hesa8HH3>-GL#qoDGcHJtriOKtH65vkpg z<&f7wDnCt*u);&mg-oc1Q4cOaGv7U-U~POp?w4y=CK{urx=$0KWgKDFxSH_ zA5&@4`A~urNaf$isY1q-%bT}vMnmDvjrik40i^}dZ9XafhZu1UC~NM~E)iab-g~=; zdu-zo#=`~%_VClEp%UY)41+}HqkP(iVA8(Iff)jQI+mD=^zU9d&k4Nc9`{vHTNj48 z?g-ev^U+6P4FOig@sRyPy_~gej{r)(+B->oor-Ded*I+I^iYcuu?OBqWgo@jE*S^n zt^56qy7s&9h2GCT3)MW|=(NYb%4f`euz8Vb+lo`)Ys<99xlDlb6OZVaPh>H_ zx+J_BCF7yBi#3YxK|my`Z*K4+aXhq%i%)=uFJ zkT&cl?w+ZXwgaOpKmJb0N6-uR1@41}7JH7Az)$7(^YBhfjHZFx9*R&c(Q7ly?7yG` z^w}`SD$!_ib8C&098QOu*RF>b82&kjWFqC{1~a^j3|mjQ^x|clr=>GG&fTj^H*Q9n z--JH9pzB$#?WXyWj)LBQ_wPb=`&o_xT#Wn%J0==p*6)t=;wV7Q5p|gA>5lljE!( z9PXq~fl8l-cvSv?i9^S@&$SPMUHJWN13Vi$`F=c_$qRErxNzx$f5m&MfT~bsz?;!w zPKrPYf7{?T8Y>@_zU9M-PxG~Ze{f%UgmkB|Eq`3HDJa=B>JUb4(~u8}fAT)xSHTlT z-apAdk2XvOyu4lcnrPi9w)60P@1dMj2FPPmmV|3^-OgYA#qYFtv`4s%afDm^jQ!U+ zP(fo@QwclsbxZEN18f1lVK&bOFsvYpWAoXwP>)Pl1D5hGGdna2jQFoZ z?;5-EiClFmV5Eb^*BXV=r}D>U%JKsQR$N;xI@%mOVUGJ)FKp06hlXc-tDuVti|n_( zWo)i_2bwF~!J&l%`fwY$fD@?UT6fr|nQ(1;Ygi@Yuxy`lJu>lf&^I<#vw@+CIvOad zkI~pRmSrOUH2&++KirSPiXs9F;PNbd0$MuH2?=$`kR^=5op~};F|@@yaVX*fIOW&3Ogzwyq zj_93yqSMsbmjau+IEx0kNBcY1kjH1(z>lO@Au(e7d3p5Qt4q;}WS>!AN{en!S3 z&UPI7&L!zK>Pr4C&42L02Qh0!xavR=--MxSc1X+WSjtG(=XcEP*~vo&7vRt&KvHpn zawPcFhaY|zBhDJ|?w9LwxL@)z=}8&vzIrcVEPT99J&oYOx0 zx%lLe*XU^VUd~;5SEnc|Mc2lTvcH-oKkAFF@!GYk1U&j8UaC_@*t5?%D0I*cBD>vp zpXV_9wzv0ne4czkog(cQmqnPwYkk2uMbEB0cqyQYWiqZ+BVYP9o7#~KW}W&*^u5M4 z>FhBuk$A4~)+VwpUpNT|8_(OIP#aN$TwdWmsn<#i21JFSHk!EVklzbWbrIKTnSs1w zY-}7||8%tV5?#jMEXBZsM*s>>`INHNtaI%>hdP_I?S31)Fxx`;XgP!P$?7!OQ#^8* z%Qu+;fYWh1x8i2!|AMB8@9diy3pBXOMS(Fj)Qw3@Nl(c-%1as=)gqK6snfPryG$;mcs?iL8R5ZL!=4MT#o9Huj4mf0HcBi!&hR=~P8I_3XiXfQE ztk>u*axFRxbV~H~5jkYY07NVa+aa7(2CVbtc5%og*C8041a`wLK!^>Y1UiI`%*+N_ z&cXXga4OC+v9vGFIXO9;kHfVjFRRaRy)w7-x%YM5mJ)bh3GQv-@-ntwX&3+hL2=(vWqz>#}WHdS8r3#SE>*_EzoWG44op(O-$U#xxqYL)|0=wF} zI1B@sMq683OgWTM3pWYcR4LOLg^^5Excixm%AsNH8ib#p30vtwJoXy*RijU)mhjg5 z<`zt`?L0Kbgl(k9W84uQ3PIQIkT(2I5-3Tir|0M`?nhuuV?cW(Um1<( zR0P&XhjFuRhWcw4!*K6Qv=c0SU^-1YzW2+Zbf^pl8nmrqNbh;<>%-ng8Kh7C=JPN!tkfbUa<{s{_rC1yFA1FKYgw}6lYFh0HH*Z!Er#Q zgJn7PFUg_jgr5J<-5iRD{+=W=As4*YAQHYtJB6E0I_bo<>Xdo;BI^+HI)|y!8XW%U z+-%OY#Ps^qnf*-jnK$?(%yd@S6s)|Cj_)|W%u?7wDP5hSUU?HGtdKoG*m(xEIN(0K zc=kMc+F$+pSJ4P}UyU$}zs^e~K-@0^&yDh~QA_RZDtM2RVgCMu zFooh>gd(fq5clKhvzVSKy&b}zYCBEirCB8ODxLq~)6YUFhU8h`t~_f%DSY+E&ttEE zhO5`ZF!Lx!8JAAwFFLn+GU&u!?9!~BIEHt@6a1ZT-2D=$*$5F&pyU5(@3@RyRsz>k73fV)^OE$S3X3g ziR+Y&iJ$1KvtNjKDNRTNKErEt7Ko2FfU~!SGJc?MAU+~B_49>w^g2%xAND;BY3c3e zEgWdzt_}u`W@$>}-{Eu2s4{Keh<-ZD-Op6yjMQiKj#`{U^b;VM;E2uTP^6_99TvVe zY9$}8#7Gx69pZ;;GWxI5t+5yzVBtuK0}|1A*U4atytVX}|Jb8pbbOReA$=A)E}-Np zhlX=&7>@-+mhJm-a z>mrW6m%smg?CGH#G|1pOhB20#;UjtMRU ztFlRBYkd$MYn{fMWNcY}wY-ns(?Xgt4lm1%RDjiarpYw$dG^du{w#sFhupIQ!%zJ| zobq#FCqFmUUwLIY$K^|xBi^|u*}VpU;FdILR%tG>ru|%3n4rPiD#qUi>&-39rX|~p z=fTf^MwB)aOMMohb5A7c{og2ISU4_I;B<`gMgmg@I}v^hzxX`%b19-Z?9>pYEcCQ- zpLPz9Q}NLqJm$}nG|UK)c5l3MBTUZCAkqwkw2%RW6a1Gnoa6iVZrzD>^2%)GfqI1c zfx4(e-A>+XR9v0R-^1*&!!^I18R_e&Yw?-R4zE|w@qW^pJSD-&>rT-HUI*C+AAcMM z=;FV$z7iHGo!cOjYYQAK&7+?IdmIP2*4WcU^V(-PGw3&i^P?I^zlM!_p&qEt=YFa8 z%bVpH{4VA*7-{B@+ku#{w=?kCuj((8##AJa}UQao;wpZsy#Ud z{`&nNh2ekvENqkcvIajIATzCkbx(8u5_n=E`>o2X!Dv~U{p(NSAoobV5sq^G)~yd> zP(@wZxd|KfS>fzH_(qs=LFC0QJ=Ve&~=nc~AGk=V(wnGUyEHMY!OgWdYTq_C%ZXBC_5T70f+ zO>+|IWUd+jdaWd)Cdw9!YDpkAO;QQUz(`bDT(bzQC(7~#M-j?{%>o^sG;jt4_8L8r zG7uFEk=68nnJ!?3A%NH*lFU-XGE*X^p|EySe^NJ0g+h!@vM-To@Qe;pH}_D49O*s( zc3pZKRsIt*_udLv)7?{NTCbCcgpZL!KNJ2Ux=lM)sQa@4-0J#js47BnB8u%1bs6wN zX6rtylv!rr-^svt4l*q7qcQE@5@}Jyy$#MV+1@FCm;JtpoL|qPJ zBK9S-8${tT_vXz!dCvcM^PC+g0C+>Y(iFccfG+xf@D9My7Jn2kVeZQS!(tBfIcp_@ zat@hX*D%uqfc_b;H3R%RuJ#fNxdyX9;oshm_mIwfW|@Kv#pjjgR0Lfg|Ni#+B}_a{ zjQ{-WzZKvz6^GyTx!q?g)@M+yJg2IJ9`v7thEzwahJV65+-#Z0Hqik&9n?0!|si%gu)O7jVGcYQU?_-vj#*Wc%J-JGxM z;hs5X@0sjd7R-Nn2EfwZL*M#or0+$@Z>bH{%@ke28&!ulWn-9dOX%h%5e{WkM83f2 zvGHsa4tl8=_h0Xi488N_wNTiB*APHkhC(7hSf9VFCE~Lg0dZUmU!W}_@!#R%8BrW4 z{|;%=dmK|VFb9K#J&Lc?r|?1z#5x!X;S=JnGim@EgDC&GA+%qkLj#^3&ym%o4X3Z} z>mUr8(DbjK#re4h$=dEx?CLsg0XJ6G!VOXzj21}RA2nX<3R@R|DCqx~@X#HKbeXP_ z0JCnM&B9xH23${#GwzFP{I6+6FTP+)VXg3Vk4y(}q$#L*MhyG;0in^Xk@RVGXFqSP zfgIM>Gn|Lwus@9uq8hiw46Vj}n|nU`;)}>My{S|5#OiacVY9J{}B56O*A9ez?vxj6B$b zR~JKbu3u4iDxME%%HnDAIC;5Y`y+T%jVS2u@28VTX&C+JBf5OFghA%shi9>wXPJQa z6jB*_kFfs|+Le~pkUGLzti!u%2*I{XH52khrOWco^BN1hk~AWtx@#Et;wliODw%oG|p#~N<+sOb%of5#MzKYM7T-TTW*?FN@|1|qdH?RcyWgY;IB&f&i2=;B5mO90JEAoR>6g1cLLDUui6m?v*Jj^eP>Co-{BR)sWm*SsgJ7 z^U@d~(A9t-UQnTTUy?KH-x~Im_Zku2o_T5Q8|+2(o#8>wozDdh+O1_{)d@ zaGcQEFNXJ@0PtTKCfhpkP!WP|u}=-gJNr8r3XnfU9;y60&azI!au)al8oPDxUZjOO z&fnulk1!_C4Fnov<6`l@QfO^?evX1}oEVroqQGBc*coTH5zLWeof3-Fn#OXAs`De`!y&JQdM|vg40^FRU@i3R za~FZrRMgU*dtRGGA>SbyvJxJ)1fI}1FF%quc+Sc>4pQ@%S#D1RB< zpJwOirb59wiY{)>TpEv6{;yHnU=_O3FfukUimYyo##hj7j3QW^8Dn-N_uZgXcukt^iSGrWTx<&~Gi(lYB%5Fa^?RiF$kzfjCn3&LW zAualElZ$AF5>%O`{30Apwla`|+JIxcmz6-Jp!YhWj`Cy(o&o#IK(#Ly|ODwZSdM+49{dT z(xrsNpYGDxqL*4PJ>hF)7ln|b0lt9!t$_ddtc9%2F847NMSNcZubigt$k{4w${TS| zt>J|D%Ro$bGP+lcq+D_RU3Z_u`8xc!`{Q}=$Gy-ZE%2vn@qLWGu7l66G8Zax zsq=t?4h8ml4~2+{hI1%4yqBNzeq!uI?kD&3bMn$;fBoC%N@TILq65tROq?__8NV|# zbD0w2JY84slgM+gqa)BW;QQ`{*OZ@0A9~@vkK+odG2UNgSQ^xDtIV`ryB&BO(w_G; ztll&N^*0R!@_W;ZW$=FAx793|jJuXbQ%k$9hx4~f8be5w)bfXQ8JU~b| zTtKT&S|I8QhurG;DlBfi3z*aZkT~5m1+$h>bL|aZ6eOwaDa^gU1nL1-5iNvhWF~H+ zg2C{RWcWP^Q9^Y-8Xh7TKqw@`17muC^YGy5(eYZQ7x;WCi$0@F%(?iQ)~9LO)Fngj zSt`Q*9+q=cY+&%@ywmccMD88eKE zxjR1vf=tGFN!SiQqae_t=AHc}r`_oPFQVdr#--kT#N$Fgrgl$Whq%ZyBf8bk6PVmsWA_qt(;Bcg!J(it!Y9 zb_J#~>}|rFH>h46stegCj8kvk3ZMV(zlXgElx{qb_7^rGv+PX{{H0vJ#CL9?ylSlV zS>>(UC>K`q)>F6zz;1R;*zx$PETxd+lfF?A2?p_?x51MlU5HEy3 z8-X$L$>&sm=4@c-yMT^imJx`I61k8=ZHn>&x@F*rU;gS#LZ?gPIVpe^rQz5$)71l zsBMT=a)6OWlnXuNdXiSi)4V`QmCj$V?#t|rplBI-c}Onp7hil%-H->7*Y>dP)$qtU z?y-T)9O0gaC|235gRR?^*oO=-EwZ*|k;4HVj_nLYbn%Abr?E&-YwoUspj_;kFo`-tx<; z%{ehz!1pvzXs}mK#KMH^li&4PVh81`kqi!%LC;n)55I3Tf)N1@&q)M^-0u?OP=kl( zHflf_CO?t?`ESpy1~}&^y^2TVvp%!uNBQm=Cu`+({ER%!*EMYDfvrX%+gd^X!=_Tb z7*ybGwNyLb*uIPgiL#i8Df3}W84@d1P#|!(fRN}m_ysf|KOOo%{@<`(1j!@s;@Y$C z<*b7#E^!^1CrP|0@;#A%O@HtK@+CVK1uI1s+6r(7W5$_^HR%C)$dXo!ZY8{@2W;t2 zbi(LJ#pn!Man`5W!|b1)ev{g;uqdrjrwHS38FMPe=%>tCM|tmi@4Ybe$tM_NX&J~l zaDA>^Av$0M`3w&<5<#z>SYUR1oHQc(eq%6O=ig1tVV%A0gg&O>RTEsVjORLqZ-`$s z`nVq#$i_1~?HavQydQu4m_wm6*Y4X;9t~P(c|B0r;E8+Y8{aZf&ti3Rz-&(jLs$16j>a*#CX@hsY6em zM=!a1oY0K&bBehupOux$Xz@d$@OvH{D#qe8zv~cNxrPZ=N^p_<)4BVjEb@%`i!vxvR&zV+!_~XD;(8ttp?5gXxq)8AG19s8 z^8Dk!ggW+mPfUXWs{jQ~qlQj3<;^Z24M-pA;dRe^BYdHL+Zl&_? z@O{@Q4t}+@rDD4EN3 z061INiv2TBc|Zv<8E%wJ%>$BzkI9T&j9!?y1g7HdqPVdVum{t=l1ZUEuaziXR$opI zjzsAY1hxSLl8`=M^PotadjAE!{_Xel%3mHZ+iV&B{4ZX7zvl*mm*P;UOLP)(VyN(a zqXT4UZny`^`^2JEd@f0AFtkXfBuGg{2c8iXCzXFK>^`%~zXwR~j_)sWxP2b07E2g1 z^+gnObJz?o^6(jItU@4xYe{!)^gh1!+G`NnrR6WN)cKy)O2f@O05Td0*&HCF2dr=4 ze#zLZ)!^DBf+zVc(Yj}@U-EC)L2!1trk9}1Yd8l0R6+m%KmbWZK~(&Vqr94yUJKJ9 zj}XeLLc%wfQJ|Q!Ow+ydcOsPhyw7GNfv+2eZrGpe>^!u*`V5X_UjAG9a{el*0>_Qf z+1T#p&d=VZ_jj!)69z++3G*lU2}@fY1$t^CJq-Qs4=5OYgz|9^QU1@l&dT^$Ckni)zC`oq{(aBSdWPID0f)5fXS}Z8_iy(?P~+<{zlw9z zhTz>8nPT0^Lq9s;IjTbHjoV?FmR1cE5R2k?7hH~{op_F2`+90q zggU@n2Ev<`dKMxq1(+%ne4cF>cf-T}aO3rR;qk|xM(@ws^d)WE7V5K)J`UN<0ASW| z{>uRt^AgC&%gP8H9iASc(*Th?W0yv%Z0OH*Hd^I^_CO6cdm%-DH{pm4)pe22x%ZxT z6+WYX+*A3c=hrhPs7m%%&t>$IlBS@7aEP*&L3aZf6CU}O;qJqGL>F8tH^=7~VK5Sz z-yQa-W=}E16V}iCal?w#B{hSvEb-%%g{B0VA7y1_44Ug;zx3 zh|;IEf8wA1iQID(T&`J8e&r(GfA?Q2zXE)ebG(C+xQAkM`@#J%@%R4?rJ+6SK7Ss& z6GVlR>&L=U@cwhwVhckln}PD36C)%pI8QrxAA0+)NB(DY)GWe0jnaGlM?VTH_R(Sur7SsR}J`7fN~o3UkAHuPD^eNQ;so6PHiXT1O5wJ`R47%zN1T?}qS z@M7+vXJPxZ&*EBSvi6>L4aD~!KI9xw4}vru&w3%}_K*<2Gxl@UeS#me8x#s7{1>l# zFFZ1{l=QU9T$B^4e6P}lgIWZI1w|CrTMOgdV-v&KifavMuya6hF=;WJDHUElCMgt% z4ln41k%ovBON1<c#7fN4S10p(4sA&Pde#JK@}T6q zNs57$oAWX9D0h_A(HqH;NVTV8x}I`dzAG?Q$#Tx}D)-j;B|~LJL#!zbuCw<_3K04k zd5Us4;dQRHU_FtQ{&sGj8NV;jbR_)Ob1T1BCL|a|Ly6~DeBjykxs6b;O`_jV^31)C z`(j!~A}5p?u5AnL8aIjb5h%}Mbd5@A-chLP!|OOP8J1A4AO45`JsQ(oYw?IJ{r2H0 zTh5WQ#l%A!=ho*N92`U$ER7y1jaOnBd14Vpu|u9$uCTpIinqTKdY)q7vwCq z5>-(RJuH05b>K^7Ri;o8eof7Z{X+^cay_w!4xZEU%T6hF?750l$H#mD3O9Q)A;m_D_=W6!?+aJ0& z?uGPn!p{_Esfn{C?!4O7Lnkk4bQVG$Eb2Ueb~K zC;h3A`nvR%j077?lYZ9syq^0l-Ff~zAAT;uX31~ya1n;vDU6FvckhI**YAg=^S#jb z1L^}1K_~xSrRCw#Dxvf>$RiDjuM}kOuPjhWHNr-G;J=-RXIDdm_jKMqyU!CDRykTH&C^Ap6C?OA^?~G((yPP$@W=Z}uRg0k(uZ{GdtTe?I;62= zI2UHA+{zn-3Mu3a5FekJ@=9_Tagf-j`GvGK9!$aIgSIq&Od9r9*d73;Bf zAB`+fNArIgPTf!U&AFL3&r0(=LD zS7JbRe)3^!vbpX?Ex67a5!@FZ?VI6Q)EMGgy5})kfwjDM_g<`jq5;ZhaA;U@cum*c z^QTcl{OON|YjK^!!px_Yc=x`m@h=eoncvx6w#d`XX4AB4NK7&}Jy%+Dk~#qD)yZM^ z@S8WOqJODeXJ9~R45?HqGCRSk2T{S~0aWpl5cIZt4G*V^m$pi1D*h=N?04ic`l#@0!qULOrwVTOg?@b?)~Z)k!d-HZ1QmLz&9>H0Zufr5W~rZg@k-}f5QoUhB!J$DH`c;2Kp8Nd4+&m4Q`@Vxt3 zpVuFU_m91x;msF>!Dq3?cORgfuCEZ0kq6j%LJ9!kiqK6niZJ!p*eBMa3_wR1=^>!% zXm~N)d3c}DL@MEPFV}x^VUl>{iqPEI9ySI?L*@=v)%0GRTQTQjkC5;Z3K449xqbZ( z#Rp$RI(6Tqr(-$}bl$o~j^4AdHO)Dp@RPZ_0(AGa_G&7E)@OqQ)DSEQHROnA<0y&ulG3p zYfqxcOQ#v|1#@;`o*s(W`s>;I@5kQGh4A{9gF`V#USTdkKVbcipf7>QIy|HH-Pbuc zbQBpQ`iJK`!??2#f47*AEslm!EOU#CVz}{}@4go%Uyg^Jg?0LSldmj|u~+inSd|=l zhUvsYYVL{MDGYOb@%!JCCPc0u^R?I?mdWtW-~MfEljwR`ccnxHXNb^e_&wFN!oub} z1<_hU2THa1_gP%e8VPF{51P478ih0m#oe>nNC@N{YkY=m$p@?m9-d$*=)st<1JAcN zdPkw$Yq~g&l!p-HeetTAi1aVz0KhvU526i9)KQYzpwumO7}@P+`(fs&fGnl zujF4d3ZfKK_Tyiz_S0Lkk+d`68ki2@`@92*^r@5u*~&nIEJiG1<% z@>l1ix80#E@kgHKZ;i_dpA*>oZ1QXOLwO`{^mEdv^Yi)TbIJ2|^ieGzqvI}XAdkBM z2T2R^ltd=^TLsYhc`eVe&*nYkEzM2M-?aOUlk{A(Kbbj17gC^3<#HcBx4p3)jiB-z zuc3j&(fgAJA)~7mR)EJB8P-7!m~qbTGBPHU`zeo#p~rpZaqd1bKWR_CD6csZ@ba9t z#necpb7J$!lW@d$(Ey@+ckksvd8}pTE1oa5+2mT=Jl*3bY;1B&cHl}!nW$?|9fBW0; zKK#JX?DD+~)^`;}!Mt4Q!8MmoZr&!poaZS+#`$b2J?`m<(KM`!ZA~wbVGTU1`#$s^ z|DUir3{JwBTS|J_QJVI;%?-%gF+BVyvAX**QH%~dFxc|XJ#Ox3jmFr+Z47n2DMIHl z43O$*i#h4T^e%ao^dfyqJFbEIE01Uq>hKkFQuLc)YN-)mv%a|)8SQ0IucJr`i#EZXT-5;)vm zS{ueNE=$kKb$`2Vo>$l0HTD_3zdtH(zUH~{brk)JfUa@JYW+Tw&!IEXAy3qc?>t)B>s>yt zjuUwuY~0T#bMlOf^VLO+ewf0T<@cqDVj@cn%U7m4{El<)#NlAEa-ZFMx3{-5zX~v< zvSNd^E{Ks@muDa&D$CYQlSUFc_IvUj>#CU+pk89siV+3sh!#53U};S@I{_qJ3v^l< zmFNB{lcY(X%R++cdY%cNdk6WbQNVk+rtZJL9j>EmE8Q5W?%r9f-TiECY2xhuOIny= z{yw+(I+=slPh?e$UT2RkYD?m^zl;9>11$pBby);ZIs6^`SOdTiy2Nr$;8FAdsc=hZ zhUEC~=v_Bdp9MDOOJI=An3EDg(Qv{Oh*zPYU&#+PY_Hy0m!Qjy7;WNM3P!qk?e&2#WhW+W)k6t(x zeGab&SHP-Q!o#id?})juuLv=|z<)e^w(GKhk?ZLpxHL3e0)IbeZlMN>8#gb*eBwUv zy7TNnk#en7t_;)d!6KjB&mNVA#l%)!SjwzJ;C!`U8RF|Rx=zkBMn>>=GRj-90+;3! zqFfsqQSc^4#v-_Ij>oKpmN(a}oNIch8k?KqTAS9Pa%efFI54yp&;PM>P=cbciee6LIHV|9 zMF;1h3~+pofhC*#e^Lp?hex7NQD8W?QVQ&3vM*5qJ)j-mc}|R8F-*PdD&F-h>Tu*x zWQC%nQ-66HL&IGI!+)>d>Bz7*dQkF`&$eVK#lFM2kdz)t4Rf2jq&yL&kxg5`lUZm7kGmnO5Ahmr z(wqI1_x7jf@wm~GnXU%~dC(kt;NFxI?Xa>G*{Q&$pTta zVpKdk09ejzA6jeyn9NO0p*88TJRnrOC4!(8!0RzIvHRhZP*3sA36za4zBe*37x9GLUiflzl1In^F8KdQ78Aj8W5u37eop;&QMr4 zPzFx8W({+xr}oMc=dl*gr~9|KZv}1uXEwzOIqMpe^|I+*P2-8&MyV-*e_3R4VPqoQ z?&=To<1^87ehmfs(W6J<9M5wJJfaq5&2w})zoRgRS2YL4)#qA%_ALDLZ~g|JGZLmh zBh7&P=QQWH48_H;{u9oFwMDA&o>OfwY*I~ok$lk7!jdrYpZ~8=3|KtkJZ|V6nk7e_ zv)0tq42YT{iUp4|27&$?{ozyY*$r^@ z7XuH4T+L@b;*69M-n@xHB@@HwH5A85*2r{#Z_9Ay&Yimy9M#ChnGkFyywL(|oWM+Tub+$8Xa0_;7;q-Mc5!<>3MEkid0+!% z#M;bd#E^zj@2l5I+LzaUV~FH@d7hQA(zZO+3jg`=k8^5!WNP5cxh!Z^NBF-fKGE36 zp|L1nd>*l!_K^xAv8sszBlYcI3@>&SXNR*X-Ij2U_Q6%ce|fa+JUMhB58l7|_n(Kl z2Um%5quU41sM2pvtZhGcNl9s)X+lIeORHen*NSq4(X|2T* z{zuZHID_-lP!Su8Wt91@ZCq>U+BTmBtfjI{g;AbuI+lMsKkub15$k&1`mSFOpAvlm zE026a`6iDjK1-?fw`(|iUWOL9O@a72E2zfm<*p^ zEGXV{?VCw;IfCbHV+`{1>+5tm1JC=6K6}F7uTmq+@2OWsUd44xA#8&#R@ZRqWM#)F zu?=Kj9nLCstz&dF7Co+aJJ{FjPJtU-f1k%;{=T|IEb97FKO+Zv2McWm;ZWLxA`8TrGm_lL#_v7{v%QuI2Nqb0+$t z^Q(r}c`i)#77IK4oFif*?&r{mV#=Gksq>EVj_<4cxtH#}d*eKG25ES(K1^)o%d_qh z<(t=v@r8MO7e6?a53`C$0f6a$XAuC^q81&atkq`tQ^Wb%Ghi;QC> z>~pyMoJwF^s47BNsA76{%->kc8~eJ$Ir)~^C>2$$^e;VntuvdI7<_fhJ`bu zl#tS1yx)Wkop6tuYg7oQV)p^hyDpI6JAwIB<3YOjHf^HFtLwOVjn_$&;Lrw(nF0K_ z4hcVE%{It=-dW{-#cV=u235A3!y$7$<$B8~AdY@Qyw-V+zWX;Rq%lBFE=6nxMrfgj zC&uvM;_OhLaFv2}(U~3cR45+1=7hz@lq32eAC?rgK7rHphL)h^Qne5RTLiFGS;{~l} z;+k62jU2F|hMG{_+88nbriXY&^AHldD;u%B&N2Cg!7y&Z*2Z2iCzP`@1am~V^f-Bz^;FLVh%ut_k2hcMLJmd#T6#Ld z&>#iQP~2%e9OgDw;+Z+5@KYwVe*(D6g0}OTC~iaO{OrVdSV7q+s-hc3S#=ou(^sK_ z{=J=7d#K)h37|`$x55gP;#chgwT5QniS8kdVVAR%O)aH|h-dqPg+3u52=LUcg|6V8JL;&hD zDm+47CIYx60@r=cM1TyUmd7ug=osxz!rkw^htUT*18iTQh=*p1vk)ngTfupzZR8n> zcvSwLPemZ4 zrvUhiV)l_Jfc)J2unZ{L;C%RA31{ED_@?{U!Y0L0`0bTdK{;f^b7RkPtJxQp7l&3r zMjn7fuc(Fo(s%}A4|jx(idPG~t%5Wh1^C7mean{-sz-Px*Oo(meRV9Zs3FecTs0kC zVIRsIu}N=qtO8f^tH zsZ=T|@jD3nJ9qD4l)G$^RL?rS#He(WYfa3cI1?GNM_<3gxmf@$VT|10d)j5@5vdCK zfbutg{j2bNaDZOWuw;teEj$_ksEAW8qDNliVg(A#4l+aIvPPIg*07Q1Yq|y>Kv_By zs7+EJ?COEqP(%nWj9wd!B}N1oGOg0H2XET>_|IVtz*ot-8j*Gi z9fH)tK7242Z^{h7@>=iJ$m`}%dQX+jJlo>bOen!1Anix63x6_ha+_Z-)8lS-wN~H}~qo@UTqbK!^9TaOdj!YG?%%ZUa_RJzZe}`DDA&eP}#8 zk2bdKr#bh2?>60JO!rt{rRP1$zbQn!@O+ht4CL1tHCc8tDa6TnTb-M>o+!h+a(=d<5e>4oEM7%1C_#xbawq-SSD_l2q367ly_9D^ z{NH{a206?9gxpI9rX%K*7KB^xy#@~$!=Oax0%|NYrrM*CVx9<^43w@6fNNAPSTl{q z0&PQFD>?V;%kYt1+a;#CUn-p71js2R>=oIo(x{?f?mt$QC`0vFs>oHaW*T&|xt{!E z1_kK?Mb}(kUWi2s4*}5C@C2O=hwxpE-mZ@ZzE$LUDer065g#f8Ed(fim`XFndD2@x zkD^_}*^&2I>~7{C|1lg6(e9O$1$s@z7JfQYbo5wzL1n}r8kTVUqnG&mtT zV3ib^d?NHtkVhHFPpo=iTJoAX1Iu8s0`|NZ!|w3-XgFsNtB~o_(-TpqM&jT@Em>)-&X7&1yOB>HMPj77|C?|2^!bceL57xDhiLril9?UvP5(_w`OxnY0 z)`Pr&OgSLRER8~DA<+d4sQq*(nVzQ`(hj^D!)bbAD$IZKf=)EFDP(W$>{QVOejox+ zEV+SEeve|lD#7)AU2$IGql?1q7=3u0hL5rinWPI|aK77b^@Xew9C8b*q3_+-!UA1Y z9Q9W_-~oiklR{G7gL48}So-*RXnvdGz8Ga|aNaCXgm4Qd(gii1F5sV8wd?`(;A z3p@i?}Lr;D;7pG1)cyk_I zZ5P8>2K?E11@3c=bjoe`-uwy?oo~Mp^_g9a$?8e!02e&}F1WJm{w+FSHGwy{Kd+y# zt`!#0U84rrtt(-hv*w=IR`ZljDCcK%(n23NrDbK{^E+#osoAz?c3$qa`sXJ1Za}Zt zhyJqIpVOTKiV3%dee@I4O;5q+l{`x>xa#2SNT5p18&X2RYdc4~5$9h(YXQBcinFAC zR#3_Hw~=#2&?ixq7hwMkaCUJ`C3-8ojr$hy9Pv!BCuiucrET@`JJsEEh+@6Ap$X5; z1x~N;YG5!S0^niK-*JQQ>@Hf)3s3^Lm#8XC7;AMe9wZP}6-=cb0o!=JE4&yRjvFU& zow1Nd9KhE8tC6{!mgeG>sR!_L=!$YfbvG4n`Fu8vcXuD9D@Erb{&<+d)q1gHXSk>t2lUE8#>9l)`(G{oKKL0&NT}m z-V>Nx*hZ)np-PzN-{)n;QTOw-HLpL2RbiYzoEaIE#=n6sN7l*^rT{ zN4cZ$2q9Rf5Oh{E#Id#$ZvFa4cxZ;nVTEW}S1Y5J^SPBY2LeJ19AK;*0D)qve3M@b zaH+g|H5^Q?5dVSo(gT7r5K1_eIcH%7BG2NPDp4e}5j1Q26ehYsHFFlI0^;0<=@)Z| za=Gp`^1_~u43XRS9BxO>Hizc=!@Dq=4b~fvT%}6zYN*lpfHHf)_SnXb{#Id+yl=F# z(DUv){F4dd3V2#Tje1!t>Q&3?Yy# zJowRjFm=MeVRn7LelJX~FGWVt4&$Er^m!<`(*fBcoGB)k!!zyW5t2;~|JaM?q2>0C zkUl5114a6fb+p~imWo{qAf8a$`YU*FshGb%LoWXP+hGG5ZtuQ=H+(b-0xiwUi*p#n zXkT-KeFFUEDSR*J%z*JDpPv-_@shl_(^3>M1Zo!Vud~m^tkX80P`fjnkry{UKNe~* zo>fzoe`^%*R)msq?{)+VqcfA_?xXC$CkwDro^!?;x;g;9*)h7}jNZT*jb$MZkNnv- zxl=cL!XkO)(O3tw6=10C2;KiiN2O z6j>r#pz&NnN}EtJR{^2fEfw@7CNg7aFf^m^rN0_Ru%jTpD&Uue!9)YbDMEG*;XgM- zp6KeOM@Au3!rG>(YTS4CHs^3CbhLHG{7lnzT)XxgSHmeZwu@)-48fI40mhvvc#ql| zqv9SQfpc06Fxj#$1Pc5idEOc%_j7nw=(PyXvIe1SK;X_KIc$K7zBliL)$K*-hBkfA zo^$3JF+40#Y!FWtd6v0#v{))DjMcB3+d4w}`E=L=oLz8@BZ>>&`ppjkdbMHn&tHW( zlr{z6$>A}@ED7~Psn3I#Shc-U`lnj8^DW|eRNgFLnZ;fS_Ej1jg@jAftC5g*YBiuJ zWRZr|4#1Cj=tOZ%qVVql>{LE`d#DIZ^pI9-i}7Uum^H{8a8^7^F`SV-vKM#sZt%Jh z35I%V;n!Px%y(TghsylgzyNDS4GRE%F0W_sopltf9TbRdK)oq5-b3YItGfSAu6G>( z|2YPO8oXgfn{5IRt2#QOCt7fwix-rbpwNEjX2_E^u=wjK_sN?HzhB1?G6MZ%^4v!# z@Zl7G2n}QDpm17E^itVo*7e#$$-Rv+L#4&M(FHsh>ufO?b3@aD7>9Nt{ z*NF0JYK=ixEj-4V7&ATRj=noLsD1G4G7@6-(rcT`Ih8h6Nhxw)RFI?RkxQ6rn1O?3mK^Pa zER2sR*rUV4EF*=uQ2ejq*;Rh20P7Xsg&%8Z+eeA^Ivt%DqDeJ5gl>IKyFIkErwCIY z4_7cMOl{L9cVZ$`cU~m~8zT_^Ywn@y{pX*D!;$guvw#1$v2KBeok?WrxzTuB`~EeG zGY^bMuiH7tE0?yU;*2UHO$L7V`*49Wf0|7_8w^&qAxpZaY@(pc19C6`*h1N2y*&IS zkAa?J=r#O9&#kFLrWBcyvxQN@T<|;4yU{p$$}RXei=yAq)g6rq3o|p}48A_U3|_(* z;`vXbL~8iR;k-Qf#g9m}BNbwnHkn7~c>k&|4W_J%#q##0F}5iO+R+eTT8t4Pn<$VD z+h%5B%(r%sX(-Eut%^#n1`eF5u{CdhI%Ac^k}LixG{q5)6Xb$c%jq@Sb;Tg1mhCEP6o; zxOX1-Ha(6J4H>(-Ld(nEws2^RyB3P3sxaYvH~{y0UPDPvC~R*Cr47}ju3(Je85a*X zLT+sZbA#`KuXUW9Ap4HNl8vn8)*i|qcyM%{Xw6bOP{2ctg4C$q+D_yF`(^Z{vdj7t zjW}iv#>=mp<|9p^)-qgvu2e=1RH?M{r3UwBO&kmr)%vRDe!GCpN#vlLt--hR4 z{2Ux1oA97T?%CW!2>U##t-O}Yb+-9z$fX@427%oZy5IcGufiPsE#$#(CfDdZK$>uO zif&TKm?w0n_`x08c+%c>ZYpH)>@8P1!z@l%b(7YYsM zh6=Q)P>vHaOM?`KkPP$lO@%z8hK)>|plQzbx%wAps~zLZ`Z19ftdj-=v<`G( z3@#WGzq4TqK*_!Cze6s3XLs3sJQ@xW1V|YURaa=Krwaby3oNgMDPz%`hnX1rk_Y(7 zqcU?1`H!(x2k$TAF*yMUH8lb5@v1d&;8y^;`4xD2wcO*GskZn7i|=)F@xEEar-9H< zsD}1ZREGWfW%QVzVihbZMA$vYO8{~2kZ+a=!?(a&02o-2Hb1X0wqHsEnlF|J<3HUG z`IXgp|FPaOM|1Lyu}+-`8TltH{=2Ru)46U=RDHl(gxixCLN2+tF| z5hsAs>W)+lKW^iB);Z+oTx)*>uNy?M#rs*A*%YY3OOM4poBLUyPDQ7-Uh54E3NZ0G1 zjBo(hD=h04?>T)*vBPo<5ZrT)a0QqUl z!{abfz$SoJ%e+NN4(B(is?J{H$t3BB7GU{Qz2>kYj9-87W_b3O&*H&7#j9cnP#({{ z0U&U_4*|Hf01CZ?YXFecUBcl2;)WAd15nJ1(%W?)7}?t;Jo#;uXDot*gU@5^vU>3b zOmY>2i4{<{z8VXs0N=Ymemmwrt+6*-0Nx@1mu)gvQCM=T2-QRJwRPCyr-Ou#vR4%J zs{$O<@ZJePZ+&bMz{#SpKe0$2VQjW3xk9lbTY4Rk)7E;E0%NRU2|#4&$uI@cD2jqG zT_>#hWSwv%su1_QdoOx6z3$r6F(Os~6s&{!&V@x3q67pJZyok$*F#G$=WcBQ<^>?( ztj(f$WI%LU-dPk{5<=rJvTcB|=d$~HA4*nf^meU|P2i;=FK}Wx(yO1B;a}_lgcxUd zN9tS1w}b|>3C-6)H2pEgFsj(+aGrO!@s`ic5;{A@IVBvN_1|G{?F&7n;SgFpM>)vH zT3Sx1_3px2IGWiA-6*I_v-1FIBaJAig&}2gbuE-;6ShUaY*QU_h*U`fDAM^jXAs;= z1A{~uP<-i6Uq=8dFiiuHHi&dMNAWo!N+u_tD!fAoL)O2bp)A~DKPRTg3DsW31K1Wa zD3)fwU%eO#%z$OQ>9xDzW?z5!>irKxb#`G?A}px3dI2bc_6=97ZzgKq)50GKGq$Vw@m8Aq-`r#I9)J-vXC%%dip(bWHz)Cw z_aRz}pQU0nfrhyzlzNTNmB@gx$(P|8&%TIZW97vlkq&F2t)F$|8oR?o7!Ti~MJW3U zUvH|S!vvir!WM@Nd6W$w+QU$3<@1;d#j~9QI#q5g#-}mD$RXEM!(jzR0;7ry6MV_D z+FhWX=l~5O^PC0Sp&3T{#gj)69g$6(1=}TAtZ)-0$53aZCvM!ng=bzcaU9ck%vJXK zZ@u+atc&0t{Ngvi34p7?SFJlcASy4KIBq z#+d`6Z_ar}4bj#Ju#QU^-WiMLrJ?^_&P^_$*xX?GQ%h%x$eNO{i}J0)+KM6FFz~M1 z*D!zpgfU{A=>=l%oJX2xD#4?AjOR{gMmMz9|Hi{G{$Kw@G*5YGVJ~xehFYRjoa^cs z;1)yd83ugm#QRkc9=rt@u7n58Ou|FCyt)2a7zp(K8yRo{4>hvKhyaz(I}h+ILYJl& zZ5G(Yx-sZQ|U_pcMCFJT<~V<4!c}4Wn4{nH=cc z5a&9I&OZ9X@4{6K2z~cn3q$|&PtizcRDof)JM8BfQFZee!At@0y!H@LkjB7qKuB_B zApjrR*aFiPpt!6p&k{*_Hw?ZU4$aq5JfYuH&On+U4Q0}>brwu1Dr4@}q>*1+sOl6xQKIhZkL}AT!XJX+Hu#Lt)3L)_3y>Xj{l-|b?2+ho5vpqxkMbc4=8Pe-FsOCDhRU8A#ZgSR%J(?ibU zArX?cINW_XA38B?FTWg#5f|>^0rZz1B>JZn+@oQZ+B}gDlZIDR1bvbgx6ax%)HlJ$ zUxeDGW;*-KAeX@b+z(J673{wE-oSVU%`NT6NQ4gd?%nTyFU<0cdrxWSh|*@;(THPM zr##X_j)`b}7fhS3@!DxaESUE;^--<@AJb2F`%9#;M?O?45aCW36=pmc6xqag%MpASNaKZA| z&trO<#*zv!WftcxAHH*hA#m%%!Ej6}!^*RP&_T3`DWUT63f9}}9k5T0V3iGMuM}A! z)_wYaTTHhRhb57!@WVrJaU)R}^Pj#5of=rdHK%;8oc&1gorSMoV2GYZhLIkPA*2vz z;r`+pvXyjKK6gqKuN|U_^D)}9?`ghYfqZa1E+!Z05Hm*v09^v0J0mc}+65TC&iMSw zBO-k;2$_#>6k`^~hkVvIkH5vSB^0ssTuKk>F{YEYXkhpJbI!c~1#1Yo#%PbVX`*gN zF@Ph}rESd4tUswT+}Ao3Mpvrm^*p>6Cg1-eWKe|G*P8hJ)carJL?qn{qlt#dBMdDi z;Mqm^$1>-x0DVt7UY?qcDKFL^vQVwM%F?sJXfVsKqK*QN=~H;z8uFT&{$MzqSL{~_ zhUPXLv3oq1&vwC&of{A!Ar1aHn8ZMoag1z0k3bn9h$-+aRZ)S6lR|f#1u*~n<;(A;I&M7FKhiB4pIPacl;eW2;Z3j zpud?Mc|z>V5lR;bu*t7jctG;`)_$l$QO(Js(qcw#$b}*db;$xCm?u}Bi`NojB<_NW zs}@GVgG2k96RM8ddo`6JyavF#PiV&}U?q)5bYI}Sbr_mZ#)|?Bd=TaaV6ZZJWibaH zkHj@{7+0wXpN%4rdqOd_ReGggxgLdZ9EtiWT+}39GTGf`VuUcgnMUZQv47B zu`{tm4_<*ueP}2q3=NQSfTwr~L7)f1b-dL@cq&z!?T5ZWQO4pTLU$$>LwXwHLk<>C zEZax32-B7ISoms_`K-R2B|i{=jt6KHKzvRfm|;LyZlavN1dtr!389zy-1t<;;4}ME zD0qhyk|Xqbn$Xz}ywdyZSNzB3d?6`lS!-oz_AO4una z#Rz}eV~w=b=CO9i2;XzorkMBkIXK(&oGn(NfTq$E=h+;e57l_D_I)-O7N**83m`Ky zjDZ5rUkQ70M9*EV@<(_}%1BA+qCfkyzmU&M`SU-M3%Elg#r& z|F#~~i?uejK!_Qk#u&uv01G?Jxf*M(9(C`1;n`qhVRTbS78TI*6yuV{rb>8%08xSB zy5$omyf=Z-2IC19wb1hLJ|4T*C@lAch=wY_Q#JQa;}HN#0njoL2(dE*#-SoW`~eEK zMuJX^602W4CEuAAhxBb$5D4freO42Fae$)T*4{&LI4X7%-sy9mv&JP@ZFe!gY0XE1 z69fT0X&q*qA^;ap@mk`UC80cQk4(`$fRNu33cUf&d{z!15h?}bSJQ5Afm#6U$38U9 zF~O+R4-ni4H|{+M6Hi~jXAm4|(uh#VjUH$qIx4my#h{RfG2{%OXBF8ptlK3#`#Rut zlS=i1M!n;PEgJ=O08r#&F}yQ^1L&v#&&DVop6E%%$Z$rulR^O$HC(s|&C^B;T|ius(O+an88bQGXPD|>LtGiCq^x~})f zoaYYio!3Yed%~`tfAkS@B^^5IJ2)$}C?zbVt`P(2ix;7^Jw^SO)!6G;rAZ@%`M1{S z7(j3zpy-sc4uXHj7HgJ;BIRf9Fi$&*GD?`|V4C}rMqGyIf(ar9#`{g)>rd?9s z7Q^!FLOgfYeVGGKX!JB{B#lAPJlQkWE~ZTIjFrgC2SmM14o}4T9`3W1=dBwQ`3#R2 zyM+MyjZC>H<^|H0>hW^gUh^0l+?LKz2>YR1I}VwjKMZ}xLT4BTZIw4a@{*{xeZV@= zV4SZr6#LtEZpS?F$De){-uuO`kZ}WHVG<>pb2N*WwG6|Z^rt~bLzTQl!vC{ zRN$8YW*s`64ec>sdmXwDbwtV#tyV-Bwz;%^KZUWZl=E&B&>`211`23FW7}hl6dhfQ z+h=|N06+jqL_t)YVR>wff~u8-LpNZ|#Sq7tl;4_Do5fktpr%nkW26R3jVj}Ow;dkD zYK3x?A`N#hc=lc9cMPvx;NMlu-OdN{A15yl)2UH|9Gd%NC|tuEy9(VpRQ^k9z=cE! z?La$ycdy5DzBacCxW9Zoeh@k{BI^*kGZLi*o-+Ovo(*QwSSwxU62>Ag&cUE1eVYoA z!lZYHXFU~ zd#hVSPTda`w8)LAK}Mc|A*xy5>@1@5xMvnQ{`tu5<;MeIs{rR0QDZqMj`PrGEsD2v zwJ=JwBYP{oNFQTFrkQe(USA7+H*ZF4bPbQc9Yd^N)5bb9Rn&)3(ik#WuWZhE6~?F? z&R_-nZDDwnH7BJwza*>}z7KAyt3+8wMs5vFM|`d>a)z#Oj(pAlSDzv`&y}+|`Jt+y zB#fGV2@h?rAv7E;BCd0fSDufDJ!qnq$kTi<}m@fxfkGc?bkeWHW?e#>lJ)gvIMp`RazqSm#0IolScbc+Qf{u0w=5Gc=PDL3& zx*3juRU9!oJ*qK^>_d~C7)2IdVE6(%Z{R3Cg61x0{e6O=ME$E0JT~)aDAIR-_q8yK zfds`9UI-7xc_q%(If?~4WU$8>$d3zn`iTawu_>OLkbllx9_MtI=*?)PTniavExb=2AKu0`YC%;3$|Yw zWG!BO?}+(Z+%g+p@?8zmd5i#fRRr)my35ojkI7r5kQE@Y73Qaf+RD&c?slNb~wx=Y+0vO+$D$0scRD_r37+tFJ>F zb9c^G9aow2yS6zRc=9y#V2oHonA@9HAWj*Wu)ajdI|@)PhpoJbe&zrMdvB^RR^t^H zIO`p$#xT;_(sr5C$U0;JVD|BP+W$Napf~T!alrGJVqGf(z`g)+}YNSmu@cpXjweLs^)N=E!d-w)T{5`KEHW`dUo`%__u00S+c4)c0ck_0b8Xb>+m+_qLo8NU`eGY$Yd*vRPXXi5+a(;|g+Cp}ex#kd)Gmk;R zYSa~g0dqc2$ zQ90FAanI-Zw5S!Ex6So(@iG@60DKPVa2e9LLt9%2?_+?*Dh0yaCx83Qw&y9tYOb~0 zp|v!wIqNJVQ+X`Hnr$5b^CT||OYWhdk>dowuqaSIYhW(<_zS|iSvP@)-mxW^tMhX2 z6|f4Vcn@f#inHkTXU6f!pfpa& zU2UO^kS)D{dV*D4?XX~Y=klxKU)JwPv*&dfXavJ1jx}I>oB#3=^!74j)>cOkpuNE^@Pc=* zt5}+DeHX{<&vCZH{q7ctXR6y3@nR_VA8yFwD z?_Ce=q~?6}`~Oa8G=-HA_#F+ca%Eaq{?I#hI}GwNGm0Ci*RIk zXzJ#TSlr42T~_1vTr4mL+?#;Y`lvjuVvyh;gpBURB6v&Bo}u8|ezYPg8OwmzDyl2b z4UdEZj2!0u9_E~r(nNUd$q_9C>F~jGN;f-rL^u@TU6iyx{ipwohlP+(6dt1_TKJqs z6r+;#URnX&6pAET;u!g~KS8DGb|N^~vkbzWm&YfFf+;3?iXvgirkDTl522*J9a=&b z_#>YL{C0Qth9LmG{ICz6K8r!NiYniWC=*FH01KLxm_Lc(%h0TbriQ3Qng^eQ5zvtB zJpfrfv=Tif$dfkaV!PdydCmtz#bgIVQ+p~Eu3zhmG^OFhNE8bo8Np{EEI+4A-DKVl zd#mexHS}FtE#osPg|S!@?|V&^ax1eNHFV|bm1y*hx%9lB!dOw;hH^rRlb(GeDTW7! zyfn2rC}M@-!?YShi@Q6!pxxE@JTV8K&sbzDIiE&B8Dg$XHj>9-^is?j#vmjA5DO@G zV$L)?yPJ9e)=m*TTOT1A@=dEuCq+`bq3P+d$tcT{&)j-Q@lh22X@F)Md}DfQiuFGK=^P5G@*mwhzPV?dF&Z-ioGpEo^H?2MMLK)4uLc@xd9Cu?q7=n z9`~H+gK2o^8*jfIp8fHUq3H%`a_rAffBp+PY#2?HAKrfZ9g5yjLj(M@iE$$X`ZqPk z^J?lt9(<*oAB|~?AAT6-z&|B_^k->Ex_Mgwr&I$vMF-Aj!S>QRZ<#jBWsnNk22Hs!UEiN?b#Da)x z&F0hyFN?BM;tp#`9W0+#-wf z(1&RPB~7Fm^WKzEj@-A3J;_97R~F$6Wj!@&rZt{0^7*?1-9iIwZFyCA{K*%gnQ(G~ zTEooCiLeG9T%Mhab%8u{%ivyhgcJ6y4%{&M>;-hxMO)lSK;q?I*b4EKJv|o3VCXQ? z$HXYuB%FY%eCQT9`SAK!l@g5gFwBwWKgWo}jiwzs6?XW_u^J-6}Fjic)U~wH<09M-^(C>fm`>~RAE?)TP zVMEaR`AB%&Ur&DsASyN>383HaO-hi#G^DhOW3*M0WH8zxxw9^TL2 zi+BMd!)YmjnY9t7#-0-$p^#EwTbRssxU|BfudzOQ-<^xV%b}N%n~(!FAB_cWqv1s= zlPU$SkD%2m!iGay>D@v`?ysShR#kPsecd^$P;XLHN8?Lldy3o~tonFn7quX>E)guV z=Ng%$uQ~QH4-bN2annyIiUkeacu3D{UbhOXRXvZ^*^^DyzB>g|%K<=5#d|q-tBfZG zn5bw&Q|1TjJ@NTn2ipKy8C0Mq{TYtvUI<7G(=0`i@ONZvP?&4$^BFSfvk5T#t-;9( z#17ZQ`)N2xp4~I!ur1LX!o)e4L#-0}?Geuq!od5uAA%|kHJJcm4P$;!!;!$(dH5Wj zUC)cp<2t(rdao@2_5AT?)QCX%u~st8q@ADllo$A2>CwG%+_-u@j9Xv`Cf<0x4`a~+ zir^dcmZw5KLOPAW+8>~07xXK=S{%>x-g6P!FmZ%`N#5WzGNZc#41ZmA5%{R1nQ z;(vn2ikj-Mx(EN7+N3%>LXq>M@QBL46R*U`LntSV6e~N%4fg*4A^3{bsi_c+g;EKx zuw%-p-Wx_0*BV9XQ@}~zxhSUvC=IXwVJF`uC>!2{t2x-dkMiip_p2B30fo(Ohlwje)a`L zRo@8{lM{qe;(=kUdQbptr@F}8EOuxSGU;AgU143aIg4%ZU3vK~w7&J>UqVfPUj*o; z4Efo7_(h7(OfM77kf&3WS_jA)4Uro0JYyQJZ6PWD?cup&{Q%ZChxe8~_>dw`T|{yW zP+`266dbzdAmil8^1K}6Psg3xk#?g2fO+il*_QjX%XF^rgLBsB?wz|~^2@Kn?VtV> zl0=Cn+9!+1o$KUuPe1xPtOBCWh?dJf!I(w_m)=?FBNjabM3+&Q#R}0r>)_V|p`Pfo z*kwYG9>Y1uv;h9CN7il&o{K~#%7gUuTdmyp{aYTT%r%lnUd_~_a^KWU1d)a<{#K!u zpEx{6iSqCL5IO4ro!xPR+Ebzv67f>Kw zzhd@Sc_wB^WUK}+?<+4gs?6_sKjo7{-YW0(`+iS(v5rz~5#rTtfISLh41JED)^0_+ zI?lDj>e}*Nt5J7$W1t78v{ImInshl0w~lSjx;0St0mAL%a@z`UV~MteCCrtz+a=|| zwJ4&nXzT4;Vfg?1hfwwQ>rr;BjgON9ObQQJW&wJ*3jegD$k6AXlk!s>W#elY*G~Ap zMm?1Z!&AMU9UK-=#0F^rBV&(f~6t+99fAO9HU;Ken_fzbh4?GBHGxBksXK)CBlO6sfA_w**>|yhbS7-jYC=y3wr)-!{)jVVVqLVx)0)0Wtz`p z6?liTSA&ySP6LuSQn{x5_1~Tqv0~D-$vP#bBte3^H)4u-miVr`)YJ)$3cjA; zOwXoks{uth;C!5`^A_KUxx~kwX^kl2eCK9sHP4rG=bB<06*u=NbODdJZ0D+SX zPj_f2jdiu^;cru4e?=+Td1|^F!lNvG<;yUuocS{mx>fpSVTZus9?e7N5!Y-5(D@v&tt-0d>8*uV0O|Nh}~*URV;9Vy`V`v7?!K!?#C2k)(t0Z)w;2 zdOdlAJi;}XCY0+vUEOr9dK~w~y>jj4e-6`zHc(2(9jXgS6qydLr1w1z#$GA@F2(E$Mu6)tLv;T{?`+CkhOYg*f zm;;zI2?l^Uhi-PB>FJ&%jlxRnQfb#^ud7sR`^K)a?)0zt##`m94boPrywa>RC22IV z13QrHW=>!x0Wbj|GC+Sn=j9o(RQ6@>nLz`5-(NWAIZr-MP-GeGYG;adDVQ1O=z+*^ zZJ-qiCI8ti<_zX=%>KYXhkb9p^;X3xaAMDOV3b0dfdl-Mrl7u#cdN9o^MW)R^?2yG z@K&^wk*RgMP}t{}gYDVrh7l)b_7GgG6VF2{Pa=EPc_v6is$7J8=G%)%Ck?>O?|a{?#9i|uL*RxmSA^kSy(pU@W?ggTa9g+MJMkqDefB#)`ca)b*c+5E$_p>xS6_7$AfF>P$lshN z{Vx>~-$CrhFC8Y{-=1aus!jX1dApw?irLr?`{%cNz>r`tFo$h9jd_sbfI}$|HY4I7 z-Z-AOCV1>m6HM;$>{s{Ny6c|%^5rlOYeql_%RDehpTjqMLQ$bu8|KwU!w31E6EOfs zg|}ya%Z~1Z4CiDpKjtuS;X;Z+rLS;=n$xzS?6vT;$3Hn;Cf1~vZQdfiTc)M-iNy=cMnFhGJHyv+kHa$Iowv^{W*itXAI+7pb+ zZ+qDoAmKBf)1}FIp{e00GRM<~EcvZV61tcuvM|wy^)!%jO9*?m;n`rtD7urdF;2wpa{aG0>%PG&|6t`KuK7Hqt>SPdb zD{`9XM6v&?&r4tS?d_a=ujHHv|9BDs7b#amaJ6(2@r3U1Q76@NV^9!~4^AgC>W$aq zpm|usqn&U%=^D)G=DHXU!mXXE5b6_gvL274;ojHhQj9W6bUu$IP@PJrW1Kw5`{2RK zzz&b$cwLiy;&i(8@yDUHH_N9#`AJS$-;Q(PT6uEjYzi}F>2VBoN9nnpFxEM96CsdO zi-*7dr0h6!G_~XwmHY9?bKZRY$rt7D-Z(vPCEqtPXN9oS@HZ#S)+@XpKSEctp|8>W zY|dQJ8aU3*nNt-qc=I4m)%lc{oc1jb-k=%#b362k2Pjb2cPl;2zmuX=F$kSLoc{Aa zPmbf;wUYey-Mgx<=3Zz_PV1Fl{Gy)3KFTRrtb_7;*0?6H`6%ms8a_D@x%nUp|5ScY zMH%jn!t?OPjT)JBJF*NPTiM%N!=pLHoJdJS7|VV<$ce@3Wobo~s2L%*H?#ivq4z^a zj-*z?2a(rsMMla1x9TG}Qe~O~XJ71WJ%W6po_g%WYtER7XYFJcss&X1! z$P2J)qwya2?#IBZv>T)hHsc=L0Z?l;C$jdWIRTtFb2Ku<+x5OjC!Ii1Hx2Y>l-Qkh;WYvZV% zh#qkNZ+=mZr*PiLqSOhBAqeNB2hEQ@v?Ql{3u1goZCDv6^0}bcx2*a;L5<*_wKt@ z<}*a^hekx5ZP~l8ycgYw{G}UQ3jbLic-;B;Bc9)~DQnjjm%J8%qE1Yzgy#Ov-p6NF zI|9_`kH{~lvJVqcC>4Y8zck%o6i$RQ#?tH~XMWFjUQ0xn@cy}}gZ8q+L%zp9$vk*q zPVk9LrFYUhnl3;-G&-W=;EDE=oQ12_(quo}YC4xW&^KBe%%-DpoV9z&b?>b(#OFh^ zO~=-*mJULnq6heKo!@i;?-8+t-p~^|GR*Brc!_IV3x})$UC?2w0h{amexAZ`562Vn znp#2=k=@VmuHaXaS!%5T^$wy`*D!j9k%&rgp?_=hw=^Xye{#7N z-W8eZTDT0C;B6b$-{_D2Z!f^!XVyr!Whl1;F>7dpK54BEX{^b54UP|=ySB>4m-h^& zc-~A>mo`PN-;bVR&+V~yd5>X!{-!^fvunH`jO{%-uz#=at#`4Z`l5dtzW3fX?DM*H zsRNV<3V74@hw~4OZ;Cwb3(ZTT;N-RUXx_ZEC`3DW-InMw+G|^@XRyx<`);kxuA`H( zag1kK171jPdic_D01s=;i98>^EQ;J}^Yvc$bEd;bbMPbD0{=(r=16AL2-@7=a1xx< zy)o2`=@|dfC*s}RLh*+>A$B1S1*Q-xpz*o@Z0nEe zenvhIj!-J!wI88Ja_Af4nH$fk4Q_@D#De&kryi9Ei^7305rOwYPL2)hYl^^$6FE)2 zlhE6I<^;(*+u#jD9NycmhZvYiBPh@2mBcvplB8TiT<^myn}N78$Tu2As1qKv0 z1j~t_?Tu%(_4u4%ZJtKTwDoy6_`S*)t=WCvXB`xM*W0VMb_nb{3{Qb7!ixZc%m@QP zHHPC_iaVm&6sN-CoCH4&!OY%EmEwd^FH7hWX6T)si2-_+{V=Q@928w%$|#>HaH+S&vHFM#PMOSo-OaECJM$suq2%qw#QI(t-M$qL_Xub2#SH9 zCI>yn)+B{6P2ZmVr*YM5#@8u*$pJIa`Y(mgntqYEWs}phYu5V6E-F@?;aC3N0rULM2YAy^XYQVFdUx!h^bh}#5c}0-e%6Hk@e9R`mR8o*z4F}RFwaH_E}b?e%02EjkgA z=An)Wn=*dKUV2QlmRUCSDG_`%XPEz%RA^!w=R)=IM0My>nMN zk`q7?8yp)?Q}z7AukC_ofEF!MQn zChAV;vk0VSG@%EB0nC_J)YaOaCDfndhacDj3Y+iu#L;7I@TJNpjo@6?8IVFvt%559YK&=1C-RO}DfBDfbU5%`mvx44E6v@ydaV|Lq%--s68zs99&Im< zMByYS$&76|m>`Q78~4wC6{l@r8Q$CzrTnX(|GXN;kAv$k;C1Lk*nE_ujx3DMSV6Qb&9r}K$|dhsIBh}~OLlVV5RAF|8= zk$J9LyROorivHkakI60j?wTi|$yK2f-wh59B#PixXl6kf{PfeZFS5$sl7F6s=E>5H z(QU}CnY?>zbhpQ$5BS>Aqmo8Y5+xWXnZl}CE(+^iwPAIt(uaRWc0B5TRMV&K-nv^3 zr6rtP>_u@f!fi5aHga#y<~V@fI$A5aE1ott;n$-%okb7kfoH%c{GiEExM_X%gf4&| z(fwTKxz+$S^irc4Gw%0Y)tNH~x&y<=e2k`dkQ;QM=5!#Z8OiV#eKq{0w}G$cyQj(J zrl)up{m;MgLHevYfGr)C4q+29F= zU~XOh#)}yF)`$-L#*bYOUtG%`P>9m^^b_mzIk+ z13%!~#@JWZ;`!!Sd3WIW!3W=oaok@WLytmdaF_jI?r@L32q!NGpV%ZKp^d}YcM&=G zC0j%h?q)xkCzw>-vt#R5W4-Zqa5M6_x9|s32(X>!jh{X6e5UI^#JPR456hIt= z(U_3yY(^W54~mSim!aG%gpabYKFX!dmzUTO!#y1YeOi%GxQk7+nLL;_k|1-6*@pR< zgY}FIcbJ|{Hty$S+Ym{BISBKW9$?+_^*x&+jUn=8D%ykq4D;9-h3(9l)Aiq&P#qa0~6qgOfX+)0n&yqPLLpn$MDFK`w~r$1`0=*kFSG=FNj>OQS4PlpC>7d?-}z zdv%yIBhb8?5{KYC3n5|%2AF^=m@yPFz#1YJrqqOpT*!gJyJhEzqy?mPh$_fVJScyN ziNM1Q-0S(~iK&=F6Jp+F9&iW)^j@bKZ8WbW0R+zW%e-7`ZWKGPr6?Po+YDyR8$6ao z!Rkt(qWgmhdCK=|Bgj_fik<*Z^9O4J)EvFr{DkBSg>J*zF_We=TRZsng`pEj zU<*#*MNs+MzQc9vZ}s_%e z)qZpOy*8gcKGlIUK}2{P3MB3O;LVzwj(+>TzEsy#@hWXwRvg(GAI3zvd+JP_3mqpI z!Mk`_S9%90+;PRC{p+biL2Lg5=!BXax;)3kvWlg z9z|PZ0=_8q=w^5)Cl%az7MY+};FZwRSa@fZ16j||)ho%TTo~NH5q`a);^1_`U}q9) zJ$54}nh9;ccI|38`P#|y@vlEBo8x>q_tSqYYx4X%Q6#mNBwSUH9}X=a&FP7J{j(|H zdGhTyt1%A8@rcVw@zH7u-#{CkZUiZ876-?I&_4K%MDZPsgK$Cc1YT0!6f;zuY%KI8 zR6jOA4V~;xPN9C%cOEAFVNvIFlhb5jg#WE;*K01TknC&WTk!O86ai@s-Y1d_z0S?^ zoIs#Ix#;U-=->GKi?S|`1bczrjwWOpf0+pV38}uEld;WF0PzA{3OL2hWiqGXyAK>m z|~rjf!~8v_*Rv8P4aTb?xae8aPrWJLsiZ_?N0^c6hC|PGGauIu&5G7&zkjX zb7B;wH<1Ogzv=)p%A*R{3NO|C+c^F3di=*+?KLNWC_0L#P73v8J&rWb5xG|*Qc_pP za4$!l{TY5fT;VNpWnJFicfGIHYT#rdtG@f)?^dVF!0qH;9^4hDc*0(RE9bI^I zQ_#J`-_=o;zbW{h*+OZBml_+Bz5^HJ#+r8C$y?82@I6g5*Nez`;qlJ`&*j0v2Z<_Ln-g)op3WsN ze91^cg&(FZZ(z8B(`z=Tcrkn?U*^|q`&o6TIEEkIPwGJ6-qX`l;jPBcvUInYm$WJ^ zfptU~lM5ZkD7c`>hKJyFF1(f8Z2A&BWx$iE&6tG`cn^Ka57}ra5bA#ahEoRF-2V3O zS7m&=&wM=xd<}TW5F>kC<6TY1^ep%R7Wk3p*(-Vg`HH5khdgzkwb(CvM4r1A>=#7t ztA{b~_|~#5by}uVLVs@z+XqP{Q7^{z1ON5&oPe&JY8dm$Trl1@|ih$CU`6jeR+R_y~9m1$@~_?i7mBrPV@kdI(TFKY!>iG(`*}f zcI?>Ex(_!qC;Z+zRr8l-3%8{0xYm8v=6&$aGdQ6tzmLO!z2|wH7K-7*zp5u?{`d*` zga6euth~du_M1Hg&Tzq=R(mu0m35*Q`{eJM&Jg_MEOD=c+4=KRSI$0WZS1^g0d<~a zmwA%u*5Pj{Kx9ol#D3{ep`(104uG6=Z~*N3vm~i3sXO@%{6`8vAXuLapv|z9?*Q>I z1V9y1MyNt08{38u3I;Gh+T`|~e=~sE^8mdKj2}`FcB)5142qdB63onoGw2PKfIXKm zQ>;U{24-v6Kne+j-VzUu?+}ycArNzKUd4IYET6qP+MI;D8juJw$yK-M@^$3DKz>!5 zg(SMB5u|&py$w+T-v2m?uHUXTtQW!?!gvhC)P^~l8%GF38{@v06Kb$@ir{pm4RAPc zV1I`|UVg~??1V;`i~YfX44)GK*3<^Ziuubqa~*FTgRlt^*C|psFU2h|f+t_5gpJr_gp+kL#E?LO-zXfSY$7!2&QJ#!iX#_$faaKGz4 z!*}NG`spagkFMS7;JvlYG{hxoC{J#`qjPiRor|FGO;hQ+(@RpgD3xaipT*NXn-J7I zYi0ToKZt{6=s`~GQh3DxEA8kOZCsTCe#w_h?(O*by9uXH8_Yxdb3x*I#ZSIk%wuQ7M!&=oImq=v(I1xHj#Kd@_m>A!imIw7y$j`EbA<9hZg{>h*mQ&Bdf;z&*o>sT5XrEt*L z!*omukE=MEeAUTB9E{vg`0!910x|wqrH8XNc}{Rga@uI@i4r!Dh=VO#({e~hfY9fo zPcD@c|N6I63~{IyaaI5CvvmOSnwngKNX(es>Xj`gnT4tnYn!@jZmgb z-_L&$qhxWqeSE8&KXoek zRD5?D-ygpIA|CV?q1k6q+T<@&o|XnT76#52GoOj99X&IUY7TqoWKo3ws1Wn~4;>xK zsi%`ZJnY8J8>w3mn#$k!Hr&1c<(Jig@hnR5#?Zz@_~h+41V+Q(ghQiuO48=;tz};5 zX-S+ATKA!Or!6;Q0BwuhVMvbWByv>@PtN7x7fFlSpD2J7bEG_Rdf$o6S=g1D5#c-5 z?fq&SNI9CKl!up1M|Mr*^TknOdv^3h4uxJ~%nA8__qTskBW2uoGS0}`w>x!4Zc}uK z#+-Ij=+6ZTw#sBc%m;R9y^2@w^K616=5Q7)X zV|eO!PHE|iGf7u~4e2^EJk|+Mzkl;y`gCgznAVSxBNQHd)z9u!P@jquaPEr8-q3*p zVd%*?a_mTz*OxB_Co)7i*aL7;D?-f_GRnyf8Fc)$GNRe=TUwD0mTP|Sqlhuab_~)xb z!9j)-BZvHvr|lHU`h4cJXfpGElFIi}sSrID0k9?&tGA_K8h#Il%oV*VnD*KmuLu95 zJV$;gklU4$!>N~s=1@`rI3w=$CCx7d><7c6<|aZosn znGhA0p4s2}m;a(%NccaPZ;HIW9fM|0_JSUUf5BBU3C-gD=4Ri|eg0Yb-Vc9RPMs0v9Naj8j{CX?=>dKX?sV{J}D)3#Y zQ(*49vc5}y`?qB>YkxF2kb=5P%7ahNX09Ea^g$7uyTvvjr``u4l&w39-%GYLgbsun$!oCD8S4>1~^k$((S|9<`T*DEYM z4~>v3uZDwH!zRcHX09ju$$C7=aInzyohDO#j#r{n_=+E*C5I>WxefBsJLv=rUEk3M z{6;(8W6f>ee%lAUxur3p$0`T&(1pR7Rj=(%H<1IiQ;d2-*RmheIZ)Fs^?n=~yMFjy z94cw67~Oq5cpk=5wuUF5_uf6b;+Rea{_Oqc$ixMy*1mK$?+=Y~62h5|uK!PZxz7xA z2hYKRPUNtq!2=I&I;}Og&*>iiO$O0o{8BS0+DGJG zYMP~pvew#$>*2O%fv>%T-wjT#!B0Jtj5J^0*{AkC#xdNj`aT*V6Tx$bpVp(>%3F!5wVy2lz&`gx_qiUNw_b1&MPs-g z%;E2uq~?L8br`O*2SV!2#k9$rjV zHMqW(h+H_0o|;3&yR1)IS)(V$IM|W{-jCM&4KF&i+1%BsRaNmR^FTkfKy&mG!(2p1 zfcL@R3tO`3?mhzt@N~%Sy$!d(&v)LZu;pYTy1uCq9a0T|Z?+BKs}2Az7mI`7Jgy8j z0E7^$SFb9E4j!r=HoyZMm42O6*dWEz0LmcLC|?8wq-Vs+)lw&$sDk6jZaRl@)RW0sgKWUxkSA|Mn$tOOAyz!2>KR=*iRGD5U^#&Z3-mx7Mx z3B173Z$$1ou(N(}0*_aRqA}L;Zt~-rvjdZIFE~8N$sBn8iOI z5ZHGJ&E8m_dwP0Oo%khjcg6U45$`VpWPXYxElqyzswl>Y5_3g#=HlP>3p1o(d9Ls6 zr|0_I_tt`um?t9T)g)BG8^h!!^<9T3rz`WrVEp(DgRp+Ifo{r-tp{OO* z#tpP!9`M3C4D<21xmc_5!zem%4dbo`-^eBz0aN+_S5|aPrB!OC;EWP;OBkzrp|?vB&VHg-#icxPTDrjN&nllE}G2A zHAP-0j>XB1U80@R+J&{1jCv5YB5dAaUfyZ=n=^;u5AV>5cM`-3Og+x&;L^0@-2cYW zN%Jlq=IgO6-KAoKTvMEKA5`|LkC%^sV8|h`7y~%)Yq6?O7 zjR$!w@Y2pDVeE@uB+@2)$ht(VY&w*@^1siCYkogXmGqIctpN*)`Q{W297%=u@$8H0 z*jtw-zdk3TaCK>v`_ZK-ER-mKwJGZN^y1ABb$xYt|HBW;%_!*Ovs#4RtgUe7r>wM= zXVRCXHEh_uy{t}e+N*#2%i2BSJMZZUf1`8-hTBiJA!>6eqaxk?C(%xoaPTkZWxt3GVu{_u5tsxCy{pR(x^025TEzxGv#_;yzy9s}N zRCXUa9KN(LM)F9yT%3xN57xcN&aBwxqQXS>Ku3&9C&m#ic;=neBoiMB0rwzbY^9gtVQ9I zPC(>1qPHi1^;czkoatYmO~KN@9slDrzi}f~_uY-pU)>=Yj)BF^$QwUTDtp|~>o^kE!wR(a?ra0NfFYpvJsx!f+7~~`A3bW_? z@5I|UQEsG29Gq-&bm#7L6G|>Qex%ca!hhTLtOT6K!58Qv`-C$&8 zcXXc{r_a=W)*M~ib|>{H^f8&g4=231KXPnqKBK?TFBWY}0n5}^7`>DByx~);(pF7T zU9xJ?q7=i5j}@(67z2+xMTp6)X6&?XIvWn}EvvUDzdQ18_m=JD zdZN5UnZhwL6F+j23vbbmLEe+q2c<4U#f1J-}QOx6ETol zP&1+Vn_qmH;)~DYbbeZPr)vG9==Bd%zaol9I(Q{LIO~_4;9T*&^?)t-`!}2eGr9*} z)ATOC(KGll^6U{uiRa&o9q}S5I?HzVquISP`twY@54;UL1mCRt5xB8a*f^dCUlaltdjCfBoxb3;HO-IR^z0cOGwB1NG2Jw* zujRbMFOgB+wKa4AmiV)XB6Guk$+xIEHFbya4OJ%Nm~F%L>^h?w ztW!h*8IB$}6UfxA$WnVoKdASFuj2L15O;72#!mP}~JutrM1XcG9K6*~o zZ!;Hz;ocm);Ap+pRB<@41ZS|fr(~2!JjDt*E<{;^HAlk(k>9!Auz#Jjoq_PK*aJD- z_MN$Up7&dqdSP_K<{S_$WWT{47CMgaUbNde#h=#7FV&qS^T zqJU%!UJQYO-yyECikQNvoTMP$hTH(UIj5?1WAZoPDY$?!8Wc9br5rR5804+UneSca z9e|24B3wqf5Fz3Elm??2!RCk9hlfXETqKk(8)z(EoP47^!zoTfE}M1rYI5sBAPU|H z^>@mSxO^uB@3n+weg669)#!oX2&je@#gV|c!k`!)=G&O(k;8{-&P#pq%l{xcX$c$# zkOq=j3q-}h%vm)|VJmWeL@jV=Fb12Fu_JqNH>dvwq-!w3DEwWGy%4c|dh4w>s{!p= zbEK%Y(HJRY1~+?xVIp#{Aq>n9abx%x6N0F74Ci~1lOVZ)18JKwn$}$2$LPTPgt1Ya zJj?Jbd*T{|2oDe)n!v+!{aa=D zd+8&(eEX(U6pnyOhX4*8wG^iFlZTf5@vMugpvZSeAp1@&3WbDbuSQXvO);t%JwkzI z7R)P$fB1e{wh|pDpE}Fla(9nq##9DWBe~M6s&a!1%n;H0;sF|S`IiZf@ zLU^4T2n>rl61so?Vv6gfGr{n~6updb^&&M7I27vMCF(#v|NKp>YnZh5Kj>gx^7{$R zZE3NlP2j;}aj;xUN=b|^-=mG^1DQjd2JigIzpD9wPD&Vjc-Ux^hMC}rc43TQIp@_# z3l5$6@^sx34g->5Z$G+A&R~q%HC8QYeGK>$31(}W-)l+bmG$GOX2fts}c77?|;8M$Q)LL zAH9{3{!jnQe<_2xhN5F_l*zH+)}g$I(KZuYrd;Cpcncvd=NtbKHXLiRRtjF4b?ywV ztPY=X9mQ%Y&V=!VPp`={=jMBcU{}IZtD}mdnrjrHb>g`==_d0+`|G0kK1-3uu5?*o za4b$6q~U}}O6^j~e=Nr5;{4tenTHR;@41woJi`eddFE8DI!6K*{9ZdGMv^>2k!0KB zB!8MUs_d+;&f++fIg044%f;vS3C=zNel8BukVt^xq*Cbjt*(c4AQN^67hFOp~S#Z*q|@0Eq`?<>7~Q!w@G zuj(3Vgic^S8by6kaML>mV^A#(e%Hvzz*k`|_%A9)4Ty_pbJ898Jo?dv^4cH$UPtZ+ zpB9EkNw*mZz1{frugjdQ#k|o7S-NEHy3!TBO||dGXA)5yyg zSp$4fM2o>N75JiGj=LyfRUxMn)xFCek7bQ{VC_(HGd$%$?y1h+I3ykXyz{{aFZIf_ zFU)oHtkF0Oj;BE4nNz0{VQ@PUTOIkMT{1&p?S}CATst+BXwErlAGUW}3V-IrGkYs7 z!Teqg0k?0@m}?i#ukoN}0j zCzFS-zKhOBp7{(u)6?vQd&qven%{ETr3@I}Ll#++pQc;+4!t=nqJ!W+=%&eK&!Q`s zAHBoe+gyI53*;Hc!qbNqCVehNfXCttT$lqDGG7hTtE2CPZAR}K ze_8j3tTAT?b>@iYfuFy@vhuAwpA7JP|2B8``0Uj||E0ehrmL? zKzQ~dPIHb2`^5g5if$#EO$4I7*^t9&`^R=&6nq!;$d0q$4Yu9gWI+d~=7iUMlMa9Y z@V`w8fE;(jh8s4(fMAdm0yIR&5O{Z5?wuSDo5{!|Y$1%zZv=}F0J1X7Y@~rHGHl#q zgKZRIB-B;u#ss{lleu(Ygy*)kE%Sv&XmrZjW zLWYb74<0JN_+`SI^L&N`#BmR#)BeN2)U68)s;4NQA#$G+)QomHqLdWZZ4N@;4Kr^= z1D7qsIR7ah7+lT4_fCUqcwnAsjR^5TPKD$LGRUpvpO2n+&nY+r1cnF(h*7}`e;bI! zKpdXQn8X~NMu4}^{F~tLx6zpJi>Xx9OrG?uRR7(#?_m0LE-#Ow;20bu1eN`3cw%q; zO$cHJo&yKG$2txB<#YSpLe$^}@3=LBIUE23_qA(1Q^WvaX}(R+dS-i%y|msrLn-={ z-tFTt!c-u>o700`aaKIZ{NT<+)~Qwl1E zcn<+?55UtfpQcb%g)h$pFV8pNN271dE)^Hj+HJZld%d?@O#Oph8@8q(|H>2qO#XKE zWhTb-+C5R2^0Q%ETEu;EHcIT>7#pkV37Geqw>5x20lQ-Tn(`tMBV&`}6}F5}kuq&P zU;Dbf?1fNvDW?l=b?$I;W3lgs{p zI31*%DLvs0mBu18mgkh{$=SX#m6U{8DKAkd;We6?NJ!~>|KlH)OBcRQm_{lrFYn3; z;6I&`&fl0Qi=5W)-G8ta(o&-UEmV3;G|k!*yQ{~1By*Y`7_QDb#?x4ggSp9}oVzUs zR(IMeo;{yX%A^6rTmK}As=5j0xHypxm(E;_!53pJO00P)E;euFg6w^IjVEON+<*Ry z)V?@e?)>cMWyjlZS7T#t@RN}ghLV%*yX9UYVmJfj(jGgS{Jj|6cP?HkyK*8a-)~EA zjJyXob841Umqcsy#}Ez!D3AKCmu>q}siA%&HV4C_}|HQ-YpltI$h!dPc`T$Ua9547_YoP>(bIy1d%iZIDbFz z9Lmq;@c(BqtTu$7phMx8*J7wG$@Nal%T5@GiT2_93FZ)4w$Lix69_7s4a-x zao?S+cQ*1gF68j2CFPA1ua~~md^mLYMEGM`iiT%&rEbN8tZh7azavp1&(arqtglm; zN~L*4>c%4@XM@{v|BZvG55UmHL*)O7`{vZgH_W5* zvCT=k7Xg&)Qc8FUS!*dN{Z}dFOW7nK~=( z6>S8+@vyU}J}nW1r8`ch^~d&?^EpYsAN;~smj>5d50{s`{#I&kTuJD5 zXyCVh_*>=TC!dz-;8TqZ3a*Jd;dncdB7C>bUo7MIo>u&xP0si9`V_d^yR){aWME#6 zaXuBfL-s5R{qB1A?J7eZKG=t;&}f8f*&5!0=c<;C-*C8%MZsSjc_xqCwf2(Sv+k$i zOKU?H_}Y^E+q-;@Zw!V9C@@B@Ih_;&E#2ou-mjyJ!lFH0DKZ$@1;?aAuHU%6+_;`p zz);it^sV0#XXfBwio$gz%Io3d8io${tb?p=hUBbht3*KDn+!h1I0!P8g>cKFlt(D?A>i)DV&cJ*0bH8)0e9Pm$X zKd5$uH82v*hu&bXD;;LeV1=iexA`@ild1}L(7Jb;E4a{~7>%CSbR74<5&Ppg_QYY8 zJ@&WvdQTf*=ihL#8lH)UR4{e?X1drUnne3!?=w8ld-3n~nZ2Z6w_(p*XCLi}xp;3I zJ~LM`#I^J}JQbd|>&(eD^zu3RADCIc)^oR#@@UMRJFniyxo(hqSwd&z5A~}=3`jGc z3jT6Ddk^@6BmUS%i>hOjnS+`d3~&E-UtMdSZC#9i&sMX>Q16U00nWii_=msN=+V&O zk`xc6mw}N}d=3pfsqSr?aDIC>8hDcTS%|s%sd|54)b_2z=R0`IF%N%^y*wmS$HnOF z?Wwo{hRtas60Ge_Z%qSuj7G+a} zjXTL{1Hp7cMN-8$hB0J7AQ&Kp!3mU&MJ=dzqqFcjB?@p_I^DtiV-3@9y# zM5=NRuudV-yoLrZ1`Kjd#%H811`lV4W&Zi4R6l?#MQ!MT@V|8xrpYD3=Zm>Il{=ARMN`fzam&@ZsmgIzRZVWx1_`#1( zmF@4oRa*?DD0OvK48^dSO6$JONB1OOz7v%*l4|<3ihgics?EKp{bk+m9i=M;o$f}F zop~6;H*ABKcV=FCkH?tZ_x9`M()ml}#ltw?V#si`ncJQ>kCyvseYkS>ma=bKZwjsT zWzuz;wJ6)QRg% z`NhIp$Dc;Q$W$K9jF#X3)Bmk}7H6hj;!o3g;X!D1OB}e5@}6(!q-H9(yEOv5J3{VO zPVu4+m3MNocQH!69`qZwZ7$cdf6Ftcm3wxS_rCX?L}aA++4}USU$(ULo%-Plz;QT{IBIo**z{7!iDIT^k$|<4mq@wbo%xfTmfA8U=wWs*Xd>*y1tWJ%JyM5Q< za2T$ql5l}6lg`qLrmCvHKJ({P9u7}s*m!^bU;C|d5G)E@@d!@HEm7vs{u9`>vc4es#7ik1UvolA;yY{1k1R z&AWBcFkVD!m>TIA;`M|4ryA&a{)3x|mWWLw+}-ewHs&+nb4prPElUXRy@c(~)@~m7 zy)aWUqqPsjv%pT+tdkwayy%5mhbAzwUTZR3Tf=LkBeZekXxbRYuqM07KD4kg&X&Rc zdvUa-QhE5vM7n;IIh4#qTm*Kn%Fp(k_Pa#~&>i3e$Nh$+;=ntp3-~@`6mORr;N1qL zUr{J&CwMdb$r)FSz1wB`;e+MsM`!AF_;-~uBOK3;H2VXZ@=?)QZ=rZk&mvH1Fs*c4u3Tz_MALYF8%l?mW1mb~JbX|N8SXl@2RTF%=Pnv!l@gf&1)V|9zQx*2%j^ z|7vdx#Ryf?<@N6;wIaCASu=bw270!L-UaU7;~n5v<$CZ(2c+q=gxmXr4-!FhuZ$-x zZT1ysuj|}H1~TyJAU)A3Jj1{z7^n= z?gM6?#W3^^hhILU1GMxmF!g=YOVBxIhvyi+r>mf8#t|K9?XlfudQ}SGCCY6!ydqze z?ig1~BJbAh=_&W(upG%A?~guv<;yS9ns-|n3=S>IUfoP<$!$p$>5r4S`{1G4LUAb0 z>eVwb(69E@d4L06;sD8d!JzSoI;s4}e8>&!HeYlP2f)Cb=|+rbu(2lBlP}=W^jv!i zj_uh^Z*mRe6-+#<>2UV2-McIY56e?C1-}@(^Qh{%4sFcCoIT4PG~KT0u5JGC)|}vj zXSxq>Gpq*;;HKzmI&^Pu2WQLy4Vahj>2eMCZ{N8cJW5Bd7@iDpgR_NR*!I(BSzc%4 z4|stn;5PV(A~YvBQQ?vAjvPJ`<30GFbUkYt%znEDe`0^o5!q|z=~?ilyL)T7a`j5J zRoD?~rM0?ioDpzW>NDDqR#y*20|zJYcrIAlTa$(RWP^EgQZW8|dU}G3owl>~_*x2^ zigYspdk2 z9J5#E*YL=`z(bC1ILP53((#*g0A$Xo0dV3Qt^sf-VX{%cgm*LCEqrT;P>~`-XsuHj z;nR#$NW~K>j1h9w@RSe?qg|1{>T!><1(^(p4akV06E2drTrUN%?V)Jc7KsoC}CdiyZ4UUkWFLYEcA~6i8(LoE6^3 z%Tx&>^D{RsJ_rqr4iOQsjOfPjycba-;%3-2W`v1QR1h-;0`VL2A{=XJ9zgFhJkR?$ zNECe}Kzue6c&^&JBSJIY?hO$fX)!gP6Hs#jTTIRzDR55td}e=6o;+FM(U>Zx38t?O zFhKn9%sk8$V`vPa&Drw}>+?MrV7LUGd%@5BeyooWgpaDU58jHG`S#tiBudM46oDN% zg#vR0$3}A!vT$9B)I}jOKMckE_4GD3ZHlJzyDuFAg0N*Qp@c_&^nSVYj~`c~tDY{r zgfn3UX69`D)@mIXguSyz4aV@$ya{acv`?6-`{0W~K>%9=&AG1PXV%JDWQ}cjzWeNn z{j;}V1s2|eS-Bq`xyHP{h*H+zI-9)E$z^lJxR>#B*UO6=|K!=^tu^<>hqjj0oAbPc z5RY65f@X@{I2ksPA@Uoxk zd5jLEuko@~Nx6szIHxxcrNQK9I{EV(6BV#H#Ryk-Z>T-i2NI^aVMz?d!H%QMzQK>x zy(#iDonG#HqRb=|cl1^V#^5m>oG$B=7e18yxOf$&5;`yB3r@TqyuI@*IonqslpQAy zmY%hn%at?dtAYo{%Tn!oY<^Vv%yD6g1I=(+goG%iJ-d3#sq?23DbZaPr&a<7)VhR{ zGZf+0iqOwQ3TX|+kvg0D2|`NkGcWt=?e zjDnv+PDufHFqqut@RTPHvQK$T@7~@RY7Z+7D)jc?i_2yA58o*R@v<+AGqo$YwRBmW zg;BPHDCue62{{CNd}bi<+8e?7k3aosh%ATpiA1pKu$#W zRl{jGj>Oe5x(6>_%>1JeMyZ?*?TyDNu=j%x%aY*z#iW=x@rHYk1B1gSUaQerBT*b? z@;;{(i}OCG&3If%?(^Iz98RvEP9<7oONyr@8sGaP{sz>nnQk>Ev z3czDH2M-VOZul@ATKN7S{ZaYFU;IV(Jf}@-*Odps{Y~L7bcDyzw-%@98kwNB#GLSQ zyoJv5jWRtRSaHrtkvx`@&^yspIJi`@9?u*C%&HuV zgt!?#F%_Er@OOVuKK;wTtMDC7YTd)f_saf1{=ITN2O=NDu&4OLcYOTxuYQ%5!P{$; zh^QU&Ya#E;^Bzj|zx?Art~%PX(Bf=xzAsTOJL0@JoAoPh<^=shK2uO@G;5m3J@%GN zrcaPz3@h?;WN{)4!nY2;@n($#7>L37=)(E5?n_wwrRb~a1YpQPuAMIO_aFS*e_cL_ zQ{_P-WoFYRa9bRglZiT$B8U&cRr}kFb96GDJy;OAH*ohx-SYzn4kryNxDb%pyQ(AE zx6G6AL6*a1x{URpPkJC(?zii#!CJ^@aB`qScQjm6aW?bm$-Y^;c{CaB8Zz8x_S~Gk z(`e2FIPAT?M>FuM&DA@7=C?Vbk)~(Vl$|{>dQ*>QWF(Hr>>JpO$I(BW)|gKc)%GO# z;dAvOZbaW(92>xT>9Ql4%YvThq<{HQjdHv5b!>ys0y(!LHGizxJeuBMzT`0@9jvNB zT36E1d3@gB)%Zx$7hUFAewsey8TOGb1}DL#-S_gbzi}p5vw3@d8{pK&R1Ow;4($z@ zr-FT)M;qc?H9va?X68n>qxZk6i}{Q`WIyqz_DpsIyv3LB4|r4gS@ua3Z(m;y{Gz*< zkMBIgTKss1`T8EetGYlATSW)kL+>JU%mpvVBkMSrXMnLbf1+o!@~b*%_OIC*^d7QG z@l#>_4lLJ(=a`$l=?M!nTTIy55+2TnR1X1^UfdaS-%q@NTkIvKo1 z=j=KWo@pSOgD%-7#!13L`dw2x(v z(yx7Ab?7*`JkuJ$gX}fn5?##wO^#>*Xs^*9XEeHkXYK<}&$Iqzp|v?1SJvlz6aUHK z*7&@YZ|wcEq@+aq`ew#t8~|~bW}_Ab+2U=@W-;z<0sz_&ZRiZ`85sWJ`CA{3r&|fa@NN%TGfl%#9PlXP7Pk*MblMssY&%G9-TSLZQJRPlW2LqbmXo(%TT2 z?;c3Wkk3t(;0fx+96e7MtWy>z`H*U9gqSrpVr|d2xr`I}C_GB9*L-J{?Q z=D>g!cD6H$Qh$^fb7HXijez&=-B*zi!c&F}gqdmA^>bbrkd5*nq_KwDBtIIg5s|TN zYl;DdP!JksU4>oB|nV+4Emn5SnUM)1M#{F|@?Z!jf*ysIz9H~3&= zhI{TuL2iuOeV%PTn5fn+h}ZXiI!vKcSHOHYb?lqJ;jF&wjwmLQ%Q>?sd08=79-aEE z?9OTDbe^r95jgk%__K20dv8|-=G4Fc&t*{zDJQO*BTPo~ycbc(R|f7i^lJ5za^TI^ zs&M@J)R%Q__QSqelXb#LaP~RetN5Aq!2^3B8sy6_(}pd$4?aGFg9bQSBRC3MV_aKH z+cWSW7&u+vGnhz0kssLJ={*f!JQsY?kAeC3_P&e=h*2=JJx;a-b83#>qLB!jC`Sf3 z)|OhEQss6$ibm!*8-c!HGM@8P9k(au>RtAs;#|U&=O={S3AwPaYd`*JLJE_2cJXR` zW_vDJQ6R0MR(pP_h+weZJM#ExSrA_TBt^_p?JTj}`NvEm8QwZs?xg_U;~Uq@^CeteLI(&igpL#zDz3zlg zK6>^zVZTYsSe&$+R7t;?)BGvV$T~fH-r8l!c|DoX#u)$4;z&z-D7~WX@%Ev+b#+4|;ak7LS zbuVEU2SLk%;3pipmlJnU0RvG=jvP-NkF4)W91|Q5GYR=$y1yqm^n1#cYgelgykPG9 z@`LYwKP?Yq(8dVfx<55K5~4j3V{hfUq#@+A`Tp6{)!2Fz1@uYy-`*%7_}AdzK;?rs zbE+6dS8EIiH-zK2@kJ?^4_H9EbCsI zlj|r3;YK^70BJd-AW`>AC)ldc-m^qw?M@UG-ne|nKb@?24+j7qvnq6R?H9kS9RW53 zKlQK{1;lYHRYiXE(}a?bWshqMrG<0L!{7hCa`D%{DuaQ=izpjcKl`+- z$;pEPWzW-PW8uP_f-Xrh*6Df4sSPiWQi5mQ_)mXb)*e5QHjCNMui~VgM z?|yMoFEpG(a4k6#I&vZ6b+qDg?)pPD*}K~PsdP*smX0hTdNDeN$`7tE9V5d z<=mqz!l&xglqL{GPZjdTQ4$wrzD=IFe#rBmjix)vq0;}9ft6ICmveC4-0+_LM`N(Y zsq`YwijCVl-DL2I$(hNjKu(V21TcJZ&b*vT&WVgmfxjI|!Pp!po|E>e$Og3rRzzlv zgx4PoFBAo1&TFC=4+lmQp&yYtcY_XC)U#|m(!xHlcqTy-aZxGWre)p@Qazy>UF$i zB=`~4Y60g)^o_|lcbBBi=;g>H2O+M#`R{*Rc6|5UngV(KMkjoo9-wgFSoqb3=uPCC zf5Q)Qh=Fq>I?ZHgQYgPD%+5*vqN=m?$AKhmhB0>`M*HR9rG38h+2?VVCdw+${ouEM z6yrsNRf>3R?Jjpi?<1T?3j7UqWGM#>$IJ5G_2uk8d>W@g@Mtu;VdRA(jrJO!FgPs8 zA9zUKl4l&5V|O2y&B24^kt^$BoZLwiKZR{q_ec0z3{+@(lZ>_Lsf3 zhvvxWHg7uq`3sSm84fua|Mt}LwVZu*9UO$7#pzdh8$p_(^M+I(@PG$!h&|UAUEFAf zxwX*|$W3r>^#X+NOM$ayYcXebj(^vP?_6&$%v*$x&#e*c*JmAgfJmVZzfV+KSkd}9uPnfnU& zbaEip200-+1cb;ots;Mbg@KC#FnEv=m{4xUFQGg?0{u6HlJ7(dAPB_Rj1oE4HlDKO zUW5!$gsZjT9`E%$n+Eab_@AA6IUt;kL39YfhGT#f6dP{yyx->?vglS}{VS!Vw%o42aPE24t7#WzFDXePHZf zUM&p38V&Gr-O6=q%BBOmqEufm<2n7`m?A*eFLjJLMy$EG);hhHBLvfF!pvS!JbVY2 z;DAsa?_|t?i{UzW;5vh_vmQ*)b=GO$!N9W-B0NN>%{caK@2|`*&uE`>ILt&~r>a0I zjt6hk+HNAb%|BQyoA=iGIfe{>V@$5GubyY`y%#*}r8#*XSYwWr$p!q&Pwpzc!L=1* zbIRS1&sB#DM!Ix)S6Q=vdwJ~-eo!7J#C0nD?8}od{Lv1L_Vo1By$5sn^CJ5*l#r^W z$C6f&yy@ZFIT=eX@rE@Uib7*ez}x$Voo@Wy!X$A*%B_!74_zIV7hiZQ1m z@znJ=XTto=?P(0FlHT7pK06m@QG`M8eM%v(gpN8PoVzShEDOV9^6GRKECXk*q>IFG zg|~g%mpu9TYnG?@U!qSQJu64{9_Uo(kMQb`@jjKx>{BB-1sSA-&eRj5i`l;?dGE$l znO6)E|Cu;*yX@-8iGM=zj1y@!`18N}dD=9ls_oOvCvzK0g>omlJpYTLoZJ5$QJn0B z%GWQZ(=P7K6SXbc`OiNq@BPm2q^fp!%|v?1N1>dF!|?gpv%z&at^GBG_E8MZH-77b zbUsS4o)j!|qBwl~ z6IWC7A^Wb-n(Yj2j*r@p9oC%TGbcr>)6klyn}X(5|u3U~I|bZB8L z#;{bjT0uDcx<7^k{FoCO8IEBB14nMBs9o-Tkz#tA^8S5CQ+P0IUX(rAxo1}l=GEo% zFFq~1g6o^YpRRv-#zA#?5uP*=x`WI8f%RzSI-Gsj{?6OMjjpP^PvzPF`rrP~wX*k# z@4R367&;w^B69UF|FZnvpZ;mN5{K2%gmvEue_7m>(E9M5l}P~^kCW<798v35uE`pD zt3sv-;e$ET6`rE>?&djrlY_l|^~Q4T)Yn-}jFSag0CJE=E(B-s&e1qD(9)`nN%II_ ze%#-|v2`2Pm5UcHR{nz5uHTyq>^oC@GY-^=6tTpc$U?lNrL*8uj1dlxJ6WHTbfNC} zpx+E2G)+E`TX-%0Mft)5oQiA9=Wlb<>4pqolt0Z0Ar3jBVhB6gPaYDsH(C4Cox>v3Xjb6UE^;ynQ~9Q|~z| z#nn+-^)Kf{dOjS-P`boWT)}YVnw90!*`ylH5#876(1RFsMR=0=?mD!u+<2TE)iF{-Hj|X>pg7XV1|L!Vx<49VBUUJ~DD!-4s{dQTC z-+1oa!1YP=4UU9?|L50b#kJkv8q1N-BD@CQ{s*cV2^ zyuc1lF3tKz^V~ISQmFUZ!|K$A2kVaPO<~>M@+kYaetlB&GGE5WfgdDNBe;uSQ>3T9 z2<-=VAN}m-Wy8rgDqPK@rZ8m>QFJDfj;7CrRZxR*ip$7+?R*-=wwW^K>ye zRArbw-X4BM*Aa~~66eRtz-{;LJ$3)_DEmJg{Ym7&qRfBz^tqINNfEd3q_ON#Qvc)V zNCCU#{y(`JxsYMraPHMX=F&I(CV$9hDWFG_0(dF>Yjj==oj7UlF@`04qRUjr?Mplb3xlloW6*WL9zI&LL4KR#{TN|%0D2t$-V?cNj^5+> z)i?`}qj%CV(1_35fa~O~wfUT$N zck`Q0WpAxVda}8;y|%wX(*0Wmu>pU;%Nj)uI~26H-t8H1qpK?gt~2Kik+qNF6g+e| z4$Hu-j?gE)L`u({IHyBCb%4Fk{iwK4AJlS|t-%>P6=$sXs*7f<%d@S&!OUmwu}_R= zgKfrf5GIy(e~DO)oqNon9V-zun+At5f|BQO?tjsF+nXlnl&6^93 zaEZgFF)0iZz7P_x4xjr0H|xb93AmmJKWlc6@6EBT9ZX#ZpD0J>W6MDImUoly zvVFVb6p6CDG)|9%=PJHveuj6Or#XTP#nMTjHTjIvVBKI1{?=g)ui~5iLq9%)yN!`~ zK4H*?HKPZgHF$U?M&0J)-yg(NPvAWWzHL0vTP6=~sO{xu0+)NIlMnyAWS## z9p&Em)ADR!F!&ZGezW6b@?MPCx?GFNGY${@;Ri8b`pb^Zad4$ez??Y?6S|(lO;KE2 z4<6Rr1mFA>i-V&bqlCb=MtBHE!N=Y;X0O-zlbj~3PkO*igp?5HzK?%hCYGlK&AQcP zYaCVmqtB8akhGT#Ys+Y^9lrgj8vjlP=cJ|IbS(G1Z@*R**2x&!OIGHcd6xI|rd`^D z=TB37a7#Im$dHE@u19n1;JVYP(HJGE1{B3V&aBU_RznIL!29j@-z#T6`Yipsb8^+4 zJiRm5YiRntD2GlaUo1~l$H{|bBF4FD{E80Zad_aWwW0rKIXR6IJ$W^IswHCD88TKG zmACH2IrUnqAz!;+tBq3>D}6=YE=^&;k)$Cg`Ub}DfA{^ghReKj9y5?4m^UBZD+dxq z^2Mj863U)dh!NxjJv@6DKD;3Y`ETVU?c6$z`n$jVJ6YdU z6x%0(OeqNSlpYNRdyv&Ag32ojM9!&AI&-QU{_V!5x z=wN8_jf4-QDf2z|w||>fOFMI2Di7n0Q3`f^_^l4k2Co0p|M92QkQ5TH>i+W383)wN z^PI?}dxP-4p-VAb<5*J}8C{}<#lelS7&)1Ic_TOvpU_T!q62304xI!<0USMYw2Z{? z7|Chi-tg%|CytZ_>qEoyCj*Dnb4eGG=ZOGY7MY+$<@V6~vYal!`+K2@nb76B@MZ7R zJ>mF=A68?A^UxY^Uhl}E9f8F^{`ki=_y5Y3%QeS&B(hKOx0%SHE7z{1LjIZ#Ze=~| zcJGV>B#LMXMQTHrdd2lLnZxIL(lDq*lR3qG@b$Se5~a;4>fPISO8@nnW#L!~7fz=0 zM)>q(deSQZi0<@spN-Rt<7hl5|58fYu-8sf8y_A``2U7|X?54v7p=X+d&p4qX`m`gsbIGCB=&Tp5|YE(JA5B4!T1 zexi1#IQP}p;ja!?V({f%c;i6c`&NwgyNL`F2_SWZelb7uS7Yhfo!ezz{o z$=0nEmXAYM!tbB2Nzusgc>2UpV2rn9F{Lj&XnSaEF#lc~SblPvn`%-K#W(roITp?sf6u8E}N zJWm>!x)h$}2hKPAW!!)deUy`)9^`xP@tN!B2R?Hz+MySFUz73lDf93w_|b-WnY(>N zPjn(WIQ^m>4&XhERqt?p!+-0uPGfFl@AFjpSKN1I+0wE)u9>U#I$#S~6W4UORB(nOj){?%t?=WEB~I7puQRO(E`VL2IoVIKCX=|bMi z0ZoRzx+e76{*4#VC+I6a_ZtiNE)0DDsHNqt)+D2Ol$u&o}QeACUzP zCVemBwS}(37xSQB!$;3`(7Geh2<*OqE1gu5IvrkXt!k)%D~IOM+>2kb|Ja6{zjfp$ z&$9-&T-O`i_c#5J5#LVj!G&FDUljIaV0Q}gkSZ{07?x36HyXxDi}3^vPtpc%6o^T7!n0^$M#N<5lHMa9+AE%1_;)_ zF*gKZb8H+$hx`TrLIQwtDh|oD+iT$|irNehr;l|QqkDLyY?eF`&!l`B3_D63!#F$i z8{`lMqi6+W;GlrePV*55rJZLnvmAPi{gJfjWFl>qU%0j6-EU5n_NKr%mb$NVUT zga+L4Sz}h7)f7&jTTdnImuvAJYr=%>sXg$F>QU}aE2J2sbCbV*FV(CU#dvxW!(uSF z+!KRkFsCn@vtRvLkJFhmXHF-!C?|`UcpP5MnYA=HJy0VFVl2kMzV~#n3?}4yW+c0ui zjz_g#Qm;|0(w;0?)|DLJgt>Oj3!X$#`si$VF+Q8V&X+%RhJVtFm~{<}$qiuUJ`W zb(pf*MvT_sm~AsrBo6F8Sh^O(&`6HFu_?yEmN+jaR^@ahxb*&azF*FNdA5GH|4`Bq z?uXXL;vkFjpl4eu0bjmZmZuKFWE5T1#+RmT+tkZ+0j>Ll94nR=>$EJ~p4M#P;iKV! z_?46+{P5b9%cVPtm?$A3#PaNK#hLOnYn)2Tk0M-h=s9^WUA$E3_njCgH$M7xtqiU6 z!IR`g?_9sF^!@C!6xy38M^C;{ofeE9Q8j0h7tF}UNA6s?QjP_0o@T#pg&#hM@o_kc zcYgWH(iOP_Pwqt?p>;-Ke@p&2?w_f!+a;Gl)b);sOLnkOY`hH`#HzXQnkH)$W!p?`o@5el_JP ze*k?GzjBpd*yUQw(%1?mX=gM&(~;dIyO|RJ5}C+3XFt!mJT2~)U#j=aumRlr59j>O zFQ;S4*&d40ru+sTRSqwaR&+Yb6Iyt_JYp5T&`k-!t>69@SP>xuHaWROu)xKcLkRW7 z(NLJ7E|NxcK4+Hb+a|a>HP9a>X+~%t0%eo6hZFG5p0j6gfZUG93n+ZCXaE2}07*na zR1UJXkLb2;RJ;tiA>1BdL>N8O2s(iN>Tp^YLo=~KQegoGT84fKIbrnE->K=~+^P(@ zu<@!~oLl>OVPa%FtkP%U5OU5=@bX}PE;Hw=*WQZC(^;GuV>o(>4$&NuXDs2cXl&uk zbE3Cp;EQ}Po(6yof9B%ZFiUECCCa-;)R}Q$sfa24@^ci9ut2nh6c*$=&M&fPqEdv+ zmp7>#Nx$j<_6$&7*dyT4!$)y1<-0l`y~e#$kMMhG+HwKqj|#5JrQgd7lPneS3yKRv zZWD?#@Gq$3h|?S*ZW!P44@XM%_Z_}l=S42^(F{G)`IG))Nr(8Sqag#26rWTy6Hiih z$g?Nrr=cfmt!r?=l4ayDGIT(8P1o7eL^tVWL1dYp+u3HL#YN%Vm2+X}`49;e%!&Wo zg?^l9VGi}_F%^bqC?^XEimZWG$I0Zm_vm3f(V`vxG=A?vsO27EvU=xU=)8U{JR}>S z1?5_}I@hQdVcgjOFb_WD`n`S|oy$`;)I}Om*kAtBZ$cee1M12n;9o^eE$6i35Y?Ci z-*miDml1MM%!T(F&#VM@TiP?6?f!kJfDf3a>nRCKvz!nzG!%}X>IoZ@@Ezo3zNL@r z7@-IBQ(hT$&gL@YcfEj7rz(YK1bS7=kRx*;hg1j{_Zud&2>31ovHgcqqfR&LItH>?L_(2 z$&`bhLb4y98N#_6H{x8Uz>f|1>^^Ix1UceH0qdFi{8q@^xEkq+W)PujmyYeT>tPC- z@HwXGtH-(ar2o0Dq@yWU)rq7}M_QBjI4lnoRzAo1i*v3|eNmq7@9Kr>p#B|Y2+vFJ zQ~!~M{5+L+m_;E>gq`pbZo<@gIGlqSP9^k=vggYtGH011i0#kfb@DaeD=&1f{r%11 zXF52NZZ7QIbNAS5oln&NShMKX*@~ zZIFFEpJ$!wZ|eWO_)Uy7a{DbXlHB=3$Q&vmro@Y+DSgl9i(DeH^GVDy83sBLY#wIB-}|G}03^^moQ8;^uvef; z$SSDrzMCoXyRK}C&3xQsJxL-%sudA&qp(%sfU%0`$=hbug9?#IC3CSUR!oQC4xOwUwG$rs7TAVP=b5E@e|9j5b4pbW3Bu0(H@4j11g!N@4|VkH5Ul(HlkWCG5? z;o5|i>-L{;Oa`03C#EOU$Ye5+p~w^+=@}|REp$a+X3t|D=~gxk-F>(AJY8$VUE(nN z!nvp6z6*1SSpno8CWnL9c%KCCyksQK!*%+%MCR}_Bj*Z1*CQ@CBxv!@clc~ajBfC~ za5n`t4et|wWqKNtd$XLI`i#b5c)!=JY33~JHVlGiw{C|r7?F77T=)5jb{Gy3VHU>L z8cmTF%u8{hbH=sn{oU80;9NKM7RN~uadyb?RB{u%-6w^aIGY5A@KV^hHwoU(-?`tt zdpE)*3Jad+zId&B>K-eIeqi=|p9HM}QDJUGz@Y-++7-6K%J;bMMi)=~;$51XZH4?5 z>Jwj57tQ+Yq%V9|!N=VSjw2gEakRdEaGJg9i4Fple22~p=d0J$=Y9CAKMOa%{X-Z< zQ9j+l8QD)%?hrf-jRxoBT9XhhYp$lD999m;=53XNBSh%;V9<8PcZe76fx=oi__rx! zHnuA(DhVw$q=%8Bzdc1~Z;azr>J;~hq~{RPs%2i^d~=i1j7`q1z7k&1h%g)_TY=~e z-K@feGnd1Yo8QOvx{f7`xrS1ZX&onQK+^>nnqi5iRR=|3>GN;G6pCdv#-MZ}t=59G^19g< z1EC%sW+z~2q80qMzFDPghM)3)0UV-@C<5|^0UU7|qJ$IBZ$1W`b>4PH*U|IN$3G+G zc`iOj;atc2+=J_66~xHKE>SZSZ4fO~L&s)ONIT!%xgBwE8XWW;8b%d-K8JC9{q5^v z;PcNzEo)oigonD`OepGTpvfbr*3?yVUk`YEC{&{moV)&ZEb%Z6dK)KV2Pu~t>kn{t zRFL+p+$ckKeNRolo!RAkHXB;Tc(H!JwTto#Ph zEH#5a@_Dn*JT6zBCjR<9`G>qFMv;)4@*AB(DsKLi&&wCZZ|~Eva_`(Lm1TM59DBXD z1fM5DX@q8rNbbRQR%Xlh)dS>Z@_zY)_^1&npODAOH{?zJjJy*4U~FP6mL|2KyUgMU z7VqTAWjIsvD~idaAyTUGZ)p*-z--6~oRSAs$aiSEo06W%XD_2+H_W-_BQ%q9RDmNl z{~IUzDGXyVbo>TC05WWya)Gr9YO>+ACwp-0vQI@sr*#C4e(^=ft*Z$Y$J(=zSEEhf zyQ!&>#xThDS+7kl^UzbG{D+QpOkaBMz3}WezX@9yM)fDVBY&JGV*r3tu0VP=ys{1& zs{jvex_Ja0#3-Ng!2Qtxcfaa&LVx>hr~xhw+;@iO&af|g;8G#He~@Ud%J-HHPmk4y zd~jBW%I!}-)uSKAaOjl)>nU`E8F0Os0L8K6q{@#mXXbA0f9BGqxDU!M*Hw-a)uCSV zHb-t20gC~QWgQdMtxaK%o-|cWG|^>W+D>(bE>2e1=Ce(XSyX@2F>7Yi(2Kz++iKd$ zW`p+C%}$-}4Kq60D6^t|B<$rG%m!vl=tbIV`~PJLfOMpBDK5%Obi#{U;-@;UIHW$H zY%Hs-4y7$Lm?JaDz9{?132|1PCCOY3SLL^|PF(dnaZtP$AB4Sf+IPAaNf+~d@{44+ zIu{)Tex^)!2s`P6n~JiIUM_l`#ZZh@=biALkLVT0As0&Y%{nG`ljuF+& zqflE2fd5D%HUa!^aSA}5$|IO%YLkYv2qU736n3%K3u67ghLi{;@%p<*2D-UXAx7Am zvgQVwZjlg3WR_4==p-bEh*pe8*NA%@Y>rVJuXFeuJ;D;I8=z-68IsQF5cBoy%v@yfIwNDLJ8*JPM6V^!F)}71I85L1{d%Ia ze`lGDuo=V~p0WY_PUgm~kw`TzL`>i3Xm8J;R82;s$@e=}?;=`W# zUWWoy`1*c_FpyX$P)g0Pcz}{6Z2ep~ox`ATjxuTgxsU6lxV2EPgxX4aad8+N84lY| zIcxj<8xh9BbNlXCIP)KV8HI%J(dcjkD^Q+}zyx%d6}2_dM}pL^QkY(CNeI-vH?(qE zhILo3hwE~C3nzy^6)wU|!6=@3pTo7-+hGV?lNN=) zI3f+nc!h)e?Y|#JBWKv|qX<&xw>yI;dl}fi_ST*tm36)x`mBdJ!jun}aJ<<3CZ!-4 z0Yr)1C-=qq7?mkIToH=eITCJ#RIz+gp>|N5Z$1G`Ao}a!{w6`5_As|NKa{mLW8jj? zMcRHPM(i4f&^{@&hfyx18-_e0_B59n_F4}XX=6BnhCBIeL|ygkf3!@0v2UnL#(5E(D> z!dD1>703Lp`f%fqe;V%68N2<&aSULrZ$>52f`+b4c=C5�Go;SQ$-8G#m=Kh^X~} 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

    A%Tg{^^8T@gHY(mhoj}}Q}g8O7h!Lh(97by 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 z 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 + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + Barotrauma + CFBundleIconFile + barotrauma + CFBundleIdentifier + com.FakeFish.Barotrauma + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + Barotrauma + CFBundlePackageType + APPL + CFBundleShortVersionString + {short_version_string} + CFBundleSignature + FONV + CFBundleVersion + {version} + LSApplicationCategoryType + public.app-category.games + LSMinimumSystemVersion + 10.13 + NSMicrophoneUsageDescription + Needs microphone access for in-game communications + NSHumanReadableCopyright + Copyright © 2017-{current_year} FakeFish. All rights reserved. + NSPrincipalClass + NSApplication + + diff --git a/Deploy/DeployAll/macSkeleton/Barotrauma.app/installscript.vdf b/Deploy/DeployAll/macSkeleton/Barotrauma.app/installscript.vdf new file mode 100644 index 000000000..e9e1eccb6 --- /dev/null +++ b/Deploy/DeployAll/macSkeleton/Barotrauma.app/installscript.vdf @@ -0,0 +1,31 @@ +"InstallScript" +{ + "version" "2" + "chmod" + { + "0" + { + "file" "Barotrauma.app/Contents/MacOS/Barotrauma" + "mode" "755" + } + "1" + { + "file" "Barotrauma.app/Contents/MacOS/Barotrauma.bin.osx" + "mode" "755" + } + "2" + { + "file" "Barotrauma.app/Contents/MacOS/DedicatedServer" + "mode" "755" + } + "3" + { + "file" "Barotrauma.app/Contents/MacOS/DedicatedServer.bin.osx" + "mode" "755" + } + } +} +"kvsignatures" +{ + "InstallScript" "2d0e72227a48d72bfda9810a7f5478af6670d8653f25a92974ceaa4d2e1009e0f5e8a5312a092a64790635d574b0adb84a265ee89df71470d7e8e15c915420da429eb4a15d4ee68840d19c8928a970ab25b8bbfb13f22ce3a061bbb604a94f92299d6e94d7543f3f7bd51170a4c31b3f9808f2f98e85ffd4bd074e88da44491e" +} diff --git a/Deploy/Linux/DeployLinux.sh b/Deploy/Linux/DeployLinux.sh deleted file mode 100755 index c9f7e721b..000000000 --- a/Deploy/Linux/DeployLinux.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/sh - -cd ../../Barotrauma - -cd BarotraumaClient -dotnet publish LinuxClient.csproj -c Release -clp:"ErrorsOnly;Summary" --self-contained -r linux-x64 \/p:Platform="x64" - -cd .. -cd BarotraumaServer -dotnet publish LinuxServer.csproj -c Release -clp:"ErrorsOnly;Summary" --self-contained -r linux-x64 \/p:Platform="x64" diff --git a/Deploy/Linux/DeployLinuxServer.sh b/Deploy/Linux/DeployLinuxServer.sh deleted file mode 100644 index 4d05a7814..000000000 --- a/Deploy/Linux/DeployLinuxServer.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh - -cd ../../Barotrauma/BarotraumaServer -dotnet publish LinuxServer.csproj -c Release --self-contained -r linux-x64 \/p:Platform="x64" diff --git a/Deploy/Linux/DeployLinuxUnstable.sh b/Deploy/Linux/DeployLinuxUnstable.sh deleted file mode 100755 index 015ae2cc7..000000000 --- a/Deploy/Linux/DeployLinuxUnstable.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/sh - -cd ../../Barotrauma - -cd BarotraumaClient -dotnet publish LinuxClient.csproj -c Unstable -clp:"ErrorsOnly;Summary" --self-contained -r linux-x64 \/p:Platform="x64" - -cd .. -cd BarotraumaServer -dotnet publish LinuxServer.csproj -c Unstable -clp:"ErrorsOnly;Summary" --self-contained -r linux-x64 \/p:Platform="x64" diff --git a/Deploy/Linux/DeployMac.sh b/Deploy/Linux/DeployMac.sh deleted file mode 100644 index 0bde38073..000000000 --- a/Deploy/Linux/DeployMac.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/sh - -cd ../../Barotrauma - -cd BarotraumaClient -dotnet publish MacClient.csproj -c Release -clp:"ErrorsOnly;Summary" --self-contained -r osx-x64 \/p:Platform="x64" - -cd .. -cd BarotraumaServer -dotnet publish MacServer.csproj -c Release -clp:"ErrorsOnly;Summary" --self-contained -r osx-x64 \/p:Platform="x64" diff --git a/Deploy/Linux/DeployMacUnstable.sh b/Deploy/Linux/DeployMacUnstable.sh deleted file mode 100644 index ecccfe3fc..000000000 --- a/Deploy/Linux/DeployMacUnstable.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/sh - -cd ../../Barotrauma - -cd BarotraumaClient -dotnet publish MacClient.csproj -c Unstable -clp:"ErrorsOnly;Summary" --self-contained -r osx-x64 \/p:Platform="x64" - -cd .. -cd BarotraumaServer -dotnet publish MacServer.csproj -c Unstable -clp:"ErrorsOnly;Summary" --self-contained -r osx-x64 \/p:Platform="x64" diff --git a/Deploy/Linux/DeployWindows.sh b/Deploy/Linux/DeployWindows.sh deleted file mode 100644 index 527841ed4..000000000 --- a/Deploy/Linux/DeployWindows.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/sh - -cd ../../Barotrauma - -cd BarotraumaClient -dotnet publish WindowsClient.csproj -c Release -clp:"ErrorsOnly;Summary" --self-contained -r win-x64 \/p:Platform="x64" - -cd .. -cd BarotraumaServer -dotnet publish WindowsServer.csproj -c Release -clp:"ErrorsOnly;Summary" --self-contained -r win-x64 \/p:Platform="x64" diff --git a/Deploy/Linux/DeployWindowsUnstable.sh b/Deploy/Linux/DeployWindowsUnstable.sh deleted file mode 100644 index ccabb7aee..000000000 --- a/Deploy/Linux/DeployWindowsUnstable.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/sh - -cd ../../Barotrauma - -cd BarotraumaClient -dotnet publish WindowsClient.csproj -c Unstable -clp:"ErrorsOnly;Summary" --self-contained -r win-x64 \/p:Platform="x64" - -cd .. -cd BarotraumaServer -dotnet publish WindowsServer.csproj -c Unstable -clp:"ErrorsOnly;Summary" --self-contained -r win-x64 \/p:Platform="x64" diff --git a/Deploy/ManualScripts/Linux/DeployLinux.sh b/Deploy/ManualScripts/Linux/DeployLinux.sh new file mode 100644 index 000000000..9ea5ba91f --- /dev/null +++ b/Deploy/ManualScripts/Linux/DeployLinux.sh @@ -0,0 +1,10 @@ +#!/bin/sh + +cd ../../../Barotrauma + +cd BarotraumaClient +dotnet publish LinuxClient.csproj -c Release -clp:"ErrorsOnly;Summary" --self-contained -r linux-x64 \/p:Platform="x64" \/p:RollForward=Disable \/p:RuntimeFrameworkVersion=3.1.16 + +cd .. +cd BarotraumaServer +dotnet publish LinuxServer.csproj -c Release -clp:"ErrorsOnly;Summary" --self-contained -r linux-x64 \/p:Platform="x64" \/p:RollForward=Disable \/p:RuntimeFrameworkVersion=3.1.16 diff --git a/Deploy/ManualScripts/Linux/DeployLinuxServer.sh b/Deploy/ManualScripts/Linux/DeployLinuxServer.sh new file mode 100644 index 000000000..5e49f9654 --- /dev/null +++ b/Deploy/ManualScripts/Linux/DeployLinuxServer.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +cd ../../../Barotrauma/BarotraumaServer +dotnet publish LinuxServer.csproj -c Release --self-contained -r linux-x64 \/p:Platform="x64" \/p:RollForward=Disable \/p:RuntimeFrameworkVersion=3.1.16 diff --git a/Deploy/ManualScripts/Linux/DeployLinuxUnstable.sh b/Deploy/ManualScripts/Linux/DeployLinuxUnstable.sh new file mode 100644 index 000000000..b2c270ee2 --- /dev/null +++ b/Deploy/ManualScripts/Linux/DeployLinuxUnstable.sh @@ -0,0 +1,10 @@ +#!/bin/sh + +cd ../../../Barotrauma + +cd BarotraumaClient +dotnet publish LinuxClient.csproj -c Unstable -clp:"ErrorsOnly;Summary" --self-contained -r linux-x64 \/p:Platform="x64" \/p:RollForward=Disable \/p:RuntimeFrameworkVersion=3.1.16 + +cd .. +cd BarotraumaServer +dotnet publish LinuxServer.csproj -c Unstable -clp:"ErrorsOnly;Summary" --self-contained -r linux-x64 \/p:Platform="x64" \/p:RollForward=Disable \/p:RuntimeFrameworkVersion=3.1.16 diff --git a/Deploy/ManualScripts/Linux/DeployMac.sh b/Deploy/ManualScripts/Linux/DeployMac.sh new file mode 100644 index 000000000..66592c074 --- /dev/null +++ b/Deploy/ManualScripts/Linux/DeployMac.sh @@ -0,0 +1,10 @@ +#!/bin/sh + +cd ../../../Barotrauma + +cd BarotraumaClient +dotnet publish MacClient.csproj -c Release -clp:"ErrorsOnly;Summary" --self-contained -r osx-x64 \/p:Platform="x64" \/p:RollForward=Disable \/p:RuntimeFrameworkVersion=3.1.16 + +cd .. +cd BarotraumaServer +dotnet publish MacServer.csproj -c Release -clp:"ErrorsOnly;Summary" --self-contained -r osx-x64 \/p:Platform="x64" \/p:RollForward=Disable \/p:RuntimeFrameworkVersion=3.1.16 diff --git a/Deploy/ManualScripts/Linux/DeployMacUnstable.sh b/Deploy/ManualScripts/Linux/DeployMacUnstable.sh new file mode 100644 index 000000000..1bea5df67 --- /dev/null +++ b/Deploy/ManualScripts/Linux/DeployMacUnstable.sh @@ -0,0 +1,10 @@ +#!/bin/sh + +cd ../../../Barotrauma + +cd BarotraumaClient +dotnet publish MacClient.csproj -c Unstable -clp:"ErrorsOnly;Summary" --self-contained -r osx-x64 \/p:Platform="x64" \/p:RollForward=Disable \/p:RuntimeFrameworkVersion=3.1.16 + +cd .. +cd BarotraumaServer +dotnet publish MacServer.csproj -c Unstable -clp:"ErrorsOnly;Summary" --self-contained -r osx-x64 \/p:Platform="x64" \/p:RollForward=Disable \/p:RuntimeFrameworkVersion=3.1.16 diff --git a/Deploy/ManualScripts/Linux/DeployWindows.sh b/Deploy/ManualScripts/Linux/DeployWindows.sh new file mode 100644 index 000000000..4cb05dc21 --- /dev/null +++ b/Deploy/ManualScripts/Linux/DeployWindows.sh @@ -0,0 +1,10 @@ +#!/bin/sh + +cd ../../../Barotrauma + +cd BarotraumaClient +dotnet publish WindowsClient.csproj -c Release -clp:"ErrorsOnly;Summary" --self-contained -r win-x64 \/p:Platform="x64" \/p:RollForward=Disable \/p:RuntimeFrameworkVersion=3.1.16 + +cd .. +cd BarotraumaServer +dotnet publish WindowsServer.csproj -c Release -clp:"ErrorsOnly;Summary" --self-contained -r win-x64 \/p:Platform="x64" \/p:RollForward=Disable \/p:RuntimeFrameworkVersion=3.1.16 diff --git a/Deploy/ManualScripts/Linux/DeployWindowsUnstable.sh b/Deploy/ManualScripts/Linux/DeployWindowsUnstable.sh new file mode 100644 index 000000000..f18b284f3 --- /dev/null +++ b/Deploy/ManualScripts/Linux/DeployWindowsUnstable.sh @@ -0,0 +1,10 @@ +#!/bin/sh + +cd ../../../Barotrauma + +cd BarotraumaClient +dotnet publish WindowsClient.csproj -c Unstable -clp:"ErrorsOnly;Summary" --self-contained -r win-x64 \/p:Platform="x64" \/p:RollForward=Disable \/p:RuntimeFrameworkVersion=3.1.16 + +cd .. +cd BarotraumaServer +dotnet publish WindowsServer.csproj -c Unstable -clp:"ErrorsOnly;Summary" --self-contained -r win-x64 \/p:Platform="x64" \/p:RollForward=Disable \/p:RuntimeFrameworkVersion=3.1.16 diff --git a/Deploy/ManualScripts/SteamPipeBuildScripts/app_1026340.vdf b/Deploy/ManualScripts/SteamPipeBuildScripts/app_1026340.vdf new file mode 100644 index 000000000..70d3550a6 --- /dev/null +++ b/Deploy/ManualScripts/SteamPipeBuildScripts/app_1026340.vdf @@ -0,0 +1,15 @@ +"appbuild" +{ + "appid" "1026340" + "desc" "" + "buildoutput" "[steamworks_sdk_install_folder]\sdk\tools\ContentBuilder\output" + "contentroot" "" + "setlive" "" + "preview" "0" + "local" "" + "depots" + { + "1026341" "[steamworks_sdk_install_folder]\sdk\tools\ContentBuilder\scripts\depot_1026341.vdf" + "1026342" "[steamworks_sdk_install_folder]\sdk\tools\ContentBuilder\scripts\depot_1026342.vdf" + } +} diff --git a/Deploy/ManualScripts/SteamPipeBuildScripts/app_602960.vdf b/Deploy/ManualScripts/SteamPipeBuildScripts/app_602960.vdf new file mode 100644 index 000000000..f2fca8b7f --- /dev/null +++ b/Deploy/ManualScripts/SteamPipeBuildScripts/app_602960.vdf @@ -0,0 +1,16 @@ +"appbuild" +{ + "appid" "602960" + "desc" "" + "buildoutput" "[steamworks_sdk_install_folder]\sdk\tools\ContentBuilder\output" + "contentroot" "" + "setlive" "" + "preview" "0" + "local" "" + "depots" + { + "602961" "[steamworks_sdk_install_folder]\sdk\tools\ContentBuilder\scripts\depot_602961.vdf" + "602962" "[steamworks_sdk_install_folder]\sdk\tools\ContentBuilder\scripts\depot_602962.vdf" + "602963" "[steamworks_sdk_install_folder]\sdk\tools\ContentBuilder\scripts\depot_602963.vdf" + } +} \ No newline at end of file diff --git a/BuildScripts/depot_1026341.vdf b/Deploy/ManualScripts/SteamPipeBuildScripts/depot_1026341.vdf similarity index 100% rename from BuildScripts/depot_1026341.vdf rename to Deploy/ManualScripts/SteamPipeBuildScripts/depot_1026341.vdf diff --git a/BuildScripts/depot_1026342.vdf b/Deploy/ManualScripts/SteamPipeBuildScripts/depot_1026342.vdf similarity index 100% rename from BuildScripts/depot_1026342.vdf rename to Deploy/ManualScripts/SteamPipeBuildScripts/depot_1026342.vdf diff --git a/BuildScripts/depot_602961.vdf b/Deploy/ManualScripts/SteamPipeBuildScripts/depot_602961.vdf similarity index 100% rename from BuildScripts/depot_602961.vdf rename to Deploy/ManualScripts/SteamPipeBuildScripts/depot_602961.vdf diff --git a/BuildScripts/depot_602962.vdf b/Deploy/ManualScripts/SteamPipeBuildScripts/depot_602962.vdf similarity index 100% rename from BuildScripts/depot_602962.vdf rename to Deploy/ManualScripts/SteamPipeBuildScripts/depot_602962.vdf diff --git a/BuildScripts/depot_602963.vdf b/Deploy/ManualScripts/SteamPipeBuildScripts/depot_602963.vdf similarity index 100% rename from BuildScripts/depot_602963.vdf rename to Deploy/ManualScripts/SteamPipeBuildScripts/depot_602963.vdf diff --git a/Deploy/ManualScripts/Windows/DeployLinux.bat b/Deploy/ManualScripts/Windows/DeployLinux.bat new file mode 100644 index 000000000..ee2f601e4 --- /dev/null +++ b/Deploy/ManualScripts/Windows/DeployLinux.bat @@ -0,0 +1,12 @@ +@ECHO OFF + +cd ../../../Barotrauma + +cd BarotraumaClient +dotnet publish LinuxClient.csproj -c Release -clp:ErrorsOnly;Summary --self-contained -r linux-x64 /p:Platform=x64 /p:RollForward=Disable /p:RuntimeFrameworkVersion=3.1.16 + +cd .. +cd BarotraumaServer +dotnet publish LinuxServer.csproj -c Release -clp:ErrorsOnly;Summary --self-contained -r linux-x64 /p:Platform=x64 /p:RollForward=Disable /p:RuntimeFrameworkVersion=3.1.16 + +PAUSE diff --git a/Deploy/ManualScripts/Windows/DeployLinuxUnstable.bat b/Deploy/ManualScripts/Windows/DeployLinuxUnstable.bat new file mode 100644 index 000000000..39d2e158f --- /dev/null +++ b/Deploy/ManualScripts/Windows/DeployLinuxUnstable.bat @@ -0,0 +1,12 @@ +@ECHO OFF + +cd ../../../Barotrauma + +cd BarotraumaClient +dotnet publish LinuxClient.csproj -c Unstable -clp:ErrorsOnly;Summary --self-contained -r linux-x64 /p:Platform=x64 /p:RollForward=Disable /p:RuntimeFrameworkVersion=3.1.16 + +cd .. +cd BarotraumaServer +dotnet publish LinuxServer.csproj -c Unstable -clp:ErrorsOnly;Summary --self-contained -r linux-x64 /p:Platform=x64 /p:RollForward=Disable /p:RuntimeFrameworkVersion=3.1.16 + +PAUSE diff --git a/Deploy/ManualScripts/Windows/DeployMac.bat b/Deploy/ManualScripts/Windows/DeployMac.bat new file mode 100644 index 000000000..7c182a920 --- /dev/null +++ b/Deploy/ManualScripts/Windows/DeployMac.bat @@ -0,0 +1,12 @@ +@ECHO OFF + +cd ../../../Barotrauma + +cd BarotraumaClient +dotnet publish MacClient.csproj -c Release -clp:ErrorsOnly;Summary --self-contained -r osx-x64 /p:Platform=x64 /p:RollForward=Disable /p:RuntimeFrameworkVersion=3.1.16 + +cd .. +cd BarotraumaServer +dotnet publish MacServer.csproj -c Release -clp:ErrorsOnly;Summary --self-contained -r osx-x64 /p:Platform=x64 /p:RollForward=Disable /p:RuntimeFrameworkVersion=3.1.16 + +PAUSE diff --git a/Deploy/ManualScripts/Windows/DeployMacUnstable.bat b/Deploy/ManualScripts/Windows/DeployMacUnstable.bat new file mode 100644 index 000000000..0ceea7daa --- /dev/null +++ b/Deploy/ManualScripts/Windows/DeployMacUnstable.bat @@ -0,0 +1,12 @@ +@ECHO OFF + +cd ../../../Barotrauma + +cd BarotraumaClient +dotnet publish MacClient.csproj -c Unstable -clp:ErrorsOnly;Summary --self-contained -r osx-x64 /p:Platform=x64 /p:RollForward=Disable /p:RuntimeFrameworkVersion=3.1.16 + +cd .. +cd BarotraumaServer +dotnet publish MacServer.csproj -c Unstable -clp:ErrorsOnly;Summary --self-contained -r osx-x64 /p:Platform=x64 /p:RollForward=Disable /p:RuntimeFrameworkVersion=3.1.16 + +PAUSE diff --git a/Deploy/ManualScripts/Windows/DeployWindows.bat b/Deploy/ManualScripts/Windows/DeployWindows.bat new file mode 100644 index 000000000..3bbdf4829 --- /dev/null +++ b/Deploy/ManualScripts/Windows/DeployWindows.bat @@ -0,0 +1,12 @@ +@ECHO OFF + +cd ../../../Barotrauma + +cd BarotraumaClient +dotnet publish WindowsClient.csproj -c Release -clp:ErrorsOnly;Summary --self-contained -r win-x64 /p:Platform=x64 /p:RollForward=Disable /p:RuntimeFrameworkVersion=3.1.16 + +cd .. +cd BarotraumaServer +dotnet publish WindowsServer.csproj -c Release -clp:ErrorsOnly;Summary --self-contained -r win-x64 /p:Platform=x64 /p:RollForward=Disable /p:RuntimeFrameworkVersion=3.1.16 + +PAUSE diff --git a/Deploy/ManualScripts/Windows/DeployWindowsServer.bat b/Deploy/ManualScripts/Windows/DeployWindowsServer.bat new file mode 100644 index 000000000..02beb909a --- /dev/null +++ b/Deploy/ManualScripts/Windows/DeployWindowsServer.bat @@ -0,0 +1,6 @@ +@ECHO OFF + +cd ../../../Barotrauma/BarotraumaServer +dotnet publish WindowsServer.csproj -c Release --self-contained -r win-x64 /p:Platform=x64 /p:RollForward=Disable /p:RuntimeFrameworkVersion=3.1.16 + +PAUSE diff --git a/Deploy/ManualScripts/Windows/DeployWindowsUnstable.bat b/Deploy/ManualScripts/Windows/DeployWindowsUnstable.bat new file mode 100644 index 000000000..7864badb0 --- /dev/null +++ b/Deploy/ManualScripts/Windows/DeployWindowsUnstable.bat @@ -0,0 +1,12 @@ +@ECHO OFF + +cd ../../../Barotrauma + +cd BarotraumaClient +dotnet publish WindowsClient.csproj -c Unstable -clp:ErrorsOnly;Summary --self-contained -r win-x64 /p:Platform=x64 /p:RollForward=Disable /p:RuntimeFrameworkVersion=3.1.16 + +cd .. +cd BarotraumaServer +dotnet publish WindowsServer.csproj -c Unstable -clp:ErrorsOnly;Summary --self-contained -r win-x64 /p:Platform=x64 /p:RollForward=Disable /p:RuntimeFrameworkVersion=3.1.16 + +PAUSE diff --git a/Deploy/Windows/DeployLinux.bat b/Deploy/Windows/DeployLinux.bat deleted file mode 100644 index 13cebab0c..000000000 --- a/Deploy/Windows/DeployLinux.bat +++ /dev/null @@ -1,12 +0,0 @@ -@ECHO OFF - -cd ../../Barotrauma - -cd BarotraumaClient -dotnet publish LinuxClient.csproj -c Release -clp:ErrorsOnly;Summary --self-contained -r linux-x64 /p:Platform=x64 - -cd .. -cd BarotraumaServer -dotnet publish LinuxServer.csproj -c Release -clp:ErrorsOnly;Summary --self-contained -r linux-x64 /p:Platform=x64 - -PAUSE diff --git a/Deploy/Windows/DeployLinuxUnstable.bat b/Deploy/Windows/DeployLinuxUnstable.bat deleted file mode 100644 index ce7c60bc5..000000000 --- a/Deploy/Windows/DeployLinuxUnstable.bat +++ /dev/null @@ -1,12 +0,0 @@ -@ECHO OFF - -cd ../../Barotrauma - -cd BarotraumaClient -dotnet publish LinuxClient.csproj -c Unstable -clp:ErrorsOnly;Summary --self-contained -r linux-x64 /p:Platform=x64 - -cd .. -cd BarotraumaServer -dotnet publish LinuxServer.csproj -c Unstable -clp:ErrorsOnly;Summary --self-contained -r linux-x64 /p:Platform=x64 - -PAUSE diff --git a/Deploy/Windows/DeployMac.bat b/Deploy/Windows/DeployMac.bat deleted file mode 100644 index c1488f7a3..000000000 --- a/Deploy/Windows/DeployMac.bat +++ /dev/null @@ -1,12 +0,0 @@ -@ECHO OFF - -cd ../../Barotrauma - -cd BarotraumaClient -dotnet publish MacClient.csproj -c Release -clp:ErrorsOnly;Summary --self-contained -r osx-x64 /p:Platform=x64 - -cd .. -cd BarotraumaServer -dotnet publish MacServer.csproj -c Release -clp:ErrorsOnly;Summary --self-contained -r osx-x64 /p:Platform=x64 - -PAUSE diff --git a/Deploy/Windows/DeployMacUnstable.bat b/Deploy/Windows/DeployMacUnstable.bat deleted file mode 100644 index 771f83526..000000000 --- a/Deploy/Windows/DeployMacUnstable.bat +++ /dev/null @@ -1,12 +0,0 @@ -@ECHO OFF - -cd ../../Barotrauma - -cd BarotraumaClient -dotnet publish MacClient.csproj -c Unstable -clp:ErrorsOnly;Summary --self-contained -r osx-x64 /p:Platform=x64 - -cd .. -cd BarotraumaServer -dotnet publish MacServer.csproj -c Unstable -clp:ErrorsOnly;Summary --self-contained -r osx-x64 /p:Platform=x64 - -PAUSE diff --git a/Deploy/Windows/DeployWindows.bat b/Deploy/Windows/DeployWindows.bat deleted file mode 100644 index cdd63185f..000000000 --- a/Deploy/Windows/DeployWindows.bat +++ /dev/null @@ -1,12 +0,0 @@ -@ECHO OFF - -cd ../../Barotrauma - -cd BarotraumaClient -dotnet publish WindowsClient.csproj -c Release -clp:ErrorsOnly;Summary --self-contained -r win-x64 /p:Platform=x64 - -cd .. -cd BarotraumaServer -dotnet publish WindowsServer.csproj -c Release -clp:ErrorsOnly;Summary --self-contained -r win-x64 /p:Platform=x64 - -PAUSE diff --git a/Deploy/Windows/DeployWindowsServer.bat b/Deploy/Windows/DeployWindowsServer.bat deleted file mode 100644 index 865d61d03..000000000 --- a/Deploy/Windows/DeployWindowsServer.bat +++ /dev/null @@ -1,6 +0,0 @@ -@ECHO OFF - -cd ../../Barotrauma/BarotraumaServer -dotnet publish WindowsServer.csproj -c Release --self-contained -r win-x64 /p:Platform=x64 - -PAUSE diff --git a/Deploy/Windows/DeployWindowsUnstable.bat b/Deploy/Windows/DeployWindowsUnstable.bat deleted file mode 100644 index d8d4b4f7e..000000000 --- a/Deploy/Windows/DeployWindowsUnstable.bat +++ /dev/null @@ -1,12 +0,0 @@ -@ECHO OFF - -cd ../../Barotrauma - -cd BarotraumaClient -dotnet publish WindowsClient.csproj -c Unstable -clp:ErrorsOnly;Summary --self-contained -r win-x64 /p:Platform=x64 - -cd .. -cd BarotraumaServer -dotnet publish WindowsServer.csproj -c Unstable -clp:ErrorsOnly;Summary --self-contained -r win-x64 /p:Platform=x64 - -PAUSE From 084f10b7d8692b8f76f9bb1cb19ddfc1808ac154 Mon Sep 17 00:00:00 2001 From: Joonas Rikkonen Date: Wed, 14 Sep 2022 17:32:26 +0300 Subject: [PATCH 07/11] Update bug_report.yml --- .github/ISSUE_TEMPLATE/bug_report.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index ca60d65a8..735822bb9 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -53,7 +53,7 @@ body: description: Which version of the game did the bug happen in? You can see the current version number in the bottom left corner of your screen in the main menu. options: - 0.18.15.1 / 0.18.15.2 on macOS - - 0.19.3.0 (unstable) + - 0.19.5.0 (unstable) - Other validations: required: true From 1fd2a51bbb1b44bac9ff3606f697bfa96142e7af Mon Sep 17 00:00:00 2001 From: Juan Pablo Arce Date: Wed, 14 Sep 2022 12:47:17 -0300 Subject: [PATCH 08/11] Unstable v0.19.5.0 --- .../ClientSource/Characters/CharacterHUD.cs | 51 +- .../ClientSource/Characters/CharacterInfo.cs | 7 +- .../ContentPackage/ModProject.cs | 12 +- .../ContentPackageManager.cs | 8 +- ...nsition.cs => LegacySteamUgcTransition.cs} | 8 +- .../ClientSource/DebugConsole.cs | 30 +- .../Events/EventActions/MessageBoxAction.cs | 73 + .../EventActions/TutorialHighlightAction.cs | 51 + .../EventActions/TutorialSegmentAction.cs | 50 + .../ClientSource/Fonts/ScalableFont.cs | 114 +- .../ClientSource/GUI/GUIComponent.cs | 4 +- .../ClientSource/GUI/GUIDropDown.cs | 27 +- .../ClientSource/GUI/GUIMessageBox.cs | 35 +- .../ClientSource/GUI/GUIPrefab.cs | 6 +- .../ClientSource/GUI/GUIStyle.cs | 2 +- .../ClientSource/GUI/GUITickBox.cs | 2 +- .../ClientSource/GUI/RectTransform.cs | 17 +- .../ClientSource/GUI/SubmarineSelection.cs | 17 +- .../ClientSource/GUI/TabMenu.cs | 15 +- .../ClientSource/GUI/UpgradeStore.cs | 48 +- .../BarotraumaClient/ClientSource/GameMain.cs | 8 +- .../ClientSource/GameSession/CrewManager.cs | 6 +- .../GameModes/Tutorials/Tutorial.cs | 199 +- .../Items/Components/Holdable/RangedWeapon.cs | 2 +- .../Items/Components/ItemComponent.cs | 1 + .../Items/Components/Machines/Sonar.cs | 13 + .../Items/Components/Repairable.cs | 19 +- .../ClientSource/Items/Item.cs | 2 +- .../ClientSource/Map/Structure.cs | 2 +- .../ClientSource/Map/SubmarineInfo.cs | 9 +- .../ClientSource/Networking/Client.cs | 8 + .../ClientSource/Networking/GameClient.cs | 704 +++--- .../Networking/Primitives/Peers/ClientPeer.cs | 103 +- .../Primitives/Peers/LidgrenClientPeer.cs | 18 +- .../Primitives/Peers/SteamP2PClientPeer.cs | 59 +- .../Primitives/Peers/SteamP2POwnerPeer.cs | 64 +- .../ClientSource/Networking/ServerInfo.cs | 517 ----- .../FriendProviders/FriendProvider.cs | 11 + .../FriendProviders/SteamFriendProvider.cs | 67 + .../Networking/ServerList/PingUtils.cs | 196 ++ .../Networking/ServerList/ServerInfo.cs | 509 ++++ .../CompositeServerProvider.cs | 35 + .../ServerProviders/ServerProvider.cs | 17 + .../SteamDedicatedServerProvider.cs | 160 ++ .../ServerProviders/SteamP2PServerProvider.cs | 107 + .../ClientSource/Networking/ServerSettings.cs | 14 +- .../ClientSource/Networking/Voting.cs | 18 + .../ClientSource/Screens/MainMenuScreen.cs | 47 +- .../ClientSource/Screens/ModDownloadScreen.cs | 60 +- .../ClientSource/Screens/NetLobbyScreen.cs | 28 +- .../ClientSource/Screens/ServerListScreen.cs | 2044 ----------------- .../Screens/ServerListScreen/PanelAnimator.cs | 112 + .../ServerListScreen/ServerListScreen.cs | 1676 ++++++++++++++ .../ClientSource/Screens/SubEditorScreen.cs | 247 +- .../Serialization/SerializableEntityEditor.cs | 5 + .../ClientSource/Sprite/Sprite.cs | 17 +- .../ClientSource/Steam/BulkDownloader.cs | 4 +- .../ClientSource/Steam/Lobby.cs | 274 +-- .../ClientSource/Steam/Workshop.cs | 16 +- .../WorkshopMenu/Mutable/InstalledTab.cs | 26 +- .../Steam/WorkshopMenu/Mutable/ItemList.cs | 16 +- .../WorkshopMenu/Mutable/ModListPreset.cs | 18 +- .../Steam/WorkshopMenu/Mutable/PublishTab.cs | 24 +- .../Text/LocalizedString/WrappedLString.cs | 2 +- .../BarotraumaClient/LinuxClient.csproj | 2 +- Barotrauma/BarotraumaClient/MacClient.csproj | 2 +- .../BarotraumaClient/WindowsClient.csproj | 2 +- .../BarotraumaServer/LinuxServer.csproj | 2 +- Barotrauma/BarotraumaServer/MacServer.csproj | 2 +- .../ServerSource/Characters/CharacterInfo.cs | 3 +- .../BarotraumaServer/ServerSource/GameMain.cs | 1 + .../GameModes/CharacterCampaignData.cs | 22 +- .../GameModes/MultiPlayerCampaign.cs | 15 +- .../ServerSource/Networking/BanList.cs | 8 + .../ServerSource/Networking/Client.cs | 40 +- .../Networking/FileTransfer/ModSender.cs | 2 +- .../ServerSource/Networking/GameServer.cs | 440 ++-- .../ServerEntityEventManager.cs | 6 +- .../Networking/OrderChatMessage.cs | 2 +- .../Peers/Server/LidgrenServerPeer.cs | 60 +- .../Primitives/Peers/Server/ServerPeer.cs | 66 +- .../Peers/Server/SteamP2PServerPeer.cs | 72 +- .../ServerSource/Networking/RespawnManager.cs | 5 +- .../ServerSource/Networking/ServerSettings.cs | 38 +- .../ServerSource/Networking/Voting.cs | 8 + .../ServerSource/Screens/NetLobbyScreen.cs | 2 +- .../ServerSource/Steam/SteamManager.cs | 7 +- .../BarotraumaServer/WindowsServer.csproj | 2 +- .../Characters/AI/IndoorsSteeringManager.cs | 4 +- .../SharedSource/Characters/CharacterInfo.cs | 4 +- .../Characters/CharacterPrefab.cs | 4 - .../SharedSource/Characters/CorpsePrefab.cs | 8 +- .../Characters/Health/CharacterHealth.cs | 3 +- .../SharedSource/Characters/Jobs/JobPrefab.cs | 8 +- .../Characters/Talents/TalentPrefab.cs | 7 +- .../ContentFile/GenericPrefabFile.cs | 4 +- .../ContentPackage/ContentPackage.cs | 37 +- .../ContentPackageId/ContentPackageId.cs | 19 + .../ContentPackageId/SteamWorkshopId.cs | 32 + .../ContentPackageManager.cs | 4 +- .../ContentManagement/ContentPath.cs | 8 +- .../SharedSource/CoroutineManager.cs | 13 + .../SharedSource/DebugConsole.cs | 2 + .../EventActions/CheckConditionalAction.cs | 5 +- .../EventActions/CheckConnectionAction.cs | 65 + .../Events/EventActions/CheckItemAction.cs | 25 +- .../Events/EventActions/CheckOrderAction.cs | 40 +- .../EventActions/CheckSelectedItemAction.cs | 89 + .../Events/EventActions/CheckTalentAction.cs | 49 + .../Events/EventActions/MessageBoxAction.cs | 91 +- .../Events/EventActions/TeleportAction.cs | 48 + .../EventActions/TutorialHighlightAction.cs | 27 + .../Events/EventActions/TutorialIconAction.cs | 65 + .../EventActions/TutorialSegmentAction.cs | 65 +- .../SharedSource/Events/EventSet.cs | 10 +- .../Extensions/IEnumerableExtensions.cs | 10 + .../Extensions/StringExtensions.cs | 17 +- .../GameModes/Tutorials/TutorialPrefab.cs | 15 +- .../Items/Components/Machines/Sonar.cs | 2 + .../BooleanOperatorComponent.cs | 9 +- .../Items/Components/Signal/WaterDetector.cs | 3 + .../SharedSource/Items/Item.cs | 3 +- .../SharedSource/Items/ItemPrefab.cs | 20 +- .../SharedSource/Map/CoreEntityPrefab.cs | 6 +- .../SharedSource/Map/ItemAssemblyPrefab.cs | 2 +- .../SharedSource/Map/Levels/CaveGenerator.cs | 4 +- .../SharedSource/Map/LinkedSubmarine.cs | 10 +- .../SharedSource/Map/Map/Location.cs | 2 +- .../SharedSource/Map/MapEntityPrefab.cs | 24 + .../SharedSource/Map/StructurePrefab.cs | 23 +- .../SharedSource/Map/Submarine.cs | 1 + .../SharedSource/Networking/Client.cs | 10 +- .../SharedSource/Networking/NetworkMember.cs | 82 +- .../Primitives/AccountId/AccountId.cs | 2 +- .../Networking/Primitives/Address/Address.cs | 2 +- .../Primitives/Address/LidgrenAddress.cs | 32 +- .../Primitives/Endpoint/Endpoint.cs | 17 +- .../Primitives/Endpoint/LidgrenEndpoint.cs | 27 +- .../Primitives/NetworkPeerStructs.cs | 175 +- .../SharedSource/Networking/RespawnManager.cs | 8 +- .../SharedSource/Networking/ServerSettings.cs | 5 +- .../SharedSource/Networking/Voting.cs | 18 - .../SharedSource/Prefabs/Prefab.cs | 2 +- .../SharedSource/Prefabs/PrefabCollection.cs | 8 + .../SharedSource/Prefabs/PrefabSelector.cs | 72 +- .../Serialization/XMLExtensions.cs | 19 + .../SharedSource/Settings/GameSettings.cs | 4 +- .../StatusEffects/DelayedEffect.cs | 2 - .../SharedSource/Steam/Workshop.cs | 16 +- .../SharedSource/Text/TextManager.cs | 48 +- .../SharedSource/Upgrades/UpgradePrefab.cs | 21 +- .../SharedSource/Utils/Option/Option.cs | 10 +- .../SharedSource/Utils/ReflectionUtils.cs | 29 +- .../SharedSource/Utils/Threading.cs | 34 + Barotrauma/BarotraumaShared/changelog.txt | 85 +- .../Facepunch.Steamworks/ServerList/Base.cs | 10 +- .../Facepunch.Steamworks/Structs/Friend.cs | 6 +- .../Facepunch.Steamworks/Structs/Lobby.cs | 14 +- 158 files changed, 5702 insertions(+), 4813 deletions(-) rename Barotrauma/BarotraumaClient/ClientSource/ContentManagement/Transition/{UgcTransition.cs => LegacySteamUgcTransition.cs} (97%) create mode 100644 Barotrauma/BarotraumaClient/ClientSource/Events/EventActions/MessageBoxAction.cs create mode 100644 Barotrauma/BarotraumaClient/ClientSource/Events/EventActions/TutorialHighlightAction.cs create mode 100644 Barotrauma/BarotraumaClient/ClientSource/Events/EventActions/TutorialSegmentAction.cs delete mode 100644 Barotrauma/BarotraumaClient/ClientSource/Networking/ServerInfo.cs create mode 100644 Barotrauma/BarotraumaClient/ClientSource/Networking/ServerList/FriendProviders/FriendProvider.cs create mode 100644 Barotrauma/BarotraumaClient/ClientSource/Networking/ServerList/FriendProviders/SteamFriendProvider.cs create mode 100644 Barotrauma/BarotraumaClient/ClientSource/Networking/ServerList/PingUtils.cs create mode 100644 Barotrauma/BarotraumaClient/ClientSource/Networking/ServerList/ServerInfo.cs create mode 100644 Barotrauma/BarotraumaClient/ClientSource/Networking/ServerList/ServerProviders/CompositeServerProvider.cs create mode 100644 Barotrauma/BarotraumaClient/ClientSource/Networking/ServerList/ServerProviders/ServerProvider.cs create mode 100644 Barotrauma/BarotraumaClient/ClientSource/Networking/ServerList/ServerProviders/SteamDedicatedServerProvider.cs create mode 100644 Barotrauma/BarotraumaClient/ClientSource/Networking/ServerList/ServerProviders/SteamP2PServerProvider.cs delete mode 100644 Barotrauma/BarotraumaClient/ClientSource/Screens/ServerListScreen.cs create mode 100644 Barotrauma/BarotraumaClient/ClientSource/Screens/ServerListScreen/PanelAnimator.cs create mode 100644 Barotrauma/BarotraumaClient/ClientSource/Screens/ServerListScreen/ServerListScreen.cs create mode 100644 Barotrauma/BarotraumaShared/SharedSource/ContentManagement/ContentPackage/ContentPackageId/ContentPackageId.cs create mode 100644 Barotrauma/BarotraumaShared/SharedSource/ContentManagement/ContentPackage/ContentPackageId/SteamWorkshopId.cs create mode 100644 Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/CheckConnectionAction.cs create mode 100644 Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/CheckSelectedItemAction.cs create mode 100644 Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/CheckTalentAction.cs create mode 100644 Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/TeleportAction.cs create mode 100644 Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/TutorialHighlightAction.cs create mode 100644 Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/TutorialIconAction.cs create mode 100644 Barotrauma/BarotraumaShared/SharedSource/Utils/Threading.cs diff --git a/Barotrauma/BarotraumaClient/ClientSource/Characters/CharacterHUD.cs b/Barotrauma/BarotraumaClient/ClientSource/Characters/CharacterHUD.cs index a605b41c6..9ef84bc9e 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Characters/CharacterHUD.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Characters/CharacterHUD.cs @@ -1,5 +1,6 @@ using Barotrauma.Extensions; using Barotrauma.Items.Components; +using Barotrauma.Tutorials; using FarseerPhysics; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; @@ -398,36 +399,58 @@ namespace Barotrauma progressBar.Draw(spriteBatch, cam); } - foreach (Character npc in Character.CharacterList) + void DrawInteractionIcon(Entity entity, string iconStyle) { - if (npc.CampaignInteractionType == CampaignMode.InteractionType.None || npc.Submarine != character.Submarine || npc.IsDead || npc.IsIncapacitated) { continue; } + if (entity == null || entity.Removed) { return; } + var characterEntity = entity as Character; + if (characterEntity is not null && (characterEntity.IsDead || characterEntity.IsIncapacitated)) { return; } + if (GUIStyle.GetComponentStyle(iconStyle) is not GUIComponentStyle style) { return; } - var iconStyle = GUIStyle.GetComponentStyle("CampaignInteractionIcon." + npc.CampaignInteractionType); - if (iconStyle == null) { continue; } - Range visibleRange = new Range(npc.CurrentHull == Character.Controlled.CurrentHull ? 500.0f : 100.0f, float.PositiveInfinity); - if (npc.CampaignInteractionType == CampaignMode.InteractionType.Examine) + Hull currentHull = entity switch + { + Character character => character.CurrentHull, + Item item => item.CurrentHull, + _ => null + }; + + Range visibleRange = new Range(currentHull == Character.Controlled.CurrentHull ? 500.0f : 100.0f, float.PositiveInfinity); + if (characterEntity?.CampaignInteractionType == CampaignMode.InteractionType.Examine) { //TODO: we could probably do better than just hardcoding //a check for InteractionType.Examine here. - if (Vector2.DistanceSquared(character.Position, npc.Position) > 500f * 500f) { continue; } + if (Vector2.DistanceSquared(character.Position, entity.Position) > 500f * 500f) { return; } - var body = Submarine.CheckVisibility(character.SimPosition, npc.SimPosition, ignoreLevel: true); - if (body != null && body.UserData as Character != npc) { continue; } + var body = Submarine.CheckVisibility(character.SimPosition, entity.SimPosition, ignoreLevel: true); + if (body != null && body.UserData != entity) { return; } visibleRange = new Range(-100f, 500f); } - float dist = Vector2.Distance(character.WorldPosition, npc.WorldPosition); + float dist = Vector2.Distance(character.WorldPosition, entity.WorldPosition); float distFactor = 1.0f - MathUtils.InverseLerp(1000.0f, 3000.0f, dist); float alpha = MathHelper.Lerp(0.3f, 1.0f, distFactor); GUI.DrawIndicator( spriteBatch, - npc.WorldPosition, + entity.WorldPosition, cam, visibleRange, - iconStyle.GetDefaultSprite(), - iconStyle.Color * alpha, - label: npc.Info?.Title); + style.GetDefaultSprite(), + style.Color * alpha, + label: characterEntity?.Info?.Title); + } + + foreach (Character npc in Character.CharacterList) + { + if (npc.CampaignInteractionType == CampaignMode.InteractionType.None) { continue; } + DrawInteractionIcon(npc, "CampaignInteractionIcon." + npc.CampaignInteractionType); + } + + if (GameMain.GameSession?.GameMode is TutorialMode tutorialMode && tutorialMode.Tutorial is not null) + { + foreach (var (entity, iconStyle) in tutorialMode.Tutorial.Icons) + { + DrawInteractionIcon(entity, iconStyle); + } } foreach (Item item in Item.ItemList) diff --git a/Barotrauma/BarotraumaClient/ClientSource/Characters/CharacterInfo.cs b/Barotrauma/BarotraumaClient/ClientSource/Characters/CharacterInfo.cs index 290746f93..ab2942b42 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Characters/CharacterInfo.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Characters/CharacterInfo.cs @@ -521,8 +521,9 @@ namespace Barotrauma Color skinColor = inc.ReadColorR8G8B8(); Color hairColor = inc.ReadColorR8G8B8(); Color facialHairColor = inc.ReadColorR8G8B8(); - string ragdollFile = inc.ReadString(); + string ragdollFile = inc.ReadString(); + Identifier npcId = inc.ReadIdentifier(); uint jobIdentifier = inc.ReadUInt32(); int variant = inc.ReadByte(); @@ -539,9 +540,9 @@ namespace Barotrauma } // TODO: animations - CharacterInfo ch = new CharacterInfo(speciesName, newName, originalName, jobPrefab, ragdollFile, variant) + CharacterInfo ch = new CharacterInfo(speciesName, newName, originalName, jobPrefab, ragdollFile, variant, npcIdentifier: npcId) { - ID = infoID, + ID = infoID }; ch.RecreateHead(tagSet.ToImmutableHashSet(), hairIndex, beardIndex, moustacheIndex, faceAttachmentIndex); ch.Head.SkinColor = skinColor; diff --git a/Barotrauma/BarotraumaClient/ClientSource/ContentManagement/ContentPackage/ModProject.cs b/Barotrauma/BarotraumaClient/ClientSource/ContentManagement/ContentPackage/ModProject.cs index 34d2a3a75..85877787b 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/ContentManagement/ContentPackage/ModProject.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/ContentManagement/ContentPackage/ModProject.cs @@ -63,7 +63,7 @@ namespace Barotrauma files = contentPackage.Files.Select(File.FromContentFile).ToList(); ModVersion = IncrementModVersion(contentPackage.ModVersion); IsCore = contentPackage is CorePackage; - SteamWorkshopId = contentPackage.SteamWorkshopId; + UgcId = contentPackage.UgcId; ExpectedHash = contentPackage.Hash; InstallTime = contentPackage.InstallTime; } @@ -90,9 +90,9 @@ namespace Barotrauma public bool IsCore = false; - public UInt64 SteamWorkshopId = 0; + public Option UgcId = Option.None(); - public DateTime? InstallTime = null; + public Option InstallTime = Option.None(); public bool HasFile(File file) => Files.Any(f => @@ -120,7 +120,7 @@ namespace Barotrauma public void DiscardHashAndInstallTime() { ExpectedHash = null; - InstallTime = null; + InstallTime = Option.None(); } public static string IncrementModVersion(string modVersion) @@ -155,11 +155,11 @@ namespace Barotrauma addRootAttribute("name", Name); if (!ModVersion.IsNullOrEmpty()) { addRootAttribute("modversion", ModVersion); } addRootAttribute("corepackage", IsCore); - if (SteamWorkshopId != 0) { addRootAttribute("steamworkshopid", SteamWorkshopId); } + if (UgcId.TryUnwrap(out var ugcId) && ugcId is SteamWorkshopId steamWorkshopId) { addRootAttribute("steamworkshopid", steamWorkshopId.Value); } addRootAttribute("gameversion", GameMain.Version); if (AltNames.Any()) { addRootAttribute("altnames", string.Join(",", AltNames)); } if (ExpectedHash != null) { addRootAttribute("expectedhash", ExpectedHash.StringRepresentation); } - if (InstallTime != null) { addRootAttribute("installtime", ToolBox.Epoch.FromDateTime(InstallTime.Value)); } + if (InstallTime.TryUnwrap(out var installTime)) { addRootAttribute("installtime", ToolBox.Epoch.FromDateTime(installTime)); } files.ForEach(f => rootElement.Add(f.ToXElement())); diff --git a/Barotrauma/BarotraumaClient/ClientSource/ContentManagement/ContentPackageManager.cs b/Barotrauma/BarotraumaClient/ClientSource/ContentManagement/ContentPackageManager.cs index 86a971bf5..e59354ecb 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/ContentManagement/ContentPackageManager.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/ContentManagement/ContentPackageManager.cs @@ -45,9 +45,11 @@ namespace Barotrauma var needInstalling = subscribedItems.Where(item => !WorkshopPackages.Any(p - => item.Id == p.SteamWorkshopId - && p.InstallTime.HasValue - && item.LatestUpdateTime <= p.InstallTime)) + => p.UgcId.TryUnwrap(out var ugcId) + && ugcId is SteamWorkshopId workshopId + && item.Id == workshopId.Value + && p.InstallTime.TryUnwrap(out var installTime) + && item.LatestUpdateTime <= installTime)) .ToArray(); if (needInstalling.Any()) { diff --git a/Barotrauma/BarotraumaClient/ClientSource/ContentManagement/Transition/UgcTransition.cs b/Barotrauma/BarotraumaClient/ClientSource/ContentManagement/Transition/LegacySteamUgcTransition.cs similarity index 97% rename from Barotrauma/BarotraumaClient/ClientSource/ContentManagement/Transition/UgcTransition.cs rename to Barotrauma/BarotraumaClient/ClientSource/ContentManagement/Transition/LegacySteamUgcTransition.cs index 748995b91..2b766254c 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/ContentManagement/Transition/UgcTransition.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/ContentManagement/Transition/LegacySteamUgcTransition.cs @@ -16,7 +16,7 @@ namespace Barotrauma.Transition /// Class dedicated to transitioning away from the old, shitty /// Mods + Submarines folders to the new LocalMods folder ///

    #Yz%#dq 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񲪦vU<||FN`-`;=i~w=Cf8vsKdp6P$QdQuQ4r^3t9IdOX z&B=klYkHP^S>9&kwK9t5FZ?=$8M^>P13>)b4gAjtfH!Rb*h1iLg`kTdzuLsJ;AhqTony;flK&{eXdWd}lNU+P2{(pK#!O5iz4vrN+i zFl@|W6-Yfi9;O1if{6;#0SKLctF)`QDgfHYS?{^V2MLGsX>KO(8Y^lHrv(VKMv0^{ zEe!x#oIFtH9}$RmO8f-6qbS{D5K4i@dy=vwqLu@gdizBr!zo2p?;AuwHtImjm8ju8 zTDCNd`1}M=&aH<05%<}(TIj>;+!qZC4$r~;v<0JWGMs}(5Q&J-5jjO#KTl^AZ{&Yo zc534*RF8oxjA2nrq?-t4Fg&TB`j%eFA&^Cdf%-=>e`%t z%cX9@^QfFoINADFy@b0jhjtY3GQ!2}r5qYb!Jx2=H4rv$^n{HO+9Fof#iBFrp-jP1 zvX4}WaugL9QW=)Oof-;RPGI;#xu~wGBTg5g^WiWDg8^)Okv{H+!XnR)Fr^O8PhmaP zv(I!#B4{xoiJ8MSC%7pkthxX}V}mFH;bdidGjv=avVoj*>top0d2WDS$E?q1Cq^SM zZmbZBcH&f6!z;f{E_)h{E##zC(IKFYS_l{s@)ju6N64cBXB+tMo>fxg!PbIX7%Ykr z+8WC7m!MV2V80v6+ZB=6b2D zY!#8O&v~BulaIp7k! zi#7KO#}{{HakPks{NZ zv2;2`$|Mh=IO#ZZ_Dp=H;lbjC?-Yh?k>@_EBwLTgJyZGD0Iz{gqo{K-P0(S!zI4gC z7{!y;;&&P?BHx4WD?}#x6TR1+=fKsNh!TBqI`&@@`>H1VubOuOE zeTVN<`8QfZSdsQ<_*WoI#uN?vu6;lJ#m~gGoPmcB`nsA}vmn=zVK&M$71X0~KTTIM zj6L!Icta(5{i)?+oD~0yhD(gKJNpX5zVjzT+X>pe^`cy{wjF3pb)*3p|B=!1_^$_; zWnt0FclX8(_*^H^WH=Mx{o}|@My0G!jP59DJ1Z!n8ZJ!_THmE(2;TZVHALoc%^U*# z8vOX~uYVm*zV%j&G;;kKF7`o3+o=^W1`TgP3AO0yN(tfcL^_$fD_o8N@4M{tflM1X z@G=a4_Z|F$aC+!&-QJpz51pRCcwt1PVa&C)HSmb?crF7(8k){lTVETE2)1Mu77WB% zLw>E=ftJ_f6yfuYlKjwkBm>JOJQq1{1iV!lv`$ee`1nJjr0klaQG?sToju|5M<0e8 z$SRe<@hptOw7@LqT^&YmJqlX`wx1@&_BA|B_?Tpk%Wq$a z`z!u0i&Jw!@uH({(mzMN){_kmkA z@FihJ`X;_*f$JT9pSXCD_Md%3N0BlMA6f@@*Rn(xqh~Ds)7`K*oTHEKp(FBtWZBvl z3?LR#hPQs1bx{=IsI+yRZyO6Z-`~}ia;B$J*Jp*Z+#^pGedves}K2XWdg~*#8Zta~& zF!{gogGLbfpea+zT*_7cc+T#j=Pq4$=v>uVBkY_+0grMX&$i}4)Cn{+fVi&H)V5jH zn$OEqG`G*tD53IiYLkW`|Mp!`p5s}bofDQ1J5R4yACtbz8{9kh#Qm^7f@c&L=+!Qi z5%IGi|IHf!_FkX{K;E0H0k8%#%uZ3An*RitBPen9ef3cM5vcvKN~!{qL^&x{xk!Mb z@E#Ru4Xev%LllBN95>R9GfdxtbOQr}abrD*H1xJxUx4@$U^a(kj7BteD=kVQHniaYY+fT^rq3zjYzJBhy*AZ0XhU<(#2BC1C z{#Y1AE2YAX?-k(;;ghLH1miP-#UbGO4u5N%Qy|f(;E)N5NJcV<>?+=R7}7etMkF^h zC0glOs{oq_px;Xv5&-&65mlr%dLb!)Uaztv@o*%>^6xaycrL8V{qs84l?a#f)S{n% z6ye2v;%9}b?P>UIpR<9rJCGibp^y0d8sBpcl@NWalxl@k7&ridmQeJ=gspz=yz;3qe-I&Kkv3$`$>BOQ{-~g-+Y8i*tOXr=|==JW6>+rrfzgN#m z>-VhF`kN^ZS4x=RYL-gB$M7WKf!ctny?izlnm#&BW$~ua4dWZ9AA5KX@oa6*kr6av znMcrCp@@*})Y_U4g&7Fnaq|45(g}0(Jd6Mt9b_&R{F+-0=ZFG$@Y%0I%Z0PjFGBMW zS_xaMAvaRbd?+EL{&Z(pW(VHHC!~;Vl@3NH8SqubcPM?X))^ln-dn`r>)HWXst+kxJf)nQ;Ot*D)grfab zVYQ0+bAEF}BtusfLH1EM`(to^i)^Vxcd6yDGMho56;S_w0c zhM@Y?ut3mt|AZs)TwGB=*Gr_bl4;A(Vrm4z4Z)j83AR1#W^ohmlfG93gsxx(wF!KMH0y&Ek(exx_1T-%uW7i0oP^@us@p8EFyU&3! zI3<>X+ReKR2p=++qG$+q^Yj`MRF1?jw)OZih;7RWr z90>2c|1QPA5DCbbp8aK6Z>kb_ne~ zDD+vF;UYpy=EO-_f|8>QP5Jtt{wc!HDU>}0%EK`9m&_+aD#zIGKM%*>eK+E%0;2mr zi*R7U!D*rtDloLHp(wy$!lhT&J?C?zEa09(qtMnBco3XBwi&bfcsuWT!d#XSYRcJ1 z1#gE+v@~&zv$WV(Gkk3i{Ok$)Y%xE>7`v%6Gr3Cb3T+FlECgD}eweN%?aDHb_zqyX5xSTM?A#~J zc?Y9JNgL4$tXVH!g&t?tTEILu@X8MNpUM`&y#*`)Gvl!~!+=BCMt-C*BMOkO#2%lo5^v;~bjY#9+*JHm zNy|CfO|dfeV1LVj2y3Pl)il!k9Udi5Xzw}_3Y&>0Xy7?R17RANIfQ4wWoV|4`%u(EKZ&zEa4X_DJYpC5E$VHgwxi)NGPxaXF zKp6V!>lg`h?i>aj&QSwc7W!Qez1G7w1D)979xL?sl4{g?`3&ho`P9DH7Ymopu+LlU zpZV6qef^v{UO`}D5!|@?{s++fr{w>Wj>LP+yRYs(8u_@gm^30rmhiq|j2Ug%_T} z)KP$!RZ&ci){l8aB3J_^jZB6p8|c0US993=Z+sOFk#<;svOhyqSN6d;>1W_AwGy_7 z_zS~};liK)FwDVs&UO=d1T6Yad0fiZPco;G!Nd0+6Y<18(&F&c+m~Wty)kLS%e8R! zt&7n>tr9LCN*f)~_yNpm7?Ae8E_bAPOCNl%w8!^(o!3iWzhE;mfTpt%1OFqAqjqmv%Xl?CV^m3$FKd8Ps`;qkf-;FyvfahwDl7N}Bl+ zzHOZ_;ao4Y*C@~UT=zw~Den4QbtJzNMvMYbsdhLItK^#=9A!U0gjOmiOWSogdY||E zT=fy&ucWkITz1Dr-au^Q%w!5f`0iOVrS%o$;<9Lq@P9rsK+Sd zyY4Zfy$-fCNBz%8G9$xGBT;XwCQ{&C`26F?k8?&X=AeEge|1k>V>EVQEK}z5dTFVt zcIunbPa_YUyF6kC8sk~1cew`JAG=2PT3GWtbq?QcRD^r$ex@_DeX;waK_KoK_r`_3 z+S7=W{>@M~nVg}}4$m5*fT+j3g9U2&b;K7rH1iLNV#gYdWeCXhHcEvT=1=mlgERDxZ? z+=dZm_JB0bOM`&>_4bvwWB9iUuL`*YBYEp3RL)reT%__n0<}NqAaD{f0o(#0&PN3L z{~KB`z2EB-LGoJ9TOyZ-M~Rh@fP^QTf^=G#sZt)t3ND`mo~Od#^*iA}5osff%P7_`2hP)!0hwZ!)V;bhgjas}c4(ujd*84BIb>1J z+v=MMucP(L5EkZ5nA(gzP1!dHQ`%?e$=~3xW1MGVql=iek1Oq@OvA2&Fck!hxIQ#c8!S zTvwdkswKz!?CH>d_feQeaN8j#URvSUD5B|54Q;N-AzY<;^EPP~5?*nrgH}7!?D3&< z!|?T6Vb5kksKU77IVh-zWB#3pw*tCCxuK%f zL;$SQmT6~YD_q07W4Nb+c}&-+%jHZP(l3n306iP?hgE2Nuk;|DmoVs_C}b_uZi`Y* zA)mdiBr3ypO{EotuuYJLbgUggk~~$sv=#zvX5Q}i5-A+!>)O-ZIwX3|^_(1U?~Ka# z@I5+Ev=M&DyGvkVBVT?UvcUDg^_$@*|L)Ht{gvKa`^isf-A6=AXIregZ;1ct_pe3k z_YCx4@o7(}LMe0qFQIIY0AmW}CA`lZHjDag;^|xDY*o6~IS2Pk!`lEkp#@9X(7C@A zI51DHB3^@(9QNq_gTCuU7cM6L;kTjY)X{Jh2KfB5&q5LOOwYt~Qoby{*LnIB70nwk z$UcIt&{>9iEC4$H?Om!iQvlC*!|-Q0KhuOdP{4$Bm49i^c130Mx<7pQFz&nI_IkVL zSywk6ffu~P>dp>p2#E8uJRiV83C8%rvv!H1GOa;eZ)ARk?T_$Id!O$&ngOG7=b1B+ zp0*r05>o|sBQCOQQ#n}wb!T-dpw`|?|%7-1<6j4<7Vgx|b(hcH!?26|E#m>&(^ zB`C&fWwUGI)cyTZLgekyJDna(TmY`>H5`MG>wzUVtN zK6;)$PugzUfHYsjmg`7{44)ry7Wh`tRuOkTwgog=K>SSw1T_?B81OouDGzWc`1yVn zSVvUI`M2}+8a?~UCMwPf($aD7m(L^vOIoKi&7mSGPDx9mr+yQe0Kr>YZ4`%*0VBgB z(NK7xg-~w8y{Z1bNe2-}2}R8&sJLzf9RO(D#|&p`tHQfP0QLVrzYa@8E}2$S$eF)&=~5VBe-EHox^@lEbr>mT zd-_7f7Dnv^BXo@^qY!XodmC}U7%&G0jhBrIx%77#*q(teRdH{u=klzVLbGSVJ(LR^ zsFN$S#D$*>Vj$T>eo)yKzvnT0n3`#%M;`lWEt5i`hhBVlH~io~{tw}00ZtP3*r>oQ z@VVw-OBD3Y{p}@cpylY%SPx|dSj|HrS?nDNjU{+2p%EJA15tQ$gspFoVz|WqR}&dv zn6ETk7?Nj5@M?(&#={3tK%WoN8H#H8@Kt$l!U2^n?{$yFW94txB)%sDhYmGyNtz*z6yG8~ zbC183yXDQw&&5sf=gOVXboFw4P6P1P|J7F*JW%SO(^>YQ1*gi?XSc!%ktdDdud=X) z?R9Yf2(t8}|MGVjPO3r`BL4y@dWYL`tq5JKw8A-$KF4@-vMXef3q8B8W>SEjq;b+x*Jt{aJRydX1J6mOaQ#L;K$PQ|d!P58qgH{}3wz30 zo~?W4-g>X}yzTJe@bKXS(vC3XLkImXr5f`%=oeAWz_V~JO|7e=@Upra-^st!BZM>c z1oz#DW(_4q(5URo>qbVx`7&sDHROo`KQj)(j9v zg(JW7`Oy)L&Z&|wY`P!nJf4mEtNfSO#D5ECzQeJ@hcWt!^+~IImirb5pPA|{t|?18 zhdkEz#ti_KZ`c5^XOZwryyPm-Zj68{V{}8^7=c@bNddyc$!%mVj8EkEF!i+CvQFkN za0w(Lj2oz@#bhY04{92zqOdJ$LV<64bS@IIfFh@aP*ALAG#)UAs4Hhq1$T${8f0;Buk zd=4ILMzG376?l((A>;G6-}_w8K;(5k{ySag_Y!q~Tz8tA*GOz4l5=K7c#h6~{60eJ zU|4@f4h$jA)S8LP=j(edF*!}n@9@JXv@L1~8(g%E(y+pNvI>FZ{Z$~0FO*S?3V}YN z8E|CXgo0NDbr)+boGEnw;98j8rO*mqpb3i5s0b=-xp(eaVkYi`LnDb+Qi+>FtO)6M znM^K3)iaXuxQD{E!l>(ZjkeQU8=ax(&RAHh$frN@l~9R?ce8|$#Syv>JR1)Ayk?Pn zcw51U6U7K;7S9VEHKFEYN2of8H5pIMonL)M=m>KI>I76NH25 zWzr9-qp;YGlBUAwv+RwowxeOe^A`7Kre`C{e4OOH=tkVjroXCnIDg>{+1cx^$805JE_p=x;RQ|0BEsVV!0v=z5 zY&TGSS!FSkX^U-3ZI4(+;ipnyYKgPg8&=8t8|!E{1)bUt4r~&-AWZvw>9bu4s=*}- zB~H#^{f7=spiIv}PfK8yt?Y~Vt&$|ZSd?>Oa47cYwh)jEbQkzm$yiY!;GB;ku&)rU zGXB-QaHxtp0!3xv(SwK4!>|dVtvGlP#cD3%a2s=<#M{z>AZAYdB%bGUAO9dmwA}sA z|2Z@v?6e~gC~Q{&BN`Djq*=k(P~XZUhl5r4_v86phNd4p+#a@B+Y1b#g&0JQ%rg2* zYBd2pYXG-j;^AM1mUW`|OP8f_S#W9z7~TPwH#tvh3be8Id5pk~2!gf1pzpS@Xnk#6 z=)Ha;97K7lXDu>r8N7yvbGPCTtP5b2fd&Pm71Bs_ zT-hf@7ATy${;Nbk%72}6;k2zV-Cx&j%Qrd9@ zzBsi-3MAez4I0w3`*-h!?c2{n!>Oau6Ytt5k&6oWuRdG+y|D?v3#GK{J9++Wh7l8m6oaD?Z|1qXC!WO|yhDSE;r5F} z|FxXxrgp{%XG_~f@Ixofz_;Iq3m<<>o_|R^U-47^HAM8!6g+of3ePF9U<<*yuW75B zR~l1M$QZ_GQ4@}wrI0T4L)bO-)Z)>m3eE7dmowaA&858G=n##Rw$pTfU_n8|e^x;P5kHMrUg@*mCaT zrjgeUX`C{jvZC;yej(1dFGhShlv}JFP>5XP8myV6jO#t(eblKqJJX$G4YpVK=e(U? zG?oG9Q6A+Cyhi$@Oyql{l@9A3nUh}*&+3A1nbvHSp@tpT70(VH;{EQE{3JK%1^~_q z-#$;ipd-S46u*=U+y?+47ATZv>A`nDjNaCOuVU}L$}YagDB6nhoZk7K9 zee9=dIHLP5QBshRIr#5%k9{(8`xYM&5$<&hq-#yzdtVv?vCP7~iAebB3lT)YDG~io zKKXAC5d&Pj`!A=WRS_C~L>`FRnZfRBAx6{F=8g^dje z;VF6AKO#hreYaTG44%z$h-V=}YRnZxV4B0CSH!(@Be^`S6#3vgg+u2lGHM-;3J>Qi z;d97TBqZ)f6bAWBWEWn9<3v=20sHkv&l%@$$ZZjd@;1uu8liIC9TflQ8N`Z{dzXsv z8tsgZ|Jxsg#X^*~s>&GN|MbgmSrY~i3{4Wr=skgm{eKNpXtYc_WDF`Fl|<3ZkG`P2 z+C0KjX|Se%MwIO$&=KNoKV*w}2|LNK=5NMCP{Q1wr(0D(SD25Y}-q8m>!$eeS%(+@7oUy*W1sqNJMXX(^$2sUq-T83!^crbkIb052sM}Ra1auky*@ywI$n0dA06UDH4zT$ zD+q0P$bRzkpW+!Cif0^|8$$FZ0$BY)_Q0^sVtQ>Oz)1L|J>o|i{wu-jiKN z8DK9KhWp5cyb|`AmH;eifK9mB0u37FIa$2&8!*I~-e+{K#4AZotazPIdPp^M6Lu!Q zxIsa%#ZbI~=MdPp`t%}n+M-|@ZEaEKdB}*z{_lSdE!Q|N1RK5H$sl#}#!VwwX?t}r z(s=RG5Mg0ly8n>;_B`mbf?fr@LgRo8R?GVcOuQUiRakuf-~k3FJi6fNCI*W0gy#=~ z%kTg2hcWd`AK7FcHEac0mxvmONh6>W$=t!tRsUE>Qv;a*q)kH7sHnmDLge=2D z+#~6o0-|A$hTTgiB7U)M=OTQa23K9f40D=dN`Bu)7g1eDEH*@8orl zWBi0KbsRWEvMEU+ujphgQ7>zRKn*Lf+6_*v|)4ZT$P z*O(y82?M4X=mk}l5U-`58Wp5x&cWxnHs>yV^*V>?3_imUbW?ML?Z_t)421*V<9-<7 z_^(G1#y0Quy}dm-W#6=iarnDl{0fx9%`8d^?^u9NmF_Kza)Sms^H#@)h|;24j)m+r zYMPJkS-1Y_2jSlRyJ4%ZpT6}i25!Z*yGOg+x5|9B2M1~I*%5i~3g@pU^5LC36dgR5 zt4Gp`Qo$aWL#r3GzEOu zfS0!DYCLu<3_f~@)vz=)(<$cellvGlPKP_U3BBe#Uy=rxIeRAVwFSRa*5}#BgN@{h z-y}My0NL`}TVVhm`QE?zd4$`(d-q}r()_b$7>%K&%wZQ=efILj@Cf5zJ@`9AN19bq zvVYJ1j3cbeONErYUlLfomz~s_}nqj(y?Tdob9GmqrG}R4+D5+0A{~L&QY3g79*p#L7saE2Kpj z$ygLpCdCA!e)bt{ovVnbgde?LCqvpVuTj=f7AYpGEK7P|mTm#9nKq*9`Y9_!+g5nS z_Vi>ZBZYA<%Kiosd3L*5M+UM*n!mGjG{PE>aj=Xo1Vq|VqbU$2#H4ZqBgHy0^W<}) z3MmBGSWP-6-zX;u+o^++7YjG8O9lJ+(|!!cL6uq{^xxulH3pXj zQXUUAk&cQZ#}okhfbYpUy2O@A2PW?@;De{!aQ;ltZ8o zK1(|6&rxWq#$xx>@BNX6_zXk&<&)AKX_$N9weF#MhYGQ4Q1%vvT+`Vz7zMx^_eKx9 z@U3CM^D?E{NTWD-hdj+^Iv0PK`S0N-p4fYqTFoN`XM@Bp;hco;<-sEZXjB~}8Lc~e?j{9Hg3$W{Iw zD)BO96>v9K51L4=KxJNq;qHkzc$f|aZ;SHDU=^et$BrHSzCXFuB(;VamTzdU7Ni8A zhS&=@3TK8}YM5{+aHKXr3K~p5{s@H5OW+V_M2y^bLKqMA+o0RsR*cWi}WI@-Za0f#PaMqM4ChtB@TLOL^O$# z%D;f=@EZ5rd8PHoFJAqx6~Gpu1l}|>Lb#?VuyUUWqJrcZxDR^J1!U*z8B4GwXx4dH zR;Z%5+v4qB3jSQ6Ele)#?R6`rXYI4RU!hU&R34VuYAny|Y(*Oeloz8T5ndJ$3@uO; z$X%SoTY|(AGVJ99XS(@KU#L3T5{cVYg#JN7iI>PF&ugq=Gf}*mt3!h3d{v}HNYBds z)BB$c01A$-)9XZbiIvtp&)a{yehIecA)G20UphyzlSj0*>roJx3H$5!(+~Y|G>9ow zD%9pT?hWl9y%l=;pT?fYn2^HQ?WbYmDc*EOLk)e_X~E~7_-sdFWbq&TPvzJ>mLNqX z2iP^t%3j48+AS3zFlOntutV72`oq3Z)9d`r!RA_J>>SFN7KVuvn)1E3>OP zg4dT05R(Y0H3%z>rLs9JQ(qefC&%Ds6ez@NQib4i`=9?nF62U7yM!}K5vH}5 z2*el&@;8X|!K$u-s2HWh^V-HURDGC&o6|4D;4Q)rx2V95U@N^4miA$Ic(Fc@;6hE2 z9X#;RrmUSB7)2Ouc8U?qct#<{5~>k~rw<;*=mftP7Q~?)n22=cAgu)#C;mk^SFlro zFvKqXEs=Mq{0fues6#jrZp7bma&R}ZgefEZ4gBU0w2maFl|7LD7$)7;(S|@V8okTX z$x*^Vlk)Ggq@Vd1Kw$HDj4?J*7r=bGIRvVXlPG%_2o4?2#Om@R2(~-y6Tm?gfBM}& zco@#(W%T-S;J&f80XQM;gVc!^LkNa2$a)NIR@>iuxGmBE!&7(J?`>#vQ5$WLx;pR_ zTit#rlu*>Gw4yw`eVH)Em3&fGWMlb6v$Domfr002M$Nkl|N+o!yrzh-ko}KT!%{#L(?9ua7FquM`o4I*2l<C~lb*Wx+fXAZ5vhi5+f-FKl2Prvgq7f|oChENNbtzw{P z##r#||NQ%qdH=0w5Ky35x_%>UupT2M8hGc4<8)HM3-|144`Ir58ldAyF+IEQQ$t|~ zWoYud+cCU#n&=pd52yfIk^cE8sW#wyIYPb#xNH;GNgb9^I)Fe5Vv5fI3PXfDU`XZB zd}jAsZ@NR_MSh~7>2G;r6so`vy+fX#yg-Awc$s*K#%y!m9UAiFuhLqTccTPUoK>Xd zMeVhP;a}scv{;xECgdNlM-NCN9Z`{okLCFIYcdK33GelLhekVToC><@ zln=_Ql1$;b<_!P2ynOG`@L`mKI4&(P+~4^NzuvE5LIa5RDlj`o`LJGNg-<=Bo`*Co zy+>iy&tr`s=IuJ9tEWz%ih`_gwy_P}hYrWEf5@-O{{`CPsgOwjoab==5K(yGFOg)n zQ}!%YG46cuzyHT@7vqwn_ZnEPLXEcG0DW|3lKJK#fIErq^D=!jHIRsWL8 zaOE7He_&PIc=X_Ycp?7LdaoE>whJBEMX+y!HmO+jJbDz~{_tAt^l%OX^XQ$P2+Okz z^lvBiYy&=8-H7K~xfWy98fUnQTmT^p`QV>?VxC9>Y0kR!b4K9VicT1E#pRVH4A0vb z*(vZ_(@+yK8B(+`$dyp5M>vybs{9Mf%2@JtY5e8_{J6a_6gQJ!+)uOw_ia$Sr=}?r zN_Qx%NLt4-(Re>4oy(2~Dv`=7%5};)(oa)f2cGqXGoN0iSnNv*mr`eFFM0A5p4}id zVH;SjAu^*bgQ1(qglgbr_Ia+@aV_E8;$>59V>k%h^p6Zvq?kG{7$#zyNv_YQhE0)O zeZcW7e5?TZqXs2Nx|oJ@Q6BAw21^SPe2WXF+1Lg)$*xKH_g-aIqgTC0Ia0nMeeii+ z@4urA0DkF=QEn5~gdz9Rp#t~rpL`mgPYs8q2ec#XAnNAJZ)o#(IP3+d2QfHX!^`?J zJIJY5e)jYD?-Jy>{$KnyOctP&LWgUBuZ`z)RQmEhdsH2r1U_H7k&F$#UpV&tI_6gM z=tOhs1W^PikrT5a(@exN_~p8#SK_nxi=)m{dMJ*GcgkkUo5F*8sl4xf@(YKbOBdyD zKFhuES?#RLe087M*Vi9^YtW2}Hup(?g)Jl3OtVY+mi$dRqwJ<3Pn|>utLu?YNi(JG zFIc1W%Fi@-BzRN#S6>hDN%-&dYWAypR{SB&G>#Fp)<3UUg5EdiPa1OrwNyj|KpT4upt&-0z-v zuN@B}PeslU&U}w^(lFt?JO}3y`8IS^Tt|G#LKaDRwo8cD%a5U{X>8z)msfZ@O0 z9Fa#s$`DBbNTo)vl3qSHT%kgsb2B|qe^jOuU~AQL#|2b3*n{%j3Q-AZq5{TezTdEr z6bX>#>Te4Ka;otjnX>@ydldvcP%TOpq)79B{odFA_8vn(ULRWaMR31!B*7$I<97n3 z!k-8w07}UG+@TT0HF>|ERk2P9fT5!f_sZ+_zL*m&;gsk)%F8Rhe~yI0Jw17{I~r6@ zojS>P%K-AhNX%?S6cH=lnfsr6s^H+hrv3CA=jf0~`AmtFjL7r!%p{I$gpyYsq97MJ za4Mzw;B40slq(dFG+dKJFL{A{|0Z6raIRrChld+$B;Jb95E?#6ypZG^H41n#}(o|F0J>s{XFoMP5q0sh$RLu2gbk3NaS zIP&Cic+LGcm`4Tm^|fa>wupJnk4#2qg^bWSN~n4ceXhdA*Bbe*M`BJ4T|AIsnd;>F zWwq`hUJr)VCzM>|6p;SD z8SHE=bM*N-AjC6aFGCmCeU>oJWKbfwPCRfe&QIe;rE?cjSfX)JGsfUJ(cP0Y7F-z` z3};w>@0X7w4*7l8;##9Z$l7J>b`IXht6y4Q6|)%ZU_L>o*n%=5Y&clru`!RHM`2Uk zQcqMqmnbgtFDwaF#dOLCk7Q`#sZse-u9vwO56(U_8qjb24a-|Uu401?!FQi#w>1pbGnZFH*&R~Ri z@`7+Fucn-b=t=uc`XZo^mz-99Z&9811Q3zIbu+Yv%+1t z1Qh2ZdJdGKxXq6-?_;|`eAQSNXI0q5dH2k;;)vJq3h~L$H4I#)9iZyr)K#@Y&;;Mp;bz_lUOY`Wn`QLlH&MIh?!D&Cy;Q`PG%7%!GB&XTxSu zm2{zAGu@QyJw0NDedrtJXgG~+n%Oz#C0<25pCN>TWiiHcc!ygfly!uV2H?I$`eZzURO zRQJKJK0^_P;Nj=~6f=h|=uKWB&aOj8IlOP?ls#Z7fR_rQLRT-j3X?wGV&z?rUy^6x!O=MCYx6s!YCVMeD;E8AP=9_6CU&(`p#E;0wfVur+ zrh$3O4V;tHv()tWh5EaT!gf>?$pt$;0JUDz;v)gWg(Jam>_x z=kNWEy35;DxOGCvd&E(*0<5q0yMD*_#0TNzaE`tgWf?N#KQ_cc*X1zSkYu^9HE!Gk z9TUnu@laaxx$+zxLGl*Y9tR|*;b}w1LmRyEzsHfy&CiAkN~*-4D8s31FX33)KAf*M zO7*C^J?6iL3~YfmRn+I8{dM?+JzJiDvp#1FIKOwCL8H9%l!})a5YFGK(MNEoBBUtMd4y>E!e@Tqi<@w}O@z78M%#b3aG z?XR;KUiI~cO^qbxc8><6|M0he7jE6l)=RtITK1&lA|+hE_$3Y3FiJQ|4lIM$&xRL| zpGAFX86yXUA(Z#@(5K)kO>r?yxnFGtV;b7lc(=CO^zI?>ZXU%P zVhN2`l`V@eUxj9x>ehj`o@8)Drso3uX`Ojm2Y>W%B3!+5gAV`u;l`~S9JPupJj6+} zbBO*zR@2aAH2$5x2E{xL^@`|_Ec@5g z!CC1;<8e;%M~C`~vRr*#e0GlNQU0xdDjqw$UfO+Iw~X?a&!l~ax|q6-Yxa77)LEoq zuT{TK*Cw6p;>Wkc6O8}HE0@D=eQC($`b~_scJ^I9v4z1}sgBAXsvkL5Gln&E_h>wM zFhkQn97V&w`Z8>f=)~3`kPS!*WBHgcPWC`rhuLmBH1f^o2y1&c?UMECyuH7+kl#!D zEFQ{3{jPeR@4F^>jxxgGv*a;;uA%C0_eMI@P}Y_(cqwmHm$xifIN!T>H+%(+CcV+? zH1y?}!Y(!HOAYUQo^;vYKM?I5=j0#i!s<8TmvgnWOFO}}yC-HBYEw1v-8p2i4Kg+8 z?XlnqYGx9|fEsZ2J7z^2Sa7)K8|t5|&(C;V)Y0ut;2M=1{&ol#`Ha^!!GFY=Rh)0a z%Am2Z6i(vX5(c#}*Z5b?Xqfwbvp1V?maFUgY;8K%@33*70c*>})H~$&+M(i=d*JO~p>Pug!rQ}ZY(fWK#i25wH(f;4K-Z{qs9?)16wss88rv~jVVM}6 z(N7tasUB{QhOmg~cZ{lNESYL3@tJvG^uHKSlpCwZOhky@L=Y=6AqBZVdU)I*H_OPq z2=VqX?L+2d8mPlmULz6C%{53cBAz343ym+{`p2|ey=Up!3F%D_Gs2RO;-g`o>J$B{ zYgPHMjx-OVkQfS4Iy^I4gd0VnOet9F>scql+f3H)Id6$wCCFX?3X`{oOhlN;XdKQ@ z#vu|Xn8_q0I^pO2-ESG4hLnuQ^se&OQ=#J)$2U=9w})~d9>~NJ+G)5>zvt(!!Phcw;UKOk09=zo z&UN^AY)W;#D^#?d=1kVWzed(vk2oMhc3$4wwMiE;H|H-- zIWPYv*R9qsNbc^Gdi(blU8vZ49__j;8E-?;W<2I!4l7%b0^rz1C?8cYr~7M3lIm-W)S? zvoQm!p@xjCzL8L0fD>$k4!uubg?be04IDn_&(*=^^E94jLc&>z{-p z;3}?}w!Y7rH!vtm5YocI?2_}~q>7d}dBAV8zHG!KJy|a0F?CC%aBo9LZO9mp6}*RW za#Vn~9=cFLc;};!NSVzZ;Wi6TG|Dml<^6E=-S@*w6xLksBX668#q>2c}j*zCx}ED1csNTZ`LxJp<)@-JWkK={KY>DFP^;!vqYX2 z21ZfJ&V&h^U6aspSvei;pS;E?Lxc@^GQ~BfX?wE7Q7#U2%0fKFrwV#7Rlk(=dt{&j z+MXD_uX^9qtpi#dUKgS=X@tjybQ-79h4NQ9p<-@!TPzzw7HSad^iVFRNd59+)=}>F zELl@#__v0yw4kD{b5nk0+N4efO8}Hr(w;bB2AcKsUh6QLuJYz{%?41;N4|!!C;ySB znoS^``aSuxbMv~C3816FdniAA&ud(B`f+{oUf1FJ)fLoNoU?eVLqVBj6v}zL8A&nZ z4dJEZ!l8rJd#2%B)OVcc37nxC`quT2;{4J%p_9hr2={oujwq}O^d62k9S=1pIl^mo zBX}g>GEG}G{&gUD&wZSW6*uTJgK?7!?52DB;wcfP;O;?xM)J?aJE$<&-S4)oqrF1{p+v_?9|WZKmReQcISmW#-{hUm07!J2Qu2l~mfSsugKWPNowJsdv6G5Fix zgbCKybKzo`vV34^CtK6K!CBqNs8cx8%%~gr)vv>8dJ3qgS#EUh#`SO(e2k|P5Lv9) zrWeE@1{gT0L(YBLBn3R~;p_ta7_tUW&sDOt$P~~yrhHK6t)qv|IHv^pI-f>;wU;|W z-)FxMgIrzDC+tt*7&vwednC3p#WZgB#=UTF(-2qHA?!~zi{tvncisoKKj&i_ z*>!eDgI))Q4I6V#kh^CFlX{uX>4d@JCwkx3bOQe5F74FX_h8rg}}%2UBF*>;J>1 zcivAPp$?jKHt(f8k+%K&O_1SaQD{BiiKDV29v$iLrc5T%oJOk01Z(W=!zb5}bIbkx zVS;&HyLE$}L$zU*<+m5thC_~BUYp4_(pI07E|m4kICW&7smyVmXEG^UG_2uy>Xb=e){arlGFb>)%vhBoqlzf)iFM&qlTeU}!)1!4G1iGuPmneV)W@Ad~E#B21&`}^ZC9mhyj-xptD>~W+a4bUF_=2xK#WjPOJ{|rX4r4yq> zvk#mfO0_s(Eur^y|Dup#T_aDQggnkvKg2MLDSF)BeRf^KQ^urH?tW*xijK#9mlQSuw@U zbCfAyk6w0_KGU>RN}ZQ`=l=K{9TU#O-=<&JXK4JCOTB3UUGs~0Ru@MH#iwH-TCX=v zCIa1{Ph#NJQ3hlErQda}3J=#O&WQJ}DG6K^w>1pPf+D(|Q(I|0f7|7A;ptbOhs)po zAWY5Ag#(O*(i14`J48~CmHx8`++4~WDwDG)>Lz#aHt^a zQHFw7!i39niz2?tc*W@gG9^k;cz5VpU2#N45K5G(&XE_O=vQCn*r_VYCmuZw`x8WM zW;v%AoDi=Xsg2)1Ssd>Emp_i(mp4$%TA1Ip%U8qm=g&c`ys*TH0`)g~!eswoSb1R- z5yupJ=QwxgYG}W5J`55OmmUg9dp<rsccziQT)>JKkk*OjWU1fRl(|< z#OX~8f^wZe2&LKIJ_|kPx?>Z(gdg5QoKktbOc(c)7(S2bc>e)SG)I_A9_jx6oFMz* za0eR6l1XeJRR@2ueqF~w8}*vQQ=?%P2Z8jy2ajz)`QAi;TT3aw5J!74Ot+zFBoYQC z4ZMb_gU9gSCJR8t#!RG>82!~4N>dsP;9V)To=YgOMcX-H`RQ=m$)8HdifC+Xiv0pA;fbaT z#~v-f!2SUqPiXYVPT~c5mLqh8{3>d5sXs2kA*B(wmbV|)PUeQXbIoC$sM*!lZj?J} zqk+vDHA|XUpp}Zlo619t;&kF6}x#`}#FXB`MA|wPgK_ zg$)e*BkGMklhL&|5nWzJF0DaVVK}S!xW5`I$}r{XC-nW;pjq5Hy)tx;PjioT8hx4a zuZ&(H68QEwg@G&Yu&cZVutu)Nta3#@qCAL(^Kn2R8a(hGmAGhRqll?&IdX75Xh4e} zI?%j_@-ls{ER=qPr}QuX(%3iM-tWnGoujf@{_Bu;I^@5R4uO++FHcUT1b$Cvfl8q? z>Ku~;z(|qna81&)8C}x6#))NtUhj_ve|nbBi;5(_#T$qH9>hh54h7ei()*L~uY<#9 zrJf;{L8u!UB^IvfeH|X+oNM>EO*0nH5tSY5A0>)i86#_U{NG$51(pV)o&u1@-S_Us zph@Va6cVKsVH`3Udgs8)ZiBx&ti?!{D)O5rubzyE#6Im$<7l0^fa zb@iMNtE6$SY!g^$Z4OsH_`u$Z(GaL)e}-7+1P+WUGZtt(m`4`WnR-qLBI99ZDywta z^v^TFbyjE2)9A1qM;Q(j^`L2tY)3WDo5c|tE|Qh8jr>037~su(PFd)t_MUhdA$w^=_T@g_EtJ{EzZ*+zB|;T%nniyk&ns~q+f9?-Ou|-=kgfuBMy44 z_lhu}*u^>JS-w# z3UJVu^E2>-ns|6e)Q_2?GTP^;W2SxZwfo{+HR!fD0wGXt(rr$Y-e((CyKBvd%K%K?hQ`|tfVUrE^hM%G2EQ9*%7z>4$R1rs8Yvs4N7U4jv_T@4-&OEi*Wur$eM$rp zkbu?rkg+-x(vcweI|7^UffDiiex9Cb6A1eP#2QzW6p`3_xsfSi=e2Hlc5~I^Dx=co z{Y7w7&)rC0du_J)h2CY-ZMly`?K)HjM0gc&eX4VF^O5LWr%0j?Q@IzWGD-Kz zzkT2J`3zq>gt^RE;&4yWa1SK>G-Mj4302nBguw-x(=qp|V$w~gvxMl}B{pFv<8e;T z!Dpo*WB2p+wzDWa^iw7MY?~%}+tk@>%+J8gbsXr_S$#FiS={%+2-yK!5bDKu?#AyL z;W!B#^QiaRc=kNBe*1kQcw;nYY5Di&D--ltuF0Ro?464^AfbvQ625yPGmudWS3h@; zbU3&sznj(}gLWOex$G6TR&@_io#!t}wa*@vrm!P7EnNRDCnZb_goV7LXtd0cPUroc zi*pk{ypJ%dqb4z*WASE|Cd0}YDOc}wlIngLgQ$ZujbD*DQ5_lzDnj{wVW`S43q2h@ zoNxX(rpLP;=jgnRoVf;Z)FwUdi5||x(7o2EdvyUR{wRi92lSf2GroxNQI8U|+)rr% z5tzx|;mFLq=ky|_31lH`5Epr!fONX8)r|;qalQI1sp}dF@1#h4l)2;@XXyvD>!>RAWP9JU;Q} zBniN6~Q^EjyH<57f%WF4)@Pk3E{q7;QH4%V~nXXBA(1sK^4DC(X`{sj@g zcJ{dvg>T^T;}`{9Md_;Hx$f!fU;HBE5CNYaz+p)iOg?;PJr{nkyBPlBzyI&T!=L^( zRP4YT!3pVhgQ&vP&wo$vg8!T*Wnba>zaEBBPNY-$nh_P1lu05T@>2KC$bEay1)^!B z&XbO4lfCCJOrvcJ-5=8rfRxz5Q$l#;x*gHN3q4B~FSv(b-*q^Gkyw8vhY{aD?`BhWo$! zk}Lqq!=T9>NTYL8i8~;*RvD-aRhcs~E-h7?nS(<>BVYNUf$#n+m%K(}T7%f{>6n!^ zoR^tzUMEibnF^H#c|?&HN-W(E&Vvt#1WS8Gv9N*K10J>2Z8#4ktU4?8zcI@ zPJzVRg{7qeDwoL_(AM4-`KfY3ymB~SBjxG^I>^1JvRWDK`@%qYC`*;GI)Hrd)}33i zbioV*<+dH=jpTQ9lfn)^EGaJ`(mNCPptu6(6%N8pGJ%RKxDFm+pOTlzoT|HB;q>Jm z_%m5s7%DnK8ZpdDS+6|>#-PtxXd%4Dd3m)veDS~j@A15J=P&QvS5JTrr7!2F>=^p% zpM?gZ+B)Mr)_C&a12PV92F4Km>JRJF7~^DM*pP6Q+I)w{x?0-m5q~ENvW~AqG6m!V z>O0l7HL=9%)V&L_S59f>bf~>_o}dQ?2fdQQ3_NCqX0RMti-?GZglq6eJoi5CzdAzF zm*qL?DB^#d1315r(Vk&Hr#N=79tWp-D5+g<^y9iR_zV2Aq>?@m@RmHXCExwzqcHN| zc|1zlsQ#O=y2Fu+1TT=Ihh!SA!G{Yd)vPY3wwX+&88QwuV&&s8+KY3*`D)BcS4p?l zA)w)_E+u~Hz)(j>5o+;EdiA?+uP+(>&PNzz;P-w-@c!{L-P^P!AJUNzd^8 zdpIUc<#%|!_wiXiSN+$u3j^=xz3q*Y@F8nYaV$39Nrt}nalZ0#*Ao>G{uTZ(ZtRY% z!K#g6KMs3LM1vRoVIDorJu!3B=lkRQwLdg;EuS*eQyO%rvp5&OV-((K}5Svo~Zho_;036Zz)#H*BTndAPgdQ=G z7?O1-Zq(aD!R-);S1yz0H_#tnYlwJlLKc~+2&bn=WkjVyAuKQzN+O$ecmiCc@VnXi z4?Lm#=lzps%6l56H)X}|x$!w#DKkf^+$9%~Us1du>YC2>q*TEFrl=&?%jBG=!e3?}GZtYTzArMmPGRh83EDOI<1=K+G6|pIHE$0E zw<8i3$gkq#FtxNAgUinC3lC{XLj>IDlFyNtg`apL?6bt3O>I&r_}c57>j@OnwO$(i zbinX#b7YfVc3`^0zRx{*5-KithrYl4G@R&c2~~Lfo%<{5PeG1Qi}GNaQa;}K=@(D& zv>9C@Q=qsa9u*`^GcZJ-nSSEr`N#DLKi`+AWnivdxCsmK$k!UvW}V2uWyT6;*X3t2 z*#nNgJAI`mj6Q~uv$t1C^^MKg21df2KmB%iHb=K}6pl_5>QU->tEx$pK9L)rtuQsk zD+lFpD+iDE;X22k!9Yt8EOfX(5A)o{s2s&py^rFx^@s=uo$gmjTU)_!wKiX->>3>I zrHsfub5F%bqo;{p#e=uU;@mvvqf;yR^mXhcuM(~9dKTkW7*wH<4ZQ57ArMi8#=5YAK|S>O(`fA3d@#4NnB(Wpu_v78 z4b#`CSCNsnjdl+o8-AaB>yz*RMc3goRSH_(xfB*o?1XC=vEyGoNAgjBi1H);$S*W# zq=9&{0W|M0>S~woQ!O+$1((J-((-`F{~|`Y#(z~qbxi-idh>czQcNv%KOGHqM5j5! zx{!!_8PBOk=*?m9mcxUjtBB{&xCX~E__;VwT08q#iy}8qBdAU4Ojo8bvL_e9?eo{* z>!(9!Q-HQ>F!kHTMsmz{-%3_NrhoXy<58J{6vJ%bXi2VWlA(%v4k z!d9W@;jh1rhP}rRI^@gZh6#4wz3+Ni<`_lXGkqt(F z4B+3wv%8=vl}Z)jvDwwiI?f1;hyuz;R4|>l3gHg(DM1k* z_~Rex)i4q6ed}9q6ap2bsoq{l#1gmd_;)@fO3S^RlF^+B8$-ns2>+ z%$eV$8lS0+nF$5d?5|D?hkYD?OE}t2fsYMDS8T(yZSX-pZ>ql8jP*DNBsjE05C9=oLTA=1WciKg+abBCU(Z?)lkHqVLDbqm(Q&9Ex-&502L&do=7d{=HuQ<;Xhm7o#z+@vn13dFtGS zozWw|uMA4%cdo~wf-1eI_noUWrGs3WQaABFz8ACqaKhOmL^^go{>T^Q4e~7wePQJN ztp|4=zUPSxHbdJ(ew3EeESJ|Ri+izLgG@2Ye;C_1I6XaNd1i@>k0$v3ay0(^Ot}@R zbHh0@w+4v1?SDmI2C}3w$h@03ZiEL99)vk?)kbrB@(-G$>QJk@$kE2k@7<3+3WI!p z200_oQdfFRy1tog7ys=0q5n6(p=661Wt?ua7_YZU?VWkj8`@ghqJDJ(oZT(S4Yl-H zv0>)b+qc744hSLgW5&2>}{CR{vBV|M#8`w+rBxUaQAHNKB zXV2k$Zl<9nb-Tcx?n2R!cn)t+HqXHaENPHGKYH{i8lQ7KV;fkzuQ~vY`l+-R)YXR3 zpZ^R69|yoNMj=kTP2|YZ!6wJ)-VBdlK8yO9nVX9|{}j%j5*!noe|Q$k3UK=4WhHhdcoC?FyFi{?Ojr>Y@xUcGhe(vylu0z?F^b+6qwb!+=7k*EeXalHo zMY_(AamBpN20cVZ*ki^rEuW*TeSsl;>4Og>0aMOFMlgoP?$(du;o+CL){97ldJW|~7p2AdJQ`m?X!cqR$NY5DG_nsQQUTg3! z>gPG$38NP~;?3zJ>~AABiE>yNk3jzp?{7AXL;hBY?c@Fk8&S_%`@x~X=u{KVb_l-7$I+j8e8hSCibObJ=ehsNA03(QfpGEJ^2fmS@>uD> z=i1ma>dM}TVFX_rNZ4vG$)ATgBHf__(5x)W$+a7WnfMeZ!RP9P(vE!G2)#J$oP18^ z82_{>4cuh)E>4F7w)QjfzTU_AI(LIP?t%E?dc+lJ$!pwKo%Op_S$d6=`~UbK+!Win zrQdJ{fTsZ11yo_YNtD{n*6U_d4M#3Uf`l&ss{pP7&%dpcP>~b3B5xujH_y)r7-yrjoyW^(tx9__St8}`Wbgpm;kkx)c86}SM{IWLvc#1LG6>{t&1 zx(~uBF$AxT#K|)y6q&cr@qHC)y>ohW6Z|9wk=v1FF4H@%g#;_Q&DxlqM!)mszF~5_KOE{q5sWefx6k>Ra8|5Hffkmob{=P}W?7xZvK& zFlB81PHS|IGAUu^{Dk@23|VF&{M}#E*Nm7rgunMGf-zgmxiyP|g+gR>du@-VGgmMu z>5Mo>6#d3}(T47K3QI-x#nXaQr+78`;jr8o#peW(^Gdd>26SmbTs5>;*SzKKT z3r~m+BTu9g9b}Oi^32@=(iv}bha-+aTII~)xq+-v5$8{1yA!7?DFMmE+U)%e&fMK0 z=5oANr(AiqDQqoswlfi=f;E&l8ZT906U~rE@JpS zr)gqNLq%x3iUEn!VHZQ_fM}MHwnchb9AR`{_?XVh81VVf;y!eplriZ;+!6mh+cp}Z z$Bs#1T*s*jofuUQ{*S*27rQRTD3<+5gt-|#(s42-Jl|WP)74Fe4j%UnqRl7IpkP`r zoz?T=oaIrCD90L|gz`sDvePI zx`Bailt3OQPRak>FAX0RtX+%(DkP($c9XyJ;dNc`z5;}$yn7YeU1kls6!(GS3214S z^je)2(wPEPIQ2h&9?$%~jNxwG=`)OoQ;lcn>QA=OgNI=n`rGIJ+c;~iSzh418u;Sk zEYT;rS68)Un=J0*aQe&t;eQODefn9X&m9yBWl#iKMdvZDmcV-*j8Q>BAypYF z;(0nm^XQ|oORtG)no)NB;G^*R@s}8>oQ~7k9#%FeBS0xx;CP^N_G%BAv<2Urc>OZm z`q2;Q>P=q+6!4kFxv;oSIUIk_4spC@OH(ZUkWZPqXd3VmP6#`Gt2pga-hpR3>@RPH z7I4C5UiN0NQJF@+d|;F2lU+UM!q_k=$SD7nb=hOWoO3ZH0hXC)IHcj4mD%!8d43u; z35>D_I*~snne6ADP@|Enfvr)ltTpvr9-39W*mo3n<+^gnXuc!KJ~IW33Q2R`R|DUD z&?)D=HTE4Ed-5Ky(dhDTBR*)7 zzVC27D#|th!RujLNn2t<%K!#c?x+R37EULjzd_)e{bUo*5EGH|^eE#Ct3A zH2osQzp9Q7*E8_1JoG4f0;puRkwr3&Of>SJMok+%6sB-uH&w(kfvpO9dtjWd!k5)E z)Mrk0pAS?2@Y~Sz{_WT>GUD{7pQbx|&#SE4ePJ`J+wr!*2&$AcG^a+fMa>`ch5oO~{gi$zv_voxPpkbgwCtEr# zs+MbSBim+xt$lXPWP0}GY5eUP)WsGsmfCRyHZ(S&Q|yvX{t6?G6B*D~mf%fBQw5lo$LX*LLp{#yog+#kOD~byy~!yv^sw2TSq$^= zm-#Py!-jhdUMhPN&Wr2*EuZzbI+S#mWVkw%P9^1SqziCe+`4n~cIf~7aky~rR@60C zr;w>+7nnKbd@L=A1Jc#7w{c@DnF8~`Zy$ZwlZo1zJP~Uq8oT?frv?LX_h^rXtb^g= zkG~%#fqUI)QrOX9l>27*s$)1Od7pEYeq2*Brgb7}M5p1p)UDJ{{Eo6D4IOT-%i%r6 zLuG<`Uk-d}uOug2`xie9dG)p7%EupvAskd&+-ncxD+d~ro~5O#x@^|1b?mQkh;PGJ z?@}gPR#zKocjf1gLp!u!?*%hV9r8r=e|2K#ENrELG!jp6P7X`=<|tWhK2Is24O7YX zlz$l@Qm@rf>KfcPhdfE%q0ZpilM}$bOZtV^2@h$)>xG-}b;u*lW^i~P@9hv?@;~)x z=cp|szSw9p+C|68gnTaPyBb*H(1i;Z!z*Y~{w+@z1_m&_r$(>5+BEm9Z9*g)+r?p{ zXiGK6#+OU13R{bS!Siy=E@z{Tk2?1H1AK?K89L9QJYX z9>U3aUcm`I!FnC)y7Tj7a{?3Zz-jQ6#>ro+Y%dcgdx5$`=b<)D+btf5qxl5S+*5&>)ey{B_=Z4$5R@?O@9 zsPGsG_Fj#A$7@6g5lTW7mhy>Kq7z0HO!;x{;MnnJS#(vAQULoLn_Z}YC_MB6YLq&B zwkeFlK||Tky?@#t3AGjmH;gyZVOM&Yoe>C!L@E(UB<_z4UE-1;ymz{vi0{6=8BG}N zW21B{CwhgjEWvA@7+VI0k*@VVzAt09e86YBZ^FZS3ac$5-4z^@w?QhE{XfQf@!64y7{ykB z6<+>Mb9&p+;XeDBzmucNxyoE++G+UOeURZfXGa%|%kyvBID2~;Z*x^MX+w6jcNc`L4EO)|8|v!WeWKG?-w1LT4^i$y zy84du9nW|jWWQuqDj@Eyf}3MmyyfI+9$gbYx!#M+HVl>$RTH|Lj4y{O-Ll z%u$BB3uI|vcsOrqSwUn9vc`Z)yu8N0-7}lw+0A>TZ#WwNCy6wbP)3o1(!WP-?J6Cc zn~CNb2~+_#s;gpQ^G9;&Ik&ooZq~QM5D_u?kY!KJC>qjoM@MHEA@w{D#l>cKUw!d; z`0!hwgkJFH3<^?R*ST;Kd^KhLA_~DC4%4bKqSbtN>&2_k0`C*g?eDSi@Ih$4bu%7k zW9qheyM&P?{WP{_(<8;l=1g0p7x8cjVce|u92n$7D+MSUIo!{6=a+FbCv(!UnnDp1 z|7-*}fv_zAr*yKIad46>1cj>Dw1rZCqP8xaB>SNiI^QCFU&VYq2P29u(8U}_`p*0B zqVVU1zE`iqGLC>8l<}GS_rnIxj#JD(zZJ*Av*$Q+3$l(u@ZS=a321kB37m(IU}1#= z_SFVQMsPLoAsnLa*?MS=gk5Mwy3!!Ih{HmjVFRTc*tIFbYZwS6WW#KOS0@@cwrL0h zs3bqU|KlIU`*|c+@4x-~5C#TA5irxCu?(CVfaM`hHtT^GkXLQzIwQ`kO_DNPh=ERd z&>~qlJNq~*gS@*uUgyVRR`Qpr5nZ;PbS<*|k z&z%ow(ljz2odBjYyMNIz;~B|l_>f~j<jP^?JW*o?0jO3|AdJkzj zKI@qOD=*}8uP{iJp^4`ve(LE2K1T&vI2+|xSDDAq)EHG4C}d6ZIIJBSmPI&_uFxxF z_%%2wUj^r;hmnIA|9Ln|)dyP6k%3sr@oev2Bt3eQ%m6Z9uHOh#&|Vu+M3rSw949&V zz^N-eyB3X^QlEB@O#lEu07*naRAkZ?`{v0<@^RlY6JWm(=PdI*1AiF&^p|0h_0GUw zG}fmus24frZj)nerQ_4h7=^&+@B~Iqc}X}4&6>@iE@KU`u(p}zMRbiB_U{g~qH*PV zr7huM){OhD+%grqjQ3RFHCAhxn~p{m`)TG4VB`7i9;>O2v&D541f|4*Bo8eKlJ}Ow zr*lioz)1{GoHIwzc0<+ah=Z0d9F&taM?=u=d+$WUFFJX--twQ49ny|>NH?YwLtd+M zzs`>PG$Pc3D285a;%sk*n!1{(zo?U`n>MtQD$Vh<#cd}!q2(F#I29)U;rF59L`nG8 zwRb}AOHMBV-qM3~Vn9LtLj5S|uHu0BEv{))3M+@-aj2V#58|LQ_9RAq9~qIk%Hx*>yE^8wNW(U|7m3P`N)%)hx=l-jq`KA<#8TAnu1!8RiqIeY~rKW7|=Cf zYi|$tQ3KiG9K4^62DOW#gOu<4zU#1*z;$Z;D<97yk6fce$DeR<*k{e>Dm(mc>aAin zn(qmFhtHOwxmS~9y~S~S57%KJRmXC?8UMDm5g_3E>KTdeXtSpIIX6qcy~cHVz1c|K z+vcY)U%rSAg5;F5=Yc^D%fY>eL2DhFZ|sBPxi~N3A)OlFSf{MEu;rw0e>1}pfd3Q@ z0PBlnv@TvIE#sDWZ0sNdmC-0%O@(*ZG*1A$J^akNLUB}}3w-M`9B$y-#=q}L03M51 zS4RyR2q3YzQEr}$UgOa-(p9D<0-2-;nS`(kw+zL3Yp|P8mw9ouyRtJr z?3?$M@ye+EuCVa_3S*-gQTgS$iDCO)Kli?Ialv8bgb6nTf&|!_w|PcnDRQ` zYovqqh6)jm7E^u3FceBy*Ww1L`P9V9c(zgUP1ARcK3}HmKC1NjUe*a!8=0c;aJ@-c z%EG%XUgzHWeeup8;izKh8X}WHIog=O+er=GJ`K6nOKBQ+raAQe)i0^LJ>YmaYFInz z%+E6vK8~u7FNL9(Ux%hk7eZxeRVbqY+sY91uz47nh)qqbp%oa7S;<$U^oD-h=nd|jl?vMBs*Irr~PS-btnJ-?FF1ZnEXdrZ$e}eOl zQSyjpY>)el~$2-xMRe8V+f#^>=%4P)&#Kv+$}%FEFsPd|;lg`$rWZG78h= zEUC#H!8gzGd(y^9q8+Q7D>M~c);=#=oQDBq_%zV)GL;WdwhUDzkOJ zjW{ig)UM;099<@znC5}S`1nEWsIQ@WhU4d?+o{nJoEYu#7`#&E z;C@I?tH8>%-yHB(T2hG+ZvGf;+Jc7`00VJu9EadC{Pya*??wedrQJxt!!PfnOySUh zmvvI#JBP8b39LM8JJU*Ir4F1YlN{|w$LhH~y7e}ljK;C$P=gO1!i#WJ)^U;nY4GwJ z;qCL~=RQMuB0aqS?)$MHz^vEv+zZsyOP^!E`3)(`G#Qge-~b-{-S0v>#*BPCDl&X` zkI&{%N)L!?+GtREZNZ7PgTw#U4?hmCNBYSMAOgVN%pn^;eDD46#sBp;p}31CW#H#J zv|UBBP&*$ObEw7$D4Rsi3X3#|Z;5q~=PO8e#N)-426tWBX$j|`JCVG5az8YTr z?caqm$63_OpuOK9L+18J&?{+jFre zT)cEKeDTE>F;eaxDX%r~#bp)UR!*Vtw~bt-Gi8gkYDC@A3l%P9o`$}u{YH4C2l__t03 zBXBw+>>S>edTGp|ihqK614SRuXB}n^`JP6p-&+MY_9=bZTczg>wd`da zBU?*N{wmJs3s)|MCr_V-%j!GKuat(hRfvX}{*lFnI#=N)IH41Rpzd~9Hq>NZLF{6(H!sg^d&k(8Amr#TETTo za|A5%pqUF~gpgg7!Le;XsRSeT#6DRq@Gzt4)?aVq1W@jl^ZJlI?QZWPTZPhEpYN+XX(RZ#YnA`HCfA^jo%BoTN`2Ec`MJaUEOVr8E>8POGUU3@ zYjx~y;>_vf+Nmc`;t{gKY#VvdaQR$V#-US=GiU*r*`TTmT_gFnv8;T|}jxL-N}IsR{-uI{xJJnO|!ldhL{34UI0xs~PFUK6r*_3>@8 zsp|0sc;v9mT1SSNN3JXG9iQ1)Pdc}&edKe%NIgK9nDxz@kq@Q^?12xLE? z?!L?0stK@oje4MS5TC_!pJ5+39n(o}*#|`jtoP8F`Tu(d!08hlo5aRQ6dF(>g@`DS zRp=Zl3KEX#BpTaU@4x3u8d0ZvJw-hBo>cNlKAw3`MJnEKc7`HyzkYkbPVPmD&)>nrte&%FmJM}|3G~F z-Me=~FUpzlOW6)~x^zu463Y-oz)to+=R`8zg?pwoL%G9CgiLoNBr`8E$1rnl!rC9# zAj~u-WkRk$lgY$vfJD3sV26$giN_z69iJy-i^e*UjN8-+-v57o5;VR1i7{Z|&A?dLn`@mtH z-}T_rv|dvPaD)9-(ZCWW4Skg(wL0+dQ^SujzJo!BB@^fETHP~;ea!-wU5wx(5kXDg$-BVwGO;m?&%Iv}8pZ+x5_>(`0xFr58vTr3sxNF&G9g_0X z(-;ry+`kDLH+5K^ES@azS#Ehzm{=l1i6&M}ID9k|$B3%L;~421P?MgR=kZAOA7zK+7E$FVaL)!-U#ZaMFw^@oS_tJLyWjK`RHL-Ac}5eehOu=6s4pI zW4aHcXq5=Y76Mr%M~CsH%a>xr+1K&`voUUwCGqI-Bld40yz~9h;U)h2&)Pvku0TwOH!RUBp4Jp^qR2lXBI=WUc z$fwwge7?VpA#?irjgU*WOCy;Q9wiqQEu3AAXPcwZdq918%p}41H`UyxqibZAxR>^O z(74qYfAZ)_RA@|1m)yizja(b+xi|79qrHwhI7~FiO?4k6t3hKs@e@;`HSCqI>H`}8 z9>Zsvsq#(UsDh_#(Kt67KxdizERS-eXuZyXbey2~ao9`4bbreT#WitA+3HXsO!x4$ z4q`tSuT7tI9ciBFXg_6w!)K~*c;bg^*O1qsRxW77SzD?RZ|cAIu!dC!g3nMsc)wu{ zWX6?iS7KI+&J{-nJkx>T(Ti!AS)+kpLphi_)ixd6{n?>0?hzRr)}WVGg6!a$%@L=U z=EBu~_AwP(@EQ2VA^5UKR*Zag0NO|C3bSOtc+_SC#?vMa%j>sp#mJUj?roGN-*>(H z>?Nslbdqn4vhPS45C7T&j?3`;8u}Kz{=2^qo9GQ&1H)KEWB_3lIohv-!_*Bef#*ib zET`&(o|T7Dm*74%@Izs)@h_d}G*1Sg#=$hbeAIDTa0H0!8vM#S_v*!q7hxA1DTU{5 z!{1zk{T7sS?rm}^EpyE&_N9S23=ZHJ1D_|*@tU}&0h^LSG7EdNUD&PpogN``p*S}T zj}DWyHIG~-P_w=r+N+Vd(=>&hUX0GIR-9()qVjutv%E*6;n-A@J;}iL=E;bYW{!{p zwVjk~kse+T95*>aH@u>pf+HO~&QV+!FO&;!2STJH^$2CRazxqfd+v*JSOY^?Yow*m zlCiC$)z5^}Ih>vv(EB*S59vR!zP%pqaU|^k=iKX{Q>TeK7pj&K{2iL;mNuOZ)%En* zdi)Z;PMImPO_+MUB~VkZhKROrhqYOnGXC^SjOv5X-jqSd&FZ!4vFdZugu{8KAq_g; zq#OBuqAfp5hO#=M>+rQWBHlR8fBR0DTpZ(+77SQueG~Z0GmpTbNisz$*w?X#UqK_# zI{UaRuK*TnI5TxztRq7zODn?q%i+*b(~L8E?2YmH{`-`df1A22u~dx%1-y?+O?~kzVtL+6Lna4L2|0N7vh5S@BS&D%;af6hZNp6XB|J8woHV5X=zzF2fccYLzpx+*~90bj+d4{`CKFS(zvg^&N+HdbyMe_ z^d#XZe0AEne(z-#f$P?mF?b;?gta*8vt75JdoPay7QX7S_5g6WUiB6u_3CP_F~PzU zPlUG)1cy4gJi~jY;IPdU-7odCcme_IwzR>ajB_uf8Rf7g5YELkfBCkh4-jm0hDg`S zOXnByBi;eI1ndnyy0$I!wQte^fUf<`X8_DR?M30truwP4Cqq#nzCBc|9B#N?BfUf# zFe0bvoD!T!B5+e3p7&^O%BJ1;U6Da1BN8dpbto7$?IuNV1f|IL6kZyGX=u#20U}~V zvfR9^0*kSv5t|r`OeTl_L^c%whr%YMH8~gOZUoBF-hMVJwW$tAWYz=i$pk7bMiRVU zg47Wbz3wOlWo4waA1@=bc!Fos^pWJm(CDwhtC@&Q zg7Dam8HA?8qc&WJgp&k=b)S|kxE7x$6BedMr-Z%p61J{I1|`EwsX5+L!cCD4uS;+e zW(sfjQexjnu&oy!g`Hv2bco>Qk&)b3_XH?yc{9JIlPeZsr$Xgxy!Oq2^oEjAO*? zkOFHD1-;w}e^nq{i_F0xe8um?jP=x}lyC7)9255xZhlwX5gyK21|%++w)pjLJ`Z

  3. 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

- public static class UgcTransition + public static class LegacySteamUgcTransition { private const string readmeName = "LOCALMODS_README.txt"; @@ -168,7 +168,11 @@ namespace Barotrauma.Transition addHeader(TextManager.Get("SubscribedMods")); foreach (var mod in mods.Mods) { - addTickbox(mod.Dir, mod.Name, ticked: !ContentPackageManager.LocalPackages.Any(p => p.SteamWorkshopId != 0 && p.SteamWorkshopId == mod.Item?.Id)); + addTickbox(mod.Dir, mod.Name, + ticked: !(mod.Item is { } item && ContentPackageManager.LocalPackages.Any(p => + p.UgcId.TryUnwrap(out var ugcId) + && ugcId is SteamWorkshopId workshopId + && workshopId.Value == item.Id))); } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/DebugConsole.cs b/Barotrauma/BarotraumaClient/ClientSource/DebugConsole.cs index 98fdaa449..bfa8a5194 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/DebugConsole.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/DebugConsole.cs @@ -2489,26 +2489,8 @@ namespace Barotrauma Barotrauma.IO.Validation.SkipValidationInDebugBuilds = false; ToolBox.OpenFileWithShell(Path.GetFullPath(filePath)); })); + #if DEBUG - commands.Add(new Command("playovervc", "Plays a sound over voice chat.", (args) => - { - VoipCapture.Instance?.SetOverrideSound(args.Length > 0 ? args[0] : null); - })); - - commands.Add(new Command("querylobbies", "Queries all SteamP2P lobbies", (args) => - { - TaskPool.Add("DebugQueryLobbies", - SteamManager.LobbyQueryRequest(), (t) => - { - t.TryGetResult(out List lobbies); - foreach (var lobby in lobbies) - { - NewMessage(lobby.GetData("name") + ", " + lobby.GetData("lobbyowner"), Color.Yellow); - } - NewMessage($"Retrieved a total of {lobbies.Count} lobbies", Color.Lime); - }); - })); - commands.Add(new Command("checkduplicates", "Checks the given language for duplicate translation keys and writes to file.", (string[] args) => { if (args.Length != 1) { return; } @@ -3056,11 +3038,6 @@ namespace Barotrauma commands.Add(new Command("reloadwearables", "Reloads the sprites of all limbs and wearable sprites (clothing) of the controlled character. Provide id or name if you want to target another character.", args => { - if (GameMain.GameSession != null) - { - ThrowError("Using the command is not allowed during an active game session: the command is intended to be used in the character editor or in the main menu."); - return; - } var character = (args.Length == 0) ? Character.Controlled : FindMatchingCharacter(args, true); if (character == null) { @@ -3072,11 +3049,6 @@ namespace Barotrauma commands.Add(new Command("loadwearable", "Force select certain variant for the selected character.", args => { - if (GameMain.GameSession != null) - { - ThrowError("Using the command is not allowed during an active game session: the command is intended to be used in the character editor or in the main menu."); - return; - } var character = Character.Controlled; if (character == null) { diff --git a/Barotrauma/BarotraumaClient/ClientSource/Events/EventActions/MessageBoxAction.cs b/Barotrauma/BarotraumaClient/ClientSource/Events/EventActions/MessageBoxAction.cs new file mode 100644 index 000000000..e2bd6f963 --- /dev/null +++ b/Barotrauma/BarotraumaClient/ClientSource/Events/EventActions/MessageBoxAction.cs @@ -0,0 +1,73 @@ +using Barotrauma.Tutorials; +using System; +using System.Linq; + +namespace Barotrauma; + +partial class MessageBoxAction : EventAction +{ + partial void UpdateProjSpecific() + { + if (Type == ActionType.Create) + { + CreateMessageBox(); + if (!ObjectiveTag.IsEmpty && GameMain.GameSession?.GameMode is TutorialMode tutorialMode) + { + Identifier id = Identifier.IsEmpty ? Text : Identifier; + var segment = Tutorial.Segment.CreateMessageBoxSegment(id, ObjectiveTag, CreateMessageBox); + tutorialMode.Tutorial?.TriggerTutorialSegment(segment); + } + } + else if (Type == ActionType.Close) + { + GUIMessageBox.Close(Tag); + } + } + + public void CreateMessageBox() + { + new GUIMessageBox( + headerText: TextManager.Get(Header), + text: RichString.Rich(TextManager.ParseInputTypes(TextManager.Get(Text).Fallback(Text.ToString()), useColorHighlight: true)), + buttons: Array.Empty(), + type: GUIMessageBox.Type.Tutorial, + tag: Tag, + iconStyle: IconStyle, + autoCloseCondition: GetAutoCloseCondition(), + hideCloseButton: HideCloseButton) + { + FlashOnAutoCloseCondition = true + }; + } + + private Func GetAutoCloseCondition() + { + var character = ParentEvent.GetTargets(TargetTag).FirstOrDefault() as Character; + Func autoCloseCondition = null; + if (!string.IsNullOrEmpty(CloseOnInput) && Enum.TryParse(CloseOnInput, true, out InputType closeOnInput)) + { + autoCloseCondition = () => PlayerInput.KeyDown(closeOnInput); + } + else if (!CloseOnSelectTag.IsEmpty) + { + autoCloseCondition = () => character?.SelectedItem != null && character.SelectedItem.HasTag(CloseOnSelectTag); + } + else if (!CloseOnPickUpTag.IsEmpty) + { + autoCloseCondition = () => character?.Inventory != null && character.Inventory.FindItemByTag(CloseOnPickUpTag, recursive: true) != null; + } + else if (!CloseOnEquipTag.IsEmpty) + { + autoCloseCondition = () => character != null && character.HasEquippedItem(CloseOnEquipTag); + } + else if (!CloseOnExitRoomName.IsEmpty) + { + autoCloseCondition = () => character?.CurrentHull == null || character.CurrentHull.RoomName.ToIdentifier() != CloseOnExitRoomName; + } + else if (!CloseOnInRoomName.IsEmpty) + { + autoCloseCondition = () => character?.CurrentHull != null && character.CurrentHull.RoomName.ToIdentifier() == CloseOnInRoomName; + } + return autoCloseCondition; + } +} \ No newline at end of file diff --git a/Barotrauma/BarotraumaClient/ClientSource/Events/EventActions/TutorialHighlightAction.cs b/Barotrauma/BarotraumaClient/ClientSource/Events/EventActions/TutorialHighlightAction.cs new file mode 100644 index 000000000..beb14498a --- /dev/null +++ b/Barotrauma/BarotraumaClient/ClientSource/Events/EventActions/TutorialHighlightAction.cs @@ -0,0 +1,51 @@ +using Microsoft.Xna.Framework; + +namespace Barotrauma; + +partial class TutorialHighlightAction : EventAction +{ + private static readonly Color highlightColor = Color.OrangeRed; + + partial void UpdateProjSpecific() + { + if (GameMain.GameSession?.GameMode is not TutorialMode) { return; } + foreach (var target in ParentEvent.GetTargets(TargetTag)) + { + SetHighlight(target); + } + } + + private void SetHighlight(Entity entity) + { + if (entity is Item i) + { + SetHighlight(i); + } + else if (entity is Structure s) + { + SetHighlight(s); + } + else if (entity is Character c) + { + SetHighlight(c); + } + } + + private void SetHighlight(Item item) + { + if (item.ExternalHighlight == State) { return; } + item.SpriteColor = (State) ? highlightColor : Color.White; + item.ExternalHighlight = State; + } + + private void SetHighlight(Structure structure) + { + structure.SpriteColor = (State) ? highlightColor : Color.White; + structure.ExternalHighlight = State; + } + + private void SetHighlight(Character character) + { + character.ExternalHighlight = State; + } +} \ No newline at end of file diff --git a/Barotrauma/BarotraumaClient/ClientSource/Events/EventActions/TutorialSegmentAction.cs b/Barotrauma/BarotraumaClient/ClientSource/Events/EventActions/TutorialSegmentAction.cs new file mode 100644 index 000000000..d39340d05 --- /dev/null +++ b/Barotrauma/BarotraumaClient/ClientSource/Events/EventActions/TutorialSegmentAction.cs @@ -0,0 +1,50 @@ +using Barotrauma.Tutorials; + +namespace Barotrauma; + +partial class TutorialSegmentAction : EventAction +{ + private Tutorial.Segment segment; + + partial void UpdateProjSpecific() + { + // Only need to create the segment when it's being triggered (otherwise the tutorial already has the segment instance) + if (Type == SegmentActionType.Trigger) + { + segment = Tutorial.Segment.CreateInfoBoxSegment(Id, ObjectiveTag, AutoPlayVideo ? Tutorials.AutoPlayVideo.Yes : Tutorials.AutoPlayVideo.No, + new Tutorial.Segment.Text(TextTag, Width, Height, Anchor.Center), + new Tutorial.Segment.Video(VideoFile, TextTag, Width, Height)); + } + else if (Type == SegmentActionType.Add) + { + segment = Tutorial.Segment.CreateObjectiveSegment(Id, !ObjectiveTag.IsEmpty ? ObjectiveTag : Id); + } + if (GameMain.GameSession?.GameMode is TutorialMode tutorialMode) + { + if (tutorialMode.Tutorial is Tutorial tutorial) + { + switch (Type) + { + case SegmentActionType.Trigger: + case SegmentActionType.Add: + tutorial.TriggerTutorialSegment(segment); + break; + case SegmentActionType.Complete: + tutorial.CompleteTutorialSegment(Id); + break; + case SegmentActionType.Remove: + tutorial.RemoveTutorialSegment(Id); + break; + case SegmentActionType.CompleteAndRemove: + tutorial.CompleteTutorialSegment(Id); + tutorial.RemoveTutorialSegment(Id); + break; + } + } + } + else + { + DebugConsole.ShowError($"Error in event \"{ParentEvent.Prefab.Identifier}\": attempting to use TutorialSegmentAction during a non-Tutorial game mode!"); + } + } +} \ No newline at end of file diff --git a/Barotrauma/BarotraumaClient/ClientSource/Fonts/ScalableFont.cs b/Barotrauma/BarotraumaClient/ClientSource/Fonts/ScalableFont.cs index ae0a54609..b7b05c7f0 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Fonts/ScalableFont.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Fonts/ScalableFont.cs @@ -6,23 +6,26 @@ using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; -using System.Xml.Linq; +using System.Threading; +using Barotrauma.Threading; namespace Barotrauma { public class ScalableFont : IDisposable { - private static List FontList = new List(); + private static readonly List FontList = new List(); private static Library Lib = null; - private readonly object mutex = new object(); + private static readonly object globalMutex = new object(); + + private readonly ReaderWriterLockSlim rwl = new ReaderWriterLockSlim(); - private string filename; - private Face face; + private readonly string filename; + private readonly Face face; private uint size; private int baseHeight; - private Dictionary texCoords; - private List textures; - private GraphicsDevice graphicsDevice; + private readonly Dictionary texCoords; + private readonly List textures; + private readonly GraphicsDevice graphicsDevice; private Vector2 currentDynamicAtlasCoords; private int currentDynamicAtlasNextY; @@ -49,7 +52,7 @@ namespace Barotrauma set { size = value; - if (graphicsDevice != null) RenderAtlas(graphicsDevice, charRanges, texDims, baseChar); + if (graphicsDevice != null) { RenderAtlas(graphicsDevice, charRanges, texDims, baseChar); } } } @@ -93,11 +96,15 @@ namespace Barotrauma public ScalableFont(string filename, uint size, GraphicsDevice gd = null, bool dynamicLoading = false, bool isCJK = false) { - lock (mutex) + lock (globalMutex) + { + Lib ??= new Library(); + } + + this.filename = filename; + this.face = null; + using (new ReadLock(rwl)) { - if (Lib == null) Lib = new Library(); - this.filename = filename; - this.face = null; foreach (ScalableFont font in FontList) { if (font.filename == filename) @@ -106,19 +113,23 @@ namespace Barotrauma break; } } - this.face ??= new Face(Lib, filename); - this.size = size; - this.textures = new List(); - this.texCoords = new Dictionary(); - this.DynamicLoading = dynamicLoading; - this.IsCJK = isCJK; - this.graphicsDevice = gd; + } - if (gd != null && !dynamicLoading) - { - RenderAtlas(gd); - } + this.face ??= new Face(Lib, filename); + this.size = size; + this.textures = new List(); + this.texCoords = new Dictionary(); + this.DynamicLoading = dynamicLoading; + this.IsCJK = isCJK; + this.graphicsDevice = gd; + if (gd != null && !dynamicLoading) + { + RenderAtlas(gd); + } + + lock (globalMutex) + { FontList.Add(this); } } @@ -162,7 +173,7 @@ namespace Barotrauma Vector2 currentCoords = Vector2.Zero; int nextY = 0; - lock (mutex) + using (new WriteLock(rwl)) { face.SetPixelSizes(0, size); face.LoadGlyph(face.GetCharIndex(baseChar), LoadFlags.Default, LoadTarget.Normal); @@ -175,19 +186,22 @@ namespace Barotrauma for (uint j = start; j <= end; j++) { uint glyphIndex = face.GetCharIndex(j); - if (glyphIndex == 0) continue; + if (glyphIndex == 0) + { + texCoords.Add(j, new GlyphData( + advance: 0, + texIndex: -1)); + continue; + } face.LoadGlyph(glyphIndex, LoadFlags.Default, LoadTarget.Normal); if (face.Glyph.Metrics.Width == 0 || face.Glyph.Metrics.Height == 0) { - if (face.Glyph.Metrics.HorizontalAdvance > 0) - { - //glyph is empty, but char still applies advance - GlyphData blankData = new GlyphData( - advance: (float)face.Glyph.Metrics.HorizontalAdvance, - texIndex: -1); //indicates no texture because the glyph is empty + //glyph is empty, but char might still apply advance + GlyphData blankData = new GlyphData( + advance: Math.Max((float)face.Glyph.Metrics.HorizontalAdvance, 0f), + texIndex: -1); //indicates no texture because the glyph is empty - texCoords.Add(j, blankData); - } + texCoords.Add(j, blankData); continue; } //stacktrace doesn't really work that well when RenderGlyph throws an exception @@ -257,7 +271,7 @@ namespace Barotrauma private void DynamicRenderAtlas(GraphicsDevice gd, uint character, int texDims = 1024, uint baseChar = 0x54) { bool missingCharacterFound = false; - lock (mutex) + using (new ReadLock(rwl)) { missingCharacterFound = !texCoords.ContainsKey(character); } @@ -268,10 +282,9 @@ namespace Barotrauma private void DynamicRenderAtlas(GraphicsDevice gd, string str, int texDims = 1024, uint baseChar = 0x54) { bool missingCharacterFound = false; - var distinctChrs = str.Distinct().Select(c => (uint)c).ToArray(); - lock (mutex) + using (new ReadLock(rwl)) { - foreach (var character in distinctChrs) + foreach (var character in str) { if (texCoords.ContainsKey(character)) { continue; } @@ -280,7 +293,7 @@ namespace Barotrauma } } if (!missingCharacterFound) { return; } - DynamicRenderAtlas(gd, distinctChrs, texDims, baseChar); + DynamicRenderAtlas(gd, str.Select(c => (uint)c), texDims, baseChar); } private void DynamicRenderAtlas(GraphicsDevice gd, IEnumerable characters, int texDims = 1024, uint baseChar = 0x54) @@ -299,7 +312,7 @@ namespace Barotrauma Fixed26Dot6 horizontalAdvance; Vector2 drawOffset; - lock (mutex) + using (new WriteLock(rwl)) { if (textures.Count == 0) { @@ -318,20 +331,23 @@ namespace Barotrauma if (texCoords.ContainsKey(character)) { continue; } uint glyphIndex = face.GetCharIndex(character); - if (glyphIndex == 0) { continue; } + if (glyphIndex == 0) + { + texCoords.Add(character, new GlyphData( + advance: 0, + texIndex: -1)); + continue; + } face.SetPixelSizes(0, size); face.LoadGlyph(glyphIndex, LoadFlags.Default, LoadTarget.Normal); if (face.Glyph.Metrics.Width == 0 || face.Glyph.Metrics.Height == 0) { - if (face.Glyph.Metrics.HorizontalAdvance > 0) - { - //glyph is empty, but char still applies advance - GlyphData blankData = new GlyphData( - advance: (float)face.Glyph.Metrics.HorizontalAdvance, - texIndex: -1); //indicates no texture because the glyph is empty - texCoords.Add(character, blankData); - } + //glyph is empty, but char might still apply advance + GlyphData blankData = new GlyphData( + advance: Math.Max((float)face.Glyph.Metrics.HorizontalAdvance, 0f), + texIndex: -1); //indicates no texture because the glyph is empty + texCoords.Add(character, blankData); continue; } diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIComponent.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIComponent.cs index 764382577..73ba38a9c 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIComponent.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIComponent.cs @@ -730,7 +730,7 @@ namespace Barotrauma public void DrawToolTip(SpriteBatch spriteBatch) { if (!Visible) { return; } - DrawToolTip(spriteBatch, ToolTip, GUI.MouseOn.Rect); + DrawToolTip(spriteBatch, ToolTip, Rect); } public static void DrawToolTip(SpriteBatch spriteBatch, RichString toolTip, Vector2 pos) @@ -781,7 +781,7 @@ namespace Barotrauma if (toolTipBlock.Rect.Bottom > GameMain.GraphicsHeight - 10) { toolTipBlock.RectTransform.AbsoluteOffset -= new Point( - (targetElement.Width / 2) * Math.Sign(targetElement.Center.X - toolTipBlock.Center.X), + 0, toolTipBlock.Rect.Bottom - (GameMain.GraphicsHeight - 10)); } toolTipBlock.SetTextPos(); diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIDropDown.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIDropDown.cs index 59510e874..a8ca188cc 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIDropDown.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIDropDown.cs @@ -204,15 +204,7 @@ namespace Barotrauma currentHighestParent = FindHighestParent(); currentHighestParent.GUIComponent.OnAddedToGUIUpdateList += AddListBoxToGUIUpdateList; - rectT.ParentChanged += (RectTransform newParent) => - { - currentHighestParent.GUIComponent.OnAddedToGUIUpdateList -= AddListBoxToGUIUpdateList; - if (newParent != null) - { - currentHighestParent = FindHighestParent(); - currentHighestParent.GUIComponent.OnAddedToGUIUpdateList += AddListBoxToGUIUpdateList; - } - }; + rectT.ParentChanged += _ => RefreshListBoxParent(); } @@ -396,6 +388,15 @@ namespace Barotrauma return true; } + public void RefreshListBoxParent() + { + currentHighestParent.GUIComponent.OnAddedToGUIUpdateList -= AddListBoxToGUIUpdateList; + if (RectTransform.Parent == null) { return; } + + currentHighestParent = FindHighestParent(); + currentHighestParent.GUIComponent.OnAddedToGUIUpdateList += AddListBoxToGUIUpdateList; + } + private void AddListBoxToGUIUpdateList(GUIComponent parent) { //the parent is not our parent anymore :( @@ -403,11 +404,13 @@ namespace Barotrauma //and somewhere between this component and the higher parent a component was removed for (int i = 1; i < parentHierarchy.Count; i++) { - if (!parentHierarchy[i].IsParentOf(parentHierarchy[i - 1], recursive: false)) + if (parentHierarchy[i].IsParentOf(parentHierarchy[i - 1], recursive: false)) { - parent.OnAddedToGUIUpdateList -= AddListBoxToGUIUpdateList; - return; + continue; } + + parent.OnAddedToGUIUpdateList -= AddListBoxToGUIUpdateList; + return; } if (Dropped) diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIMessageBox.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIMessageBox.cs index f7bad7dc1..b67fd7713 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIMessageBox.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIMessageBox.cs @@ -34,7 +34,7 @@ namespace Barotrauma public GUIFrame InnerFrame { get; private set; } public GUITextBlock Header { get; private set; } public GUITextBlock Text { get; private set; } - public string Tag { get; private set; } + public Identifier Tag { get; private set; } public bool Closed { get; private set; } public bool DisplayInLoadingScreens; @@ -78,6 +78,8 @@ namespace Barotrauma ///
private readonly Func autoCloseCondition; + public bool FlashOnAutoCloseCondition { get; set; } + public Type MessageBoxType => type; public static GUIComponent VisibleBox => MessageBoxes.LastOrDefault(); @@ -142,7 +144,7 @@ namespace Barotrauma } GUIStyle.Apply(InnerFrame, "", this); this.type = type; - Tag = tag; + Tag = tag.ToIdentifier(); #warning TODO: These should be broken into separate methods at least if (type == Type.Default || type == Type.Vote) @@ -199,6 +201,7 @@ namespace Barotrauma var button = new GUIButton(new RectTransform(new Vector2(0.6f, 1.0f / buttons.Length), buttonContainer.RectTransform), buttons[i]); Buttons.Add(button); } + GUITextBlock.AutoScaleAndNormalize(Buttons.Select(btn => btn.TextBlock)); } else if (type == Type.InGame || type == Type.Tutorial) { @@ -540,9 +543,7 @@ namespace Barotrauma if (type == Type.InGame || type == Type.Tutorial) { initialPos = new Vector2(0.0f, GameMain.GraphicsHeight); - defaultPos = type == Type.InGame ? - new Vector2(0.0f, HUDLayoutSettings.InventoryAreaLower.Y - InnerFrame.Rect.Height - 20 * GUI.Scale) : - new Vector2(0.0f, GameMain.GraphicsHeight / 2); + defaultPos = new Vector2(0.0f, HUDLayoutSettings.InventoryAreaLower.Y - InnerFrame.Rect.Height - 20 * GUI.Scale); endPos = new Vector2(GameMain.GraphicsWidth, defaultPos.Y); } else @@ -574,10 +575,18 @@ namespace Barotrauma inGameCloseTimer += deltaTime; } - if (inGameCloseTimer >= inGameCloseTime || (autoCloseCondition != null && autoCloseCondition())) + if (inGameCloseTimer >= inGameCloseTime) { Close(); } + else if (autoCloseCondition != null && autoCloseCondition()) + { + Close(); + if (FlashOnAutoCloseCondition) + { + InnerFrame.Flash(GUIStyle.Green); + } + } } else { @@ -634,7 +643,6 @@ namespace Barotrauma } } - public void Close() { if (IsAnimated) @@ -662,6 +670,19 @@ namespace Barotrauma MessageBoxes.Clear(); } + public static void Close(Identifier tag) + { + foreach (var messageBox in MessageBoxes) + { + if (messageBox is GUIMessageBox mb && mb.Tag == tag) + { + mb.Close(); + } + } + } + + public static void Close(string tag) => Close(tag.ToIdentifier()); + /// /// Parent does not matter. It's overridden. /// diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIPrefab.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIPrefab.cs index 137eee850..8ae5366b8 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIPrefab.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIPrefab.cs @@ -178,19 +178,19 @@ namespace Barotrauma { public GUIFont(string identifier) : base(identifier) { } - public bool HasValue => Prefabs.Any(); + public bool HasValue => !Prefabs.IsEmpty; public ScalableFont Value => Prefabs.ActivePrefab.Font; public static implicit operator ScalableFont(GUIFont reference) => reference.Value; - public bool ForceUpperCase => HasValue && Value.ForceUpperCase; + public bool ForceUpperCase => Prefabs.ActivePrefab?.Font is { ForceUpperCase: true }; public uint Size => HasValue ? Value.Size : 0; private ScalableFont GetFontForStr(LocalizedString str) => GetFontForStr(str.Value); - private ScalableFont GetFontForStr(string str) => + public ScalableFont GetFontForStr(string str) => TextManager.IsCJK(str) ? Prefabs.ActivePrefab.CjkFont : Prefabs.ActivePrefab.Font; public void DrawString(SpriteBatch sb, LocalizedString text, Vector2 position, Color color, float rotation, Vector2 origin, Vector2 scale, SpriteEffects se, float layerDepth) diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIStyle.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIStyle.cs index 6451c8d24..4737c85f7 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIStyle.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIStyle.cs @@ -161,7 +161,7 @@ namespace Barotrauma public static Point ItemFrameOffset => new Point(0, 3).Multiply(GUI.SlicedSpriteScale); public static GUIComponentStyle GetComponentStyle(string name) - => ComponentStyles.ContainsKey(name) ? ComponentStyles[name] : null; + => ComponentStyles.TryGet(name, out var style) ? style : null; public static void Apply(GUIComponent targetComponent, string styleName = "", GUIComponent parent = null) { diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUITickBox.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUITickBox.cs index 47ce9cab1..8ab3992d5 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUITickBox.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUITickBox.cs @@ -177,7 +177,7 @@ namespace Barotrauma radioButtonGroup = rbg; } - private void ResizeBox() + public void ResizeBox() { Vector2 textBlockScale = new Vector2(Math.Max(Rect.Width - box.Rect.Width, 0.0f) / Math.Max(Rect.Width, 1.0f), 1.0f); text.RectTransform.RelativeSize = textBlockScale; diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/RectTransform.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/RectTransform.cs index 5a750998d..03a16c643 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/RectTransform.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/RectTransform.cs @@ -233,7 +233,9 @@ namespace Barotrauma get { Point absoluteOffset = ConvertOffsetRelativeToAnchor(AbsoluteOffset, Anchor); - Point relativeOffset = NonScaledParentRect.MultiplySize(RelativeOffset); + Point relativeOffset = new Point( + (int)(NonScaledParentSize.X * RelativeOffset.X), + (int)(NonScaledParentSize.Y * RelativeOffset.Y)); relativeOffset = ConvertOffsetRelativeToAnchor(relativeOffset, Anchor); return AnchorPoint + PivotOffset + absoluteOffset + relativeOffset + ScreenSpaceOffset; } @@ -256,6 +258,7 @@ namespace Barotrauma public Rectangle ParentRect => Parent != null ? Parent.Rect : UIRect; protected Rectangle NonScaledRect => new Rectangle(NonScaledTopLeft, NonScaledSize); protected virtual Rectangle NonScaledUIRect => NonScaledRect; + protected Point NonScaledParentSize => parent?.NonScaledSize ?? new Point(GUI.UIWidth, GameMain.GraphicsHeight); protected Rectangle NonScaledParentRect => parent != null ? Parent.NonScaledRect : UIRect; protected Rectangle NonScaledParentUIRect => parent != null ? Parent.NonScaledUIRect : UIRect; protected Rectangle UIRect => new Rectangle(0, 0, GUI.UIWidth, GameMain.GraphicsHeight); @@ -336,6 +339,11 @@ namespace Barotrauma public event Action ChildrenChanged; public event Action ScaleChanged; public event Action SizeChanged; + + public void ResetSizeChanged() + { + SizeChanged = null; + } #endregion #region Initialization @@ -730,17 +738,17 @@ namespace Barotrauma get { return animTargetPos ?? AbsoluteOffset; } } - public void MoveOverTime(Point targetPos, float duration) + public void MoveOverTime(Point targetPos, float duration, Action onDoneMoving = null) { animTargetPos = targetPos; - CoroutineManager.StartCoroutine(DoMoveAnimation(targetPos, duration)); + CoroutineManager.StartCoroutine(DoMoveAnimation(targetPos, duration, onDoneMoving)); } public void ScaleOverTime(Point targetSize, float duration) { CoroutineManager.StartCoroutine(DoScaleAnimation(targetSize, duration)); } - private IEnumerable DoMoveAnimation(Point targetPos, float duration) + private IEnumerable DoMoveAnimation(Point targetPos, float duration, Action onDoneMoving = null) { Vector2 startPos = AbsoluteOffset.ToVector2(); float t = 0.0f; @@ -752,6 +760,7 @@ namespace Barotrauma } AbsoluteOffset = targetPos; animTargetPos = null; + onDoneMoving?.Invoke(); yield return CoroutineStatus.Success; } private IEnumerable DoScaleAnimation(Point targetSize, float duration) diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/SubmarineSelection.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/SubmarineSelection.cs index 6e140e57b..7a9a97fc5 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/SubmarineSelection.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/SubmarineSelection.cs @@ -226,17 +226,18 @@ namespace Barotrauma }; submarineDisplayElement.submarineImage = new GUIImage(new RectTransform(new Vector2(0.8f, 1f), submarineDisplayElement.background.RectTransform, Anchor.Center), null, true); submarineDisplayElement.middleTextBlock = new GUITextBlock(new RectTransform(new Vector2(0.8f, 1f), submarineDisplayElement.background.RectTransform, Anchor.Center), string.Empty, textAlignment: Alignment.Center); - submarineDisplayElement.submarineName = new GUITextBlock(new RectTransform(new Vector2(1f, 0.1f), submarineDisplayElement.background.RectTransform, Anchor.TopCenter, Pivot.TopCenter) { AbsoluteOffset = new Point(0, HUDLayoutSettings.Padding) }, string.Empty, textAlignment: Alignment.Center, font: GUIStyle.SubHeadingFont); - submarineDisplayElement.submarineClass = new GUITextBlock(new RectTransform(new Vector2(1f, 0.1f), submarineDisplayElement.background.RectTransform, Anchor.TopCenter, Pivot.TopCenter) { AbsoluteOffset = new Point(0, HUDLayoutSettings.Padding + (int)GUIStyle.Font.MeasureString(submarineDisplayElement.submarineName.Text).Y) }, string.Empty, textAlignment: Alignment.Left); - submarineDisplayElement.submarineTier = new GUITextBlock(new RectTransform(new Vector2(1f, 0.1f), submarineDisplayElement.background.RectTransform, Anchor.TopCenter, Pivot.TopCenter) { AbsoluteOffset = new Point(0, HUDLayoutSettings.Padding + (int)GUIStyle.Font.MeasureString(submarineDisplayElement.submarineName.Text).Y) }, string.Empty, textAlignment: Alignment.Right); - submarineDisplayElement.submarineFee = new GUITextBlock(new RectTransform(new Vector2(1f, 0.1f), submarineDisplayElement.background.RectTransform, Anchor.BottomCenter, Pivot.BottomCenter) { AbsoluteOffset = new Point(0, HUDLayoutSettings.Padding) }, string.Empty, textAlignment: Alignment.Center, font: GUIStyle.SubHeadingFont); + submarineDisplayElement.submarineName = new GUITextBlock(new RectTransform(new Vector2(1f, 0.1f), submarineDisplayElement.background.RectTransform, Anchor.TopCenter) { AbsoluteOffset = new Point(0, HUDLayoutSettings.Padding) }, string.Empty, textAlignment: Alignment.Center, font: GUIStyle.SubHeadingFont); + submarineDisplayElement.submarineFee = new GUITextBlock(new RectTransform(new Vector2(1f, 0.1f), submarineDisplayElement.background.RectTransform, Anchor.BottomCenter) { AbsoluteOffset = new Point(0, HUDLayoutSettings.Padding) }, string.Empty, textAlignment: Alignment.Center, font: GUIStyle.SubHeadingFont); submarineDisplayElement.selectSubmarineButton = new GUIButton(new RectTransform(Vector2.One, submarineDisplayElement.background.RectTransform), style: null); - submarineDisplayElement.previewButton = new GUIButton(new RectTransform(Vector2.One * 0.12f, submarineDisplayElement.background.RectTransform, anchor: Anchor.BottomRight, pivot: Pivot.BottomRight, scaleBasis: ScaleBasis.BothHeight) { AbsoluteOffset = new Point((int)(0.03f * background.Rect.Height)) }, style: "ExpandButton") + submarineDisplayElement.previewButton = new GUIButton(new RectTransform(Vector2.One * 0.12f, submarineDisplayElement.background.RectTransform, anchor: Anchor.BottomRight, scaleBasis: ScaleBasis.BothHeight) { AbsoluteOffset = new Point((int)(0.03f * background.Rect.Height)) }, style: "ExpandButton") { Color = Color.White, HoverColor = Color.White, PressedColor = Color.White }; + submarineDisplayElement.submarineClass = new GUITextBlock(new RectTransform(new Vector2(1f, 0.1f), submarineDisplayElement.background.RectTransform, Anchor.TopCenter) { AbsoluteOffset = new Point(0, HUDLayoutSettings.Padding + (int)GUIStyle.Font.MeasureString(submarineDisplayElement.submarineName.Text).Y) }, string.Empty, textAlignment: Alignment.Left); + submarineDisplayElement.submarineTier = new GUITextBlock(new RectTransform(new Vector2(0.5f, 0.1f), submarineDisplayElement.background.RectTransform, Anchor.TopRight) { AbsoluteOffset = new Point(0, HUDLayoutSettings.Padding + (int)GUIStyle.Font.MeasureString(submarineDisplayElement.submarineName.Text).Y) }, string.Empty, textAlignment: Alignment.Right); + submarineDisplays[i] = submarineDisplayElement; } @@ -395,9 +396,13 @@ namespace Barotrauma return true; }; - submarineDisplays[i].submarineName.Text = subToDisplay.DisplayName; + submarineDisplays[i].submarineName.Text = subToDisplay.DisplayName; + submarineDisplays[i].submarineClass.Text = TextManager.GetWithVariable("submarineclass.classsuffixformat", "[type]", TextManager.Get($"submarineclass.{subToDisplay.SubmarineClass}")); + submarineDisplays[i].submarineClass.ToolTip = TextManager.Get("submarineclass.description") + "\n\n" + TextManager.Get($"submarineclass.{subToDisplay.SubmarineClass}.description"); + submarineDisplays[i].submarineTier.Text = TextManager.Get($"submarinetier.{subToDisplay.Tier}"); + submarineDisplays[i].submarineTier.ToolTip = TextManager.Get("submarinetier.description"); if (!GameMain.GameSession.IsSubmarineOwned(subToDisplay)) { diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/TabMenu.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/TabMenu.cs index 1f49c63f0..4b17d15d3 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/TabMenu.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/TabMenu.cs @@ -1722,7 +1722,11 @@ namespace Barotrauma var subInfoTextLayout = new GUILayoutGroup(new RectTransform(Vector2.One, paddedFrame.RectTransform)); - LocalizedString className = !sub.Info.HasTag(SubmarineTag.Shuttle) ? $"{TextManager.Get($"submarineclass.{sub.Info.SubmarineClass}")} ({TextManager.Get($"submarinetier.{sub.Info.Tier}")})" : TextManager.Get("shuttle"); + LocalizedString className = !sub.Info.HasTag(SubmarineTag.Shuttle) ? + TextManager.GetWithVariables("submarine.classandtier", + ("[class]", TextManager.Get($"submarineclass.{sub.Info.SubmarineClass}")), + ("[tier]", TextManager.Get($"submarinetier.{sub.Info.Tier}"))) : + TextManager.Get("shuttle"); int nameHeight = (int)GUIStyle.LargeFont.MeasureString(sub.Info.DisplayName, true).Y; int classHeight = (int)GUIStyle.SubHeadingFont.MeasureString(className).Y; @@ -2140,18 +2144,17 @@ namespace Barotrauma skillNames.Add(skillName); skillName.RectTransform.MinSize = new Point(0, skillName.Rect.Height); skillContainer.RectTransform.MinSize = new Point(0, skillName.Rect.Height); - + new GUITextBlock(new RectTransform(new Vector2(0.15f, 1.0f), skillContainer.RectTransform), Math.Floor(skill.Level).ToString("F0"), textAlignment: Alignment.TopRight); float modifiedSkillLevel = character?.GetSkillLevel(skill.Identifier) ?? skill.Level; if (!MathUtils.NearlyEqual(MathF.Floor(modifiedSkillLevel), MathF.Floor(skill.Level))) { int skillChange = (int)MathF.Floor(modifiedSkillLevel - skill.Level); - //TODO: if/when we upgrade to C# 9, do neater pattern matching here - string stringColor = true switch + string stringColor = skillChange switch { - true when skillChange > 0 => XMLExtensions.ToStringHex(GUIStyle.Green), - true when skillChange < 0 => XMLExtensions.ToStringHex(GUIStyle.Red), + > 0 => XMLExtensions.ToStringHex(GUIStyle.Green), + < 0 => XMLExtensions.ToStringHex(GUIStyle.Red), _ => XMLExtensions.ToStringHex(GUIStyle.TextColorNormal) }; diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/UpgradeStore.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/UpgradeStore.cs index db946f01a..ad7358468 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/UpgradeStore.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/UpgradeStore.cs @@ -1257,12 +1257,17 @@ namespace Barotrauma List upgrades = entity.GetUpgrades(); int upgradesCount = upgrades.Count; const int maxUpgrades = 4; - - itemName.Text = entity is Item ? entity.Name : TextManager.Get("upgradecategory.walls"); + + Item? item = entity as Item; + itemName.Text = item?.Name ?? TextManager.Get("upgradecategory.walls"); if (slotIndex > -1) { itemName.Text = TextManager.GetWithVariables("weaponslotwithname", ("[number]", slotIndex.ToString()), ("[weaponname]", itemName.Text)); } + if (item?.PendingItemSwap != null) + { + itemName.Text = RichString.Rich(itemName.Text + "\n" + TextManager.GetWithVariable("upgrades.pendingitem", "[itemname]", item.PendingItemSwap.Name)); + } upgradeList.Content.ClearChildren(); for (var i = 0; i < upgrades.Count && i < maxUpgrades; i++) { @@ -1275,7 +1280,7 @@ namespace Barotrauma // include pending upgrades into the tooltip foreach (var (prefab, category, level) in upgradeManager.PendingUpgrades) { - if (entity is Item item && category.CanBeApplied(item, prefab) || entity is Structure && category.IsWallUpgrade) + if (item != null && category.CanBeApplied(item, prefab) || entity is Structure && category.IsWallUpgrade) { bool found = false; foreach (GUITextBlock textBlock in upgradeList.Content.Children.Where(c => c is GUITextBlock).Cast()) @@ -1392,6 +1397,10 @@ namespace Barotrauma if (!itemElement.Selected) { itemElement.OnClicked(itemElement, itemElement.UserData); } (itemElement.Parent?.Parent?.Parent as GUIListBox)?.ScrollToElement(itemElement); } + else + { + ScrollToCategory(data => data.Category.CanBeApplied(item, null)); + } } } else @@ -1463,23 +1472,16 @@ namespace Barotrauma // submarine name new GUITextBlock(rectT(1, 0, submarineInfoFrame), submarine.Info.DisplayName, textAlignment: Alignment.Right, font: GUIStyle.LargeFont); - GUILayoutGroup classLayout = new GUILayoutGroup(rectT(1, 0.15f, submarineInfoFrame), isHorizontal: true) { Stretch = true }; LocalizedString classText = $"{TextManager.GetWithVariable("submarineclass.classsuffixformat", "[type]", TextManager.Get($"submarineclass.{submarine.Info.SubmarineClass}"))}"; // submarine class + tier - new GUITextBlock(rectT(0.8f, 1, classLayout), classText, textAlignment: Alignment.Right, font: GUIStyle.Font) + new GUITextBlock(rectT(1.0f, 0.15f, submarineInfoFrame), classText, textAlignment: Alignment.Right, font: GUIStyle.Font) { - ToolTip = TextManager.Get("submarineclass.description") + '\n' + TextManager.Get($"submarineclass.{submarine.Info.SubmarineClass}.description") + ToolTip = TextManager.Get("submarineclass.description") + "\n\n" + TextManager.Get($"submarineclass.{submarine.Info.SubmarineClass}.description") }; - int tier = submarine.Info.Tier; - string tierStyle = $"SubmarineTier.{tier}"; - if (GUIStyle.GetComponentStyle(tierStyle) != null) + new GUITextBlock(rectT(1.0f, 0.15f, submarineInfoFrame), TextManager.Get($"submarinetier.{submarine.Info.Tier}"), textAlignment: Alignment.Right, font: GUIStyle.Font) { - LocalizedString tooltip = TextManager.Get("submarinetier.description").Fallback(string.Empty); - new GUIImage(rectT(0.15f, 1, classLayout), style: tierStyle, scaleToFit: false) - { - ToolTip = tooltip - }; - } + ToolTip = TextManager.Get("submarinetier.description") + }; var description = new GUITextBlock(rectT(1, 0, submarineInfoFrame), submarine.Info.Description, textAlignment: Alignment.Right, wrap: true); submarineInfoFrame.RectTransform.ScreenSpaceOffset = new Point(0, (int)(16 * GUI.Scale)); @@ -1750,14 +1752,26 @@ namespace Barotrauma { if (currentStoreLayout == null) { return; } + CategoryData? mostAppropriateCategory = null; + GUIComponent? mostAppropriateChild = null; foreach (GUIComponent child in currentStoreLayout.Content.Children) { if (child.UserData is CategoryData data && predicate(data)) { - currentStoreLayout.ScrollToElement(child, playSelectSound); - break; + //choose the category with least items in it as the "most appropriate" + //e.g. when selecting junction boxes, we want to select the "junction boxes" category instead of "electrical repairs" which contains many electrical devices + if (mostAppropriateCategory == null || + data.Category.ItemTags.Count() < mostAppropriateCategory.Value.Category.ItemTags.Count()) + { + mostAppropriateCategory = data; + mostAppropriateChild = child; + } } } + if (mostAppropriateChild != null) + { + currentStoreLayout.ScrollToElement(mostAppropriateChild, playSelectSound); + } } /// diff --git a/Barotrauma/BarotraumaClient/ClientSource/GameMain.cs b/Barotrauma/BarotraumaClient/ClientSource/GameMain.cs index ffd792e44..226487ec1 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GameMain.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GameMain.cs @@ -461,7 +461,7 @@ namespace Barotrauma yield return CoroutineStatus.Running; - UgcTransition.Prepare(); + LegacySteamUgcTransition.Prepare(); var contentPackageLoadRoutine = ContentPackageManager.Init(); foreach (var progress in contentPackageLoadRoutine) { @@ -715,7 +715,7 @@ namespace Barotrauma } #endif - NetworkMember?.Update((float)Timing.Step); + Client?.Update((float)Timing.Step); if (!HasLoaded && !CoroutineManager.IsCoroutineRunning(loadingCoroutine)) { @@ -874,7 +874,7 @@ namespace Barotrauma } } - NetworkMember?.Update((float)Timing.Step); + Client?.Update((float)Timing.Step); GUI.Update((float)Timing.Step); @@ -1181,7 +1181,7 @@ namespace Barotrauma { exiting = true; DebugConsole.NewMessage("Exiting..."); - NetworkMember?.Quit(); + Client?.Quit(); SteamManager.ShutDown(); try diff --git a/Barotrauma/BarotraumaClient/ClientSource/GameSession/CrewManager.cs b/Barotrauma/BarotraumaClient/ClientSource/GameSession/CrewManager.cs index 01f09f376..a1f3594bf 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GameSession/CrewManager.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GameSession/CrewManager.cs @@ -3516,9 +3516,9 @@ namespace Barotrauma if (node == null || characterContext != null) { return false; } if (node.UserData is Order nodeOrder) { - return !nodeOrder.TargetAllCharacters && !nodeOrder.Prefab.HasOptions && - (!nodeOrder.MustSetTarget || itemContext != null || - nodeOrder.GetMatchingItems(GetTargetSubmarine(), true, interactableFor: Character.Controlled).Count < 2); + return !nodeOrder.TargetAllCharacters && + (!nodeOrder.Prefab.HasOptions || !nodeOrder.Option.IsEmpty) && + (!nodeOrder.MustSetTarget || itemContext != null || nodeOrder.GetMatchingItems(GetTargetSubmarine(), true, interactableFor: Character.Controlled).Count < 2); } return false; } diff --git a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/Tutorial.cs b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/Tutorial.cs index ea4e51c49..3dbc348f4 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/Tutorial.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/Tutorial.cs @@ -1,22 +1,21 @@ using Barotrauma.Extensions; +using Barotrauma.IO; using Barotrauma.Items.Components; using Microsoft.Xna.Framework; using System; using System.Collections.Generic; -using System.Collections.Immutable; using System.Linq; namespace Barotrauma.Tutorials { enum AutoPlayVideo { Yes, No }; - enum TutorialSegmentType { MessageBox, InfoBox }; + enum TutorialSegmentType { MessageBox, InfoBox, Objective }; - class Tutorial + sealed class Tutorial { #region Constants - private const string PlayableContentPath = "Content/Tutorials/TutorialVideos/"; private const SpawnType SpawnPointType = SpawnType.Human; private const float FadeOutTime = 3f; private const float WaitBeforeFade = 4f; @@ -25,19 +24,11 @@ namespace Barotrauma.Tutorials #region Tutorial variables - public static ImmutableHashSet Types; - - static Tutorial() - { - Types = ReflectionUtils.GetDerivedNonAbstract() - .ToImmutableHashSet(); - } - public readonly Identifier Identifier; public LocalizedString DisplayName { get; } - public bool ContentRunning { get; protected set; } + public bool ContentRunning { get; private set; } private GUIComponent infoBox; private Action infoBoxClosedCallback; @@ -51,47 +42,25 @@ namespace Barotrauma.Tutorials private readonly LocalizedString objectiveTextTranslated; private readonly List ActiveObjectives = new List(); - private const float ObjectiveComponentRemovalTime = 1.5f; + private const float ObjectiveComponentAnimationTime = 1.5f; private Segment ActiveContentSegment { get; set; } public class Segment { - public struct Text + public readonly record struct Text( + Identifier Tag, + int Width = DefaultWidth, + int Height = DefaultHeight, + Anchor Anchor = Anchor.Center); + + public readonly record struct Video( + string FullPath, + Identifier TextTag, + int Width = DefaultWidth, + int Height = DefaultHeight) { - private const Anchor DefaultAnchor = Anchor.Center; - - public Identifier Tag; - public int Width; - public int Height; - public Anchor Anchor; - - public Text(Identifier tag, int? width = null, int? height = null, Anchor? anchor = null) - { - Tag = tag; - Width = width ?? DefaultWidth; - Height = height ?? DefaultHeight; - Anchor = anchor ?? DefaultAnchor; - } - - public Text(string tag, int? width = null, int? height = null, Anchor? anchor = null) : this(tag.ToIdentifier(), width, height, anchor) { } - } - - public struct Video - { - public string File; - public Identifier TextTag; - public int Width; - public int Height; - - public Video(string file, Identifier textTag, int? width = null, int? height = null) - { - File = file; - TextTag = textTag; - Width = width ?? DefaultWidth; - Height = height ?? DefaultHeight; - } - - public Video(string file, string textTag, int? width = null, int? height = null) : this(file, textTag.ToIdentifier(), width, height) { } + public string FileName => Path.GetFileName(FullPath.CleanUpPath()); + public string ContentPath => Path.GetDirectoryName(FullPath.CleanUpPath()); } private const int DefaultWidth = 450; @@ -103,15 +72,30 @@ namespace Barotrauma.Tutorials public LocalizedString ObjectiveText; public readonly Identifier Id; - public readonly Text? TextContent; - public readonly Video? VideoContent; + public readonly Text TextContent; + public readonly Video VideoContent; public readonly AutoPlayVideo AutoPlayVideo; - public Action OnClickToDisplayMessage; + public Action OnClickObjective; public readonly TutorialSegmentType SegmentType; - public Segment(Identifier id, Identifier objectiveTextTag, AutoPlayVideo autoPlayVideo, Text? textContent = null, Video? videoContent = null) + public static Segment CreateInfoBoxSegment(Identifier id, Identifier objectiveTextTag, AutoPlayVideo autoPlayVideo, Text textContent = default, Video videoContent = default) + { + return new Segment(id, objectiveTextTag, autoPlayVideo, textContent, videoContent); + } + + public static Segment CreateMessageBoxSegment(Identifier id, Identifier objectiveTextTag, Action onClickObjective) + { + return new Segment(id, objectiveTextTag, onClickObjective); + } + + public static Segment CreateObjectiveSegment(Identifier id, Identifier objectiveTextTag) + { + return new Segment(id, objectiveTextTag); + } + + private Segment(Identifier id, Identifier objectiveTextTag, AutoPlayVideo autoPlayVideo, Text textContent = default, Video videoContent = default) { Id = id; ObjectiveText = TextManager.ParseInputTypes(TextManager.Get(objectiveTextTag)); @@ -121,15 +105,21 @@ namespace Barotrauma.Tutorials SegmentType = TutorialSegmentType.InfoBox; } - public Segment(Identifier id, Action onClickToDisplayMessage) + private Segment(Identifier id, Identifier objectiveTextTag, Action onClickObjective) { Id = id; - var objetiveTextTag = $"{id}.objective".ToIdentifier(); - ObjectiveText = TextManager.ParseInputTypes(TextManager.Get(objetiveTextTag)); - OnClickToDisplayMessage = onClickToDisplayMessage; + ObjectiveText = TextManager.ParseInputTypes(TextManager.Get(objectiveTextTag)); + OnClickObjective = onClickObjective; SegmentType = TutorialSegmentType.MessageBox; } - } + + private Segment(Identifier id, Identifier objectiveTextTag) + { + Id = id; + ObjectiveText = TextManager.ParseInputTypes(TextManager.Get(objectiveTextTag)); + SegmentType = TutorialSegmentType.Objective; + } + } private bool completed; public bool Completed @@ -157,60 +147,57 @@ namespace Barotrauma.Tutorials private Character character; - private readonly string submarinePath = "Content/Tutorials/Dugong_Tutorial.sub"; - private readonly string startOutpostPath = "Content/Tutorials/TutorialOutpost.sub"; - - private readonly string levelSeed = "nLoZLLtza"; - private readonly string levelParams = "ColdCavernsTutorial"; + private string SubmarinePath => TutorialPrefab.SubmarinePath.Value; + private string StartOutpostPath => TutorialPrefab.OutpostPath.Value; + private string LevelSeed => TutorialPrefab.LevelSeed; + private string LevelParams => TutorialPrefab.LevelParams; private SubmarineInfo startOutpost = null; + public readonly List<(Entity entity, string iconStyle)> Icons = new List<(Entity entity, string iconStyle)>(); + #endregion #region Tutorial Controls public Tutorial(TutorialPrefab prefab) { - Identifier = $"tutorial.{prefab?.Identifier ?? Identifier.Empty}".ToIdentifier(); + Identifier = $"tutorial.{prefab.Identifier}".ToIdentifier(); DisplayName = TextManager.Get(Identifier); objectiveTextTranslated = TextManager.Get("Tutorial.Objective"); TutorialPrefab = prefab; - submarinePath = prefab.SubmarinePath.Value; - startOutpostPath = prefab.OutpostPath.Value; - levelSeed = prefab.LevelSeed; - levelParams = prefab.LevelParams; eventPrefab = EventSet.GetEventPrefab(prefab.EventIdentifier); } private IEnumerable Loading() { - SubmarineInfo subInfo = new SubmarineInfo(submarinePath); + SubmarineInfo subInfo = new SubmarineInfo(SubmarinePath); - LevelGenerationParams generationParams = LevelGenerationParams.LevelParams.Find(p => p.Identifier == levelParams); + LevelGenerationParams.LevelParams.TryGet(LevelParams, out LevelGenerationParams generationParams); yield return CoroutineStatus.Running; GameMain.GameSession = new GameSession(subInfo, GameModePreset.Tutorial, missionPrefabs: null); (GameMain.GameSession.GameMode as TutorialMode).Tutorial = this; - if (generationParams != null) + if (generationParams is not null) { Biome biome = Biome.Prefabs.FirstOrDefault(b => generationParams.AllowedBiomeIdentifiers.Contains(b.Identifier)) ?? Biome.Prefabs.First(); - if (!string.IsNullOrEmpty(startOutpostPath)) + if (!string.IsNullOrEmpty(StartOutpostPath)) { - startOutpost = new SubmarineInfo(startOutpostPath); + startOutpost = new SubmarineInfo(StartOutpostPath); } - LevelData tutorialLevel = new LevelData(levelSeed, 0, 0, generationParams, biome); + LevelData tutorialLevel = new LevelData(LevelSeed, 0, 0, generationParams, biome); GameMain.GameSession.StartRound(tutorialLevel, startOutpost: startOutpost); } else { - GameMain.GameSession.StartRound(levelSeed); + GameMain.GameSession.StartRound(LevelSeed); } GameMain.GameSession.EventManager.ActiveEvents.Clear(); @@ -274,6 +261,7 @@ namespace Barotrauma.Tutorials private void Initialize() { GameMain.GameSession.CrewManager.AllowCharacterSwitch = TutorialPrefab.AllowCharacterSwitch; + GameMain.GameSession.CrewManager.AutoHideCrewList(); if (Character.Controlled is Character character) { @@ -450,7 +438,7 @@ namespace Barotrauma.Tutorials public void TriggerTutorialSegment(Segment segment) { - if (segment.SegmentType == TutorialSegmentType.MessageBox) + if (segment.SegmentType != TutorialSegmentType.InfoBox) { ActiveObjectives.Add(segment); AddToObjectiveList(segment); @@ -462,7 +450,7 @@ namespace Barotrauma.Tutorials ActiveContentSegment = segment; var title = TextManager.Get(segment.Id); - LocalizedString tutorialText = TextManager.GetFormatted(segment.TextContent.Value.Tag); + LocalizedString tutorialText = TextManager.GetFormatted(segment.TextContent.Tag); tutorialText = TextManager.ParseInputTypes(tutorialText); switch (segment.AutoPlayVideo) @@ -471,9 +459,9 @@ namespace Barotrauma.Tutorials infoBox = CreateInfoFrame( title, tutorialText, - segment.TextContent.Value.Width, - segment.TextContent.Value.Height, - segment.TextContent.Value.Anchor, + segment.TextContent.Width, + segment.TextContent.Height, + segment.TextContent.Anchor, hasButton: true, onInfoBoxClosed: LoadActiveContentVideo); break; @@ -481,9 +469,9 @@ namespace Barotrauma.Tutorials infoBox = CreateInfoFrame( title, tutorialText, - segment.TextContent.Value.Width, - segment.TextContent.Value.Height, - segment.TextContent.Value.Anchor, + segment.TextContent.Width, + segment.TextContent.Height, + segment.TextContent.Anchor, hasButton: true, onInfoBoxClosed: StopCurrentContentSegment, onVideoButtonClicked: LoadActiveContentVideo); @@ -493,7 +481,7 @@ namespace Barotrauma.Tutorials public void CompleteTutorialSegment(Identifier segmentId) { - if (!(GetActiveObjective(segmentId) is Segment segment)) + if (GetActiveObjective(segmentId) is not Segment segment) { DebugConsole.AddWarning($"Warning: tried to complete the tutorial segment \"{segmentId}\" in tutorial \"{Identifier}\" but it isn't active!"); return; @@ -501,29 +489,28 @@ namespace Barotrauma.Tutorials if (GUIStyle.GetComponentStyle("ObjectiveIndicatorCompleted") is GUIComponentStyle style) { segment.ObjectiveStateIndicator.ApplyStyle(style); - segment.ObjectiveStateIndicator.Flash(color: GUIStyle.Green); } + segment.ObjectiveStateIndicator.Parent.Flash(color: GUIStyle.Green, flashDuration: 0.35f, useRectangleFlash: true); segment.ObjectiveButton.OnClicked = null; segment.ObjectiveButton.CanBeFocused = false; } public void RemoveTutorialSegment(Identifier segmentId) { - if (!(GetActiveObjective(segmentId) is Segment segment)) + if (GetActiveObjective(segmentId) is not Segment segment) { DebugConsole.AddWarning($"Warning: tried to remove the tutorial segment \"{segmentId}\" in tutorial \"{Identifier}\" but it isn't active!"); return; } - segment.ObjectiveStateIndicator.FadeOut(ObjectiveComponentRemovalTime, false); - segment.LinkedTextBlock.FadeOut(ObjectiveComponentRemovalTime, false); + segment.ObjectiveStateIndicator.FadeOut(ObjectiveComponentAnimationTime, false); + segment.LinkedTextBlock.FadeOut(ObjectiveComponentAnimationTime, false); var parent = segment.LinkedTextBlock.Parent; - parent.FadeOut(ObjectiveComponentRemovalTime, true, onRemove: () => + parent.FadeOut(ObjectiveComponentAnimationTime, true, onRemove: () => { ActiveObjectives.Remove(segment); objectiveGroup?.Recalculate(); }); - var targetPos = new Point(GameMain.GraphicsWidth - parent.Rect.X, 0); - parent.RectTransform.MoveOverTime(targetPos, ObjectiveComponentRemovalTime); + parent.RectTransform.MoveOverTime(GetObjectiveHiddenPosition(parent.RectTransform), ObjectiveComponentAnimationTime); segment.ObjectiveButton.OnClicked = null; segment.ObjectiveButton.CanBeFocused = false; } @@ -585,12 +572,14 @@ namespace Barotrauma.Tutorials { var frameRt = new RectTransform(new Vector2(1.0f, 0.1f), objectiveGroup.RectTransform) { + AbsoluteOffset = GetObjectiveHiddenPosition(), MinSize = new Point(0, objectiveGroup.AbsoluteSpacing) }; var frame = new GUIFrame(frameRt, style: null) { CanBeFocused = true }; + objectiveGroup.Recalculate(); segment.LinkedTextBlock = new GUITextBlock( new RectTransform(new Point(frameRt.Rect.Width - objectiveGroup.AbsoluteSpacing, 0), frame.RectTransform, anchor: Anchor.TopRight), @@ -612,6 +601,7 @@ namespace Barotrauma.Tutorials segment.ObjectiveButton = new GUIButton(new RectTransform(Vector2.One, segment.LinkedTextBlock.RectTransform, Anchor.TopLeft, Pivot.TopLeft), style: null) { + CanBeFocused = segment.SegmentType != TutorialSegmentType.Objective, ToolTip = objectiveTextTranslated, OnClicked = (GUIButton btn, object userdata) => { @@ -628,13 +618,15 @@ namespace Barotrauma.Tutorials } else if (segment.SegmentType == TutorialSegmentType.MessageBox) { - segment.OnClickToDisplayMessage?.Invoke(); + segment.OnClickObjective?.Invoke(); } return true; } }; SetTransparent(segment.ObjectiveButton); + frameRt.MoveOverTime(new Point(0, frameRt.AbsoluteOffset.Y), ObjectiveComponentAnimationTime, onDoneMoving: () => objectiveGroup?.Recalculate()); + static void SetTransparent(GUIComponent component) => component.Color = component.HoverColor = component.PressedColor = component.SelectedColor = Color.Transparent; } @@ -654,15 +646,20 @@ namespace Barotrauma.Tutorials ActiveContentSegment = segment; infoBox = CreateInfoFrame( TextManager.Get(segment.Id), - TextManager.Get(segment.TextContent.Value.Tag), - segment.TextContent.Value.Width, - segment.TextContent.Value.Height, - segment.TextContent.Value.Anchor, + TextManager.Get(segment.TextContent.Tag), + segment.TextContent.Width, + segment.TextContent.Height, + segment.TextContent.Anchor, hasButton: true, onInfoBoxClosed: () => ContentRunning = false, onVideoButtonClicked: () => LoadVideo(segment)); } + private Point GetObjectiveHiddenPosition(RectTransform rt = null) + { + return new Point(GameMain.GraphicsWidth - objectiveGroup.Rect.X, rt?.AbsoluteOffset.Y ?? 0); + } + #endregion #region InfoFrame @@ -772,9 +769,9 @@ namespace Barotrauma.Tutorials if (segment.AutoPlayVideo == AutoPlayVideo.Yes) { videoPlayer.LoadContent( - contentPath: PlayableContentPath, - videoSettings: new VideoPlayer.VideoSettings(segment.VideoContent.Value.File), - textSettings: new VideoPlayer.TextSettings(segment.VideoContent.Value.TextTag, segment.VideoContent.Value.Width), + contentPath: segment.VideoContent.ContentPath, + videoSettings: new VideoPlayer.VideoSettings(segment.VideoContent.FileName), + textSettings: new VideoPlayer.TextSettings(segment.VideoContent.TextTag, segment.VideoContent.Width), contentId: segment.Id, startPlayback: true, objective: segment.ObjectiveText, @@ -783,8 +780,8 @@ namespace Barotrauma.Tutorials else { videoPlayer.LoadContent( - contentPath: PlayableContentPath, - videoSettings: new VideoPlayer.VideoSettings(segment.VideoContent.Value.File), + contentPath: segment.VideoContent.ContentPath, + videoSettings: new VideoPlayer.VideoSettings(segment.VideoContent.FileName), textSettings: null, contentId: segment.Id, startPlayback: true, diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Holdable/RangedWeapon.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Holdable/RangedWeapon.cs index 39982b6cd..8a605499d 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Holdable/RangedWeapon.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Holdable/RangedWeapon.cs @@ -153,7 +153,7 @@ namespace Barotrauma.Items.Components GUI.MouseOn == null && !Inventory.IsMouseOnInventory && !GameMain.Instance.Paused; if (GUI.HideCursor) { - crosshairSprite?.Draw(spriteBatch, crosshairPos, Color.White, 0, currentCrossHairScale); + crosshairSprite?.Draw(spriteBatch, crosshairPos, ReloadTimer <= 0.0f ? Color.White : Color.White * 0.2f, 0, currentCrossHairScale); crosshairPointerSprite?.Draw(spriteBatch, crosshairPointerPos, 0, currentCrossHairPointerScale); } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/ItemComponent.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/ItemComponent.cs index a1b1857e8..77e267d14 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/ItemComponent.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/ItemComponent.cs @@ -369,6 +369,7 @@ namespace Barotrauma.Items.Components loopingSoundChannel = loopingSound.RoundSound.Sound.Play( new Vector3(position.X, position.Y, 0.0f), 0.01f, + freqMult: itemSound.RoundSound.GetRandomFrequencyMultiplier(), muffle: SoundPlayer.ShouldMuffleSound(Character.Controlled, position, loopingSound.Range, Character.Controlled?.CurrentHull)); loopingSoundChannel.Looping = true; //TODO: tweak diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Sonar.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Sonar.cs index 2deca5a59..dbac05552 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Sonar.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Sonar.cs @@ -1013,6 +1013,19 @@ namespace Barotrauma.Items.Components if (!CheckResourceMarkerVisibility(c.center, transducerCenter)) { continue; } var i = unobtainedMinerals.FirstOrDefault(); if (i == null) { continue; } + + bool disrupted = false; + foreach ((Vector2 disruptPos, float disruptStrength) in disruptedDirections) + { + float dot = Vector2.Dot(Vector2.Normalize(c.center - transducerCenter), disruptPos); + if (dot > 1.0f - disruptStrength) + { + disrupted = true; + break; + } + } + if (disrupted) { continue; } + DrawMarker(spriteBatch, i.Name, "mineral".ToIdentifier(), "mineralcluster" + i, c.center, transducerCenter, diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Repairable.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Repairable.cs index 83f660f0d..a6c9f47da 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Repairable.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Repairable.cs @@ -22,6 +22,8 @@ namespace Barotrauma.Items.Components private GUILayoutGroup extraButtonContainer; + private GUIComponent skillTextContainer; + private readonly List particleEmitters = new List(); //the corresponding particle emitter is active when the condition is within this range private readonly List particleEmitterConditionRanges = new List(); @@ -132,9 +134,10 @@ namespace Barotrauma.Items.Components new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedFrame.RectTransform), TextManager.Get("RequiredRepairSkills"), font: GUIStyle.SubHeadingFont); + skillTextContainer = paddedFrame; for (int i = 0; i < requiredSkills.Count; i++) { - var skillText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedFrame.RectTransform), + var skillText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), skillTextContainer.RectTransform), " - " + TextManager.AddPunctuation(':', TextManager.Get("SkillName." + requiredSkills[i].Identifier), ((int) Math.Round(requiredSkills[i].Level * SkillRequirementMultiplier)).ToString()), font: GUIStyle.SmallFont) { @@ -359,19 +362,11 @@ namespace Barotrauma.Items.Components extraButtonContainer.Visible = SabotageButton.Visible || TinkerButton.Visible; extraButtonContainer.IgnoreLayoutGroups = !extraButtonContainer.Visible; - foreach (GUIComponent c in GuiFrame.GetChild(0).Children) + foreach (GUIComponent c in skillTextContainer.Children) { - if (!(c.UserData is Skill skill)) continue; - + if (c.UserData is not Skill skill) { continue; } GUITextBlock textBlock = (GUITextBlock)c; - if (character.GetSkillLevel(skill.Identifier) < (skill.Level * SkillRequirementMultiplier)) - { - textBlock.TextColor = GUIStyle.Red; - } - else - { - textBlock.TextColor = Color.White; - } + textBlock.TextColor = character.GetSkillLevel(skill.Identifier) < (skill.Level * SkillRequirementMultiplier) ? GUIStyle.Red : GUIStyle.TextColorNormal; } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Item.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Item.cs index 1a6590180..8950850cc 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Item.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Item.cs @@ -823,7 +823,7 @@ namespace Barotrauma reloadTextureButton.OnClicked += (button, data) => { Sprite.ReloadXML(); - Sprite.ReloadTexture(updateAllSprites: true); + Sprite.ReloadTexture(); return true; }; } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Map/Structure.cs b/Barotrauma/BarotraumaClient/ClientSource/Map/Structure.cs index 1342557f5..b41a0f0a6 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Map/Structure.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Map/Structure.cs @@ -163,7 +163,7 @@ namespace Barotrauma OnClicked = (button, data) => { Sprite.ReloadXML(); - Sprite.ReloadTexture(updateAllSprites: true); + Sprite.ReloadTexture(); return true; } }; diff --git a/Barotrauma/BarotraumaClient/ClientSource/Map/SubmarineInfo.cs b/Barotrauma/BarotraumaClient/ClientSource/Map/SubmarineInfo.cs index f0047e10c..a08893601 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Map/SubmarineInfo.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Map/SubmarineInfo.cs @@ -93,10 +93,11 @@ namespace Barotrauma { float leftPanelWidth = 0.6f; float rightPanelWidth = 0.4f / leftPanelWidth; - LocalizedString className = !HasTag(SubmarineTag.Shuttle) - ? $"{TextManager.Get($"submarineclass.{SubmarineClass}")} ({TextManager.Get($"submarinetier.{Tier}")})" - : TextManager.Get("shuttle"); - + LocalizedString className = !HasTag(SubmarineTag.Shuttle) ? + TextManager.GetWithVariables("submarine.classandtier", + ("[class]", TextManager.Get($"submarineclass.{SubmarineClass}")), + ("[tier]", TextManager.Get($"submarinetier.{Tier}"))) : + TextManager.Get("shuttle"); int classHeight = (int)GUIStyle.SubHeadingFont.MeasureString(className).Y; int leftPanelWidthInt = (int)(parent.Rect.Width * leftPanelWidth); diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/Client.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/Client.cs index 480fa90cc..3c72ee33a 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Networking/Client.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/Client.cs @@ -134,6 +134,14 @@ namespace Barotrauma.Networking return Permissions.HasFlag(permission); } + public void ResetVotes() + { + for (int i = 0; i < votes.Length; i++) + { + votes[i] = null; + } + } + partial void DisposeProjSpecific() { if (VoipQueue != null) diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/GameClient.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/GameClient.cs index 30ab2172f..c78321411 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Networking/GameClient.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/GameClient.cs @@ -14,12 +14,12 @@ using System.Xml.Linq; namespace Barotrauma.Networking { - class GameClient : NetworkMember + sealed class GameClient : NetworkMember { - public override bool IsClient - { - get { return true; } - } + public override bool IsClient => true; + public override bool IsServer => false; + + public override Voting Voting { get; } private UInt16 nameId = 0; @@ -29,7 +29,6 @@ namespace Barotrauma.Networking public void SetName(string value) { - value = value.Replace(":", "").Replace(";", ""); if (string.IsNullOrEmpty(value)) { return; } Name = value; nameId++; @@ -40,8 +39,7 @@ namespace Barotrauma.Networking nameId++; } - private ClientPeer clientPeer; - public ClientPeer ClientPeer { get { return clientPeer; } } + public ClientPeer ClientPeer { get; private set; } private GUIMessageBox reconnectBox, waitInServerQueueBox; @@ -56,7 +54,7 @@ namespace Barotrauma.Networking public GUITickBox FollowSubTickBox => cameraFollowsSub; public bool IsFollowSubTickBoxVisible => - gameStarted && Screen.Selected == GameMain.GameScreen && + GameStarted && Screen.Selected == GameMain.GameScreen && cameraFollowsSub != null && cameraFollowsSub.Visible; public CameraTransition EndCinematic; @@ -88,9 +86,6 @@ namespace Barotrauma.Networking public string ServerName { get; private set; } - private bool allowReconnect; - private bool requiresPw; - private int pwRetries; private bool canStart; private UInt16 lastSentChatMsgID = 0; //last message this client has successfully sent @@ -99,14 +94,10 @@ namespace Barotrauma.Networking public UInt16 LastSentEntityEventID; - private readonly ClientEntityEventManager entityEventManager; - - private readonly FileReceiver fileReceiver; - #if DEBUG public void PrintReceiverTransters() { - foreach (var transfer in fileReceiver.ActiveTransfers) + foreach (var transfer in FileReceiver.ActiveTransfers) { DebugConsole.NewMessage(transfer.FileName + " " + transfer.Progress.ToString()); } @@ -136,26 +127,30 @@ namespace Barotrauma.Networking } } + public Option Ping + { + get + { + Client selfClient = ConnectedClients.FirstOrDefault(c => c.SessionId == SessionId); + if (selfClient is null || selfClient.Ping == 0) { return Option.None(); } + return Option.Some(selfClient.Ping); + } + } + private readonly List previouslyConnectedClients = new List(); public IEnumerable PreviouslyConnectedClients { get { return previouslyConnectedClients; } } - public FileReceiver FileReceiver - { - get { return fileReceiver; } - } + public readonly FileReceiver FileReceiver; public bool MidRoundSyncing { - get { return entityEventManager.MidRoundSyncing; } + get { return EntityEventManager.MidRoundSyncing; } } - public ClientEntityEventManager EntityEventManager - { - get { return entityEventManager; } - } + public readonly ClientEntityEventManager EntityEventManager; public bool? WaitForNextRoundRespawn { @@ -189,8 +184,6 @@ namespace Barotrauma.Networking roundInitStatus = RoundInitStatus.NotStarted; - allowReconnect = true; - NetStats = new NetStats(); inGameHUD = new GUIFrame(new RectTransform(GUI.Canvas.RelativeSize, GUI.Canvas), style: null) @@ -237,13 +230,13 @@ namespace Barotrauma.Networking { OnClicked = (GUIButton button, object userData) => { - if (serverSettings.ServerLog.LogFrame == null) + if (ServerSettings.ServerLog.LogFrame == null) { - serverSettings.ServerLog.CreateLogFrame(); + ServerSettings.ServerLog.CreateLogFrame(); } else { - serverSettings.ServerLog.LogFrame = null; + ServerSettings.ServerLog.LogFrame = null; GUI.KeyboardDispatcher.Subscriber = null; } return true; @@ -257,11 +250,11 @@ namespace Barotrauma.Networking SetName(newName); - entityEventManager = new ClientEntityEventManager(this); + EntityEventManager = new ClientEntityEventManager(this); - fileReceiver = new FileReceiver(); - fileReceiver.OnFinished += OnFileReceived; - fileReceiver.OnTransferFailed += OnTransferFailed; + FileReceiver = new FileReceiver(); + FileReceiver.OnFinished += OnFileReceived; + FileReceiver.OnTransferFailed += OnTransferFailed; characterInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, Name, originalName: null) { @@ -270,7 +263,7 @@ namespace Barotrauma.Networking otherClients = new List(); - serverSettings = new ServerSettings(this, "Server", 0, 0, 0, false, false); + ServerSettings = new ServerSettings(this, "Server", 0, 0, 0, false, false); Voting = new Voting(); serverEndpoint = endpoint; @@ -282,6 +275,13 @@ namespace Barotrauma.Networking GameMain.ResetNetLobbyScreen(); } + public ServerInfo CreateServerInfoFromSettings() + { + var serverInfo = ServerInfo.FromServerConnection(ClientPeer.ServerConnection, ServerSettings); + GameMain.ServerListScreen.UpdateOrAddServerInfo(serverInfo); + return serverInfo; + } + private void InitiateServerJoin(string hostName) { LastClientListUpdateID = 0; @@ -304,11 +304,9 @@ namespace Barotrauma.Networking myCharacter = Character.Controlled; ChatMessage.LastID = 0; - clientPeer?.Close(); - clientPeer = CreateNetPeer(); - clientPeer.Start(); - - updateInterval = new TimeSpan(0, 0, 0, 0, 150); + ClientPeer?.Close(PeerDisconnectPacket.WithReason(DisconnectReason.Disconnected)); + ClientPeer = CreateNetPeer(); + ClientPeer.Start(); CoroutineManager.StartCoroutine(WaitForStartingInfo(), "WaitForStartingInfo"); } @@ -318,16 +316,6 @@ namespace Barotrauma.Networking Networking.ClientPeer.Callbacks callbacks = new ClientPeer.Callbacks( ReadDataMessage, OnClientPeerDisconnect, - HandleDisconnectMessage, - (int salt, int retries) => - { - if (pwRetries != retries) - { - wrongPassword = retries > 0; - requiresPw = true; - } - pwRetries = retries; - }, OnConnectionInitializationComplete); return serverEndpoint switch { @@ -362,21 +350,15 @@ namespace Barotrauma.Networking private bool connectCancelled; private void CancelConnect() { - ChildServerRelay.ShutDown(); - connectCancelled = true; Quit(); } - private bool wrongPassword; - // Before main looping starts, we loop here and wait for approval message private IEnumerable WaitForStartingInfo() { GUI.SetCursorWaiting(); - requiresPw = false; - pwRetries = -1; - connectCancelled = wrongPassword = false; + connectCancelled = false; // When this is set to true, we are approved and ready to go canStart = false; @@ -390,7 +372,7 @@ namespace Barotrauma.Networking if (reconnectBox == null && waitInServerQueueBox == null) { string serverDisplayName = ServerName; - if (string.IsNullOrEmpty(serverDisplayName) && clientPeer?.ServerConnection is SteamP2PConnection steamConnection) + if (string.IsNullOrEmpty(serverDisplayName) && ClientPeer?.ServerConnection is SteamP2PConnection steamConnection) { if (SteamManager.IsInitialized && steamConnection.AccountInfo.AccountId.TryUnwrap(out var accountId) && accountId is SteamId steamId) { @@ -404,12 +386,9 @@ namespace Barotrauma.Networking } if (string.IsNullOrEmpty(serverDisplayName)) { serverDisplayName = TextManager.Get("Unknown").Value; } - reconnectBox = new GUIMessageBox( + CreateReconnectBox( connectingText, - TextManager.GetWithVariable("ConnectingTo", "[serverip]", serverDisplayName), - new LocalizedString[] { TextManager.Get("Cancel") }); - reconnectBox.Buttons[0].OnClicked += (btn, userdata) => { CancelConnect(); return true; }; - reconnectBox.Buttons[0].OnClicked += reconnectBox.Close; + TextManager.GetWithVariable("ConnectingTo", "[serverip]", serverDisplayName)); } if (reconnectBox != null) @@ -421,82 +400,29 @@ namespace Barotrauma.Networking if (DateTime.Now > timeOut) { - clientPeer?.Close(Lidgren.Network.NetConnection.NoResponseMessage); - var msgBox = new GUIMessageBox(TextManager.Get("ConnectionFailed"), TextManager.Get("CouldNotConnectToServer")); + ClientPeer?.Close(PeerDisconnectPacket.WithReason(DisconnectReason.Timeout)); + var msgBox = new GUIMessageBox(TextManager.Get("ConnectionFailed"), TextManager.Get("CouldNotConnectToServer")) + { + DisplayInLoadingScreens = true + }; msgBox.Buttons[0].OnClicked += ReturnToPreviousMenu; - reconnectBox?.Close(); reconnectBox = null; + CloseReconnectBox(); break; } - if (requiresPw && !canStart && !connectCancelled) + if (ClientPeer.WaitingForPassword && !canStart && !connectCancelled) { GUI.ClearCursorWait(); - reconnectBox?.Close(); reconnectBox = null; + CloseReconnectBox(); - LocalizedString pwMsg = TextManager.Get("PasswordRequired"); - - var msgBox = new GUIMessageBox(pwMsg, "", new LocalizedString[] { TextManager.Get("OK"), TextManager.Get("Cancel") }, - relativeSize: new Vector2(0.25f, 0.1f), minSize: new Point(400, GUI.IntScale(170))); - var passwordHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.5f), msgBox.Content.RectTransform), childAnchor: Anchor.TopCenter); - var passwordBox = new GUITextBox(new RectTransform(new Vector2(0.8f, 1f), passwordHolder.RectTransform) { MinSize = new Point(0, 20) }) + while (ClientPeer.WaitingForPassword) { - UserData = "password", - Censor = true - }; - - if (wrongPassword) - { - var incorrectPasswordText = new GUITextBlock(new RectTransform(new Vector2(1f, 0.0f), passwordHolder.RectTransform), TextManager.Get("incorrectpassword"), GUIStyle.Red, GUIStyle.Font, textAlignment: Alignment.Center); - incorrectPasswordText.RectTransform.MinSize = new Point(0, (int)incorrectPasswordText.TextSize.Y); - passwordHolder.Recalculate(); - } - - msgBox.Content.Recalculate(); - msgBox.Content.RectTransform.MinSize = new Point(0, msgBox.Content.RectTransform.Children.Sum(c => c.Rect.Height)); - msgBox.Content.Parent.RectTransform.MinSize = new Point(0, (int)(msgBox.Content.RectTransform.MinSize.Y / msgBox.Content.RectTransform.RelativeSize.Y)); - - var okButton = msgBox.Buttons[0]; - okButton.OnClicked += msgBox.Close; - var cancelButton = msgBox.Buttons[1]; - cancelButton.OnClicked += msgBox.Close; - passwordBox.OnEnterPressed += (GUITextBox textBox, string text) => - { - msgBox.Close(); - clientPeer?.SendPassword(passwordBox.Text); - requiresPw = false; - return true; - }; - - okButton.OnClicked += (GUIButton button, object obj) => - { - clientPeer?.SendPassword(passwordBox.Text); - requiresPw = false; - return true; - }; - - cancelButton.OnClicked += (GUIButton button, object obj) => - { - requiresPw = false; - connectCancelled = true; - GameMain.ServerListScreen.Select(); - return true; - }; - yield return CoroutineStatus.Running; - passwordBox.Select(); - - while (GUIMessageBox.MessageBoxes.Contains(msgBox)) - { - if (!requiresPw) - { - msgBox.Close(); - break; - } yield return CoroutineStatus.Running; } } } - reconnectBox?.Close(); reconnectBox = null; + CloseReconnectBox(); GUI.ClearCursorWait(); if (connectCancelled) { yield return CoroutineStatus.Success; } @@ -504,7 +430,7 @@ namespace Barotrauma.Networking yield return CoroutineStatus.Success; } - public override void Update(float deltaTime) + public void Update(float deltaTime) { #if DEBUG if (PlayerInput.GetKeyboardState.IsKeyDown(Keys.P)) return; @@ -541,8 +467,6 @@ namespace Barotrauma.Networking UpdateHUD(deltaTime); - base.Update(deltaTime); - try { incomingMessagesToProcess.Clear(); @@ -552,7 +476,7 @@ namespace Barotrauma.Networking ReadDataMessage(inc); } pendingIncomingMessages.Clear(); - clientPeer?.Update(deltaTime); + ClientPeer?.Update(deltaTime); } catch (Exception e) { @@ -571,19 +495,15 @@ namespace Barotrauma.Networking return; } - if (!connected) return; + if (!connected) { return; } - if (reconnectBox != null) - { - reconnectBox.Close(); - reconnectBox = null; - } + CloseReconnectBox(); - if (gameStarted && Screen.Selected == GameMain.GameScreen) + if (GameStarted && Screen.Selected == GameMain.GameScreen) { EndVoteTickBox.Visible = ServerSettings.AllowEndVoting && HasSpawned && !(GameMain.GameSession?.GameMode is CampaignMode); - respawnManager?.Update(deltaTime); + RespawnManager?.Update(deltaTime); if (updateTimer <= DateTime.Now) { @@ -598,7 +518,7 @@ namespace Barotrauma.Networking } } - if (serverSettings.VoiceChatEnabled) + if (ServerSettings.VoiceChatEnabled) { VoipClient?.SendToServer(); } @@ -622,7 +542,7 @@ namespace Barotrauma.Networking if (updateTimer <= DateTime.Now) { // Update current time - updateTimer = DateTime.Now + updateInterval; + updateTimer = DateTime.Now + UpdateInterval; } } @@ -633,11 +553,12 @@ namespace Barotrauma.Networking { ServerPacketHeader header = (ServerPacketHeader)inc.ReadByte(); - if (roundInitStatus == RoundInitStatus.WaitingForStartGameFinalize && - roundInitStatus == RoundInitStatus.Started && - header != ServerPacketHeader.ENDGAME && - header != ServerPacketHeader.PING_REQUEST && - header != ServerPacketHeader.FILE_TRANSFER) + if (roundInitStatus == RoundInitStatus.WaitingForStartGameFinalize + && header is not ( + ServerPacketHeader.STARTGAMEFINALIZE + or ServerPacketHeader.ENDGAME + or ServerPacketHeader.PING_REQUEST + or ServerPacketHeader.FILE_TRANSFER)) { //rewind the header byte we just read inc.BitPosition -= 8; @@ -660,10 +581,10 @@ namespace Barotrauma.Networking //allow interpreting this packet break; case ServerPacketHeader.STARTGAME: - gameStarted = true; + GameStarted = true; return; case ServerPacketHeader.ENDGAME: - gameStarted = false; + GameStarted = false; return; default: return; //ignore any other packets @@ -682,7 +603,7 @@ namespace Barotrauma.Networking byte b = inc.ReadByte(); response.WriteByte(b); } - clientPeer.Send(response, DeliveryMethod.Unreliable); + ClientPeer.Send(response, DeliveryMethod.Unreliable); break; case ServerPacketHeader.CLIENT_PINGS: byte clientCount = inc.ReadByte(); @@ -776,7 +697,7 @@ namespace Barotrauma.Networking WriteCharacterInfo(readyToStartMsg); - clientPeer.Send(readyToStartMsg, DeliveryMethod.Reliable); + ClientPeer.Send(readyToStartMsg, DeliveryMethod.Reliable); if (readyToStart && !CoroutineManager.IsCoroutineRunning("WaitForStartRound")) { @@ -803,7 +724,7 @@ namespace Barotrauma.Networking //waiting for a save file if (campaign != null && NetIdUtils.IdMoreRecent(campaign.PendingSaveID, campaign.LastSaveID) && - fileReceiver.ActiveTransfers.Any(t => t.FileType == FileTransferType.CampaignSave)) + FileReceiver.ActiveTransfers.Any(t => t.FileType == FileTransferType.CampaignSave)) { return; } @@ -898,7 +819,7 @@ namespace Barotrauma.Networking ReadyCheck.ClientRead(inc); break; case ServerPacketHeader.FILE_TRANSFER: - fileReceiver.ReadMessage(inc); + FileReceiver.ReadMessage(inc); break; case ServerPacketHeader.TRAITOR_MESSAGE: ReadTraitorMessage(inc); @@ -1003,204 +924,136 @@ namespace Barotrauma.Networking /// /// Fires when the ClientPeer gets disconnected from the server. Does not necessarily mean the client is shutting down, we may still be able to reconnect. /// - private void OnClientPeerDisconnect(bool disableReconnect) + private void OnClientPeerDisconnect(PeerDisconnectPacket disconnectPacket) { + bool wasConnected = connected; + connected = false; + connectCancelled = true; + CoroutineManager.StopCoroutines("WaitForStartingInfo"); - reconnectBox?.Close(); - reconnectBox = null; + CloseReconnectBox(); GUI.ClearCursorWait(); - if (disableReconnect) { allowReconnect = false; } - if (!this.allowReconnect) { CancelConnect(); } - + ChildServerRelay.ShutDown(); + if (SteamManager.IsInitialized) { Steamworks.SteamFriends.ClearRichPresence(); } - } - private void HandleDisconnectMessage(string disconnectMsg) - { - disconnectMsg = disconnectMsg ?? ""; - - string[] splitMsg = disconnectMsg.Split('/'); - DisconnectReason disconnectReason = DisconnectReason.Unknown; - bool disconnectReasonIncluded = false; - if (splitMsg.Length > 0) - { - if (Enum.TryParse(splitMsg[0], out disconnectReason)) { disconnectReasonIncluded = true; } - } - - if (disconnectMsg == Lidgren.Network.NetConnection.NoResponseMessage || - disconnectReason == DisconnectReason.Banned || - disconnectReason == DisconnectReason.Kicked || - disconnectReason == DisconnectReason.TooManyFailedLogins) - { - allowReconnect = false; - } - - DebugConsole.NewMessage("Received a disconnect message (" + disconnectMsg + ")"); - - if (disconnectReason != DisconnectReason.Banned && - disconnectReason != DisconnectReason.ServerShutdown && - disconnectReason != DisconnectReason.TooManyFailedLogins && - disconnectReason != DisconnectReason.MissingContentPackage && - disconnectReason != DisconnectReason.InvalidVersion) + if (disconnectPacket.ShouldCreateAnalyticsEvent) { GameAnalyticsManager.AddErrorEventOnce( "GameClient.HandleDisconnectMessage", GameAnalyticsManager.ErrorSeverity.Debug, - "Client received a disconnect message. Reason: " + disconnectReason.ToString()); + $"Client received a disconnect message. Reason: {disconnectPacket.DisconnectReason}"); } - - if (disconnectReason == DisconnectReason.ServerFull) + + if (disconnectPacket.DisconnectReason == DisconnectReason.ServerFull) { - CoroutineManager.StopCoroutines("WaitForStartingInfo"); - //already waiting for a slot to free up, stop waiting for starting info and - //let WaitInServerQueue reattempt connecting later - if (CoroutineManager.IsCoroutineRunning("WaitInServerQueue")) - { - return; - } - - reconnectBox?.Close(); reconnectBox = null; - - var queueBox = new GUIMessageBox( - TextManager.Get("DisconnectReason.ServerFull"), - TextManager.Get("ServerFullQuestionPrompt"), new LocalizedString[] { TextManager.Get("Cancel"), TextManager.Get("ServerQueue") }); - - queueBox.Buttons[0].OnClicked += queueBox.Close; - queueBox.Buttons[1].OnClicked += queueBox.Close; - queueBox.Buttons[1].OnClicked += (btn, userdata) => - { - reconnectBox?.Close(); reconnectBox = null; - CoroutineManager.StartCoroutine(WaitInServerQueue(), "WaitInServerQueue"); - return true; - }; - return; + AskToWaitInQueue(); } - else + else if (disconnectPacket.ShouldAttemptReconnect && !IsServerOwner && wasConnected) { - //disconnected/denied for some other reason than the server being full - // -> stop queuing and show a message box - waitInServerQueueBox?.Close(); - waitInServerQueueBox = null; - CoroutineManager.StopCoroutines("WaitInServerQueue"); - } - - bool eventSyncError = - disconnectReason == DisconnectReason.ExcessiveDesyncOldEvent || - disconnectReason == DisconnectReason.ExcessiveDesyncRemovedEvent || - disconnectReason == DisconnectReason.SyncTimeout; - - if (allowReconnect && - (disconnectReason == DisconnectReason.Unknown || eventSyncError)) - { - if (eventSyncError) + if (disconnectPacket.IsEventSyncError) { GameMain.NetLobbyScreen.Select(); GameMain.GameSession?.EndRound("", null); - gameStarted = false; + GameStarted = false; myCharacter = null; } - - DebugConsole.NewMessage("Attempting to reconnect..."); - - //if the first part of the message is the disconnect reason Enum, don't include it in the popup message - LocalizedString msg = TextManager.GetServerMessage(disconnectReasonIncluded ? string.Join('/', splitMsg.Skip(1)) : disconnectMsg); - msg = msg.IsNullOrWhiteSpace() ? - TextManager.Get("ConnectionLostReconnecting") : - msg + '\n' + TextManager.Get("ConnectionLostReconnecting"); - - reconnectBox?.Close(); - reconnectBox = new GUIMessageBox( - TextManager.Get("ConnectionLost"), msg, - new LocalizedString[] { TextManager.Get("Cancel") }) + AttemptReconnect(disconnectPacket); + } + else if (disconnectPacket.ShouldShowMessage) + { + ReturnToPreviousMenu(null, null); + var msgBox = new GUIMessageBox(TextManager.Get(wasConnected ? "ConnectionLost" : "CouldNotConnectToServer"), disconnectPacket.PopupMessage) { DisplayInLoadingScreens = true }; - reconnectBox.Buttons[0].OnClicked += ReturnToPreviousMenu; - connected = false; - var prevContentPackages = clientPeer.ServerContentPackages; - //decrement lobby update ID to make sure we update the lobby when we reconnect - GameMain.NetLobbyScreen.LastUpdateID--; - InitiateServerJoin(ServerName); - if (clientPeer != null) - { - //restore the previous list of content packages so we can reconnect immediately without having to recheck that the packages match - clientPeer.ServerContentPackages = prevContentPackages; - } - } - else - { - connected = false; - connectCancelled = true; - - LocalizedString msg = ""; - if (disconnectReason == DisconnectReason.Unknown) - { - DebugConsole.NewMessage("Not attempting to reconnect (unknown disconnect reason)."); - msg = disconnectMsg; - } - else - { - DebugConsole.NewMessage("Not attempting to reconnect (DisconnectReason doesn't allow reconnection)."); - msg = TextManager.Get("DisconnectReason." + disconnectReason.ToString()) + " "; - - for (int i = 1; i < splitMsg.Length; i++) - { - msg += TextManager.GetServerMessage(splitMsg[i]); - } - - if (disconnectReason == DisconnectReason.ServerCrashed && IsServerOwner) - { - msg = TextManager.GetWithVariable("ServerProcessCrashed", "[reportfilepath]", ChildServerRelay.CrashReportFilePath); - } - } - - reconnectBox?.Close(); - - if (msg == Lidgren.Network.NetConnection.NoResponseMessage) - { - //display a generic "could not connect" popup if the message is Lidgren's "failed to establish connection" - var msgBox = new GUIMessageBox(TextManager.Get("ConnectionFailed"), TextManager.Get(allowReconnect ? "ConnectionLost" : "CouldNotConnectToServer")) - { - DisplayInLoadingScreens = true - }; - msgBox.Buttons[0].OnClicked += ReturnToPreviousMenu; - } - else - { - var msgBox = new GUIMessageBox(TextManager.Get(allowReconnect ? "ConnectionLost" : "CouldNotConnectToServer"), msg) - { - DisplayInLoadingScreens = true - }; - msgBox.Buttons[0].OnClicked += ReturnToPreviousMenu; - } - - if (disconnectReason == DisconnectReason.InvalidName) - { - GameMain.ServerListScreen.ClientNameBox.Text = ""; - GameMain.ServerListScreen.ClientNameBox.Flash(flashDuration: 5.0f); - GameMain.ServerListScreen.ClientNameBox.Select(); - } } } + private void CreateReconnectBox(LocalizedString headerText, LocalizedString bodyText) + { + reconnectBox = new GUIMessageBox( + headerText, + bodyText, + new LocalizedString[] { TextManager.Get("Cancel") }) + { + DisplayInLoadingScreens = true + }; + reconnectBox.Buttons[0].OnClicked += (btn, userdata) => { CancelConnect(); return true; }; + reconnectBox.Buttons[0].OnClicked += reconnectBox.Close; + } + + private void CloseReconnectBox() + { + reconnectBox?.Close(); + reconnectBox = null; + } + + private void AskToWaitInQueue() + { + CoroutineManager.StopCoroutines("WaitForStartingInfo"); + //already waiting for a slot to free up, stop waiting for starting info and + //let WaitInServerQueue reattempt connecting later + if (CoroutineManager.IsCoroutineRunning("WaitInServerQueue")) + { + return; + } + + var queueBox = new GUIMessageBox( + TextManager.Get("DisconnectReason.ServerFull"), + TextManager.Get("ServerFullQuestionPrompt"), new LocalizedString[] { TextManager.Get("Cancel"), TextManager.Get("ServerQueue") }); + + queueBox.Buttons[0].OnClicked += queueBox.Close; + queueBox.Buttons[1].OnClicked += queueBox.Close; + queueBox.Buttons[1].OnClicked += (btn, userdata) => + { + CloseReconnectBox(); + CoroutineManager.StartCoroutine(WaitInServerQueue(), "WaitInServerQueue"); + return true; + }; + } + + private void AttemptReconnect(PeerDisconnectPacket peerDisconnectPacket) + { + connectCancelled = false; + + CreateReconnectBox( + TextManager.Get("ConnectionLost"), + peerDisconnectPacket.ReconnectMessage); + + var prevContentPackages = ClientPeer.ServerContentPackages; + //decrement lobby update ID to make sure we update the lobby when we reconnect + GameMain.NetLobbyScreen.LastUpdateID--; + InitiateServerJoin(ServerName); + if (ClientPeer != null) + { + //restore the previous list of content packages so we can reconnect immediately without having to recheck that the packages match + ClientPeer.ServerContentPackages = prevContentPackages; + } + } + private void OnConnectionInitializationComplete() { if (SteamManager.IsInitialized) { Steamworks.SteamFriends.ClearRichPresence(); - Steamworks.SteamFriends.SetRichPresence("status", "Playing on " + ServerName); - Steamworks.SteamFriends.SetRichPresence("connect", "-connect \"" + ServerName.Replace("\"", "\\\"") + "\" " + serverEndpoint); + Steamworks.SteamFriends.SetRichPresence("servername", ServerName); + #warning TODO: use Steamworks localization functionality + Steamworks.SteamFriends.SetRichPresence("status", + TextManager.GetWithVariable("FriendPlayingOnServer", "[servername]", ServerName).Value); + Steamworks.SteamFriends.SetRichPresence("connect", + $"-connect \"{ToolBox.EscapeCharacters(ServerName)}\" {serverEndpoint}"); } canStart = true; connected = true; - VoipClient = new VoipClient(this, clientPeer); + VoipClient = new VoipClient(this, ClientPeer); //if we're still in the game, roundsummary or lobby screen, we don't need to redownload the mods if (!(Screen.Selected is GameScreen) && !(Screen.Selected is RoundSummaryScreen) && !(Screen.Selected is NetLobbyScreen)) @@ -1209,7 +1062,7 @@ namespace Barotrauma.Networking } else { - entityEventManager.ClearSelf(); + EntityEventManager.ClearSelf(); foreach (Character c in Character.CharacterList) { c.ResetNetState(); @@ -1433,7 +1286,7 @@ namespace Barotrauma.Networking //(for example, due to a missing sub file or an error) GameMain.NetLobbyScreen.ShowSpectateButton(); - entityEventManager.Clear(); + EntityEventManager.Clear(); LastSentEntityEventID = 0; EndVoteTickBox.Selected = false; @@ -1454,19 +1307,19 @@ namespace Barotrauma.Networking } bool respawnAllowed = inc.ReadBoolean(); - serverSettings.AllowDisguises = inc.ReadBoolean(); - serverSettings.AllowRewiring = inc.ReadBoolean(); - serverSettings.AllowFriendlyFire = inc.ReadBoolean(); - serverSettings.LockAllDefaultWires = inc.ReadBoolean(); - serverSettings.AllowRagdollButton = inc.ReadBoolean(); - serverSettings.AllowLinkingWifiToChat = inc.ReadBoolean(); - serverSettings.MaximumMoneyTransferRequest = inc.ReadInt32(); + ServerSettings.AllowDisguises = inc.ReadBoolean(); + ServerSettings.AllowRewiring = inc.ReadBoolean(); + ServerSettings.AllowFriendlyFire = inc.ReadBoolean(); + ServerSettings.LockAllDefaultWires = inc.ReadBoolean(); + ServerSettings.AllowRagdollButton = inc.ReadBoolean(); + ServerSettings.AllowLinkingWifiToChat = inc.ReadBoolean(); + ServerSettings.MaximumMoneyTransferRequest = inc.ReadInt32(); bool usingShuttle = GameMain.NetLobbyScreen.UsingShuttle = inc.ReadBoolean(); GameMain.LightManager.LosMode = (LosMode)inc.ReadByte(); bool includesFinalize = inc.ReadBoolean(); inc.ReadPadBits(); GameMain.LightManager.LightingEnabled = true; - serverSettings.ReadMonsterEnabled(inc); + ServerSettings.ReadMonsterEnabled(inc); Rand.SetSyncedSeed(seed); @@ -1522,7 +1375,7 @@ namespace Barotrauma.Networking errorMsg += "\n" + "Hash mismatch: " + GameMain.NetLobbyScreen.SelectedSub.MD5Hash?.StringRepresentation + " != " + subHash; } } - gameStarted = true; + GameStarted = true; GameMain.NetLobbyScreen.Select(); DebugConsole.ThrowError(errorMsg); GameAnalyticsManager.AddErrorEventOnce("GameClient.StartGame:FailedToSelectSub" + subName, GameAnalyticsManager.ErrorSeverity.Error, errorMsg); @@ -1533,7 +1386,7 @@ namespace Barotrauma.Networking GameMain.NetLobbyScreen.SelectedShuttle.Name != shuttleName || GameMain.NetLobbyScreen.SelectedShuttle.MD5Hash?.StringRepresentation != shuttleHash) { - gameStarted = true; + GameStarted = true; GameMain.NetLobbyScreen.Select(); string errorMsg = "Failed to select shuttle \"" + shuttleName + "\" (hash: " + shuttleHash + ")."; DebugConsole.ThrowError(errorMsg); @@ -1565,7 +1418,7 @@ namespace Barotrauma.Networking if (campaign.CampaignID != campaignID) { - gameStarted = true; + GameStarted = true; DebugConsole.ThrowError("Failed to start campaign round (campaign ID does not match)."); GameMain.NetLobbyScreen.Select(); roundInitStatus = RoundInitStatus.Interrupted; @@ -1573,7 +1426,7 @@ namespace Barotrauma.Networking } else if (campaign.Map == null) { - gameStarted = true; + GameStarted = true; DebugConsole.ThrowError("Failed to start campaign round (campaign map not loaded yet)."); GameMain.NetLobbyScreen.Select(); roundInitStatus = RoundInitStatus.Interrupted; @@ -1588,7 +1441,7 @@ namespace Barotrauma.Networking { if (DateTime.Now > saveFileTimeOut) { - gameStarted = true; + GameStarted = true; DebugConsole.ThrowError("Failed to start campaign round (timed out while waiting for the up-to-date save file)."); GameMain.NetLobbyScreen.Select(); roundInitStatus = RoundInitStatus.Interrupted; @@ -1626,7 +1479,7 @@ namespace Barotrauma.Networking } } - if (clientPeer == null) + if (ClientPeer == null) { DebugConsole.ThrowError("There was an error initializing the round (disconnected during the StartGame coroutine.)"); roundInitStatus = RoundInitStatus.Error; @@ -1641,7 +1494,7 @@ namespace Barotrauma.Networking TimeSpan requestFinalizeInterval = new TimeSpan(0, 0, 2); IWriteMessage msg = new WriteOnlyMessage(); msg.WriteByte((byte)ClientPacketHeader.REQUEST_STARTGAMEFINALIZE); - clientPeer.Send(msg, DeliveryMethod.Unreliable); + ClientPeer.Send(msg, DeliveryMethod.Unreliable); GUIMessageBox interruptPrompt = null; @@ -1655,7 +1508,7 @@ namespace Barotrauma.Networking { msg = new WriteOnlyMessage(); msg.WriteByte((byte)ClientPacketHeader.REQUEST_STARTGAMEFINALIZE); - clientPeer.Send(msg, DeliveryMethod.Unreliable); + ClientPeer.Send(msg, DeliveryMethod.Unreliable); requestFinalizeTime = DateTime.Now + requestFinalizeInterval; } if (DateTime.Now > timeOut && interruptPrompt == null) @@ -1669,7 +1522,7 @@ namespace Barotrauma.Networking { roundInitStatus = RoundInitStatus.Interrupted; DebugConsole.ThrowError("Error while starting the round (did not receive STARTGAMEFINALIZE message from the server). Returning to the lobby..."); - gameStarted = true; + GameStarted = true; GameMain.NetLobbyScreen.Select(); interruptPrompt.Close(); interruptPrompt = null; @@ -1762,10 +1615,10 @@ namespace Barotrauma.Networking if (respawnAllowed) { - respawnManager = new RespawnManager(this, usingShuttle && !isOutpost ? GameMain.NetLobbyScreen.SelectedShuttle : null); + RespawnManager = new RespawnManager(this, usingShuttle && !isOutpost ? GameMain.NetLobbyScreen.SelectedShuttle : null); } - gameStarted = true; + GameStarted = true; ServerSettings.ServerDetailsChanged = true; if (roundSummary != null) @@ -1797,7 +1650,7 @@ namespace Barotrauma.Networking yield return new WaitForSeconds(1.0f); } - if (!gameStarted) + if (!GameStarted) { GameMain.NetLobbyScreen.Select(); yield return CoroutineStatus.Success; @@ -1807,13 +1660,13 @@ namespace Barotrauma.Networking ServerSettings.ServerDetailsChanged = true; - gameStarted = false; + GameStarted = false; Character.Controlled = null; WaitForNextRoundRespawn = null; SpawnAsTraitor = false; GameMain.GameScreen.Cam.TargetPos = Vector2.Zero; GameMain.LightManager.LosEnabled = false; - respawnManager = null; + RespawnManager = null; if (Screen.Selected == GameMain.GameScreen) { @@ -1885,12 +1738,12 @@ namespace Barotrauma.Networking GameMain.NetLobbyScreen.UpdateSubList(GameMain.NetLobbyScreen.SubList, ServerSubmarines); GameMain.NetLobbyScreen.UpdateSubList(GameMain.NetLobbyScreen.ShuttleList.ListBox, ServerSubmarines.Where(s => s.HasTag(SubmarineTag.Shuttle))); - gameStarted = inc.ReadBoolean(); + GameStarted = inc.ReadBoolean(); bool allowSpectating = inc.ReadBoolean(); ReadPermissions(inc); - if (gameStarted) + if (GameStarted) { if (Screen.Selected != GameMain.GameScreen) { @@ -1994,15 +1847,15 @@ namespace Barotrauma.Networking } if (updateClientListId) { LastClientListUpdateID = listId; } - if (clientPeer is SteamP2POwnerPeer) + if (ClientPeer is SteamP2POwnerPeer) { TaskPool.Add("WaitForPingDataAsync (owner)", Steamworks.SteamNetworkingUtils.WaitForPingDataAsync(), (task) => { - Steam.SteamManager.UpdateLobby(serverSettings); + Steam.SteamManager.UpdateLobby(ServerSettings); }); - Steam.SteamManager.UpdateLobby(serverSettings); + Steam.SteamManager.UpdateLobby(ServerSettings); } } @@ -2083,10 +1936,10 @@ namespace Barotrauma.Networking { ReadWriteMessage settingsBuf = new ReadWriteMessage(); settingsBuf.WriteBytes(settingsData, 0, settingsLen); settingsBuf.BitPosition = 0; - serverSettings.ClientRead(settingsBuf); + ServerSettings.ClientRead(settingsBuf); if (!IsServerOwner) { - ServerInfo info = serverSettings.GetServerListInfo(); + ServerInfo info = CreateServerInfoFromSettings(); GameMain.ServerListScreen.AddToRecentServers(info); GameMain.NetLobbyScreen.Favorite.Visible = true; GameMain.NetLobbyScreen.Favorite.Selected = GameMain.ServerListScreen.IsFavorite(info); @@ -2098,10 +1951,10 @@ namespace Barotrauma.Networking GameMain.NetLobbyScreen.LastUpdateID = updateID; - serverSettings.ServerLog.ServerName = serverSettings.ServerName; + ServerSettings.ServerLog.ServerName = ServerSettings.ServerName; - if (!GameMain.NetLobbyScreen.ServerName.Selected) { GameMain.NetLobbyScreen.ServerName.Text = serverSettings.ServerName; } - if (!GameMain.NetLobbyScreen.ServerMessage.Selected) { GameMain.NetLobbyScreen.ServerMessage.Text = serverSettings.ServerMessageText; } + if (!GameMain.NetLobbyScreen.ServerName.Selected) { GameMain.NetLobbyScreen.ServerName.Text = ServerSettings.ServerName; } + if (!GameMain.NetLobbyScreen.ServerMessage.Selected) { GameMain.NetLobbyScreen.ServerMessage.Text = ServerSettings.ServerMessageText; } GameMain.NetLobbyScreen.UsingShuttle = usingShuttle; if (!allowSubVoting) { GameMain.NetLobbyScreen.TrySelectSub(selectSubName, selectSubHash, GameMain.NetLobbyScreen.SubList); } @@ -2131,13 +1984,13 @@ namespace Barotrauma.Networking GameMain.NetLobbyScreen.SetBotCount(botCount); GameMain.NetLobbyScreen.SetAutoRestart(autoRestartEnabled, autoRestartTimer); - serverSettings.VoiceChatEnabled = voiceChatEnabled; - serverSettings.AllowSubVoting = allowSubVoting; - serverSettings.AllowModeVoting = allowModeVoting; + ServerSettings.VoiceChatEnabled = voiceChatEnabled; + ServerSettings.AllowSubVoting = allowSubVoting; + ServerSettings.AllowModeVoting = allowModeVoting; - if (clientPeer is SteamP2POwnerPeer) + if (ClientPeer is SteamP2POwnerPeer) { - Steam.SteamManager.UpdateLobby(serverSettings); + Steam.SteamManager.UpdateLobby(ServerSettings); } GUI.KeyboardDispatcher.Subscriber = prevDispatcher; @@ -2252,7 +2105,7 @@ namespace Barotrauma.Networking break; case ServerNetObject.ENTITY_EVENT: case ServerNetObject.ENTITY_EVENT_INITIAL: - if (!entityEventManager.Read(objHeader.Value, inc, sendingTime, debugEntityList)) + if (!EntityEventManager.Read(objHeader.Value, inc, sendingTime, debugEntityList)) { return; } @@ -2385,20 +2238,20 @@ namespace Barotrauma.Networking DebugConsole.ThrowError($"Maximum packet size exceeded ({outmsg.LengthBytes} > {MsgConstants.MTU})"); } - clientPeer.Send(outmsg, DeliveryMethod.Unreliable); + ClientPeer.Send(outmsg, DeliveryMethod.Unreliable); } private void SendIngameUpdate() { IWriteMessage outmsg = new WriteOnlyMessage(); outmsg.WriteByte((byte)ClientPacketHeader.UPDATE_INGAME); - outmsg.WriteBoolean(entityEventManager.MidRoundSyncingDone); + outmsg.WriteBoolean(EntityEventManager.MidRoundSyncingDone); outmsg.WritePadBits(); outmsg.WriteByte((byte)ClientNetObject.SYNC_IDS); //outmsg.Write(GameMain.NetLobbyScreen.LastUpdateID); outmsg.WriteUInt16(ChatMessage.LastID); - outmsg.WriteUInt16(entityEventManager.LastReceivedID); + outmsg.WriteUInt16(EntityEventManager.LastReceivedID); outmsg.WriteUInt16(LastClientListUpdateID); if (!(GameMain.GameSession?.GameMode is MultiPlayerCampaign campaign) || campaign.LastSaveID == 0) @@ -2419,7 +2272,7 @@ namespace Barotrauma.Networking Character.Controlled?.ClientWriteInput(outmsg); GameMain.GameScreen.Cam?.ClientWrite(outmsg); - entityEventManager.Write(outmsg, clientPeer?.ServerConnection); + EntityEventManager.Write(outmsg, ClientPeer?.ServerConnection); chatMsgQueue.RemoveAll(cMsg => !NetIdUtils.IdMoreRecent(cMsg.NetStateID, lastSentChatMsgID)); for (int i = 0; i < chatMsgQueue.Count && i < ChatMessage.MaxMessagesPerPacket; i++) @@ -2439,12 +2292,12 @@ namespace Barotrauma.Networking DebugConsole.ThrowError($"Maximum packet size exceeded ({outmsg.LengthBytes} > {MsgConstants.MTU})"); } - clientPeer.Send(outmsg, DeliveryMethod.Unreliable); + ClientPeer.Send(outmsg, DeliveryMethod.Unreliable); } public void SendChatMessage(ChatMessage msg) { - if (clientPeer?.ServerConnection == null) { return; } + if (ClientPeer?.ServerConnection == null) { return; } lastQueueChatMsgID++; msg.NetStateID = lastQueueChatMsgID; chatMsgQueue.Add(msg); @@ -2452,13 +2305,13 @@ namespace Barotrauma.Networking public void SendChatMessage(string message, ChatMessageType type = ChatMessageType.Default) { - if (clientPeer?.ServerConnection == null) { return; } + if (ClientPeer?.ServerConnection == null) { return; } ChatMessage chatMessage = ChatMessage.Create( - gameStarted && myCharacter != null ? myCharacter.Name : Name, + GameStarted && myCharacter != null ? myCharacter.Name : Name, message, type, - gameStarted && myCharacter != null ? myCharacter : null); + GameStarted && myCharacter != null ? myCharacter : null); chatMessage.ChatMode = GameMain.ActiveChatMode; lastQueueChatMsgID++; @@ -2473,7 +2326,7 @@ namespace Barotrauma.Networking IWriteMessage msg = new WriteOnlyMessage(); msg.WriteByte((byte)ClientPacketHeader.READY_TO_SPAWN); msg.WriteBoolean((bool)waitForNextRoundRespawn); - clientPeer?.Send(msg, DeliveryMethod.Reliable); + ClientPeer?.Send(msg, DeliveryMethod.Reliable); } public void RequestFile(FileTransferType fileType, string file, string fileHash) @@ -2492,7 +2345,7 @@ namespace Barotrauma.Networking msg.WriteString(file ?? throw new ArgumentNullException(nameof(file))); msg.WriteString(fileHash ?? throw new ArgumentNullException(nameof(fileHash))); } - clientPeer.Send(msg, DeliveryMethod.Reliable); + ClientPeer.Send(msg, DeliveryMethod.Reliable); } public void CancelFileTransfer(FileReceiver.FileTransferIn transfer) @@ -2514,7 +2367,7 @@ namespace Barotrauma.Networking msg.WriteByte((byte)transfer.ID); msg.WriteInt32(expecting); msg.WriteInt32(lastSeen); - clientPeer.Send(msg, reliable ? DeliveryMethod.Reliable : DeliveryMethod.Unreliable); + ClientPeer.Send(msg, reliable ? DeliveryMethod.Reliable : DeliveryMethod.Unreliable); } public void CancelFileTransfer(int id) @@ -2523,7 +2376,7 @@ namespace Barotrauma.Networking msg.WriteByte((byte)ClientPacketHeader.FILE_REQUEST); msg.WriteByte((byte)FileTransferMessageType.Cancel); msg.WriteByte((byte)id); - clientPeer.Send(msg, DeliveryMethod.Reliable); + ClientPeer.Send(msg, DeliveryMethod.Reliable); } private void OnFileReceived(FileReceiver.FileTransferIn transfer) @@ -2669,7 +2522,7 @@ namespace Barotrauma.Networking { throw new InvalidCastException($"Entity is not {nameof(IClientSerializable)}"); } - entityEventManager.CreateEvent(clientSerializable, extraData); + EntityEventManager.CreateEvent(clientSerializable, extraData); } public bool HasPermission(ClientPermissions permission) @@ -2696,11 +2549,9 @@ namespace Barotrauma.Networking return false; } - public override void Quit() + public void Quit() { - allowReconnect = false; - - if (clientPeer is SteamP2PClientPeer || clientPeer is SteamP2POwnerPeer) + if (ClientPeer is SteamP2PClientPeer || ClientPeer is SteamP2POwnerPeer) { SteamManager.LeaveLobby(); } @@ -2710,20 +2561,14 @@ namespace Barotrauma.Networking CampaignMode.StartRoundCancellationToken?.Cancel(); - clientPeer?.Close(); - clientPeer = null; + ClientPeer?.Close(PeerDisconnectPacket.WithReason(DisconnectReason.Disconnected)); + ClientPeer = null; - List activeTransfers = new List(FileReceiver.ActiveTransfers); - foreach (var fileTransfer in activeTransfers) + foreach (var fileTransfer in FileReceiver.ActiveTransfers.ToArray()) { FileReceiver.StopTransfer(fileTransfer, deleteFile: true); } - if (HasPermission(ClientPermissions.ServerLog)) - { - serverSettings.ServerLog?.Save(); - } - if (ChildServerRelay.Process != null) { int checks = 0; @@ -2753,7 +2598,7 @@ namespace Barotrauma.Networking msg.WriteByte((byte)ClientPacketHeader.UPDATE_CHARACTERINFO); WriteCharacterInfo(msg, newName); msg.WriteByte((byte)ServerNetObject.END_OF_MESSAGE); - clientPeer?.Send(msg, DeliveryMethod.Reliable); + ClientPeer?.Send(msg, DeliveryMethod.Reliable); } public void WriteCharacterInfo(IWriteMessage msg, string newName = null) @@ -2788,7 +2633,7 @@ namespace Barotrauma.Networking public void Vote(VoteType voteType, object data) { - if (clientPeer == null) { return; } + if (ClientPeer == null) { return; } IWriteMessage msg = new WriteOnlyMessage(); msg.WriteByte((byte)ClientPacketHeader.UPDATE_LOBBY); @@ -2796,7 +2641,7 @@ namespace Barotrauma.Networking Voting.ClientWrite(msg, voteType, data); msg.WriteByte((byte)ServerNetObject.END_OF_MESSAGE); - clientPeer.Send(msg, DeliveryMethod.Reliable); + ClientPeer.Send(msg, DeliveryMethod.Reliable); } public void VoteForKick(Client votedClient) @@ -2852,7 +2697,7 @@ namespace Barotrauma.Networking msg.WriteString(kickedName); msg.WriteString(reason); - clientPeer.Send(msg, DeliveryMethod.Reliable); + ClientPeer.Send(msg, DeliveryMethod.Reliable); } public override void BanPlayer(string kickedName, string reason, TimeSpan? duration = null) @@ -2864,7 +2709,7 @@ namespace Barotrauma.Networking msg.WriteString(reason); msg.WriteDouble(duration.HasValue ? duration.Value.TotalSeconds : 0.0); //0 = permaban - clientPeer.Send(msg, DeliveryMethod.Reliable); + ClientPeer.Send(msg, DeliveryMethod.Reliable); } public override void UnbanPlayer(string playerName) @@ -2874,7 +2719,7 @@ namespace Barotrauma.Networking msg.WriteUInt16((UInt16)ClientPermissions.Unban); msg.WriteBoolean(true); msg.WritePadBits(); msg.WriteString(playerName); - clientPeer.Send(msg, DeliveryMethod.Reliable); + ClientPeer.Send(msg, DeliveryMethod.Reliable); } public override void UnbanPlayer(Endpoint endpoint) @@ -2884,7 +2729,7 @@ namespace Barotrauma.Networking msg.WriteUInt16((UInt16)ClientPermissions.Unban); msg.WriteBoolean(false); msg.WritePadBits(); msg.WriteString(endpoint.StringRepresentation); - clientPeer.Send(msg, DeliveryMethod.Reliable); + ClientPeer.Send(msg, DeliveryMethod.Reliable); } public void UpdateClientPermissions(Client targetClient) @@ -2893,7 +2738,7 @@ namespace Barotrauma.Networking msg.WriteByte((byte)ClientPacketHeader.SERVER_COMMAND); msg.WriteUInt16((UInt16)ClientPermissions.ManagePermissions); targetClient.WritePermissions(msg); - clientPeer.Send(msg, DeliveryMethod.Reliable); + ClientPeer.Send(msg, DeliveryMethod.Reliable); } public void SendCampaignState() @@ -2908,7 +2753,7 @@ namespace Barotrauma.Networking msg.WriteUInt16((UInt16)ClientPermissions.ManageCampaign); campaign.ClientWrite(msg); msg.WriteByte((byte)ServerNetObject.END_OF_MESSAGE); - clientPeer.Send(msg, DeliveryMethod.Reliable); + ClientPeer.Send(msg, DeliveryMethod.Reliable); } public void SendConsoleCommand(string command) @@ -2927,7 +2772,7 @@ namespace Barotrauma.Networking msg.WriteSingle(cursorWorldPos.X); msg.WriteSingle(cursorWorldPos.Y); - clientPeer.Send(msg, DeliveryMethod.Reliable); + ClientPeer.Send(msg, DeliveryMethod.Reliable); } /// @@ -2941,7 +2786,7 @@ namespace Barotrauma.Networking msg.WriteBoolean(false); //indicates round start msg.WriteBoolean(continueCampaign); - clientPeer.Send(msg, DeliveryMethod.Reliable); + ClientPeer.Send(msg, DeliveryMethod.Reliable); } /// @@ -2957,7 +2802,7 @@ namespace Barotrauma.Networking msg.WriteBoolean(isShuttle); msg.WritePadBits(); msg.WriteString(sub.MD5Hash.StringRepresentation); msg.WriteByte((byte)ServerNetObject.END_OF_MESSAGE); - clientPeer.Send(msg, DeliveryMethod.Reliable); + ClientPeer.Send(msg, DeliveryMethod.Reliable); } /// @@ -2978,7 +2823,7 @@ namespace Barotrauma.Networking msg.WriteUInt16((UInt16)modeIndex); msg.WriteByte((byte)ServerNetObject.END_OF_MESSAGE); - clientPeer.Send(msg, DeliveryMethod.Reliable); + ClientPeer.Send(msg, DeliveryMethod.Reliable); } public void SetupNewCampaign(SubmarineInfo sub, string saveName, string mapSeed, CampaignSettings settings) @@ -2998,12 +2843,12 @@ namespace Barotrauma.Networking msg.WriteString(sub.MD5Hash.StringRepresentation); msg.WriteNetSerializableStruct(settings); - clientPeer.Send(msg, DeliveryMethod.Reliable); + ClientPeer.Send(msg, DeliveryMethod.Reliable); } public void SetupLoadCampaign(string saveName) { - if (clientPeer == null) { return; } + if (ClientPeer == null) { return; } GameMain.NetLobbyScreen.CampaignSetupFrame.Visible = false; GameMain.NetLobbyScreen.CampaignFrame.Visible = false; @@ -3014,7 +2859,7 @@ namespace Barotrauma.Networking msg.WriteBoolean(false); msg.WritePadBits(); msg.WriteString(saveName); - clientPeer.Send(msg, DeliveryMethod.Reliable); + ClientPeer.Send(msg, DeliveryMethod.Reliable); } /// @@ -3028,7 +2873,7 @@ namespace Barotrauma.Networking msg.WriteBoolean(true); //indicates round end msg.WriteBoolean(save); - clientPeer.Send(msg, DeliveryMethod.Reliable); + ClientPeer.Send(msg, DeliveryMethod.Reliable); } public bool SpectateClicked(GUIButton button, object userData) @@ -3044,7 +2889,7 @@ namespace Barotrauma.Networking if (button != null) { button.Enabled = false; } if (campaign != null) { LateCampaignJoin = true; } - if (clientPeer == null) { return false; } + if (ClientPeer == null) { return false; } IWriteMessage readyToStartMsg = new WriteOnlyMessage(); readyToStartMsg.WriteByte((byte)ClientPacketHeader.RESPONSE_STARTGAME); @@ -3055,14 +2900,14 @@ namespace Barotrauma.Networking WriteCharacterInfo(readyToStartMsg); - clientPeer.Send(readyToStartMsg, DeliveryMethod.Reliable); + ClientPeer.Send(readyToStartMsg, DeliveryMethod.Reliable); return false; } public bool SetReadyToStart(GUITickBox tickBox) { - if (gameStarted) + if (GameStarted) { tickBox.Parent.Visible = false; return false; @@ -3073,9 +2918,9 @@ namespace Barotrauma.Networking public bool ToggleEndRoundVote(GUITickBox tickBox) { - if (!gameStarted) return false; + if (!GameStarted) return false; - if (!serverSettings.AllowEndVoting || !HasSpawned) + if (!ServerSettings.AllowEndVoting || !HasSpawned) { tickBox.Visible = false; return false; @@ -3176,19 +3021,19 @@ namespace Barotrauma.Networking return true; } - public virtual void AddToGUIUpdateList() + public void AddToGUIUpdateList() { if (GUI.DisableHUD || GUI.DisableUpperHUD) return; - if (gameStarted && + if (GameStarted && Screen.Selected == GameMain.GameScreen) { inGameHUD.AddToGUIUpdateList(); GameMain.NetLobbyScreen.FileTransferFrame?.AddToGUIUpdateList(); } - serverSettings.AddToGUIUpdateList(); - if (serverSettings.ServerLog.LogFrame != null) serverSettings.ServerLog.LogFrame.AddToGUIUpdateList(); + ServerSettings.AddToGUIUpdateList(); + if (ServerSettings.ServerLog.LogFrame != null) ServerSettings.ServerLog.LogFrame.AddToGUIUpdateList(); GameMain.NetLobbyScreen?.PlayerFrame?.AddToGUIUpdateList(); } @@ -3208,7 +3053,7 @@ namespace Barotrauma.Networking UpdateLogButtonVisibility(); - if (gameStarted && Screen.Selected == GameMain.GameScreen) + if (GameStarted && Screen.Selected == GameMain.GameScreen) { bool disableButtons = Character.Controlled?.SelectedItem?.GetComponent() is Controller c1 && c1.HideHUD || Character.Controlled?.SelectedSecondaryItem?.GetComponent() is Controller c2 && c2.HideHUD; @@ -3265,13 +3110,13 @@ namespace Barotrauma.Networking } } - public virtual void Draw(Microsoft.Xna.Framework.Graphics.SpriteBatch spriteBatch) + public void Draw(Microsoft.Xna.Framework.Graphics.SpriteBatch spriteBatch) { if (GUI.DisableHUD || GUI.DisableUpperHUD) return; - if (fileReceiver != null && fileReceiver.ActiveTransfers.Count > 0) + if (FileReceiver != null && FileReceiver.ActiveTransfers.Count > 0) { - var transfer = fileReceiver.ActiveTransfers.First(); + var transfer = FileReceiver.ActiveTransfers.First(); GameMain.NetLobbyScreen.FileTransferFrame.Visible = true; GameMain.NetLobbyScreen.FileTransferFrame.UserData = transfer; GameMain.NetLobbyScreen.FileTransferTitle.Text = @@ -3288,7 +3133,7 @@ namespace Barotrauma.Networking GameMain.NetLobbyScreen.FileTransferFrame.Visible = false; } - if (!gameStarted || Screen.Selected != GameMain.GameScreen) { return; } + if (!GameStarted || Screen.Selected != GameMain.GameScreen) { return; } inGameHUD.DrawManually(spriteBatch); @@ -3314,7 +3159,7 @@ namespace Barotrauma.Networking EndVoteTickBox.Text = endRoundVoteText; } - if (respawnManager != null) + if (RespawnManager != null) { LocalizedString respawnText = string.Empty; Color textColor = Color.White; @@ -3323,26 +3168,26 @@ namespace Barotrauma.Networking Character.Controlled == null && Level.Loaded?.Type != LevelData.LevelType.Outpost && (characterInfo == null || HasSpawned); - if (respawnManager.CurrentState == RespawnManager.State.Waiting) + if (RespawnManager.CurrentState == RespawnManager.State.Waiting) { - if (respawnManager.RespawnCountdownStarted) + if (RespawnManager.RespawnCountdownStarted) { - float timeLeft = (float)(respawnManager.RespawnTime - DateTime.Now).TotalSeconds; + float timeLeft = (float)(RespawnManager.RespawnTime - DateTime.Now).TotalSeconds; respawnText = TextManager.GetWithVariable( - respawnManager.UsingShuttle && !respawnManager.ForceSpawnInMainSub ? + RespawnManager.UsingShuttle && !RespawnManager.ForceSpawnInMainSub ? "RespawnShuttleDispatching" : "RespawningIn", "[time]", ToolBox.SecondsToReadableTime(timeLeft)); } - else if (respawnManager.PendingRespawnCount > 0) + else if (RespawnManager.PendingRespawnCount > 0) { respawnText = TextManager.GetWithVariables("RespawnWaitingForMoreDeadPlayers", - ("[deadplayers]", respawnManager.PendingRespawnCount.ToString()), - ("[requireddeadplayers]", respawnManager.RequiredRespawnCount.ToString())); + ("[deadplayers]", RespawnManager.PendingRespawnCount.ToString()), + ("[requireddeadplayers]", RespawnManager.RequiredRespawnCount.ToString())); } } - else if (respawnManager.CurrentState == RespawnManager.State.Transporting && - respawnManager.ReturnCountdownStarted) + else if (RespawnManager.CurrentState == RespawnManager.State.Transporting && + RespawnManager.ReturnCountdownStarted) { - float timeLeft = (float)(respawnManager.ReturnTime - DateTime.Now).TotalSeconds; + float timeLeft = (float)(RespawnManager.ReturnTime - DateTime.Now).TotalSeconds; respawnText = timeLeft <= 0.0f ? "" : TextManager.GetWithVariable("RespawnShuttleLeavingIn", "[time]", ToolBox.SecondsToReadableTime(timeLeft)); @@ -3390,7 +3235,7 @@ namespace Barotrauma.Networking }*/ } - public virtual bool SelectCrewCharacter(Character character, GUIComponent frame) + public bool SelectCrewCharacter(Character character, GUIComponent frame) { if (character == null) { return false; } @@ -3405,7 +3250,7 @@ namespace Barotrauma.Networking return true; } - public virtual bool SelectCrewClient(Client client, GUIComponent frame) + public bool SelectCrewClient(Client client, GUIComponent frame) { if (client == null || client.SessionId == SessionId) { return false; } CreateSelectionRelatedButtons(client, frame); @@ -3470,7 +3315,7 @@ namespace Barotrauma.Networking OnClicked = (btn, userdata) => { GameMain.NetLobbyScreen.KickPlayer(client); return false; } }; } - else if (serverSettings.AllowVoteKick && client.AllowKicking) + else if (ServerSettings.AllowVoteKick && client.AllowKicking) { var kickVoteButton = new GUIButton(new RectTransform(new Vector2(0.45f, 0.9f), buttonContainer.RectTransform), TextManager.Get("VoteToKick"), style: "GUIButtonSmall") @@ -3580,18 +3425,15 @@ namespace Barotrauma.Networking } break; } - clientPeer.Send(outMsg, DeliveryMethod.Reliable); + ClientPeer.Send(outMsg, DeliveryMethod.Reliable); - if (!eventErrorWritten) - { - WriteEventErrorData(error, expectedId, eventId, entityId); - eventErrorWritten = true; - } + WriteEventErrorData(error, expectedId, eventId, entityId); } private bool eventErrorWritten; private void WriteEventErrorData(ClientNetError error, UInt16 expectedID, UInt16 eventID, UInt16 entityID) { + if (eventErrorWritten) { return; } List errorLines = new List { error.ToString(), "" @@ -3681,12 +3523,14 @@ namespace Barotrauma.Networking Directory.CreateDirectory(ServerLog.SavePath); } File.WriteAllLines(filePath, errorLines); + + eventErrorWritten = true; } #if DEBUG public void ForceTimeOut() { - clientPeer?.ForceTimeOut(); + ClientPeer?.ForceTimeOut(); } #endif } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/Primitives/Peers/ClientPeer.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/Primitives/Peers/ClientPeer.cs index e2ce04903..e6b45ac85 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Networking/Primitives/Peers/ClientPeer.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/Primitives/Peers/ClientPeer.cs @@ -2,6 +2,8 @@ using Barotrauma.Steam; using System; using System.Collections.Immutable; +using System.Linq; +using Microsoft.Xna.Framework; namespace Barotrauma.Networking { @@ -10,37 +12,14 @@ namespace Barotrauma.Networking public ImmutableArray ServerContentPackages { get; set; } = ImmutableArray.Empty; - public delegate void MessageCallback(IReadMessage message); - - public delegate void DisconnectCallback(bool disableReconnect); - - public delegate void DisconnectMessageCallback(string message); - - public delegate void PasswordCallback(int salt, int retries); - - public delegate void InitializationCompleteCallback(); - - [Obsolete("TODO: delete in nr3-layer-1-2-cleanup")] - public readonly struct Callbacks + public readonly record struct Callbacks( + Callbacks.MessageCallback OnMessageReceived, + Callbacks.DisconnectCallback OnDisconnect, + Callbacks.InitializationCompleteCallback OnInitializationComplete) { - public readonly MessageCallback OnMessageReceived; - public readonly DisconnectCallback OnDisconnect; - public readonly DisconnectMessageCallback OnDisconnectMessageReceived; - public readonly PasswordCallback OnRequestPassword; - public readonly InitializationCompleteCallback OnInitializationComplete; - - public Callbacks(MessageCallback onMessageReceived, - DisconnectCallback onDisconnect, - DisconnectMessageCallback onDisconnectMessageReceived, - PasswordCallback onRequestPassword, - InitializationCompleteCallback onInitializationComplete) - { - OnMessageReceived = onMessageReceived; - OnDisconnect = onDisconnect; - OnDisconnectMessageReceived = onDisconnectMessageReceived; - OnRequestPassword = onRequestPassword; - OnInitializationComplete = onInitializationComplete; - } + public delegate void MessageCallback(IReadMessage message); + public delegate void DisconnectCallback(PeerDisconnectPacket disconnectPacket); + public delegate void InitializationCompleteCallback(); } protected readonly Callbacks callbacks; @@ -51,6 +30,8 @@ namespace Barotrauma.Networking protected readonly bool isOwner; protected readonly Option ownerKey; + protected bool isActive; + public ClientPeer(Endpoint serverEndpoint, Callbacks callbacks, Option ownerKey) { ServerEndpoint = serverEndpoint; @@ -60,7 +41,7 @@ namespace Barotrauma.Networking } public abstract void Start(); - public abstract void Close(string? msg = null, bool disableReconnect = false); + public abstract void Close(PeerDisconnectPacket peerDisconnectPacket); public abstract void Update(float deltaTime); public abstract void Send(IWriteMessage msg, DeliveryMethod deliveryMethod, bool compressPastThreshold = true); public abstract void SendPassword(string password); @@ -71,6 +52,12 @@ namespace Barotrauma.Networking public bool ContentPackageOrderReceived { get; protected set; } protected int passwordSalt; protected Steamworks.AuthTicket? steamAuthTicket; + private GUIMessageBox? passwordMsgBox; + + public bool WaitingForPassword + => isActive && initializationStep == ConnectionInitialization.Password + && passwordMsgBox != null + && GUIMessageBox.MessageBoxes.Contains(passwordMsgBox); public struct IncomingInitializationMessage { @@ -112,8 +99,9 @@ namespace Barotrauma.Networking } case ConnectionInitialization.ContentPackageOrder: { - if (initializationStep == ConnectionInitialization.SteamTicketAndVersion || - initializationStep == ConnectionInitialization.Password) + if (initializationStep + is ConnectionInitialization.SteamTicketAndVersion + or ConnectionInitialization.Password) { initializationStep = ConnectionInitialization.ContentPackageOrder; } @@ -155,10 +143,57 @@ namespace Barotrauma.Networking var passwordPacket = INetSerializableStruct.Read(inc.Message); + if (WaitingForPassword) { return; } + passwordPacket.Salt.TryUnwrap(out passwordSalt); passwordPacket.RetriesLeft.TryUnwrap(out var retries); - callbacks.OnRequestPassword.Invoke(passwordSalt, retries); + LocalizedString pwMsg = TextManager.Get("PasswordRequired"); + + passwordMsgBox = new GUIMessageBox(pwMsg, "", new LocalizedString[] { TextManager.Get("OK"), TextManager.Get("Cancel") }, + relativeSize: new Vector2(0.25f, 0.1f), minSize: new Point(400, GUI.IntScale(170))); + var passwordHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.5f), passwordMsgBox.Content.RectTransform), childAnchor: Anchor.TopCenter); + var passwordBox = new GUITextBox(new RectTransform(new Vector2(0.8f, 1f), passwordHolder.RectTransform) { MinSize = new Point(0, 20) }) + { + Censor = true + }; + + if (retries > 0) + { + var incorrectPasswordText = new GUITextBlock(new RectTransform(new Vector2(1f, 0.0f), passwordHolder.RectTransform), TextManager.Get("incorrectpassword"), GUIStyle.Red, GUIStyle.Font, textAlignment: Alignment.Center); + incorrectPasswordText.RectTransform.MinSize = new Point(0, (int)incorrectPasswordText.TextSize.Y); + passwordHolder.Recalculate(); + } + + passwordMsgBox.Content.Recalculate(); + passwordMsgBox.Content.RectTransform.MinSize = new Point(0, passwordMsgBox.Content.RectTransform.Children.Sum(c => c.Rect.Height)); + passwordMsgBox.Content.Parent.RectTransform.MinSize = new Point(0, (int)(passwordMsgBox.Content.RectTransform.MinSize.Y / passwordMsgBox.Content.RectTransform.RelativeSize.Y)); + + var okButton = passwordMsgBox.Buttons[0]; + okButton.OnClicked += (_, __) => + { + SendPassword(passwordBox.Text); + return true; + }; + okButton.OnClicked += passwordMsgBox.Close; + + var cancelButton = passwordMsgBox.Buttons[1]; + cancelButton.OnClicked = (_, __) => + { + Close(PeerDisconnectPacket.WithReason(DisconnectReason.Disconnected)); + passwordMsgBox?.Close(); passwordMsgBox = null; + + return true; + }; + + passwordBox.OnEnterPressed += (_, __) => + { + okButton.OnClicked.Invoke(okButton, okButton.UserData); + return true; + }; + + passwordBox.Select(); + break; } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/Primitives/Peers/LidgrenClientPeer.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/Primitives/Peers/LidgrenClientPeer.cs index 5cb7795d0..a95afd553 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Networking/Primitives/Peers/LidgrenClientPeer.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/Primitives/Peers/LidgrenClientPeer.cs @@ -9,7 +9,6 @@ namespace Barotrauma.Networking { internal sealed class LidgrenClientPeer : ClientPeer { - private bool isActive; private NetClient? netClient; private readonly NetPeerConfiguration netPeerConfiguration; @@ -94,7 +93,7 @@ namespace Barotrauma.Networking if (isOwner && !(ChildServerRelay.Process is { HasExited: false })) { - Close(); + Close(PeerDisconnectPacket.WithReason(DisconnectReason.ServerCrashed)); var msgBox = new GUIMessageBox(TextManager.Get("ConnectionLost"), ChildServerRelay.CrashMessage); msgBox.Buttons[0].OnClicked += (btn, obj) => { @@ -140,8 +139,10 @@ namespace Barotrauma.Networking var (_, packetHeader, initialization) = INetSerializableStruct.Read(inc); - if (packetHeader.IsConnectionInitializationStep() && initializationStep != ConnectionInitialization.Success) + if (packetHeader.IsConnectionInitializationStep()) { + if (initializationStep == ConnectionInitialization.Success) { return; } + ReadConnectionInitializationStep(new IncomingInitializationMessage { InitializationStep = initialization ?? throw new Exception("Initialization step missing"), @@ -170,8 +171,9 @@ namespace Barotrauma.Networking { case NetConnectionStatus.Disconnected: string disconnectMsg = inc.ReadString(); - Close(disconnectMsg); - callbacks.OnDisconnectMessageReceived.Invoke(disconnectMsg); + var peerDisconnectPacket = + PeerDisconnectPacket.FromLidgrenStringRepresentation(disconnectMsg); + Close(peerDisconnectPacket.Fallback(PeerDisconnectPacket.WithReason(DisconnectReason.Unknown))); break; } } @@ -198,7 +200,7 @@ namespace Barotrauma.Networking SendMsgInternal(headers, body); } - public override void Close(string? msg = null, bool disableReconnect = false) + public override void Close(PeerDisconnectPacket peerDisconnectPacket) { if (!isActive) { return; } @@ -206,13 +208,13 @@ namespace Barotrauma.Networking isActive = false; - netClient.Shutdown(msg ?? TextManager.Get("Disconnecting").Value); + netClient.Shutdown(peerDisconnectPacket.ToLidgrenStringRepresentation()); netClient = null; steamAuthTicket?.Cancel(); steamAuthTicket = null; - callbacks.OnDisconnect.Invoke(disableReconnect); + callbacks.OnDisconnect.Invoke(peerDisconnectPacket); } public override void Send(IWriteMessage msg, DeliveryMethod deliveryMethod, bool compressPastThreshold = true) diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/Primitives/Peers/SteamP2PClientPeer.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/Primitives/Peers/SteamP2PClientPeer.cs index 64c8b29b5..e817616b2 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Networking/Primitives/Peers/SteamP2PClientPeer.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/Primitives/Peers/SteamP2PClientPeer.cs @@ -10,7 +10,6 @@ namespace Barotrauma.Networking { internal sealed class SteamP2PClientPeer : ClientPeer { - private bool isActive; private readonly SteamId hostSteamId; private double timeout; private double heartbeatTimer; @@ -97,8 +96,7 @@ namespace Barotrauma.Networking if (steamId != hostSteamId.Value) { return; } - Close($"SteamP2P connection failed: {error}"); - callbacks.OnDisconnectMessageReceived.Invoke($"{DisconnectReason.SteamP2PError}/SteamP2P connection failed: {error}"); + Close(PeerDisconnectPacket.SteamP2PError(error)); } private void OnP2PData(ulong steamId, byte[] data, int dataLength) @@ -117,8 +115,10 @@ namespace Barotrauma.Networking if (!packetHeader.IsServerMessage()) { return; } - if (packetHeader.IsConnectionInitializationStep() && initialization.HasValue) + if (packetHeader.IsConnectionInitializationStep()) { + if (!initialization.HasValue) { return; } + var relayPacket = INetSerializableStruct.Read(inc); SteamManager.JoinLobby(relayPacket.LobbyID, false); @@ -127,7 +127,7 @@ namespace Barotrauma.Networking incomingInitializationMessages.Add(new IncomingInitializationMessage { InitializationStep = initialization.Value, - Message = relayPacket.Message.GetReadMessage() + Message = relayPacket.Message.GetReadMessageUncompressed() }); } } @@ -138,13 +138,12 @@ namespace Barotrauma.Networking else if (packetHeader.IsDisconnectMessage()) { PeerDisconnectPacket packet = INetSerializableStruct.Read(inc); - Close(packet.Message); - callbacks.OnDisconnectMessageReceived.Invoke(packet.Message); + Close(packet); } else { var packet = INetSerializableStruct.Read(inc); - incomingDataMessages.Add(packet.GetReadMessage()); + incomingDataMessages.Add(packet.GetReadMessage(packetHeader.IsCompressed(), ServerConnection!)); } } @@ -170,14 +169,12 @@ namespace Barotrauma.Networking { if (state.P2PSessionError != Steamworks.P2PSessionError.None) { - Close($"SteamP2P error code: {state.P2PSessionError}"); - callbacks.OnDisconnectMessageReceived.Invoke($"{DisconnectReason.SteamP2PError}/SteamP2P error code: {state.P2PSessionError}"); + Close(PeerDisconnectPacket.SteamP2PError(state.P2PSessionError)); } } else { - Close("SteamP2P connection could not be established"); - callbacks.OnDisconnectMessageReceived.Invoke(DisconnectReason.SteamP2PError.ToString()); + Close(PeerDisconnectPacket.WithReason(DisconnectReason.Timeout)); } connectionStatusTimer = 1.0f; @@ -212,8 +209,7 @@ namespace Barotrauma.Networking if (timeout < 0.0) { - Close("Timed out"); - callbacks.OnDisconnectMessageReceived.Invoke(DisconnectReason.SteamP2PTimeOut.ToString()); + Close(PeerDisconnectPacket.WithReason(DisconnectReason.SteamP2PTimeOut)); return; } @@ -221,20 +217,26 @@ namespace Barotrauma.Networking { if (incomingDataMessages.Count > 0) { - var incomingMessage = incomingDataMessages.First(); - byte incomingHeader = incomingMessage.LengthBytes > 0 ? incomingMessage.PeekByte() : (byte)0; - if (ContentPackageOrderReceived) + void initializationError(string errorMsg, string analyticsTag) { -#warning: TODO: do not allow completing initialization until content package order has been received? - string errorMsg = $"Error during connection initialization: completed initialization before receiving content package order. Incoming header: {incomingHeader}"; - GameAnalyticsManager.AddErrorEventOnce("SteamP2PClientPeer.OnInitializationComplete:ContentPackageOrderNotReceived", GameAnalyticsManager.ErrorSeverity.Error, errorMsg); + GameAnalyticsManager.AddErrorEventOnce($"SteamP2PClientPeer.OnInitializationComplete:{analyticsTag}", GameAnalyticsManager.ErrorSeverity.Error, errorMsg); DebugConsole.ThrowError(errorMsg); + Close(PeerDisconnectPacket.WithReason(DisconnectReason.Disconnected)); + } + + if (!ContentPackageOrderReceived) + { + initializationError( + errorMsg: "Error during connection initialization: completed initialization before receiving content package order.", + analyticsTag: "ContentPackageOrderNotReceived"); + return; } if (ServerContentPackages.Length == 0) { - string errorMsg = $"Error during connection initialization: list of content packages enabled on the server was empty when completing initialization. Incoming header: {incomingHeader}"; - GameAnalyticsManager.AddErrorEventOnce("SteamP2PClientPeer.OnInitializationComplete:NoContentPackages", GameAnalyticsManager.ErrorSeverity.Error, errorMsg); - DebugConsole.ThrowError(errorMsg); + initializationError( + errorMsg: "Error during connection initialization: list of content packages enabled on the server was empty when completing initialization.", + analyticsTag: "NoContentPackages"); + return; } callbacks.OnInitializationComplete.Invoke(); initializationStep = ConnectionInitialization.Success; @@ -320,7 +322,7 @@ namespace Barotrauma.Networking SendMsgInternal(headers, body); } - public override void Close(string? msg = null, bool disableReconnect = false) + public override void Close(PeerDisconnectPacket peerDisconnectPacket) { if (!isActive) { return; } @@ -334,12 +336,7 @@ namespace Barotrauma.Networking PacketHeader = PacketHeader.IsDisconnectMessage, Initialization = null }; - var body = new PeerDisconnectPacket - { - Message = msg ?? "Disconnected" - }; - - SendMsgInternal(headers, body); + SendMsgInternal(headers, peerDisconnectPacket); Thread.Sleep(100); @@ -349,7 +346,7 @@ namespace Barotrauma.Networking steamAuthTicket?.Cancel(); steamAuthTicket = null; - callbacks.OnDisconnect.Invoke(disableReconnect); + callbacks.OnDisconnect.Invoke(peerDisconnectPacket); } protected override void SendMsgInternal(PeerPacketHeaders headers, INetSerializableStruct? body) diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/Primitives/Peers/SteamP2POwnerPeer.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/Primitives/Peers/SteamP2POwnerPeer.cs index 23deeacce..440e3126e 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Networking/Primitives/Peers/SteamP2POwnerPeer.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/Primitives/Peers/SteamP2POwnerPeer.cs @@ -9,8 +9,6 @@ namespace Barotrauma.Networking { sealed class SteamP2POwnerPeer : ClientPeer { - private bool isActive; - private readonly SteamId selfSteamID; private UInt64 ownerKey64 => unchecked((UInt64)ownerKey.Fallback(0)); @@ -68,6 +66,7 @@ namespace Barotrauma.Networking : throw new InvalidOperationException("Steamworks not initialized"); } + public override void Start() { if (isActive) { return; } @@ -93,22 +92,13 @@ namespace Barotrauma.Networking private void OnAuthChange(Steamworks.SteamId steamId, Steamworks.SteamId ownerId, Steamworks.AuthResponse status) { RemotePeer? remotePeer = remotePeers.Find(p => p.SteamId.Value == steamId); - DebugConsole.Log($"{steamId} validation: {status}, {remotePeer != null}"); if (remotePeer == null) { return; } - if (remotePeer.Authenticated) - { - if (status != Steamworks.AuthResponse.OK) - { - DisconnectPeer(remotePeer, $"{DisconnectReason.SteamAuthenticationFailed}/ Steam authentication status changed: {status}"); - } - - return; - } - if (status == Steamworks.AuthResponse.OK) { + if (remotePeer.Authenticated) { return; } + SteamId ownerSteamId = new SteamId(ownerId); remotePeer.OwnerSteamId = Option.Some(ownerSteamId); remotePeer.Authenticated = true; @@ -126,7 +116,7 @@ namespace Barotrauma.Networking } else { - DisconnectPeer(remotePeer, $"{DisconnectReason.SteamAuthenticationFailed}/ Steam authentication failed: {status}"); + DisconnectPeer(remotePeer, PeerDisconnectPacket.SteamAuthError(status)); } } @@ -171,7 +161,7 @@ namespace Barotrauma.Networking Steamworks.BeginAuthResult authSessionStartState = SteamManager.StartAuthSession(ticket, steamId); if (authSessionStartState != Steamworks.BeginAuthResult.OK) { - DisconnectPeer(remotePeer, $"{DisconnectReason.SteamAuthenticationFailed}/ Steam auth session failed to start: {authSessionStartState}"); + DisconnectPeer(remotePeer, PeerDisconnectPacket.SteamAuthError(authSessionStartState)); return; } } @@ -197,9 +187,9 @@ namespace Barotrauma.Networking { if (!isActive) { return; } - if (ChildServerRelay.HasShutDown || (ChildServerRelay.Process?.HasExited ?? true)) + if (ChildServerRelay.HasShutDown || !(ChildServerRelay.Process is { HasExited: false })) { - Close(); + Close(PeerDisconnectPacket.WithReason(DisconnectReason.ServerCrashed)); var msgBox = new GUIMessageBox(TextManager.Get("ConnectionLost"), ChildServerRelay.CrashMessage); msgBox.Buttons[0].OnClicked += (btn, obj) => { @@ -279,7 +269,7 @@ namespace Barotrauma.Networking if (packetHeader.IsDisconnectMessage()) { var packet = INetSerializableStruct.Read(inc); - DisconnectPeer(peer, packet.Message); + DisconnectPeer(peer, packet); return; } @@ -366,30 +356,20 @@ namespace Barotrauma.Networking } } - private void DisconnectPeer(RemotePeer peer, string msg) + private void DisconnectPeer(RemotePeer peer, PeerDisconnectPacket peerDisconnectPacket) { - if (!string.IsNullOrWhiteSpace(msg)) - { - peer.DisconnectTime ??= Timing.TotalTime + 1.0; + peer.DisconnectTime ??= Timing.TotalTime + 1.0; - IWriteMessage outMsg = new WriteOnlyMessage(); - outMsg.WriteNetSerializableStruct(new PeerPacketHeaders - { - DeliveryMethod = DeliveryMethod.Reliable, - PacketHeader = PacketHeader.IsServerMessage | PacketHeader.IsDisconnectMessage - }); - outMsg.WriteNetSerializableStruct(new PeerDisconnectPacket - { - Message = msg - }); - - Steamworks.SteamNetworking.SendP2PPacket(peer.SteamId.Value, outMsg.Buffer, outMsg.LengthBytes, 0, Steamworks.P2PSend.Reliable); - sentBytes += outMsg.LengthBytes; - } - else + IWriteMessage outMsg = new WriteOnlyMessage(); + outMsg.WriteNetSerializableStruct(new PeerPacketHeaders { - ClosePeerSession(peer); - } + DeliveryMethod = DeliveryMethod.Reliable, + PacketHeader = PacketHeader.IsServerMessage | PacketHeader.IsDisconnectMessage + }); + outMsg.WriteNetSerializableStruct(peerDisconnectPacket); + + Steamworks.SteamNetworking.SendP2PPacket(peer.SteamId.Value, outMsg.Buffer, outMsg.LengthBytes, 0, Steamworks.P2PSend.Reliable); + sentBytes += outMsg.LengthBytes; } private void ClosePeerSession(RemotePeer peer) @@ -403,7 +383,7 @@ namespace Barotrauma.Networking //owner doesn't send passwords } - public override void Close(string? msg = null, bool disableReconnect = false) + public override void Close(PeerDisconnectPacket peerDisconnectPacket) { if (!isActive) { return; } @@ -411,7 +391,7 @@ namespace Barotrauma.Networking for (int i = remotePeers.Count - 1; i >= 0; i--) { - DisconnectPeer(remotePeers[i], msg ?? DisconnectReason.ServerShutdown.ToString()); + DisconnectPeer(remotePeers[i], peerDisconnectPacket); } Thread.Sleep(100); @@ -423,7 +403,7 @@ namespace Barotrauma.Networking ChildServerRelay.ClosePipes(); - callbacks.OnDisconnect.Invoke(disableReconnect); + callbacks.OnDisconnect.Invoke(peerDisconnectPacket); SteamManager.LeaveLobby(); Steamworks.SteamNetworking.ResetActions(); diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerInfo.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerInfo.cs deleted file mode 100644 index 93e854e66..000000000 --- a/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerInfo.cs +++ /dev/null @@ -1,517 +0,0 @@ -using Barotrauma.Steam; -using Microsoft.Xna.Framework; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using System.Xml.Linq; - -namespace Barotrauma.Networking -{ - class ServerInfo - { - public Endpoint Endpoint; - - #region TODO: genericize - public int QueryPort; - public UInt64 LobbyID; - public Steamworks.Data.NetPingLocation? PingLocation; - #endregion - - public bool OwnerVerified; - - private string serverName; - public string ServerName - { - get { return serverName; } - set - { - serverName = value; - if (serverName.Length > NetConfig.ServerNameMaxLength) { ServerName = ServerName.Substring(0, NetConfig.ServerNameMaxLength); } - } - } - - public string ServerMessage; - public bool GameStarted; - public int PlayerCount; - public int MaxPlayers; - public bool HasPassword; - - public bool PingChecked; - public int Ping = -1; - - //null value means that the value isn't known (the server may be using - //an old version of the game that didn't report these values or the FetchRules query to Steam may not have finished yet) - // TODO: death to Nullable!!!! - public SelectionMode? ModeSelectionMode; - public SelectionMode? SubSelectionMode; - public bool? AllowSpectating; - public bool? VoipEnabled; - public bool? KarmaEnabled; - public bool? FriendlyFireEnabled; - public bool? AllowRespawn; - public YesNoMaybe? TraitorsEnabled; - public Identifier GameMode; - public PlayStyle? PlayStyle; - - public bool Recent; - public bool Favorite; - - public bool? RespondedToSteamQuery = null; - - public Steamworks.Friend? SteamFriend; - public Steamworks.SteamMatchmakingPingResponse MatchmakingPingResponse; - - public string GameVersion; - public List ContentPackageNames - { - get; - private set; - } = new List(); - public List ContentPackageHashes - { - get; - private set; - } = new List(); - public List ContentPackageWorkshopIds - { - get; - private set; - } = new List(); - - public void CreatePreviewWindow(GUIFrame frame) - { - if (frame == null) { return; } - - frame.ClearChildren(); - - var title = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), frame.RectTransform), ServerName, font: GUIStyle.LargeFont) - { - ToolTip = ServerName, - CanBeFocused = false - }; - title.Text = ToolBox.LimitString(title.Text, title.Font, (int)(title.Rect.Width * 0.85f)); - - GUITickBox favoriteTickBox = new GUITickBox(new RectTransform(new Vector2(0.15f, 0.8f), title.RectTransform, Anchor.CenterRight), - "", null, "GUIServerListFavoriteTickBox") - { - Selected = Favorite, - ToolTip = TextManager.Get(Favorite ? "removefromfavorites" : "addtofavorites"), - OnSelected = (tickbox) => - { - if (tickbox.Selected) - { - GameMain.ServerListScreen.AddToFavoriteServers(this); - } - else - { - GameMain.ServerListScreen.RemoveFromFavoriteServers(this); - } - tickbox.ToolTip = TextManager.Get(tickbox.Selected ? "removefromfavorites" : "addtofavorites"); - return true; - } - }; - - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), frame.RectTransform), - TextManager.AddPunctuation(':', TextManager.Get("ServerListVersion"), - string.IsNullOrEmpty(GameVersion) ? TextManager.Get("Unknown") : GameVersion)) - { - CanBeFocused = false - }; - - bool hidePlaystyleBanner = !PlayStyle.HasValue; - if (!hidePlaystyleBanner) - { - PlayStyle playStyle = PlayStyle ?? Networking.PlayStyle.Serious; - Sprite playStyleBannerSprite = ServerListScreen.PlayStyleBanners[(int)playStyle]; - float playStyleBannerAspectRatio = playStyleBannerSprite.SourceRect.Width / playStyleBannerSprite.SourceRect.Height; - var playStyleBanner = new GUIImage(new RectTransform(new Point(frame.Rect.Width, (int)(frame.Rect.Width / playStyleBannerAspectRatio)), frame.RectTransform), - playStyleBannerSprite, null, true); - - var playStyleName = new GUITextBlock( - new RectTransform(new Vector2(0.15f, 0.0f), playStyleBanner.RectTransform) - { RelativeOffset = new Vector2(0.0f, 0.06f) }, - TextManager.AddPunctuation(':', TextManager.Get("serverplaystyle"), - TextManager.Get("servertag." + playStyle)), textColor: Color.White, - font: GUIStyle.SmallFont, textAlignment: Alignment.Center, - color: ServerListScreen.PlayStyleColors[(int)playStyle], style: "GUISlopedHeader"); - playStyleName.RectTransform.NonScaledSize = (playStyleName.Font.MeasureString(playStyleName.Text) + new Vector2(20, 5) * GUI.Scale).ToPoint(); - playStyleName.RectTransform.IsFixedSize = true; - } - - var serverType = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), frame.RectTransform), - Endpoint.ServerTypeString, - textAlignment: Alignment.TopLeft) - { - CanBeFocused = false - }; - serverType.RectTransform.MinSize = new Point(0, (int)(serverType.Rect.Height * 1.5f)); - - var content = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.6f), frame.RectTransform)) - { - Stretch = true - }; - // playstyle tags ----------------------------------------------------------------------------- - - var playStyleContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.15f), content.RectTransform), isHorizontal: true) - { - Stretch = true, - RelativeSpacing = 0.01f, - CanBeFocused = true - }; - - var playStyleTags = GetPlayStyleTags(); - foreach (string tag in playStyleTags) - { - if (!ServerListScreen.PlayStyleIcons.ContainsKey(tag)) { continue; } - - new GUIImage(new RectTransform(Vector2.One, playStyleContainer.RectTransform), - ServerListScreen.PlayStyleIcons[tag], scaleToFit: true) - { - ToolTip = TextManager.Get("servertagdescription." + tag), - Color = ServerListScreen.PlayStyleIconColors[tag] - }; - } - - playStyleContainer.Recalculate(); - - // ----------------------------------------------------------------------------- - - float elementHeight = 0.075f; - - // Spacing - new GUIFrame(new RectTransform(new Vector2(1.0f, 0.025f), content.RectTransform), style: null); - - var serverMsg = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.3f), content.RectTransform)) { ScrollBarVisible = true }; - var msgText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), serverMsg.Content.RectTransform), ServerMessage, font: GUIStyle.SmallFont, wrap: true) - { - CanBeFocused = false - }; - serverMsg.Content.RectTransform.SizeChanged += () => { msgText.CalculateHeightFromText(); }; - msgText.RectTransform.SizeChanged += () => { serverMsg.UpdateScrollBarSize(); }; - - var gameMode = new GUITextBlock(new RectTransform(new Vector2(1.0f, elementHeight), content.RectTransform), TextManager.Get("GameMode")); - new GUITextBlock(new RectTransform(Vector2.One, gameMode.RectTransform), - TextManager.Get(GameMode.IsEmpty ? "Unknown" : "GameMode." + GameMode).Fallback(GameMode.Value), - textAlignment: Alignment.Right); - - GUITextBlock playStyleText = null; - if (hidePlaystyleBanner && PlayStyle.HasValue) - { - PlayStyle playStyle = PlayStyle.Value; - playStyleText = new GUITextBlock(new RectTransform(new Vector2(1.0f, elementHeight), content.RectTransform), TextManager.Get("serverplaystyle")); - new GUITextBlock(new RectTransform(Vector2.One, playStyleText.RectTransform), TextManager.Get("servertag." + playStyle), textAlignment: Alignment.Right); - } - - var subSelection = new GUITextBlock(new RectTransform(new Vector2(1.0f, elementHeight), content.RectTransform), TextManager.Get("ServerListSubSelection")); - new GUITextBlock(new RectTransform(Vector2.One, subSelection.RectTransform), TextManager.Get(!SubSelectionMode.HasValue ? "Unknown" : SubSelectionMode.Value.ToString()), textAlignment: Alignment.Right); - - var modeSelection = new GUITextBlock(new RectTransform(new Vector2(1.0f, elementHeight), content.RectTransform), TextManager.Get("ServerListModeSelection")); - new GUITextBlock(new RectTransform(Vector2.One, modeSelection.RectTransform), TextManager.Get(!ModeSelectionMode.HasValue ? "Unknown" : ModeSelectionMode.Value.ToString()), textAlignment: Alignment.Right); - - if (gameMode.TextSize.X + gameMode.GetChild().TextSize.X > gameMode.Rect.Width || - subSelection.TextSize.X + subSelection.GetChild().TextSize.X > subSelection.Rect.Width || - modeSelection.TextSize.X + modeSelection.GetChild().TextSize.X > modeSelection.Rect.Width) - { - gameMode.Font = subSelection.Font = modeSelection.Font = GUIStyle.SmallFont; - gameMode.GetChild().Font = subSelection.GetChild().Font = modeSelection.GetChild().Font = GUIStyle.SmallFont; - if (playStyleText != null) - { - playStyleText.Font = playStyleText.GetChild().Font = GUIStyle.SmallFont; - } - } - - var allowSpectating = new GUITickBox(new RectTransform(new Vector2(1, elementHeight), content.RectTransform), TextManager.Get("ServerListAllowSpectating")) - { - CanBeFocused = false - }; - if (!AllowSpectating.HasValue) - new GUITextBlock(new RectTransform(new Vector2(0.8f, 0.8f), allowSpectating.Box.RectTransform, Anchor.Center), "?", textAlignment: Alignment.Center); - else - allowSpectating.Selected = AllowSpectating.Value; - - var allowRespawn = new GUITickBox(new RectTransform(new Vector2(1, elementHeight), content.RectTransform), TextManager.Get("ServerSettingsAllowRespawning")) - { - CanBeFocused = false - }; - if (!AllowRespawn.HasValue) - new GUITextBlock(new RectTransform(new Vector2(0.8f, 0.8f), allowRespawn.Box.RectTransform, Anchor.Center), "?", textAlignment: Alignment.Center); - else - allowRespawn.Selected = AllowRespawn.Value; - - /*var voipEnabledTickBox = new GUITickBox(new RectTransform(new Vector2(1.0f, elementHeight), bodyContainer.RectTransform), TextManager.Get("serversettingsvoicechatenabled")) - { - CanBeFocused = false - }; - if (!VoipEnabled.HasValue) - new GUITextBlock(new RectTransform(new Vector2(0.8f, 0.8f), voipEnabledTickBox.Box.RectTransform, Anchor.Center), "?", textAlignment: Alignment.Center); - else - voipEnabledTickBox.Selected = VoipEnabled.Value;*/ - - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), content.RectTransform), - TextManager.Get("ServerListContentPackages"), textAlignment: Alignment.Center, font: GUIStyle.SubHeadingFont); - - var contentPackageList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.3f), frame.RectTransform)) - { - ScrollBarVisible = true, - OnSelected = (component, o) => false - }; - if (ContentPackageNames.Count == 0) - { - new GUITextBlock(new RectTransform(Vector2.One, contentPackageList.Content.RectTransform), TextManager.Get("Unknown"), textAlignment: Alignment.Center) - { - CanBeFocused = false - }; - } - else - { - for (int i = 0; i < ContentPackageNames.Count; i++) - { - var packageText = new GUITickBox( - new RectTransform(new Vector2(1.0f, 0.15f), contentPackageList.Content.RectTransform) - { MinSize = new Point(0, 15) }, - ContentPackageNames[i]) - { - Enabled = false - }; - packageText.Box.Enabled = true; - packageText.TextBlock.Enabled = true; - if (i < ContentPackageHashes.Count) - { - if (ContentPackageManager.AllPackages.Any(contentPackage => contentPackage.Hash.StringRepresentation == ContentPackageHashes[i])) - { - packageText.TextColor = GUIStyle.Green; - packageText.Selected = true; - } - //workshop download link found - else if (i < ContentPackageWorkshopIds.Count && ContentPackageWorkshopIds[i] != 0) - { - packageText.ToolTip = TextManager.GetWithVariable("ServerListIncompatibleContentPackageWorkshopAvailable", "[contentpackage]", ContentPackageNames[i]); - } - else //no package or workshop download link found (TODO: update text to say that they could be downloaded through the server) - { - packageText.TextColor = GameMain.VanillaContent.NameMatches(ContentPackageNames[i]) ? GUIStyle.Red : GUIStyle.Yellow; - packageText.ToolTip = TextManager.GetWithVariables("ServerListIncompatibleContentPackage", - ("[contentpackage]", ContentPackageNames[i]), ("[hash]", ContentPackageHashes[i])); - } - } - } - } - - // ----------------------------------------------------------------------------- - - foreach (GUIComponent c in content.Children) - { - if (c is GUITextBlock textBlock) { textBlock.Padding = Vector4.Zero; } - } - } - - public IEnumerable GetPlayStyleTags() - { - List tags = new List(); - if (KarmaEnabled.HasValue) - { - tags.Add(KarmaEnabled.Value ? "karma.true" : "karma.false"); - } - if (TraitorsEnabled.HasValue) - { - tags.Add(TraitorsEnabled.Value == YesNoMaybe.Maybe ? - "traitors.maybe" : - (TraitorsEnabled.Value == YesNoMaybe.Yes ? "traitors.true" : "traitors.false")); - } - if (VoipEnabled.HasValue) - { - tags.Add(VoipEnabled.Value ? "voip.true" : "voip.false"); - } - if (FriendlyFireEnabled.HasValue) - { - tags.Add(FriendlyFireEnabled.Value ? "friendlyfire.true" : "friendlyfire.false"); - } - if (ContentPackageNames.Count > 0) - { - tags.Add(ContentPackageNames.Count > 1 || !GameMain.VanillaContent.NameMatches(ContentPackageNames[0]) ? "modded.true" : "modded.false"); - } - return tags; - } - - public static ServerInfo FromXElement(XElement element) - { - string endpointStr - = element.GetAttributeString("Endpoint", null) - ?? element.GetAttributeString("OwnerID", null) - ?? $"{element.GetAttributeString("IP", "")}:{element.GetAttributeInt("Port", 0)}"; - - if (!(Endpoint.Parse(endpointStr).TryUnwrap(out var endpoint))) { return null; } - - ServerInfo info = new ServerInfo - { - ServerName = element.GetAttributeString("ServerName", ""), - ServerMessage = element.GetAttributeString("ServerMessage", ""), - Endpoint = endpoint, - QueryPort = !string.IsNullOrEmpty(element.GetAttributeString("QueryPort", string.Empty)) ? element.GetAttributeInt("QueryPort", 0) : 0, - GameMode = element.GetAttributeIdentifier("GameMode", Identifier.Empty), - GameVersion = element.GetAttributeString("GameVersion", ""), - MaxPlayers = Math.Min(element.GetAttributeInt("MaxPlayers", 0), NetConfig.MaxPlayers), - HasPassword = element.GetAttributeBool("HasPassword", false), - RespondedToSteamQuery = null - }; - - if (Enum.TryParse(element.GetAttributeString("PlayStyle", ""), out PlayStyle playStyleTemp)) { info.PlayStyle = playStyleTemp; } - if (Enum.TryParse(element.GetAttributeString("TraitorsEnabled", ""), out YesNoMaybe traitorsTemp)) { info.TraitorsEnabled = traitorsTemp; } - if (Enum.TryParse(element.GetAttributeString("SubSelectionMode", ""), out SelectionMode subSelectionTemp)) { info.SubSelectionMode = subSelectionTemp; } - if (Enum.TryParse(element.GetAttributeString("ModeSelectionMode", ""), out SelectionMode modeSelectionTemp)) { info.ModeSelectionMode = modeSelectionTemp; } - if (bool.TryParse(element.GetAttributeString("VoipEnabled", ""), out bool voipTemp)) { info.VoipEnabled = voipTemp; } - if (bool.TryParse(element.GetAttributeString("KarmaEnabled", ""), out bool karmaTemp)) { info.KarmaEnabled = karmaTemp; } - if (bool.TryParse(element.GetAttributeString("FriendlyFireEnabled", ""), out bool friendlyFireTemp)) { info.FriendlyFireEnabled = friendlyFireTemp; } - - return info; - } - - public void QueryLiveInfo(Action onServerRulesReceived, Action onQueryDone) - { - if (!SteamManager.IsInitialized) { return; } - - if (QueryPort != 0 && Endpoint is LidgrenEndpoint { NetEndpoint: { Address: var ipAddress } }) - { - if (MatchmakingPingResponse is { QueryActive: true }) - { - MatchmakingPingResponse.Cancel(); - } - - MatchmakingPingResponse = new Steamworks.SteamMatchmakingPingResponse( - (server) => - { - ServerName = server.Name; - RespondedToSteamQuery = true; - PlayerCount = server.Players; - MaxPlayers = server.MaxPlayers; - HasPassword = server.Passworded; - PingChecked = true; - Ping = server.Ping; - LobbyID = 0; - TaskPool.Add("QueryServerRules (QueryLiveInfo)", server.QueryRulesAsync(), - (t) => - { - onQueryDone(this); - if (t.Status == TaskStatus.Faulted) - { - TaskPool.PrintTaskExceptions(t, "Failed to retrieve rules for " + ServerName); - return; - } - - t.TryGetResult(out Dictionary rules); - SteamManager.AssignServerRulesToServerInfo(rules, this); - - onServerRulesReceived(this); - }); - }, - () => - { - RespondedToSteamQuery = false; - }); - - MatchmakingPingResponse.HQueryPing(ipAddress, QueryPort); - } - else if (Endpoint is SteamP2PEndpoint { SteamId: var ownerId }) - { - SteamFriend ??= new Steamworks.Friend(ownerId.Value); - if (LobbyID == 0) - { - TaskPool.Add("RequestSteamP2POwnerInfo", SteamFriend?.RequestInfoAsync(), - (t) => - { - onQueryDone(this); - if ((SteamFriend?.IsPlayingThisGame ?? false) && ((SteamFriend?.GameInfo?.Lobby?.Id ?? 0) != 0)) - { - LobbyID = SteamFriend?.GameInfo?.Lobby?.Id.Value ?? 0; - Steamworks.SteamMatchmaking.OnLobbyDataChanged += UpdateInfoFromSteamworksLobby; - SteamFriend?.GameInfo?.Lobby?.Refresh(); - } - else - { - RespondedToSteamQuery = false; - } - }); - } - else - { - onQueryDone(this); - } - } - } - - private void UpdateInfoFromSteamworksLobby(Steamworks.Data.Lobby lobby) - { - if (lobby.Id != LobbyID) { return; } - Steamworks.SteamMatchmaking.OnLobbyDataChanged -= UpdateInfoFromSteamworksLobby; - if (string.IsNullOrWhiteSpace(lobby.GetData("haspassword"))) { return; } - bool.TryParse(lobby.GetData("haspassword"), out bool hasPassword); - int.TryParse(lobby.GetData("playercount"), out int currPlayers); - int.TryParse(lobby.GetData("maxplayernum"), out int maxPlayers); - - if (!SteamId.Parse(lobby.GetData("lobbyowner")).TryUnwrap(out var ownerId)) { return; } - if (!(Endpoint is SteamP2PEndpoint { SteamId: var id }) || id != ownerId) { return; } - - ServerName = lobby.GetData("name"); - PlayerCount = currPlayers; - MaxPlayers = maxPlayers; - HasPassword = hasPassword; - RespondedToSteamQuery = true; - PingChecked = false; - OwnerVerified = true; - - SteamManager.AssignLobbyDataToServerInfo(lobby, this); - } - - public XElement ToXElement() - { - if (Endpoint is null) - { - return null; //can't save this one since it's not set up correctly - } - - XElement element = new XElement("ServerInfo"); - - element.SetAttributeValue("ServerName", ServerName); - element.SetAttributeValue("ServerMessage", ServerMessage); - element.SetAttributeValue("Endpoint", Endpoint.ToString()); - - element.SetAttributeValue("GameMode", GameMode); - element.SetAttributeValue("GameVersion", GameVersion ?? ""); - element.SetAttributeValue("MaxPlayers", MaxPlayers); - if (PlayStyle.HasValue) { element.SetAttributeValue("PlayStyle", PlayStyle.Value.ToString()); } - if (TraitorsEnabled.HasValue) { element.SetAttributeValue("TraitorsEnabled", TraitorsEnabled.Value.ToString()); } - if (SubSelectionMode.HasValue) { element.SetAttributeValue("SubSelectionMode", SubSelectionMode.Value.ToString()); } - if (ModeSelectionMode.HasValue) { element.SetAttributeValue("ModeSelectionMode", ModeSelectionMode.Value.ToString()); } - if (VoipEnabled.HasValue) { element.SetAttributeValue("VoipEnabled", VoipEnabled.Value.ToString()); } - if (KarmaEnabled.HasValue) { element.SetAttributeValue("KarmaEnabled", KarmaEnabled.Value.ToString()); } - if (FriendlyFireEnabled.HasValue) { element.SetAttributeValue("FriendlyFireEnabled", FriendlyFireEnabled.Value.ToString()); } - element.SetAttributeValue("HasPassword", HasPassword.ToString()); - - return element; - } - - public override bool Equals(object obj) - { - return obj is ServerInfo other ? Equals(other) : base.Equals(obj); - } - - public bool Equals(ServerInfo other) - { - return - other.Endpoint == Endpoint && - (other.LobbyID == LobbyID || other.LobbyID == 0 || LobbyID == 0); - } - - /// - /// This class is trash, so punish its use by making it horribly inefficient in hashsets - /// Doing anything else here would make it cause even more bugs - /// - public override int GetHashCode() => 0; - - public bool MatchesByEndpoint(ServerInfo other) - { - return other.Endpoint == Endpoint; - } - } -} diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerList/FriendProviders/FriendProvider.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerList/FriendProviders/FriendProvider.cs new file mode 100644 index 000000000..1a1753091 --- /dev/null +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerList/FriendProviders/FriendProvider.cs @@ -0,0 +1,11 @@ +#nullable enable + +namespace Barotrauma +{ + abstract class FriendProvider + { + public abstract ServerListScreen.FriendInfo[] RetrieveFriends(); + public abstract void RetrieveAvatar(ServerListScreen.FriendInfo friend, ServerListScreen.AvatarSize avatarSize); + public abstract string GetUserName(); + } +} \ No newline at end of file diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerList/FriendProviders/SteamFriendProvider.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerList/FriendProviders/SteamFriendProvider.cs new file mode 100644 index 000000000..9026de250 --- /dev/null +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerList/FriendProviders/SteamFriendProvider.cs @@ -0,0 +1,67 @@ +#nullable enable +using System; +using System.Linq; +using System.Threading.Tasks; +using Barotrauma.Networking; +using Barotrauma.Steam; +using Microsoft.Xna.Framework.Graphics; + +namespace Barotrauma +{ + class SteamFriendProvider : FriendProvider + { + private static ServerListScreen.FriendInfo FromSteamFriend(Steamworks.Friend steamFriend) + => new ServerListScreen.FriendInfo( + steamFriend.Name, + new SteamId(steamFriend.Id), + steamFriend.State switch + { + Steamworks.FriendState.Offline => ServerListScreen.FriendInfo.Status.Offline, + Steamworks.FriendState.Invisible => ServerListScreen.FriendInfo.Status.Offline, + _ when steamFriend.IsPlayingThisGame => ServerListScreen.FriendInfo.Status.PlayingBarotrauma, + _ when steamFriend.GameInfo is { GameID: var gameId } && gameId > 0 => ServerListScreen.FriendInfo.Status.PlayingAnotherGame, + _ => ServerListScreen.FriendInfo.Status.NotPlaying + }) + { + ServerName = steamFriend.GetRichPresence("servername"), + ConnectCommand = steamFriend.GetRichPresence("connect") is { } connectCmd + ? ToolBox.ParseConnectCommand(ToolBox.SplitCommand(connectCmd)) + : Option.None() + }; + + public override ServerListScreen.FriendInfo[] RetrieveFriends() + => SteamManager.IsInitialized + ? Steamworks.SteamFriends.GetFriends().Select(FromSteamFriend).ToArray() + : Array.Empty(); + + public override void RetrieveAvatar(ServerListScreen.FriendInfo friend, ServerListScreen.AvatarSize avatarSize) + { + if (!(friend.Id is SteamId steamId)) { return; } + + Func> avatarFunc = avatarSize switch + { + ServerListScreen.AvatarSize.Small => Steamworks.SteamFriends.GetSmallAvatarAsync, + ServerListScreen.AvatarSize.Medium => Steamworks.SteamFriends.GetMediumAvatarAsync, + ServerListScreen.AvatarSize.Large => Steamworks.SteamFriends.GetLargeAvatarAsync, + }; + TaskPool.Add($"Get{avatarSize}AvatarAsync", avatarFunc(steamId.Value), task => + { + if (!task.TryGetResult(out Steamworks.Data.Image? img)) { return; } + if (!(img is { } avatarImage)) { return; } + + if (friend.Avatar.TryUnwrap(out var prevAvatar)) + { + prevAvatar.Remove(); + } + + #warning TODO: create an avatar atlas? + var avatarTexture = new Texture2D(GameMain.Instance.GraphicsDevice, (int)avatarImage.Width, (int)avatarImage.Height); + avatarTexture.SetData(avatarImage.Data); + friend.Avatar = Option.Some(new Sprite(avatarTexture, null, null)); + }); + } + + public override string GetUserName() + => SteamManager.GetUsername(); + } +} \ No newline at end of file diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerList/PingUtils.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerList/PingUtils.cs new file mode 100644 index 000000000..4f099bf4e --- /dev/null +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerList/PingUtils.cs @@ -0,0 +1,196 @@ +using Barotrauma.Steam; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Net.NetworkInformation; +using System.Net.Sockets; +using System.Threading.Tasks; +using Steamworks.Data; +using Color = Microsoft.Xna.Framework.Color; +using Socket = System.Net.Sockets.Socket; + +namespace Barotrauma.Networking +{ + static class PingUtils + { + private static readonly Dictionary activePings = new Dictionary(); + + private static bool steamPingInfoReady; + + public static void QueryPingData() + { + steamPingInfoReady = false; + if (SteamManager.IsInitialized) + { + TaskPool.Add("WaitForPingDataAsync (serverlist)", Steamworks.SteamNetworkingUtils.WaitForPingDataAsync(), task => + { + steamPingInfoReady = true; + }); + } + } + + public static void GetServerPing(ServerInfo serverInfo, Action onPingDiscovered) + { + if (CoroutineManager.IsCoroutineRunning("ConnectToServer")) { return; } + + switch (serverInfo.Endpoint) + { + case LidgrenEndpoint { NetEndpoint: { Address: var address } }: + GetIPAddressPing(serverInfo, address, onPingDiscovered); + break; + case SteamP2PEndpoint steamP2PEndpoint: + TaskPool.Add($"EstimateSteamLobbyPing ({steamP2PEndpoint.StringRepresentation})", + EstimateSteamLobbyPing(serverInfo), + t => + { + if (!t.TryGetResult(out Option ping)) { return; } + serverInfo.Ping = ping; + onPingDiscovered(serverInfo); + }); + break; + } + } + + private readonly ref struct LobbyDataChangedEventHandler + { + private readonly Action action; + + public LobbyDataChangedEventHandler(Action action) + { + this.action = action; + Steamworks.SteamMatchmaking.OnLobbyDataChanged += action; + } + + public void Dispose() + { + Steamworks.SteamMatchmaking.OnLobbyDataChanged -= action; + } + } + + public static async Task GetSteamLobbyForUser(SteamId steamId) + { + var steamFriend = new Steamworks.Friend(steamId.Value); + await steamFriend.RequestInfoAsync(); + + var friendLobby = steamFriend.GameInfo?.Lobby; + if (!(friendLobby is { } lobby)) { return null; } + + bool waiting = true; + Lobby loadedLobby = default; + + void finishWaiting(Steamworks.Data.Lobby l) + { + loadedLobby = l; + waiting = false; + } + + using (new LobbyDataChangedEventHandler(finishWaiting)) + { + lobby.Refresh(); + + for (int i = 0;; i++) + { + if (!waiting) { break; } + if (i >= 100) { return null; } + } + } + + return loadedLobby; + } + + private static async Task> EstimateSteamLobbyPing(ServerInfo serverInfo) + { + if (!(serverInfo.Endpoint is SteamP2PEndpoint { SteamId: var ownerId })) { return Option.None(); } + while (!steamPingInfoReady) { await Task.Delay(50); } + + Lobby lobby; + + if (serverInfo.MetadataSource.TryUnwrap(out SteamP2PServerProvider.DataSource src)) + { + lobby = src.Lobby; + } + else + { + var friendLobby = await GetSteamLobbyForUser(ownerId); + if (friendLobby is null) { return Option.None(); } + lobby = friendLobby.Value; + } + + var pingLocation = NetPingLocation.TryParseFromString(lobby.GetData("pinglocation")); + + if (pingLocation.HasValue && Steamworks.SteamNetworkingUtils.LocalPingLocation.HasValue) + { + int ping = Steamworks.SteamNetworkingUtils.LocalPingLocation.Value.EstimatePingTo(pingLocation.Value); + return ping >= 0 ? Option.Some(ping) : Option.None(); + } + else + { + return Option.None(); + } + } + + private static void GetIPAddressPing(ServerInfo serverInfo, IPAddress address, Action onPingDiscovered) + { + lock (activePings) + { + if (activePings.ContainsKey(address)) { return; } + activePings.Add(address, activePings.Any() ? activePings.Values.Max() + 1 : 0); + } + + serverInfo.Ping = Option.None(); + + TaskPool.Add($"PingServerAsync ({address})", PingServerAsync(address, 1000), + rtt => + { + if (!rtt.TryGetResult(out serverInfo.Ping)) { serverInfo.Ping = Option.None(); } + onPingDiscovered(serverInfo); + lock (activePings) + { + activePings.Remove(address); + } + }); + } + + private static async Task> PingServerAsync(IPAddress ipAddress, int timeOut) + { + await Task.Yield(); + bool shouldGo = false; + while (!shouldGo) + { + lock (activePings) + { + shouldGo = activePings.Count(kvp => kvp.Value < activePings[ipAddress]) < 25; + } + await Task.Delay(25); + } + + if (ipAddress == null) { return Option.None(); } + + //don't attempt to ping if the address is IPv6 and it's not supported + if (ipAddress.AddressFamily == AddressFamily.InterNetworkV6 && !Socket.OSSupportsIPv6) { return Option.None(); } + + Ping ping = new Ping(); + byte[] buffer = new byte[32]; + try + { + PingReply pingReply = await ping.SendPingAsync(ipAddress, timeOut, buffer, new PingOptions(128, true)); + + return pingReply.Status switch + { + IPStatus.Success => Option.Some((int)pingReply.RoundtripTime), + _ => Option.None(), + }; + } + catch (Exception ex) + { + GameAnalyticsManager.AddErrorEventOnce("ServerListScreen.PingServer:PingException" + ipAddress, GameAnalyticsManager.ErrorSeverity.Warning, "Failed to ping a server - " + (ex?.InnerException?.Message ?? ex.Message)); +#if DEBUG + DebugConsole.NewMessage("Failed to ping a server (" + ipAddress + ") - " + (ex?.InnerException?.Message ?? ex.Message), Color.Red); +#endif + + return Option.None(); + } + } + } +} diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerList/ServerInfo.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerList/ServerInfo.cs new file mode 100644 index 000000000..8b1e9e2d3 --- /dev/null +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerList/ServerInfo.cs @@ -0,0 +1,509 @@ +#nullable enable + +using Microsoft.Xna.Framework; +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using System.Reflection; +using System.Xml.Linq; +using Barotrauma.Steam; + +namespace Barotrauma.Networking +{ + sealed class ServerInfo : ISerializableEntity + { + public abstract class DataSource + { + public static Option Parse(XElement element) + => ReflectionUtils.ParseDerived(element); + public abstract void Write(XElement element); + } + + public Endpoint Endpoint { get; private set; } + + public Option MetadataSource = Option.None(); + + [Serialize("", IsPropertySaveable.Yes)] + public string ServerName { get; set; } = ""; + + [Serialize("", IsPropertySaveable.Yes)] + public string ServerMessage { get; set; } = ""; + + public int PlayerCount { get; set; } + + [Serialize(0, IsPropertySaveable.Yes)] + public int MaxPlayers { get; set; } + + public bool GameStarted { get; set; } + + [Serialize(false, IsPropertySaveable.Yes)] + public bool HasPassword { get; set; } + + [Serialize("", IsPropertySaveable.Yes)] + public Identifier GameMode { get; set; } + + [Serialize(SelectionMode.Manual, IsPropertySaveable.Yes)] + public SelectionMode ModeSelectionMode { get; set; } + + [Serialize(SelectionMode.Manual, IsPropertySaveable.Yes)] + public SelectionMode SubSelectionMode { get; set; } + + [Serialize(false, IsPropertySaveable.Yes)] + public bool AllowSpectating { get; set; } + + [Serialize(false, IsPropertySaveable.Yes)] + public bool VoipEnabled { get; set; } + + [Serialize(false, IsPropertySaveable.Yes)] + public bool KarmaEnabled { get; set; } + + [Serialize(false, IsPropertySaveable.Yes)] + public bool FriendlyFireEnabled { get; set; } + + [Serialize(false, IsPropertySaveable.Yes)] + public bool AllowRespawn { get; set; } + + [Serialize(YesNoMaybe.No, IsPropertySaveable.Yes)] + public YesNoMaybe TraitorsEnabled { get; set; } + + [Serialize(PlayStyle.Casual, IsPropertySaveable.Yes)] + public PlayStyle PlayStyle { get; set; } + + public Version GameVersion { get; set; } = new Version(0,0,0,0); + + public Option Ping = Option.None(); + + public bool Checked = false; + + public readonly struct ContentPackageInfo + { + public readonly string Name; + public readonly string Hash; + public readonly Option Id; + + public ContentPackageInfo(string name, string hash, Option id) + { + Name = name; + Hash = hash; + Id = id; + } + + public ContentPackageInfo(ContentPackage pkg) + { + Name = pkg.Name; + Hash = pkg.Hash.StringRepresentation; + Id = pkg.UgcId; + } + } + + public ImmutableArray ContentPackages; + + public bool IsModded => ContentPackages.Any(p => !GameMain.VanillaContent.NameMatches(p.Name)); + + public ServerInfo(Endpoint endpoint) + { + SerializableProperties = SerializableProperty.GetProperties(this); + Endpoint = endpoint; + ContentPackages = ImmutableArray.Empty; + } + + public static ServerInfo FromServerConnection(NetworkConnection connection, ServerSettings serverSettings) + { + var serverInfo = new ServerInfo(connection.Endpoint) + { + GameMode = GameMain.NetLobbyScreen.SelectedMode?.Identifier ?? Identifier.Empty, + GameStarted = Screen.Selected != GameMain.NetLobbyScreen, + GameVersion = GameMain.Version, + PlayerCount = GameMain.Client.ConnectedClients.Count, + ContentPackages = ContentPackageManager.EnabledPackages.All.Select(p => new ContentPackageInfo(p)).ToImmutableArray(), + Ping = GameMain.Client.Ping, + + // ------------------------------------- + // Settings that cannot be copied via + // SerializableProperty because they do + // not implement the attribute + ServerName = serverSettings.ServerName, + ServerMessage = serverSettings.ServerMessageText, + // ------------------------------------- + // Settings that cannot be copied via + // SerializableProperty due to name mismatch + HasPassword = serverSettings.HasPassword, + VoipEnabled = serverSettings.VoiceChatEnabled, + FriendlyFireEnabled = serverSettings.AllowFriendlyFire, + // ------------------------------------- + + Checked = true + }; + + var serverInfoSerializableProperties + = SerializableProperty.GetProperties(serverInfo); + var serverSettingsSerializableProperties + = SerializableProperty.GetProperties(serverSettings); + + var intersection = serverInfoSerializableProperties.Keys + .Where(serverSettingsSerializableProperties.ContainsKey); + + foreach (var key in intersection) + { + var propToGet = serverSettingsSerializableProperties[key]; + var propToSet = serverInfoSerializableProperties[key]; + if (!propToGet.PropertyInfo.CanRead) { continue; } + if (!propToSet.PropertyInfo.CanWrite) { continue; } + propToSet.SetValue( + serverInfo, + propToGet.GetValue(serverSettings)); + } + + return serverInfo; + } + + public void CreatePreviewWindow(GUIFrame frame) + { + frame.ClearChildren(); + + var serverListScreen = GameMain.ServerListScreen; + + var title = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), frame.RectTransform), ServerName, font: GUIStyle.LargeFont) + { + ToolTip = ServerName, + CanBeFocused = false + }; + title.Text = ToolBox.LimitString(title.Text, title.Font, (int)(title.Rect.Width * 0.85f)); + + bool isFavorite = serverListScreen.IsFavorite(this); + + static LocalizedString favoriteTickBoxToolTip(bool isFavorite) + => TextManager.Get(isFavorite ? "RemoveFromFavorites" : "AddToFavorites"); + + GUITickBox favoriteTickBox = new GUITickBox(new RectTransform(new Vector2(0.15f, 0.8f), title.RectTransform, Anchor.CenterRight), + "", null, "GUIServerListFavoriteTickBox") + { + UserData = this, + Selected = isFavorite, + ToolTip = favoriteTickBoxToolTip(isFavorite), + OnSelected = tickbox => + { + ServerInfo info = (ServerInfo)tickbox.UserData; + if (tickbox.Selected) + { + GameMain.ServerListScreen.AddToFavoriteServers(info); + } + else + { + GameMain.ServerListScreen.RemoveFromFavoriteServers(info); + } + tickbox.ToolTip = favoriteTickBoxToolTip(tickbox.Selected); + return true; + } + }; + + new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), frame.RectTransform), + TextManager.AddPunctuation(':', TextManager.Get("ServerListVersion"), + GameVersion.ToString())) + { + CanBeFocused = false + }; + + PlayStyle playStyle = PlayStyle; + Sprite? playStyleBannerSprite = GUIStyle.GetComponentStyle($"PlayStyleBanner.{playStyle}")?.GetSprite(GUIComponent.ComponentState.None); + + GUIComponent playStyleBanner; + Color playStyleBannerColor; + if (playStyleBannerSprite != null) + { + float playStyleBannerAspectRatio = (float)playStyleBannerSprite.SourceRect.Width / (float)playStyleBannerSprite.SourceRect.Height; + playStyleBanner = new GUIImage(new RectTransform(new Vector2(1.0f, 1.0f / playStyleBannerAspectRatio), frame.RectTransform, scaleBasis: ScaleBasis.BothWidth), + playStyleBannerSprite, null, true); + playStyleBannerColor = playStyleBannerSprite.SourceElement.GetAttributeColor("bannercolor", Color.Black); + } + else + { + playStyleBanner = new GUIFrame(new RectTransform((1.0f, 0.2f), frame.RectTransform), style: null) + { + Color = Color.Black, + DisabledColor = Color.Black, + OutlineColor = Color.Black, + PressedColor = Color.Black, + SelectedColor = Color.Black, + HoverColor = Color.Black + }; + playStyleBannerColor = Color.Black; + } + + var playStyleName = new GUITextBlock( + new RectTransform(new Vector2(0.15f, 0.0f), playStyleBanner.RectTransform) + { RelativeOffset = new Vector2(0.0f, 0.06f) }, + TextManager.AddPunctuation(':', TextManager.Get("serverplaystyle"), + TextManager.Get($"servertag.{playStyle}")), textColor: Color.White, + font: GUIStyle.SmallFont, textAlignment: Alignment.Center, + color: playStyleBannerColor, style: "GUISlopedHeader"); + playStyleName.RectTransform.NonScaledSize = (playStyleName.Font.MeasureString(playStyleName.Text) + new Vector2(20, 5) * GUI.Scale).ToPoint(); + playStyleName.RectTransform.IsFixedSize = true; + + var serverType = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), frame.RectTransform), + Endpoint?.ServerTypeString ?? string.Empty, + textAlignment: Alignment.TopLeft) + { + CanBeFocused = false + }; + serverType.RectTransform.MinSize = new Point(0, (int)(serverType.Rect.Height * 1.5f)); + + var content = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.6f), frame.RectTransform)) + { + Stretch = true + }; + // playstyle tags ----------------------------------------------------------------------------- + + var playStyleContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.15f), content.RectTransform), isHorizontal: true) + { + Stretch = true, + RelativeSpacing = 0.01f, + CanBeFocused = true + }; + + var playStyleTags = GetPlayStyleTags(); + foreach (var tag in playStyleTags) + { + var playStyleIcon = GUIStyle.GetComponentStyle($"PlayStyleIcon.{tag}") + ?.GetSprite(GUIComponent.ComponentState.None); + if (playStyleIcon is null) { continue; } + + new GUIImage(new RectTransform(Vector2.One, playStyleContainer.RectTransform), + playStyleIcon, scaleToFit: true) + { + ToolTip = TextManager.Get($"servertagdescription.{tag}"), + Color = Color.White + }; + } + + playStyleContainer.Recalculate(); + + // ----------------------------------------------------------------------------- + + float elementHeight = 0.075f; + + // Spacing + new GUIFrame(new RectTransform(new Vector2(1.0f, 0.025f), content.RectTransform), style: null); + + var serverMsg = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.3f), content.RectTransform)) { ScrollBarVisible = true }; + var msgText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), serverMsg.Content.RectTransform), ServerMessage ?? string.Empty, font: GUIStyle.SmallFont, wrap: true) + { + CanBeFocused = false + }; + serverMsg.Content.RectTransform.SizeChanged += () => { msgText.CalculateHeightFromText(); }; + msgText.RectTransform.SizeChanged += () => { serverMsg.UpdateScrollBarSize(); }; + + var gameMode = new GUITextBlock(new RectTransform(new Vector2(1.0f, elementHeight), content.RectTransform), TextManager.Get("GameMode")); + new GUITextBlock(new RectTransform(Vector2.One, gameMode.RectTransform), + TextManager.Get(GameMode.IsEmpty ? "Unknown" : "GameMode." + GameMode).Fallback(GameMode.Value), + textAlignment: Alignment.Right); + + GUITextBlock playStyleText = new GUITextBlock(new RectTransform(new Vector2(1.0f, elementHeight), content.RectTransform), TextManager.Get("serverplaystyle")); + new GUITextBlock(new RectTransform(Vector2.One, playStyleText.RectTransform), TextManager.Get("servertag." + playStyle), textAlignment: Alignment.Right); + + var subSelection = new GUITextBlock(new RectTransform(new Vector2(1.0f, elementHeight), content.RectTransform), TextManager.Get("ServerListSubSelection")); + new GUITextBlock(new RectTransform(Vector2.One, subSelection.RectTransform), TextManager.Get(SubSelectionMode.ToString()), textAlignment: Alignment.Right); + + var modeSelection = new GUITextBlock(new RectTransform(new Vector2(1.0f, elementHeight), content.RectTransform), TextManager.Get("ServerListModeSelection")); + new GUITextBlock(new RectTransform(Vector2.One, modeSelection.RectTransform), TextManager.Get(ModeSelectionMode.ToString()), textAlignment: Alignment.Right); + + if (gameMode.TextSize.X + gameMode.GetChild().TextSize.X > gameMode.Rect.Width || + subSelection.TextSize.X + subSelection.GetChild().TextSize.X > subSelection.Rect.Width || + modeSelection.TextSize.X + modeSelection.GetChild().TextSize.X > modeSelection.Rect.Width) + { + gameMode.Font = subSelection.Font = modeSelection.Font = GUIStyle.SmallFont; + gameMode.GetChild().Font = subSelection.GetChild().Font = modeSelection.GetChild().Font = GUIStyle.SmallFont; + playStyleText.Font = playStyleText.GetChild().Font = GUIStyle.SmallFont; + } + + var allowSpectating = new GUITickBox(new RectTransform(new Vector2(1, elementHeight), content.RectTransform), TextManager.Get("ServerListAllowSpectating")) + { + CanBeFocused = false + }; + allowSpectating.Selected = AllowSpectating; + + var allowRespawn = new GUITickBox(new RectTransform(new Vector2(1, elementHeight), content.RectTransform), TextManager.Get("ServerSettingsAllowRespawning")) + { + CanBeFocused = false + }; + allowRespawn.Selected = AllowRespawn; + + new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), content.RectTransform), + TextManager.Get("ServerListContentPackages"), textAlignment: Alignment.Center, font: GUIStyle.SubHeadingFont); + + var contentPackageList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.3f), frame.RectTransform)) + { + ScrollBarVisible = true, + OnSelected = (component, o) => false + }; + if (ContentPackages.Length == 0) + { + new GUITextBlock(new RectTransform(Vector2.One, contentPackageList.Content.RectTransform), TextManager.Get("Unknown"), textAlignment: Alignment.Center) + { + CanBeFocused = false + }; + } + else + { + foreach (var package in ContentPackages) + { + var packageText = new GUITickBox( + new RectTransform(new Vector2(1.0f, 0.15f), contentPackageList.Content.RectTransform) + { MinSize = new Point(0, 15) }, + package.Name) + { + CanBeFocused = false + }; + if (!string.IsNullOrEmpty(package.Hash)) + { + if (ContentPackageManager.AllPackages.Any(contentPackage => contentPackage.Hash.StringRepresentation == package.Hash)) + { + packageText.TextColor = GUIStyle.Green; + packageText.Selected = true; + } + //workshop download link found + else if (package.Id is Some { Value: var ugcId } && ugcId is SteamWorkshopId) + { + packageText.ToolTip = TextManager.GetWithVariable("ServerListIncompatibleContentPackageWorkshopAvailable", "[contentpackage]", package.Name); + } + else //no package or workshop download link found + { + packageText.TextColor = GameMain.VanillaContent.NameMatches(package.Name) ? GUIStyle.Red : GUIStyle.Yellow; + packageText.ToolTip = TextManager.GetWithVariables("ServerListIncompatibleContentPackage", + ("[contentpackage]", package.Name), ("[hash]", package.Hash)); + } + } + } + } + + // ----------------------------------------------------------------------------- + + foreach (GUIComponent c in content.Children) + { + if (c is GUITextBlock textBlock) { textBlock.Padding = Vector4.Zero; } + } + } + + public IEnumerable GetPlayStyleTags() + { + yield return $"Karma.{KarmaEnabled}".ToIdentifier(); + yield return (TraitorsEnabled == YesNoMaybe.Yes ? $"Traitors.True" : $"Traitors.False").ToIdentifier(); + yield return $"VoIP.{VoipEnabled}".ToIdentifier(); + yield return $"FriendlyFire.{FriendlyFireEnabled}".ToIdentifier(); + yield return $"Modded.{ContentPackages.Any()}".ToIdentifier(); + } + + public void UpdateInfo(Func valueGetter) + { + ServerMessage = valueGetter("message") ?? ""; + GameVersion = Version.TryParse(valueGetter("version"), out var version) + ? version + : GameMain.Version; + + if (int.TryParse(valueGetter("playercount"), out int playerCount)) { PlayerCount = playerCount; } + if (int.TryParse(valueGetter("maxplayernum"), out int maxPlayers)) { MaxPlayers = maxPlayers; } + if (Enum.TryParse(valueGetter("modeselectionmode"), out SelectionMode modeSelectionMode)) { ModeSelectionMode = modeSelectionMode; } + if (Enum.TryParse(valueGetter("subselectionmode"), out SelectionMode subSelectionMode)) { SubSelectionMode = subSelectionMode; } + + HasPassword = getBool("haspassword"); + GameStarted = getBool("gamestarted"); + KarmaEnabled = getBool("karmaenabled"); + FriendlyFireEnabled = getBool("friendlyfireenabled"); + AllowSpectating = getBool("allowspectating"); + AllowRespawn = getBool("allowrespawn"); + VoipEnabled = getBool("voicechatenabled"); + + GameMode = valueGetter("gamemode")?.ToIdentifier() ?? Identifier.Empty; + if (Enum.TryParse(valueGetter("traitors"), out YesNoMaybe traitorsEnabled)) { TraitorsEnabled = traitorsEnabled; } + if (Enum.TryParse(valueGetter("playstyle"), out PlayStyle playStyle)) { PlayStyle = playStyle; } + + ContentPackages = ExtractContentPackageInfo(valueGetter).ToImmutableArray(); + + bool getBool(string key) + { + string? data = valueGetter(key); + return bool.TryParse(data, out var result) && result; + } + } + + private static ContentPackageInfo[] ExtractContentPackageInfo(Func valueGetter) + { + string? joinedNames = valueGetter("contentpackage"); + string? joinedHashes = valueGetter("contentpackagehash"); + string? joinedWorkshopIds = valueGetter("contentpackageid"); + + string[] contentPackageNames = joinedNames.IsNullOrEmpty() ? Array.Empty() : joinedNames.Split(','); + string[] contentPackageHashes = joinedHashes.IsNullOrEmpty() ? Array.Empty() : joinedHashes.Split(','); + #warning TODO: genericize + ulong[] contentPackageIds = joinedWorkshopIds.IsNullOrEmpty() ? new ulong[1] : SteamManager.ParseWorkshopIds(joinedWorkshopIds).ToArray(); + + if (contentPackageNames.Length != contentPackageHashes.Length + || contentPackageHashes.Length != contentPackageIds.Length) + { + return Array.Empty(); + } + + return contentPackageNames + .Zip(contentPackageHashes, (name, hash) => (name, hash)) + .Zip(contentPackageIds, (t1, id) => + new ContentPackageInfo( + t1.name, + t1.hash, + Option.Some(new SteamWorkshopId(id)))) + .ToArray(); + } + + public static Option FromXElement(XElement element) + { + string endpointStr + = element.GetAttributeString("Endpoint", null) + ?? element.GetAttributeString("OwnerID", null) + ?? $"{element.GetAttributeString("IP", "")}:{element.GetAttributeInt("Port", 0)}"; + + if (!Endpoint.Parse(endpointStr).TryUnwrap(out var endpoint)) { return Option.None(); } + + var gameVersionStr = element.GetAttributeString("GameVersion", ""); + if (!Version.TryParse(gameVersionStr, out var gameVersion)) { gameVersion = GameMain.Version; } + var info = new ServerInfo(endpoint) + { + GameVersion = gameVersion + }; + SerializableProperty.DeserializeProperties(info, element); + + info.MetadataSource = DataSource.Parse(element); + + return Option.Some(info); + } + + public XElement ToXElement() + { + XElement element = new XElement(GetType().Name); + + element.SetAttributeValue("Endpoint", Endpoint.ToString()); + element.SetAttributeValue("GameVersion", GameVersion.ToString()); + + SerializableProperty.SerializeProperties(this, element, saveIfDefault: true); + + if (MetadataSource.TryUnwrap(out var dataSource)) + { + dataSource.Write(element); + } + + return element; + } + + public override bool Equals(object? obj) + { + return obj is ServerInfo other && Equals(other); + } + + public bool Equals(ServerInfo other) + => other.Endpoint == Endpoint; + + public override int GetHashCode() => Endpoint.GetHashCode(); + + string ISerializableEntity.Name => "ServerInfo"; + public Dictionary SerializableProperties { get; } + } +} diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerList/ServerProviders/CompositeServerProvider.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerList/ServerProviders/CompositeServerProvider.cs new file mode 100644 index 000000000..205d4f034 --- /dev/null +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerList/ServerProviders/CompositeServerProvider.cs @@ -0,0 +1,35 @@ +#nullable enable +using System; +using System.Collections.Immutable; +using Barotrauma.Extensions; +using Barotrauma.Networking; + +namespace Barotrauma +{ + class CompositeServerProvider : ServerProvider + { + private readonly ImmutableArray providers; + + public CompositeServerProvider(params ServerProvider[] providers) + { + this.providers = providers.ToImmutableArray(); + } + + protected override void RetrieveServersImpl(Action onServerDataReceived, Action onQueryCompleted) + { + int providersFinished = 0; + void ackFinishedProvider() + { + providersFinished++; + if (providersFinished == providers.Length) + { + onQueryCompleted(); + } + } + providers.ForEach(p => p.RetrieveServers(onServerDataReceived, ackFinishedProvider)); + } + + public override void Cancel() + => providers.ForEach(p => p.Cancel()); + } +} \ No newline at end of file diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerList/ServerProviders/ServerProvider.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerList/ServerProviders/ServerProvider.cs new file mode 100644 index 000000000..8664c58ed --- /dev/null +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerList/ServerProviders/ServerProvider.cs @@ -0,0 +1,17 @@ +#nullable enable +using System; +using Barotrauma.Networking; + +namespace Barotrauma +{ + abstract class ServerProvider + { + public void RetrieveServers(Action onServerDataReceived, Action onQueryCompleted) + { + Cancel(); + RetrieveServersImpl(onServerDataReceived, onQueryCompleted); + } + protected abstract void RetrieveServersImpl(Action onServerDataReceived, Action onQueryCompleted); + public abstract void Cancel(); + } +} \ No newline at end of file diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerList/ServerProviders/SteamDedicatedServerProvider.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerList/ServerProviders/SteamDedicatedServerProvider.cs new file mode 100644 index 000000000..ff9079caf --- /dev/null +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerList/ServerProviders/SteamDedicatedServerProvider.cs @@ -0,0 +1,160 @@ +#nullable enable +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Threading.Tasks; +using System.Xml.Linq; +using Barotrauma.Networking; +using Barotrauma.Steam; + +namespace Barotrauma +{ + sealed class SteamDedicatedServerProvider : ServerProvider + { + public class DataSource : ServerInfo.DataSource + { + public readonly UInt16 QueryPort; + + public DataSource(UInt16 queryPort) + { + QueryPort = queryPort; + } + + /// Method is invoked via reflection, + /// see + public new static Option Parse(XElement element) + => element.TryGetAttributeInt("QueryPort", out var result) + ? result switch + { + var invalidPort when invalidPort <= 0 || invalidPort > UInt16.MaxValue => Option.None(), + var queryPort => Option.Some(new DataSource((UInt16)queryPort)) + } + : Option.None(); + + public override void Write(XElement element) => element.SetAttributeValue("QueryPort", QueryPort); + } + + private static Option InfoFromListEntry(Steamworks.Data.ServerInfo entry) => + entry.Name.IsNullOrEmpty() + ? Option.None() + : Option.Some(new ServerInfo(new LidgrenEndpoint(entry.Address, entry.ConnectionPort)) + { + ServerName = entry.Name, + HasPassword = entry.Passworded, + PlayerCount = entry.Players, + MaxPlayers = entry.MaxPlayers, + MetadataSource = Option.Some(new DataSource((UInt16)entry.QueryPort)) + }); + + private static void HandleResponsiveServer(Steamworks.Data.ServerInfo entry, Action onServerDataReceived) + { + TaskPool.Add($"QueryServerRules (GetServers, {entry.Name}, {entry.Address})", entry.QueryRulesAsync(), + t => + { + if (t.Status == TaskStatus.Faulted) + { + TaskPool.PrintTaskExceptions(t, $"Failed to retrieve rules for {entry.Name}"); + return; + } + + if (!t.TryGetResult(out Dictionary rules)) { return; } + if (rules is null) { return; } + if (!InfoFromListEntry(entry).TryUnwrap(out var serverInfo)) { return; } + serverInfo.UpdateInfo(key => + { + if (rules.TryGetValue(key, out var val)) { return val; } + return null; + }); + serverInfo.Checked = true; //rules != null; + + onServerDataReceived(serverInfo); + }); + } + + private static void HandleUnresponsiveServer(Steamworks.Data.ServerInfo entry, Action onServerDataReceived) + { + //TODO: do we still want to list unresponsive servers? + if (!InfoFromListEntry(entry).TryUnwrap(out var serverInfo)) { return; } + onServerDataReceived(serverInfo); + } + + private Steamworks.ServerList.Internet? serverQuery; + private CoroutineHandle? queryCoroutine; + + protected override void RetrieveServersImpl(Action onServerDataReceived, Action onQueryCompleted) + { + if (!SteamManager.IsInitialized) + { + onQueryCompleted(); + return; + } + + // All lambdas in here must only capture this call's + // query, not the provider's latest query + var selfServerQuery = new Steamworks.ServerList.Internet(); + serverQuery = selfServerQuery; + + ConcurrentQueue responsiveServers = + new ConcurrentQueue(); + ConcurrentQueue unresponsiveServers = + new ConcurrentQueue(); + + selfServerQuery.OnResponsiveServer = responsiveServers.Enqueue; + selfServerQuery.OnUnresponsiveServer = unresponsiveServers.Enqueue; + + void dequeue(int? limit = null) + { + for (int i = 0; (!limit.HasValue || i < limit) && responsiveServers.TryDequeue(out var serverInfo); i++) + { + HandleResponsiveServer(serverInfo, onServerDataReceived); + } + + for (int i = 0; (!limit.HasValue || i < limit) && unresponsiveServers.TryDequeue(out var serverInfo); i++) + { + HandleUnresponsiveServer(serverInfo, onServerDataReceived); + } + } + + IEnumerable dequeueCoroutine() + { + while (true) + { + dequeue(limit: 20); + yield return new WaitForSeconds(0.1f, ignorePause: true); + } + } + var selfQueryCoroutine = CoroutineManager.StartCoroutine(dequeueCoroutine(), + $"{nameof(SteamDedicatedServerProvider)}.{nameof(RetrieveServers)}.{nameof(dequeueCoroutine)}"); + queryCoroutine = selfQueryCoroutine; + + TaskPool.Add("RunServerQuery", selfServerQuery.RunQueryAsync(timeoutSeconds: 30f), + t => + { + try + { + // Clear the callbacks because it's too late now, we want to get this over with + selfServerQuery.OnResponsiveServer = null; + selfServerQuery.OnUnresponsiveServer = null; + + CoroutineManager.StopCoroutines(selfQueryCoroutine); + dequeue(); + + if (t.Status == TaskStatus.Faulted) { TaskPool.PrintTaskExceptions(t, "Failed to retrieve servers"); } + + selfServerQuery.Dispose(); + } + finally + { + onQueryCompleted(); + } + }); + } + + public override void Cancel() + { + if (queryCoroutine != null) { CoroutineManager.StopCoroutines(queryCoroutine); } + serverQuery?.Dispose(); + serverQuery = null; + } + } +} \ No newline at end of file diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerList/ServerProviders/SteamP2PServerProvider.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerList/ServerProviders/SteamP2PServerProvider.cs new file mode 100644 index 000000000..fe80749e5 --- /dev/null +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerList/ServerProviders/SteamP2PServerProvider.cs @@ -0,0 +1,107 @@ +#nullable enable +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using System.Xml.Linq; +using Barotrauma.Networking; +using Barotrauma.Steam; + +namespace Barotrauma +{ + sealed class SteamP2PServerProvider : ServerProvider + { + public class DataSource : ServerInfo.DataSource + { + public readonly Steamworks.Data.Lobby Lobby; + + public override void Write(XElement element) { /* do nothing */ } + + public DataSource(Steamworks.Data.Lobby lobby) + { + Lobby = lobby; + } + } + + private object? queryRef = null; + + protected override void RetrieveServersImpl(Action onServerDataReceived, Action onQueryCompleted) + { + if (!SteamManager.IsInitialized) + { + onQueryCompleted(); + return; + } + + // All lambdas and local methods in here must only capture + // this call's query, not the provider's latest query + var selfQueryRef = new object(); + queryRef = selfQueryRef; + + Steamworks.Data.LobbyQuery lobbyQuery = Steamworks.SteamMatchmaking.CreateLobbyQuery() + .FilterDistanceWorldwide() + .WithMaxResults(50); + // Steamworks is unable to retrieve more than 50 lobbies per request + // (see https://partner.steamgames.com/doc/features/multiplayer/matchmaking#3) + // To work around this, we'll make up to 10 requests, asking to ignore + // all previous results in each subsequent request. + #warning TODO: do something less horrible here? + + int requestCount = 0; + HashSet retrieved = new HashSet(); + + void startQuery() + { + if (requestCount >= 10) { return; } + requestCount++; + TaskPool.Add($"LobbyQuery.RequestAsync ({requestCount})", lobbyQuery.RequestAsync(), onRequestComplete); + } + + void onRequestComplete(Task t) + { + // If queryRef != selfQueryRef, this query was cancelled + if (!ReferenceEquals(selfQueryRef, queryRef)) { return; } + + if (!t.TryGetResult(out Steamworks.Data.Lobby[] lobbies) + || lobbies is null + || lobbies.Length == 0) + { + onQueryCompleted(); + return; + } + + foreach (var lobby in lobbies) + { + string lobbyOwnerStr = lobby.GetData("lobbyowner"); + lobbyQuery = lobbyQuery.WithoutKeyValue("lobbyowner", lobbyOwnerStr); + + string serverName = lobby.GetData("name"); + if (string.IsNullOrEmpty(serverName)) { continue; } + + var ownerId = SteamId.Parse(lobbyOwnerStr); + if (!ownerId.TryUnwrap(out var lobbyOwnerId)) { continue; } + + if (retrieved.Contains(lobbyOwnerId)) { continue; } + retrieved.Add(lobbyOwnerId); + + var serverInfo = new ServerInfo(new SteamP2PEndpoint(lobbyOwnerId)) + { + ServerName = serverName, + MetadataSource = Option.Some(new DataSource(lobby)) + }; + serverInfo.UpdateInfo(key => lobby.GetData(key)); + serverInfo.Checked = true; + + onServerDataReceived(serverInfo); + } + startQuery(); + } + + startQuery(); + } + + public override void Cancel() + { + queryRef = null; + } + } +} \ No newline at end of file diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerSettings.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerSettings.cs index 018a897a3..10829d4fb 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerSettings.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerSettings.cs @@ -125,8 +125,6 @@ namespace Barotrauma.Networking public void ClientRead(IReadMessage incMsg) { - cachedServerListInfo = null; - NetFlags requiredFlags = (NetFlags)incMsg.ReadByte(); if (requiredFlags.HasFlag(NetFlags.Name)) @@ -146,7 +144,6 @@ namespace Barotrauma.Networking AllowFileTransfers = incMsg.ReadBoolean(); incMsg.ReadPadBits(); TickRate = incMsg.ReadRangedInteger(1, 60); - GameMain.NetworkMember.TickRate = TickRate; if (requiredFlags.HasFlag(NetFlags.Properties)) { @@ -241,7 +238,8 @@ namespace Barotrauma.Networking outMsg.WriteSingle(levelDifficulty ?? -1000.0f); - outMsg.WriteBoolean(useRespawnShuttle ?? UseRespawnShuttle); + outMsg.WriteBoolean(useRespawnShuttle != null); + outMsg.WriteBoolean(useRespawnShuttle ?? false); outMsg.WriteBoolean(autoRestart != null); outMsg.WriteBoolean(autoRestart ?? false); @@ -1057,15 +1055,7 @@ namespace Barotrauma.Networking } settingsFrame = null; } - return false; } - - private ServerInfo cachedServerListInfo = null; - public ServerInfo GetServerListInfo() - { - cachedServerListInfo ??= GameMain.ServerListScreen.UpdateServerInfoWithServerSettings(GameMain.Client.ClientPeer.ServerConnection, this); - return cachedServerListInfo; - } } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/Voting.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/Voting.cs index b2f044280..f07d6f7a9 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Networking/Voting.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/Voting.cs @@ -3,6 +3,7 @@ using Microsoft.Xna.Framework; using System.Collections.Generic; using System.Linq; using Barotrauma.Extensions; +using System; namespace Barotrauma { @@ -111,6 +112,23 @@ namespace Barotrauma } } + public void ResetVotes(IEnumerable connectedClients) + { + foreach (Client client in connectedClients) + { + client.ResetVotes(); + } + + foreach (VoteType voteType in Enum.GetValues(typeof(VoteType))) + { + SetVoteCountYes(voteType, 0); + SetVoteCountNo(voteType, 0); + SetVoteCountMax(voteType, 0); + } + UpdateVoteTexts(connectedClients, VoteType.Mode); + UpdateVoteTexts(connectedClients, VoteType.Sub); + } + public void ClientWrite(IWriteMessage msg, VoteType voteType, object data) { msg.WriteByte((byte)voteType); diff --git a/Barotrauma/BarotraumaClient/ClientSource/Screens/MainMenuScreen.cs b/Barotrauma/BarotraumaClient/ClientSource/Screens/MainMenuScreen.cs index 0f1ec526f..01f4b8506 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Screens/MainMenuScreen.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Screens/MainMenuScreen.cs @@ -67,6 +67,8 @@ namespace Barotrauma public static readonly Queue WorkshopItemsToUpdate = new Queue(); + private readonly GUIListBox tutorialList; + #region Creation public MainMenuScreen(GameMain game) { @@ -429,26 +431,19 @@ namespace Barotrauma menuTabs[Tab.Tutorials] = new GUIFrame(new RectTransform(relativeSize, GUI.Canvas, anchor, pivot, minSize, maxSize) { RelativeOffset = relativeSpacing }); //PLACEHOLDER - var tutorialList = new GUIListBox( + tutorialList = new GUIListBox( new RectTransform(new Vector2(0.95f, 0.85f), menuTabs[Tab.Tutorials].RectTransform, Anchor.TopCenter) { RelativeOffset = new Vector2(0.0f, 0.1f) }) { PlaySoundOnSelect = true, }; - foreach (var tutorialPrefab in TutorialPrefab.Prefabs.OrderBy(p => p.Order)) - { - var tutorial = new Tutorial(tutorialPrefab); - var tutorialText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.15f), tutorialList.Content.RectTransform), tutorial.DisplayName, textAlignment: Alignment.Center, font: GUIStyle.LargeFont) - { - TextColor = GUIStyle.Green, - UserData = tutorial - }; - } tutorialList.OnSelected += (component, obj) => { (obj as Tutorial)?.Start(); return true; }; + CreateTutorialButtons(); + this.game = game; menuTabs[Tab.Credits] = new GUIFrame(new RectTransform(Vector2.One, GUI.Canvas, Anchor.Center), style: null) @@ -463,7 +458,28 @@ namespace Barotrauma var creditsContainer = new GUIFrame(new RectTransform(new Vector2(0.75f, 1.5f), menuTabs[Tab.Credits].RectTransform, Anchor.CenterRight), style: "OuterGlow", color: Color.Black * 0.8f); creditsPlayer = new CreditsPlayer(new RectTransform(Vector2.One, creditsContainer.RectTransform), "Content/Texts/Credits.xml"); } -#endregion + + private void CreateTutorialButtons() + { + foreach (var tutorialPrefab in TutorialPrefab.Prefabs.OrderBy(p => p.Order)) + { + var tutorial = new Tutorial(tutorialPrefab); + var tutorialText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.15f), tutorialList.Content.RectTransform), tutorial.DisplayName, textAlignment: Alignment.Center, font: GUIStyle.LargeFont) + { + TextColor = GUIStyle.Green, + UserData = tutorial + }; + } + } + + public static void UpdateInstanceTutorialButtons() + { + if (GameMain.MainMenuScreen is not MainMenuScreen menuScreen) { return; } + menuScreen.tutorialList.ClearChildren(); + menuScreen.CreateTutorialButtons(); + } + + #endregion #region Selection public override void Select() @@ -1117,7 +1133,7 @@ namespace Barotrauma var playstyleContainer = new GUIFrame(new RectTransform(new Vector2(1.35f, 0.1f), parent.RectTransform), style: null, color: Color.Black); playstyleBanner = new GUIImage(new RectTransform(new Vector2(1.0f, 0.1f), playstyleContainer.RectTransform), - ServerListScreen.PlayStyleBanners[0], scaleToFit: true) + GUIStyle.GetComponentStyle($"PlayStyleBanner.{PlayStyle.Serious}").GetSprite(GUIComponent.ComponentState.None), scaleToFit: true) { UserData = PlayStyle.Serious }; @@ -1336,12 +1352,15 @@ namespace Barotrauma private void SetServerPlayStyle(PlayStyle playStyle) { - playstyleBanner.Sprite = ServerListScreen.PlayStyleBanners[(int)playStyle]; + playstyleBanner.Sprite = GUIStyle + .GetComponentStyle($"PlayStyleBanner.{playStyle}") + .GetSprite(GUIComponent.ComponentState.None); playstyleBanner.UserData = playStyle; var nameText = playstyleBanner.GetChild(); nameText.Text = TextManager.AddPunctuation(':', TextManager.Get("serverplaystyle"), TextManager.Get("servertag." + playStyle)); - nameText.Color = ServerListScreen.PlayStyleColors[(int)playStyle]; + nameText.Color = playstyleBanner.Sprite + .SourceElement.GetAttributeColor("BannerColor") ?? Color.White; nameText.RectTransform.NonScaledSize = (nameText.Font.MeasureString(nameText.Text) + new Vector2(25, 10) * GUI.Scale).ToPoint(); playstyleDescription.Text = TextManager.Get("servertagdescription." + playStyle); diff --git a/Barotrauma/BarotraumaClient/ClientSource/Screens/ModDownloadScreen.cs b/Barotrauma/BarotraumaClient/ClientSource/Screens/ModDownloadScreen.cs index e638bf0e5..a37fda6f5 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Screens/ModDownloadScreen.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Screens/ModDownloadScreen.cs @@ -92,7 +92,7 @@ namespace Barotrauma var missingPackages = GameMain.Client.ClientPeer.ServerContentPackages .Where(sp => sp.ContentPackage is null).ToArray(); - if (!missingPackages.Any()) + if (!missingPackages.Any(p => p.IsMandatory)) { if (!GameMain.Client.IsServerOwner) { @@ -106,7 +106,7 @@ namespace Barotrauma .Select(p => p.RegularPackage) .OfType().ToList(); //keep enabled client-side-only mods enabled - regularPackages.AddRange(ContentPackageManager.EnabledPackages.Regular.Where(p => !p.HasMultiplayerSyncedContent)); + regularPackages.AddRange(ContentPackageManager.EnabledPackages.Regular.Where(p => !p.HasMultiplayerSyncedContent && !regularPackages.Contains(p))); ContentPackageManager.EnabledPackages.SetRegular(regularPackages); } GameMain.NetLobbyScreen.Select(); @@ -177,11 +177,11 @@ namespace Barotrauma }); buttonContainerSpacing(0.1f); - var missingIds = missingPackages.Where( - mp => mp.WorkshopId != 0 - && ContentPackageManager.WorkshopPackages.All(wp - => wp.SteamWorkshopId != mp.WorkshopId)) - .Select(mp => mp.WorkshopId) + var missingIds = missingPackages + .Where(p => p.IsMandatory) + .Select(mp => ContentPackageId.Parse(mp.UgcId)) + .NotNone() + .Where(id => ContentPackageManager.WorkshopPackages.All(wp => !wp.UgcId.Equals(id))) .ToArray(); if (missingIds.Any() && SteamManager.IsInitialized) { @@ -191,7 +191,7 @@ namespace Barotrauma { if (GameMain.Client != null) { - BulkDownloader.SubscribeToServerMods(missingIds, + BulkDownloader.SubscribeToServerMods(missingIds.OfType().Select(id => id.Value), new ConnectCommand( serverName: GameMain.Client.ServerName, endpoint: GameMain.Client.ClientPeer.ServerEndpoint)); @@ -202,7 +202,7 @@ namespace Barotrauma buttonContainerSpacing(0.15f); } - foreach (var p in missingPackages) + foreach (var p in missingPackages.Where(p => p.IsMandatory)) { pendingDownloads.Enqueue(p); @@ -294,26 +294,50 @@ namespace Barotrauma ?? serverPackages.FirstOrDefault(p => p.CorePackage != null) ?.CorePackage ?? throw new Exception($"Failed to find core package to enable"); - List regularPackages - = serverPackages.Where(p => p.CorePackage is null) - .Select(p => - p.RegularPackage - ?? downloadedPackages.FirstOrDefault(d => d is RegularPackage && d.Hash.Equals(p.Hash)) - ?? throw new Exception($"Could not find regular package \"{p.Name}\"")) - .Cast() - .ToList(); + + List regularPackages = new List(); + foreach (var p in serverPackages) + { + if (p.CorePackage != null) { continue; } + RegularPackage? matchingPackage = + p.RegularPackage ?? downloadedPackages.FirstOrDefault(d => d is RegularPackage && d.Hash.Equals(p.Hash)) as RegularPackage; + if (matchingPackage is null) + { + if (!p.IsMandatory) + { + //we don't need to care about missing non-mandatory (= submarine) mods + continue; + } + else + { + throw new Exception($"Could not find regular package \"{p.Name}\""); + } + } + regularPackages.Add(matchingPackage); + } foreach (var regularPackage in regularPackages) { DebugConsole.NewMessage($"Enabling \"{regularPackage.Name}\" ({regularPackage.Dir})", Color.Lime); } //keep enabled client-side-only mods enabled - regularPackages.AddRange(ContentPackageManager.EnabledPackages.Regular.Where(p => !p.HasMultiplayerSyncedContent)); + regularPackages.AddRange(ContentPackageManager.EnabledPackages.Regular.Where(p => !p.HasMultiplayerSyncedContent && !regularPackages.Contains(p))); ContentPackageManager.EnabledPackages.BackUp(); ContentPackageManager.EnabledPackages.SetCore(corePackage); ContentPackageManager.EnabledPackages.SetRegular(regularPackages); + //see if any of the packages we enabled contain subs that we were missing previously, and update their paths + foreach (var serverSub in GameMain.Client.ServerSubmarines) + { + if (File.Exists(serverSub.FilePath)) { continue; } + var matchingSub = SubmarineInfo.SavedSubmarines.FirstOrDefault(s => s.Name == serverSub.Name && s.MD5Hash == serverSub.MD5Hash); + if (matchingSub != null) + { + serverSub.FilePath = matchingSub.FilePath; + } + } + GameMain.NetLobbyScreen.UpdateSubList(GameMain.NetLobbyScreen.SubList, GameMain.Client.ServerSubmarines); GameMain.NetLobbyScreen.Select(); } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Screens/NetLobbyScreen.cs b/Barotrauma/BarotraumaClient/ClientSource/Screens/NetLobbyScreen.cs index 9c9e999d6..9471d8128 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Screens/NetLobbyScreen.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Screens/NetLobbyScreen.cs @@ -666,7 +666,7 @@ namespace Barotrauma OnSelected = (tickbox) => { if (GameMain.Client == null) { return true; } - ServerInfo info = GameMain.Client.ServerSettings.GetServerListInfo(); + ServerInfo info = GameMain.Client.CreateServerInfoFromSettings(); if (tickbox.Selected) { GameMain.ServerListScreen.AddToFavoriteServers(info); @@ -1432,10 +1432,6 @@ namespace Barotrauma bool nameChangePending = isGameRunning && GameMain.Client.PendingName != string.Empty && GameMain.Client?.Character?.Name != GameMain.Client.PendingName; changesPendingText = null; - if (isGameRunning) - { - infoContainer.RectTransform.AbsoluteOffset = new Point(0, (int)(parent.Rect.Height * 0.025f)); - } if (TabMenu.PendingChanges) { @@ -1454,7 +1450,6 @@ namespace Barotrauma { if (GameMain.Client == null) { return; } string newName = Client.SanitizeName(tb.Text); - newName = newName.Replace(":", "").Replace(";", ""); if (newName == GameMain.Client.Name) return; if (string.IsNullOrWhiteSpace(newName)) { @@ -1782,6 +1777,10 @@ namespace Barotrauma // Hide spectate tickbox if spectating is not allowed spectateBox.Visible = allowSpectating; + if (infoContainer != null) + { + infoContainer.RectTransform.RelativeSize = new Vector2(infoContainer.RectTransform.RelativeSize.X, spectateBox.Visible ? 0.92f : 0.97f); + } } public void SetAutoRestart(bool enabled, float timer = 0.0f) @@ -2753,25 +2752,24 @@ namespace Barotrauma if (GameMain.NetworkMember?.ServerSettings == null) { return; } PlayStyle playStyle = GameMain.NetworkMember.ServerSettings.PlayStyle; - if ((int)playStyle < 0 || - (int)playStyle >= ServerListScreen.PlayStyleBanners.Length) - { - return; - } - Sprite sprite = ServerListScreen.PlayStyleBanners[(int)playStyle]; + Sprite sprite = GUIStyle + .GetComponentStyle($"PlayStyleBanner.{playStyle}")? + .GetSprite(GUIComponent.ComponentState.None); + if (sprite is null) { return; } + float scale = component.Rect.Width / sprite.size.X; sprite.Draw(spriteBatch, component.Center, scale: scale); if (!prevPlayStyle.HasValue || playStyle != prevPlayStyle.Value) { var nameText = component.GetChild(); - nameText.Text = TextManager.Get("servertag." + playStyle); - nameText.Color = ServerListScreen.PlayStyleColors[(int)playStyle]; + nameText.Text = TextManager.Get($"ServerTag.{playStyle}"); + nameText.Color = sprite.SourceElement.GetAttributeColor("BannerColor") ?? Color.White; nameText.RectTransform.NonScaledSize = (nameText.Font.MeasureString(nameText.Text) + new Vector2(25, 10) * GUI.Scale).ToPoint(); prevPlayStyle = playStyle; - component.ToolTip = TextManager.Get("servertagdescription." + playStyle); + component.ToolTip = TextManager.Get($"ServerTagDescription.{playStyle}"); } publicOrPrivate.RectTransform.NonScaledSize = (publicOrPrivate.Font.MeasureString(publicOrPrivate.Text) + new Vector2(25, 8) * GUI.Scale).ToPoint(); diff --git a/Barotrauma/BarotraumaClient/ClientSource/Screens/ServerListScreen.cs b/Barotrauma/BarotraumaClient/ClientSource/Screens/ServerListScreen.cs deleted file mode 100644 index 984cb5cbb..000000000 --- a/Barotrauma/BarotraumaClient/ClientSource/Screens/ServerListScreen.cs +++ /dev/null @@ -1,2044 +0,0 @@ -using Barotrauma.Extensions; -using Barotrauma.IO; -using Barotrauma.Networking; -using Barotrauma.Steam; -using Microsoft.Xna.Framework; -using Microsoft.Xna.Framework.Graphics; -using RestSharp; -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Linq; -using System.Net; -using System.Net.NetworkInformation; -using System.Net.Sockets; -using System.Threading.Tasks; -using System.Xml.Linq; - -namespace Barotrauma -{ - class ServerListScreen : Screen - { - //how often the client is allowed to refresh servers - private readonly TimeSpan AllowedRefreshInterval = new TimeSpan(0, 0, 3); - - public ImmutableDictionary ContentPackagesByWorkshopId { get; private set; } - = ImmutableDictionary.Empty; - public ImmutableDictionary ContentPackagesByHash { get; private set; } - = ImmutableDictionary.Empty; - - private GUIFrame menu; - - private GUIListBox serverList; - private GUIFrame serverPreviewContainer; - private GUIListBox serverPreview; - - private GUIButton joinButton; - private ServerInfo selectedServer; - - private GUIButton scanServersButton; - - //friends list - private GUILayoutGroup friendsButtonHolder; - - private GUIButton friendsDropdownButton; - private GUIListBox friendsDropdown; - - private enum TernaryOption - { - Any, - Enabled, - Disabled - } - - private class FriendInfo - { - public UInt64 SteamId; - public string Name; - public Sprite Sprite; - public LocalizedString StatusText; - public bool PlayingThisGame; - public bool PlayingAnotherGame; - public Option ConnectCommand = Option.None(); - - public bool InServer - { - get - { - return PlayingThisGame && !StatusText.IsNullOrWhiteSpace() && ConnectCommand.IsSome(); - } - } - } - private List friendsList; - private GUIFrame friendPopup; - private double friendsListUpdateTime; - - //favorite servers/history - private const string recentServersFile = "Data/recentservers.xml"; - private const string favoriteServersFile = "Data/favoriteservers.xml"; - private List favoriteServers; - private List recentServers; - - private readonly Dictionary activePings = new Dictionary(); - - private enum ServerListTab - { - All = 0, - Favorites = 1, - Recent = 2 - }; - private ServerListTab selectedTab; - private ServerListTab SelectedTab - { - get { return selectedTab; } - set - { - if (selectedTab == value) { return; } - var tabVals = Enum.GetValues(typeof(ServerListTab)); - for (int i = 0; i < tabVals.Length; i++) - { - tabButtons[i].Selected = false; - } - tabButtons[(int)value].Selected = true; - selectedTab = value; - FilterServers(); - } - } - private GUIButton[] tabButtons; - - private static Sprite[] playStyleBanners; - //server playstyle and tags - public static Sprite[] PlayStyleBanners - { - get - { - if (playStyleBanners == null) - { - LoadPlayStyleBanners(); - } - return playStyleBanners; - } - } - public static Color[] PlayStyleColors - { - get; private set; - } - - public GUITextBox ClientNameBox { get; private set; } - - public static Dictionary PlayStyleIcons - { - get; private set; - } - public static Dictionary PlayStyleIconColors - { - get; private set; - } - - private bool masterServerResponded; - private IRestResponse masterServerResponse; - - private readonly float[] columnRelativeWidth = new float[] { 0.1f, 0.1f, 0.7f, 0.12f, 0.08f, 0.08f }; - private readonly string[] columnLabel = new string[] { "ServerListCompatible", "ServerListHasPassword", "ServerListName", "ServerListRoundStarted", "ServerListPlayers", "ServerListPing" }; - - private GUILayoutGroup labelHolder; - private readonly List labelTexts = new List(); - - //filters - private GUITextBox searchBox; - private GUITickBox filterSameVersion; - private GUITickBox filterPassword; - private GUITickBox filterIncompatible; - private GUITickBox filterFull; - private GUITickBox filterEmpty; - private Dictionary ternaryFilters; - private Dictionary filterTickBoxes; - private Dictionary playStyleTickBoxes; - private Dictionary gameModeTickBoxes; - private GUITickBox filterOffensive; - - //GUIDropDown sends the OnSelected event before SelectedData is set, so we have to cache it manually. - private TernaryOption filterFriendlyFireValue = TernaryOption.Any; - private TernaryOption filterKarmaValue = TernaryOption.Any; - private TernaryOption filterTraitorValue = TernaryOption.Any; - private TernaryOption filterVoipValue = TernaryOption.Any; - private TernaryOption filterModdedValue = TernaryOption.Any; - - private string sortedBy; - - private GUIButton serverPreviewToggleButton; - - //a timer for preventing the client from spamming the refresh button faster than AllowedRefreshInterval - private DateTime refreshDisableTimer; - private bool waitingForRefresh; - - private bool steamPingInfoReady; - - private const float sidebarWidth = 0.2f; - public ServerListScreen() - { - GameMain.Instance.ResolutionChanged += CreateUI; - CreateUI(); - } - - private void AddTernaryFilter(RectTransform parent, float elementHeight, Identifier tag, Action valueSetter) - { - var filterLayoutGroup = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, elementHeight), parent), isHorizontal: true) - { - Stretch = true - }; - - var box = new GUIFrame(new RectTransform(Vector2.One, filterLayoutGroup.RectTransform, Anchor.CenterLeft, scaleBasis: ScaleBasis.BothHeight) - { - IsFixedSize = true, - }, null) - { - HoverColor = Color.Gray, - SelectedColor = Color.DarkGray, - CanBeFocused = false - }; - if (box.RectTransform.MinSize.Y > 0) - { - box.RectTransform.MinSize = new Point(box.RectTransform.MinSize.Y); - box.RectTransform.Resize(box.RectTransform.MinSize); - } - Vector2 textBlockScale = new Vector2((float)(filterLayoutGroup.Rect.Width - filterLayoutGroup.Rect.Height) / (float)Math.Max(filterLayoutGroup.Rect.Width, 1.0), 1.0f); - - var filterLabel = new GUITextBlock(new RectTransform(new Vector2(0.6f, 1.0f) * textBlockScale, filterLayoutGroup.RectTransform, Anchor.CenterLeft), TextManager.Get("servertag." + tag + ".label"), textAlignment: Alignment.CenterLeft) - { - UserData = TextManager.Get("servertag." + tag + ".label") - }; - GUIStyle.Apply(filterLabel, "GUITextBlock", null); - - var dropDown = new GUIDropDown(new RectTransform(new Vector2(0.4f, 1.0f) * textBlockScale, filterLayoutGroup.RectTransform, Anchor.CenterLeft), elementCount: 3); - dropDown.AddItem(TextManager.Get("any"), TernaryOption.Any); - dropDown.AddItem(TextManager.Get("servertag." + tag + ".true"), TernaryOption.Enabled, TextManager.Get("servertagdescription." + tag + ".true")); - dropDown.AddItem(TextManager.Get("servertag." + tag + ".false"), TernaryOption.Disabled, TextManager.Get("servertagdescription." + tag + ".false")); - dropDown.SelectItem(TernaryOption.Any); - dropDown.OnSelected = (_, data) => { - valueSetter((TernaryOption)data); - FilterServers(); - StoreServerFilters(); - return true; - }; - - ternaryFilters.Add(tag, dropDown); - } - - private void CreateUI() - { - menu = new GUIFrame(new RectTransform(new Vector2(0.95f, 0.85f), GUI.Canvas, Anchor.Center) { MinSize = new Point(GameMain.GraphicsHeight, 0) }); - - var paddedFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.98f, 0.98f), menu.RectTransform, Anchor.Center)) - { - RelativeSpacing = 0.02f, - Stretch = true - }; - - //------------------------------------------------------------------------------------- - //Top row - //------------------------------------------------------------------------------------- - - var topRow = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.15f), paddedFrame.RectTransform)) { Stretch = true }; - - var title = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.33f), topRow.RectTransform), TextManager.Get("JoinServer"), font: GUIStyle.LargeFont) - { - Padding = Vector4.Zero, - ForceUpperCase = ForceUpperCase.Yes, - AutoScaleHorizontal = true - }; - - var infoHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.33f), topRow.RectTransform), isHorizontal: true, Anchor.BottomLeft) { RelativeSpacing = 0.01f, Stretch = false }; - - var clientNameHolder = new GUILayoutGroup(new RectTransform(new Vector2(sidebarWidth, 1.0f), infoHolder.RectTransform)) { RelativeSpacing = 0.05f }; - - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), clientNameHolder.RectTransform), TextManager.Get("YourName"), font: GUIStyle.SubHeadingFont); - ClientNameBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 0.5f), clientNameHolder.RectTransform), "") - { - Text = MultiplayerPreferences.Instance.PlayerName, - MaxTextLength = Client.MaxNameLength, - OverflowClip = true - }; - - if (string.IsNullOrEmpty(ClientNameBox.Text)) - { - ClientNameBox.Text = SteamManager.GetUsername(); - } - ClientNameBox.OnTextChanged += (textbox, text) => - { - MultiplayerPreferences.Instance.PlayerName = text; - return true; - }; - - var tabButtonHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f - sidebarWidth - infoHolder.RelativeSpacing, 0.5f), infoHolder.RectTransform), isHorizontal: true); - - var tabVals = Enum.GetValues(typeof(ServerListTab)); - tabButtons = new GUIButton[tabVals.Length]; - foreach (ServerListTab tab in tabVals) - { - tabButtons[(int)tab] = new GUIButton(new RectTransform(new Vector2(0.2f, 1.0f), tabButtonHolder.RectTransform), - TextManager.Get("ServerListTab." + tab.ToString()), style: "GUITabButton") - { - OnClicked = (btn, usrdat) => - { - SelectedTab = tab; - return false; - } - }; - } - - var friendsButtonFrame = new GUIFrame(new RectTransform(new Vector2(0.31f, 2.0f), tabButtonHolder.RectTransform, Anchor.BottomRight), style: "InnerFrame") - { - IgnoreLayoutGroups = true - }; - - friendsButtonHolder = new GUILayoutGroup(new RectTransform(new Vector2(0.98f, 0.9f), friendsButtonFrame.RectTransform, Anchor.Center), childAnchor: Anchor.TopLeft) { RelativeSpacing = 0.01f, IsHorizontal = true }; - friendsList = new List(); - - //------------------------------------------------------------------------------------- - // Bottom row - //------------------------------------------------------------------------------------- - - var bottomRow = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 1.0f - topRow.RectTransform.RelativeSize.Y), - paddedFrame.RectTransform, Anchor.CenterRight)) - { - Stretch = true - }; - - var serverListHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 1.0f), bottomRow.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterLeft) - { - OutlineColor = Color.Black - }; - - GUILayoutGroup serverListContainer = null; - GUIFrame filtersHolder = null; - GUIButton filterToggle = null; - - void RecalculateHolder() - { - float listContainerSubtract = filtersHolder.Visible ? sidebarWidth : 0.0f; - listContainerSubtract += serverPreviewContainer.Visible ? sidebarWidth : 0.0f; - - float toggleButtonsSubtract = 1.1f * filterToggle.Rect.Width / serverListHolder.Rect.Width; - listContainerSubtract += filterToggle.Visible ? toggleButtonsSubtract : 0.0f; - listContainerSubtract += serverPreviewContainer.Visible ? toggleButtonsSubtract : 0.0f; - - serverListContainer.RectTransform.RelativeSize = new Vector2(1.0f - listContainerSubtract, 1.0f); - serverListHolder.Recalculate(); - } - - // filters ------------------------------------------- - - filtersHolder = new GUIFrame(new RectTransform(new Vector2(sidebarWidth, 1.0f), serverListHolder.RectTransform, Anchor.Center), style: null) - { - Color = new Color(12, 14, 15, 255) * 0.5f, - OutlineColor = Color.Black - }; - - float elementHeight = 0.05f; - var filterTitle = new GUITextBlock(new RectTransform(new Vector2(1.0f, elementHeight), filtersHolder.RectTransform), TextManager.Get("FilterServers"), font: GUIStyle.SubHeadingFont) - { - Padding = Vector4.Zero, - AutoScaleHorizontal = true, - CanBeFocused = false - }; - - var searchHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, elementHeight), filtersHolder.RectTransform) { RelativeOffset = new Vector2(0.0f, elementHeight) }, isHorizontal: true) { Stretch = true }; - - var searchTitle = new GUITextBlock(new RectTransform(new Vector2(0.001f, 1.0f), searchHolder.RectTransform), TextManager.Get("Search") + "..."); - searchBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 1.0f), searchHolder.RectTransform), ""); - searchBox.OnSelected += (sender, userdata) => { searchTitle.Visible = false; }; - searchBox.OnDeselected += (sender, userdata) => { searchTitle.Visible = true; }; - searchBox.OnTextChanged += (txtBox, txt) => { FilterServers(); return true; }; - - var filters = new GUIListBox(new RectTransform(new Vector2(0.98f, 1.0f - elementHeight * 2), filtersHolder.RectTransform, Anchor.BottomLeft)) - { - ScrollBarVisible = true, - Spacing = (int)(5 * GUI.Scale) - }; - - filterToggle = new GUIButton(new RectTransform(new Vector2(0.01f, 1.0f), serverListHolder.RectTransform) - { MinSize = new Point(20, 0), MaxSize = new Point(int.MaxValue, (int)(150 * GUI.Scale)) }, - style: "UIToggleButton") - { - OnClicked = (btn, userdata) => - { - filtersHolder.RectTransform.RelativeSize = new Vector2(sidebarWidth, 1.0f); - filtersHolder.Visible = !filtersHolder.Visible; - filtersHolder.IgnoreLayoutGroups = !filtersHolder.Visible; - - RecalculateHolder(); - - btn.Children.ForEach(c => c.SpriteEffects = !filtersHolder.Visible ? SpriteEffects.None : SpriteEffects.FlipHorizontally); - return true; - } - }; - filterToggle.Children.ForEach(c => c.SpriteEffects = SpriteEffects.FlipHorizontally); - - ternaryFilters = new Dictionary(); - filterTickBoxes = new Dictionary(); - - GUITickBox addTickBox(Identifier key, LocalizedString text = null, bool defaultState = false, bool addTooltip = false) - { - text ??= TextManager.Get(key); - var tickBox = new GUITickBox(new RectTransform(new Vector2(1.0f, elementHeight), filters.Content.RectTransform), text) - { - UserData = text, - Selected = defaultState, - ToolTip = addTooltip ? text : null, - OnSelected = (tickBox) => - { - FilterServers(); - StoreServerFilters(); - return true; - } - }; - filterTickBoxes.Add(key, tickBox); - return tickBox; - } - - filterSameVersion = addTickBox("FilterSameVersion".ToIdentifier(), defaultState: true); - filterPassword = addTickBox("FilterPassword".ToIdentifier()); - filterIncompatible = addTickBox("FilterIncompatibleServers".ToIdentifier()); - filterFull = addTickBox("FilterFullServers".ToIdentifier()); - filterEmpty = addTickBox("FilterEmptyServers".ToIdentifier()); - filterOffensive = addTickBox("FilterOffensiveServers".ToIdentifier()); - - // Filter Tags - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), filters.Content.RectTransform), TextManager.Get("servertags"), font: GUIStyle.SubHeadingFont) - { - CanBeFocused = false - }; - - AddTernaryFilter(filters.Content.RectTransform, elementHeight, "karma".ToIdentifier(), (value) => { filterKarmaValue = value; }); - AddTernaryFilter(filters.Content.RectTransform, elementHeight, "traitors".ToIdentifier(), (value) => { filterTraitorValue = value; }); - AddTernaryFilter(filters.Content.RectTransform, elementHeight, "friendlyfire".ToIdentifier(), (value) => { filterFriendlyFireValue = value; }); - AddTernaryFilter(filters.Content.RectTransform, elementHeight, "voip".ToIdentifier(), (value) => { filterVoipValue = value; }); - AddTernaryFilter(filters.Content.RectTransform, elementHeight, "modded".ToIdentifier(), (value) => { filterModdedValue = value; }); - - // Play Style Selection - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), filters.Content.RectTransform), TextManager.Get("ServerSettingsPlayStyle"), font: GUIStyle.SubHeadingFont) - { - CanBeFocused = false - }; - - playStyleTickBoxes = new Dictionary(); - foreach (PlayStyle playStyle in Enum.GetValues(typeof(PlayStyle))) - { - var selectionTick = addTickBox($"servertag.{playStyle}".ToIdentifier(), defaultState: true, addTooltip: true); - selectionTick.UserData = playStyle; - playStyleTickBoxes.Add($"servertag.{playStyle}".ToIdentifier(), selectionTick); - } - - // Game mode Selection - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), filters.Content.RectTransform), TextManager.Get("gamemode"), font: GUIStyle.SubHeadingFont) { CanBeFocused = false }; - - gameModeTickBoxes = new Dictionary(); - foreach (GameModePreset mode in GameModePreset.List) - { - if (mode.IsSinglePlayer) { continue; } - - var selectionTick = addTickBox(mode.Identifier, mode.Name, defaultState: true, addTooltip: true); - selectionTick.UserData = mode.Identifier; - gameModeTickBoxes.Add(mode.Identifier, selectionTick); - } - - filters.Content.RectTransform.SizeChanged += () => - { - filters.Content.RectTransform.RecalculateChildren(true, true); - filterTickBoxes.ForEach(t => t.Value.Text = t.Value.UserData is LocalizedString lStr ? lStr : t.Value.UserData.ToString()); - gameModeTickBoxes.ForEach(tb => tb.Value.Text = tb.Value.ToolTip); - playStyleTickBoxes.ForEach(tb => tb.Value.Text = tb.Value.ToolTip); - GUITextBlock.AutoScaleAndNormalize( - filterTickBoxes.Values.Select(tb => tb.TextBlock) - .Concat(ternaryFilters.Values.Select(dd => dd.Parent.GetChild())), - defaultScale: 1.0f); - if (filterTickBoxes.Values.First().TextBlock.TextScale < 0.8f) - { - filterTickBoxes.ForEach(t => t.Value.TextBlock.TextScale = 1.0f); - filterTickBoxes.ForEach(t => t.Value.TextBlock.Text = ToolBox.LimitString(t.Value.TextBlock.Text, t.Value.TextBlock.Font, (int)(filters.Content.Rect.Width * 0.8f))); - } - }; - - // server list --------------------------------------------------------------------- - - serverListContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 1.0f), serverListHolder.RectTransform)) { Stretch = true }; - - labelHolder = new GUILayoutGroup(new RectTransform(new Vector2(0.99f, 0.05f), serverListContainer.RectTransform) { MinSize = new Point(0, 15) }, - isHorizontal: true, childAnchor: Anchor.BottomLeft) - { - Stretch = true - }; - - for (int i = 0; i < columnRelativeWidth.Length; i++) - { - var btn = new GUIButton(new RectTransform(new Vector2(columnRelativeWidth[i], 1.0f), labelHolder.RectTransform), - text: TextManager.Get(columnLabel[i]), textAlignment: Alignment.Center, style: "GUIButtonSmall") - { - ToolTip = TextManager.Get(columnLabel[i]), - ForceUpperCase = ForceUpperCase.Yes, - UserData = columnLabel[i], - OnClicked = SortList - }; - btn.Color *= 0.5f; - labelTexts.Add(btn.TextBlock); - - new GUIImage(new RectTransform(new Vector2(0.5f, 0.3f), btn.RectTransform, Anchor.BottomCenter, scaleBasis: ScaleBasis.BothHeight), style: "GUIButtonVerticalArrow", scaleToFit: true) - { - CanBeFocused = false, - UserData = "arrowup", - Visible = false - }; - new GUIImage(new RectTransform(new Vector2(0.5f, 0.3f), btn.RectTransform, Anchor.BottomCenter, scaleBasis: ScaleBasis.BothHeight), style: "GUIButtonVerticalArrow", scaleToFit: true) - { - CanBeFocused = false, - UserData = "arrowdown", - SpriteEffects = SpriteEffects.FlipVertically, - Visible = false - }; - } - - serverList = new GUIListBox(new RectTransform(new Vector2(1.0f, 1.0f), serverListContainer.RectTransform, Anchor.Center)) - { - PlaySoundOnSelect = true, - ScrollBarVisible = true, - OnSelected = (btn, obj) => - { - if (obj is ServerInfo serverInfo) - { - joinButton.Enabled = true; - selectedServer = serverInfo; - if (!serverPreviewContainer.Visible) - { - serverPreviewContainer.RectTransform.RelativeSize = new Vector2(sidebarWidth, 1.0f); - serverPreviewToggleButton.Visible = true; - serverPreviewToggleButton.IgnoreLayoutGroups = false; - serverPreviewContainer.Visible = true; - serverPreviewContainer.IgnoreLayoutGroups = false; - RecalculateHolder(); - } - serverInfo.CreatePreviewWindow(serverPreview.Content); - serverPreview.ForceLayoutRecalculation(); - btn.Children.ForEach(c => c.SpriteEffects = serverPreviewContainer.Visible ? SpriteEffects.None : SpriteEffects.FlipHorizontally); - } - return true; - } - }; - - //server preview panel -------------------------------------------------- - - serverPreviewToggleButton = new GUIButton(new RectTransform(new Vector2(0.01f, 1.0f), serverListHolder.RectTransform) - { MinSize = new Point(20, 0), MaxSize = new Point(int.MaxValue, (int)(150 * GUI.Scale)) }, - style: "UIToggleButton") - { - Visible = false, - OnClicked = (btn, userdata) => - { - serverPreviewContainer.RectTransform.RelativeSize = new Vector2(0.2f, 1.0f); - serverPreviewContainer.Visible = !serverPreviewContainer.Visible; - serverPreviewContainer.IgnoreLayoutGroups = !serverPreviewContainer.Visible; - - RecalculateHolder(); - - btn.Children.ForEach(c => c.SpriteEffects = serverPreviewContainer.Visible ? SpriteEffects.None : SpriteEffects.FlipHorizontally); - return true; - } - }; - - serverPreviewContainer = new GUIFrame(new RectTransform(new Vector2(sidebarWidth, 1.0f), serverListHolder.RectTransform, Anchor.Center), style: null) - { - Color = new Color(12, 14, 15, 255) * 0.5f, - OutlineColor = Color.Black, - IgnoreLayoutGroups = true, - Visible = false - }; - serverPreview = new GUIListBox(new RectTransform(Vector2.One, serverPreviewContainer.RectTransform, Anchor.Center)) - { - Padding = Vector4.One * 10 * GUI.Scale, - HoverCursor = CursorState.Default, - OnSelected = (component, o) => false - }; - - // Spacing - new GUIFrame(new RectTransform(new Vector2(1.0f, 0.02f), bottomRow.RectTransform), style: null); - - var buttonContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.075f), bottomRow.RectTransform, Anchor.Center), isHorizontal: true) - { - RelativeSpacing = 0.02f, - Stretch = true - }; - - GUIButton button = new GUIButton(new RectTransform(new Vector2(0.25f, 0.9f), buttonContainer.RectTransform), - TextManager.Get("Back")) - { - OnClicked = GameMain.MainMenuScreen.ReturnToMainMenu - }; - - scanServersButton = new GUIButton(new RectTransform(new Vector2(0.25f, 0.9f), buttonContainer.RectTransform), - TextManager.Get("ServerListRefresh")) - { - OnClicked = (btn, userdata) => { RefreshServers(); return true; } - }; - - var directJoinButton = new GUIButton(new RectTransform(new Vector2(0.25f, 0.9f), buttonContainer.RectTransform), - TextManager.Get("serverlistdirectjoin")) - { - OnClicked = (btn, userdata) => - { - if (string.IsNullOrWhiteSpace(ClientNameBox.Text)) - { - ClientNameBox.Flash(); - ClientNameBox.Select(); - SoundPlayer.PlayUISound(GUISoundType.PickItemFail); - return false; - } - ShowDirectJoinPrompt(); - return true; - } - }; - - joinButton = new GUIButton(new RectTransform(new Vector2(0.25f, 0.9f), buttonContainer.RectTransform), - TextManager.Get("ServerListJoin")) - { - OnClicked = (btn, userdata) => - { - if (selectedServer != null) - { - if (selectedServer.LobbyID != 0) - { - Steam.SteamManager.JoinLobby(selectedServer.LobbyID, true); - } - else if (selectedServer.Endpoint != null) - { - JoinServer(selectedServer.Endpoint, selectedServer.ServerName); - } - else - { - new GUIMessageBox("", TextManager.Get("ServerOffline")); - return false; - } - } - return true; - }, - Enabled = false - }; - - buttonContainer.RectTransform.MinSize = new Point(0, (int)(buttonContainer.RectTransform.Children.Max(c => c.MinSize.Y) * 1.2f)); - - //-------------------------------------------------------- - - bottomRow.Recalculate(); - serverListHolder.Recalculate(); - serverListContainer.Recalculate(); - labelHolder.RectTransform.MaxSize = new Point(serverList.Content.Rect.Width, int.MaxValue); - labelHolder.Recalculate(); - - serverList.Content.RectTransform.SizeChanged += () => - { - labelHolder.RectTransform.MaxSize = new Point(serverList.Content.Rect.Width, int.MaxValue); - labelHolder.Recalculate(); - foreach (GUITextBlock labelText in labelTexts) - { - labelText.Text = ToolBox.LimitString(labelText.ToolTip, labelText.Font, labelText.Rect.Width); - } - RecalculateHolder(); - }; - - button.SelectedColor = button.Color; - refreshDisableTimer = DateTime.Now; - - //recent and favorite servers - ReadServerMemFromFile(recentServersFile, ref recentServers); - ReadServerMemFromFile(favoriteServersFile, ref favoriteServers); - recentServers.ForEach(s => s.Recent = true); - favoriteServers.ForEach(s => s.Favorite = true); - - SelectedTab = ServerListTab.All; - tabButtons[(int)selectedTab].Selected = true; - - RecalculateHolder(); - } - - - private static void LoadPlayStyleBanners() - { - //playstyle banners - playStyleBanners = new Sprite[Enum.GetValues(typeof(PlayStyle)).Length]; - PlayStyleColors = new Color[Enum.GetValues(typeof(PlayStyle)).Length]; - PlayStyleIcons = new Dictionary(); - PlayStyleIconColors = new Dictionary(); - - XDocument playStylesDoc = XMLExtensions.TryLoadXml("Content/UI/Server/PlayStyles.xml"); - - var rootElement = playStylesDoc.Root.FromPackage(ContentPackageManager.VanillaCorePackage); - foreach (var element in rootElement.Elements()) - { - switch (element.Name.ToString().ToLowerInvariant()) - { - case "playstylebanner": - if (Enum.TryParse(element.GetAttributeString("identifier", ""), out PlayStyle playStyle)) - { - PlayStyleBanners[(int)playStyle] = new Sprite(element, lazyLoad: true); - PlayStyleColors[(int)playStyle] = element.GetAttributeColor("color", Color.White); - } - break; - case "playstyleicon": - string identifier = element.GetAttributeString("identifier", ""); - if (string.IsNullOrEmpty(identifier)) { continue; } - PlayStyleIcons[identifier] = new Sprite(element, lazyLoad: true); - PlayStyleIconColors[identifier] = element.GetAttributeColor("color", Color.White); - break; - } - } - } - - private void ReadServerMemFromFile(string file, ref List servers) - { - if (servers == null) { servers = new List(); } - servers.Clear(); - - if (!File.Exists(file)) { return; } - - XDocument doc = XMLExtensions.TryLoadXml(file); - if (doc == null) - { - DebugConsole.NewMessage("Failed to load file \"" + file + "\". Attempting to recreate the file..."); - try - { - doc = new XDocument(new XElement("servers")); - doc.Save(file); - DebugConsole.NewMessage("Recreated \"" + file + "\"."); - } - catch (Exception e) - { - DebugConsole.ThrowError("Failed to recreate the file \"" + file + "\".", e); - } - return; - } - - bool saveCleanup = false; - foreach (XElement element in doc.Root.Elements()) - { - if (element.Name != "ServerInfo") { continue; } - var info = ServerInfo.FromXElement(element); - if (!servers.Any(s => s.Equals(info))) - { - servers.Add(info); - } - else - { - saveCleanup = true; - } - } - if (saveCleanup) { WriteServerMemToFile(file, servers); } - } - - private void WriteServerMemToFile(string file, List servers) - { - if (servers == null) { return; } - - XDocument doc = new XDocument(); - XElement rootElement = new XElement("servers"); - doc.Add(rootElement); - - foreach (ServerInfo info in servers) - { - rootElement.Add(info.ToXElement()); - } - - doc.SaveSafe(file); - } - - public ServerInfo UpdateServerInfoWithServerSettings(NetworkConnection connection, ServerSettings serverSettings) - { - bool isInfoNew = false; - ServerInfo info = serverList.Content.FindChild(d => (d.UserData is ServerInfo serverInfo) && - serverInfo.Endpoint == connection.Endpoint)?.UserData as ServerInfo; - if (info == null) - { - isInfoNew = true; - info = new ServerInfo(); - } - - info.ServerName = serverSettings.ServerName; - info.ServerMessage = serverSettings.ServerMessageText; - info.Endpoint = connection.Endpoint; - info.LobbyID = SteamManager.CurrentLobbyID; - info.GameMode = GameMain.NetLobbyScreen.SelectedMode?.Identifier ?? Identifier.Empty; - info.GameStarted = Screen.Selected != GameMain.NetLobbyScreen; - info.GameVersion = GameMain.Version.ToString(); - info.MaxPlayers = serverSettings.MaxPlayers; - info.PlayStyle = serverSettings.PlayStyle; - info.RespondedToSteamQuery = true; - info.TraitorsEnabled = serverSettings.TraitorsEnabled; - info.SubSelectionMode = serverSettings.SubSelectionMode; - info.ModeSelectionMode = serverSettings.ModeSelectionMode; - info.VoipEnabled = serverSettings.VoiceChatEnabled; - info.FriendlyFireEnabled = serverSettings.AllowFriendlyFire; - info.KarmaEnabled = serverSettings.KarmaEnabled; - info.PlayerCount = GameMain.Client.ConnectedClients.Count; - info.PingChecked = false; - info.HasPassword = serverSettings.HasPassword; - info.OwnerVerified = true; - - if (isInfoNew) - { - AddToServerList(info); - } - - return info; - } - - public void AddToRecentServers(ServerInfo info) - { - if (info.Endpoint is LidgrenEndpoint { NetEndpoint: { Address: var ip } } && IPAddress.IsLoopback(ip)) - { - return; - } - - info.Recent = true; - ServerInfo existingInfo = recentServers.Find(info.MatchesByEndpoint); - if (existingInfo == null) - { - recentServers.Add(info); - } - else - { - int index = recentServers.IndexOf(existingInfo); - recentServers[index] = info; - } - - WriteServerMemToFile(recentServersFile, recentServers); - } - - public bool IsFavorite(ServerInfo info) - { - return favoriteServers.Any(info.MatchesByEndpoint); - } - - public void AddToFavoriteServers(ServerInfo info) - { - info.Favorite = true; - ServerInfo existingInfo = favoriteServers.Find(info.MatchesByEndpoint); - if (existingInfo == null) - { - favoriteServers.Add(info); - } - else - { - int index = favoriteServers.IndexOf(existingInfo); - favoriteServers[index] = info; - } - - WriteServerMemToFile(favoriteServersFile, favoriteServers); - } - - public void RemoveFromFavoriteServers(ServerInfo info) - { - info.Favorite = false; - ServerInfo existingInfo = favoriteServers.Find(info.MatchesByEndpoint); - if (existingInfo != null) - { - favoriteServers.Remove(existingInfo); - WriteServerMemToFile(favoriteServersFile, favoriteServers); - } - } - - private bool SortList(GUIButton button, object obj) - { - if (!(obj is string sortBy)) { return false; } - SortList(sortBy, toggle: true); - return true; - } - - private void SortList(string sortBy, bool toggle) - { - if (!(labelHolder.GetChildByUserData(sortBy) is GUIButton button)) { return; } - - sortedBy = sortBy; - - var arrowUp = button.GetChildByUserData("arrowup"); - var arrowDown = button.GetChildByUserData("arrowdown"); - - //disable arrow buttons in other labels - foreach (var child in button.Parent.Children) - { - if (child != button) - { - child.GetChildByUserData("arrowup").Visible = false; - child.GetChildByUserData("arrowdown").Visible = false; - } - } - - bool ascending = arrowUp.Visible; - if (toggle) - { - ascending = !ascending; - } - - arrowUp.Visible = ascending; - arrowDown.Visible = !ascending; - serverList.Content.RectTransform.SortChildren((c1, c2) => - { - ServerInfo s1 = c1.GUIComponent.UserData as ServerInfo; - ServerInfo s2 = c2.GUIComponent.UserData as ServerInfo; - - if (s1 == null && s2 == null) - { - return 0; - } - else if (s1 == null) - { - return ascending ? 1 : -1; - } - else if (s2 == null) - { - return ascending ? -1 : 1; - } - - switch (sortBy) - { - case "ServerListCompatible": - bool? s1Compatible = NetworkMember.IsCompatible(GameMain.Version.ToString(), s1.GameVersion); - bool? s2Compatible = NetworkMember.IsCompatible(GameMain.Version.ToString(), s2.GameVersion); - - //convert to int to make sorting easier - //1 Compatible - //0 Unknown - //-1 Incompatible - int s1CompatibleInt = s1Compatible.HasValue ? - (s1Compatible.Value ? 1 : -1) : - 0; - int s2CompatibleInt = s2Compatible.HasValue ? - (s2Compatible.Value ? 1 : -1) : - 0; - return s2CompatibleInt.CompareTo(s1CompatibleInt) * (ascending ? 1 : -1); - case "ServerListHasPassword": - if (s1.HasPassword == s2.HasPassword) { return 0; } - return (s1.HasPassword ? 1 : -1) * (ascending ? 1 : -1); - case "ServerListName": - return string.Compare(s1.ServerName, s2.ServerName) * (ascending ? 1 : -1); - case "ServerListRoundStarted": - if (s1.GameStarted == s2.GameStarted) { return 0; } - return (s1.GameStarted ? 1 : -1) * (ascending ? 1 : -1); - case "ServerListPlayers": - return s2.PlayerCount.CompareTo(s1.PlayerCount) * (ascending ? 1 : -1); - case "ServerListPing": - return s2.Ping.CompareTo(s1.Ping) * (ascending ? 1 : -1); - default: - return 0; - } - }); - } - - public override void Select() - { - base.Select(); - - ContentPackagesByWorkshopId = ContentPackageManager.AllPackages - .Select(p => new KeyValuePair(p.SteamWorkshopId, p)) - .Where(p => p.Key != 0) - .GroupBy(x => x.Key).Select(g => g.First()) - .ToImmutableDictionary(); - ContentPackagesByHash = ContentPackageManager.AllPackages - .Select(p => new KeyValuePair(p.Hash.StringRepresentation, p)) - .GroupBy(x => x.Key).Select(g => g.First()) - .ToImmutableDictionary(); - - SelectedTab = ServerListTab.All; - GameMain.ServerListScreen.LoadServerFilters(); - if (GameSettings.CurrentConfig.ShowOffensiveServerPrompt) - { - var filterOffensivePrompt = new GUIMessageBox(string.Empty, TextManager.Get("filteroffensiveserversprompt"), new LocalizedString[] { TextManager.Get("yes"), TextManager.Get("no") }); - filterOffensivePrompt.Buttons[0].OnClicked = (btn, userData) => - { - filterOffensive.Selected = true; - filterOffensivePrompt.Close(); - return true; - }; - filterOffensivePrompt.Buttons[1].OnClicked = filterOffensivePrompt.Close; - - var config = GameSettings.CurrentConfig; - config.ShowOffensiveServerPrompt = false; - GameSettings.SetCurrentConfig(config); - } - - Steamworks.SteamMatchmaking.ResetActions(); - - if (GameMain.Client != null) - { - GameMain.Client.Quit(); - GameMain.Client = null; - } - - RefreshServers(); - } - - public override void Deselect() - { - ContentPackagesByWorkshopId = ImmutableDictionary.Empty; - ContentPackagesByHash = ImmutableDictionary.Empty; - base.Deselect(); - - GameSettings.SaveCurrentConfig(); - } - - public override void Update(double deltaTime) - { - base.Update(deltaTime); - - UpdateFriendsList(); - UpdateInfoQueries(); - - if (PlayerInput.PrimaryMouseButtonClicked()) - { - friendPopup = null; - if (friendsDropdown != null && friendsDropdownButton != null && - !friendsDropdown.Rect.Contains(PlayerInput.MousePosition) && - !friendsDropdownButton.Rect.Contains(PlayerInput.MousePosition)) - { - friendsDropdown.Visible = false; - } - } - } - - private void FilterServers() - { - serverList.Content.RemoveChild(serverList.Content.FindChild("noresults")); - - foreach (GUIComponent child in serverList.Content.Children) - { - if (!(child.UserData is ServerInfo serverInfo)) { continue; } - - Version remoteVersion = null; - if (!string.IsNullOrEmpty(serverInfo.GameVersion)) - { - Version.TryParse(serverInfo.GameVersion, out remoteVersion); - } - - //never show newer versions - //(ignore revision number, it doesn't affect compatibility) - if (remoteVersion != null && - ToolBox.VersionNewerIgnoreRevision(GameMain.Version, remoteVersion)) - { - child.Visible = false; - } - else - { - bool incompatible = - remoteVersion != null && !NetworkMember.IsCompatible(GameMain.Version, remoteVersion); - - var karmaFilterPassed = filterKarmaValue == TernaryOption.Any|| (filterKarmaValue == TernaryOption.Enabled) == serverInfo.KarmaEnabled; - var friendlyFireFilterPassed = filterFriendlyFireValue == TernaryOption.Any || (filterFriendlyFireValue == TernaryOption.Enabled) == serverInfo.FriendlyFireEnabled; - var traitorsFilterPassed = filterTraitorValue == TernaryOption.Any || (filterTraitorValue == TernaryOption.Enabled) == (serverInfo.TraitorsEnabled == YesNoMaybe.Yes || serverInfo.TraitorsEnabled == YesNoMaybe.Maybe); - var voipFilterPassed = filterVoipValue == TernaryOption.Any || (filterVoipValue == TernaryOption.Enabled) == serverInfo.VoipEnabled; - var moddedFilterPassed = filterModdedValue == TernaryOption.Any || (filterModdedValue == TernaryOption.Enabled) == serverInfo.GetPlayStyleTags().Any(t => t.Contains("modded.true")); - - child.Visible = - serverInfo.OwnerVerified && - serverInfo.ServerName.Contains(searchBox.Text, StringComparison.OrdinalIgnoreCase) && - (!filterSameVersion.Selected || (remoteVersion != null && NetworkMember.IsCompatible(remoteVersion, GameMain.Version))) && - (!filterPassword.Selected || !serverInfo.HasPassword) && - (!filterIncompatible.Selected || !incompatible) && - (!filterFull.Selected || serverInfo.PlayerCount < serverInfo.MaxPlayers) && - (!filterEmpty.Selected || serverInfo.PlayerCount > 0) && - (!filterOffensive.Selected || !ForbiddenWordFilter.IsForbidden(serverInfo.ServerName)) && - karmaFilterPassed && - friendlyFireFilterPassed && - traitorsFilterPassed && - voipFilterPassed && - moddedFilterPassed && - ((selectedTab == ServerListTab.All && (serverInfo.LobbyID != 0 || serverInfo.Endpoint != null)) || - (selectedTab == ServerListTab.Recent && serverInfo.Recent) || - (selectedTab == ServerListTab.Favorites && serverInfo.Favorite)); - } - - foreach (GUITickBox tickBox in playStyleTickBoxes.Values) - { - var playStyle = (PlayStyle)tickBox.UserData; - if (!tickBox.Selected && (serverInfo.PlayStyle == playStyle || !serverInfo.PlayStyle.HasValue)) - { - child.Visible = false; - break; - } - } - - foreach (GUITickBox tickBox in gameModeTickBoxes.Values) - { - var gameMode = (Identifier)tickBox.UserData; - if (!tickBox.Selected && serverInfo.GameMode != null && serverInfo.GameMode == gameMode) - { - child.Visible = false; - break; - } - } - } - - if (serverList.Content.Children.All(c => !c.Visible)) - { - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), serverList.Content.RectTransform), - TextManager.Get("NoMatchingServers")) - { - UserData = "noresults" - }; - } - - serverList.UpdateScrollBarSize(); - } - - private readonly Queue pendingQueries = new Queue(); - int activeQueries = 0; - private void QueueInfoQuery(ServerInfo info) - { - pendingQueries.Enqueue(info); - } - - private void OnQueryDone(ServerInfo info) - { - activeQueries--; - } - - public void UpdateInfoQueries() - { - while (activeQueries < 25 && pendingQueries.Count > 0) - { - activeQueries++; - var info = pendingQueries.Dequeue(); - info.QueryLiveInfo(UpdateServerInfo, OnQueryDone); - } - } - - private void ShowDirectJoinPrompt() - { - var msgBox = new GUIMessageBox(TextManager.Get("ServerListDirectJoin"), "", - new LocalizedString[] { TextManager.Get("ServerListJoin"), TextManager.Get("AddToFavorites"), TextManager.Get("Cancel") }, - relativeSize: new Vector2(0.25f, 0.2f), minSize: new Point(400, 150)); - msgBox.Content.ChildAnchor = Anchor.TopCenter; - - var content = new GUILayoutGroup(new RectTransform(new Vector2(0.8f, 0.5f), msgBox.Content.RectTransform), childAnchor: Anchor.TopCenter) - { - IgnoreLayoutGroups = false, - Stretch = true, - RelativeSpacing = 0.05f - }; - - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), content.RectTransform), TextManager.Get("ServerEndpoint"), textAlignment: Alignment.Center); - var endpointBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 0.5f), content.RectTransform)); - - content.RectTransform.NonScaledSize = new Point(content.Rect.Width, (int)(content.RectTransform.Children.Sum(c => c.Rect.Height))); - content.RectTransform.IsFixedSize = true; - msgBox.InnerFrame.RectTransform.MinSize = new Point(0, (int)((content.RectTransform.NonScaledSize.Y + msgBox.Content.RectTransform.Children.Sum(c => c.NonScaledSize.Y + msgBox.Content.AbsoluteSpacing)) * 1.1f)); - - var okButton = msgBox.Buttons[0]; - okButton.Enabled = false; - okButton.OnClicked = (btn, userdata) => - { - if (!(Endpoint.Parse(endpointBox.Text).TryUnwrap(out var endpoint))) { return false; } - JoinServer(endpoint, ""); - msgBox.Close(); - return false; - }; - - var favoriteButton = msgBox.Buttons[1]; - favoriteButton.Enabled = false; - favoriteButton.OnClicked = (button, userdata) => - { - if (!(Endpoint.Parse(endpointBox.Text).TryUnwrap(out var endpoint))) { return false; } - - ServerInfo serverInfo = new ServerInfo() - { - ServerName = "Server", - Endpoint = endpoint, - GameVersion = GameMain.Version.ToString(), - PlayStyle = null - }; - - var serverFrame = serverList.Content.FindChild(d => (d.UserData is ServerInfo info) && - info.MatchesByEndpoint(serverInfo)); - - if (serverFrame != null) - { - serverInfo = serverFrame.UserData as ServerInfo; - } - else - { - AddToServerList(serverInfo); - } - - AddToFavoriteServers(serverInfo); - - SelectedTab = ServerListTab.Favorites; - FilterServers(); - - QueueInfoQuery(serverInfo); - - msgBox.Close(); - return false; - }; - - var cancelButton = msgBox.Buttons[2]; - cancelButton.OnClicked = msgBox.Close; - - endpointBox.OnTextChanged += (textBox, text) => - { - okButton.Enabled = favoriteButton.Enabled = !string.IsNullOrEmpty(text); - return true; - }; - } - - private bool JoinFriend(GUIButton button, object userdata) - { - if (!(userdata is FriendInfo { InServer: true } info)) { return false; } - - GameMain.Instance.ConnectCommand = info.ConnectCommand; - return false; - } - - private bool OpenFriendPopup(GUIButton button, object userdata) - { - if (!(userdata is FriendInfo { InServer: true } info)) { return false; } - - if (info.InServer - && info.ConnectCommand is Some { Value: { EndpointOrLobby: var endpointOrLobby } } - && endpointOrLobby.TryGet(out ConnectCommand.NameAndEndpoint nameAndEndpoint)) - { - const int framePadding = 5; - - friendPopup = new GUIFrame(new RectTransform(Vector2.One, GUI.Canvas)); - - var serverNameText = new GUITextBlock(new RectTransform(new Vector2(0.7f, 1.0f), friendPopup.RectTransform, Anchor.CenterLeft), nameAndEndpoint.ServerName ?? "[Unnamed]"); - serverNameText.RectTransform.AbsoluteOffset = new Point(framePadding, 0); - - var joinButton = new GUIButton(new RectTransform(new Vector2(0.3f, 1.0f), friendPopup.RectTransform, Anchor.CenterRight), TextManager.Get("ServerListJoin")) - { - UserData = info - }; - joinButton.OnClicked = JoinFriend; - joinButton.RectTransform.AbsoluteOffset = new Point(framePadding, 0); - - Point joinButtonTextSize = joinButton.Font.MeasureString(joinButton.Text).ToPoint(); - int joinButtonHeight = joinButton.RectTransform.NonScaledSize.Y; - int totalAdditionalTextPadding = (joinButtonHeight - joinButtonTextSize.Y); - - // Make the final button sized so that the space between the text and the edges in the X direction is the same as the Y direction. - Point finalButtonSize = new Point(joinButtonTextSize.X + totalAdditionalTextPadding, joinButtonHeight); - - // Add padding to the server name to match the padding on the button text. - serverNameText.Padding = new Vector4(totalAdditionalTextPadding / 2); - - // Get the dimensions of the text we want to show, plus the extra padding we added. - Point serverNameSize = serverNameText.Font.MeasureString(serverNameText.Text).ToPoint() + new Point(totalAdditionalTextPadding, totalAdditionalTextPadding); - - // Now determine how large the parent frame has to be to exactly fit our two controls. - Point frameDims = new Point(serverNameSize.X + finalButtonSize.X + framePadding*2, Math.Max(serverNameSize.Y, finalButtonSize.Y) + framePadding * 2); - - var popupPos = PlayerInput.MousePosition.ToPoint(); - if(popupPos.X+frameDims.X > GUI.Canvas.NonScaledSize.X) - { - // Prevent the Join button from going off the end of the screen if the server name is long or we click a user towards the edge. - popupPos.X = GUI.Canvas.NonScaledSize.X - frameDims.X; - } - - // Apply the size and position changes. - friendPopup.RectTransform.NonScaledSize = frameDims; - friendPopup.RectTransform.RelativeOffset = Vector2.Zero; - friendPopup.RectTransform.AbsoluteOffset = popupPos; - - joinButton.RectTransform.NonScaledSize = finalButtonSize; - - friendPopup.RectTransform.RecalculateChildren(true); - friendPopup.RectTransform.SetPosition(Anchor.TopLeft); - } - - return false; - } - - private enum AvatarSize - { - Small, - Medium, - Large - } - - private void UpdateFriendsList() - { - if (!SteamManager.IsInitialized) { return; } - - if (friendsListUpdateTime > Timing.TotalTime) { return; } - friendsListUpdateTime = Timing.TotalTime + 5.0; - - float prevDropdownScroll = friendsDropdown?.ScrollBar.BarScrollValue ?? 0.0f; - - if (friendsDropdown == null) - { - friendsDropdown = new GUIListBox(new RectTransform(Vector2.One, GUI.Canvas)) - { - OutlineColor = Color.Black, - Visible = false - }; - } - friendsDropdown.ClearChildren(); - - AvatarSize avatarSize = AvatarSize.Large; - if (friendsButtonHolder.RectTransform.Rect.Height <= 24) - { - avatarSize = AvatarSize.Small; - } - else if (friendsButtonHolder.RectTransform.Rect.Height <= 48) - { - avatarSize = AvatarSize.Medium; - } - - List friends = Steamworks.SteamFriends.GetFriends().ToList(); - - for (int i = friendsList.Count - 1; i >= 0; i--) - { - var friend = friendsList[i]; - if (!friends.Any(g => g.Id == friend.SteamId && g.IsOnline)) - { - friend.Sprite?.Remove(); - friendsList.RemoveAt(i); - } - } - - foreach (var friend in friends) - { - if (!friend.IsOnline) { continue; } - - FriendInfo info = friendsList.Find(f => f.SteamId == friend.Id); - if (info == null) - { - info = new FriendInfo() - { - SteamId = friend.Id - }; - friendsList.Insert(0, info); - } - - if (info.Sprite == null) - { - Func> avatarFunc = null; - switch (avatarSize) - { - case AvatarSize.Small: - avatarFunc = Steamworks.SteamFriends.GetSmallAvatarAsync; - break; - case AvatarSize.Medium: - avatarFunc = Steamworks.SteamFriends.GetMediumAvatarAsync; - break; - case AvatarSize.Large: - avatarFunc = Steamworks.SteamFriends.GetLargeAvatarAsync; - break; - } - TaskPool.Add($"Get{avatarSize}AvatarAsync", avatarFunc(friend.Id), (task) => - { - if (!task.TryGetResult(out Steamworks.Data.Image? img)) { return; } - if (!img.HasValue) { return; } - - var avatarImage = img.Value; - - const int desaturatedWeight = 180; - - byte[] avatarData = (byte[])avatarImage.Data.Clone(); - for (int i = 0; i < avatarData.Length; i += 4) - { - int luma = (avatarData[i + 0] * 299 + avatarData[i + 1] * 587 + avatarData[i + 2] * 114) / 1000; - luma = (int)(luma * 0.7f + ((luma / 100.0f) * (luma / 255.0f) * 255.0f * 0.3f)); - int chn0 = ((avatarData[i + 0] * (255 - desaturatedWeight)) / 255) + ((luma * desaturatedWeight) / 255); - int chn1 = ((avatarData[i + 1] * (255 - desaturatedWeight)) / 255) + ((luma * desaturatedWeight) / 255); - int chn2 = ((avatarData[i + 2] * (255 - desaturatedWeight)) / 255) + ((luma * desaturatedWeight) / 255); - int chn3 = 255; - - chn0 = chn0 * chn3 / 255; - chn1 = chn1 * chn3 / 255; - chn2 = chn2 * chn3 / 255; - - avatarData[i + 0] = chn0 > 255 ? (byte)255 : (byte)chn0; - avatarData[i + 1] = chn1 > 255 ? (byte)255 : (byte)chn1; - avatarData[i + 2] = chn2 > 255 ? (byte)255 : (byte)chn2; - avatarData[i + 3] = chn3 > 255 ? (byte)255 : (byte)chn3; - } - CrossThread.RequestExecutionOnMainThread(() => - { - //TODO: create an avatar atlas? - var avatarTexture = new Texture2D(GameMain.Instance.GraphicsDevice, (int)avatarImage.Width, (int)avatarImage.Height); - avatarTexture.SetData(avatarData); - info.Sprite = new Sprite(avatarTexture, null, null); - }); - }); - } - - info.Name = friend.Name; - - info.ConnectCommand = Option.None(); - - info.PlayingThisGame = friend.IsPlayingThisGame; - info.PlayingAnotherGame = friend.GameInfo.HasValue; - - if (friend.IsPlayingThisGame) - { - info.StatusText = friend.GetRichPresence("status") ?? ""; - string connectCommand = friend.GetRichPresence("connect") ?? ""; - - try - { - info.ConnectCommand = ToolBox.ParseConnectCommand(ToolBox.SplitCommand(connectCommand)); - } - catch (IndexOutOfRangeException e) - { -#if DEBUG - DebugConsole.ThrowError($"Failed to parse a Steam friend's connect command ({connectCommand})", e); -#else - DebugConsole.Log($"Failed to parse a Steam friend's connect command ({connectCommand})\n" + e.StackTrace.CleanupStackTrace()); -#endif - info.ConnectCommand = Option.None(); - } - } - else - { - info.StatusText = TextManager.Get(info.PlayingAnotherGame ? "FriendPlayingAnotherGame" : "FriendNotPlaying"); - } - } - - friendsList.Sort((a, b) => - { - if (a.InServer && !b.InServer) { return -1; } - if (b.InServer && !a.InServer) { return 1; } - if (a.PlayingThisGame && !b.PlayingThisGame) { return -1; } - if (b.PlayingThisGame && !a.PlayingThisGame) { return 1; } - return 0; - }); - - friendsButtonHolder.ClearChildren(); - - if (friendsList.Count > 0) - { - friendsDropdownButton = new GUIButton(new RectTransform(Vector2.One, friendsButtonHolder.RectTransform, Anchor.BottomRight, Pivot.BottomRight, scaleBasis: ScaleBasis.BothHeight), "\u2022 \u2022 \u2022", style: "GUIButtonFriendsDropdown") - { - OnClicked = (button, udt) => - { - friendsDropdown.RectTransform.NonScaledSize = new Point(friendsButtonHolder.Rect.Height * 5 * 166 / 100, friendsButtonHolder.Rect.Height * 4 * 166 / 100); - friendsDropdown.RectTransform.AbsoluteOffset = new Point(friendsButtonHolder.Rect.X, friendsButtonHolder.Rect.Bottom); - friendsDropdown.RectTransform.RecalculateChildren(true); - friendsDropdown.Visible = !friendsDropdown.Visible; - return false; - } - }; - } - else - { - friendsDropdownButton = null; - friendsDropdown.Visible = false; - } - - int buttonCount = 0; - - for (int i = 0; i < friendsList.Count; i++) - { - var friend = friendsList[i]; - buttonCount++; - - if (buttonCount <= 5) - { - string style = "GUIButtonFriendNotPlaying"; - if (friend.InServer) - { - style = "GUIButtonFriendPlaying"; - } - else - { - style = friend.PlayingThisGame ? "GUIButtonFriendPlaying" : "GUIButtonFriendNotPlaying"; - } - - var guiButton = new GUIButton(new RectTransform(Vector2.One, friendsButtonHolder.RectTransform, scaleBasis: ScaleBasis.BothHeight), style: style) - { - UserData = friend, - OnClicked = OpenFriendPopup - }; - guiButton.ToolTip = friend.Name + "\n" + friend.StatusText; - - if (friend.Sprite != null) - { - static Color BrightenColor(Color color) - { - Vector3 hls = ToolBox.RgbToHLS(color); - hls.Y = hls.Y * 0.3f + 0.7f; - hls.Z = hls.Z * 0.6f + 0.4f; - - return ToolBox.HLSToRGB(hls); - } - - var imgColor = BrightenColor(guiButton.Color); - var imgHoverColor = BrightenColor(guiButton.HoverColor); - var imgSelectColor = BrightenColor(guiButton.SelectedColor); - var imgPressColor = BrightenColor(guiButton.PressedColor); - var guiImage = new GUIImage(new RectTransform(Vector2.One * 0.925f, guiButton.RectTransform, Anchor.Center) { RelativeOffset = new Vector2(0.025f, 0.025f) }, friend.Sprite, null, true) - { - Color = imgColor, - HoverColor = imgHoverColor, - SelectedColor = imgSelectColor, - PressedColor = imgPressColor, - CanBeFocused = false - }; - guiImage = new GUIImage(new RectTransform(Vector2.One * 0.925f, guiButton.RectTransform, Anchor.Center) { RelativeOffset = new Vector2(0.025f, 0.025f) }, friend.Sprite, null, true) - { - Color = Color.White * 0.8f, - HoverColor = Color.White * 0.8f, - SelectedColor = Color.White * 0.8f, - PressedColor = Color.White * 0.8f, - BlendState = BlendState.Additive, - CanBeFocused = false - }; - } - } - - var friendFrame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.167f), friendsDropdown.Content.RectTransform), style: "GUIFrameFriendsDropdown"); - var guiImage2TheSequel = new GUIImage(new RectTransform(Vector2.One * 0.9f, friendFrame.RectTransform, Anchor.CenterLeft, scaleBasis: ScaleBasis.BothHeight) { RelativeOffset = new Vector2(0.02f, 0.02f) } , friend.Sprite, null, true); - - var textBlock = new GUITextBlock(new RectTransform(Vector2.One * 0.8f, friendFrame.RectTransform, Anchor.CenterLeft, scaleBasis: ScaleBasis.BothHeight) { RelativeOffset = new Vector2(1.0f / 7.7f, 0.0f) }, friend.Name + "\n" + friend.StatusText) - { - Font = GUIStyle.SmallFont - }; - if (friend.PlayingThisGame) { textBlock.TextColor = GUIStyle.Green; } - if (friend.PlayingAnotherGame) { textBlock.TextColor = GUIStyle.Blue; } - - if (friend.InServer) - { - var joinButton = new GUIButton(new RectTransform(new Vector2(0.25f, 0.6f), friendFrame.RectTransform, Anchor.CenterRight) { RelativeOffset = new Vector2(0.05f, 0.0f) }, TextManager.Get("ServerListJoin"), style: "GUIButtonJoinFriend") - { - UserData = friend - }; - joinButton.OnClicked = JoinFriend; - } - } - - friendsDropdown.RectTransform.NonScaledSize = new Point(friendsButtonHolder.Rect.Height * 5 * 166 / 100, friendsButtonHolder.Rect.Height * 4 * 166 / 100); - friendsDropdown.RectTransform.AbsoluteOffset = new Point(friendsButtonHolder.Rect.X, friendsButtonHolder.Rect.Bottom); - friendsDropdown.RectTransform.RecalculateChildren(true); - - friendsDropdown.ScrollBar.BarScrollValue = prevDropdownScroll; - } - - private void RefreshServers() - { - if (waitingForRefresh) { return; } - - steamPingInfoReady = false; - - CoroutineManager.StopCoroutines("EstimateLobbyPing"); - - if (SteamManager.IsInitialized) - { - TaskPool.Add("WaitForPingDataAsync (serverlist)", Steamworks.SteamNetworkingUtils.WaitForPingDataAsync(), (task) => - { - steamPingInfoReady = true; - }); - } - - friendsListUpdateTime = Timing.TotalTime - 1.0; - UpdateFriendsList(); - - serverList.ClearChildren(); - serverPreview.Content.ClearChildren(); - joinButton.Enabled = false; - selectedServer = null; - - new GUITextBlock(new RectTransform(new Vector2(1.0f, 1.0f), serverList.Content.RectTransform), - TextManager.Get("RefreshingServerList"), textAlignment: Alignment.Center) - { - CanBeFocused = false - }; - - CoroutineManager.StartCoroutine(WaitForRefresh()); - } - - private IEnumerable WaitForRefresh() - { - waitingForRefresh = true; - if (refreshDisableTimer > DateTime.Now) - { - yield return new WaitForSeconds((float)(refreshDisableTimer - DateTime.Now).TotalSeconds); - } - - recentServers.Concat(favoriteServers).ForEach(si => si.OwnerVerified = false); - if (GameSettings.CurrentConfig.UseSteamMatchmaking) - { - serverList.ClearChildren(); - if (!SteamManager.GetServers(AddToServerList, ServerQueryFinished)) - { - serverList.ClearChildren(); - new GUITextBlock(new RectTransform(new Vector2(1.0f, 1.0f), serverList.Content.RectTransform), - TextManager.Get("ServerListNoSteamConnection"), textAlignment: Alignment.Center) - { - CanBeFocused = false - }; - scanServersButton.Enabled = false; - } - else - { - List knownServers = recentServers.Concat(favoriteServers).ToList(); - foreach (ServerInfo info in knownServers) - { - AddToServerList(info); - QueueInfoQuery(info); - } - scanServersButton.Enabled = true; - } - } - - refreshDisableTimer = DateTime.Now + AllowedRefreshInterval; - - yield return CoroutineStatus.Success; - } - - private GUIComponent FindFrameMatchingServerInfo(ServerInfo serverInfo) - => serverList.Content.FindChild(d => - d.UserData is ServerInfo info - && (info.LobbyID == 0 || info.LobbyID == serverInfo.LobbyID) - && info.OwnerVerified - && serverInfo.Endpoint == info.Endpoint); - - private void AddToServerList(ServerInfo serverInfo) - { - var serverFrame = FindFrameMatchingServerInfo(serverInfo); - - if (serverFrame == null) - { - serverFrame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.06f), serverList.Content.RectTransform) { MinSize = new Point(0, 35) }, - style: "ListBoxElement") - { - UserData = serverInfo - }; - new GUILayoutGroup(new RectTransform(new Vector2(0.98f, 1.0f), serverFrame.RectTransform, Anchor.Center), isHorizontal: true, childAnchor: Anchor.CenterLeft) - { - Stretch = true, - //RelativeSpacing = 0.02f - }; - } - else - { - int index = recentServers.IndexOf(serverFrame.UserData as ServerInfo); - if (index >= 0) - { - recentServers[index] = serverInfo; - serverInfo.Recent = true; - } - index = favoriteServers.IndexOf(serverFrame.UserData as ServerInfo); - if (index >= 0) - { - favoriteServers[index] = serverInfo; - serverInfo.Favorite = true; - } - } - serverFrame.UserData = serverInfo; - - if (serverInfo.OwnerVerified) - { - var childrenToRemove = serverList.Content.FindChildren(c => - c.UserData is ServerInfo info - && !ReferenceEquals(info, serverInfo) - && serverInfo.Endpoint == info.Endpoint).ToList(); - foreach (var child in childrenToRemove) - { - serverList.Content.RemoveChild(child); - } - } - - UpdateServerInfo(serverInfo); - - SortList(sortedBy, toggle: false); - FilterServers(); - } - - private void UpdateServerInfo(ServerInfo serverInfo) - { - var serverFrame = FindFrameMatchingServerInfo(serverInfo); - if (serverFrame == null) return; - - var serverContent = serverFrame.Children.First() as GUILayoutGroup; - serverContent.ClearChildren(); - - var compatibleBox = new GUITickBox(new RectTransform(new Vector2(columnRelativeWidth[0], 0.9f), serverContent.RectTransform, Anchor.Center), label: "") - { - CanBeFocused = false, - Selected = - (NetworkMember.IsCompatible(GameMain.Version.ToString(), serverInfo.GameVersion) ?? true), - UserData = "compatible" - }; - - var passwordBox = new GUITickBox(new RectTransform(new Vector2(columnRelativeWidth[1], 0.5f), serverContent.RectTransform, Anchor.Center), label: "", style: "GUIServerListPasswordTickBox") - { - ToolTip = TextManager.Get((serverInfo.HasPassword) ? "ServerListHasPassword" : "FilterPassword"), - Selected = serverInfo.HasPassword, - CanBeFocused = false, - UserData = "password" - }; - - var serverName = new GUITextBlock(new RectTransform(new Vector2(columnRelativeWidth[2] * 1.1f, 1.0f), serverContent.RectTransform), -#if DEBUG - (serverInfo.Endpoint is SteamP2PEndpoint ? "[STEAMP2P] " : "[LIDGREN] ") + -#endif - serverInfo.ServerName, - style: "GUIServerListTextBox"); - serverName.UserData = serverName.Text; - serverName.RectTransform.SizeChanged += () => - { - serverName.Text = ToolBox.LimitString(serverName.Text, serverName.Font, serverName.Rect.Width); - }; - - if (serverInfo.ContentPackageNames.Any()) - { - if (serverInfo.ContentPackageNames.Any(p => !GameMain.VanillaContent.NameMatches(p))) - { - serverName.TextColor = GUIStyle.ModdedServerColor; - } - } - - new GUITickBox(new RectTransform(new Vector2(columnRelativeWidth[3], 0.9f), serverContent.RectTransform, Anchor.Center), label: "") - { - ToolTip = TextManager.Get((serverInfo.GameStarted) ? "ServerListRoundStarted" : "ServerListRoundNotStarted"), - Selected = serverInfo.GameStarted, - CanBeFocused = false - }; - - var serverPlayers = new GUITextBlock(new RectTransform(new Vector2(columnRelativeWidth[4], 1.0f), serverContent.RectTransform), - serverInfo.PlayerCount + "/" + serverInfo.MaxPlayers, style: "GUIServerListTextBox", textAlignment: Alignment.Right) - { - ToolTip = TextManager.Get("ServerListPlayers") - }; - - var serverPingText = new GUITextBlock(new RectTransform(new Vector2(columnRelativeWidth[5], 1.0f), serverContent.RectTransform), "?", - style: "GUIServerListTextBox", textColor: Color.White * 0.5f, textAlignment: Alignment.Right) - { - ToolTip = TextManager.Get("ServerListPing") - }; - - if (serverInfo.PingChecked) - { - serverPingText.Text = serverInfo.Ping > -1 ? serverInfo.Ping.ToString() : "?"; - serverPingText.TextColor = GetPingTextColor(serverInfo.Ping); - } - else if (serverInfo.Endpoint is LidgrenEndpoint lidgrenEndpoint) - { - try - { - GetServerPing(serverInfo, serverPingText); - } - catch (NullReferenceException ex) - { - DebugConsole.ThrowError("Ping is null", ex); - } - } - else if (serverInfo.PingLocation != null) - { - CoroutineManager.StartCoroutine(EstimateLobbyPing(serverInfo, serverPingText), "EstimateLobbyPing"); - } - - if (serverInfo.LobbyID == 0) - { - LocalizedString toolTip = TextManager.Get("ServerOffline"); - serverContent.Children.ForEach(c => c.ToolTip = toolTip); - serverName.TextColor *= 0.8f; - serverPlayers.TextColor *= 0.8f; - } - else if (GameSettings.CurrentConfig.UseSteamMatchmaking && serverInfo.RespondedToSteamQuery.HasValue && serverInfo.RespondedToSteamQuery.Value == false) - { - LocalizedString toolTip = TextManager.Get("ServerListNoSteamQueryResponse"); - compatibleBox.Selected = false; - serverContent.Children.ForEach(c => c.ToolTip = toolTip); - serverName.TextColor *= 0.8f; - serverPlayers.TextColor *= 0.8f; - } - else if (string.IsNullOrEmpty(serverInfo.GameVersion) || !serverInfo.ContentPackageHashes.Any()) - { - compatibleBox.Selected = false; - new GUITextBlock(new RectTransform(new Vector2(0.8f, 0.8f), compatibleBox.Box.RectTransform, Anchor.Center), " ? ", GUIStyle.Orange * 0.85f, textAlignment: Alignment.Center) - { - ToolTip = TextManager.Get(string.IsNullOrEmpty(serverInfo.GameVersion) ? - "ServerListUnknownVersion" : - "ServerListUnknownContentPackage") - }; - } - else if (!compatibleBox.Selected) - { - LocalizedString toolTip = ""; - if (serverInfo.GameVersion != GameMain.Version.ToString()) - { - toolTip = TextManager.GetWithVariable("ServerListIncompatibleVersion", "[version]", serverInfo.GameVersion); - } - - int maxIncompatibleToList = 10; - List incompatibleModNames = new List(); - for (int i = 0; i < serverInfo.ContentPackageNames.Count; i++) - { - bool listAsIncompatible = !ContentPackageManager.EnabledPackages.All.Any(contentPackage => contentPackage.Hash.StringRepresentation == serverInfo.ContentPackageHashes[i]); - if (listAsIncompatible) - { - incompatibleModNames.Add(TextManager.GetWithVariables("ModNameAndHashFormat", - ("[name]", serverInfo.ContentPackageNames[i]), - ("[hash]", Md5Hash.GetShortHash(serverInfo.ContentPackageHashes[i])))); - - } - } - if (incompatibleModNames.Any()) - { - toolTip += '\n' + TextManager.Get("ModDownloadHeader") + "\n" + string.Join(", ", incompatibleModNames.Take(maxIncompatibleToList)); - if (incompatibleModNames.Count > maxIncompatibleToList) - { - toolTip += '\n' + TextManager.GetWithVariable("workshopitemdownloadprompttruncated", "[number]", (incompatibleModNames.Count - maxIncompatibleToList).ToString()); - } - } - serverContent.Children.ForEach(c => c.ToolTip = toolTip); - - serverName.TextColor *= 0.5f; - serverPlayers.TextColor *= 0.5f; - } - else - { - LocalizedString toolTip = ""; - for (int i = 0; i < serverInfo.ContentPackageNames.Count; i++) - { - if (ContentPackageManager.EnabledPackages.All.None(contentPackage => contentPackage.Hash.StringRepresentation == serverInfo.ContentPackageHashes[i])) - { - if (toolTip != "") { toolTip += "\n"; } - toolTip += TextManager.GetWithVariable("ServerListIncompatibleContentPackageWorkshopAvailable", "[contentpackage]", serverInfo.ContentPackageNames[i]); - break; - } - } - serverContent.Children.ForEach(c => c.ToolTip = toolTip); - } - - serverContent.Recalculate(); - - if (serverInfo.Favorite) - { - AddToFavoriteServers(serverInfo); - } - - SortList(sortedBy, toggle: false); - FilterServers(); - } - - private IEnumerable EstimateLobbyPing(ServerInfo serverInfo, GUITextBlock serverPingText) - { - while (!steamPingInfoReady) - { - yield return CoroutineStatus.Running; - } - - Steamworks.Data.NetPingLocation pingLocation = serverInfo.PingLocation.Value; - serverInfo.Ping = Steamworks.SteamNetworkingUtils.LocalPingLocation?.EstimatePingTo(pingLocation) ?? -1; - serverInfo.PingChecked = true; - serverPingText.TextColor = GetPingTextColor(serverInfo.Ping); - serverPingText.Text = serverInfo.Ping > -1 ? serverInfo.Ping.ToString() : "?"; - - yield return CoroutineStatus.Success; - } - - private void ServerQueryFinished() - { - if (!serverList.Content.Children.Any()) - { - new GUITextBlock(new RectTransform(Vector2.One, serverList.Content.RectTransform), - TextManager.Get("NoServers"), textAlignment: Alignment.Center) - { - CanBeFocused = false - }; - } - else if (serverList.Content.Children.All(c => !c.Visible)) - { - new GUITextBlock(new RectTransform(Vector2.One, serverList.Content.RectTransform), - TextManager.Get("NoMatchingServers"), textAlignment: Alignment.Center) - { - CanBeFocused = false, - UserData = "noresults" - }; - } - waitingForRefresh = false; - } - - private void MasterServerCallBack(IRestResponse response) - { - masterServerResponse = response; - masterServerResponded = true; - } - - private bool JoinServer(Endpoint endpoint, string serverName) - { - if (string.IsNullOrWhiteSpace(ClientNameBox.Text)) - { - ClientNameBox.Flash(); - ClientNameBox.Select(); - SoundPlayer.PlayUISound(GUISoundType.PickItemFail); - return false; - } - - MultiplayerPreferences.Instance.PlayerName = ClientNameBox.Text; - GameSettings.SaveCurrentConfig(); - - CoroutineManager.StartCoroutine(ConnectToServer(endpoint, serverName), "ConnectToServer"); - - return true; - } - - private IEnumerable ConnectToServer(Endpoint endpoint, string serverName) - { -#if !DEBUG - try - { -#endif - GameMain.Client = new GameClient(MultiplayerPreferences.Instance.PlayerName.FallbackNullOrEmpty(SteamManager.GetUsername()), endpoint, serverName, Option.None()); -#if !DEBUG - } - catch (Exception e) - { - DebugConsole.ThrowError("Failed to start the client", e); - } -#endif - - yield return CoroutineStatus.Success; - } - - private void GetServerPing(ServerInfo serverInfo, GUITextBlock serverPingText) - { - if (CoroutineManager.IsCoroutineRunning("ConnectToServer")) { return; } - if (!(serverInfo.Endpoint is LidgrenEndpoint { NetEndpoint: { Address: var address } })) { return; } - - lock (activePings) - { - if (activePings.ContainsKey(address)) { return; } - activePings.Add(address, activePings.Any() ? activePings.Values.Max()+1 : 0); - } - - serverInfo.PingChecked = false; - serverInfo.Ping = -1; - - TaskPool.Add($"PingServerAsync ({address})", PingServerAsync(address, 1000), - new Tuple(serverInfo, serverPingText), - (rtt, obj) => - { - var (info, text) = obj; - if (!rtt.TryGetResult(out info.Ping)) { info.Ping = -1; } - info.PingChecked = true; - text.TextColor = GetPingTextColor(info.Ping); - text.Text = info.Ping > -1 ? info.Ping.ToString() : "?"; - lock (activePings) - { - activePings.Remove(address); - } - }); - } - - private Color GetPingTextColor(int ping) - { - if (ping < 0) { return Color.DarkRed; } - return ToolBox.GradientLerp(ping / 200.0f, GUIStyle.Green, GUIStyle.Orange, GUIStyle.Red); - } - - public async Task PingServerAsync(IPAddress ipAddress, int timeOut) - { - await Task.Yield(); - bool shouldGo = false; - while (!shouldGo) - { - lock (activePings) - { - shouldGo = activePings.Count(kvp => kvp.Value < activePings[ipAddress]) < 25; - } - await Task.Delay(25); - } - - long rtt = -1; - if (ipAddress != null) - { - //don't attempt to ping if the address is IPv6 and it's not supported - if (ipAddress.AddressFamily != AddressFamily.InterNetworkV6 || Socket.OSSupportsIPv6) - { - Ping ping = new Ping(); - byte[] buffer = new byte[32]; - try - { - PingReply pingReply = ping.Send(ipAddress, timeOut, buffer, new PingOptions(128, true)); - - if (pingReply != null) - { - switch (pingReply.Status) - { - case IPStatus.Success: - rtt = pingReply.RoundtripTime; - break; - default: - rtt = -1; - break; - } - } - } - catch (Exception ex) - { - GameAnalyticsManager.AddErrorEventOnce("ServerListScreen.PingServer:PingException" + ipAddress, GameAnalyticsManager.ErrorSeverity.Warning, "Failed to ping a server - " + (ex?.InnerException?.Message ?? ex.Message)); -#if DEBUG - DebugConsole.NewMessage("Failed to ping a server (" + ipAddress + ") - " + (ex?.InnerException?.Message ?? ex.Message), Color.Red); -#endif - } - } - } - - return (int)rtt; - } - - public override void Draw(double deltaTime, GraphicsDevice graphics, SpriteBatch spriteBatch) - { - graphics.Clear(Color.CornflowerBlue); - - GameMain.TitleScreen.DrawLoadingText = false; - GameMain.MainMenuScreen.DrawBackground(graphics, spriteBatch); - - spriteBatch.Begin(SpriteSortMode.Deferred, null, GUI.SamplerState, null, GameMain.ScissorTestEnable); - - GUI.Draw(Cam, spriteBatch); - - spriteBatch.End(); - } - - public override void AddToGUIUpdateList() - { - menu.AddToGUIUpdateList(); - friendPopup?.AddToGUIUpdateList(); - friendsDropdown?.AddToGUIUpdateList(); - } - - public void StoreServerFilters() - { - foreach (KeyValuePair filterBox in filterTickBoxes) - { - ServerListFilters.Instance.SetAttribute(filterBox.Key, filterBox.Value.Selected.ToString()); - } - foreach (KeyValuePair ternaryFilter in ternaryFilters) - { - ServerListFilters.Instance.SetAttribute(ternaryFilter.Key, ternaryFilter.Value.SelectedData.ToString()); - } - } - - public void LoadServerFilters() - { - XDocument currentConfigDoc = XMLExtensions.TryLoadXml(GameSettings.PlayerConfigPath); - ServerListFilters.Init(currentConfigDoc.Root.GetChildElement("serverfilters")); - foreach (KeyValuePair filterBox in filterTickBoxes) - { - filterBox.Value.Selected = - ServerListFilters.Instance.GetAttributeBool(filterBox.Key, filterBox.Value.Selected); - } - foreach (KeyValuePair ternaryFilter in ternaryFilters) - { - TernaryOption ternaryOption = - ServerListFilters.Instance.GetAttributeEnum( - ternaryFilter.Key, - (TernaryOption)ternaryFilter.Value.SelectedData); - - var child = ternaryFilter.Value.ListBox.Content.GetChildByUserData(ternaryOption); - ternaryFilter.Value.Select(ternaryFilter.Value.ListBox.Content.GetChildIndex(child)); - } - } - - } -} diff --git a/Barotrauma/BarotraumaClient/ClientSource/Screens/ServerListScreen/PanelAnimator.cs b/Barotrauma/BarotraumaClient/ClientSource/Screens/ServerListScreen/PanelAnimator.cs new file mode 100644 index 000000000..f8cece982 --- /dev/null +++ b/Barotrauma/BarotraumaClient/ClientSource/Screens/ServerListScreen/PanelAnimator.cs @@ -0,0 +1,112 @@ +using System; +using Barotrauma.Extensions; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; + +namespace Barotrauma +{ + public class PanelAnimator + { + private readonly GUIScissorComponent container; + + private readonly GUIFrame leftFrame; + private readonly GUIComponent middleFrame; + private readonly GUIFrame rightFrame; + + private readonly GUIButton leftButton; + private readonly GUIButton rightButton; + + private float leftAnimState = 1.0f; + private float rightAnimState = 0.0f; + + public bool LeftEnabled + { + get => leftButton.Enabled; + set => leftButton.Enabled = value; + } + public bool RightEnabled + { + get => rightButton.Enabled; + set => rightButton.Enabled = value; + } + + public bool LeftVisible = true; + public bool RightVisible = false; + + public PanelAnimator(RectTransform rectTransform, GUIFrame leftFrame, GUIComponent middleFrame, GUIFrame rightFrame) + { + container = new GUIScissorComponent(rectTransform); + + this.leftFrame = leftFrame; + this.middleFrame = middleFrame; + this.rightFrame = rightFrame; + + void own(GUIComponent component) + { + component.RectTransform.Parent = container.Content.RectTransform; + component.RectTransform.Anchor = Anchor.TopLeft; + component.RectTransform.Pivot = Pivot.TopLeft; + + component.GetAllChildren().ForEach(dd => dd.RefreshListBoxParent()); + } + + GUIButton makeButton(Action action) + => new GUIButton(new RectTransform(new Vector2(0.01f, 1.0f), container.Content.RectTransform) + { MinSize = new Point(20, 0), MaxSize = new Point(int.MaxValue, (int)(150 * GUI.Scale)) }, + style: "UIToggleButton") + { + OnClicked = (_, __) => + { + action(); + return false; + } + }; + + own(leftFrame); + this.leftButton = makeButton(() => LeftVisible = !LeftVisible); + + own(middleFrame); + + this.rightButton = makeButton(() => RightVisible = !RightVisible); + own(rightFrame); + } + + public void Update() + { + if (!LeftEnabled) { LeftVisible = false; } + if (!RightEnabled) { RightVisible = false; } + + static void updateState(ref float state, bool visible) + => state = MathHelper.Lerp(state, visible ? 0.0f : 1.0f, 0.5f); + updateState(ref leftAnimState, LeftVisible); + updateState(ref rightAnimState, RightVisible); + + static int width(GUIComponent c) + => c.RectTransform.NonScaledSize.X; + + int height = container.RectTransform.NonScaledSize.Y; + int buttonY = height/2 - leftButton.RectTransform.NonScaledSize.Y/2; + + leftFrame.RectTransform.AbsoluteOffset = new Point((int)(-width(leftFrame) * leftAnimState), 0); + leftButton.RectTransform.AbsoluteOffset = leftFrame.RectTransform.AbsoluteOffset + + new Point(width(leftFrame), buttonY); + leftButton.Children.ForEach(c => c.SpriteEffects = LeftVisible + ? SpriteEffects.FlipHorizontally + : SpriteEffects.None); + + rightFrame.RectTransform.AbsoluteOffset = new Point((int)(width(container) + width(rightFrame) * (rightAnimState-1f)), 0); + rightButton.RectTransform.AbsoluteOffset = rightFrame.RectTransform.AbsoluteOffset + + new Point(-width(rightButton), buttonY); + rightButton.Children.ForEach(c => c.SpriteEffects = RightVisible + ? SpriteEffects.None + : SpriteEffects.FlipHorizontally); + + middleFrame.RectTransform.AbsoluteOffset = new Point( + leftButton.RectTransform.AbsoluteOffset.X + width(leftButton), + 0); + middleFrame.RectTransform.NonScaledSize = new Point( + rightButton.RectTransform.AbsoluteOffset.X - middleFrame.RectTransform.AbsoluteOffset.X, + height); + } + } +} \ No newline at end of file diff --git a/Barotrauma/BarotraumaClient/ClientSource/Screens/ServerListScreen/ServerListScreen.cs b/Barotrauma/BarotraumaClient/ClientSource/Screens/ServerListScreen/ServerListScreen.cs new file mode 100644 index 000000000..8e54407a4 --- /dev/null +++ b/Barotrauma/BarotraumaClient/ClientSource/Screens/ServerListScreen/ServerListScreen.cs @@ -0,0 +1,1676 @@ +using Barotrauma.Extensions; +using Barotrauma.IO; +using Barotrauma.Networking; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using System.Xml.Linq; + +namespace Barotrauma +{ + sealed class ServerListScreen : Screen + { + private enum MsgUserData + { + RefreshingServerList, + NoServers, + NoMatchingServers + } + + //how often the client is allowed to refresh servers + private static readonly TimeSpan AllowedRefreshInterval = TimeSpan.FromSeconds(3); + + private DateTime lastRefreshTime = DateTime.Now; + + private GUIFrame menu; + + private GUIListBox serverList; + private PanelAnimator panelAnimator; + private GUIFrame serverPreviewContainer; + private GUIListBox serverPreview; + + private GUIButton joinButton; + private Option selectedServer; + + private GUIButton scanServersButton; + + private enum TernaryOption + { + Any, + Enabled, + Disabled + } + + //friends list + public sealed class FriendInfo + { + public string Name; + + public readonly AccountId Id; + + public enum Status + { + Offline, + NotPlaying, + PlayingAnotherGame, + PlayingBarotrauma + } + + public readonly Status CurrentStatus; + + public string ServerName; + + public Option ConnectCommand; + public Option Avatar; + + public bool IsInServer + => CurrentStatus == Status.PlayingBarotrauma && ConnectCommand.IsSome(); + + public bool IsPlayingBarotrauma + => CurrentStatus == Status.PlayingBarotrauma; + + public bool PlayingAnotherGame + => CurrentStatus == Status.PlayingAnotherGame; + + public bool IsOnline + => CurrentStatus != Status.Offline; + + public LocalizedString StatusText + => CurrentStatus switch + { + Status.Offline => "", + _ when ConnectCommand.IsSome() + => TextManager.GetWithVariable("FriendPlayingOnServer", "[servername]", ServerName), + _ => TextManager.Get($"Friend{CurrentStatus}") + }; + + public FriendInfo(string name, AccountId id, Status status) + { + Name = name; + Id = id; + CurrentStatus = status; + ConnectCommand = Option.None(); + Avatar = Option.None(); + } + } + + private GUILayoutGroup friendsButtonHolder; + + private GUIButton friendsDropdownButton; + private GUIListBox friendsDropdown; + + private readonly FriendProvider friendProvider = new SteamFriendProvider(); + + private List friendsList; + private GUIFrame friendPopup; + private double friendsListUpdateTime; + + public enum TabEnum + { + All, + Favorites, + Recent + } + + public struct Tab + { + public readonly string Storage; + public readonly GUIButton Button; + + private readonly List servers; + public IReadOnlyList Servers => servers; + + public Tab(TabEnum tabEnum, ServerListScreen serverListScreen, GUILayoutGroup tabber, string storage) + { + Storage = storage; + servers = new List(); + Button = new GUIButton(new RectTransform(new Vector2(0.2f, 1.0f), tabber.RectTransform), + TextManager.Get($"ServerListTab.{tabEnum}"), style: "GUITabButton") + { + OnClicked = (_,__) => + { + serverListScreen.selectedTab = tabEnum; + return false; + } + }; + + Reload(); + } + + public void Reload() + { + if (Storage.IsNullOrEmpty()) { return; } + servers.Clear(); + XDocument doc = XMLExtensions.TryLoadXml(Storage, out _); + if (doc?.Root is null) { return; } + servers.AddRange(doc.Root.Elements().Select(ServerInfo.FromXElement).NotNone().Distinct()); + } + + public bool Contains(ServerInfo info) => servers.Contains(info); + public bool Remove(ServerInfo info) => servers.Remove(info); + public void AddOrUpdate(ServerInfo info) + { + servers.Remove(info); servers.Add(info); + } + + public void Clear() => servers.Clear(); + + public void Save() + { + XDocument doc = new XDocument(); + XElement rootElement = new XElement("servers"); + doc.Add(rootElement); + + foreach (ServerInfo info in servers) + { + rootElement.Add(info.ToXElement()); + } + + doc.SaveSafe(Storage); + } + } + + private readonly Dictionary tabs = new Dictionary(); + + private TabEnum _selectedTabBackingField; + private TabEnum selectedTab + { + get => _selectedTabBackingField; + set + { + _selectedTabBackingField = value; + tabs.ForEach(kvp => kvp.Value.Button.Selected = (value == kvp.Key)); + if (Screen.Selected == this) { RefreshServers(); } + } + } + + private readonly ServerProvider serverProvider + = new CompositeServerProvider(new SteamDedicatedServerProvider(), new SteamP2PServerProvider()); + + public GUITextBox ClientNameBox { get; private set; } + + enum ColumnLabel + { + ServerListCompatible, + ServerListHasPassword, + ServerListName, + ServerListRoundStarted, + ServerListPlayers, + ServerListPing + } + private struct Column + { + public float RelativeWidth; + public ColumnLabel Label; + + public static implicit operator Column((float W, ColumnLabel L) pair) => + new Column { RelativeWidth = pair.W, Label = pair.L }; + + public static Column[] Normalize(params Column[] columns) + { + var totalWidth = columns.Select(c => c.RelativeWidth).Aggregate((a, b) => a + b); + for (int i = 0; i < columns.Length; i++) + { + columns[i].RelativeWidth /= totalWidth; + } + return columns; + } + } + + private static readonly ImmutableDictionary columns = + Column.Normalize( + (0.1f, ColumnLabel.ServerListCompatible), + (0.1f, ColumnLabel.ServerListHasPassword), + (0.7f, ColumnLabel.ServerListName), + (0.12f, ColumnLabel.ServerListRoundStarted), + (0.08f, ColumnLabel.ServerListPlayers), + (0.08f, ColumnLabel.ServerListPing) + ).Select(c => (c.Label, c)).ToImmutableDictionary(); + + private GUILayoutGroup labelHolder; + private readonly List labelTexts = new List(); + + //filters + private GUITextBox searchBox; + private GUITickBox filterSameVersion; + private GUITickBox filterPassword; + private GUITickBox filterFull; + private GUITickBox filterEmpty; + private Dictionary ternaryFilters; + private Dictionary filterTickBoxes; + private Dictionary playStyleTickBoxes; + private Dictionary gameModeTickBoxes; + private GUITickBox filterOffensive; + + //GUIDropDown sends the OnSelected event before SelectedData is set, so we have to cache it manually. + private TernaryOption filterFriendlyFireValue = TernaryOption.Any; + private TernaryOption filterKarmaValue = TernaryOption.Any; + private TernaryOption filterTraitorValue = TernaryOption.Any; + private TernaryOption filterVoipValue = TernaryOption.Any; + private TernaryOption filterModdedValue = TernaryOption.Any; + + private ColumnLabel sortedBy; + + private const float sidebarWidth = 0.2f; + public ServerListScreen() + { + selectedServer = Option.None(); + GameMain.Instance.ResolutionChanged += CreateUI; + CreateUI(); + } + + private string GetDefaultUserName() + { + return friendProvider.GetUserName(); + } + + private void AddTernaryFilter(RectTransform parent, float elementHeight, Identifier tag, Action valueSetter) + { + var filterLayoutGroup = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, elementHeight), parent), isHorizontal: true) + { + Stretch = true + }; + + var box = new GUIFrame(new RectTransform(Vector2.One, filterLayoutGroup.RectTransform, Anchor.CenterLeft, scaleBasis: ScaleBasis.BothHeight) + { + IsFixedSize = true, + }, null) + { + HoverColor = Color.Gray, + SelectedColor = Color.DarkGray, + CanBeFocused = false + }; + if (box.RectTransform.MinSize.Y > 0) + { + box.RectTransform.MinSize = new Point(box.RectTransform.MinSize.Y); + box.RectTransform.Resize(box.RectTransform.MinSize); + } + Vector2 textBlockScale = new Vector2((float)(filterLayoutGroup.Rect.Width - filterLayoutGroup.Rect.Height) / (float)Math.Max(filterLayoutGroup.Rect.Width, 1.0), 1.0f); + + var filterLabel = new GUITextBlock(new RectTransform(new Vector2(0.6f, 1.0f) * textBlockScale, filterLayoutGroup.RectTransform, Anchor.CenterLeft), TextManager.Get("servertag." + tag + ".label"), textAlignment: Alignment.CenterLeft) + { + UserData = TextManager.Get($"servertag.{tag}.label") + }; + GUIStyle.Apply(filterLabel, "GUITextBlock", null); + + var dropDown = new GUIDropDown(new RectTransform(new Vector2(0.4f, 1.0f) * textBlockScale, filterLayoutGroup.RectTransform, Anchor.CenterLeft), elementCount: 3); + dropDown.AddItem(TextManager.Get("any"), TernaryOption.Any); + dropDown.AddItem(TextManager.Get($"servertag.{tag}.true"), TernaryOption.Enabled, TextManager.Get( + $"servertagdescription.{tag}.true")); + dropDown.AddItem(TextManager.Get($"servertag.{tag}.false"), TernaryOption.Disabled, TextManager.Get( + $"servertagdescription.{tag}.false")); + dropDown.SelectItem(TernaryOption.Any); + dropDown.OnSelected = (_, data) => { + valueSetter((TernaryOption)data); + FilterServers(); + StoreServerFilters(); + return true; + }; + + ternaryFilters.Add(tag, dropDown); + } + + private void CreateUI() + { + menu = new GUIFrame(new RectTransform(new Vector2(0.95f, 0.85f), GUI.Canvas, Anchor.Center) { MinSize = new Point(GameMain.GraphicsHeight, 0) }); + + var paddedFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.98f, 0.98f), menu.RectTransform, Anchor.Center)) + { + RelativeSpacing = 0.02f, + Stretch = true + }; + + //------------------------------------------------------------------------------------- + //Top row + //------------------------------------------------------------------------------------- + + var topRow = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.15f), paddedFrame.RectTransform)) { Stretch = true }; + + var title = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.33f), topRow.RectTransform), TextManager.Get("JoinServer"), font: GUIStyle.LargeFont) + { + Padding = Vector4.Zero, + ForceUpperCase = ForceUpperCase.Yes, + AutoScaleHorizontal = true + }; + + var infoHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.33f), topRow.RectTransform), isHorizontal: true, Anchor.BottomLeft) { RelativeSpacing = 0.01f, Stretch = false }; + + var clientNameHolder = new GUILayoutGroup(new RectTransform(new Vector2(sidebarWidth, 1.0f), infoHolder.RectTransform)) { RelativeSpacing = 0.05f }; + + new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), clientNameHolder.RectTransform), TextManager.Get("YourName"), font: GUIStyle.SubHeadingFont); + ClientNameBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 0.5f), clientNameHolder.RectTransform), "") + { + Text = MultiplayerPreferences.Instance.PlayerName, + MaxTextLength = Client.MaxNameLength, + OverflowClip = true + }; + + if (string.IsNullOrEmpty(ClientNameBox.Text)) + { + ClientNameBox.Text = GetDefaultUserName(); + } + ClientNameBox.OnTextChanged += (textbox, text) => + { + MultiplayerPreferences.Instance.PlayerName = text; + return true; + }; + + var tabButtonHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f - sidebarWidth - infoHolder.RelativeSpacing, 0.5f), infoHolder.RectTransform), isHorizontal: true); + + tabs[TabEnum.All] = new Tab(TabEnum.All, this, tabButtonHolder, ""); + tabs[TabEnum.Favorites] = new Tab(TabEnum.Favorites, this, tabButtonHolder, "Data/favoriteservers.xml"); + tabs[TabEnum.Recent] = new Tab(TabEnum.Recent, this, tabButtonHolder, "Data/recentservers.xml"); + + var friendsButtonFrame = new GUIFrame(new RectTransform(new Vector2(0.31f, 2.0f), tabButtonHolder.RectTransform, Anchor.BottomRight), style: "InnerFrame") + { + IgnoreLayoutGroups = true + }; + + friendsButtonHolder = new GUILayoutGroup(new RectTransform(new Vector2(0.98f, 0.9f), friendsButtonFrame.RectTransform, Anchor.Center), childAnchor: Anchor.TopLeft) { RelativeSpacing = 0.01f, IsHorizontal = true }; + friendsList = new List(); + + //------------------------------------------------------------------------------------- + // Bottom row + //------------------------------------------------------------------------------------- + + var bottomRow = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 1.0f - topRow.RectTransform.RelativeSize.Y), + paddedFrame.RectTransform, Anchor.CenterRight)) + { + Stretch = true + }; + + var serverListHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 1.0f), bottomRow.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterLeft) + { + OutlineColor = Color.Black + }; + + GUILayoutGroup serverListContainer = null; + GUIFrame filtersHolder = null; + + // filters ------------------------------------------- + + filtersHolder = new GUIFrame(new RectTransform(new Vector2(sidebarWidth, 1.0f), serverListHolder.RectTransform, Anchor.Center), style: null) + { + Color = new Color(12, 14, 15, 255) * 0.5f, + OutlineColor = Color.Black + }; + + float elementHeight = 0.05f; + var filterTitle = new GUITextBlock(new RectTransform(new Vector2(1.0f, elementHeight), filtersHolder.RectTransform), TextManager.Get("FilterServers"), font: GUIStyle.SubHeadingFont) + { + Padding = Vector4.Zero, + AutoScaleHorizontal = true, + CanBeFocused = false + }; + + var searchHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, elementHeight), filtersHolder.RectTransform) { RelativeOffset = new Vector2(0.0f, elementHeight) }, isHorizontal: true) { Stretch = true }; + + var searchTitle = new GUITextBlock(new RectTransform(new Vector2(0.001f, 1.0f), searchHolder.RectTransform), TextManager.Get("Search") + "..."); + searchBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 1.0f), searchHolder.RectTransform), ""); + searchBox.OnSelected += (sender, userdata) => { searchTitle.Visible = false; }; + searchBox.OnDeselected += (sender, userdata) => { searchTitle.Visible = true; }; + searchBox.OnTextChanged += (txtBox, txt) => { FilterServers(); return true; }; + + var filters = new GUIListBox(new RectTransform(new Vector2(0.98f, 1.0f - elementHeight * 2), filtersHolder.RectTransform, Anchor.BottomLeft)) + { + ScrollBarVisible = true, + Spacing = (int)(5 * GUI.Scale) + }; + + ternaryFilters = new Dictionary(); + filterTickBoxes = new Dictionary(); + + GUITickBox addTickBox(Identifier key, LocalizedString text = null, bool defaultState = false, bool addTooltip = false) + { + text ??= TextManager.Get(key); + var tickBox = new GUITickBox(new RectTransform(new Vector2(1.0f, elementHeight), filters.Content.RectTransform), text) + { + UserData = text, + Selected = defaultState, + ToolTip = addTooltip ? text : null, + OnSelected = (tickBox) => + { + FilterServers(); + StoreServerFilters(); + return true; + } + }; + filterTickBoxes.Add(key, tickBox); + return tickBox; + } + + filterSameVersion = addTickBox("FilterSameVersion".ToIdentifier(), defaultState: true); + filterPassword = addTickBox("FilterPassword".ToIdentifier()); + filterFull = addTickBox("FilterFullServers".ToIdentifier()); + filterEmpty = addTickBox("FilterEmptyServers".ToIdentifier()); + filterOffensive = addTickBox("FilterOffensiveServers".ToIdentifier()); + + // Filter Tags + new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), filters.Content.RectTransform), TextManager.Get("servertags"), font: GUIStyle.SubHeadingFont) + { + CanBeFocused = false + }; + + AddTernaryFilter(filters.Content.RectTransform, elementHeight, "karma".ToIdentifier(), (value) => { filterKarmaValue = value; }); + AddTernaryFilter(filters.Content.RectTransform, elementHeight, "traitors".ToIdentifier(), (value) => { filterTraitorValue = value; }); + AddTernaryFilter(filters.Content.RectTransform, elementHeight, "friendlyfire".ToIdentifier(), (value) => { filterFriendlyFireValue = value; }); + AddTernaryFilter(filters.Content.RectTransform, elementHeight, "voip".ToIdentifier(), (value) => { filterVoipValue = value; }); + AddTernaryFilter(filters.Content.RectTransform, elementHeight, "modded".ToIdentifier(), (value) => { filterModdedValue = value; }); + + // Play Style Selection + new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), filters.Content.RectTransform), TextManager.Get("ServerSettingsPlayStyle"), font: GUIStyle.SubHeadingFont) + { + CanBeFocused = false + }; + + playStyleTickBoxes = new Dictionary(); + foreach (PlayStyle playStyle in Enum.GetValues(typeof(PlayStyle))) + { + var selectionTick = addTickBox($"servertag.{playStyle}".ToIdentifier(), defaultState: true, addTooltip: true); + selectionTick.UserData = playStyle; + playStyleTickBoxes.Add($"servertag.{playStyle}".ToIdentifier(), selectionTick); + } + + // Game mode Selection + new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), filters.Content.RectTransform), TextManager.Get("gamemode"), font: GUIStyle.SubHeadingFont) { CanBeFocused = false }; + + gameModeTickBoxes = new Dictionary(); + foreach (GameModePreset mode in GameModePreset.List) + { + if (mode.IsSinglePlayer) { continue; } + + var selectionTick = addTickBox(mode.Identifier, mode.Name, defaultState: true, addTooltip: true); + selectionTick.UserData = mode.Identifier; + gameModeTickBoxes.Add(mode.Identifier, selectionTick); + } + + filters.Content.RectTransform.SizeChanged += () => + { + filters.Content.RectTransform.RecalculateChildren(true, true); + filterTickBoxes.ForEach(t => t.Value.Text = t.Value.UserData is LocalizedString lStr ? lStr : t.Value.UserData.ToString()); + gameModeTickBoxes.ForEach(tb => tb.Value.Text = tb.Value.ToolTip); + playStyleTickBoxes.ForEach(tb => tb.Value.Text = tb.Value.ToolTip); + GUITextBlock.AutoScaleAndNormalize( + filterTickBoxes.Values.Select(tb => tb.TextBlock) + .Concat(ternaryFilters.Values.Select(dd => dd.Parent.GetChild())), + defaultScale: 1.0f); + if (filterTickBoxes.Values.First().TextBlock.TextScale < 0.8f) + { + filterTickBoxes.ForEach(t => t.Value.TextBlock.TextScale = 1.0f); + filterTickBoxes.ForEach(t => t.Value.TextBlock.Text = ToolBox.LimitString(t.Value.TextBlock.Text, t.Value.TextBlock.Font, (int)(filters.Content.Rect.Width * 0.8f))); + } + }; + + // server list --------------------------------------------------------------------- + + serverListContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 1.0f), serverListHolder.RectTransform)) { Stretch = true }; + + labelHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), serverListContainer.RectTransform) { MinSize = new Point(0, 15) }, + isHorizontal: true, childAnchor: Anchor.BottomLeft) + { + Stretch = false + }; + + foreach (var column in columns.Values) + { + var label = TextManager.Get(column.Label.ToString()); + var btn = new GUIButton(new RectTransform(new Vector2(column.RelativeWidth, 1.0f), labelHolder.RectTransform), + text: label, textAlignment: Alignment.Center, style: "GUIButtonSmall") + { + ToolTip = label, + ForceUpperCase = ForceUpperCase.Yes, + UserData = column.Label, + OnClicked = SortList + }; + btn.Color *= 0.5f; + labelTexts.Add(btn.TextBlock); + + GUIImage arrowImg(object userData, SpriteEffects sprEffects) + => new GUIImage(new RectTransform(new Vector2(0.5f, 0.3f), btn.RectTransform, Anchor.BottomCenter, scaleBasis: ScaleBasis.BothHeight), style: "GUIButtonVerticalArrow", scaleToFit: true) + { + CanBeFocused = false, + UserData = userData, + SpriteEffects = sprEffects, + Visible = false + }; + + arrowImg("arrowup", SpriteEffects.None); + arrowImg("arrowdown", SpriteEffects.FlipVertically); + } + + serverList = new GUIListBox(new RectTransform(new Vector2(1.0f, 1.0f), serverListContainer.RectTransform, Anchor.Center)) + { + PlaySoundOnSelect = true, + ScrollBarVisible = true, + OnSelected = (btn, obj) => + { + if (!(obj is ServerInfo serverInfo)) { return false; } + + joinButton.Enabled = true; + selectedServer = Option.Some(serverInfo); + if (!serverPreviewContainer.Visible) + { + serverPreviewContainer.RectTransform.RelativeSize = new Vector2(sidebarWidth, 1.0f); + serverPreviewContainer.Visible = true; + serverPreviewContainer.IgnoreLayoutGroups = false; + } + serverInfo.CreatePreviewWindow(serverPreview.Content); + serverPreview.ForceLayoutRecalculation(); + panelAnimator.RightEnabled = true; + panelAnimator.RightVisible = true; + btn.Children.ForEach(c => c.SpriteEffects = serverPreviewContainer.Visible ? SpriteEffects.None : SpriteEffects.FlipHorizontally); + return true; + } + }; + + //server preview panel -------------------------------------------------- + serverPreviewContainer = new GUIFrame(new RectTransform(new Vector2(sidebarWidth, 1.0f), serverListHolder.RectTransform, Anchor.Center), style: null) + { + Color = new Color(12, 14, 15, 255) * 0.5f, + OutlineColor = Color.Black, + IgnoreLayoutGroups = true + }; + serverPreview = new GUIListBox(new RectTransform(Vector2.One, serverPreviewContainer.RectTransform, Anchor.Center)) + { + Padding = Vector4.One * 10 * GUI.Scale, + HoverCursor = CursorState.Default, + OnSelected = (component, o) => false + }; + + panelAnimator = new PanelAnimator(new RectTransform(Vector2.One, serverListHolder.RectTransform), + filtersHolder, + serverListContainer, + serverPreviewContainer); + panelAnimator.RightEnabled = false; + + // Spacing + new GUIFrame(new RectTransform(new Vector2(1.0f, 0.02f), bottomRow.RectTransform), style: null); + + var buttonContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.075f), bottomRow.RectTransform, Anchor.Center), isHorizontal: true) + { + RelativeSpacing = 0.02f, + Stretch = true + }; + + GUIButton button = new GUIButton(new RectTransform(new Vector2(0.25f, 0.9f), buttonContainer.RectTransform), + TextManager.Get("Back")) + { + OnClicked = GameMain.MainMenuScreen.ReturnToMainMenu + }; + + scanServersButton = new GUIButton(new RectTransform(new Vector2(0.25f, 0.9f), buttonContainer.RectTransform), + TextManager.Get("ServerListRefresh")) + { + OnClicked = (btn, userdata) => { RefreshServers(); return true; } + }; + + var directJoinButton = new GUIButton(new RectTransform(new Vector2(0.25f, 0.9f), buttonContainer.RectTransform), + TextManager.Get("serverlistdirectjoin")) + { + OnClicked = (btn, userdata) => + { + if (string.IsNullOrWhiteSpace(ClientNameBox.Text)) + { + ClientNameBox.Flash(); + ClientNameBox.Select(); + SoundPlayer.PlayUISound(GUISoundType.PickItemFail); + return false; + } + ShowDirectJoinPrompt(); + return true; + } + }; + + joinButton = new GUIButton(new RectTransform(new Vector2(0.25f, 0.9f), buttonContainer.RectTransform), + TextManager.Get("ServerListJoin")) + { + OnClicked = (btn, userdata) => + { + if (selectedServer.TryUnwrap(out var serverInfo)) + { + JoinServer(serverInfo.Endpoint, serverInfo.ServerName); + } + return true; + }, + Enabled = false + }; + + buttonContainer.RectTransform.MinSize = new Point(0, (int)(buttonContainer.RectTransform.Children.Max(c => c.MinSize.Y) * 1.2f)); + + //-------------------------------------------------------- + + bottomRow.Recalculate(); + serverListHolder.Recalculate(); + serverListContainer.Recalculate(); + labelHolder.RectTransform.MaxSize = new Point(serverList.Content.Rect.Width, int.MaxValue); + labelHolder.RectTransform.AbsoluteOffset = new Point((int)serverList.Padding.X, 0); + labelHolder.Recalculate(); + + serverList.Content.RectTransform.SizeChanged += () => + { + labelHolder.RectTransform.MaxSize = new Point(serverList.Content.Rect.Width, int.MaxValue); + labelHolder.RectTransform.AbsoluteOffset = new Point((int)serverList.Padding.X, 0); + labelHolder.Recalculate(); + foreach (GUITextBlock labelText in labelTexts) + { + labelText.Text = ToolBox.LimitString(labelText.ToolTip, labelText.Font, labelText.Rect.Width); + } + }; + + button.SelectedColor = button.Color; + + selectedTab = TabEnum.All; + } + + public void UpdateOrAddServerInfo(ServerInfo serverInfo) + { + GUIComponent existingElement = serverList.Content.FindChild(d => + d.UserData is ServerInfo existingServerInfo && + existingServerInfo.Endpoint == serverInfo.Endpoint); + if (existingElement == null) + { + AddToServerList(serverInfo); + } + else + { + existingElement.UserData = serverInfo; + } + } + + public void AddToRecentServers(ServerInfo info) + { + if (info.Endpoint.Address.IsLocalHost) { return; } + tabs[TabEnum.Recent].AddOrUpdate(info); + tabs[TabEnum.Recent].Save(); + } + + public bool IsFavorite(ServerInfo info) + => tabs[TabEnum.Favorites].Contains(info); + + public void AddToFavoriteServers(ServerInfo info) + { + tabs[TabEnum.Favorites].AddOrUpdate(info); + tabs[TabEnum.Favorites].Save(); + } + + public void RemoveFromFavoriteServers(ServerInfo info) + { + tabs[TabEnum.Favorites].Remove(info); + tabs[TabEnum.Favorites].Save(); + } + + private bool SortList(GUIButton button, object obj) + { + if (!(obj is ColumnLabel sortBy)) { return false; } + SortList(sortBy, toggle: true); + return true; + } + + private void SortList(ColumnLabel sortBy, bool toggle) + { + if (!(labelHolder.GetChildByUserData(sortBy) is GUIButton button)) { return; } + + sortedBy = sortBy; + + var arrowUp = button.GetChildByUserData("arrowup"); + var arrowDown = button.GetChildByUserData("arrowdown"); + + //disable arrow buttons in other labels + foreach (var child in button.Parent.Children) + { + if (child != button) + { + child.GetChildByUserData("arrowup").Visible = false; + child.GetChildByUserData("arrowdown").Visible = false; + } + } + + bool ascending = arrowUp.Visible; + if (toggle) + { + ascending = !ascending; + } + + arrowUp.Visible = ascending; + arrowDown.Visible = !ascending; + serverList.Content.RectTransform.SortChildren((c1, c2) => + { + if (!(c1.GUIComponent.UserData is ServerInfo s1)) { return 0; } + if (!(c2.GUIComponent.UserData is ServerInfo s2)) { return 0; } + + switch (sortBy) + { + case ColumnLabel.ServerListCompatible: + bool s1Compatible = NetworkMember.IsCompatible(GameMain.Version, s1.GameVersion); + bool s2Compatible = NetworkMember.IsCompatible(GameMain.Version, s2.GameVersion); + + if (s1Compatible == s2Compatible) { return 0; } + return (s1Compatible ? 1 : -1) * (ascending ? 1 : -1); + case ColumnLabel.ServerListHasPassword: + if (s1.HasPassword == s2.HasPassword) { return 0; } + return (s1.HasPassword ? 1 : -1) * (ascending ? 1 : -1); + case ColumnLabel.ServerListName: + // I think we actually want culture-specific sorting here? + return string.Compare(s1.ServerName, s2.ServerName, StringComparison.CurrentCulture) * (ascending ? 1 : -1); + case ColumnLabel.ServerListRoundStarted: + if (s1.GameStarted == s2.GameStarted) { return 0; } + return (s1.GameStarted ? 1 : -1) * (ascending ? 1 : -1); + case ColumnLabel.ServerListPlayers: + return s2.PlayerCount.CompareTo(s1.PlayerCount) * (ascending ? 1 : -1); + case ColumnLabel.ServerListPing: + return (s1.Ping.TryUnwrap(out var s1Ping), s2.Ping.TryUnwrap(out var s2Ping)) switch + { + (false, false) => 0, + (true, true) => s2Ping.CompareTo(s1Ping) * (ascending ? 1 : -1), + (false, true) => 1, + (true, false) => -1 + }; + default: + return 0; + } + }); + } + + public override void Select() + { + base.Select(); + + Steamworks.SteamMatchmaking.ResetActions(); + + selectedTab = TabEnum.All; + GameMain.ServerListScreen.LoadServerFilters(); + if (GameSettings.CurrentConfig.ShowOffensiveServerPrompt) + { + var filterOffensivePrompt = new GUIMessageBox(string.Empty, TextManager.Get("FilterOffensiveServersPrompt"), new LocalizedString[] { TextManager.Get("yes"), TextManager.Get("no") }); + filterOffensivePrompt.Buttons[0].OnClicked = (btn, userData) => + { + filterOffensive.Selected = true; + filterOffensivePrompt.Close(); + return true; + }; + filterOffensivePrompt.Buttons[1].OnClicked = filterOffensivePrompt.Close; + + var config = GameSettings.CurrentConfig; + config.ShowOffensiveServerPrompt = false; + GameSettings.SetCurrentConfig(config); + } + + if (GameMain.Client != null) + { + GameMain.Client.Quit(); + GameMain.Client = null; + } + + RefreshServers(); + } + + public override void Deselect() + { + base.Deselect(); + GameSettings.SaveCurrentConfig(); + } + + public override void Update(double deltaTime) + { + base.Update(deltaTime); + + UpdateFriendsList(); + panelAnimator?.Update(); + scanServersButton.Enabled = (DateTime.Now - lastRefreshTime) >= AllowedRefreshInterval; + + if (PlayerInput.PrimaryMouseButtonClicked()) + { + friendPopup = null; + if (friendsDropdown != null && friendsDropdownButton != null && + !friendsDropdown.Rect.Contains(PlayerInput.MousePosition) && + !friendsDropdownButton.Rect.Contains(PlayerInput.MousePosition)) + { + friendsDropdown.Visible = false; + } + } + } + + private void FilterServers() + { + RemoveMsgFromServerList(MsgUserData.NoMatchingServers); + foreach (GUIComponent child in serverList.Content.Children) + { + if (!(child.UserData is ServerInfo serverInfo)) { continue; } + child.Visible = ShouldShowServer(serverInfo); + } + + if (serverList.Content.Children.All(c => !c.Visible)) + { + PutMsgInServerList(MsgUserData.NoMatchingServers); + } + serverList.UpdateScrollBarSize(); + } + + private bool ShouldShowServer(ServerInfo serverInfo) + { +#if !DEBUG + //never show newer versions + //(ignore revision number, it doesn't affect compatibility) + if (ToolBox.VersionNewerIgnoreRevision(GameMain.Version, serverInfo.GameVersion)) + { + return false; + } +#endif + + if (!string.IsNullOrEmpty(searchBox.Text) && !serverInfo.ServerName.Contains(searchBox.Text, StringComparison.OrdinalIgnoreCase)) { return false; } + + if (filterSameVersion.Selected) + { + if (!NetworkMember.IsCompatible(serverInfo.GameVersion, GameMain.Version)) { return false; } + } + if (filterPassword.Selected) + { + if (serverInfo.HasPassword) { return false; } + } + if (filterFull.Selected) + { + if (serverInfo.PlayerCount >= serverInfo.MaxPlayers) { return false; } + } + if (filterEmpty.Selected) + { + if (serverInfo.PlayerCount <= 0) { return false; } + } + if (filterOffensive.Selected) + { + if (ForbiddenWordFilter.IsForbidden(serverInfo.ServerName)) { return false; } + } + + if (filterKarmaValue != TernaryOption.Any) + { + if (serverInfo.KarmaEnabled != (filterKarmaValue == TernaryOption.Enabled)) { return false; } + } + if (filterFriendlyFireValue != TernaryOption.Any) + { + if (serverInfo.FriendlyFireEnabled != (filterFriendlyFireValue == TernaryOption.Enabled)) { return false; } + } + if (filterTraitorValue != TernaryOption.Any) + { + if ((serverInfo.TraitorsEnabled == YesNoMaybe.Yes || serverInfo.TraitorsEnabled == YesNoMaybe.Maybe) != (filterTraitorValue == TernaryOption.Enabled)) + { + return false; + } + } + if (filterVoipValue != TernaryOption.Any) + { + if (serverInfo.VoipEnabled != (filterVoipValue == TernaryOption.Enabled)) { return false; } + } + if (filterModdedValue != TernaryOption.Any) + { + if (serverInfo.IsModded != (filterModdedValue == TernaryOption.Enabled)) { return false; } + } + + foreach (GUITickBox tickBox in playStyleTickBoxes.Values) + { + var playStyle = (PlayStyle)tickBox.UserData; + if (!tickBox.Selected && serverInfo.PlayStyle == playStyle) + { + return false; + } + } + + foreach (GUITickBox tickBox in gameModeTickBoxes.Values) + { + var gameMode = (Identifier)tickBox.UserData; + if (!tickBox.Selected && !serverInfo.GameMode.IsEmpty && serverInfo.GameMode == gameMode) + { + return false; + } + } + + return true; + } + + private void ShowDirectJoinPrompt() + { + var msgBox = new GUIMessageBox(TextManager.Get("ServerListDirectJoin"), "", + new LocalizedString[] { TextManager.Get("ServerListJoin"), TextManager.Get("AddToFavorites"), TextManager.Get("Cancel") }, + relativeSize: new Vector2(0.25f, 0.2f), minSize: new Point(400, 150)); + msgBox.Content.ChildAnchor = Anchor.TopCenter; + + var content = new GUILayoutGroup(new RectTransform(new Vector2(0.8f, 0.5f), msgBox.Content.RectTransform), childAnchor: Anchor.TopCenter) + { + IgnoreLayoutGroups = false, + Stretch = true, + RelativeSpacing = 0.05f + }; + + new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), content.RectTransform), TextManager.Get("ServerEndpoint"), textAlignment: Alignment.Center); + var endpointBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 0.5f), content.RectTransform)); + + content.RectTransform.NonScaledSize = new Point(content.Rect.Width, (int)(content.RectTransform.Children.Sum(c => c.Rect.Height))); + content.RectTransform.IsFixedSize = true; + msgBox.InnerFrame.RectTransform.MinSize = new Point(0, (int)((content.RectTransform.NonScaledSize.Y + msgBox.Content.RectTransform.Children.Sum(c => c.NonScaledSize.Y + msgBox.Content.AbsoluteSpacing)) * 1.1f)); + + var okButton = msgBox.Buttons[0]; + okButton.Enabled = false; + okButton.OnClicked = (btn, userdata) => + { + if (!Endpoint.Parse(endpointBox.Text).TryUnwrap(out var endpoint)) { return false; } + JoinServer(endpoint, ""); + msgBox.Close(); + return false; + }; + + var favoriteButton = msgBox.Buttons[1]; + favoriteButton.Enabled = false; + favoriteButton.OnClicked = (button, userdata) => + { + if (!Endpoint.Parse(endpointBox.Text).TryUnwrap(out var endpoint)) { return false; } + + var serverInfo = new ServerInfo(endpoint) + { + ServerName = "Server", + GameVersion = GameMain.Version + }; + + var serverFrame = serverList.Content.FindChild(d => + d.UserData is ServerInfo info + && info.Equals(serverInfo)); + + if (serverFrame != null) + { + serverInfo = (ServerInfo)serverFrame.UserData; + } + else + { + AddToServerList(serverInfo); + } + + AddToFavoriteServers(serverInfo); + + selectedTab = TabEnum.Favorites; + FilterServers(); + + #warning Interface with server providers to get up-to-date info on the given server + + msgBox.Close(); + return false; + }; + + var cancelButton = msgBox.Buttons[2]; + cancelButton.OnClicked = msgBox.Close; + + endpointBox.OnTextChanged += (textBox, text) => + { + okButton.Enabled = favoriteButton.Enabled = !string.IsNullOrEmpty(text); + return true; + }; + } + + private bool JoinFriend(GUIButton button, object userdata) + { + if (!(userdata is FriendInfo { IsInServer: true } info)) { return false; } + + GameMain.Instance.ConnectCommand = info.ConnectCommand; + return false; + } + + private bool OpenFriendPopup(GUIButton button, object userdata) + { + if (!(userdata is FriendInfo { IsInServer: true } info)) { return false; } + + if (info.IsInServer + && info.ConnectCommand is Some { Value: { EndpointOrLobby: var endpointOrLobby } } + && endpointOrLobby.TryGet(out ConnectCommand.NameAndEndpoint nameAndEndpoint)) + { + const int framePadding = 5; + + friendPopup = new GUIFrame(new RectTransform(Vector2.One, GUI.Canvas)); + + var serverNameText = new GUITextBlock(new RectTransform(new Vector2(0.7f, 1.0f), friendPopup.RectTransform, Anchor.CenterLeft), nameAndEndpoint.ServerName ?? "[Unnamed]"); + serverNameText.RectTransform.AbsoluteOffset = new Point(framePadding, 0); + + var joinButton = new GUIButton(new RectTransform(new Vector2(0.3f, 1.0f), friendPopup.RectTransform, Anchor.CenterRight), TextManager.Get("ServerListJoin")) + { + UserData = info + }; + joinButton.OnClicked = JoinFriend; + joinButton.RectTransform.AbsoluteOffset = new Point(framePadding, 0); + + Point joinButtonTextSize = joinButton.Font.MeasureString(joinButton.Text).ToPoint(); + int joinButtonHeight = joinButton.RectTransform.NonScaledSize.Y; + int totalAdditionalTextPadding = (joinButtonHeight - joinButtonTextSize.Y); + + // Make the final button sized so that the space between the text and the edges in the X direction is the same as the Y direction. + Point finalButtonSize = new Point(joinButtonTextSize.X + totalAdditionalTextPadding, joinButtonHeight); + + // Add padding to the server name to match the padding on the button text. + serverNameText.Padding = new Vector4(totalAdditionalTextPadding / 2); + + // Get the dimensions of the text we want to show, plus the extra padding we added. + Point serverNameSize = serverNameText.Font.MeasureString(serverNameText.Text).ToPoint() + new Point(totalAdditionalTextPadding, totalAdditionalTextPadding); + + // Now determine how large the parent frame has to be to exactly fit our two controls. + Point frameDims = new Point(serverNameSize.X + finalButtonSize.X + framePadding*2, Math.Max(serverNameSize.Y, finalButtonSize.Y) + framePadding * 2); + + var popupPos = PlayerInput.MousePosition.ToPoint(); + if(popupPos.X+frameDims.X > GUI.Canvas.NonScaledSize.X) + { + // Prevent the Join button from going off the end of the screen if the server name is long or we click a user towards the edge. + popupPos.X = GUI.Canvas.NonScaledSize.X - frameDims.X; + } + + // Apply the size and position changes. + friendPopup.RectTransform.NonScaledSize = frameDims; + friendPopup.RectTransform.RelativeOffset = Vector2.Zero; + friendPopup.RectTransform.AbsoluteOffset = popupPos; + + joinButton.RectTransform.NonScaledSize = finalButtonSize; + + friendPopup.RectTransform.RecalculateChildren(true); + friendPopup.RectTransform.SetPosition(Anchor.TopLeft); + } + + return false; + } + + public enum AvatarSize + { + Small, + Medium, + Large + } + + private void UpdateFriendsList() + { + if (friendsListUpdateTime > Timing.TotalTime) { return; } + friendsListUpdateTime = Timing.TotalTime + 5.0; + + float prevDropdownScroll = friendsDropdown?.ScrollBar.BarScrollValue ?? 0.0f; + + friendsDropdown ??= new GUIListBox(new RectTransform(Vector2.One, GUI.Canvas)) + { + OutlineColor = Color.Black, + Visible = false + }; + friendsDropdown.ClearChildren(); + + var avatarSize = friendsButtonHolder.RectTransform.Rect.Height switch + { + var h when h <= 24 => AvatarSize.Small, + var h when h <= 48 => AvatarSize.Medium, + _ => AvatarSize.Large + }; + + FriendInfo[] friends = friendProvider.RetrieveFriends(); + + foreach (var friend in friends) + { + int existingIndex = friendsList.FindIndex(f => f.Id == friend.Id); + if (existingIndex >= 0) + { + friend.Avatar = friend.Avatar.Fallback(friendsList[existingIndex].Avatar); + } + + if (friend.Avatar.IsNone()) + { + friendProvider.RetrieveAvatar(friend, avatarSize); + } + } + + friendsList.Clear(); friendsList.AddRange(friends.OrderByDescending(f => f.CurrentStatus)); + + friendsButtonHolder.ClearChildren(); + + if (friendsList.Count > 0) + { + friendsDropdownButton = new GUIButton(new RectTransform(Vector2.One, friendsButtonHolder.RectTransform, Anchor.BottomRight, Pivot.BottomRight, scaleBasis: ScaleBasis.BothHeight), "\u2022 \u2022 \u2022", style: "GUIButtonFriendsDropdown") + { + OnClicked = (button, udt) => + { + friendsDropdown.RectTransform.NonScaledSize = new Point(friendsButtonHolder.Rect.Height * 5 * 166 / 100, friendsButtonHolder.Rect.Height * 4 * 166 / 100); + friendsDropdown.RectTransform.AbsoluteOffset = new Point(friendsButtonHolder.Rect.X, friendsButtonHolder.Rect.Bottom); + friendsDropdown.RectTransform.RecalculateChildren(true); + friendsDropdown.Visible = !friendsDropdown.Visible; + return false; + } + }; + } + else + { + friendsDropdownButton = null; + friendsDropdown.Visible = false; + } + + for (int i = 0; i < friendsList.Count; i++) + { + var friend = friendsList[i]; + + if (i < 5) + { + string style = friend.IsPlayingBarotrauma + ? "GUIButtonFriendPlaying" + : "GUIButtonFriendNotPlaying"; + + var guiButton = new GUIButton(new RectTransform(Vector2.One, friendsButtonHolder.RectTransform, scaleBasis: ScaleBasis.BothHeight), style: style) + { + UserData = friend, + OnClicked = OpenFriendPopup + }; + guiButton.ToolTip = friend.Name + "\n" + friend.StatusText; + + if (friend.Avatar.TryUnwrap(out Sprite sprite)) + { + new GUICustomComponent(new RectTransform(Vector2.One, guiButton.RectTransform, Anchor.Center), + onDraw: (sb, component) => + { + var destinationRect = component.Rect; + destinationRect.Inflate(-GUI.IntScale(4), -GUI.IntScale(4)); + sb.Draw(sprite.Texture, destinationRect, Color.White); + + if (!GUI.IsMouseOn(guiButton)) + { + return; + } + + sb.End(); + sb.Begin( + SpriteSortMode.Deferred, + blendState: BlendState.Additive, + samplerState: GUI.SamplerState, + rasterizerState: GameMain.ScissorTestEnable); + sb.Draw(sprite.Texture, destinationRect, Color.White * 0.5f); + sb.End(); + sb.Begin( + SpriteSortMode.Deferred, + samplerState: GUI.SamplerState, + rasterizerState: GameMain.ScissorTestEnable); + }) { CanBeFocused = false }; + } + } + + var friendFrame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.167f), friendsDropdown.Content.RectTransform), style: "GUIFrameFriendsDropdown"); + if (friend.Avatar.TryUnwrap(out var avatar)) + { + GUIImage guiImage = + new GUIImage( + new RectTransform(Vector2.One * 0.9f, friendFrame.RectTransform, Anchor.CenterLeft, + scaleBasis: ScaleBasis.BothHeight) { RelativeOffset = new Vector2(0.02f, 0.02f) }, + avatar, null, true); + } + + var textBlock = new GUITextBlock(new RectTransform(Vector2.One * 0.8f, friendFrame.RectTransform, Anchor.CenterLeft, scaleBasis: ScaleBasis.BothHeight) { RelativeOffset = new Vector2(1.0f / 7.7f, 0.0f) }, friend.Name + "\n" + friend.StatusText) + { + Font = GUIStyle.SmallFont + }; + if (friend.IsPlayingBarotrauma) { textBlock.TextColor = GUIStyle.Green; } + if (friend.PlayingAnotherGame) { textBlock.TextColor = GUIStyle.Blue; } + + if (friend.IsInServer) + { + var joinButton = new GUIButton(new RectTransform(new Vector2(0.25f, 0.6f), friendFrame.RectTransform, Anchor.CenterRight) { RelativeOffset = new Vector2(0.05f, 0.0f) }, TextManager.Get("ServerListJoin"), style: "GUIButtonJoinFriend") + { + UserData = friend, + OnClicked = JoinFriend + }; + } + } + + friendsDropdown.RectTransform.NonScaledSize = new Point(friendsButtonHolder.Rect.Height * 5 * 166 / 100, friendsButtonHolder.Rect.Height * 4 * 166 / 100); + friendsDropdown.RectTransform.AbsoluteOffset = new Point(friendsButtonHolder.Rect.X, friendsButtonHolder.Rect.Bottom); + friendsDropdown.RectTransform.RecalculateChildren(true); + + friendsDropdown.ScrollBar.BarScrollValue = prevDropdownScroll; + } + + private void RemoveMsgFromServerList() + { + serverList.Content.Children + .Where(c => c.UserData is MsgUserData) + .ForEachMod(serverList.Content.RemoveChild); + } + + private void RemoveMsgFromServerList(MsgUserData userData) + { + serverList.Content.RemoveChild(serverList.Content.FindChild(userData)); + } + + private void PutMsgInServerList(MsgUserData userData) + { + RemoveMsgFromServerList(); + new GUITextBlock(new RectTransform(Vector2.One, serverList.Content.RectTransform), + TextManager.Get(userData.ToString()), textAlignment: Alignment.Center) + { + CanBeFocused = false, + UserData = userData + }; + } + + private void RefreshServers() + { + lastRefreshTime = DateTime.Now; + serverProvider.Cancel(); + currentServerDataRecvCallbackObj = null; + + PingUtils.QueryPingData(); + + tabs[TabEnum.All].Clear(); + serverList.ClearChildren(); + serverPreview.Content.ClearChildren(); + panelAnimator.RightEnabled = false; + joinButton.Enabled = false; + selectedServer = null; + + if (selectedTab == TabEnum.All) + { + PutMsgInServerList(MsgUserData.RefreshingServerList); + } + else + { + var servers = tabs[selectedTab].Servers.ToArray(); + foreach (var server in servers) + { + server.Ping = Option.None(); + AddToServerList(server, skipPing: true); + } + + if (!servers.Any()) + { + PutMsgInServerList(MsgUserData.NoServers); + return; + } + } + + var (onServerDataReceived, onQueryCompleted) = MakeServerQueryCallbacks(); + serverProvider.RetrieveServers(onServerDataReceived, onQueryCompleted); + } + + private GUIComponent FindFrameMatchingServerInfo(ServerInfo serverInfo) + { + bool matches(GUIComponent c) + => c.UserData is ServerInfo info + && info.Equals(serverInfo); + +#if DEBUG + if (serverList.Content.Children.Count(matches) > 1) + { + DebugConsole.ThrowError($"There are several entries in the server list for endpoint {serverInfo.Endpoint}"); + } +#endif + + return serverList.Content.FindChild(matches); + } + + private object currentServerDataRecvCallbackObj = null; + private (Action OnServerDataReceived, Action OnQueryCompleted) MakeServerQueryCallbacks() + { + var uniqueObject = new object(); + currentServerDataRecvCallbackObj = uniqueObject; + + bool shouldRunCallback() + { + // If currentServerDataRecvCallbackObj != uniqueObject, then one of the following happened: + // - The query this call is associated to was meant to be over + // - Another query was started before the one associated to this call was finished + // In either case, do not add the received info to the server list. + return ReferenceEquals(currentServerDataRecvCallbackObj, uniqueObject); + } + + return ( + serverInfo => + { + if (!shouldRunCallback()) { return; } + + if (selectedTab == TabEnum.All) + { + AddToServerList(serverInfo); + } + else + { + if (FindFrameMatchingServerInfo(serverInfo) == null) { return; } + UpdateServerInfoUI(serverInfo); + PingUtils.GetServerPing(serverInfo, UpdateServerInfoUI); + } + }, + () => + { + if (shouldRunCallback()) { ServerQueryFinished(); } + } + ); + } + + private void AddToServerList(ServerInfo serverInfo, bool skipPing = false) + { + RemoveMsgFromServerList(MsgUserData.RefreshingServerList); + RemoveMsgFromServerList(MsgUserData.NoServers); + var serverFrame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.06f), serverList.Content.RectTransform) { MinSize = new Point(0, 35) }, + style: "ListBoxElement") + { + UserData = serverInfo + }; + new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 1.0f), serverFrame.RectTransform, Anchor.Center), isHorizontal: true, childAnchor: Anchor.CenterLeft) + { + Stretch = false + }; + UpdateServerInfoUI(serverInfo); + if (!skipPing) { PingUtils.GetServerPing(serverInfo, UpdateServerInfoUI); } + + SortList(sortedBy, toggle: false); + FilterServers(); + } + + private void UpdateServerInfoUI(ServerInfo serverInfo) + { + var serverFrame = FindFrameMatchingServerInfo(serverInfo); + if (serverFrame == null) { return; } + + serverFrame.UserData = serverInfo; + + serverFrame.ToolTip = ""; + var serverContent = serverFrame.Children.First() as GUILayoutGroup; + serverContent.ClearChildren(); + + Dictionary sections = new Dictionary(); + foreach (ColumnLabel label in Enum.GetValues(typeof(ColumnLabel))) + { + sections[label] = + new GUIFrame( + new RectTransform(new Vector2(columns[label].RelativeWidth, 1.0f), serverContent.RectTransform), + style: null); + } + + void errorTooltip(RichString toolTip) + { + sections.Values.ForEach(c => + { + c.CanBeFocused = false; + c.Children.First().CanBeFocused = false; + }); + serverFrame.ToolTip = toolTip; + } + + RectTransform columnRT(ColumnLabel label, float scale = 0.95f) + => new RectTransform(Vector2.One * scale, sections[label].RectTransform, Anchor.Center); + + void sectionTooltip(ColumnLabel label, RichString toolTip) + { + var section = sections[label]; + section.CanBeFocused = true; + section.ToolTip = toolTip; + } + + var compatibleBox = new GUITickBox(columnRT(ColumnLabel.ServerListCompatible), label: "") + { + CanBeFocused = false, + Selected = + NetworkMember.IsCompatible(GameMain.Version, serverInfo.GameVersion), + UserData = "compatible" + }; + + var passwordBox = new GUITickBox(columnRT(ColumnLabel.ServerListHasPassword, scale: 0.6f), label: "", style: "GUIServerListPasswordTickBox") + { + Selected = serverInfo.HasPassword, + UserData = "password", + CanBeFocused = false + }; + sectionTooltip(ColumnLabel.ServerListHasPassword, + TextManager.Get((serverInfo.HasPassword) ? "ServerListHasPassword" : "FilterPassword")); + + var serverName = new GUITextBlock(columnRT(ColumnLabel.ServerListName), +#if DEBUG + $"[{serverInfo.Endpoint.GetType().Name}] " + +#endif + serverInfo.ServerName, + style: "GUIServerListTextBox") { CanBeFocused = false }; + + if (serverInfo.IsModded) + { + serverName.TextColor = GUIStyle.ModdedServerColor; + } + + new GUITickBox(columnRT(ColumnLabel.ServerListRoundStarted), label: "") + { + Selected = serverInfo.GameStarted, + CanBeFocused = false + }; + sectionTooltip(ColumnLabel.ServerListRoundStarted, + TextManager.Get(serverInfo.GameStarted ? "ServerListRoundStarted" : "ServerListRoundNotStarted")); + + var serverPlayers = new GUITextBlock(columnRT(ColumnLabel.ServerListPlayers), + $"{serverInfo.PlayerCount}/{serverInfo.MaxPlayers}", style: "GUIServerListTextBox", textAlignment: Alignment.Right) + { + ToolTip = TextManager.Get("ServerListPlayers") + }; + + var serverPingText = new GUITextBlock(columnRT(ColumnLabel.ServerListPing), "?", + style: "GUIServerListTextBox", textColor: Color.White * 0.5f, textAlignment: Alignment.Right) + { + ToolTip = TextManager.Get("ServerListPing") + }; + + if (serverInfo.Ping.TryUnwrap(out var ping)) + { + serverPingText.Text = ping.ToString(); + serverPingText.TextColor = GetPingTextColor(ping); + } + else + { + serverPingText.Text = "?"; + serverPingText.TextColor = Color.DarkRed; + } + + if (!serverInfo.Checked) + { + errorTooltip(TextManager.Get("ServerOffline")); + serverName.TextColor *= 0.8f; + serverPlayers.TextColor *= 0.8f; + } + else if (!serverInfo.ContentPackages.Any()) + { + compatibleBox.Selected = false; + new GUITextBlock(new RectTransform(new Vector2(0.8f, 0.8f), compatibleBox.Box.RectTransform, Anchor.Center), + " ? ", GUIStyle.Orange * 0.85f, textAlignment: Alignment.Center) + { + ToolTip = TextManager.Get("ServerListUnknownContentPackage") + }; + } + else if (!compatibleBox.Selected) + { + LocalizedString toolTip = ""; + if (serverInfo.GameVersion != GameMain.Version) + { + toolTip = TextManager.GetWithVariable("ServerListIncompatibleVersion", "[version]", serverInfo.GameVersion.ToString()); + } + + int maxIncompatibleToList = 10; + List incompatibleModNames = new List(); + foreach (var contentPackage in serverInfo.ContentPackages) + { + bool listAsIncompatible = !ContentPackageManager.EnabledPackages.All.Any(cp => cp.Hash.StringRepresentation == contentPackage.Hash); + if (listAsIncompatible) + { + incompatibleModNames.Add(TextManager.GetWithVariables("ModNameAndHashFormat", + ("[name]", contentPackage.Name), + ("[hash]", Md5Hash.GetShortHash(contentPackage.Hash)))); + } + } + if (incompatibleModNames.Any()) + { + toolTip += '\n' + TextManager.Get("ModDownloadHeader") + "\n" + string.Join(", ", incompatibleModNames.Take(maxIncompatibleToList)); + if (incompatibleModNames.Count > maxIncompatibleToList) + { + toolTip += '\n' + TextManager.GetWithVariable("workshopitemdownloadprompttruncated", "[number]", (incompatibleModNames.Count - maxIncompatibleToList).ToString()); + } + } + errorTooltip(toolTip); + + serverName.TextColor *= 0.5f; + serverPlayers.TextColor *= 0.5f; + } + else + { + LocalizedString toolTip = ""; + foreach (var contentPackage in serverInfo.ContentPackages) + { + if (ContentPackageManager.EnabledPackages.All.None(cp => cp.Hash.StringRepresentation == contentPackage.Hash)) + { + if (toolTip != "") { toolTip += "\n"; } + toolTip += TextManager.GetWithVariable("ServerListIncompatibleContentPackageWorkshopAvailable", "[contentpackage]", contentPackage.Name); + break; + } + } + errorTooltip(toolTip); + } + + foreach (var section in sections.Values) + { + var child = section.Children.First(); + child.RectTransform.ScaleBasis + = child is GUITextBlock ? ScaleBasis.Normal : ScaleBasis.BothHeight; + } + + // The next twenty-something lines are an optimization. + // The issue is that the serverlist has a ton of text elements, + // and resizing all of them is extremely expensive. However, since + // you don't see most of them most of the time, it makes sense to + // just resize them lazily based on when you actually can see them. + // That would entail a UI refactor of some kind, and I don't want to + // do that just yet, so here's a hack instead! + bool isDirty = true; + void markAsDirty() => isDirty = true; + serverContent.GetAllChildren().ForEach(c => + { + c.RectTransform.ResetSizeChanged(); + c.RectTransform.SizeChanged += markAsDirty; + }); + new GUICustomComponent(new RectTransform(Vector2.Zero, serverContent.RectTransform), onUpdate: (_, __) => + { + if (serverFrame.MouseRect.Height <= 0 || !isDirty) { return; } + serverContent.GetAllChildren().ForEach(c => + { + switch (c) + { + case GUITextBlock textBlock: + textBlock.SetTextPos(); + break; + case GUITickBox tickBox: + tickBox.ResizeBox(); + break; + } + }); + serverName.Text = ToolBox.LimitString(serverInfo.ServerName, serverName.Font, serverName.Rect.Width); + isDirty = false; + }); + // Hacky optimization ends here + + serverContent.Recalculate(); + + if (tabs[TabEnum.Favorites].Contains(serverInfo)) + { + AddToFavoriteServers(serverInfo); + } + + SortList(sortedBy, toggle: false); + FilterServers(); + } + + private void ServerQueryFinished() + { + currentServerDataRecvCallbackObj = null; + if (!serverList.Content.Children.Any(c => c.UserData is ServerInfo)) + { + PutMsgInServerList(MsgUserData.NoServers); + } + else if (serverList.Content.Children.All(c => !c.Visible)) + { + PutMsgInServerList(MsgUserData.NoMatchingServers); + } + } + + public void JoinServer(Endpoint endpoint, string serverName) + { + if (string.IsNullOrWhiteSpace(ClientNameBox.Text)) + { + ClientNameBox.Flash(); + ClientNameBox.Select(); + SoundPlayer.PlayUISound(GUISoundType.PickItemFail); + return; + } + + MultiplayerPreferences.Instance.PlayerName = ClientNameBox.Text; + GameSettings.SaveCurrentConfig(); + +#if !DEBUG + try + { +#endif + GameMain.Client = new GameClient(MultiplayerPreferences.Instance.PlayerName.FallbackNullOrEmpty(GetDefaultUserName()), endpoint, serverName, Option.None()); +#if !DEBUG + } + catch (Exception e) + { + DebugConsole.ThrowError("Failed to start the client", e); + } +#endif + } + + private Color GetPingTextColor(int ping) + { + if (ping < 0) { return Color.DarkRed; } + return ToolBox.GradientLerp(ping / 200.0f, GUIStyle.Green, GUIStyle.Orange, GUIStyle.Red); + } + + public override void Draw(double deltaTime, GraphicsDevice graphics, SpriteBatch spriteBatch) + { + graphics.Clear(Color.CornflowerBlue); + + GameMain.TitleScreen.DrawLoadingText = false; + GameMain.MainMenuScreen.DrawBackground(graphics, spriteBatch); + + spriteBatch.Begin(SpriteSortMode.Deferred, null, GUI.SamplerState, null, GameMain.ScissorTestEnable); + + GUI.Draw(Cam, spriteBatch); + + spriteBatch.End(); + } + + public override void AddToGUIUpdateList() + { + menu.AddToGUIUpdateList(); + friendPopup?.AddToGUIUpdateList(); + friendsDropdown?.AddToGUIUpdateList(); + } + + public void StoreServerFilters() + { + foreach (KeyValuePair filterBox in filterTickBoxes) + { + ServerListFilters.Instance.SetAttribute(filterBox.Key, filterBox.Value.Selected.ToString()); + } + foreach (KeyValuePair ternaryFilter in ternaryFilters) + { + ServerListFilters.Instance.SetAttribute(ternaryFilter.Key, ternaryFilter.Value.SelectedData.ToString()); + } + } + + public void LoadServerFilters() + { + XDocument currentConfigDoc = XMLExtensions.TryLoadXml(GameSettings.PlayerConfigPath); + ServerListFilters.Init(currentConfigDoc.Root.GetChildElement("serverfilters")); + foreach (KeyValuePair filterBox in filterTickBoxes) + { + filterBox.Value.Selected = + ServerListFilters.Instance.GetAttributeBool(filterBox.Key, filterBox.Value.Selected); + } + foreach (KeyValuePair ternaryFilter in ternaryFilters) + { + TernaryOption ternaryOption = + ServerListFilters.Instance.GetAttributeEnum( + ternaryFilter.Key, + (TernaryOption)ternaryFilter.Value.SelectedData); + + var child = ternaryFilter.Value.ListBox.Content.GetChildByUserData(ternaryOption); + ternaryFilter.Value.Select(ternaryFilter.Value.ListBox.Content.GetChildIndex(child)); + } + } + + } +} diff --git a/Barotrauma/BarotraumaClient/ClientSource/Screens/SubEditorScreen.cs b/Barotrauma/BarotraumaClient/ClientSource/Screens/SubEditorScreen.cs index 3178cff7e..9bff7dac0 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Screens/SubEditorScreen.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Screens/SubEditorScreen.cs @@ -1547,6 +1547,8 @@ namespace Barotrauma GUI.ForceMouseOn(null); + if (ImageManager.EditorMode) { GameSettings.SaveCurrentConfig(); } + MapEntityPrefab.Selected = null; saveFrame = null; @@ -1797,25 +1799,14 @@ namespace Barotrauma { Type subFileType = DetermineSubFileType(MainSub?.Info.Type ?? SubmarineType.Player); - void addSubAndSaveModProject(ModProject modProject, string filePath, string packagePath) + static string getExistingFilePath(ContentPackage package, string fileName) { - filePath = filePath.CleanUpPath(); - packagePath = packagePath.CleanUpPath(); - string packageDir = Path.GetDirectoryName(packagePath).CleanUpPathCrossPlatform(correctFilenameCase: false); - if (filePath.StartsWith(packageDir)) + if (Submarine.MainSub?.Info == null) { return null; } + if (package.Files.Any(f => f.Path == MainSub.Info.FilePath && Path.GetFileName(f.Path.Value) == fileName)) { - filePath = $"{ContentPath.ModDirStr}/{filePath[packageDir.Length..]}"; + return MainSub.Info.FilePath; } - if (!modProject.Files.Any(f => f.Type == subFileType && - f.Path == filePath)) - { - var newFile = ModProject.File.FromPath(filePath, subFileType); - modProject.AddFile(newFile); - } - - using var _ = Validation.SkipInDebugBuilds(); - modProject.DiscardHashAndInstallTime(); - modProject.Save(packagePath); + return null; } if (!GameMain.DebugDraw) @@ -1861,101 +1852,139 @@ namespace Barotrauma #if !DEBUG throw new InvalidOperationException("Cannot save to Vanilla package"); #endif - savePath = string.Format((MainSub?.Info.Type ?? SubmarineType.Player) switch - { - SubmarineType.Player => "Content/Submarines/{0}", - SubmarineType.Outpost => "Content/Map/Outposts/{0}", - SubmarineType.Ruin => "Content/Submarines/{0}", //we don't seem to use this anymore... - SubmarineType.Wreck => "Content/Map/Wrecks/{0}", - SubmarineType.BeaconStation => "Content/Map/BeaconStations/{0}", - SubmarineType.EnemySubmarine => "Content/Map/EnemySubmarines/{0}", - SubmarineType.OutpostModule => "Content/Map/Outposts/{0}", - _ => throw new InvalidOperationException() - }, savePath); + savePath = + getExistingFilePath(packageToSaveTo, savePath) ?? + string.Format((MainSub?.Info.Type ?? SubmarineType.Player) switch + { + SubmarineType.Player => "Content/Submarines/{0}", + SubmarineType.Outpost => "Content/Map/Outposts/{0}", + SubmarineType.Ruin => "Content/Submarines/{0}", //we don't seem to use this anymore... + SubmarineType.Wreck => "Content/Map/Wrecks/{0}", + SubmarineType.BeaconStation => "Content/Map/BeaconStations/{0}", + SubmarineType.EnemySubmarine => "Content/Map/EnemySubmarines/{0}", + SubmarineType.OutpostModule => "Content/Map/Outposts/{0}", + _ => throw new InvalidOperationException() + }, savePath); modProject.ModVersion = ""; } else { - savePath = Path.Combine(packageToSaveTo.Dir, savePath); + string existingFilePath = getExistingFilePath(packageToSaveTo, savePath); + //if we're trying to save a sub that's already included in the package with the same name as before, save directly in the same path + if (existingFilePath != null) + { + savePath = existingFilePath; + } + //otherwise make sure we're not trying to overwrite another sub in the same package + else + { + savePath = Path.Combine(packageToSaveTo.Dir, savePath); + if (File.Exists(savePath)) + { + var verification = new GUIMessageBox(TextManager.Get("warning"), TextManager.Get("subeditor.duplicatesubinpackage"), + new LocalizedString[] { TextManager.Get("yes"), TextManager.Get("no") }); + verification.Buttons[0].OnClicked = (_, _) => + { + addSubAndSave(modProject, savePath, fileListPath); + verification.Close(); + return true; + }; + verification.Buttons[1].OnClicked = verification.Close; + return false; + } + } } - addSubAndSaveModProject(modProject, savePath, fileListPath); - } - else if (MainSub?.Info?.FilePath != null - && MainSub.Info.Name != null - && MainSub.Info.FilePath.StartsWith(ContentPackage.LocalModsDir) - && MainSub.Info.Name.Equals(name, StringComparison.InvariantCultureIgnoreCase)) - { - prevSavePath = MainSub.Info.FilePath.CleanUpPath(); - ContentPackage contentPackage = GetLocalPackageThatOwnsSub(MainSub.Info); - if (contentPackage == null) - { - throw new InvalidOperationException($"Tried to overwrite a submarine ({name}) that's not in a local package!"); - } - ModProject modProject = new ModProject(contentPackage); - packageToSaveTo = contentPackage; - savePath = prevSavePath; - addSubAndSaveModProject(modProject, savePath, contentPackage.Path); + addSubAndSave(modProject, savePath, fileListPath); } else { savePath = Path.Combine(newLocalModDir, savePath); - ModProject modProject = new ModProject { Name = name }; - addSubAndSaveModProject(modProject, savePath, Path.Combine(Path.GetDirectoryName(savePath), ContentPackage.FileListFileName)); - } - savePath = savePath.CleanUpPathCrossPlatform(correctFilenameCase: false); - - if (MainSub != null) - { - Barotrauma.IO.Validation.SkipValidationInDebugBuilds = true; - if (previewImage?.Sprite?.Texture != null && !previewImage.Sprite.Texture.IsDisposed && MainSub.Info.Type != SubmarineType.OutpostModule) + if (File.Exists(savePath)) { - bool savePreviewImage = true; - using System.IO.MemoryStream imgStream = new System.IO.MemoryStream(); - try - { - previewImage.Sprite.Texture.SaveAsPng(imgStream, previewImage.Sprite.Texture.Width, previewImage.Sprite.Texture.Height); - } - catch (Exception e) - { - DebugConsole.ThrowError($"Saving the preview image of the submarine \"{MainSub.Info.Name}\" failed.", e); - savePreviewImage = false; - } - MainSub.TrySaveAs(savePath, savePreviewImage ? imgStream : null); + new GUIMessageBox(TextManager.Get("warning"), TextManager.GetWithVariable("subeditor.packagealreadyexists", "[name]", name)); + return false; } else { - MainSub.TrySaveAs(savePath); + ModProject modProject = new ModProject { Name = name }; + addSubAndSave(modProject, savePath, Path.Combine(Path.GetDirectoryName(savePath), ContentPackage.FileListFileName)); } - Barotrauma.IO.Validation.SkipValidationInDebugBuilds = false; + } - MainSub.CheckForErrors(); - - GUI.AddMessage(TextManager.GetWithVariable("SubSavedNotification", "[filepath]", savePath), GUIStyle.Green); - - if (savePath.StartsWith(newLocalModDir)) + void addSubAndSave(ModProject modProject, string filePath, string packagePath) + { + filePath = filePath.CleanUpPath(); + packagePath = packagePath.CleanUpPath(); + string packageDir = Path.GetDirectoryName(packagePath).CleanUpPathCrossPlatform(correctFilenameCase: false); + if (filePath.StartsWith(packageDir)) { - ContentPackageManager.LocalPackages.Refresh(); - var newPackage = ContentPackageManager.LocalPackages.FirstOrDefault(p => p.Path.StartsWith(newLocalModDir)); - if (newPackage is RegularPackage regular) + filePath = $"{ContentPath.ModDirStr}/{filePath[packageDir.Length..]}"; + } + if (!modProject.Files.Any(f => f.Type == subFileType && + f.Path == filePath)) + { + var newFile = ModProject.File.FromPath(filePath, subFileType); + modProject.AddFile(newFile); + } + + using var _ = Validation.SkipInDebugBuilds(); + modProject.DiscardHashAndInstallTime(); + modProject.Save(packagePath); + + savePath = savePath.CleanUpPathCrossPlatform(correctFilenameCase: false); + if (MainSub != null) + { + Barotrauma.IO.Validation.SkipValidationInDebugBuilds = true; + if (previewImage?.Sprite?.Texture != null && !previewImage.Sprite.Texture.IsDisposed && MainSub.Info.Type != SubmarineType.OutpostModule) { - ContentPackageManager.EnabledPackages.EnableRegular(regular); - GameSettings.SaveCurrentConfig(); + bool savePreviewImage = true; + using System.IO.MemoryStream imgStream = new System.IO.MemoryStream(); + try + { + previewImage.Sprite.Texture.SaveAsPng(imgStream, previewImage.Sprite.Texture.Width, previewImage.Sprite.Texture.Height); + } + catch (Exception e) + { + DebugConsole.ThrowError($"Saving the preview image of the submarine \"{MainSub.Info.Name}\" failed.", e); + savePreviewImage = false; + } + MainSub.TrySaveAs(savePath, savePreviewImage ? imgStream : null); } - } - if (packageToSaveTo != null) { ReloadModifiedPackage(packageToSaveTo); } - SubmarineInfo.RefreshSavedSub(savePath); - if (prevSavePath != null && prevSavePath != savePath) { SubmarineInfo.RefreshSavedSub(prevSavePath); } - MainSub.Info.PreviewImage = SubmarineInfo.SavedSubmarines.FirstOrDefault(s => s.FilePath == savePath)?.PreviewImage; + else + { + MainSub.TrySaveAs(savePath); + } + Barotrauma.IO.Validation.SkipValidationInDebugBuilds = false; - string downloadFolder = Path.GetFullPath(SaveUtil.SubmarineDownloadFolder); - linkedSubBox.ClearChildren(); - foreach (SubmarineInfo sub in SubmarineInfo.SavedSubmarines) - { - if (sub.Type != SubmarineType.Player) { continue; } - if (Path.GetDirectoryName(Path.GetFullPath(sub.FilePath)) == downloadFolder) { continue; } - linkedSubBox.AddItem(sub.Name, sub); + MainSub.CheckForErrors(); + + GUI.AddMessage(TextManager.GetWithVariable("SubSavedNotification", "[filepath]", savePath), GUIStyle.Green); + + if (savePath.StartsWith(newLocalModDir)) + { + ContentPackageManager.LocalPackages.Refresh(); + var newPackage = ContentPackageManager.LocalPackages.FirstOrDefault(p => p.Path.StartsWith(newLocalModDir)); + if (newPackage is RegularPackage regular) + { + ContentPackageManager.EnabledPackages.EnableRegular(regular); + GameSettings.SaveCurrentConfig(); + } + } + if (packageToSaveTo != null) { ReloadModifiedPackage(packageToSaveTo); } + SubmarineInfo.RefreshSavedSub(savePath); + if (prevSavePath != null && prevSavePath != savePath) { SubmarineInfo.RefreshSavedSub(prevSavePath); } + MainSub.Info.PreviewImage = SubmarineInfo.SavedSubmarines.FirstOrDefault(s => s.FilePath == savePath)?.PreviewImage; + + string downloadFolder = Path.GetFullPath(SaveUtil.SubmarineDownloadFolder); + linkedSubBox.ClearChildren(); + foreach (SubmarineInfo sub in SubmarineInfo.SavedSubmarines) + { + if (sub.Type != SubmarineType.Player) { continue; } + if (Path.GetDirectoryName(Path.GetFullPath(sub.FilePath)) == downloadFolder) { continue; } + linkedSubBox.AddItem(sub.Name, sub); + } + subNameLabel.Text = ToolBox.LimitString(MainSub.Info.Name, subNameLabel.Font, subNameLabel.Rect.Width); } - subNameLabel.Text = ToolBox.LimitString(MainSub.Info.Name, subNameLabel.Font, subNameLabel.Rect.Width); } return false; @@ -2735,40 +2764,31 @@ namespace Barotrauma new GUICustomComponent(new RectTransform(Vector2.Zero, saveInPackageLayout.RectTransform), onUpdate: (f, component) => { - bool canCreateNewPackage = true; foreach (GUIComponent contentChild in packageToSaveInList.Content.Children) { - contentChild.Visible = !(contentChild.UserData is ContentPackage p) - || !string.Equals(p.Name, nameBox.Text, StringComparison.OrdinalIgnoreCase); - canCreateNewPackage &= contentChild.Visible; contentChild.Visible &= !(contentChild.GetChild()?.GetChild() is GUITextBlock tb && !tb.Text.Contains(packToSaveInFilter.Text, StringComparison.OrdinalIgnoreCase)); } - - if (newPackageListIcon.Style.Identifier != "NewContentPackageIcon" && canCreateNewPackage) - { - GUIStyle.Apply(newPackageListIcon, "NewContentPackageIcon"); - newPackageListText.Text = TextManager.Get("CreateNewLocalPackage"); - } - if (newPackageListIcon.Style.Identifier != "WorkshopMenu.EditButton" && !canCreateNewPackage) - { - GUIStyle.Apply(newPackageListIcon, "WorkshopMenu.EditButton"); - newPackageListText.Text = TextManager.GetWithVariable("UpdateExistingLocalPackage", "[mod]", nameBox.Text); - } }); - packageToSaveInList.Select(0); ContentPackage ownerPkg = null; if (MainSub?.Info != null) { ownerPkg = GetLocalPackageThatOwnsSub(MainSub.Info); } foreach (var p in ContentPackageManager.LocalPackages) { - addItemToPackageToSaveList(p.Name, p); + var packageListItem = addItemToPackageToSaveList(p.Name, p); + if (p == ownerPkg) + { + var packageListIcon = packageListItem.GetChild(); + var packageListText = packageListItem.GetChild(); + GUIStyle.Apply(packageListIcon, "WorkshopMenu.EditButton"); + packageListText.Text = TextManager.GetWithVariable("UpdateExistingLocalPackage", "[mod]", p.Name); + } } - - if (ownerPkg != null && !string.Equals(ownerPkg.Name, nameBox.Text, StringComparison.OrdinalIgnoreCase)) + if (ownerPkg != null) { - packageToSaveInList.Select(ownerPkg); - packageToSaveInList.ScrollToElement(packageToSaveInList.SelectedComponent); + var element = packageToSaveInList.Content.FindChild(ownerPkg); + element?.RectTransform.SetAsFirstChild(); } + packageToSaveInList.Select(0); var requiredContentPackagesLayout = new GUILayoutGroup(new RectTransform(Vector2.One, horizontalArea.RectTransform, Anchor.BottomRight)) @@ -3424,7 +3444,8 @@ namespace Barotrauma { if (GetWorkshopPackageThatOwnsSub(selectedSubInfo) is ContentPackage workshopPackage) { - if (publishedWorkshopItemIds.Contains(workshopPackage.SteamWorkshopId)) + if (workshopPackage.TryExtractSteamWorkshopId(out var workshopId) + && publishedWorkshopItemIds.Contains(workshopId.Value)) { AskLoadPublishedSub(selectedSubInfo, workshopPackage); } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Serialization/SerializableEntityEditor.cs b/Barotrauma/BarotraumaClient/ClientSource/Serialization/SerializableEntityEditor.cs index 3040f674e..a63e7c905 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Serialization/SerializableEntityEditor.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Serialization/SerializableEntityEditor.cs @@ -380,6 +380,11 @@ namespace Barotrauma } LocalizedString toolTip = TextManager.Get($"sp.{propertyTag}.description"); + if (toolTip.IsNullOrEmpty() && entity.GetType() != property.PropertyInfo.DeclaringType) + { + Identifier propertyTagForDerivedClass = $"{entity.GetType().Name}.{property.PropertyInfo.Name}".ToIdentifier(); + toolTip = TextManager.Get($"{propertyTagForDerivedClass}.description", $"sp.{propertyTagForDerivedClass}.description"); + } if (toolTip.IsNullOrEmpty()) { toolTip = TextManager.Get($"{propertyTag}.description", $"sp.{fallbackTag}.description"); diff --git a/Barotrauma/BarotraumaClient/ClientSource/Sprite/Sprite.cs b/Barotrauma/BarotraumaClient/ClientSource/Sprite/Sprite.cs index 1b1aae8c0..82c294c6e 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Sprite/Sprite.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Sprite/Sprite.cs @@ -127,15 +127,22 @@ namespace Barotrauma } } - public void ReloadTexture(bool updateAllSprites = false) => ReloadTexture(updateAllSprites ? LoadedSprites.Where(s => s.texture == texture).ToList() : new List() { this }); - - public void ReloadTexture(IEnumerable spritesToUpdate) + public void ReloadTexture() { + var oldTexture = texture; texture.Dispose(); texture = TextureLoader.FromFile(FilePath.Value, Compress); - foreach (Sprite sprite in spritesToUpdate) + Identifier pathKey = FullPath.ToIdentifier(); + if (textureRefCounts.ContainsKey(pathKey)) { - sprite.texture = texture; + textureRefCounts[pathKey].Texture = texture; + } + foreach (Sprite sprite in LoadedSprites) + { + if (sprite.texture == oldTexture) + { + sprite.texture = texture; + } } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Steam/BulkDownloader.cs b/Barotrauma/BarotraumaClient/ClientSource/Steam/BulkDownloader.cs index 4a25ebe63..d572c3797 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Steam/BulkDownloader.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Steam/BulkDownloader.cs @@ -70,7 +70,9 @@ namespace Barotrauma.Steam (ContentPackage Package, bool IsUpToDate)[] outOfDatePackages = await Task.WhenAll(determiningTasks); return (await Task.WhenAll(outOfDatePackages.Where(p => !p.IsUpToDate) - .Select(async p => await SteamManager.Workshop.GetItem(p.Package.SteamWorkshopId)))) + .Select(p => p.Package.UgcId) + .OfType() + .Select(async id => await SteamManager.Workshop.GetItem(id.Value)))) .Where(p => p.HasValue).Select(p => p ?? default).ToArray(); } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Steam/Lobby.cs b/Barotrauma/BarotraumaClient/ClientSource/Steam/Lobby.cs index 7701c1469..54cab99e7 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Steam/Lobby.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Steam/Lobby.cs @@ -1,7 +1,5 @@ using Barotrauma.Networking; -using Microsoft.Xna.Framework; using System; -using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; @@ -102,7 +100,7 @@ namespace Barotrauma.Steam currentLobby?.SetData("contentpackage", string.Join(",", contentPackages.Select(cp => cp.Name))); currentLobby?.SetData("contentpackagehash", string.Join(",", contentPackages.Select(cp => cp.Hash.StringRepresentation))); - currentLobby?.SetData("contentpackageid", string.Join(",", contentPackages.Select(cp => cp.SteamWorkshopId))); + currentLobby?.SetData("contentpackageid", string.Join(",", contentPackages.Select(cp => cp.UgcId))); currentLobby?.SetData("modeselectionmode", serverSettings.ModeSelectionMode.ToString()); currentLobby?.SetData("subselectionmode", serverSettings.SubSelectionMode.ToString()); currentLobby?.SetData("voicechatenabled", serverSettings.VoiceChatEnabled.ToString()); @@ -152,275 +150,5 @@ namespace Barotrauma.Steam } }); } - - public static bool GetServers(Action addToServerList, Action serverQueryFinished) - { - if (!IsInitialized) { return false; } - - int doneTasks = 0; - void taskDone() - { - doneTasks++; - if (doneTasks >= 2) - { - serverQueryFinished?.Invoke(); - serverQueryFinished = null; - } - } - - - Steamworks.Dispatch.OnDebugCallback = (callbackType, contents, isServer) => - { - DebugConsole.NewMessage($"{callbackType}: " + contents, Color.Yellow); - }; - - TaskPool.Add("LobbyQueryRequest", LobbyQueryRequest(), - (t) => - { - Steamworks.Dispatch.OnDebugCallback = null; - if (t.Status == TaskStatus.Faulted) - { - TaskPool.PrintTaskExceptions(t, "Failed to retrieve SteamP2P lobbies"); - taskDone(); - return; - } - var lobbies = ((Task>)t).Result; - if (lobbies != null) - { - foreach (var lobby in lobbies) - { - if (string.IsNullOrEmpty(lobby.GetData("name"))) { continue; } - - ServerInfo serverInfo = new ServerInfo - { - ServerName = lobby.GetData("name"), - Endpoint = new SteamP2PEndpoint(SteamId.Parse(lobby.GetData("lobbyowner")).Fallback(default(SteamId))), - LobbyID = lobby.Id, - RespondedToSteamQuery = true - }; - bool.TryParse(lobby.GetData("haspassword"), out serverInfo.HasPassword); - serverInfo.PlayerCount = int.TryParse(lobby.GetData("playercount"), out int playerCount) ? playerCount : 0; - serverInfo.MaxPlayers = int.TryParse(lobby.GetData("maxplayernum"), out int maxPlayers) ? maxPlayers : 1; - - AssignLobbyDataToServerInfo(lobby, serverInfo); - - addToServerList(serverInfo); - } - } - taskDone(); - }); - - Steamworks.ServerList.Internet serverQuery = new Steamworks.ServerList.Internet(); - void onServer(Steamworks.Data.ServerInfo info, bool responsive) - { - if (string.IsNullOrEmpty(info.Name)) { return; } - - ServerInfo serverInfo = new ServerInfo - { - ServerName = info.Name, - HasPassword = info.Passworded, - Endpoint = new LidgrenEndpoint(info.Address, info.ConnectionPort), - PlayerCount = info.Players, - MaxPlayers = info.MaxPlayers, - RespondedToSteamQuery = responsive - }; - - if (responsive) - { - TaskPool.Add($"QueryServerRules (GetServers, {info.Name}, {info.Address})", info.QueryRulesAsync(), - (t) => - { - if (t.Status == TaskStatus.Faulted) - { - TaskPool.PrintTaskExceptions(t, "Failed to retrieve rules for " + info.Name); - return; - } - - var rules = ((Task>)t).Result; - AssignServerRulesToServerInfo(rules, serverInfo); - - CrossThread.RequestExecutionOnMainThread(() => - { - addToServerList(serverInfo); - }); - }); - } - else - { - CrossThread.RequestExecutionOnMainThread(() => - { - addToServerList(serverInfo); - }); - } - - } - serverQuery.OnResponsiveServer += (info) => onServer(info, true); - serverQuery.OnUnresponsiveServer += (info) => onServer(info, false); - - TaskPool.Add("RunServerQuery", serverQuery.RunQueryAsync(), - (t) => - { - serverQuery.Dispose(); - taskDone(); - if (t.Status == TaskStatus.Faulted) - { - TaskPool.PrintTaskExceptions(t, "Failed to retrieve servers"); - return; - } - }); - - return true; - } - - public static async Task> LobbyQueryRequest() - { - List allLobbies = new List(); - Steamworks.Data.LobbyQuery lobbyQuery = Steamworks.SteamMatchmaking.CreateLobbyQuery() - .FilterDistanceWorldwide() - .WithMaxResults(50); - //steamworks seems to unable to retrieve more than 50 - //lobbies per request; to work around this, we'll make - //up to 10 requests, asking to ignore all previous results - //in each subsequent request - for (int i = 0; i < 10; i++) - { - Steamworks.Data.Lobby[] lobbies = await lobbyQuery.RequestAsync(); - if (lobbies == null) { break; } - foreach (var l in lobbies) - { - lobbyQuery = lobbyQuery - .WithoutKeyValue("lobbyowner", l.GetData("lobbyowner")); - } - allLobbies.AddRange(lobbies); - } - - //make sure all returned lobbies are distinct, don't want any duplicates here - return allLobbies.Select(l => l.Id).Distinct().Select(i => allLobbies.Find(l => l.Id == i)).ToList(); - } - - public static void AssignLobbyDataToServerInfo(Steamworks.Data.Lobby lobby, ServerInfo serverInfo) - { - serverInfo.OwnerVerified = true; - - serverInfo.ServerMessage = lobby.GetData("message"); - serverInfo.GameVersion = lobby.GetData("version"); - - serverInfo.ContentPackageNames.AddRange(lobby.GetData("contentpackage").Split(',')); - serverInfo.ContentPackageHashes.AddRange(lobby.GetData("contentpackagehash").Split(',')); - - string workshopIdData = lobby.GetData("contentpackageid"); - if (!string.IsNullOrEmpty(workshopIdData)) - { - serverInfo.ContentPackageWorkshopIds.AddRange(ParseWorkshopIds(workshopIdData)); - } - else - { - string[] workshopUrls = lobby.GetData("contentpackageurl").Split(','); - serverInfo.ContentPackageWorkshopIds.AddRange(WorkshopUrlsToIds(workshopUrls)); - } - - if (Enum.TryParse(lobby.GetData("modeselectionmode"), out SelectionMode selectionMode)) { serverInfo.ModeSelectionMode = selectionMode; } - if (Enum.TryParse(lobby.GetData("subselectionmode"), out selectionMode)) { serverInfo.SubSelectionMode = selectionMode; } - - serverInfo.AllowSpectating = getLobbyBool("allowspectating"); - serverInfo.AllowRespawn = getLobbyBool("allowrespawn"); - serverInfo.VoipEnabled = getLobbyBool("voicechatenabled"); - serverInfo.KarmaEnabled = getLobbyBool("karmaenabled"); - serverInfo.FriendlyFireEnabled = getLobbyBool("friendlyfireenabled"); - if (Enum.TryParse(lobby.GetData("traitors"), out YesNoMaybe traitorsEnabled)) { serverInfo.TraitorsEnabled = traitorsEnabled; } - - serverInfo.GameStarted = lobby.GetData("gamestarted") == "True"; - serverInfo.GameMode = (lobby.GetData("gamemode") ?? "").ToIdentifier(); - if (Enum.TryParse(lobby.GetData("playstyle"), out PlayStyle playStyle)) serverInfo.PlayStyle = playStyle; - - if (serverInfo.ContentPackageNames.Count != serverInfo.ContentPackageHashes.Count || - serverInfo.ContentPackageHashes.Count != serverInfo.ContentPackageWorkshopIds.Count) - { - //invalid contentpackage info - serverInfo.ContentPackageNames.Clear(); - serverInfo.ContentPackageHashes.Clear(); - serverInfo.ContentPackageWorkshopIds.Clear(); - } - - string pingLocation = lobby.GetData("pinglocation"); - if (!string.IsNullOrEmpty(pingLocation)) - { - serverInfo.PingLocation = Steamworks.Data.NetPingLocation.TryParseFromString(pingLocation); - } - - bool? getLobbyBool(string key) - { - string data = lobby.GetData(key); - if (string.IsNullOrEmpty(data)) { return null; } - return data == "True" || data == "true"; - } - } - - public static void AssignServerRulesToServerInfo(Dictionary rules, ServerInfo serverInfo) - { - serverInfo.OwnerVerified = true; - - if (rules == null) { return; } - - if (rules.ContainsKey("message")) { serverInfo.ServerMessage = rules["message"]; } - if (rules.ContainsKey("version")) { serverInfo.GameVersion = rules["version"]; } - - if (rules.ContainsKey("playercount")) - { - if (int.TryParse(rules["playercount"], out int playerCount)) { serverInfo.PlayerCount = playerCount; } - } - - serverInfo.ContentPackageNames.Clear(); - serverInfo.ContentPackageHashes.Clear(); - serverInfo.ContentPackageWorkshopIds.Clear(); - if (rules.ContainsKey("contentpackage")) { serverInfo.ContentPackageNames.AddRange(rules["contentpackage"].Split(',')); } - if (rules.ContainsKey("contentpackagehash")) { serverInfo.ContentPackageHashes.AddRange(rules["contentpackagehash"].Split(',')); } - if (rules.ContainsKey("contentpackageid")) - { - serverInfo.ContentPackageWorkshopIds.AddRange(ParseWorkshopIds(rules["contentpackageid"])); - } - else if (rules.ContainsKey("contentpackageurl")) - { - string[] workshopUrls = rules["contentpackageurl"].Split(','); - serverInfo.ContentPackageWorkshopIds.AddRange(WorkshopUrlsToIds(workshopUrls)); - } - - if (rules.ContainsKey("modeselectionmode")) - { - if (Enum.TryParse(rules["modeselectionmode"], out SelectionMode selectionMode)) { serverInfo.ModeSelectionMode = selectionMode; } - } - if (rules.ContainsKey("subselectionmode")) - { - if (Enum.TryParse(rules["subselectionmode"], out SelectionMode selectionMode)) { serverInfo.SubSelectionMode = selectionMode; } - } - if (rules.ContainsKey("allowspectating")) { serverInfo.AllowSpectating = rules["allowspectating"] == "True"; } - if (rules.ContainsKey("allowrespawn")) { serverInfo.AllowRespawn = rules["allowrespawn"] == "True"; } - if (rules.ContainsKey("voicechatenabled")) { serverInfo.VoipEnabled = rules["voicechatenabled"] == "True"; } - if (rules.ContainsKey("friendlyfireenabled")) { serverInfo.FriendlyFireEnabled = rules["friendlyfireenabled"] == "True"; } - if (rules.ContainsKey("karmaenabled")) { serverInfo.KarmaEnabled = rules["karmaenabled"] == "True"; } - if (rules.ContainsKey("traitors")) - { - if (Enum.TryParse(rules["traitors"], out YesNoMaybe traitorsEnabled)) { serverInfo.TraitorsEnabled = traitorsEnabled; } - } - - if (rules.ContainsKey("gamestarted")) { serverInfo.GameStarted = rules["gamestarted"] == "True"; } - if (rules.ContainsKey("gamemode")) - { - serverInfo.GameMode = rules["gamemode"].ToIdentifier(); - } - if (rules.ContainsKey("playstyle") && Enum.TryParse(rules["playstyle"], out PlayStyle playStyle)) - { - serverInfo.PlayStyle = playStyle; - } - - if (serverInfo.ContentPackageNames.Count != serverInfo.ContentPackageHashes.Count || - serverInfo.ContentPackageHashes.Count != serverInfo.ContentPackageWorkshopIds.Count) - { - //invalid contentpackage info - serverInfo.ContentPackageNames.Clear(); - serverInfo.ContentPackageHashes.Clear(); - serverInfo.ContentPackageWorkshopIds.Clear(); - } - } } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Steam/Workshop.cs b/Barotrauma/BarotraumaClient/ClientSource/Steam/Workshop.cs index a21ef24c9..370b47f3f 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Steam/Workshop.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Steam/Workshop.cs @@ -196,7 +196,7 @@ namespace Barotrauma.Steam throw new Exception("Expected Workshop package"); } - if (contentPackage.SteamWorkshopId == 0) + if (!contentPackage.UgcId.TryUnwrap(out var ugcId) || !(ugcId is SteamWorkshopId workshopId)) { throw new Exception($"Steam Workshop ID not set for {contentPackage.Name}"); } @@ -210,7 +210,7 @@ namespace Barotrauma.Steam string newPath = $"{ContentPackage.LocalModsDir}/{sanitizedName}"; if (File.Exists(newPath) || Directory.Exists(newPath)) { - newPath += $"_{contentPackage.SteamWorkshopId}"; + newPath += $"_{workshopId.Value}"; } if (File.Exists(newPath) || Directory.Exists(newPath)) @@ -226,7 +226,7 @@ namespace Barotrauma.Steam RefreshLocalMods(); - return ContentPackageManager.LocalPackages.FirstOrDefault(p => p.SteamWorkshopId == contentPackage.SteamWorkshopId); + return ContentPackageManager.LocalPackages.FirstOrDefault(p => p.UgcId == contentPackage.UgcId); } private struct InstallWaiter @@ -266,7 +266,10 @@ namespace Barotrauma.Steam { NukeDownload(workshopItem); var toUninstall - = ContentPackageManager.WorkshopPackages.Where(p => p.SteamWorkshopId == workshopItem.Id) + = ContentPackageManager.WorkshopPackages.Where(p => + p.UgcId.TryUnwrap(out var ugcId) + && ugcId is SteamWorkshopId workshopId + && workshopId.Value == workshopItem.Id) .ToHashSet(); toUninstall.Select(p => p.Dir).ForEach(d => Directory.Delete(d)); CrossThread.RequestExecutionOnMainThread(() => ContentPackageManager.WorkshopPackages.Refresh()); @@ -296,7 +299,10 @@ namespace Barotrauma.Steam return; } else if (CanBeInstalled(id) - && !ContentPackageManager.WorkshopPackages.Any(p => p.SteamWorkshopId == id) + && !ContentPackageManager.WorkshopPackages.Any(p => + p.UgcId.TryUnwrap(out var ugcId) + && ugcId is SteamWorkshopId workshopId + && workshopId.Value == id) && !InstallTaskCounter.IsInstalling(id)) { TaskPool.Add($"InstallItem{id}", InstallMod(id), t => InstallWaiter.StopWaiting(id)); diff --git a/Barotrauma/BarotraumaClient/ClientSource/Steam/WorkshopMenu/Mutable/InstalledTab.cs b/Barotrauma/BarotraumaClient/ClientSource/Steam/WorkshopMenu/Mutable/InstalledTab.cs index 32482cc76..cce1627d8 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Steam/WorkshopMenu/Mutable/InstalledTab.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Steam/WorkshopMenu/Mutable/InstalledTab.cs @@ -35,7 +35,12 @@ namespace Barotrauma.Steam memSubscribedModCount = numSubscribedMods; var subscribedIds = SteamManager.GetSubscribedItems().ToHashSet(); - var installedIds = ContentPackageManager.WorkshopPackages.Select(p => p.SteamWorkshopId).ToHashSet(); + var installedIds = ContentPackageManager.WorkshopPackages + .Select(p => p.UgcId) + .NotNone() + .OfType() + .Select(id => id.Value) + .ToHashSet(); foreach (var id in subscribedIds.Where(id2 => !installedIds.Contains(id2))) { Steamworks.Ugc.Item item = new Steamworks.Ugc.Item(id); @@ -514,7 +519,9 @@ namespace Barotrauma.Steam private void PrepareToShowModInfo(ContentPackage mod) { - TaskPool.Add($"PrepareToShow{mod.SteamWorkshopId}Info", SteamManager.Workshop.GetItem(mod.SteamWorkshopId), + if (!mod.UgcId.TryUnwrap(out var ugcId) + || !(ugcId is SteamWorkshopId workshopId)) { return; } + TaskPool.Add($"PrepareToShow{mod.UgcId}Info", SteamManager.Workshop.GetItem(workshopId.Value), t => { if (!t.TryGetResult(out Steamworks.Ugc.Item? item)) { return; } @@ -592,7 +599,12 @@ namespace Barotrauma.Steam isEnabled: true, onSelected: () => { - TaskPool.AddIfNotFound($"UnsubFromSelected", Task.WhenAll(selectedMods.Select(m => SteamManager.Workshop.GetItem(m.SteamWorkshopId))), + var workshopIds = selectedMods + .Select(m => m.UgcId) + .NotNone() + .OfType() + .Select(id => id.Value); + TaskPool.AddIfNotFound($"UnsubFromSelected", Task.WhenAll(workshopIds.Select(SteamManager.Workshop.GetItem)), t => { if (!t.TryGetResult(out Steamworks.Ugc.Item?[] items)) { return; } @@ -672,7 +684,7 @@ namespace Barotrauma.Steam infoButton.Enabled = false; } TaskPool.AddIfNotFound( - $"DetermineUpdateRequired{mod.SteamWorkshopId}", + $"DetermineUpdateRequired{mod.UgcId}", mod.IsUpToDate(), t => { @@ -725,6 +737,8 @@ namespace Barotrauma.Steam { var mod = child.UserData as RegularPackage; if (mod is null || !ContentPackageManager.WorkshopPackages.Contains(mod)) { continue; } + if (!mod.UgcId.TryUnwrap(out var ugcId)) { continue; } + if (!(ugcId is SteamWorkshopId workshopId)) { continue; } var btn = child.GetChild()?.GetAllChildren().Last(); if (btn is null) { continue; } @@ -732,11 +746,11 @@ namespace Barotrauma.Steam btn.ApplyStyle( GUIStyle.GetComponentStyle( - ids.Contains(mod.SteamWorkshopId) + ids.Contains(workshopId.Value) ? "WorkshopMenu.PublishedIcon" : "WorkshopMenu.DownloadedIcon")); btn.ToolTip = TextManager.Get( - ids.Contains(mod.SteamWorkshopId) + ids.Contains(workshopId.Value) ? "PublishedWorkshopMod" : "DownloadedWorkshopMod"); btn.HoverCursor = CursorState.Default; diff --git a/Barotrauma/BarotraumaClient/ClientSource/Steam/WorkshopMenu/Mutable/ItemList.cs b/Barotrauma/BarotraumaClient/ClientSource/Steam/WorkshopMenu/Mutable/ItemList.cs index 0d401f95a..17a677d57 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Steam/WorkshopMenu/Mutable/ItemList.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Steam/WorkshopMenu/Mutable/ItemList.cs @@ -226,7 +226,7 @@ namespace Barotrauma.Steam (Steamworks.Ugc.Item WorkshopItem, ContentPackage? LocalPackage)[] publishedItems = workshopItems .Select(item => (item, (ContentPackage?)ContentPackageManager.LocalPackages.FirstOrDefault(p - => p.SteamWorkshopId != 0 && p.SteamWorkshopId == item.Id))) + => p.TryExtractSteamWorkshopId(out var workshopId) && workshopId.Value == item.Id))) //Sort the pairs by last local edit time if available .OrderBy(t => t.Item2 == null) .ThenByDescending(t => t.Item2 is { } p ? getEditTime(p) : t.Item1.LatestUpdateTime) @@ -241,7 +241,9 @@ namespace Barotrauma.Steam //Get mods that haven't been published and add them to the list var unpublishedMods = ContentPackageManager.LocalPackages - .Where(p => p.SteamWorkshopId == 0 || !publishedItems.Any(item => item.WorkshopItem.Id == p.SteamWorkshopId)) + .Where(p => + !p.TryExtractSteamWorkshopId(out var workshopId) + || !publishedItems.Any(item => item.WorkshopItem.Id == workshopId.Value)) .OrderByDescending(getEditTime).ToArray(); if (unpublishedMods.Any()) @@ -556,7 +558,9 @@ namespace Barotrauma.Steam taskCancelSrc = taskCancelSrc.IsCancellationRequested ? new CancellationTokenSource() : taskCancelSrc; var contentPackage - = ContentPackageManager.WorkshopPackages.FirstOrDefault(p => p.SteamWorkshopId == workshopItem.Id); + = ContentPackageManager.WorkshopPackages.FirstOrDefault(p => + p.TryExtractSteamWorkshopId(out var workshopId) + && workshopId.Value == workshopItem.Id); var verticalLayout = new GUILayoutGroup(new RectTransform(Vector2.One, parentFrame.RectTransform)); @@ -619,7 +623,7 @@ namespace Barotrauma.Steam if (contentPackage != null) { TaskPool.AddIfNotFound( - $"DetermineUpdateRequired{contentPackage.SteamWorkshopId}", + $"DetermineUpdateRequired{contentPackage.UgcId}", contentPackage.IsUpToDate(), t => { @@ -652,7 +656,9 @@ namespace Barotrauma.Steam if (contentPackage != null && !ContentPackageManager.WorkshopPackages.Contains(contentPackage) - && ContentPackageManager.WorkshopPackages.Any(p => p.SteamWorkshopId == workshopItem.Id)) + && ContentPackageManager.WorkshopPackages.Any(p => + p.TryExtractSteamWorkshopId(out var workshopId) + && workshopId.Value == workshopItem.Id)) { updateButton.Visible = false; } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Steam/WorkshopMenu/Mutable/ModListPreset.cs b/Barotrauma/BarotraumaClient/ClientSource/Steam/WorkshopMenu/Mutable/ModListPreset.cs index df5e42de0..daec8758f 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Steam/WorkshopMenu/Mutable/ModListPreset.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Steam/WorkshopMenu/Mutable/ModListPreset.cs @@ -6,6 +6,7 @@ using System.Linq; using System.Xml.Linq; using Barotrauma.IO; using Barotrauma.Extensions; +using Barotrauma.Steam; using Microsoft.Xna.Framework; namespace Barotrauma @@ -49,21 +50,18 @@ namespace Barotrauma case ModType.Workshop: { var id = element.GetAttributeUInt64("id", 0); - var pkg = ContentPackageManager.WorkshopPackages.FirstOrDefault(p => p.SteamWorkshopId == id); - if (id != 0 && pkg != null) - { - addPkg(pkg); - } + if (id == 0) { continue; } + var pkg = ContentPackageManager.WorkshopPackages.FirstOrDefault(p => + p.TryExtractSteamWorkshopId(out var workshopId) && workshopId.Value == id); + if (pkg != null) { addPkg(pkg); } } break; case ModType.Local: { var name = element.GetAttributeString("name", ""); + if (name.IsNullOrEmpty()) { continue; } var pkg = ContentPackageManager.LocalPackages.FirstOrDefault(p => p.NameMatches(name)); - if (!name.IsNullOrEmpty() && pkg != null) - { - addPkg(pkg); - } + if (pkg != null) { addPkg(pkg); } } break; } @@ -115,7 +113,7 @@ namespace Barotrauma { case ModType.Workshop: pkgElem.SetAttributeValue("name", pkg.Name); - pkgElem.SetAttributeValue("id", pkg.SteamWorkshopId.ToString()); + pkgElem.SetAttributeValue("id", pkg.UgcId.ToString()); break; case ModType.Local: pkgElem.SetAttributeValue("name", pkg.Name); diff --git a/Barotrauma/BarotraumaClient/ClientSource/Steam/WorkshopMenu/Mutable/PublishTab.cs b/Barotrauma/BarotraumaClient/ClientSource/Steam/WorkshopMenu/Mutable/PublishTab.cs index 6d6cc04ed..61d849dbe 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Steam/WorkshopMenu/Mutable/PublishTab.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Steam/WorkshopMenu/Mutable/PublishTab.cs @@ -95,6 +95,9 @@ namespace Barotrauma.Steam SelectTab(Tab.Publish); } + private static bool PackageMatchesItem(ContentPackage p, Steamworks.Ugc.Item workshopItem) + => p.TryExtractSteamWorkshopId(out var workshopId) && workshopId.Value == workshopItem.Id; + private void PopulatePublishTab(ItemOrPackage itemOrPackage, GUIFrame parentFrame) { ContentPackageManager.LocalPackages.Refresh(); @@ -105,18 +108,19 @@ namespace Barotrauma.Steam childAnchor: Anchor.TopCenter); Steamworks.Ugc.Item workshopItem = itemOrPackage.TryGet(out Steamworks.Ugc.Item item) ? item : default; + ContentPackage? localPackage = itemOrPackage.TryGet(out ContentPackage package) ? package - : ContentPackageManager.LocalPackages.FirstOrDefault(p => p.SteamWorkshopId == workshopItem.Id); + : ContentPackageManager.LocalPackages.FirstOrDefault(p => PackageMatchesItem(p, workshopItem)); ContentPackage? workshopPackage - = ContentPackageManager.WorkshopPackages.FirstOrDefault(p => p.SteamWorkshopId == workshopItem.Id); + = ContentPackageManager.WorkshopPackages.FirstOrDefault(p => PackageMatchesItem(p, workshopItem)); if (localPackage is null) { new GUIFrame(new RectTransform((1.0f, 0.15f), mainLayout.RectTransform), style: null); //Local copy does not exist; check for Workshop copy bool workshopCopyExists = - ContentPackageManager.WorkshopPackages.Any(p => p.SteamWorkshopId == workshopItem.Id); + ContentPackageManager.WorkshopPackages.Any(p => PackageMatchesItem(p, workshopItem)); new GUITextBlock(new RectTransform((0.7f, 0.4f), mainLayout.RectTransform), TextManager.Get(workshopCopyExists ? "LocalCopyRequired" : "ItemInstallRequired"), @@ -403,7 +407,7 @@ namespace Barotrauma.Steam private IEnumerable CreateLocalCopy(GUITextBlock currentStepText, Steamworks.Ugc.Item workshopItem, GUIFrame parentFrame) { ContentPackage? workshopCopy = - ContentPackageManager.WorkshopPackages.FirstOrDefault(p => p.SteamWorkshopId == workshopItem.Id); + ContentPackageManager.WorkshopPackages.FirstOrDefault(p => PackageMatchesItem(p, workshopItem)); if (workshopCopy is null) { if (!SteamManager.Workshop.CanBeInstalled(workshopItem)) @@ -417,7 +421,7 @@ namespace Barotrauma.Steam { ContentPackageManager.WorkshopPackages.Refresh(); }); - while (!ContentPackageManager.WorkshopPackages.Any(p => p.SteamWorkshopId == workshopItem.Id)) + while (!ContentPackageManager.WorkshopPackages.Any(p => PackageMatchesItem(p, workshopItem))) { currentStepText.Text = SteamManager.Workshop.CanBeInstalled(workshopItem) ? TextManager.Get("PublishPopupInstall") @@ -426,7 +430,7 @@ namespace Barotrauma.Steam } workshopCopy = - ContentPackageManager.WorkshopPackages.First(p => p.SteamWorkshopId == workshopItem.Id); + ContentPackageManager.WorkshopPackages.First(p => PackageMatchesItem(p, workshopItem)); } bool localCopyMade = false; @@ -480,7 +484,7 @@ namespace Barotrauma.Steam messageBox.Buttons[0].Enabled = false; Steamworks.Ugc.PublishResult? result = null; Exception? resultException = null; - TaskPool.Add($"Publishing {localPackage.Name} ({localPackage.SteamWorkshopId})", + TaskPool.Add($"Publishing {localPackage.Name} ({localPackage.UgcId})", editor.SubmitAsync(), t => { @@ -496,6 +500,8 @@ namespace Barotrauma.Steam if (result is { Success: true }) { var resultId = result.Value.FileId; + bool packageMatchesResult(ContentPackage p) + => p.TryExtractSteamWorkshopId(out var workshopId) && workshopId.Value == resultId; Steamworks.Ugc.Item resultItem = new Steamworks.Ugc.Item(resultId); Task downloadTask = SteamManager.Workshop.ForceRedownload(resultItem); while (!resultItem.IsInstalled && !downloadTask.IsCompleted) @@ -511,7 +517,7 @@ namespace Barotrauma.Steam } ContentPackage? pkgToNuke - = ContentPackageManager.WorkshopPackages.FirstOrDefault(p => p.SteamWorkshopId == resultId); + = ContentPackageManager.WorkshopPackages.FirstOrDefault(packageMatchesResult); if (pkgToNuke != null) { Directory.Delete(pkgToNuke.Dir, recursive: true); @@ -537,7 +543,7 @@ namespace Barotrauma.Steam var localModProject = new ModProject(localPackage) { - SteamWorkshopId = resultId + UgcId = Option.Some(new SteamWorkshopId(resultId)) }; localModProject.DiscardHashAndInstallTime(); localModProject.Save(localPackage.Path); diff --git a/Barotrauma/BarotraumaClient/ClientSource/Text/LocalizedString/WrappedLString.cs b/Barotrauma/BarotraumaClient/ClientSource/Text/LocalizedString/WrappedLString.cs index f13fdd117..f2cf800d2 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Text/LocalizedString/WrappedLString.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Text/LocalizedString/WrappedLString.cs @@ -19,7 +19,7 @@ namespace Barotrauma public override bool Loaded => nestedStr.Loaded; public override void RetrieveValue() { - cachedValue = ToolBox.WrapText(nestedStr.Value, lineLength, font.Value, textScale); + cachedValue = ToolBox.WrapText(nestedStr.Value, lineLength, font.GetFontForStr(nestedStr.Value), textScale); UpdateLanguage(); } } diff --git a/Barotrauma/BarotraumaClient/LinuxClient.csproj b/Barotrauma/BarotraumaClient/LinuxClient.csproj index ce5e7b251..50cde2d74 100644 --- a/Barotrauma/BarotraumaClient/LinuxClient.csproj +++ b/Barotrauma/BarotraumaClient/LinuxClient.csproj @@ -6,7 +6,7 @@ Barotrauma FakeFish, Undertow Games Barotrauma - 0.19.3.0 + 0.19.5.0 Copyright © FakeFish 2018-2022 AnyCPU;x64 Barotrauma diff --git a/Barotrauma/BarotraumaClient/MacClient.csproj b/Barotrauma/BarotraumaClient/MacClient.csproj index fd0d561b2..a6511a7d3 100644 --- a/Barotrauma/BarotraumaClient/MacClient.csproj +++ b/Barotrauma/BarotraumaClient/MacClient.csproj @@ -6,7 +6,7 @@ Barotrauma FakeFish, Undertow Games Barotrauma - 0.19.3.0 + 0.19.5.0 Copyright © FakeFish 2018-2022 AnyCPU;x64 Barotrauma diff --git a/Barotrauma/BarotraumaClient/WindowsClient.csproj b/Barotrauma/BarotraumaClient/WindowsClient.csproj index 4e4bc2642..97e542512 100644 --- a/Barotrauma/BarotraumaClient/WindowsClient.csproj +++ b/Barotrauma/BarotraumaClient/WindowsClient.csproj @@ -6,7 +6,7 @@ Barotrauma FakeFish, Undertow Games Barotrauma - 0.19.3.0 + 0.19.5.0 Copyright © FakeFish 2018-2022 AnyCPU;x64 Barotrauma diff --git a/Barotrauma/BarotraumaServer/LinuxServer.csproj b/Barotrauma/BarotraumaServer/LinuxServer.csproj index f60b3ea38..be1d93bfe 100644 --- a/Barotrauma/BarotraumaServer/LinuxServer.csproj +++ b/Barotrauma/BarotraumaServer/LinuxServer.csproj @@ -6,7 +6,7 @@ Barotrauma FakeFish, Undertow Games Barotrauma Dedicated Server - 0.19.3.0 + 0.19.5.0 Copyright © FakeFish 2018-2022 AnyCPU;x64 DedicatedServer diff --git a/Barotrauma/BarotraumaServer/MacServer.csproj b/Barotrauma/BarotraumaServer/MacServer.csproj index 2f621c063..52c412583 100644 --- a/Barotrauma/BarotraumaServer/MacServer.csproj +++ b/Barotrauma/BarotraumaServer/MacServer.csproj @@ -6,7 +6,7 @@ Barotrauma FakeFish, Undertow Games Barotrauma Dedicated Server - 0.19.3.0 + 0.19.5.0 Copyright © FakeFish 2018-2022 AnyCPU;x64 DedicatedServer diff --git a/Barotrauma/BarotraumaServer/ServerSource/Characters/CharacterInfo.cs b/Barotrauma/BarotraumaServer/ServerSource/Characters/CharacterInfo.cs index 561218a63..49893f4dd 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Characters/CharacterInfo.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Characters/CharacterInfo.cs @@ -61,8 +61,9 @@ namespace Barotrauma msg.WriteColorR8G8B8(Head.SkinColor); msg.WriteColorR8G8B8(Head.HairColor); msg.WriteColorR8G8B8(Head.FacialHairColor); - msg.WriteString(ragdollFileName); + msg.WriteString(ragdollFileName); + msg.WriteIdentifier(HumanPrefabIds.NpcIdentifier); if (Job != null) { msg.WriteUInt32(Job.Prefab.UintIdentifier); diff --git a/Barotrauma/BarotraumaServer/ServerSource/GameMain.cs b/Barotrauma/BarotraumaServer/ServerSource/GameMain.cs index be7481ad2..1cf319471 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/GameMain.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/GameMain.cs @@ -243,6 +243,7 @@ namespace Barotrauma maxPlayers, ownerKey, steamId); + Server.StartServer(); for (int i = 0; i < CommandLineArgs.Length; i++) { diff --git a/Barotrauma/BarotraumaServer/ServerSource/GameSession/GameModes/CharacterCampaignData.cs b/Barotrauma/BarotraumaServer/ServerSource/GameSession/GameModes/CharacterCampaignData.cs index e81939b28..138dc3cfe 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/GameSession/GameModes/CharacterCampaignData.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/GameSession/GameModes/CharacterCampaignData.cs @@ -1,4 +1,5 @@ using Barotrauma.Networking; +using System; using System.Xml.Linq; namespace Barotrauma @@ -20,19 +21,22 @@ namespace Barotrauma CharacterInfo = client.CharacterInfo; healthData = new XElement("health"); - client.Character?.CharacterHealth?.Save(healthData); - if (client.Character?.Inventory != null) + + //the character may not be controlled by the client atm, but still exist + Character character = client.Character ?? CharacterInfo?.Character; + + character?.CharacterHealth?.Save(healthData); + if (character?.Inventory != null) { itemData = new XElement("inventory"); - Character.SaveInventory(client.Character.Inventory, itemData); + Character.SaveInventory(character.Inventory, itemData); } OrderData = new XElement("orders"); - if (client.CharacterInfo != null) + if (CharacterInfo != null) { - CharacterInfo.SaveOrderData(client.CharacterInfo, OrderData); + CharacterInfo.SaveOrderData(CharacterInfo, OrderData); } - - if (client.Character?.Wallet.Save() is { } walletSave) + if (character?.Wallet.Save() is { } walletSave) { WalletData = walletSave; } @@ -118,9 +122,9 @@ namespace Barotrauma character.SpawnInventoryItems(inventory, itemData.FromPackage(null)); } - public void ApplyHealthData(Character character) + public void ApplyHealthData(Character character, Func afflictionPredicate = null) { - CharacterInfo.ApplyHealthData(character, healthData); + CharacterInfo.ApplyHealthData(character, healthData, afflictionPredicate); } public void ApplyOrderData(Character character) diff --git a/Barotrauma/BarotraumaServer/ServerSource/GameSession/GameModes/MultiPlayerCampaign.cs b/Barotrauma/BarotraumaServer/ServerSource/GameSession/GameModes/MultiPlayerCampaign.cs index accb5e13a..502f148fc 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/GameSession/GameModes/MultiPlayerCampaign.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/GameSession/GameModes/MultiPlayerCampaign.cs @@ -917,15 +917,14 @@ namespace Barotrauma foreach (var kvp in purchasedItems) { - foreach (var purchasedItemList in purchasedItems.Values) + var storeId = kvp.Key; + var purchasedItemList = kvp.Value; + foreach (var purchasedItem in purchasedItemList) { - foreach (var purchasedItem in purchasedItemList) - { - int availableQuantity = map.CurrentLocation.Stores[kvp.Key].Stock.Find(s => s.ItemPrefab == purchasedItem.ItemPrefab)?.Quantity ?? 0; - purchasedItem.Quantity = Math.Min(purchasedItem.Quantity, availableQuantity); - } - } - CargoManager.PurchaseItems(kvp.Key, kvp.Value, false, sender); + int availableQuantity = map.CurrentLocation.Stores[storeId].Stock.Find(s => s.ItemPrefab == purchasedItem.ItemPrefab)?.Quantity ?? 0; + purchasedItem.Quantity = Math.Min(purchasedItem.Quantity, availableQuantity); + } + CargoManager.PurchaseItems(storeId, purchasedItemList, false, sender); } foreach (var (storeIdentifier, items) in CargoManager.PurchasedItems) diff --git a/Barotrauma/BarotraumaServer/ServerSource/Networking/BanList.cs b/Barotrauma/BarotraumaServer/ServerSource/Networking/BanList.cs index 6ba6dea70..15f4d365a 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Networking/BanList.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Networking/BanList.cs @@ -71,6 +71,12 @@ namespace Barotrauma.Networking { expirationTime = parsedTime; } + else + { + string error = $"Failed to parse the ban duration of \"{name}\" ({separatedLine[2]}) from the legacy ban list file (text file which has now been changed to XML). Considering the ban permanent."; + DebugConsole.ThrowError(error); + GameServer.AddPendingMessageToOwner(error, ChatMessageType.Error); + } } string reason = separatedLine.Length > 3 ? string.Join(",", separatedLine.Skip(3)) : ""; @@ -156,6 +162,8 @@ namespace Barotrauma.Networking public void BanPlayer(string name, Either addressOrAccountId, string reason, TimeSpan? duration) { + if (addressOrAccountId.TryGet(out Address address) && address.IsLocalHost) { return; } + var existingBan = bannedPlayers.Find(bp => bp.AddressOrAccountId == addressOrAccountId); if (existingBan != null) { bannedPlayers.Remove(existingBan); } diff --git a/Barotrauma/BarotraumaServer/ServerSource/Networking/Client.cs b/Barotrauma/BarotraumaServer/ServerSource/Networking/Client.cs index 551e32707..fdea971a5 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Networking/Client.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Networking/Client.cs @@ -224,27 +224,55 @@ namespace Barotrauma.Networking } } + /// + /// Reset what this client has voted for and the kick votes given to this client + /// + public void ResetVotes(bool resetKickVotes) + { + for (int i = 0; i < votes.Length; i++) + { + votes[i] = null; + } + if (resetKickVotes) + { + kickVoters.Clear(); + } + } + public void SetPermissions(ClientPermissions permissions, IEnumerable permittedConsoleCommands) { - this.Permissions = permissions; - this.PermittedConsoleCommands.Clear(); - this.PermittedConsoleCommands.UnionWith(permittedConsoleCommands); + Permissions = permissions; + PermittedConsoleCommands.Clear(); + PermittedConsoleCommands.UnionWith(permittedConsoleCommands); + if (Permissions.HasFlag(ClientPermissions.ManageSettings)) + { + //ensure the client has the up-to-date server settings + GameMain.Server?.ServerSettings?.ForcePropertyUpdate(); + } } public void GivePermission(ClientPermissions permission) { - if (!this.Permissions.HasFlag(permission)) this.Permissions |= permission; + if (!Permissions.HasFlag(permission)) + { + Permissions |= permission; + if (permission.HasFlag(ClientPermissions.ManageSettings)) + { + //ensure the client has the up-to-date server settings + GameMain.Server?.ServerSettings?.ForcePropertyUpdate(); + } + } } public void RemovePermission(ClientPermissions permission) { - this.Permissions &= ~permission; + Permissions &= ~permission; } public bool HasPermission(ClientPermissions permission) { - return this.Permissions.HasFlag(permission); + return Permissions.HasFlag(permission); } } } diff --git a/Barotrauma/BarotraumaServer/ServerSource/Networking/FileTransfer/ModSender.cs b/Barotrauma/BarotraumaServer/ServerSource/Networking/FileTransfer/ModSender.cs index 54bbd573c..318f77ff8 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Networking/FileTransfer/ModSender.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Networking/FileTransfer/ModSender.cs @@ -39,7 +39,7 @@ namespace Barotrauma.Networking string resultFileName = dir.StartsWith(ContentPackage.LocalModsDir) ? $"Local_{mod.Name}" - : $"Workshop_{mod.Name}_{mod.SteamWorkshopId}"; + : $"Workshop_{mod.Name}_{(mod.UgcId.TryUnwrap(out var ugcId) ? ugcId.ToString() : "NULL")}"; resultFileName = ToolBox.RemoveInvalidFileNameChars(resultFileName.Replace('\\', '_').Replace('/', '_')); resultFileName = $"{resultFileName}{Extension}"; return Path.Combine(UploadFolder, resultFileName); diff --git a/Barotrauma/BarotraumaServer/ServerSource/Networking/GameServer.cs b/Barotrauma/BarotraumaServer/ServerSource/Networking/GameServer.cs index c3bdd614c..116010200 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Networking/GameServer.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Networking/GameServer.cs @@ -14,9 +14,12 @@ using System.Xml.Linq; namespace Barotrauma.Networking { - partial class GameServer : NetworkMember + sealed class GameServer : NetworkMember { public override bool IsServer => true; + public override bool IsClient => false; + + public override Voting Voting { get; } private string serverName; public string ServerName @@ -25,7 +28,8 @@ namespace Barotrauma.Networking set { if (string.IsNullOrEmpty(value)) { return; } - serverName = value.Replace(":", "").Replace(";", ""); + + serverName = value; } } @@ -49,7 +53,7 @@ namespace Barotrauma.Networking public ServerPeer ServerPeer { get { return serverPeer; } } private DateTime refreshMasterTimer; - private TimeSpan refreshMasterInterval = new TimeSpan(0, 0, 60); + private readonly TimeSpan refreshMasterInterval = new TimeSpan(0, 0, 60); private bool registeredToMaster; private DateTime roundStartTime; @@ -57,6 +61,11 @@ namespace Barotrauma.Networking private bool autoRestartTimerRunning; private float endRoundTimer; + /// + /// Chat messages that get sent to the owner of the server when the owner is determined + /// + private static readonly Queue pendingMessagesToOwner = new Queue(); + public VoipServer VoipServer { get; @@ -98,15 +107,10 @@ namespace Barotrauma.Networking get { return entityEventManager; } } - public TimeSpan UpdateInterval - { - get { return updateInterval; } - } - - public int Port => serverSettings?.Port ?? 0; + public int Port => ServerSettings?.Port ?? 0; //only used when connected to steam - public int QueryPort => serverSettings?.QueryPort ?? 0; + public int QueryPort => ServerSettings?.QueryPort ?? 0; public NetworkConnection OwnerConnection { get; private set; } private readonly Option ownerKey; @@ -123,8 +127,6 @@ namespace Barotrauma.Networking Option ownerKey, Option ownerSteamId) { - name = name.Replace(":", ""); - name = name.Replace(";", ""); if (name.Length > NetConfig.ServerNameMaxLength) { name = name.Substring(0, NetConfig.ServerNameMaxLength); @@ -134,9 +136,9 @@ namespace Barotrauma.Networking LastClientListUpdateID = 0; - serverSettings = new ServerSettings(this, name, port, queryPort, maxPlayers, isPublic, attemptUPnP); - KarmaManager.SelectPreset(serverSettings.KarmaPreset); - serverSettings.SetPassword(password); + ServerSettings = new ServerSettings(this, name, port, queryPort, maxPlayers, isPublic, attemptUPnP); + KarmaManager.SelectPreset(ServerSettings.KarmaPreset); + ServerSettings.SetPassword(password); Voting = new Voting(); @@ -145,91 +147,74 @@ namespace Barotrauma.Networking this.ownerSteamId = ownerSteamId; entityEventManager = new ServerEntityEventManager(this); - - CoroutineManager.StartCoroutine(StartServer(isPublic)); } - private IEnumerable StartServer(bool isPublic) + public void StartServer() { - bool error = false; - try + Log("Starting the server...", ServerLog.MessageType.ServerMessage); + + var callbacks = new ServerPeer.Callbacks( + ReadDataMessage, + OnClientDisconnect, + OnInitializationComplete, + GameMain.Instance.CloseServer, + OnOwnerDetermined); + + if (ownerSteamId.TryUnwrap(out var steamId)) { - Log("Starting the server...", ServerLog.MessageType.ServerMessage); - if (ownerSteamId.TryUnwrap(out var steamId)) - { - Log("Using SteamP2P networking.", ServerLog.MessageType.ServerMessage); - serverPeer = new SteamP2PServerPeer(steamId, ownerKey.Fallback(0), serverSettings); - } - else - { - Log("Using Lidgren networking. Manual port forwarding may be required. If players cannot connect to the server, you may want to use the in-game hosting menu (which uses SteamP2P networking and does not require port forwarding).", ServerLog.MessageType.ServerMessage); - serverPeer = new LidgrenServerPeer(ownerKey, serverSettings); - } - - serverPeer.OnInitializationComplete = OnInitializationComplete; - serverPeer.OnMessageReceived = ReadDataMessage; - serverPeer.OnDisconnect = OnClientDisconnect; - serverPeer.OnShutdown = GameMain.Instance.CloseServer; - serverPeer.OnOwnerDetermined = OnOwnerDetermined; - - FileSender = new FileSender(serverPeer, MsgConstants.MTU); - FileSender.OnEnded += FileTransferChanged; - FileSender.OnStarted += FileTransferChanged; - - if (serverSettings.AllowModDownloads) { ModSender = new ModSender(); } - - serverPeer.Start(); - - VoipServer = new VoipServer(serverPeer); + Log("Using SteamP2P networking.", ServerLog.MessageType.ServerMessage); + serverPeer = new SteamP2PServerPeer(steamId, ownerKey.Fallback(0), ServerSettings, callbacks); } - catch (Exception e) + else { - Log("Error while starting the server (" + e.Message + ")", ServerLog.MessageType.Error); - - System.Net.Sockets.SocketException socketException = e as System.Net.Sockets.SocketException; - - error = true; + Log("Using Lidgren networking. Manual port forwarding may be required. If players cannot connect to the server, you may want to use the in-game hosting menu (which uses SteamP2P networking and does not require port forwarding).", ServerLog.MessageType.ServerMessage); + serverPeer = new LidgrenServerPeer(ownerKey, ServerSettings, callbacks); } - if (error) - { - if (serverPeer != null) serverPeer.Close("Error while starting the server"); + FileSender = new FileSender(serverPeer, MsgConstants.MTU); + FileSender.OnEnded += FileTransferChanged; + FileSender.OnStarted += FileTransferChanged; - Environment.Exit(-1); + if (ServerSettings.AllowModDownloads) { ModSender = new ModSender(); } - yield return CoroutineStatus.Success; - } + serverPeer.Start(); + VoipServer = new VoipServer(serverPeer); if (serverPeer is LidgrenServerPeer) { #if USE_STEAM - registeredToMaster = SteamManager.CreateServer(this, isPublic); + registeredToMaster = SteamManager.CreateServer(this, ServerSettings.IsPublic); #endif } - TickRate = serverSettings.TickRate; - Log("Server started", ServerLog.MessageType.ServerMessage); GameMain.NetLobbyScreen.Select(); GameMain.NetLobbyScreen.RandomizeSettings(); - if (!string.IsNullOrEmpty(serverSettings.SelectedSubmarine)) + if (!string.IsNullOrEmpty(ServerSettings.SelectedSubmarine)) { - SubmarineInfo sub = SubmarineInfo.SavedSubmarines.FirstOrDefault(s => s.Name == serverSettings.SelectedSubmarine); + SubmarineInfo sub = SubmarineInfo.SavedSubmarines.FirstOrDefault(s => s.Name == ServerSettings.SelectedSubmarine); if (sub != null) { GameMain.NetLobbyScreen.SelectedSub = sub; } } - if (!string.IsNullOrEmpty(serverSettings.SelectedShuttle)) + if (!string.IsNullOrEmpty(ServerSettings.SelectedShuttle)) { - SubmarineInfo shuttle = SubmarineInfo.SavedSubmarines.FirstOrDefault(s => s.Name == serverSettings.SelectedShuttle); + SubmarineInfo shuttle = SubmarineInfo.SavedSubmarines.FirstOrDefault(s => s.Name == ServerSettings.SelectedShuttle); if (shuttle != null) { GameMain.NetLobbyScreen.SelectedShuttle = shuttle; } } started = true; GameAnalyticsManager.AddDesignEvent("GameServer:Start"); + } - yield return CoroutineStatus.Success; + + /// + /// Creates a message that gets sent to the server owner once the connection is initialized. Can be used to for example notify the owner of problems during initialization + /// + public static void AddPendingMessageToOwner(string message, ChatMessageType messageType) + { + pendingMessagesToOwner.Enqueue(ChatMessage.Create(string.Empty, message, messageType, sender: null)); } private void OnOwnerDetermined(NetworkConnection connection) @@ -251,12 +236,12 @@ namespace Barotrauma.Networking var tempList = ConnectedClients.Where(c => c.Connection != OwnerConnection).ToList(); foreach (var c in tempList) { - DisconnectClient(c.Connection, DisconnectReason.ServerCrashed.ToString(), DisconnectReason.ServerCrashed.ToString()); + DisconnectClient(c.Connection, PeerDisconnectPacket.WithReason(DisconnectReason.ServerCrashed)); } if (OwnerConnection != null) { var conn = OwnerConnection; OwnerConnection = null; - DisconnectClient(conn, DisconnectReason.ServerCrashed.ToString(), DisconnectReason.ServerCrashed.ToString()); + DisconnectClient(conn, PeerDisconnectPacket.WithReason(DisconnectReason.ServerCrashed)); } Thread.Sleep(500); } @@ -296,7 +281,7 @@ namespace Barotrauma.Networking } SendChatMessage($"ServerMessage.JoinedServer~[client]={ClientLogName(newClient)}", ChatMessageType.Server, null, changeType: PlayerConnectionChangeType.Joined); - serverSettings.ServerDetailsChanged = true; + ServerSettings.ServerDetailsChanged = true; if (previousPlayer != null && previousPlayer.Name != newClient.Name) { @@ -305,7 +290,7 @@ namespace Barotrauma.Networking previousPlayer.Name = newClient.Name; } - var savedPermissions = serverSettings.ClientPermissions.Find(scp => + var savedPermissions = ServerSettings.ClientPermissions.Find(scp => scp.AddressOrAccountId.TryGet(out AccountId accountId) ? newClient.AccountId.ValueEquals(accountId) : newClient.Connection.Endpoint.Address == scp.AddressOrAccountId); @@ -336,14 +321,14 @@ namespace Barotrauma.Networking } } - private void OnClientDisconnect(NetworkConnection connection, string disconnectMsg) + private void OnClientDisconnect(NetworkConnection connection, PeerDisconnectPacket peerDisconnectPacket) { Client connectedClient = connectedClients.Find(c => c.Connection == connection); - DisconnectClient(connectedClient, reason: disconnectMsg); + DisconnectClient(connectedClient, peerDisconnectPacket); } - public override void Update(float deltaTime) + public void Update(float deltaTime) { #if CLIENT if (ShowNetStats) { netStats.Update(deltaTime); } @@ -356,21 +341,19 @@ namespace Barotrauma.Networking return; } - base.Update(deltaTime); - FileSender.Update(deltaTime); KarmaManager.UpdateClients(ConnectedClients, deltaTime); UpdatePing(); - if (serverSettings.VoiceChatEnabled) + if (ServerSettings.VoiceChatEnabled) { VoipServer.SendToClients(connectedClients); } - if (gameStarted) + if (GameStarted) { - respawnManager?.Update(deltaTime); + RespawnManager?.Update(deltaTime); entityEventManager.Update(connectedClients); @@ -385,14 +368,14 @@ namespace Barotrauma.Networking Client owner = connectedClients.Find(c => (c.Character == null || c.Character == character) && c.AddressMatches(character.OwnerClientAddress)); - if ((OwnerConnection == null || owner?.Connection != OwnerConnection) && character.KillDisconnectedTimer > serverSettings.KillDisconnectedTime) + if ((OwnerConnection == null || owner?.Connection != OwnerConnection) && character.KillDisconnectedTimer > ServerSettings.KillDisconnectedTime) { character.Kill(CauseOfDeathType.Disconnected, null); continue; } if (owner != null && owner.InGame && !owner.NeedsMidRoundSync && - (!serverSettings.AllowSpectating || !owner.SpectateOnly)) + (!ServerSettings.AllowSpectating || !owner.SpectateOnly)) { SetClientCharacter(owner, character); } @@ -438,7 +421,7 @@ namespace Barotrauma.Networking endRoundDelay = 5.0f; endRoundTimer += deltaTime; } - else if (serverSettings.AutoRestart && isCrewDead) + else if (ServerSettings.AutoRestart && isCrewDead) { endRoundDelay = 5.0f; endRoundTimer += deltaTime; @@ -448,7 +431,7 @@ namespace Barotrauma.Networking endRoundDelay = 5.0f; endRoundTimer += deltaTime; } - else if (isCrewDead && respawnManager == null) + else if (isCrewDead && RespawnManager == null) { #if !DEBUG if (endRoundTimer <= 0.0f) @@ -477,7 +460,7 @@ namespace Barotrauma.Networking { Log("Ending round (a traitor completed their mission)", ServerLog.MessageType.ServerMessage); } - else if (serverSettings.AutoRestart && isCrewDead) + else if (ServerSettings.AutoRestart && isCrewDead) { Log("Ending round (entire crew dead)", ServerLog.MessageType.ServerMessage); } @@ -485,7 +468,7 @@ namespace Barotrauma.Networking { Log("Ending round (submarine reached the end of the level)", ServerLog.MessageType.ServerMessage); } - else if (respawnManager == null) + else if (RespawnManager == null) { Log("Ending round (no living players left and respawning is not enabled during this round)", ServerLog.MessageType.ServerMessage); } @@ -503,7 +486,7 @@ 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); + if (ServerSettings.AutoRestart) ServerSettings.AutoRestartTimer = Math.Max(ServerSettings.AutoRestartInterval, 5.0f); //GameMain.NetLobbyScreen.StartButtonEnabled = true; GameMain.NetLobbyScreen.LastUpdateID++; @@ -512,15 +495,15 @@ namespace Barotrauma.Networking initiatedStartGame = false; } } - else if (Screen.Selected == GameMain.NetLobbyScreen && !gameStarted && !initiatedStartGame && + else if (Screen.Selected == GameMain.NetLobbyScreen && !GameStarted && !initiatedStartGame && (GameMain.NetLobbyScreen.SelectedMode != GameModePreset.MultiPlayerCampaign || GameMain.GameSession?.GameMode is MultiPlayerCampaign)) { - if (serverSettings.AutoRestart) + if (ServerSettings.AutoRestart) { //autorestart if there are any non-spectators on the server (ignoring the server owner) bool shouldAutoRestart = connectedClients.Any(c => c.Connection != OwnerConnection && - (!c.SpectateOnly || !serverSettings.AllowSpectating)); + (!c.SpectateOnly || !ServerSettings.AllowSpectating)); if (shouldAutoRestart != autoRestartTimerRunning) { @@ -530,18 +513,18 @@ namespace Barotrauma.Networking if (autoRestartTimerRunning) { - serverSettings.AutoRestartTimer -= deltaTime; + ServerSettings.AutoRestartTimer -= deltaTime; } } - if (serverSettings.AutoRestart && autoRestartTimerRunning && serverSettings.AutoRestartTimer < 0.0f) + if (ServerSettings.AutoRestart && autoRestartTimerRunning && ServerSettings.AutoRestartTimer < 0.0f) { StartGame(); } - else if (serverSettings.StartWhenClientsReady) + else if (ServerSettings.StartWhenClientsReady) { int clientsReady = connectedClients.Count(c => c.GetVote(VoteType.StartRound)); - if (clientsReady / (float)connectedClients.Count >= serverSettings.StartWhenClientsReadyRatio) + if (clientsReady / (float)connectedClients.Count >= ServerSettings.StartWhenClientsReadyRatio) { StartGame(); } @@ -553,7 +536,7 @@ namespace Barotrauma.Networking disconnectedClients[i].DeleteDisconnectedTimer -= deltaTime; if (disconnectedClients[i].DeleteDisconnectedTimer > 0.0f) continue; - if (gameStarted && disconnectedClients[i].Character != null) + if (GameStarted && disconnectedClients[i].Character != null) { disconnectedClients[i].Character.Kill(CauseOfDeathType.Disconnected, null); disconnectedClients[i].Character = null; @@ -569,16 +552,16 @@ namespace Barotrauma.Networking c.ChatSpamSpeed = Math.Max(0.0f, c.ChatSpamSpeed - deltaTime); //constantly increase AFK timer if the client is controlling a character (gets reset to zero every time an input is received) - if (gameStarted && c.Character != null && !c.Character.IsDead && !c.Character.IsIncapacitated) + if (GameStarted && c.Character != null && !c.Character.IsDead && !c.Character.IsIncapacitated) { if (c.Connection != OwnerConnection && c.Permissions != ClientPermissions.All) { c.KickAFKTimer += deltaTime; } } } - if (connectedClients.Any(c => c.KickAFKTimer >= serverSettings.KickAFKTime)) + if (connectedClients.Any(c => c.KickAFKTimer >= ServerSettings.KickAFKTime)) { IEnumerable kickAFK = connectedClients.FindAll(c => - c.KickAFKTimer >= serverSettings.KickAFKTime && + c.KickAFKTimer >= ServerSettings.KickAFKTime && (OwnerConnection == null || c.Connection != OwnerConnection)); foreach (Client c in kickAFK) { @@ -638,10 +621,10 @@ namespace Barotrauma.Networking } } - updateTimer = DateTime.Now + updateInterval; + updateTimer = DateTime.Now + UpdateInterval; } - if (registeredToMaster && (DateTime.Now > refreshMasterTimer || serverSettings.ServerDetailsChanged)) + if (registeredToMaster && (DateTime.Now > refreshMasterTimer || ServerSettings.ServerDetailsChanged)) { if (GameSettings.CurrentConfig.UseSteamMatchmaking) { @@ -654,7 +637,7 @@ namespace Barotrauma.Networking } } refreshMasterTimer = DateTime.Now + refreshMasterInterval; - serverSettings.ServerDetailsChanged = false; + ServerSettings.ServerDetailsChanged = false; } } @@ -717,7 +700,7 @@ namespace Barotrauma.Networking UpdateCharacterInfo(inc, connectedClient); //game already started -> send start message immediately - if (gameStarted) + if (GameStarted) { SendStartMessage(roundStartSeed, GameMain.GameSession.Level.Seed, GameMain.GameSession, connectedClient, true); } @@ -728,7 +711,7 @@ namespace Barotrauma.Networking { DebugConsole.AddWarning("Received a REQUEST_STARTGAMEFINALIZE message. Client not connected, ignoring the message."); } - else if (!gameStarted) + else if (!GameStarted) { DebugConsole.AddWarning("Received a REQUEST_STARTGAMEFINALIZE message. Game not started, ignoring the message."); } @@ -741,7 +724,7 @@ namespace Barotrauma.Networking ClientReadLobby(inc); break; case ClientPacketHeader.UPDATE_INGAME: - if (!gameStarted) { return; } + if (!GameStarted) { return; } ClientReadIngame(inc); break; case ClientPacketHeader.CAMPAIGN_SETUP_INFO: @@ -756,7 +739,7 @@ namespace Barotrauma.Networking var matchingSub = SubmarineInfo.SavedSubmarines.FirstOrDefault(s => s.Name == subName && s.MD5Hash.StringRepresentation == subHash); - if (gameStarted) + if (GameStarted) { SendDirectChatMessage(TextManager.Get("CampaignStartFailedRoundRunning").Value, connectedClient, ChatMessageType.MessageBox); return; @@ -782,7 +765,7 @@ namespace Barotrauma.Networking else { string saveName = inc.ReadString(); - if (gameStarted) + if (GameStarted) { SendDirectChatMessage(TextManager.Get("CampaignStartFailedRoundRunning").Value, connectedClient, ChatMessageType.MessageBox); return; @@ -791,7 +774,7 @@ namespace Barotrauma.Networking } break; case ClientPacketHeader.VOICE: - if (serverSettings.VoiceChatEnabled && !connectedClient.Muted) + if (ServerSettings.VoiceChatEnabled && !connectedClient.Muted) { byte id = inc.ReadByte(); if (connectedClient.SessionId != id) @@ -806,7 +789,7 @@ namespace Barotrauma.Networking } break; case ClientPacketHeader.SERVER_SETTINGS: - serverSettings.ServerRead(inc, connectedClient); + ServerSettings.ServerRead(inc, connectedClient); break; case ClientPacketHeader.SERVER_COMMAND: ClientReadServerCommand(inc); @@ -830,7 +813,7 @@ namespace Barotrauma.Networking ReadReadyToSpawnMessage(inc, connectedClient); break; case ClientPacketHeader.FILE_REQUEST: - if (serverSettings.AllowFileTransfers) + if (ServerSettings.AllowFileTransfers) { FileSender.ReadFileRequest(inc, connectedClient); } @@ -887,7 +870,7 @@ namespace Barotrauma.Networking { errorStr = errorStrNoName = $"Missing entity {entity}, sub: {entity.Submarine?.Info?.Name ?? "none"} (event id {eventID}, entity id {entityID})."; } - if (gameStarted) + if (GameStarted) { var serverSubNames = Submarine.Loaded.Select(s => s.Info.Name); if (subCount != Submarine.Loaded.Count || !subNames.SequenceEqual(serverSubNames)) @@ -1107,7 +1090,7 @@ namespace Barotrauma.Networking bool midroundSyncingDone = inc.ReadBoolean(); inc.ReadPadBits(); - if (gameStarted) + if (GameStarted) { if (!c.InGame) { @@ -1170,7 +1153,7 @@ namespace Barotrauma.Networking c.LastRecvEntityEventID = lastRecvEntityEventID; DebugConsole.Log("Finished midround syncing " + c.Name + " - switching from ID " + prevID + " to " + c.LastRecvEntityEventID); //notify the client of the state of the respawn manager (so they show the respawn prompt if needed) - if (respawnManager != null) { CreateEntityEvent(respawnManager); } + if (RespawnManager != null) { CreateEntityEvent(RespawnManager); } if (GameMain.GameSession?.GameMode is MultiPlayerCampaign campaign) { //notify the client of the current bank balance and purchased repairs @@ -1291,7 +1274,7 @@ namespace Barotrauma.Networking private void ReadReadyToSpawnMessage(IReadMessage inc, Client sender) { - sender.SpectateOnly = inc.ReadBoolean() && (serverSettings.AllowSpectating || sender.Connection == OwnerConnection); + sender.SpectateOnly = inc.ReadBoolean() && (ServerSettings.AllowSpectating || sender.Connection == OwnerConnection); sender.WaitForNextRoundRespawn = inc.ReadBoolean(); if (!(GameMain.GameSession?.GameMode is CampaignMode)) { @@ -1399,7 +1382,7 @@ namespace Barotrauma.Networking mpCampaign.AllowedToManageCampaign(sender, ClientPermissions.ManageCampaign)) { bool save = inc.ReadBoolean(); - if (gameStarted) + if (GameStarted) { Log("Client \"" + GameServer.ClientLogName(sender) + "\" ended the round.", ServerLog.MessageType.ServerMessage); if (mpCampaign != null && Level.IsLoadedFriendlyOutpost && save) @@ -1421,7 +1404,7 @@ namespace Barotrauma.Networking bool continueCampaign = inc.ReadBoolean(); if (mpCampaign != null && mpCampaign.GameOver || continueCampaign) { - if (gameStarted) + if (GameStarted) { SendDirectChatMessage("Cannot continue the campaign from the previous save (round already running).", sender, ChatMessageType.Error); break; @@ -1432,7 +1415,7 @@ namespace Barotrauma.Networking } } - else if (!gameStarted && !initiatedStartGame) + else if (!GameStarted && !initiatedStartGame) { Log("Client \"" + ClientLogName(sender) + "\" started the round.", ServerLog.MessageType.ServerMessage); StartGame(); @@ -1562,7 +1545,7 @@ namespace Barotrauma.Networking private void ClientWrite(Client c) { - if (gameStarted && c.InGame) + if (GameStarted && c.InGame) { ClientWriteIngame(c); } @@ -1570,7 +1553,7 @@ namespace Barotrauma.Networking { //if 30 seconds have passed since the round started and the client isn't ingame yet, //consider the client's character disconnected (causing it to die if the client does not join soon) - if (gameStarted && c.Character != null && (DateTime.Now - roundStartTime).Seconds > 30.0f) + if (GameStarted && c.Character != null && (DateTime.Now - roundStartTime).Seconds > 30.0f) { c.Character.ClientDisconnected = true; } @@ -1578,6 +1561,15 @@ namespace Barotrauma.Networking ClientWriteLobby(c); } + + if (c.Connection == OwnerConnection) + { + while (pendingMessagesToOwner.Any()) + { + SendDirectChatMessage(pendingMessagesToOwner.Dequeue(), c); + } + } + if (GameMain.GameSession?.GameMode is MultiPlayerCampaign campaign && GameMain.NetLobbyScreen.SelectedMode == campaign.Preset && NetIdUtils.IdMoreRecent(campaign.LastSaveID, c.LastRecvCampaignSave)) @@ -1625,7 +1617,7 @@ namespace Barotrauma.Networking } outmsg.WriteBoolean(GameStarted); - outmsg.WriteBoolean(serverSettings.AllowSpectating); + outmsg.WriteBoolean(ServerSettings.AllowSpectating); c.WritePermissions(outmsg); } @@ -1834,11 +1826,11 @@ namespace Barotrauma.Networking AccountInfo = client.AccountInfo, NameId = client.NameId, Name = client.Name, - PreferredJob = client.Character?.Info?.Job != null && gameStarted + PreferredJob = client.Character?.Info?.Job != null && GameStarted ? client.Character.Info.Job.Prefab.Identifier : client.PreferredJob, PreferredTeam = client.PreferredTeam, - CharacterId = client.Character == null || !gameStarted ? (ushort)0 : client.Character.ID, + CharacterId = client.Character == null || !GameStarted ? (ushort)0 : client.Character.ID, Karma = c.HasPermission(ClientPermissions.ServerLog) ? client.Karma : 100.0f, Muted = client.Muted, InGame = client.InGame, @@ -1882,7 +1874,7 @@ namespace Barotrauma.Networking outmsg.WriteUInt16(GameMain.NetLobbyScreen.LastUpdateID); settingsBuf = new ReadWriteMessage(); - serverSettings.ServerWrite(settingsBuf, c); + ServerSettings.ServerWrite(settingsBuf, c); outmsg.WriteUInt16((UInt16)settingsBuf.LengthBytes); outmsg.WriteBytes(settingsBuf.Buffer, 0, settingsBuf.LengthBytes); @@ -1897,34 +1889,34 @@ namespace Barotrauma.Networking outmsg.WriteString(GameMain.NetLobbyScreen.SelectedSub.Name); outmsg.WriteString(GameMain.NetLobbyScreen.SelectedSub.MD5Hash.ToString()); outmsg.WriteBoolean(IsUsingRespawnShuttle()); - var selectedShuttle = gameStarted && respawnManager != null && respawnManager.UsingShuttle ? - respawnManager.RespawnShuttle.Info : + var selectedShuttle = GameStarted && RespawnManager != null && RespawnManager.UsingShuttle ? + RespawnManager.RespawnShuttle.Info : GameMain.NetLobbyScreen.SelectedShuttle; outmsg.WriteString(selectedShuttle.Name); outmsg.WriteString(selectedShuttle.MD5Hash.ToString()); - outmsg.WriteBoolean(serverSettings.AllowSubVoting); - outmsg.WriteBoolean(serverSettings.AllowModeVoting); + outmsg.WriteBoolean(ServerSettings.AllowSubVoting); + outmsg.WriteBoolean(ServerSettings.AllowModeVoting); - outmsg.WriteBoolean(serverSettings.VoiceChatEnabled); + outmsg.WriteBoolean(ServerSettings.VoiceChatEnabled); - outmsg.WriteBoolean(serverSettings.AllowSpectating); + outmsg.WriteBoolean(ServerSettings.AllowSpectating); - outmsg.WriteRangedInteger((int)serverSettings.TraitorsEnabled, 0, 2); + outmsg.WriteRangedInteger((int)ServerSettings.TraitorsEnabled, 0, 2); outmsg.WriteRangedInteger((int)GameMain.NetLobbyScreen.MissionType, 0, (int)MissionType.All); outmsg.WriteByte((byte)GameMain.NetLobbyScreen.SelectedModeIndex); outmsg.WriteString(GameMain.NetLobbyScreen.LevelSeed); - outmsg.WriteSingle(serverSettings.SelectedLevelDifficulty); + outmsg.WriteSingle(ServerSettings.SelectedLevelDifficulty); - outmsg.WriteByte((byte)serverSettings.BotCount); - outmsg.WriteBoolean(serverSettings.BotSpawnMode == BotSpawnMode.Fill); + outmsg.WriteByte((byte)ServerSettings.BotCount); + outmsg.WriteBoolean(ServerSettings.BotSpawnMode == BotSpawnMode.Fill); - outmsg.WriteBoolean(serverSettings.AutoRestart); - if (serverSettings.AutoRestart) + outmsg.WriteBoolean(ServerSettings.AutoRestart); + if (ServerSettings.AutoRestart) { - outmsg.WriteSingle(autoRestartTimerRunning ? serverSettings.AutoRestartTimer : 0.0f); + outmsg.WriteSingle(autoRestartTimerRunning ? ServerSettings.AutoRestartTimer : 0.0f); } } else @@ -2032,13 +2024,13 @@ namespace Barotrauma.Networking public bool StartGame() { - if (initiatedStartGame || gameStarted) { return false; } + if (initiatedStartGame || GameStarted) { return false; } Log("Starting a new round...", ServerLog.MessageType.ServerMessage); SubmarineInfo selectedShuttle = GameMain.NetLobbyScreen.SelectedShuttle; SubmarineInfo selectedSub; - if (serverSettings.AllowSubVoting) + if (ServerSettings.AllowSubVoting) { selectedSub = Voting.HighestVoted(VoteType.Sub, connectedClients); if (selectedSub == null) { selectedSub = GameMain.NetLobbyScreen.SelectedSub; } @@ -2163,7 +2155,7 @@ namespace Barotrauma.Networking List playingClients = new List(connectedClients); - if (serverSettings.AllowSpectating) + if (ServerSettings.AllowSpectating) { playingClients.RemoveAll(c => c.SpectateOnly); } @@ -2209,7 +2201,7 @@ namespace Barotrauma.Networking else { SendStartMessage(roundStartSeed, GameMain.NetLobbyScreen.LevelSeed, GameMain.GameSession, connectedClients, false); - GameMain.GameSession.StartRound(GameMain.NetLobbyScreen.LevelSeed, serverSettings.SelectedLevelDifficulty); + GameMain.GameSession.StartRound(GameMain.NetLobbyScreen.LevelSeed, ServerSettings.SelectedLevelDifficulty); Log("Game mode: " + selectedMode.Name.Value, ServerLog.MessageType.ServerMessage); Log("Submarine: " + selectedSub.Name, ServerLog.MessageType.ServerMessage); Log("Level seed: " + GameMain.NetLobbyScreen.LevelSeed, ServerLog.MessageType.ServerMessage); @@ -2231,9 +2223,9 @@ namespace Barotrauma.Networking bool missionAllowRespawn = !(GameMain.GameSession.GameMode is MissionMode missionMode) || !missionMode.Missions.Any(m => !m.AllowRespawn); bool isOutpost = campaign != null && campaign.NextLevel?.Type == LevelData.LevelType.Outpost; - if (serverSettings.AllowRespawn && missionAllowRespawn) + if (ServerSettings.AllowRespawn && missionAllowRespawn) { - respawnManager = new RespawnManager(this, serverSettings.UseRespawnShuttle && !isOutpost ? selectedShuttle : null); + RespawnManager = new RespawnManager(this, ServerSettings.UseRespawnShuttle && !isOutpost ? selectedShuttle : null); } if (campaign != null) { @@ -2273,7 +2265,7 @@ namespace Barotrauma.Networking //find the clients in this team List teamClients = teamCount == 1 ? new List(playingClients) : playingClients.FindAll(c => c.TeamID == teamID); - if (serverSettings.AllowSpectating) + if (ServerSettings.AllowSpectating) { teamClients.RemoveAll(c => c.SpectateOnly); } @@ -2311,7 +2303,7 @@ namespace Barotrauma.Networking // do not load new bots if we already have them if (crewManager == null || !crewManager.HasBots) { - int botsToSpawn = serverSettings.BotSpawnMode == BotSpawnMode.Fill ? serverSettings.BotCount - characterInfos.Count : serverSettings.BotCount; + int botsToSpawn = ServerSettings.BotSpawnMode == BotSpawnMode.Fill ? ServerSettings.BotCount - characterInfos.Count : ServerSettings.BotCount; for (int i = 0; i < botsToSpawn; i++) { var botInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName) @@ -2449,7 +2441,7 @@ namespace Barotrauma.Networking { if (sub == null) { continue; } List spawnList = new List(); - foreach (KeyValuePair kvp in serverSettings.ExtraCargo) + foreach (KeyValuePair kvp in ServerSettings.ExtraCargo) { spawnList.Add(new PurchasedItem(kvp.Key, kvp.Value, buyer: null)); } @@ -2458,8 +2450,8 @@ namespace Barotrauma.Networking } TraitorManager = null; - if (serverSettings.TraitorsEnabled == YesNoMaybe.Yes || - (serverSettings.TraitorsEnabled == YesNoMaybe.Maybe && Rand.Range(0.0f, 1.0f) < 0.5f)) + if (ServerSettings.TraitorsEnabled == YesNoMaybe.Yes || + (ServerSettings.TraitorsEnabled == YesNoMaybe.Maybe && Rand.Range(0.0f, 1.0f) < 0.5f)) { if (!(GameMain.GameSession?.GameMode is CampaignMode)) { @@ -2472,13 +2464,13 @@ namespace Barotrauma.Networking yield return CoroutineStatus.Running; - Voting?.ResetVotes(GameMain.Server.ConnectedClients); + Voting?.ResetVotes(GameMain.Server.ConnectedClients, resetKickVotes: false); GameMain.GameScreen.Select(); Log("Round started.", ServerLog.MessageType.ServerMessage); - gameStarted = true; + GameStarted = true; initiatedStartGame = false; GameMain.ResetFrameTime(); @@ -2508,28 +2500,28 @@ namespace Barotrauma.Networking msg.WriteInt32(seed); msg.WriteIdentifier(gameSession.GameMode.Preset.Identifier); bool missionAllowRespawn = missionMode == null || !missionMode.Missions.Any(m => !m.AllowRespawn); - msg.WriteBoolean(serverSettings.AllowRespawn && missionAllowRespawn); - msg.WriteBoolean(serverSettings.AllowDisguises); - msg.WriteBoolean(serverSettings.AllowRewiring); - msg.WriteBoolean(serverSettings.AllowFriendlyFire); - msg.WriteBoolean(serverSettings.LockAllDefaultWires); - msg.WriteBoolean(serverSettings.AllowRagdollButton); - msg.WriteBoolean(serverSettings.AllowLinkingWifiToChat); - msg.WriteInt32(serverSettings.MaximumMoneyTransferRequest); + msg.WriteBoolean(ServerSettings.AllowRespawn && missionAllowRespawn); + msg.WriteBoolean(ServerSettings.AllowDisguises); + msg.WriteBoolean(ServerSettings.AllowRewiring); + msg.WriteBoolean(ServerSettings.AllowFriendlyFire); + msg.WriteBoolean(ServerSettings.LockAllDefaultWires); + msg.WriteBoolean(ServerSettings.AllowRagdollButton); + msg.WriteBoolean(ServerSettings.AllowLinkingWifiToChat); + msg.WriteInt32(ServerSettings.MaximumMoneyTransferRequest); msg.WriteBoolean(IsUsingRespawnShuttle()); - msg.WriteByte((byte)serverSettings.LosMode); + msg.WriteByte((byte)ServerSettings.LosMode); msg.WriteBoolean(includesFinalize); msg.WritePadBits(); - serverSettings.WriteMonsterEnabled(msg); + ServerSettings.WriteMonsterEnabled(msg); if (campaign == null) { msg.WriteString(levelSeed); - msg.WriteSingle(serverSettings.SelectedLevelDifficulty); + msg.WriteSingle(ServerSettings.SelectedLevelDifficulty); msg.WriteString(gameSession.SubmarineInfo.Name); msg.WriteString(gameSession.SubmarineInfo.MD5Hash.StringRepresentation); - var selectedShuttle = gameStarted && respawnManager != null && respawnManager.UsingShuttle ? - respawnManager.RespawnShuttle.Info : GameMain.NetLobbyScreen.SelectedShuttle; + var selectedShuttle = GameStarted && RespawnManager != null && RespawnManager.UsingShuttle ? + RespawnManager.RespawnShuttle.Info : GameMain.NetLobbyScreen.SelectedShuttle; msg.WriteString(selectedShuttle.Name); msg.WriteString(selectedShuttle.MD5Hash.StringRepresentation); msg.WriteByte((byte)GameMain.GameSession.GameMode.Missions.Count()); @@ -2560,7 +2552,7 @@ namespace Barotrauma.Networking private bool IsUsingRespawnShuttle() { - return serverSettings.UseRespawnShuttle || (gameStarted && respawnManager != null && respawnManager.UsingShuttle); + return ServerSettings.UseRespawnShuttle || (GameStarted && RespawnManager != null && RespawnManager.UsingShuttle); } private void SendRoundStartFinalize(Client client) @@ -2600,7 +2592,7 @@ namespace Barotrauma.Networking public void EndGame(CampaignMode.TransitionType transitionType = CampaignMode.TransitionType.None, bool wasSaved = false) { - if (!gameStarted) + if (!GameStarted) { return; } @@ -2626,14 +2618,14 @@ namespace Barotrauma.Networking endRoundTimer = 0.0f; - if (serverSettings.AutoRestart) + if (ServerSettings.AutoRestart) { - serverSettings.AutoRestartTimer = serverSettings.AutoRestartInterval; + ServerSettings.AutoRestartTimer = ServerSettings.AutoRestartInterval; //send a netlobby update to get the clients' autorestart timers up to date GameMain.NetLobbyScreen.LastUpdateID++; } - if (serverSettings.SaveServerLogs) { serverSettings.ServerLog.Save(); } + if (ServerSettings.SaveServerLogs) { ServerSettings.ServerLog.Save(); } GameMain.GameScreen.Cam.TargetPos = Vector2.Zero; @@ -2647,12 +2639,8 @@ namespace Barotrauma.Networking KarmaManager.OnRoundEnded(); -#if DEBUG - messageCount.Clear(); -#endif - - respawnManager = null; - gameStarted = false; + RespawnManager = null; + GameStarted = false; if (connectedClients.Count > 0) { @@ -2762,7 +2750,7 @@ namespace Barotrauma.Networking if (c.Connection != OwnerConnection) { - if (!Client.IsValidName(newName, serverSettings)) + if (!Client.IsValidName(newName, ServerSettings)) { SendDirectChatMessage($"ServerMessage.NameChangeFailedSymbols~[newname]={newName}", c, ChatMessageType.ServerMessageBox); return false; @@ -2809,7 +2797,7 @@ namespace Barotrauma.Networking public void KickClient(Client client, string reason, bool resetKarma = false) { - if (client == null || client.Connection == OwnerConnection) return; + if (client == null || client.Connection == OwnerConnection) { return; } if (resetKarma) { @@ -2821,9 +2809,7 @@ namespace Barotrauma.Networking client.Karma = Math.Max(client.Karma, 50.0f); } - string msg = DisconnectReason.Kicked.ToString(); - string logMsg = $"ServerMessage.KickedFromServer~[client]={client.Name}"; - DisconnectClient(client, logMsg, msg, reason, PlayerConnectionChangeType.Kicked); + DisconnectClient(client, PeerDisconnectPacket.Kicked(reason)); } public override void BanPlayer(string playerName, string reason, TimeSpan? duration = null) @@ -2853,17 +2839,19 @@ namespace Barotrauma.Networking } client.Karma = Math.Max(client.Karma, 50.0f); - string targetMsg = DisconnectReason.Banned.ToString(); - DisconnectClient(client, $"ServerMessage.BannedFromServer~[client]={client.Name}", targetMsg, reason, PlayerConnectionChangeType.Banned); + DisconnectClient(client, PeerDisconnectPacket.Banned(reason)); - serverSettings.BanList.BanPlayer(client.Name, client.Connection.Endpoint, reason, duration); if (client.AccountInfo.AccountId.TryUnwrap(out var accountId)) { - serverSettings.BanList.BanPlayer(client.Name, accountId, reason, duration); + ServerSettings.BanList.BanPlayer(client.Name, accountId, reason, duration); + } + else + { + ServerSettings.BanList.BanPlayer(client.Name, client.Connection.Endpoint, reason, duration); } foreach (var relatedId in client.AccountInfo.OtherMatchingIds) { - serverSettings.BanList.BanPlayer(client.Name, relatedId, reason, duration); + ServerSettings.BanList.BanPlayer(client.Name, relatedId, reason, duration); } } @@ -2874,14 +2862,14 @@ namespace Barotrauma.Networking //reset karma to a neutral value, so if/when the ban is revoked the client wont get immediately punished by low karma again previousPlayer.Karma = Math.Max(previousPlayer.Karma, 50.0f); - serverSettings.BanList.BanPlayer(previousPlayer.Name, previousPlayer.Address, reason, duration); + ServerSettings.BanList.BanPlayer(previousPlayer.Name, previousPlayer.Address, reason, duration); if (previousPlayer.AccountInfo.AccountId.TryUnwrap(out var accountId)) { - serverSettings.BanList.BanPlayer(previousPlayer.Name, accountId, reason, duration); + ServerSettings.BanList.BanPlayer(previousPlayer.Name, accountId, reason, duration); } foreach (var relatedId in previousPlayer.AccountInfo.OtherMatchingIds) { - serverSettings.BanList.BanPlayer(previousPlayer.Name, relatedId, reason, duration); + ServerSettings.BanList.BanPlayer(previousPlayer.Name, relatedId, reason, duration); } string msg = $"ServerMessage.BannedFromServer~[client]={previousPlayer.Name}"; @@ -2895,31 +2883,25 @@ namespace Barotrauma.Networking public override void UnbanPlayer(string playerName) { BannedPlayer bannedPlayer - = serverSettings.BanList.BannedPlayers.FirstOrDefault(bp => bp.Name == playerName); + = ServerSettings.BanList.BannedPlayers.FirstOrDefault(bp => bp.Name == playerName); if (bannedPlayer is null) { return; } - serverSettings.BanList.UnbanPlayer(bannedPlayer.AddressOrAccountId); + ServerSettings.BanList.UnbanPlayer(bannedPlayer.AddressOrAccountId); } public override void UnbanPlayer(Endpoint endpoint) { - serverSettings.BanList.UnbanPlayer(endpoint); + ServerSettings.BanList.UnbanPlayer(endpoint); } - public void DisconnectClient(NetworkConnection senderConnection, string msg = "", string targetmsg = "") + public void DisconnectClient(NetworkConnection senderConnection, PeerDisconnectPacket peerDisconnectPacket) { - if (senderConnection == OwnerConnection) - { - DebugConsole.NewMessage("Owner disconnected: closing the server...", Color.Yellow); - Log("Owner disconnected: closing the server...", ServerLog.MessageType.ServerMessage); - GameMain.ShouldRun = false; - } Client client = connectedClients.Find(x => x.Connection == senderConnection); - if (client == null) return; + if (client == null) { return; } - DisconnectClient(client, msg, targetmsg, string.Empty, PlayerConnectionChangeType.Disconnected); + DisconnectClient(client, peerDisconnectPacket); } - public void DisconnectClient(Client client, string msg = "", string targetmsg = "", string reason = "", PlayerConnectionChangeType changeType = PlayerConnectionChangeType.Disconnected) + public void DisconnectClient(Client client, PeerDisconnectPacket peerDisconnectPacket) { if (client == null) return; @@ -2934,14 +2916,6 @@ namespace Barotrauma.Networking client.WaitForNextRoundRespawn = null; client.InGame = false; - if (string.IsNullOrWhiteSpace(msg)) { msg = $"ServerMessage.ClientLeftServer~[client]={ClientLogName(client)}"; } - if (string.IsNullOrWhiteSpace(targetmsg)) { targetmsg = "ServerMessage.YouLeftServer"; } - if (!string.IsNullOrWhiteSpace(reason)) - { - msg += $"/ /ServerMessage.Reason/: /{reason}"; - targetmsg += $"/\n/ServerMessage.Reason/: /{reason}"; - } - if (client.AccountId is Some { Value: SteamId steamId }) { SteamManager.StopAuthSession(steamId); } var previousPlayer = previousPlayers.Find(p => p.MatchesClient(client)); @@ -2959,19 +2933,19 @@ namespace Barotrauma.Networking if (client.HasKickVoteFrom(c)) { previousPlayer.KickVoters.Add(c); } } - serverPeer.Disconnect(client.Connection, targetmsg); client.Dispose(); connectedClients.Remove(client); + serverPeer.Disconnect(client.Connection, peerDisconnectPacket); KarmaManager.OnClientDisconnected(client); UpdateVoteStatus(); - SendChatMessage(msg, ChatMessageType.Server, changeType: changeType); + SendChatMessage(peerDisconnectPacket.ChatMessage(client).Value, ChatMessageType.Server, changeType: peerDisconnectPacket.ConnectionChangeType); UpdateCrewFrame(); - serverSettings.ServerDetailsChanged = true; + ServerSettings.ServerDetailsChanged = true; refreshMasterTimer = DateTime.Now; } @@ -3086,7 +3060,7 @@ namespace Barotrauma.Networking message = tempStr; } - if (gameStarted) + if (GameStarted) { if (senderClient == null) { @@ -3282,11 +3256,11 @@ namespace Barotrauma.Networking int no = eligibleClients.Count(c => c.GetVote(Voting.ActiveVote.VoteType) == 1); int max = eligibleClients.Count(); // Required ratio cannot be met - if (no / (float)max > 1f - serverSettings.VoteRequiredRatio) + if (no / (float)max > 1f - ServerSettings.VoteRequiredRatio) { Voting.ActiveVote.Finish(Voting, passed: false); } - else if (yes / (float)max >= serverSettings.VoteRequiredRatio) + else if (yes / (float)max >= ServerSettings.VoteRequiredRatio) { Voting.ActiveVote.Finish(Voting, passed: true); } @@ -3296,7 +3270,7 @@ namespace Barotrauma.Networking Client.UpdateKickVotes(connectedClients); var kickVoteEligibleClients = connectedClients.Where(c => (DateTime.Now - c.JoinTime).TotalSeconds > ServerSettings.DisallowKickVoteTime); - float minimumKickVotes = Math.Max(2.0f, kickVoteEligibleClients.Count() * serverSettings.KickVoteRequiredRatio); + float minimumKickVotes = Math.Max(2.0f, kickVoteEligibleClients.Count() * ServerSettings.KickVoteRequiredRatio); var clientsToKick = connectedClients.FindAll(c => c.Connection != OwnerConnection && !c.HasPermission(ClientPermissions.Kick) && @@ -3306,13 +3280,9 @@ namespace Barotrauma.Networking foreach (Client c in clientsToKick) { //reset the client's kick votes (they can rejoin after their ban expires) - c.ResetVotes(); - var previousPlayer = previousPlayers.Find(p => p.MatchesClient(c)); - previousPlayer?.KickVoters.Clear(); - - SendChatMessage($"ServerMessage.KickedFromServer~[client]={c.Name}", ChatMessageType.Server, null, changeType: PlayerConnectionChangeType.Kicked); - KickClient(c, "ServerMessage.KickedByVote"); - BanClient(c, "ServerMessage.KickedByVoteAutoBan", duration: TimeSpan.FromSeconds(serverSettings.AutoBanTime)); + c.ResetVotes(resetKickVotes: true); + previousPlayers.Where(p => p.MatchesClient(c)).ForEach(p => p.KickVoters.Clear()); + BanClient(c, "ServerMessage.KickedByVoteAutoBan", duration: TimeSpan.FromSeconds(ServerSettings.AutoBanTime)); } //GameMain.NetLobbyScreen.LastUpdateID++; @@ -3321,8 +3291,8 @@ namespace Barotrauma.Networking int endVoteCount = ConnectedClients.Count(c => c.HasSpawned && c.GetVote(VoteType.EndRound)); int endVoteMax = GameMain.Server.ConnectedClients.Count(c => c.HasSpawned); - if (serverSettings.AllowEndVoting && endVoteMax > 0 && - ((float)endVoteCount / (float)endVoteMax) >= serverSettings.EndVoteRequiredRatio) + if (ServerSettings.AllowEndVoting && endVoteMax > 0 && + ((float)endVoteCount / (float)endVoteMax) >= ServerSettings.EndVoteRequiredRatio) { Log("Ending round by votes (" + endVoteCount + "/" + (endVoteMax - endVoteCount) + ")", ServerLog.MessageType.ServerMessage); EndGame(wasSaved: false); @@ -3380,10 +3350,10 @@ namespace Barotrauma.Networking { if (client.AccountId.TryUnwrap(out var accountId)) { - serverSettings.ClientPermissions.RemoveAll(scp => scp.AddressOrAccountId == accountId); + ServerSettings.ClientPermissions.RemoveAll(scp => scp.AddressOrAccountId == accountId); if (client.Permissions != ClientPermissions.None) { - serverSettings.ClientPermissions.Add(new ServerSettings.SavedClientPermission( + ServerSettings.ClientPermissions.Add(new ServerSettings.SavedClientPermission( client.Name, accountId, client.Permissions, @@ -3392,10 +3362,10 @@ namespace Barotrauma.Networking } else { - serverSettings.ClientPermissions.RemoveAll(scp => client.Connection.Endpoint.Address == scp.AddressOrAccountId); + ServerSettings.ClientPermissions.RemoveAll(scp => client.Connection.Endpoint.Address == scp.AddressOrAccountId); if (client.Permissions != ClientPermissions.None) { - serverSettings.ClientPermissions.Add(new ServerSettings.SavedClientPermission( + ServerSettings.ClientPermissions.Add(new ServerSettings.SavedClientPermission( client.Name, client.Connection.Endpoint.Address, client.Permissions, @@ -3407,7 +3377,7 @@ namespace Barotrauma.Networking { CoroutineManager.StartCoroutine(SendClientPermissionsAfterClientListSynced(recipient, client)); } - serverSettings.SaveClientPermissions(); + ServerSettings.SaveClientPermissions(); } private IEnumerable SendClientPermissionsAfterClientListSynced(Client recipient, Client client) @@ -3557,7 +3527,7 @@ namespace Barotrauma.Networking private void UpdateCharacterInfo(IReadMessage message, Client sender) { - sender.SpectateOnly = message.ReadBoolean() && (serverSettings.AllowSpectating || sender.Connection == OwnerConnection); + sender.SpectateOnly = message.ReadBoolean() && (ServerSettings.AllowSpectating || sender.Connection == OwnerConnection); if (sender.SpectateOnly) { return; @@ -3935,29 +3905,29 @@ namespace Barotrauma.Networking } } - public override void Quit() + public void Quit() { if (started) { started = false; - serverSettings.BanList.Save(); + ServerSettings.BanList.Save(); - if (GameMain.NetLobbyScreen.SelectedSub != null) { serverSettings.SelectedSubmarine = GameMain.NetLobbyScreen.SelectedSub.Name; } - if (GameMain.NetLobbyScreen.SelectedShuttle != null) { serverSettings.SelectedShuttle = GameMain.NetLobbyScreen.SelectedShuttle.Name; } + if (GameMain.NetLobbyScreen.SelectedSub != null) { ServerSettings.SelectedSubmarine = GameMain.NetLobbyScreen.SelectedSub.Name; } + if (GameMain.NetLobbyScreen.SelectedShuttle != null) { ServerSettings.SelectedShuttle = GameMain.NetLobbyScreen.SelectedShuttle.Name; } - serverSettings.SaveSettings(); + ServerSettings.SaveSettings(); ModSender.Dispose(); - if (serverSettings.SaveServerLogs) + if (ServerSettings.SaveServerLogs) { Log("Shutting down the server...", ServerLog.MessageType.ServerMessage); - serverSettings.ServerLog.Save(); + ServerSettings.ServerLog.Save(); } GameAnalyticsManager.AddDesignEvent("GameServer:ShutDown"); - serverPeer?.Close(DisconnectReason.ServerShutdown.ToString()); + serverPeer?.Close(); SteamManager.CloseServer(); } diff --git a/Barotrauma/BarotraumaServer/ServerSource/Networking/NetEntityEvent/ServerEntityEventManager.cs b/Barotrauma/BarotraumaServer/ServerSource/Networking/NetEntityEvent/ServerEntityEventManager.cs index 0bc4f9d87..abcbbf42c 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Networking/NetEntityEvent/ServerEntityEventManager.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Networking/NetEntityEvent/ServerEntityEventManager.cs @@ -246,7 +246,7 @@ namespace Barotrauma.Networking " (created " + (Timing.TotalTime - firstEventToResend.CreateTime).ToString("0.##") + " s ago, " + (lastSentToAnyoneTime - firstEventToResend.CreateTime).ToString("0.##") + " s older than last event sent to anyone)" + " Events queued: " + events.Count + ", last sent to all: " + lastSentToAll, ServerLog.MessageType.Error); - server.DisconnectClient(c, "", DisconnectReason.ExcessiveDesyncOldEvent + "/ServerMessage.ExcessiveDesyncOldEvent"); + server.DisconnectClient(c, PeerDisconnectPacket.WithReason(DisconnectReason.ExcessiveDesyncOldEvent)); } ); } @@ -260,7 +260,7 @@ namespace Barotrauma.Networking { DebugConsole.NewMessage(c.Name + " was kicked because they were expecting a removed network event (" + (c.LastRecvEntityEventID + 1).ToString() + ", last available is " + events[0].ID.ToString() + ")", Color.Red); GameServer.Log(GameServer.ClientLogName(c) + " was kicked because they were expecting a removed network event (" + (c.LastRecvEntityEventID + 1).ToString() + ", last available is " + events[0].ID.ToString() + ")", ServerLog.MessageType.Error); - server.DisconnectClient(c, "", DisconnectReason.ExcessiveDesyncRemovedEvent + "/ServerMessage.ExcessiveDesyncRemovedEvent"); + server.DisconnectClient(c, PeerDisconnectPacket.WithReason(DisconnectReason.ExcessiveDesyncRemovedEvent)); }); } } @@ -269,7 +269,7 @@ namespace Barotrauma.Networking foreach (Client timedOutClient in timedOutClients) { GameServer.Log("Disconnecting client " + GameServer.ClientLogName(timedOutClient) + ". Syncing the client with the server took too long.", ServerLog.MessageType.Error); - GameMain.Server.DisconnectClient(timedOutClient, "", DisconnectReason.SyncTimeout + "/ServerMessage.SyncTimeout"); + GameMain.Server.DisconnectClient(timedOutClient, PeerDisconnectPacket.WithReason(DisconnectReason.SyncTimeout)); } bufferedEvents.RemoveAll(b => b.IsProcessed); diff --git a/Barotrauma/BarotraumaServer/ServerSource/Networking/OrderChatMessage.cs b/Barotrauma/BarotraumaServer/ServerSource/Networking/OrderChatMessage.cs index dbf398cae..21d3f9ae8 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Networking/OrderChatMessage.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Networking/OrderChatMessage.cs @@ -20,7 +20,7 @@ namespace Barotrauma.Networking if (Sender != null && c.InGame) { msg.WriteUInt16(Sender.ID); - } + } msg.WriteBoolean(false); //text color (no custom text colors for order messages) msg.WritePadBits(); WriteOrder(msg); diff --git a/Barotrauma/BarotraumaServer/ServerSource/Networking/Primitives/Peers/Server/LidgrenServerPeer.cs b/Barotrauma/BarotraumaServer/ServerSource/Networking/Primitives/Peers/Server/LidgrenServerPeer.cs index 51e8c3749..c49417f23 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Networking/Primitives/Peers/Server/LidgrenServerPeer.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Networking/Primitives/Peers/Server/LidgrenServerPeer.cs @@ -15,7 +15,7 @@ namespace Barotrauma.Networking private readonly List incomingLidgrenMessages; - public LidgrenServerPeer(Option ownKey, ServerSettings settings) + public LidgrenServerPeer(Option ownKey, ServerSettings settings, Callbacks callbacks) : base(callbacks) { serverSettings = settings; @@ -68,21 +68,21 @@ namespace Barotrauma.Networking } } - public override void Close(string? msg = null) + public override void Close() { if (netServer == null) { return; } for (int i = pendingClients.Count - 1; i >= 0; i--) { - RemovePendingClient(pendingClients[i], DisconnectReason.ServerShutdown, msg); + RemovePendingClient(pendingClients[i], PeerDisconnectPacket.WithReason(DisconnectReason.ServerShutdown)); } for (int i = connectedClients.Count - 1; i >= 0; i--) { - Disconnect(connectedClients[i], msg ?? DisconnectReason.ServerShutdown.ToString()); + Disconnect(connectedClients[i], PeerDisconnectPacket.WithReason(DisconnectReason.ServerShutdown)); } - netServer.Shutdown(msg ?? DisconnectReason.ServerShutdown.ToString()); + netServer.Shutdown(PeerDisconnectPacket.WithReason(DisconnectReason.ServerShutdown).ToLidgrenStringRepresentation()); pendingClients.Clear(); connectedClients.Clear(); @@ -91,7 +91,7 @@ namespace Barotrauma.Networking Steamworks.SteamServer.OnValidateAuthTicketResponse -= OnAuthChange; - OnShutdown?.Invoke(); + callbacks.OnShutdown.Invoke(); } public override void Update(float deltaTime) @@ -100,12 +100,6 @@ namespace Barotrauma.Networking ToolBox.ThrowIfNull(incomingLidgrenMessages); - if (OnOwnerDetermined != null && OwnerConnection != null) - { - OnOwnerDetermined?.Invoke(OwnerConnection); - OnOwnerDetermined = null; - } - netServer.ReadMessages(incomingLidgrenMessages); //process incoming connections first @@ -193,14 +187,14 @@ namespace Barotrauma.Networking if (connectedClients.Count >= serverSettings.MaxPlayers) { - inc.SenderConnection.Deny(DisconnectReason.ServerFull.ToString()); + inc.SenderConnection.Deny(PeerDisconnectPacket.WithReason(DisconnectReason.ServerFull).ToLidgrenStringRepresentation()); return; } if (serverSettings.BanList.IsBanned(new LidgrenEndpoint(inc.SenderConnection.RemoteEndPoint), out string banReason)) { //IP banned: deny immediately - inc.SenderConnection.Deny($"{DisconnectReason.Banned}/ {banReason}"); + inc.SenderConnection.Deny(PeerDisconnectPacket.Banned(banReason).ToLidgrenStringRepresentation()); return; } @@ -235,12 +229,12 @@ namespace Barotrauma.Networking { if (pendingClient != null) { - RemovePendingClient(pendingClient, DisconnectReason.AuthenticationRequired, "Received data message from unauthenticated client"); + RemovePendingClient(pendingClient, PeerDisconnectPacket.WithReason(DisconnectReason.AuthenticationRequired)); } else if (lidgrenMsg.SenderConnection.Status != NetConnectionStatus.Disconnected && lidgrenMsg.SenderConnection.Status != NetConnectionStatus.Disconnecting) { - lidgrenMsg.SenderConnection.Disconnect($"{DisconnectReason.AuthenticationRequired}/ Received data message from unauthenticated client"); + lidgrenMsg.SenderConnection.Disconnect(PeerDisconnectPacket.WithReason(DisconnectReason.AuthenticationRequired).ToLidgrenStringRepresentation()); } return; @@ -252,12 +246,12 @@ namespace Barotrauma.Networking || (conn.AccountInfo.AccountId.TryUnwrap(out var accountId) && serverSettings.BanList.IsBanned(accountId, out banReason)) || conn.AccountInfo.OtherMatchingIds.Any(id => serverSettings.BanList.IsBanned(id, out banReason))) { - Disconnect(conn, $"{DisconnectReason.Banned}/ {banReason}"); + Disconnect(conn, PeerDisconnectPacket.Banned(banReason)); return; } var packet = INetSerializableStruct.Read(inc); - OnMessageReceived?.Invoke(conn, packet.GetReadMessage(packetHeader.IsCompressed(), conn)); + callbacks.OnMessageReceived.Invoke(conn, packet.GetReadMessage(packetHeader.IsCompressed(), conn)); } } @@ -275,12 +269,11 @@ namespace Barotrauma.Networking { DebugConsole.NewMessage("Owner disconnected: closing the server..."); GameServer.Log("Owner disconnected: closing the server...", ServerLog.MessageType.ServerMessage); - Close($"{DisconnectReason.ServerShutdown}/ Owner disconnected"); + Close(); } else { -#warning TODO: kill off disconnect in layer 1 - Disconnect(conn, $"ServerMessage.HasDisconnected~[client]={GameMain.Server.ConnectedClients.First(c => c.Connection == conn).Name}"); + Disconnect(conn, PeerDisconnectPacket.WithReason(DisconnectReason.Disconnected)); } } else @@ -288,7 +281,7 @@ namespace Barotrauma.Networking PendingClient? pendingClient = pendingClients.Find(c => c.Connection is LidgrenConnection l && l.NetConnection == inc.SenderConnection); if (pendingClient != null) { - RemovePendingClient(pendingClient, DisconnectReason.Unknown, $"ServerMessage.HasDisconnected~[client]={pendingClient.Name}"); + RemovePendingClient(pendingClient, PeerDisconnectPacket.WithReason(DisconnectReason.Disconnected)); } } @@ -312,9 +305,11 @@ namespace Barotrauma.Networking { if (status == Steamworks.AuthResponse.OK) { return; } - if (connectedClients.Find(c => c.AccountInfo.AccountId is Some { Value: SteamId id } && id.Value == steamId) is LidgrenConnection connection) + if (connectedClients.Find(c + => c.AccountInfo.AccountId is Some { Value: SteamId id } && id.Value == steamId) + is LidgrenConnection connection) { - Disconnect(connection, $"{DisconnectReason.SteamAuthenticationFailed}/ Steam authentication status changed: {status}"); + Disconnect(connection, PeerDisconnectPacket.SteamAuthError(status)); } return; @@ -325,7 +320,7 @@ namespace Barotrauma.Networking || serverSettings.BanList.IsBanned(new SteamId(steamId), out banReason) || serverSettings.BanList.IsBanned(new SteamId(ownerId), out banReason)) { - RemovePendingClient(pendingClient, DisconnectReason.Banned, banReason); + RemovePendingClient(pendingClient, PeerDisconnectPacket.Banned(banReason)); return; } @@ -337,7 +332,7 @@ namespace Barotrauma.Networking } else { - RemovePendingClient(pendingClient, DisconnectReason.SteamAuthenticationFailed, $"Steam authentication failed: {status}"); + RemovePendingClient(pendingClient, PeerDisconnectPacket.SteamAuthError(status)); } } @@ -374,7 +369,7 @@ namespace Barotrauma.Networking SendMsgInternal(conn, headers, body); } - public override void Disconnect(NetworkConnection conn, string? msg = null) + public override void Disconnect(NetworkConnection conn, PeerDisconnectPacket peerDisconnectPacket) { if (netServer == null) { return; } @@ -384,11 +379,11 @@ namespace Barotrauma.Networking { lidgrenConn.Status = NetworkConnectionStatus.Disconnected; connectedClients.Remove(lidgrenConn); - OnDisconnect?.Invoke(conn, msg); + callbacks.OnDisconnect.Invoke(conn, peerDisconnectPacket); if (conn.AccountInfo.AccountId is Some { Value: SteamId steamId }) { SteamManager.StopAuthSession(steamId); } } - lidgrenConn.NetConnection.Disconnect(msg ?? "Disconnected"); + lidgrenConn.NetConnection.Disconnect(peerDisconnectPacket.ToLidgrenStringRepresentation()); } protected override void SendMsgInternal(NetworkConnection conn, PeerPacketHeaders headers, INetSerializableStruct? body) @@ -413,6 +408,7 @@ namespace Barotrauma.Networking { ownerKey = Option.None(); OwnerConnection = pendingClient.Connection; + callbacks.OnOwnerDetermined.Invoke(OwnerConnection); } } @@ -440,7 +436,7 @@ namespace Barotrauma.Networking { if (requireSteamAuth) { - RemovePendingClient(pendingClient, DisconnectReason.SteamAuthenticationFailed, "Steam auth session failed to start: Steam ID not provided"); + RemovePendingClient(pendingClient, PeerDisconnectPacket.WithReason(DisconnectReason.SteamAuthenticationFailed)); return; } } @@ -451,7 +447,7 @@ namespace Barotrauma.Networking { if (requireSteamAuth) { - RemovePendingClient(pendingClient, DisconnectReason.SteamAuthenticationFailed, $"Steam auth session failed to start: {authSessionStartState}"); + RemovePendingClient(pendingClient, PeerDisconnectPacket.SteamAuthError(authSessionStartState)); } else { @@ -471,7 +467,7 @@ namespace Barotrauma.Networking { if (pendingClient.AccountInfo.AccountId != packet.SteamId.Select(uid => (AccountId)uid)) { - RemovePendingClient(pendingClient, DisconnectReason.SteamAuthenticationFailed, "SteamID mismatch"); + RemovePendingClient(pendingClient, PeerDisconnectPacket.WithReason(DisconnectReason.SteamAuthenticationFailed)); } } } diff --git a/Barotrauma/BarotraumaServer/ServerSource/Networking/Primitives/Peers/Server/ServerPeer.cs b/Barotrauma/BarotraumaServer/ServerSource/Networking/Primitives/Peers/Server/ServerPeer.cs index a00aa7a17..bc8acf2d6 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Networking/Primitives/Peers/Server/ServerPeer.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Networking/Primitives/Peers/Server/ServerPeer.cs @@ -9,26 +9,31 @@ namespace Barotrauma.Networking { internal abstract class ServerPeer { - public delegate void MessageCallback(NetworkConnection connection, IReadMessage message); + public readonly record struct Callbacks( + Callbacks.MessageCallback OnMessageReceived, + Callbacks.DisconnectCallback OnDisconnect, + Callbacks.InitializationCompleteCallback OnInitializationComplete, + Callbacks.ShutdownCallback OnShutdown, + Callbacks.OwnerDeterminedCallback OnOwnerDetermined) + { + public delegate void MessageCallback(NetworkConnection connection, IReadMessage message); + public delegate void DisconnectCallback(NetworkConnection connection, PeerDisconnectPacket peerDisconnectPacket); + public delegate void InitializationCompleteCallback(NetworkConnection connection, string? clientName); + public delegate void ShutdownCallback(); + public delegate void OwnerDeterminedCallback(NetworkConnection connection); + } - public delegate void DisconnectCallback(NetworkConnection connection, string? reason); - - public delegate void InitializationCompleteCallback(NetworkConnection connection, string? clientName); - - public delegate void ShutdownCallback(); - - public delegate void OwnerDeterminedCallback(NetworkConnection connection); - - public MessageCallback? OnMessageReceived; - public DisconnectCallback? OnDisconnect; - public InitializationCompleteCallback? OnInitializationComplete; - public ShutdownCallback? OnShutdown; - public OwnerDeterminedCallback? OnOwnerDetermined; + protected readonly Callbacks callbacks; + protected ServerPeer(Callbacks callbacks) + { + this.callbacks = callbacks; + } + public abstract void InitializeSteamServerCallbacks(); public abstract void Start(); - public abstract void Close(string? msg = null); + public abstract void Close(); public abstract void Update(float deltaTime); protected sealed class PendingClient @@ -84,15 +89,16 @@ namespace Barotrauma.Networking if (!Client.IsValidName(authPacket.Name, serverSettings)) { - RemovePendingClient(pendingClient, DisconnectReason.InvalidName, ""); + RemovePendingClient(pendingClient, PeerDisconnectPacket.WithReason(DisconnectReason.InvalidName)); return; } - bool isCompatibleVersion = NetworkMember.IsCompatible(authPacket.GameVersion, GameMain.Version.ToString()) ?? false; + bool isCompatibleVersion = + Version.TryParse(authPacket.GameVersion, out var remoteVersion) + && NetworkMember.IsCompatible(remoteVersion, GameMain.Version); if (!isCompatibleVersion) { - RemovePendingClient(pendingClient, DisconnectReason.InvalidVersion, - $"DisconnectMessage.InvalidVersion~[version]={GameMain.Version}~[clientversion]={authPacket.GameVersion}"); + RemovePendingClient(pendingClient, PeerDisconnectPacket.InvalidVersion()); GameServer.Log($"{authPacket.Name} ({authPacket.SteamId}) couldn't join the server (incompatible game version)", ServerLog.MessageType.Error); DebugConsole.NewMessage($"{authPacket.Name} ({authPacket.SteamId}) couldn't join the server (incompatible game version)", Microsoft.Xna.Framework.Color.Red); @@ -104,7 +110,7 @@ namespace Barotrauma.Networking Client nameTaken = GameMain.Server.ConnectedClients.Find(c => Homoglyphs.Compare(c.Name.ToLower(), authPacket.Name.ToLower())); if (nameTaken != null) { - RemovePendingClient(pendingClient, DisconnectReason.NameTaken, ""); + RemovePendingClient(pendingClient, PeerDisconnectPacket.WithReason(DisconnectReason.NameTaken)); GameServer.Log($"{authPacket.Name} ({authPacket.SteamId}) couldn't join the server (name too similar to the name of the client \"" + nameTaken.Name + "\").", ServerLog.MessageType.Error); return; } @@ -135,7 +141,7 @@ namespace Barotrauma.Networking { const string banMsg = "Failed to enter correct password too many times"; BanPendingClient(pendingClient, banMsg, null); - RemovePendingClient(pendingClient, DisconnectReason.Banned, banMsg); + RemovePendingClient(pendingClient, PeerDisconnectPacket.Banned(banMsg)); return; } } @@ -190,13 +196,13 @@ namespace Barotrauma.Networking { if (IsPendingClientBanned(pendingClient, out string? banReason)) { - RemovePendingClient(pendingClient, DisconnectReason.Banned, banReason); + RemovePendingClient(pendingClient, PeerDisconnectPacket.Banned(banReason)); return; } if (connectedClients.Count >= serverSettings.MaxPlayers) { - RemovePendingClient(pendingClient, DisconnectReason.ServerFull, ""); + RemovePendingClient(pendingClient, PeerDisconnectPacket.WithReason(DisconnectReason.ServerFull)); } if (pendingClient.InitializationStep == ConnectionInitialization.Success) @@ -205,15 +211,15 @@ namespace Barotrauma.Networking connectedClients.Add(newConnection); pendingClients.Remove(pendingClient); - CheckOwnership(pendingClient); + callbacks.OnInitializationComplete.Invoke(newConnection, pendingClient.Name); - OnInitializationComplete?.Invoke(newConnection, pendingClient.Name); + CheckOwnership(pendingClient); } pendingClient.TimeOut -= Timing.Step; if (pendingClient.TimeOut < 0.0) { - RemovePendingClient(pendingClient, DisconnectReason.Unknown, Lidgren.Network.NetConnection.NoResponseMessage); + RemovePendingClient(pendingClient, PeerDisconnectPacket.WithReason(DisconnectReason.Timeout)); } if (Timing.TotalTime < pendingClient.UpdateTime) { return; } @@ -237,7 +243,7 @@ namespace Barotrauma.Networking structToSend = new ServerPeerContentPackageOrderPacket { ServerName = GameMain.Server.ServerName, - ContentPackages = ContentPackageManager.EnabledPackages.All.Where(cp => cp.HasMultiplayerSyncedContent) + ContentPackages = ContentPackageManager.EnabledPackages.All.Where(cp => cp.HasMultiplayerSyncedContent || cp.Files.All(f => f is SubmarineFile)) .Select(contentPackage => new ServerContentPackage(contentPackage, timeNow)) .ToImmutableArray() }; @@ -267,11 +273,11 @@ namespace Barotrauma.Networking protected virtual void CheckOwnership(PendingClient pendingClient) { } - protected void RemovePendingClient(PendingClient pendingClient, DisconnectReason reason, string? msg) + protected void RemovePendingClient(PendingClient pendingClient, PeerDisconnectPacket peerDisconnectPacket) { if (pendingClients.Contains(pendingClient)) { - Disconnect(pendingClient.Connection, $"{reason}/{msg}"); + Disconnect(pendingClient.Connection, peerDisconnectPacket); pendingClients.Remove(pendingClient); @@ -285,6 +291,6 @@ namespace Barotrauma.Networking } public abstract void Send(IWriteMessage msg, NetworkConnection conn, DeliveryMethod deliveryMethod, bool compressPastThreshold = true); - public abstract void Disconnect(NetworkConnection conn, string? msg = null); + public abstract void Disconnect(NetworkConnection conn, PeerDisconnectPacket peerDisconnectPacket); } } \ No newline at end of file diff --git a/Barotrauma/BarotraumaServer/ServerSource/Networking/Primitives/Peers/Server/SteamP2PServerPeer.cs b/Barotrauma/BarotraumaServer/ServerSource/Networking/Primitives/Peers/Server/SteamP2PServerPeer.cs index 70976272e..8bf68f4b5 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Networking/Primitives/Peers/Server/SteamP2PServerPeer.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Networking/Primitives/Peers/Server/SteamP2PServerPeer.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Linq; +using Microsoft.Xna.Framework; namespace Barotrauma.Networking { @@ -16,7 +17,7 @@ namespace Barotrauma.Networking private SteamId ReadSteamId(IReadMessage inc) => new SteamId(inc.ReadUInt64() ^ ownerKey64); private void WriteSteamId(IWriteMessage msg, SteamId val) => msg.WriteUInt64(val.Value ^ ownerKey64); - public SteamP2PServerPeer(SteamId steamId, int ownerKey, ServerSettings settings) + public SteamP2PServerPeer(SteamId steamId, int ownerKey, ServerSettings settings, Callbacks callbacks) : base(callbacks) { serverSettings = settings; @@ -43,7 +44,7 @@ namespace Barotrauma.Networking started = true; } - public override void Close(string? msg = null) + public override void Close() { if (!started) { return; } @@ -51,12 +52,12 @@ namespace Barotrauma.Networking for (int i = pendingClients.Count - 1; i >= 0; i--) { - RemovePendingClient(pendingClients[i], DisconnectReason.ServerShutdown, msg); + RemovePendingClient(pendingClients[i], PeerDisconnectPacket.WithReason(DisconnectReason.ServerShutdown)); } for (int i = connectedClients.Count - 1; i >= 0; i--) { - Disconnect(connectedClients[i], msg ?? DisconnectReason.ServerShutdown.ToString()); + Disconnect(connectedClients[i], PeerDisconnectPacket.WithReason(DisconnectReason.ServerShutdown)); } pendingClients.Clear(); @@ -64,19 +65,13 @@ namespace Barotrauma.Networking ChildServerRelay.ShutDown(); - OnShutdown?.Invoke(); + callbacks.OnShutdown.Invoke(); } public override void Update(float deltaTime) { if (!started) { return; } - if (OnOwnerDetermined != null && OwnerConnection != null) - { - OnOwnerDetermined?.Invoke(OwnerConnection); - OnOwnerDetermined = null; - } - //backwards for loop so we can remove elements while iterating for (int i = connectedClients.Count - 1; i >= 0; i--) { @@ -84,7 +79,7 @@ namespace Barotrauma.Networking conn.Decay(deltaTime); if (conn.Timeout < 0.0) { - Disconnect(conn, "Timed out"); + Disconnect(conn, PeerDisconnectPacket.WithReason(DisconnectReason.Timeout)); } } @@ -149,24 +144,22 @@ namespace Barotrauma.Networking { if (pendingClient != null) { - RemovePendingClient(pendingClient, DisconnectReason.Banned, banReason); + RemovePendingClient(pendingClient, PeerDisconnectPacket.Banned(banReason)); } else if (connectedClient != null) { - Disconnect(connectedClient, $"{DisconnectReason.Banned}/ {banReason}"); + Disconnect(connectedClient, PeerDisconnectPacket.Banned(banReason)); } } else if (packetHeader.IsDisconnectMessage()) { if (pendingClient != null) { - string disconnectMsg = $"ServerMessage.HasDisconnected~[client]={pendingClient.Name}"; - RemovePendingClient(pendingClient, DisconnectReason.Unknown, disconnectMsg); + RemovePendingClient(pendingClient, PeerDisconnectPacket.WithReason(DisconnectReason.Disconnected)); } else if (connectedClient != null) { - string disconnectMsg = $"ServerMessage.HasDisconnected~[client]={GameMain.Server.ConnectedClients.First(c => c.Connection == connectedClient).Name}"; - Disconnect(connectedClient, disconnectMsg, false); + Disconnect(connectedClient, PeerDisconnectPacket.WithReason(DisconnectReason.Disconnected)); } } else if (packetHeader.IsHeartbeatMessage()) @@ -176,28 +169,27 @@ namespace Barotrauma.Networking } else if (packetHeader.IsConnectionInitializationStep()) { + if (!initialization.HasValue) { return; } + ConnectionInitialization initializationStep = initialization.Value; + if (pendingClient != null) { pendingClient.Connection.SetAccountInfo(new AccountInfo(senderSteamId, sentOwnerSteamId)); ReadConnectionInitializationStep( pendingClient, new ReadWriteMessage(inc.Buffer, inc.BitPosition, inc.LengthBits, false), - initialization ?? throw new Exception("Initialization step missing")); + initializationStep); } - else if (initialization.HasValue) + else if (initializationStep == ConnectionInitialization.ConnectionStarted) { - ConnectionInitialization initializationStep = initialization.Value; - if (initializationStep == ConnectionInitialization.ConnectionStarted) - { - pendingClients.Add(new PendingClient(new SteamP2PConnection(senderSteamId))); - } + pendingClients.Add(new PendingClient(new SteamP2PConnection(senderSteamId))); } } else if (connectedClient != null) { var packet = INetSerializableStruct.Read(inc); IReadMessage msg = new ReadOnlyMessage(packet.Buffer, packetHeader.IsCompressed(), 0, packet.Length, connectedClient); - OnMessageReceived?.Invoke(connectedClient, msg); + callbacks.OnMessageReceived.Invoke(connectedClient, msg); } } else //sender is owner @@ -227,7 +219,8 @@ namespace Barotrauma.Networking }; OwnerConnection.SetAccountInfo(new AccountInfo(ownerSteamId, ownerSteamId)); - OnInitializationComplete?.Invoke(OwnerConnection, packet.OwnerName); + callbacks.OnInitializationComplete.Invoke(OwnerConnection, packet.OwnerName); + callbacks.OnOwnerDetermined.Invoke(OwnerConnection); } return; @@ -241,7 +234,7 @@ namespace Barotrauma.Networking { var packet = INetSerializableStruct.Read(inc); IReadMessage msg = new ReadOnlyMessage(packet.Buffer, packetHeader.IsCompressed(), 0, packet.Length, OwnerConnection); - OnMessageReceived?.Invoke(OwnerConnection!, msg); + callbacks.OnMessageReceived.Invoke(OwnerConnection!, msg); } } } @@ -281,27 +274,21 @@ namespace Barotrauma.Networking SendMsgInternal(steamP2PConn, headers, body); } - private void SendDisconnectMessage(SteamId steamId, string? msg) + private void SendDisconnectMessage(SteamId steamId, PeerDisconnectPacket peerDisconnectPacket) { if (!started) { return; } - if (string.IsNullOrWhiteSpace(msg)) { return; } - var headers = new PeerPacketHeaders { DeliveryMethod = DeliveryMethod.Reliable, PacketHeader = PacketHeader.IsDisconnectMessage | PacketHeader.IsServerMessage, Initialization = null }; - var packet = new PeerDisconnectPacket - { - Message = msg - }; - SendMsgInternal(steamId, headers, packet); + SendMsgInternal(steamId, headers, peerDisconnectPacket); } - private void Disconnect(NetworkConnection conn, string? msg, bool sendDisconnectMessage) + public override void Disconnect(NetworkConnection conn, PeerDisconnectPacket peerDisconnectPacket) { if (!started) { return; } @@ -309,26 +296,21 @@ namespace Barotrauma.Networking if (!conn.AccountInfo.AccountId.TryUnwrap(out var connAccountId) || !(connAccountId is SteamId connSteamId)) { return; } - if (sendDisconnectMessage) { SendDisconnectMessage(connSteamId, msg); } + SendDisconnectMessage(connSteamId, peerDisconnectPacket); if (connectedClients.Contains(steamp2pConn)) { steamp2pConn.Status = NetworkConnectionStatus.Disconnected; connectedClients.Remove(steamp2pConn); - OnDisconnect?.Invoke(conn, msg); + callbacks.OnDisconnect.Invoke(conn, peerDisconnectPacket); Steam.SteamManager.StopAuthSession(connSteamId); } else if (steamp2pConn == OwnerConnection) { - //TODO: fix? + throw new InvalidOperationException("Cannot disconnect owner peer"); } } - public override void Disconnect(NetworkConnection conn, string? msg = null) - { - Disconnect(conn, msg, true); - } - protected override void SendMsgInternal(NetworkConnection conn, PeerPacketHeaders headers, INetSerializableStruct? body) { var connSteamId = conn is SteamP2PConnection { Endpoint: SteamP2PEndpoint { SteamId: var id } } ? id : null; diff --git a/Barotrauma/BarotraumaServer/ServerSource/Networking/RespawnManager.cs b/Barotrauma/BarotraumaServer/ServerSource/Networking/RespawnManager.cs index 6d0acea10..b8f298682 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Networking/RespawnManager.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Networking/RespawnManager.cs @@ -505,9 +505,10 @@ namespace Barotrauma.Networking var characterData = campaign?.GetClientCharacterData(clients[i]); if (characterData != null && Level.Loaded?.Type != LevelData.LevelType.Outpost && characterData.HasSpawned) { + //we need to reapply the previous respawn penalty affliction or successive deaths won't make it stack + characterData.ApplyHealthData(character, (AfflictionPrefab ap) => ap == GetRespawnPenaltyAfflictionPrefab()); GiveRespawnPenaltyAffliction(character); } - if (characterData == null || characterData.HasSpawned) { //give the character the items they would've gotten if they had spawned in the main sub @@ -555,7 +556,7 @@ namespace Barotrauma.Networking foreach (Skill skill in characterInfo.Job.GetSkills()) { var skillPrefab = characterInfo.Job.Prefab.Skills.Find(s => skill.Identifier == s.Identifier); - if (skillPrefab == null) { continue; } + if (skillPrefab == null || skill.Level < skillPrefab.LevelRange.End) { continue; } skill.Level = MathHelper.Lerp(skill.Level, skillPrefab.LevelRange.End, SkillReductionOnDeath); } } diff --git a/Barotrauma/BarotraumaServer/ServerSource/Networking/ServerSettings.cs b/Barotrauma/BarotraumaServer/ServerSource/Networking/ServerSettings.cs index 3a997b41a..603683348 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Networking/ServerSettings.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Networking/ServerSettings.cs @@ -18,10 +18,14 @@ namespace Barotrauma.Networking { if (!PropEquals(lastSyncedValue, Value)) { - LastUpdateID = (UInt16)(GameMain.NetLobbyScreen.LastUpdateID); + LastUpdateID = GameMain.NetLobbyScreen.LastUpdateID; lastSyncedValue = Value; } } + public void ForceUpdate() + { + LastUpdateID = GameMain.NetLobbyScreen.LastUpdateID++; + } } public static readonly string ClientPermissionsFile = "Data" + Path.DirectorySeparatorChar + "clientpermissions.xml"; @@ -54,6 +58,15 @@ namespace Barotrauma.Networking LoadClientPermissions(); } + public void ForcePropertyUpdate() + { + UpdateFlag(NetFlags.Properties); + foreach (NetPropertyData property in netProperties.Values) + { + property.ForceUpdate(); + } + } + private void WriteNetProperties(IWriteMessage outMsg, Client c) { foreach (UInt32 key in netProperties.Keys) @@ -197,27 +210,32 @@ namespace Barotrauma.Networking { int orBits = incMsg.ReadRangedInteger(0, (int)Barotrauma.MissionType.All) & (int)Barotrauma.MissionType.All; int andBits = incMsg.ReadRangedInteger(0, (int)Barotrauma.MissionType.All) & (int)Barotrauma.MissionType.All; - GameMain.NetLobbyScreen.MissionType = (Barotrauma.MissionType)(((int)GameMain.NetLobbyScreen.MissionType | orBits) & andBits); + GameMain.NetLobbyScreen.MissionType = (MissionType)(((int)GameMain.NetLobbyScreen.MissionType | orBits) & andBits); int traitorSetting = (int)TraitorsEnabled + incMsg.ReadByte() - 1; - if (traitorSetting < 0) traitorSetting = 2; - if (traitorSetting > 2) traitorSetting = 0; + if (traitorSetting < 0) { traitorSetting = 2; } + if (traitorSetting > 2) { traitorSetting = 0; } TraitorsEnabled = (YesNoMaybe)traitorSetting; int botCount = BotCount + incMsg.ReadByte() - 1; - if (botCount < 0) botCount = MaxBotCount; - if (botCount > MaxBotCount) botCount = 0; + if (botCount < 0) { botCount = MaxBotCount; } + if (botCount > MaxBotCount) { botCount = 0; } BotCount = botCount; int botSpawnMode = (int)BotSpawnMode + incMsg.ReadByte() - 1; - if (botSpawnMode < 0) botSpawnMode = 1; - if (botSpawnMode > 1) botSpawnMode = 0; + if (botSpawnMode < 0) { botSpawnMode = 1; } + if (botSpawnMode > 1) { botSpawnMode = 0; } BotSpawnMode = (BotSpawnMode)botSpawnMode; float levelDifficulty = incMsg.ReadSingle(); - if (levelDifficulty >= 0.0f) SelectedLevelDifficulty = levelDifficulty; + if (levelDifficulty >= 0.0f) { SelectedLevelDifficulty = levelDifficulty; } - UseRespawnShuttle = incMsg.ReadBoolean(); + bool changedUseRespawnShuttle = incMsg.ReadBoolean(); + bool useRespawnShuttle = incMsg.ReadBoolean(); + if (changedUseRespawnShuttle) + { + UseRespawnShuttle = useRespawnShuttle; + } bool changedAutoRestart = incMsg.ReadBoolean(); bool autoRestart = incMsg.ReadBoolean(); diff --git a/Barotrauma/BarotraumaServer/ServerSource/Networking/Voting.cs b/Barotrauma/BarotraumaServer/ServerSource/Networking/Voting.cs index ff031da8e..be597c2da 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Networking/Voting.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Networking/Voting.cs @@ -216,6 +216,14 @@ namespace Barotrauma } } + public void ResetVotes(IEnumerable connectedClients, bool resetKickVotes) + { + foreach (Client client in connectedClients) + { + client.ResetVotes(resetKickVotes); + } + } + public void ServerRead(IReadMessage inc, Client sender) { if (GameMain.Server == null || sender == null) { return; } diff --git a/Barotrauma/BarotraumaServer/ServerSource/Screens/NetLobbyScreen.cs b/Barotrauma/BarotraumaServer/ServerSource/Screens/NetLobbyScreen.cs index e746fac64..ec2ca5d40 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Screens/NetLobbyScreen.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Screens/NetLobbyScreen.cs @@ -192,7 +192,7 @@ namespace Barotrauma public override void Select() { base.Select(); - GameMain.Server.Voting.ResetVotes(GameMain.Server.ConnectedClients); + GameMain.Server.Voting.ResetVotes(GameMain.Server.ConnectedClients, resetKickVotes: false); if (SelectedMode != GameModePreset.MultiPlayerCampaign && GameMain.GameSession?.GameMode is CampaignMode && Selected == this) { GameMain.GameSession = null; diff --git a/Barotrauma/BarotraumaServer/ServerSource/Steam/SteamManager.cs b/Barotrauma/BarotraumaServer/ServerSource/Steam/SteamManager.cs index f4a37340a..18e6c142d 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Steam/SteamManager.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Steam/SteamManager.cs @@ -53,12 +53,13 @@ namespace Barotrauma.Steam Steamworks.SteamServer.Passworded = server.ServerSettings.HasPassword; Steamworks.SteamServer.MapName = GameMain.NetLobbyScreen?.SelectedSub?.DisplayName?.Value ?? ""; Steamworks.SteamServer.SetKey("haspassword", server.ServerSettings.HasPassword.ToString()); - Steamworks.SteamServer.SetKey("message", GameMain.Server.ServerSettings.ServerMessageText); + Steamworks.SteamServer.SetKey("message", server.ServerSettings.ServerMessageText); Steamworks.SteamServer.SetKey("version", GameMain.Version.ToString()); - Steamworks.SteamServer.SetKey("playercount", GameMain.Server.ConnectedClients.Count.ToString()); + Steamworks.SteamServer.SetKey("playercount", server.ConnectedClients.Count.ToString()); Steamworks.SteamServer.SetKey("contentpackage", string.Join(",", contentPackages.Select(cp => cp.Name))); Steamworks.SteamServer.SetKey("contentpackagehash", string.Join(",", contentPackages.Select(cp => cp.Hash.StringRepresentation))); - Steamworks.SteamServer.SetKey("contentpackageid", string.Join(",", contentPackages.Select(cp => cp.SteamWorkshopId))); + Steamworks.SteamServer.SetKey("contentpackageid", string.Join(",", contentPackages.Select(cp + => cp.UgcId.TryUnwrap(out var ugcId) ? ugcId.StringRepresentation : ""))); Steamworks.SteamServer.SetKey("modeselectionmode", server.ServerSettings.ModeSelectionMode.ToString()); Steamworks.SteamServer.SetKey("subselectionmode", server.ServerSettings.SubSelectionMode.ToString()); Steamworks.SteamServer.SetKey("voicechatenabled", server.ServerSettings.VoiceChatEnabled.ToString()); diff --git a/Barotrauma/BarotraumaServer/WindowsServer.csproj b/Barotrauma/BarotraumaServer/WindowsServer.csproj index 319a53b07..68ab0885b 100644 --- a/Barotrauma/BarotraumaServer/WindowsServer.csproj +++ b/Barotrauma/BarotraumaServer/WindowsServer.csproj @@ -6,7 +6,7 @@ Barotrauma FakeFish, Undertow Games Barotrauma Dedicated Server - 0.19.3.0 + 0.19.5.0 Copyright © FakeFish 2018-2022 AnyCPU;x64 DedicatedServer diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/IndoorsSteeringManager.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/IndoorsSteeringManager.cs index 740c80b72..5dc043af1 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/IndoorsSteeringManager.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/IndoorsSteeringManager.cs @@ -527,7 +527,7 @@ namespace Barotrauma { // We'll want this to run each time, because the delegate is used to find a valid button component. bool canAccessButtons = false; - foreach (var button in door.Item.GetConnectedComponents(true)) + foreach (var button in door.Item.GetConnectedComponents(true, connectionFilter: c => c.Name == "toggle" || c.Name == "set_state")) { if (button.HasAccess(character) && (buttonFilter == null || buttonFilter(button))) { @@ -675,6 +675,8 @@ namespace Barotrauma } } float distance = Vector2.DistanceSquared(button.Item.WorldPosition, character.WorldPosition); + //heavily prefer buttons linked to the door, so sub builders can help the bots figure out which button to use by linking them + if (door.Item.linkedTo.Contains(button.Item)) { distance *= 0.1f; } if (closestButton == null || distance < closestDist && character.CanSeeTarget(button.Item)) { closestButton = button; diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/CharacterInfo.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/CharacterInfo.cs index f2d68c7c8..b524580df 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/CharacterInfo.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/CharacterInfo.cs @@ -1634,9 +1634,9 @@ namespace Barotrauma return id; } - public static void ApplyHealthData(Character character, XElement healthData) + public static void ApplyHealthData(Character character, XElement healthData, Func afflictionPredicate = null) { - if (healthData != null) { character?.CharacterHealth.Load(healthData); } + if (healthData != null) { character?.CharacterHealth.Load(healthData, afflictionPredicate); } } /// diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/CharacterPrefab.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/CharacterPrefab.cs index f41b7720f..cb1b33763 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/CharacterPrefab.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/CharacterPrefab.cs @@ -12,12 +12,8 @@ namespace Barotrauma { public readonly static PrefabCollection Prefabs = new PrefabCollection(); - private bool disposed = false; public override void Dispose() { - if (disposed) { return; } - disposed = true; - Prefabs.Remove(this); Character.RemoveByPrefab(this); } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/CorpsePrefab.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/CorpsePrefab.cs index ae592923a..f34b8ae11 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/CorpsePrefab.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/CorpsePrefab.cs @@ -11,13 +11,7 @@ namespace Barotrauma { public static readonly PrefabCollection Prefabs = new PrefabCollection(); - private bool disposed = false; - public override void Dispose() - { - if (disposed) { return; } - disposed = true; - Prefabs.Remove(this); - } + public override void Dispose() { } public static CorpsePrefab Get(Identifier identifier) { diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/Health/CharacterHealth.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/Health/CharacterHealth.cs index 58c1de0d0..685429eb9 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/Health/CharacterHealth.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/Health/CharacterHealth.cs @@ -1227,7 +1227,7 @@ namespace Barotrauma } } - public void Load(XElement element) + public void Load(XElement element, Func afflictionPredicate = null) { foreach (var subElement in element.Elements()) { @@ -1260,6 +1260,7 @@ namespace Barotrauma DebugConsole.ThrowError($"Error while loading character health: affliction \"{id}\" not found."); return; } + if (afflictionPredicate != null && !afflictionPredicate.Invoke(afflictionPrefab)) { return; } float strength = afflictionElement.GetAttributeFloat("strength", 0.0f); var irremovableAffliction = irremovableAfflictions.FirstOrDefault(a => a.Prefab == afflictionPrefab); if (irremovableAffliction != null) diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/Jobs/JobPrefab.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/Jobs/JobPrefab.cs index b0df4f80d..2db2aaadf 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/Jobs/JobPrefab.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/Jobs/JobPrefab.cs @@ -65,13 +65,7 @@ namespace Barotrauma { public static readonly PrefabCollection Prefabs = new PrefabCollection(); - private bool disposed = false; - public override void Dispose() - { - if (disposed) { return; } - disposed = true; - Prefabs.Remove(this); - } + public override void Dispose() { } private static readonly Dictionary _itemRepairPriorities = new Dictionary(); /// diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/Talents/TalentPrefab.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/Talents/TalentPrefab.cs index 2e505890e..d8f954873 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/Talents/TalentPrefab.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/Talents/TalentPrefab.cs @@ -56,11 +56,6 @@ namespace Barotrauma } } - private bool disposed = false; - public override void Dispose() - { - if (disposed) { return; } - disposed = true; - } + public override void Dispose() { } } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/ContentManagement/ContentFile/GenericPrefabFile.cs b/Barotrauma/BarotraumaShared/SharedSource/ContentManagement/ContentFile/GenericPrefabFile.cs index cd0906887..b57133514 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/ContentManagement/ContentFile/GenericPrefabFile.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/ContentManagement/ContentFile/GenericPrefabFile.cs @@ -40,7 +40,9 @@ namespace Barotrauma } catch { - prefab.Dispose(); //clean up before rethrowing, since some prefab types might lock resources + //clean up before rethrowing, since some prefab types might lock resources + prefab.Dispose(); + Prefabs.Remove(prefab); throw; } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/ContentManagement/ContentPackage/ContentPackage.cs b/Barotrauma/BarotraumaShared/SharedSource/ContentManagement/ContentPackage/ContentPackage.cs index 1cfef53ce..d99d29b57 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/ContentManagement/ContentPackage/ContentPackage.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/ContentManagement/ContentPackage/ContentPackage.cs @@ -29,25 +29,25 @@ namespace Barotrauma public readonly ImmutableArray AltNames; public readonly string Path; public string Dir => Barotrauma.IO.Path.GetDirectoryName(Path) ?? ""; - public readonly UInt64 SteamWorkshopId; + public readonly Option UgcId; public readonly Version GameVersion; public readonly string ModVersion; public Md5Hash Hash { get; private set; } - public readonly DateTime? InstallTime; + public readonly Option InstallTime; public ImmutableArray Files { get; private set; } public ImmutableArray Errors { get; private set; } public async Task IsUpToDate() { - if (SteamWorkshopId != 0 && InstallTime.HasValue) - { - Steamworks.Ugc.Item? item = await SteamManager.Workshop.GetItem(SteamWorkshopId); - if (item is null) { return true; } - return item.Value.LatestUpdateTime <= InstallTime; - } - return true; + if (!UgcId.TryUnwrap(out var ugcId)) { return true; } + if (!(ugcId is SteamWorkshopId steamWorkshopId)) { return true; } + if (!InstallTime.TryUnwrap(out var installTime)) { return true; } + + Steamworks.Ugc.Item? item = await SteamManager.Workshop.GetItem(steamWorkshopId.Value); + if (item is null) { return true; } + return item.Value.LatestUpdateTime <= installTime; } public int Index => ContentPackageManager.EnabledPackages.IndexOf(this); @@ -66,18 +66,19 @@ namespace Barotrauma AltNames = rootElement.GetAttributeStringArray("altnames", Array.Empty()) .Select(n => n.Trim()).ToImmutableArray(); AssertCondition(!string.IsNullOrEmpty(Name), "Name is null or empty"); - SteamWorkshopId = rootElement.GetAttributeUInt64("steamworkshopid", 0); + + UInt64 steamWorkshopId = rootElement.GetAttributeUInt64("steamworkshopid", 0); + + UgcId = steamWorkshopId != 0 + ? Option.Some(new SteamWorkshopId(steamWorkshopId)) + : Option.None(); GameVersion = rootElement.GetAttributeVersion("gameversion", GameMain.Version); ModVersion = rootElement.GetAttributeString("modversion", DefaultModVersion); - if (rootElement.Attribute("installtime") != null) - { - InstallTime = ToolBox.Epoch.ToDateTime(rootElement.GetAttributeUInt("installtime", 0)); - } - else - { - InstallTime = null; - } + UInt64 installTimeUnix = rootElement.GetAttributeUInt64("installtime", 0); + InstallTime = installTimeUnix != 0 + ? Option.Some(ToolBox.Epoch.ToDateTime(installTimeUnix)) + : Option.None(); var fileResults = rootElement.Elements() .Select(e => ContentFile.CreateFromXElement(this, e)) diff --git a/Barotrauma/BarotraumaShared/SharedSource/ContentManagement/ContentPackage/ContentPackageId/ContentPackageId.cs b/Barotrauma/BarotraumaShared/SharedSource/ContentManagement/ContentPackage/ContentPackageId/ContentPackageId.cs new file mode 100644 index 000000000..6a9f22ba3 --- /dev/null +++ b/Barotrauma/BarotraumaShared/SharedSource/ContentManagement/ContentPackage/ContentPackageId/ContentPackageId.cs @@ -0,0 +1,19 @@ +#nullable enable + +namespace Barotrauma +{ + public abstract class ContentPackageId + { + public abstract string StringRepresentation { get; } + + public override string ToString() + => StringRepresentation; + + public abstract override bool Equals(object? obj); + + public abstract override int GetHashCode(); + + public static Option Parse(string s) + => ReflectionUtils.ParseDerived(s); + } +} \ No newline at end of file diff --git a/Barotrauma/BarotraumaShared/SharedSource/ContentManagement/ContentPackage/ContentPackageId/SteamWorkshopId.cs b/Barotrauma/BarotraumaShared/SharedSource/ContentManagement/ContentPackage/ContentPackageId/SteamWorkshopId.cs new file mode 100644 index 000000000..6e8411d9d --- /dev/null +++ b/Barotrauma/BarotraumaShared/SharedSource/ContentManagement/ContentPackage/ContentPackageId/SteamWorkshopId.cs @@ -0,0 +1,32 @@ +#nullable enable +using System; +using System.Globalization; + +namespace Barotrauma +{ + sealed class SteamWorkshopId : ContentPackageId + { + public readonly UInt64 Value; + + public SteamWorkshopId(UInt64 value) + { + Value = value; + } + + private const string Prefix = "STEAM_WORKSHOP_"; + + public override string StringRepresentation => Value.ToString(CultureInfo.InvariantCulture); + + public override bool Equals(object? obj) + => obj is SteamWorkshopId otherWorkshopId && otherWorkshopId.Value == Value; + + public override int GetHashCode() => Value.GetHashCode(); + + public new static Option Parse(string s) + { + if (s.StartsWith(Prefix)) { s = s[Prefix.Length..]; } + if (!UInt64.TryParse(s, out var id) || id == 0) { return Option.None(); } + return Option.Some(new SteamWorkshopId(id)); + } + } +} \ No newline at end of file diff --git a/Barotrauma/BarotraumaShared/SharedSource/ContentManagement/ContentPackageManager.cs b/Barotrauma/BarotraumaShared/SharedSource/ContentManagement/ContentPackageManager.cs index 6eb09305c..11862c85b 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/ContentManagement/ContentPackageManager.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/ContentManagement/ContentPackageManager.cs @@ -181,7 +181,7 @@ namespace Barotrauma { if (Core != null && !ContentPackageManager.CorePackages.Contains(Core)) { - SetCore(ContentPackageManager.WorkshopPackages.Core.FirstOrDefault(p => p.SteamWorkshopId == Core.SteamWorkshopId) ?? + SetCore(ContentPackageManager.WorkshopPackages.Core.FirstOrDefault(p => p.UgcId == Core.UgcId) ?? ContentPackageManager.CorePackages.First()); } @@ -193,7 +193,7 @@ namespace Barotrauma newRegular.Add(p); } else if (ContentPackageManager.WorkshopPackages.Regular.FirstOrDefault(p2 - => p2.SteamWorkshopId == p.SteamWorkshopId) is { } newP) + => p2.UgcId == p.UgcId) is { } newP) { newRegular.Add(newP); } diff --git a/Barotrauma/BarotraumaShared/SharedSource/ContentManagement/ContentPath.cs b/Barotrauma/BarotraumaShared/SharedSource/ContentManagement/ContentPath.cs index b7388bb2b..4e0a4328b 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/ContentManagement/ContentPath.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/ContentManagement/ContentPath.cs @@ -43,10 +43,10 @@ namespace Barotrauma cachedValue = cachedValue .Replace(ModDirStr, modPath, StringComparison.OrdinalIgnoreCase) .Replace(string.Format(OtherModDirFmt, ContentPackage.Name), modPath, StringComparison.OrdinalIgnoreCase); - if (ContentPackage.SteamWorkshopId != 0) + if (ContentPackage.UgcId.TryUnwrap(out var ugcId)) { cachedValue = cachedValue - .Replace(string.Format(OtherModDirFmt, ContentPackage.SteamWorkshopId.ToString(CultureInfo.InvariantCulture)), modPath, StringComparison.OrdinalIgnoreCase); + .Replace(string.Format(OtherModDirFmt, ugcId.StringRepresentation), modPath, StringComparison.OrdinalIgnoreCase); } } var allPackages = ContentPackageManager.AllPackages; @@ -55,9 +55,9 @@ namespace Barotrauma #endif foreach (Identifier otherModName in otherMods) { - if (!UInt64.TryParse(otherModName.Value, out UInt64 workshopId)) { workshopId = 0; } + Option ugcId = ContentPackageId.Parse(otherModName.Value); ContentPackage? otherMod = - allPackages.FirstOrDefault(p => workshopId != 0 && p.SteamWorkshopId != 0 && workshopId == p.SteamWorkshopId) + allPackages.FirstOrDefault(p => ugcId == p.UgcId) ?? allPackages.FirstOrDefault(p => p.Name == otherModName) ?? allPackages.FirstOrDefault(p => p.NameMatches(otherModName)) ?? throw new MissingContentPackageException(ContentPackage, otherModName.Value); diff --git a/Barotrauma/BarotraumaShared/SharedSource/CoroutineManager.cs b/Barotrauma/BarotraumaShared/SharedSource/CoroutineManager.cs index 8b3842223..e381b89ac 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/CoroutineManager.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/CoroutineManager.cs @@ -278,6 +278,19 @@ namespace Barotrauma } } } + + public static void ListCoroutines() + { + lock (Coroutines) + { + DebugConsole.NewMessage("***********"); + DebugConsole.NewMessage($"{Coroutines.Count} coroutine(s)"); + foreach (var c in Coroutines) + { + DebugConsole.NewMessage($"- {c.Name}"); + } + } + } } class WaitForSeconds : CoroutineStatus diff --git a/Barotrauma/BarotraumaShared/SharedSource/DebugConsole.cs b/Barotrauma/BarotraumaShared/SharedSource/DebugConsole.cs index ad6fcde98..3899632f6 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/DebugConsole.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/DebugConsole.cs @@ -1651,6 +1651,8 @@ namespace Barotrauma }, isCheat: false)); commands.Add(new Command("listtasks", "listtasks: Lists all asynchronous tasks currently in the task pool.", (string[] args) => { TaskPool.ListTasks(); })); + + commands.Add(new Command("listcoroutines", "listcoroutines: Lists all coroutines currently running.", (string[] args) => { CoroutineManager.ListCoroutines(); })); commands.Add(new Command("calculatehashes", "calculatehashes [content package name]: Show the MD5 hashes of the files in the selected content package. If the name parameter is omitted, the first content package is selected.", (string[] args) => { diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/CheckConditionalAction.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/CheckConditionalAction.cs index cd9087d16..1cda074e2 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/CheckConditionalAction.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/CheckConditionalAction.cs @@ -28,10 +28,7 @@ namespace Barotrauma DebugConsole.ShowError($"CheckConditionalAction error: {GetEventName()} uses a CheckConditionalAction with no valid PropertyConditional! This will cause the check to automatically succeed."); } - static bool IsTargetTagAttribute(XAttribute attribute) - { - return attribute.Name.ToString().Equals("targettag", System.StringComparison.OrdinalIgnoreCase); - } + static bool IsTargetTagAttribute(XAttribute attribute) => attribute.NameAsIdentifier() == "targettag"; } private string GetEventName() diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/CheckConnectionAction.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/CheckConnectionAction.cs new file mode 100644 index 000000000..f2d7af787 --- /dev/null +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/CheckConnectionAction.cs @@ -0,0 +1,65 @@ +using Barotrauma.Extensions; +using Barotrauma.Items.Components; +using System.Linq; + +namespace Barotrauma; + +class CheckConnectionAction : BinaryOptionAction +{ + [Serialize("", IsPropertySaveable.Yes)] + public Identifier ItemTag { get; set; } + + [Serialize("", IsPropertySaveable.Yes)] + public Identifier ConnectionName { get; set; } + + [Serialize("", IsPropertySaveable.Yes)] + public Identifier ConnectedItemTag { get; set; } + + [Serialize("", IsPropertySaveable.Yes)] + public Identifier OtherConnectionName { get; set; } + + public CheckConnectionAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element) { } + + protected override bool? DetermineSuccess() + { + var connectTargets = !ConnectedItemTag.IsEmpty ? ParentEvent.GetTargets(ConnectedItemTag) : Enumerable.Empty(); + foreach (var target in ParentEvent.GetTargets(ItemTag)) + { + if (target is not Item targetItem) { continue; } + if (targetItem.GetComponent() is not ConnectionPanel panel) { continue; } + if (panel.Connections == null || panel.Connections.None()) { continue; } + foreach (var connection in panel.Connections) + { + if (!IsCorrectConnection(connection, ConnectionName)) { continue; } + if (ConnectedItemTag.IsEmpty && OtherConnectionName.IsEmpty) + { + if (connection.Wires.Any()) { return true; } + continue; + } + foreach (var wire in connection.Wires) + { + if (wire.OtherConnection(connection) is not Connection otherConnection) { continue; } + if (ConnectedItemTag.IsEmpty) + { + if (IsCorrectConnection(otherConnection, OtherConnectionName)) { return true; } + } + else if (OtherConnectionName.IsEmpty) + { + if (IsCorrectItem()) { return true; } + } + else + { + if (!IsCorrectConnection(otherConnection, OtherConnectionName)) { continue; } + if (!IsCorrectItem()) { continue; } + return true; + } + + bool IsCorrectItem() => connectTargets.Contains(otherConnection.Item); + } + + bool IsCorrectConnection(Connection connection, Identifier id) => connection.Name.ToIdentifier() == id; + } + } + return false; + } +} \ No newline at end of file diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/CheckItemAction.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/CheckItemAction.cs index b7874d26a..dba8364ef 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/CheckItemAction.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/CheckItemAction.cs @@ -14,6 +14,9 @@ namespace Barotrauma [Serialize("", IsPropertySaveable.Yes)] public string ItemTags { get; set; } + + [Serialize(false, IsPropertySaveable.Yes)] + public bool RequireEquipped { get; set; } private readonly Identifier[] itemIdentifierSplit; private readonly Identifier[] itemTags; @@ -30,20 +33,24 @@ namespace Barotrauma if (!targets.Any()) { return null; } foreach (var target in targets) { - if (!(target is Character chr)) { continue; } - if (chr.Inventory == null) { continue; } - - if (itemTags.Any(tag => chr.Inventory.FindItemByTag(tag, recursive: true) != null)) { return true; } - - foreach (var identifier in itemIdentifierSplit) + if (target is Character character) { - if (chr.Inventory.FindItemByIdentifier(identifier, recursive: true) != null) + if (RequireEquipped) { - return true; + if (itemTags.Any(tag => character.HasEquippedItem(tag))) { return true; } + if (itemIdentifierSplit.Any(identifier => character.HasEquippedItem(identifier))) { return true; } + return false; } + if (character.Inventory is not CharacterInventory inventory) { continue; } + if (itemTags.Any(tag => inventory.FindItemByTag(tag, recursive: true) is not null)) { return true; } + if (itemIdentifierSplit.Any(identifier => inventory.FindItemByIdentifier(identifier, recursive: true) is not null)) { return true; } + } + else if (target is Item item && item.OwnInventory is ItemInventory inventory) + { + if (itemTags.Any(tag => inventory.FindItemByTag(tag, recursive: true) is not null)) { return true; } + if (itemIdentifierSplit.Any(identifier => inventory.FindItemByIdentifier(identifier, recursive: true) is not null)) { return true; } } } - return false; } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/CheckOrderAction.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/CheckOrderAction.cs index 8413b6746..0803242f1 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/CheckOrderAction.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/CheckOrderAction.cs @@ -15,40 +15,36 @@ namespace Barotrauma protected override bool? DetermineSuccess() { - ISerializableEntity target = null; + Character targetCharacter = null; if (!TargetTag.IsEmpty) { foreach (var t in ParentEvent.GetTargets(TargetTag)) { - if (t is ISerializableEntity e) + if (t is Character c) { - target = e; + targetCharacter = c; break; } } } - if (target == null) + if (targetCharacter == null) { - DebugConsole.ShowError($"CheckConditionalAction error: {GetEventName()} uses a CheckOrderAction but no valid target was found for tag \"{TargetTag}\"! This will cause the check to automatically succeed."); - return true; - } - if (target is Character character) - { - var currentOrderInfo = character.GetCurrentOrderWithTopPriority(); - if (currentOrderInfo?.Identifier == OrderIdentifier) - { - if (OrderOption.IsEmpty) - { - return true; - } - else - { - return currentOrderInfo?.Option == OrderOption; - } - } + DebugConsole.ShowError($"CheckConditionalAction error: {GetEventName()} uses a CheckOrderAction but no valid target character was found for tag \"{TargetTag}\"! This will cause the check to automatically fail."); return false; } - return true; + var currentOrderInfo = targetCharacter.GetCurrentOrderWithTopPriority(); + if (currentOrderInfo?.Identifier == OrderIdentifier) + { + if (OrderOption.IsEmpty) + { + return true; + } + else + { + return currentOrderInfo?.Option == OrderOption; + } + } + return false; } private string GetEventName() diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/CheckSelectedItemAction.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/CheckSelectedItemAction.cs new file mode 100644 index 000000000..1c9903f6a --- /dev/null +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/CheckSelectedItemAction.cs @@ -0,0 +1,89 @@ +using Barotrauma.Extensions; +using System.Collections.Generic; + +namespace Barotrauma +{ + class CheckSelectedItemAction : BinaryOptionAction + { + public enum SelectedItemType { Primary, Secondary, Any }; + + [Serialize("", IsPropertySaveable.Yes)] + public Identifier CharacterTag { get; set; } + + [Serialize("", IsPropertySaveable.Yes)] + public Identifier TargetTag { get; set; } + + [Serialize(SelectedItemType.Any, IsPropertySaveable.Yes)] + public SelectedItemType ItemType { get; set; } + + public CheckSelectedItemAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element) { } + + protected override bool? DetermineSuccess() + { + Character character = null; + if (!CharacterTag.IsEmpty) + { + foreach (var t in ParentEvent.GetTargets(CharacterTag)) + { + if (t is Character c) + { + character = c; + break; + } + } + } + if (character == null) + { + DebugConsole.ShowError($"CheckSelectedItemAction error: {GetEventName()} uses a CheckSelectedItemAction but no valid character was found for tag \"{CharacterTag}\"! This will cause the check to automatically fail."); + return false; + } + if (!TargetTag.IsEmpty) + { + IEnumerable targets = ParentEvent.GetTargets(TargetTag); + if (targets.None()) + { + DebugConsole.ShowError($"CheckSelectedItemAction error: {GetEventName()} uses a CheckSelectedItemAction but no valid targets were found for tag \"{TargetTag}\"! This will cause the check to automatically fail."); + return false; + } + foreach (var target in targets) + { + if (target is not Item targetItem) + { + continue; + } + if (IsSelected(targetItem)) + { + return true; + } + } + return false; + + bool IsSelected(Item item) + { + return ItemType switch + { + SelectedItemType.Any => character.IsAnySelectedItem(item), + SelectedItemType.Primary => character.SelectedItem == item, + SelectedItemType.Secondary => character.SelectedSecondaryItem == item, + _ => false + }; + } + } + else + { + return ItemType switch + { + SelectedItemType.Any => !character.HasSelectedAnyItem, + SelectedItemType.Primary => character.SelectedItem == null, + SelectedItemType.Secondary => character.SelectedSecondaryItem == null, + _ => false + }; + } + } + + private string GetEventName() + { + return ParentEvent?.Prefab?.Identifier is { IsEmpty: false } identifier ? $"the event \"{identifier}\"" : "an unknown event"; + } + } +} \ No newline at end of file diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/CheckTalentAction.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/CheckTalentAction.cs new file mode 100644 index 000000000..b974c6f83 --- /dev/null +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/CheckTalentAction.cs @@ -0,0 +1,49 @@ +#nullable enable + +namespace Barotrauma +{ + internal sealed class CheckTalentAction : BinaryOptionAction + { + [Serialize("", IsPropertySaveable.Yes)] + public Identifier TalentIdentifier { get; set; } + + [Serialize("", IsPropertySaveable.Yes)] + public Identifier TargetTag { get; set; } + + public CheckTalentAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element) { } + + protected override bool? DetermineSuccess() + { + if (TargetTag.IsEmpty) + { + return false; + } + + Character? matchingCharacter = null; + + foreach (Entity entity in ParentEvent.GetTargets(TargetTag)) + { + if (entity is Character character) + { + matchingCharacter = character; + break; + } + } + + return matchingCharacter is not null && matchingCharacter.HasTalent(TalentIdentifier); + } + + public override string ToDebugString() + { + string subActionStr = ""; + if (succeeded.HasValue) + { + subActionStr = $"\n Sub action: {(succeeded.Value ? Success : Failure)?.CurrentSubAction.ColorizeObject()}"; + } + + return $"{ToolBox.GetDebugSymbol(DetermineFinished())} {nameof(CheckTalentAction)} -> (Talent: {TalentIdentifier.ColorizeObject()}" + + $" Succeeded: {(succeeded.HasValue ? succeeded.Value.ToString() : "not determined").ColorizeObject()})" + + subActionStr; + } + } +} \ No newline at end of file diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/MessageBoxAction.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/MessageBoxAction.cs index 1577c7514..2056c9656 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/MessageBoxAction.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/MessageBoxAction.cs @@ -1,10 +1,18 @@ -using System; -using System.Linq; - namespace Barotrauma { - class MessageBoxAction : EventAction + partial class MessageBoxAction : EventAction { + public enum ActionType { Create, Close } + + [Serialize(ActionType.Create, IsPropertySaveable.Yes)] + public ActionType Type { get; set; } + + [Serialize("", IsPropertySaveable.Yes)] + public Identifier Identifier { get; set; } + + [Serialize("", IsPropertySaveable.Yes)] + public string Tag { get; set; } + [Serialize("", IsPropertySaveable.Yes)] public Identifier Header { get; set; } @@ -24,7 +32,7 @@ namespace Barotrauma public string CloseOnInput { get; set; } [Serialize("", IsPropertySaveable.Yes)] - public Identifier CloseOnInteractTag { get; set; } + public Identifier CloseOnSelectTag { get; set; } [Serialize("", IsPropertySaveable.Yes)] public Identifier CloseOnPickUpTag { get; set; } @@ -35,8 +43,11 @@ namespace Barotrauma [Serialize("", IsPropertySaveable.Yes)] public Identifier CloseOnExitRoomName { get; set; } - [Serialize(false, IsPropertySaveable.Yes)] - public bool IsTutorialObjective { get; set; } + [Serialize("", IsPropertySaveable.Yes)] + public Identifier CloseOnInRoomName { get; set; } + + [Serialize("", IsPropertySaveable.Yes)] + public Identifier ObjectiveTag { get; set; } private bool isFinished = false; @@ -45,72 +56,16 @@ namespace Barotrauma public override void Update(float deltaTime) { if (isFinished) { return; } -#if CLIENT - CreateMessageBox(); - if (IsTutorialObjective && GameMain.GameSession?.GameMode is TutorialMode tutorialMode) - { - tutorialMode.Tutorial?.TriggerTutorialSegment(new Tutorials.Tutorial.Segment(Text, CreateMessageBox)); - } -#endif + UpdateProjSpecific(); isFinished = true; } -#if CLIENT - public void CreateMessageBox() - { - new GUIMessageBox( - headerText: TextManager.Get(Header), - text: RichString.Rich(TextManager.ParseInputTypes(TextManager.Get(Text).Fallback(Text.ToString()), useColorHighlight: true)), - buttons: Array.Empty(), - type: GUIMessageBox.Type.Tutorial, - iconStyle: IconStyle, - autoCloseCondition: GetAutoCloseCondition(), - hideCloseButton: HideCloseButton); - } -#endif + partial void UpdateProjSpecific(); - private Func GetAutoCloseCondition() - { - var character = ParentEvent.GetTargets(TargetTag).FirstOrDefault() as Character; - Func autoCloseCondition = null; - if (!string.IsNullOrEmpty(CloseOnInput) && Enum.TryParse(CloseOnInput, true, out InputType closeOnInput)) - { -#if CLIENT - autoCloseCondition = () => PlayerInput.KeyDown(closeOnInput); -#endif - } - else if (!CloseOnInteractTag.IsEmpty) - { - autoCloseCondition = () => character?.SelectedItem != null && character.SelectedItem.HasTag(CloseOnInteractTag); - } - else if (!CloseOnPickUpTag.IsEmpty) - { - autoCloseCondition = () => character?.Inventory != null && character.Inventory.FindItemByTag(CloseOnPickUpTag, recursive: true) != null; - } - else if (!CloseOnEquipTag.IsEmpty) - { - autoCloseCondition = () => character != null && character.HasEquippedItem(CloseOnEquipTag); - } - else if (!CloseOnExitRoomName.IsEmpty) - { - autoCloseCondition = () => character?.CurrentHull != null && character.CurrentHull.RoomName.ToIdentifier() != CloseOnExitRoomName; - } - return autoCloseCondition; - } + public override bool IsFinished(ref string goToLabel) => isFinished; - public override bool IsFinished(ref string goToLabel) - { - return isFinished; - } + public override void Reset() => isFinished = false; - public override void Reset() - { - isFinished = false; - } - - public override string ToDebugString() - { - return $"{ToolBox.GetDebugSymbol(isFinished)} {nameof(MessageBoxAction)}"; - } + public override string ToDebugString() => $"{ToolBox.GetDebugSymbol(isFinished)} {nameof(MessageBoxAction)}"; } } \ No newline at end of file diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/TeleportAction.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/TeleportAction.cs new file mode 100644 index 000000000..1aacece60 --- /dev/null +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/TeleportAction.cs @@ -0,0 +1,48 @@ +namespace Barotrauma; + +class TeleportAction : EventAction +{ + public enum TeleportPosition { MainSub, Outpost } + + [Serialize(TeleportPosition.MainSub, IsPropertySaveable.Yes)] + public TeleportPosition Position { get; set; } + + [Serialize(SpawnType.Human, IsPropertySaveable.Yes)] + public SpawnType SpawnType { get; set; } + + [Serialize("", IsPropertySaveable.Yes)] + public string SpawnPointTag { get; set; } + + [Serialize("", IsPropertySaveable.Yes)] + public Identifier TargetTag { get; set; } + + private bool isFinished; + + public TeleportAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element) { } + + public override void Update(float deltaTime) + { + if (isFinished) { return; } + Submarine sub = Position switch + { + TeleportPosition.MainSub => Submarine.MainSub, + TeleportPosition.Outpost => GameMain.GameSession?.Level?.StartOutpost, + _ => null + }; + if (WayPoint.GetRandom(spawnType: SpawnType, sub: sub, spawnPointTag: SpawnPointTag) is WayPoint wp) + { + foreach (var target in ParentEvent.GetTargets(TargetTag)) + { + if (target is Character c) + { + c.TeleportTo(wp.WorldPosition); + } + } + } + isFinished = true; + } + + public override bool IsFinished(ref string goToLabel) => isFinished; + + public override void Reset() => isFinished = false; +} \ No newline at end of file diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/TutorialHighlightAction.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/TutorialHighlightAction.cs new file mode 100644 index 000000000..eebac860d --- /dev/null +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/TutorialHighlightAction.cs @@ -0,0 +1,27 @@ +namespace Barotrauma; + +partial class TutorialHighlightAction : EventAction +{ + [Serialize("", IsPropertySaveable.Yes)] + public Identifier TargetTag { get; set; } + + [Serialize(true, IsPropertySaveable.Yes)] + public bool State { get; set; } + + private bool isFinished; + + public TutorialHighlightAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element) { } + + public override void Update(float deltaTime) + { + if (isFinished) { return; } + UpdateProjSpecific(); + isFinished = true; + } + + partial void UpdateProjSpecific(); + + public override bool IsFinished(ref string goToLabel) => isFinished; + + public override void Reset() => isFinished = false; +} \ No newline at end of file diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/TutorialIconAction.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/TutorialIconAction.cs new file mode 100644 index 000000000..317966346 --- /dev/null +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/TutorialIconAction.cs @@ -0,0 +1,65 @@ +using System.Linq; + +namespace Barotrauma; + +class TutorialIconAction : EventAction +{ + public enum ActionType { Add, Remove, RemoveTarget, RemoveIcon, Clear }; + + [Serialize(ActionType.Add, IsPropertySaveable.Yes)] + public ActionType Type { get; set; } + + [Serialize("", IsPropertySaveable.Yes)] + public Identifier TargetTag { get; set; } + + [Serialize("", IsPropertySaveable.Yes)] + public string IconStyle { get; set; } + + private bool isFinished; + + public TutorialIconAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element) { } + + public override void Update(float deltaTime) + { + if (isFinished) { return; } +#if CLIENT + if (GameMain.GameSession?.GameMode is TutorialMode tutorialMode) + { + if (ParentEvent.GetTargets(TargetTag).FirstOrDefault() is Entity target) + { + if (Type == ActionType.Add) + { + tutorialMode.Tutorial?.Icons.Add((target, IconStyle)); + } + else if(Type == ActionType.Remove) + { + tutorialMode.Tutorial?.Icons.RemoveAll(i => i.entity == target && i.iconStyle.Equals(IconStyle, System.StringComparison.OrdinalIgnoreCase)); + } + else if (Type == ActionType.RemoveTarget) + { + tutorialMode.Tutorial?.Icons.RemoveAll(i => i.entity == target); + } + else if (Type == ActionType.RemoveIcon) + { + tutorialMode.Tutorial?.Icons.RemoveAll(i => i.iconStyle.Equals(IconStyle, System.StringComparison.OrdinalIgnoreCase)); + } + else if (Type == ActionType.Clear) + { + tutorialMode.Tutorial?.Icons.Clear(); + } + } + } +#endif + isFinished = true; + } + + public override bool IsFinished(ref string goToLabel) + { + return isFinished; + } + + public override void Reset() + { + isFinished = false; + } +} \ No newline at end of file diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/TutorialSegmentAction.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/TutorialSegmentAction.cs index a7e6a7658..b447875bc 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/TutorialSegmentAction.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/TutorialSegmentAction.cs @@ -1,12 +1,8 @@ -#if CLIENT -using Barotrauma.Tutorials; -#endif - namespace Barotrauma { - class TutorialSegmentAction : EventAction + partial class TutorialSegmentAction : EventAction { - public enum SegmentActionType { Trigger, Complete, Remove }; + public enum SegmentActionType { Trigger, Add, Complete, CompleteAndRemove, Remove }; [Serialize(SegmentActionType.Trigger, IsPropertySaveable.Yes)] public SegmentActionType Type { get; set; } @@ -15,7 +11,7 @@ namespace Barotrauma public Identifier Id { get; set; } [Serialize("", IsPropertySaveable.Yes)] - public Identifier ObjectiveTextTag { get; set; } + public Identifier ObjectiveTag { get; set; } [Serialize(false, IsPropertySaveable.Yes)] public bool AutoPlayVideo { get; set; } @@ -32,64 +28,21 @@ namespace Barotrauma [Serialize(80, IsPropertySaveable.Yes)] public int Height { get; set; } -#if CLIENT - private readonly Tutorial.Segment segment; -#endif private bool isFinished; - public TutorialSegmentAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element) - { -#if CLIENT - // Only need to create the segment when it's being triggered (otherwise the tutorial already has the segment instance) - if (Type == SegmentActionType.Trigger) - { - segment = new Tutorial.Segment(Id, ObjectiveTextTag, AutoPlayVideo ? Tutorials.AutoPlayVideo.Yes : Tutorials.AutoPlayVideo.No, - new Tutorial.Segment.Text(TextTag, Width, Height, Anchor.Center), - new Tutorial.Segment.Video(VideoFile, TextTag, Width, Height)); - } -#endif - } + public TutorialSegmentAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element) { } public override void Update(float deltaTime) { if (isFinished) { return; } - -#if CLIENT - if (GameMain.GameSession?.GameMode is TutorialMode tutorialMode) - { - if (tutorialMode.Tutorial is Tutorial tutorial) - { - switch (Type) - { - case SegmentActionType.Trigger: - tutorial.TriggerTutorialSegment(segment); - break; - case SegmentActionType.Complete: - tutorial.CompleteTutorialSegment(Id); - break; - case SegmentActionType.Remove: - tutorial.RemoveTutorialSegment(Id); - break; - } - } - } - else - { - DebugConsole.ShowError($"Error in event \"{ParentEvent.Prefab.Identifier}\": attempting to use TutorialSegmentAction during a non-Tutorial game mode!"); - } -#endif - + UpdateProjSpecific(); isFinished = true; } - public override bool IsFinished(ref string goToLabel) - { - return isFinished; - } + partial void UpdateProjSpecific(); - public override void Reset() - { - isFinished = false; - } + public override bool IsFinished(ref string goToLabel) => isFinished; + + public override void Reset() => isFinished = false; } } \ No newline at end of file diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/EventSet.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/EventSet.cs index a8015d651..9b397d4be 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Events/EventSet.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/EventSet.cs @@ -24,7 +24,7 @@ namespace Barotrauma } #endif - class EventSet : Prefab + sealed class EventSet : Prefab { internal class EventDebugStats { @@ -489,12 +489,6 @@ namespace Barotrauma } } - public override void Dispose() - { - foreach (var childSet in ChildSets) - { - childSet.Dispose(); - } - } + public override void Dispose() { } } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Extensions/IEnumerableExtensions.cs b/Barotrauma/BarotraumaShared/SharedSource/Extensions/IEnumerableExtensions.cs index 4039e31dc..9ea8ff2a0 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Extensions/IEnumerableExtensions.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Extensions/IEnumerableExtensions.cs @@ -298,5 +298,15 @@ namespace Barotrauma.Extensions return null; } + + public static IEnumerable NotNull(this IEnumerable source) where T : struct + => source + .Where(nullable => nullable.HasValue) + .Select(nullable => nullable.Value); + + public static IEnumerable NotNone(this IEnumerable> source) + => source + .OfType>() + .Select(some => some.Value); } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Extensions/StringExtensions.cs b/Barotrauma/BarotraumaShared/SharedSource/Extensions/StringExtensions.cs index 7b2e4ab9f..3b56fd1aa 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Extensions/StringExtensions.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Extensions/StringExtensions.cs @@ -1,5 +1,6 @@ #nullable enable using System; +using System.Diagnostics.CodeAnalysis; namespace Barotrauma { @@ -7,14 +8,14 @@ namespace Barotrauma { public static string FallbackNullOrEmpty(this string s, string fallback) => string.IsNullOrEmpty(s) ? fallback : s; - public static bool IsNullOrEmpty(this string? s) => string.IsNullOrEmpty(s); - public static bool IsNullOrWhiteSpace(this string? s) => string.IsNullOrWhiteSpace(s); - public static bool IsNullOrEmpty(this ContentPath? p) => p?.IsNullOrEmpty() ?? true; - public static bool IsNullOrWhiteSpace(this ContentPath? p) => p?.IsNullOrWhiteSpace() ?? true; - public static bool IsNullOrEmpty(this LocalizedString? s) => s is null || string.IsNullOrEmpty(s.Value); - public static bool IsNullOrWhiteSpace(this LocalizedString? s) => s is null || string.IsNullOrWhiteSpace(s.Value); - public static bool IsNullOrEmpty(this RichString? s) => s is null || s.NestedStr.IsNullOrEmpty(); - public static bool IsNullOrWhiteSpace(this RichString? s) => s is null || s.NestedStr.IsNullOrWhiteSpace(); + public static bool IsNullOrEmpty([NotNullWhen(returnValue: false)]this string? s) => string.IsNullOrEmpty(s); + public static bool IsNullOrWhiteSpace([NotNullWhen(returnValue: false)]this string? s) => string.IsNullOrWhiteSpace(s); + public static bool IsNullOrEmpty([NotNullWhen(returnValue: false)]this ContentPath? p) => p?.IsNullOrEmpty() ?? true; + public static bool IsNullOrWhiteSpace([NotNullWhen(returnValue: false)]this ContentPath? p) => p?.IsNullOrWhiteSpace() ?? true; + public static bool IsNullOrEmpty([NotNullWhen(returnValue: false)]this LocalizedString? s) => s is null || string.IsNullOrEmpty(s.Value); + public static bool IsNullOrWhiteSpace([NotNullWhen(returnValue: false)]this LocalizedString? s) => s is null || string.IsNullOrWhiteSpace(s.Value); + public static bool IsNullOrEmpty([NotNullWhen(returnValue: false)]this RichString? s) => s is null || s.NestedStr.IsNullOrEmpty(); + public static bool IsNullOrWhiteSpace([NotNullWhen(returnValue: false)]this RichString? s) => s is null || s.NestedStr.IsNullOrWhiteSpace(); public static string RemoveFromEnd(this string s, string substr, StringComparison stringComparison = StringComparison.Ordinal) => s.EndsWith(substr, stringComparison) ? s.Substring(0, s.Length - substr.Length) : s; diff --git a/Barotrauma/BarotraumaShared/SharedSource/GameSession/GameModes/Tutorials/TutorialPrefab.cs b/Barotrauma/BarotraumaShared/SharedSource/GameSession/GameModes/Tutorials/TutorialPrefab.cs index d1f5112a8..ad6dec773 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/GameSession/GameModes/Tutorials/TutorialPrefab.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/GameSession/GameModes/Tutorials/TutorialPrefab.cs @@ -5,7 +5,13 @@ namespace Barotrauma { class TutorialPrefab : Prefab { - public static readonly PrefabCollection Prefabs = new PrefabCollection(); + + public static readonly PrefabCollection Prefabs = +#if CLIENT + new PrefabCollection(onSort: MainMenuScreen.UpdateInstanceTutorialButtons); +#else + new PrefabCollection(); +#endif public readonly int Order; public readonly bool DisableBotConversations; @@ -54,8 +60,11 @@ namespace Barotrauma return null; } Identifier speciesName = tutorialCharacterElement.GetAttributeIdentifier("speciesname", CharacterPrefab.HumanSpeciesName); - string jobPrefabIdentifier = tutorialCharacterElement.GetAttributeString("jobidentifier", "assistant"); - var jobPrefab = JobPrefab.Prefabs.FirstOrDefault(p => p.Identifier == jobPrefabIdentifier) ?? JobPrefab.Prefabs.First(); + Identifier jobPrefabIdentifier = tutorialCharacterElement.GetAttributeIdentifier("jobidentifier", "assistant"); + if (!JobPrefab.Prefabs.TryGet(jobPrefabIdentifier, out var jobPrefab)) + { + jobPrefab = JobPrefab.Prefabs.First(); + } int jobVariant = tutorialCharacterElement.GetAttributeInt("variant", 0); var characterInfo = new CharacterInfo(speciesName, jobOrJobPrefab: jobPrefab, variant: jobVariant); foreach (var skillElement in tutorialCharacterElement.GetChildElements("skill")) diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Sonar.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Sonar.cs index 44065d74e..07d3b598c 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Sonar.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Sonar.cs @@ -64,6 +64,8 @@ namespace Barotrauma.Items.Components private const float MinZoom = 1.0f, MaxZoom = 4.0f; private float zoom = 1.0f; + /// Accessed through event actions. Do not remove even if there are no references in code. + public bool UseDirectionalPing => useDirectionalPing; private bool useDirectionalPing = false; private Vector2 pingDirection = new Vector2(1.0f, 0.0f); private bool useMineralScanner; diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/BooleanOperatorComponent/BooleanOperatorComponent.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/BooleanOperatorComponent/BooleanOperatorComponent.cs index bd3140234..3803e5b16 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/BooleanOperatorComponent/BooleanOperatorComponent.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/BooleanOperatorComponent/BooleanOperatorComponent.cs @@ -82,9 +82,14 @@ namespace Barotrauma.Items.Components public sealed override void Update(float deltaTime, Camera cam) { int receivedInputs = 0; + bool allInputsTimedOut = true; for (int i = 0; i < timeSinceReceived.Length; i++) { - if (timeSinceReceived[i] <= timeFrame) { receivedInputs += 1; } + if (timeSinceReceived[i] <= timeFrame) + { + allInputsTimedOut = false; + receivedInputs += 1; + } timeSinceReceived[i] += deltaTime; } @@ -93,7 +98,7 @@ namespace Barotrauma.Items.Components if (string.IsNullOrEmpty(signalOut)) { //deactivate the component if state is false and there's no false output (will be woken up by non-zero signals in ReceiveSignal) - if (!state) { IsActive = false; } + if (!state && allInputsTimedOut) { IsActive = false; } return; } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/WaterDetector.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/WaterDetector.cs index 5e70fcf9d..10fec01b0 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/WaterDetector.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/WaterDetector.cs @@ -58,6 +58,9 @@ namespace Barotrauma.Items.Components } } + public bool WaterDetected => isInWater; + public int WaterPercentage => GetWaterPercentage(item.CurrentHull); + public WaterDetector(Item item, ContentXElement element) : base(item, element) { diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Item.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Item.cs index c8fc6f8a2..278b4a102 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Item.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Item.cs @@ -2179,7 +2179,7 @@ namespace Barotrauma /// /// Note: This function generates garbage and might be a bit too heavy to be used once per frame. /// - public List GetConnectedComponents(bool recursive = false, bool allowTraversingBackwards = true) where T : ItemComponent + public List GetConnectedComponents(bool recursive = false, bool allowTraversingBackwards = true, Func connectionFilter = null) where T : ItemComponent { List connectedComponents = new List(); @@ -2195,6 +2195,7 @@ namespace Barotrauma foreach (Connection c in connectionPanel.Connections) { + if (connectionFilter != null && !connectionFilter.Invoke(c)) { continue; } var recipients = c.Recipients; foreach (Connection recipient in recipients) { diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/ItemPrefab.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/ItemPrefab.cs index ce8d957e2..79d80014d 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/ItemPrefab.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/ItemPrefab.cs @@ -807,9 +807,6 @@ namespace Barotrauma //only used if the item doesn't have a name/description defined in the currently selected language string fallbackNameIdentifier = ConfigElement.GetAttributeString("fallbacknameidentifier", ""); - //works the same as nameIdentifier, but just replaces the description - Identifier descriptionIdentifier = ConfigElement.GetAttributeIdentifier("descriptionidentifier", ""); - name = TextManager.Get(nameIdentifier.IsEmpty ? $"EntityName.{Identifier}" : $"EntityName.{nameIdentifier}", @@ -858,18 +855,7 @@ namespace Barotrauma SerializableProperty.DeserializeProperties(this, ConfigElement); - if (descriptionIdentifier != Identifier.Empty) - { - Description = TextManager.Get($"EntityDescription.{descriptionIdentifier}").Fallback(Description); - } - else if (nameIdentifier == Identifier.Empty) - { - Description = TextManager.Get($"EntityDescription.{Identifier}").Fallback(Description); - } - else - { - Description = TextManager.Get($"EntityDescription.{nameIdentifier}").Fallback(Description); - } + LoadDescription(ConfigElement); var allowDroppingOnSwapWith = ConfigElement.GetAttributeIdentifierArray("allowdroppingonswapwith", Array.Empty()); AllowDroppingOnSwapWith = allowDroppingOnSwapWith.ToImmutableHashSet(); @@ -1320,12 +1306,8 @@ namespace Barotrauma throw new InvalidOperationException("Can't call ItemPrefab.CreateInstance"); } - private bool disposed = false; public override void Dispose() { - if (disposed) { return; } - disposed = true; - Prefabs.Remove(this); Item.RemoveByPrefab(this); } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Map/CoreEntityPrefab.cs b/Barotrauma/BarotraumaShared/SharedSource/Map/CoreEntityPrefab.cs index c5c646150..193e7fdf0 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Map/CoreEntityPrefab.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Map/CoreEntityPrefab.cs @@ -84,7 +84,6 @@ namespace Barotrauma } } - private bool disposed = false; public override Sprite Sprite => null; @@ -102,9 +101,8 @@ namespace Barotrauma public override void Dispose() { - if (disposed) { return; } - disposed = true; - Prefabs.Remove(this); + throw new InvalidOperationException( + $"{nameof(CoreEntityPrefab)}.{nameof(Dispose)} should never be called"); } } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Map/ItemAssemblyPrefab.cs b/Barotrauma/BarotraumaShared/SharedSource/Map/ItemAssemblyPrefab.cs index 574115e1f..ab5c17c8b 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Map/ItemAssemblyPrefab.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Map/ItemAssemblyPrefab.cs @@ -157,7 +157,7 @@ namespace Barotrauma public void Delete() { - Dispose(); + Prefabs.Remove(this); try { if (ContentPackage is { Files: { Length: 1 } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Map/Levels/CaveGenerator.cs b/Barotrauma/BarotraumaShared/SharedSource/Map/Levels/CaveGenerator.cs index 133da33e1..4daa4282a 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Map/Levels/CaveGenerator.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Map/Levels/CaveGenerator.cs @@ -238,8 +238,8 @@ namespace Barotrauma //find the edge at the opposite side of the adjacent cell foreach (GraphEdge otherEdge in adjacentEmptyCell.Edges) { - if (Vector2.Dot(adjacentEmptyCell.Center - edge.Center, adjacentEmptyCell.Center - otherEdge.Center) < 0 && - otherEdge.AdjacentCell(adjacentEmptyCell)?.CellType == CellType.Solid) + if (Vector2.Dot(adjacentEmptyCell.Center - edge.Center, adjacentEmptyCell.Center - otherEdge.Center) > 0 && + otherEdge.AdjacentCell(adjacentEmptyCell)?.CellType != CellType.Solid) { adjacentEdge = otherEdge; break; diff --git a/Barotrauma/BarotraumaShared/SharedSource/Map/LinkedSubmarine.cs b/Barotrauma/BarotraumaShared/SharedSource/Map/LinkedSubmarine.cs index a1de6a144..46d549e2f 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Map/LinkedSubmarine.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Map/LinkedSubmarine.cs @@ -11,15 +11,7 @@ namespace Barotrauma { partial class LinkedSubmarinePrefab : MapEntityPrefab { - //public static readonly PrefabCollection Prefabs = new PrefabCollection(); - - private bool disposed = false; - public override void Dispose() - { - if (disposed) { return; } - disposed = true; - //Prefabs.Remove(this); - } + public override void Dispose() { } public readonly SubmarineInfo subInfo; diff --git a/Barotrauma/BarotraumaShared/SharedSource/Map/Map/Location.cs b/Barotrauma/BarotraumaShared/SharedSource/Map/Map/Location.cs index 08ac7d07d..d90c90e99 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Map/Map/Location.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Map/Map/Location.cs @@ -1253,7 +1253,7 @@ namespace Barotrauma { var characters = GameSession.GetSessionCrewCharacters(CharacterType.Both); if (!characters.Any()) { return 0; } - return characters.Max(c => (int)c.GetStatValue(StatTypes.ExtraSpecialSalesCount)); + return characters.Sum(c => (int)c.GetStatValue(StatTypes.ExtraSpecialSalesCount)); } public void Discover(bool checkTalents = true) diff --git a/Barotrauma/BarotraumaShared/SharedSource/Map/MapEntityPrefab.cs b/Barotrauma/BarotraumaShared/SharedSource/Map/MapEntityPrefab.cs index 258e7262f..bdec8d1b4 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Map/MapEntityPrefab.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Map/MapEntityPrefab.cs @@ -280,5 +280,29 @@ namespace Barotrauma return AllowedLinks.Contains(target.Identifier) || target.AllowedLinks.Contains(Identifier) || target.Tags.Any(t => AllowedLinks.Contains(t)) || Tags.Any(t => target.AllowedLinks.Contains(t)); } + + protected void LoadDescription(ContentXElement element) + { + Identifier descriptionIdentifier = element.GetAttributeIdentifier("descriptionidentifier", ""); + Identifier nameIdentifier = element.GetAttributeIdentifier("nameidentifier", ""); + + string originalDescription = Description.Value; + if (descriptionIdentifier != Identifier.Empty) + { + Description = TextManager.Get($"EntityDescription.{descriptionIdentifier}"); + } + else if (nameIdentifier == Identifier.Empty) + { + Description = TextManager.Get($"EntityDescription.{Identifier}"); + } + else + { + Description = TextManager.Get($"EntityDescription.{nameIdentifier}"); + } + if (!originalDescription.IsNullOrEmpty()) + { + Description = Description.Fallback(originalDescription); + } + } } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Map/StructurePrefab.cs b/Barotrauma/BarotraumaShared/SharedSource/Map/StructurePrefab.cs index d13d4216f..3dd5eea35 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Map/StructurePrefab.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Map/StructurePrefab.cs @@ -142,8 +142,6 @@ namespace Barotrauma //only used if the item doesn't have a name/description defined in the currently selected language Identifier fallbackNameIdentifier = element.GetAttributeIdentifier("fallbacknameidentifier", ""); - Identifier descriptionIdentifier = element.GetAttributeIdentifier("descriptionidentifier", ""); - Name = TextManager.Get(nameIdentifier.IsEmpty ? $"EntityName.{Identifier}" : $"EntityName.{nameIdentifier}", @@ -271,18 +269,7 @@ namespace Barotrauma tags.Add("wall".ToIdentifier()); } - if (!descriptionIdentifier.IsEmpty) - { - Description = TextManager.Get($"EntityDescription.{descriptionIdentifier}").Fallback(Description); - } - else if (nameIdentifier.IsEmpty) - { - Description = TextManager.Get($"EntityDescription.{Identifier}").Fallback(Description); - } - else - { - Description = TextManager.Get($"EntityDescription.{nameIdentifier}").Fallback(Description); - } + LoadDescription(element); //backwards compatibility if (element.GetAttribute("size") == null) @@ -331,12 +318,6 @@ namespace Barotrauma throw new NotImplementedException(); } - private bool disposed = false; - public override void Dispose() - { - if (disposed) { return; } - disposed = true; - Prefabs.Remove(this); - } + public override void Dispose() { } } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Map/Submarine.cs b/Barotrauma/BarotraumaShared/SharedSource/Map/Submarine.cs index 50e3f4507..6ffee8449 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Map/Submarine.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Map/Submarine.cs @@ -1548,6 +1548,7 @@ namespace Barotrauma element.Add(new XAttribute("description", Info.Description ?? "")); element.Add(new XAttribute("checkval", Rand.Int(int.MaxValue))); element.Add(new XAttribute("price", Info.Price)); + element.Add(new XAttribute("tier", Info.Tier)); element.Add(new XAttribute("initialsuppliesspawned", Info.InitialSuppliesSpawned)); element.Add(new XAttribute("noitems", Info.NoItems)); element.Add(new XAttribute("lowfuel", !CheckFuel())); diff --git a/Barotrauma/BarotraumaShared/SharedSource/Networking/Client.cs b/Barotrauma/BarotraumaShared/SharedSource/Networking/Client.cs index 1d7e30e5e..84fb06106 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Networking/Client.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Networking/Client.cs @@ -205,15 +205,7 @@ namespace Barotrauma.Networking { votes[(int)voteType] = value; } - - public void ResetVotes() - { - for (int i = 0; i < votes.Length; i++) - { - votes[i] = null; - } - } - + public bool SessionOrAccountIdMatches(string userId) => (AccountId.IsSome() && Networking.AccountId.Parse(userId) == AccountId) || (byte.TryParse(userId, out byte sessionId) && SessionId == sessionId); diff --git a/Barotrauma/BarotraumaShared/SharedSource/Networking/NetworkMember.cs b/Barotrauma/BarotraumaShared/SharedSource/Networking/NetworkMember.cs index 7e93a540c..a1505a420 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Networking/NetworkMember.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Networking/NetworkMember.cs @@ -131,28 +131,29 @@ namespace Barotrauma.Networking enum DisconnectReason { + //do not attempt reconnecting with these reasons Unknown, + Disconnected, Banned, Kicked, ServerShutdown, ServerCrashed, ServerFull, AuthenticationRequired, - SteamAuthenticationRequired, SteamAuthenticationFailed, SessionTaken, TooManyFailedLogins, - NoName, InvalidName, NameTaken, InvalidVersion, - MissingContentPackage, - IncompatibleContentPackage, + SteamP2PError, + + //attempt reconnecting with these reasons + Timeout, ExcessiveDesyncOldEvent, ExcessiveDesyncRemovedEvent, SyncTimeout, - SteamP2PError, - SteamP2PTimeOut, + SteamP2PTimeOut } abstract partial class NetworkMember @@ -163,71 +164,38 @@ namespace Barotrauma.Networking set; } - public virtual bool IsServer - { - get { return false; } - } + public abstract bool IsServer { get; } - public virtual bool IsClient - { - get { return false; } - } + public abstract bool IsClient { get; } public abstract void CreateEntityEvent(INetSerializable entity, NetEntityEvent.IData extraData = null); -#if DEBUG - public Dictionary messageCount = new Dictionary(); -#endif - - protected ServerSettings serverSettings; + public abstract Voting Voting { get; } - public Voting Voting { get; protected set; } - - protected TimeSpan updateInterval; protected DateTime updateTimer; - protected bool gameStarted; - - protected RespawnManager respawnManager; - public bool ShowNetStats; public float SimulatedRandomLatency, SimulatedMinimumLatency; public float SimulatedLoss; public float SimulatedDuplicatesChance; - public int TickRate - { - get { return serverSettings.TickRate; } - set - { - serverSettings.TickRate = MathHelper.Clamp(value, 1, 60); - updateInterval = new TimeSpan(0, 0, 0, 0, MathHelper.Clamp(1000 / serverSettings.TickRate, 1, 500)); - } - } - public KarmaManager KarmaManager { get; private set; } = new KarmaManager(); - public bool GameStarted - { - get { return gameStarted; } - } + public bool GameStarted { get; protected set; } public abstract IReadOnlyList ConnectedClients { get; } - public RespawnManager RespawnManager - { - get { return respawnManager; } - } + public RespawnManager RespawnManager { get; protected set; } + + public ServerSettings ServerSettings { get; protected set; } + + public TimeSpan UpdateInterval => new TimeSpan(0, 0, 0, 0, MathHelper.Clamp(1000 / ServerSettings.TickRate, 1, 500)); - public ServerSettings ServerSettings - { - get { return serverSettings; } - } public bool CanUseRadio(Character sender) { @@ -277,24 +245,6 @@ namespace Barotrauma.Networking public abstract void UnbanPlayer(Endpoint endpoint); - public virtual void Update(float deltaTime) { } - - public virtual void Quit() { } - - /// - /// Check if the two version are compatible (= if they can play together in multiplayer). - /// Returns null if compatibility could not be determined (invalid/unknown version number). - /// - public static bool? IsCompatible(string myVersion, string remoteVersion) - { - if (string.IsNullOrEmpty(myVersion) || string.IsNullOrEmpty(remoteVersion)) { return null; } - - if (!Version.TryParse(myVersion, out Version myVersionNumber)) { return null; } - if (!Version.TryParse(remoteVersion, out Version remoteVersionNumber)) { return null; } - - return IsCompatible(myVersionNumber, remoteVersionNumber); - } - /// /// Check if the two version are compatible (= if they can play together in multiplayer). /// diff --git a/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/AccountId/AccountId.cs b/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/AccountId/AccountId.cs index 3be504afe..47fc84fd3 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/AccountId/AccountId.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/AccountId/AccountId.cs @@ -7,7 +7,7 @@ namespace Barotrauma.Networking public abstract string StringRepresentation { get; } public static Option Parse(string str) - => ReflectionUtils.ParseDerived(str); + => ReflectionUtils.ParseDerived(str); public abstract override bool Equals(object? obj); diff --git a/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/Address/Address.cs b/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/Address/Address.cs index 0724a0bca..f5ca6da14 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/Address/Address.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/Address/Address.cs @@ -7,7 +7,7 @@ namespace Barotrauma.Networking public abstract string StringRepresentation { get; } public static Option
Parse(string str) - => ReflectionUtils.ParseDerived
(str); + => ReflectionUtils.ParseDerived(str); public abstract bool IsLocalHost { get; } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/Address/LidgrenAddress.cs b/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/Address/LidgrenAddress.cs index 3a724de81..5fadd7644 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/Address/LidgrenAddress.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/Address/LidgrenAddress.cs @@ -17,31 +17,27 @@ namespace Barotrauma.Networking public LidgrenAddress(IPAddress netAddress) { - NetAddress = netAddress; + if (IPAddress.IsLoopback(netAddress)) + { + NetAddress = IPAddress.Loopback; + } + else + { + NetAddress = netAddress; + } } public new static Option Parse(string endpointStr) { - if (IPAddress.TryParse(endpointStr, out IPAddress? netEndpoint)) + if (endpointStr.Equals("localhost", StringComparison.OrdinalIgnoreCase)) + { + return Option.Some(new LidgrenAddress(IPAddress.Loopback)); + } + else if (IPAddress.TryParse(endpointStr, out IPAddress? netEndpoint)) { return Option.Some(new LidgrenAddress(netEndpoint!)); } - - try - { - var resolvedAddresses = Dns.GetHostAddresses(endpointStr); - return resolvedAddresses.Any() - ? Option.Some(new LidgrenAddress(resolvedAddresses.First())) - : Option.None(); - } - catch (SocketException) - { - return Option.None(); - } - catch (ArgumentOutOfRangeException) - { - return Option.None(); - } + return Option.None(); } public override bool Equals(object? obj) diff --git a/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/Endpoint/Endpoint.cs b/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/Endpoint/Endpoint.cs index 6880848c4..f1599e654 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/Endpoint/Endpoint.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/Endpoint/Endpoint.cs @@ -22,12 +22,21 @@ namespace Barotrauma.Networking public override string ToString() => StringRepresentation; public static Option Parse(string str) - => ReflectionUtils.ParseDerived(str); + => ReflectionUtils.ParseDerived(str); - public static bool operator ==(Endpoint a, Endpoint b) - => a.Equals(b); + public static bool operator ==(Endpoint? a, Endpoint? b) + { + if (a is null) + { + return b is null; + } + else + { + return a.Equals(b); + } + } - public static bool operator !=(Endpoint a, Endpoint b) + public static bool operator !=(Endpoint? a, Endpoint? b) => !(a == b); } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/Endpoint/LidgrenEndpoint.cs b/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/Endpoint/LidgrenEndpoint.cs index 32e85d169..44d20264a 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/Endpoint/LidgrenEndpoint.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/Endpoint/LidgrenEndpoint.cs @@ -24,24 +24,23 @@ namespace Barotrauma.Networking public new static Option Parse(string endpointStr) { - if (IPEndPoint.TryParse(endpointStr, out IPEndPoint? netEndpoint)) - { - return Option.Some(new LidgrenEndpoint(netEndpoint!)); - } - + string hostName = endpointStr; + int port = NetConfig.DefaultPort; if (endpointStr.Count(c => c == ':') == 1) { string[] split = endpointStr.Split(':'); - string hostName = split[0]; - if (LidgrenAddress.Parse(hostName).TryUnwrap(out var adr) - && int.TryParse(split[1], out var port)) - { - return Option.Some(new LidgrenEndpoint(adr.NetAddress, port)); - } + hostName = split[0]; + port = int.TryParse(split[1], out var tmpPort) ? tmpPort : port; } - - return LidgrenAddress.Parse(endpointStr) - .Select(adr => new LidgrenEndpoint(adr.NetAddress, NetConfig.DefaultPort)); + + if (LidgrenAddress.Parse(hostName).TryUnwrap(out var adr)) + { + return Option.Some(new LidgrenEndpoint(adr.NetAddress, port)); + } + + return IPEndPoint.TryParse(endpointStr, out IPEndPoint? netEndpoint) + ? Option.Some(new LidgrenEndpoint(netEndpoint)) + : Option.None(); } public override bool Equals(object? obj) diff --git a/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/NetworkPeerStructs.cs b/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/NetworkPeerStructs.cs index 6ae0d0e1b..893bed235 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/NetworkPeerStructs.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/NetworkPeerStructs.cs @@ -1,8 +1,8 @@ #nullable enable - using System; using System.Collections.Immutable; using System.Linq; +using System.Text; namespace Barotrauma.Networking { @@ -68,7 +68,7 @@ namespace Barotrauma.Networking public byte[] Buffer; public readonly int Length => Buffer.Length; - public readonly IReadMessage GetReadMessage() => new ReadWriteMessage(Buffer, 0, Length, copyBuf: false); + public readonly IReadMessage GetReadMessageUncompressed() => new ReadWriteMessage(Buffer, 0, Length, copyBuf: false); public readonly IReadMessage GetReadMessage(bool isCompressed, NetworkConnection conn) => new ReadOnlyMessage(Buffer, isCompressed, 0, Length, conn); } @@ -86,9 +86,164 @@ namespace Barotrauma.Networking } [NetworkSerialize] - internal struct PeerDisconnectPacket : INetSerializableStruct + internal readonly struct PeerDisconnectPacket : INetSerializableStruct { - public string Message; + public readonly DisconnectReason DisconnectReason; + + public readonly string AdditionalInformation; + + private PeerDisconnectPacket( + DisconnectReason disconnectReason, + string additionalInformation = "") + { + DisconnectReason = disconnectReason; + AdditionalInformation = additionalInformation; + } + + public LocalizedString ChatMessage(Client c) + => DisconnectReason switch + { + DisconnectReason.Disconnected => TextManager.GetWithVariable("ServerMessage.ClientLeftServer", + "[client]", c.Name), + _ => TextManager.GetWithVariables("ChatMsg.DisconnectedWithReason", + ("[client]", c.Name), + ("[reason]", TextManager.Get($"ChatMsg.DisconnectReason.{DisconnectReason}"))) + }; + + private LocalizedString msgWithReason + => TextManager.Get($"DisconnectReason.{DisconnectReason}") + + "\n\n" + + TextManager.Get("banreason") + " " + AdditionalInformation; + + private LocalizedString serverMessage + => TextManager.Get($"ServerMessage.{DisconnectReason}"); + + public LocalizedString PopupMessage + => DisconnectReason switch + { + DisconnectReason.Banned => msgWithReason, + DisconnectReason.Kicked => msgWithReason, + DisconnectReason.InvalidVersion => TextManager.GetWithVariables("DisconnectMessage.InvalidVersion", + ("[version]", AdditionalInformation), + ("[clientversion]", GameMain.Version.ToString())), + DisconnectReason.ExcessiveDesyncOldEvent => serverMessage, + DisconnectReason.ExcessiveDesyncRemovedEvent => serverMessage, + DisconnectReason.SyncTimeout => serverMessage, + _ => TextManager.Get($"DisconnectReason.{DisconnectReason}").Fallback(TextManager.Get("ConnectionLost")) + }; + + public LocalizedString ReconnectMessage + => PopupMessage + "\n\n" + TextManager.Get("ConnectionLostReconnecting"); + + public PlayerConnectionChangeType ConnectionChangeType + => DisconnectReason switch + { + DisconnectReason.Banned => PlayerConnectionChangeType.Banned, + DisconnectReason.Kicked => PlayerConnectionChangeType.Kicked, + _ => PlayerConnectionChangeType.Disconnected + }; + + public bool ShouldAttemptReconnect + => DisconnectReason + is DisconnectReason.ExcessiveDesyncOldEvent + or DisconnectReason.ExcessiveDesyncRemovedEvent + or DisconnectReason.Timeout + or DisconnectReason.SyncTimeout + or DisconnectReason.SteamP2PTimeOut; + + public bool IsEventSyncError + => DisconnectReason + is DisconnectReason.ExcessiveDesyncOldEvent + or DisconnectReason.ExcessiveDesyncRemovedEvent + or DisconnectReason.SyncTimeout; + + public bool ShouldCreateAnalyticsEvent + => DisconnectReason is not ( + DisconnectReason.Disconnected + or DisconnectReason.Banned + or DisconnectReason.Kicked + or DisconnectReason.TooManyFailedLogins + or DisconnectReason.InvalidVersion); + + public bool ShouldShowMessage + => DisconnectReason is not DisconnectReason.Disconnected; + + private const string lidgrenSeparator = ":hankey:"; + + /// + /// This exists because Lidgren is a piece of shit and + /// doesn't readily support sending anything other than + /// a string through a disconnect packet, so this thing + /// needs a sufficiently nasty string representation that + /// can be decoded with some certainty that it won't get + /// mangled by user input. + /// + public string ToLidgrenStringRepresentation() + { + static string strToBase64(string str) + => Convert.ToBase64String(Encoding.UTF8.GetBytes(str)); + + return DisconnectReason + + lidgrenSeparator + + strToBase64(AdditionalInformation); + } + + public static Option FromLidgrenStringRepresentation(string str) + { + // Lidgren has some hardcoded disconnect strings that it uses + // when it detects that a connection has failed. We can handle + // timeouts, so let's look for strings related to that and return + // an appropriate PeerDisconnectPacket. + switch (str) + { + case Lidgren.Network.NetConnection.NoResponseMessage: + case "Connection timed out": + case "Reconnecting": + return Option.Some(WithReason(DisconnectReason.Timeout)); + } + + static string base64ToStr(string base64) + => Encoding.UTF8.GetString(Convert.FromBase64String(base64)); + + string[] split = str.Split(lidgrenSeparator); + if (split.Length != 2) { return Option.None(); } + if (!Enum.TryParse(split[0], out DisconnectReason disconnectReason)) { return Option.None(); } + return Option.Some(new PeerDisconnectPacket(disconnectReason, base64ToStr(split[1]))); + } + + public static PeerDisconnectPacket Custom(string customMessage) + => new PeerDisconnectPacket( + DisconnectReason.Unknown, + customMessage); + + public static PeerDisconnectPacket WithReason(DisconnectReason disconnectReason) + => new PeerDisconnectPacket(disconnectReason); + + public static PeerDisconnectPacket Kicked(string? msg) + => new PeerDisconnectPacket(DisconnectReason.Kicked, msg ?? ""); + + public static PeerDisconnectPacket Banned(string? msg) + => new PeerDisconnectPacket(DisconnectReason.Banned, msg ?? ""); + + public static PeerDisconnectPacket InvalidVersion() + => new PeerDisconnectPacket( + DisconnectReason.InvalidVersion, + GameMain.Version.ToString()); + + public static PeerDisconnectPacket SteamP2PError(Steamworks.P2PSessionError error) + => new PeerDisconnectPacket( + DisconnectReason.SteamP2PError, + error.ToString()); + + public static PeerDisconnectPacket SteamAuthError(Steamworks.BeginAuthResult error) + => new PeerDisconnectPacket( + DisconnectReason.SteamAuthenticationFailed, + $"{nameof(Steamworks.BeginAuthResult)}.{error}"); + + public static PeerDisconnectPacket SteamAuthError(Steamworks.AuthResponse error) + => new PeerDisconnectPacket( + DisconnectReason.SteamAuthenticationFailed, + $"{nameof(Steamworks.AuthResponse)}.{error}"); } // ReSharper disable MemberCanBePrivate.Global, FieldCanBeMadeReadOnly.Global, UnassignedField.Global @@ -101,11 +256,14 @@ namespace Barotrauma.Networking public byte[] HashBytes = Array.Empty(); [NetworkSerialize] - public ulong WorkshopId; + public string UgcId = ""; [NetworkSerialize] public uint InstallTimeDiffInSeconds; + [NetworkSerialize] + public bool IsMandatory; + private Md5Hash? cachedHash; private DateTime? cachedDateTime; @@ -130,9 +288,12 @@ namespace Barotrauma.Networking { Name = contentPackage.Name; Hash = contentPackage.Hash; - WorkshopId = contentPackage.SteamWorkshopId; + UgcId = contentPackage.UgcId.TryUnwrap(out var ugcId) + ? ugcId.StringRepresentation + : ""; + IsMandatory = !contentPackage.Files.All(f => f is SubmarineFile); InstallTimeDiffInSeconds = - contentPackage.InstallTime is { } installTime + contentPackage.InstallTime.TryUnwrap(out var installTime) ? (uint)(installTime - referenceTime).TotalSeconds : 0; } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Networking/RespawnManager.cs b/Barotrauma/BarotraumaShared/SharedSource/Networking/RespawnManager.cs index 5aad66b97..6f68b3730 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Networking/RespawnManager.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Networking/RespawnManager.cs @@ -333,10 +333,14 @@ namespace Barotrauma.Networking RespawnCharactersProjSpecific(shuttlePos); } + public static AfflictionPrefab GetRespawnPenaltyAfflictionPrefab() + { + return AfflictionPrefab.Prefabs.First(a => a.AfflictionType == "respawnpenalty"); + } + public static Affliction GetRespawnPenaltyAffliction() { - var respawnPenaltyAffliction = AfflictionPrefab.Prefabs.First(a => a.AfflictionType == "respawnpenalty"); - return respawnPenaltyAffliction?.Instantiate(10.0f); + return GetRespawnPenaltyAfflictionPrefab()?.Instantiate(10.0f); } public static void GiveRespawnPenaltyAffliction(Character character) diff --git a/Barotrauma/BarotraumaShared/SharedSource/Networking/ServerSettings.cs b/Barotrauma/BarotraumaShared/SharedSource/Networking/ServerSettings.cs index 74e9223ec..cbf0474b8 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Networking/ServerSettings.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Networking/ServerSettings.cs @@ -388,11 +388,12 @@ namespace Barotrauma.Networking public List ClientPermissions { get; private set; } = new List(); + private int tickRate = 20; [Serialize(20, IsPropertySaveable.Yes)] public int TickRate { - get; - set; + get { return tickRate; } + set { tickRate = MathHelper.Clamp(value, 1, 60); } } [Serialize(true, IsPropertySaveable.Yes)] diff --git a/Barotrauma/BarotraumaShared/SharedSource/Networking/Voting.cs b/Barotrauma/BarotraumaShared/SharedSource/Networking/Voting.cs index e26cb7e62..594171239 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Networking/Voting.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Networking/Voting.cs @@ -56,23 +56,5 @@ namespace Barotrauma return selected; } - - public void ResetVotes(IEnumerable connectedClients) - { - foreach (Client client in connectedClients) - { - client.ResetVotes(); - } -#if CLIENT - foreach (VoteType voteType in Enum.GetValues(typeof(VoteType))) - { - SetVoteCountYes(voteType, 0); - SetVoteCountNo(voteType, 0); - SetVoteCountMax(voteType, 0); - } - UpdateVoteTexts(connectedClients, VoteType.Mode); - UpdateVoteTexts(connectedClients, VoteType.Sub); -#endif - } } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Prefabs/Prefab.cs b/Barotrauma/BarotraumaShared/SharedSource/Prefabs/Prefab.cs index c86e6050c..167725951 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Prefabs/Prefab.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Prefabs/Prefab.cs @@ -7,7 +7,7 @@ using System.Xml.Linq; namespace Barotrauma { - public abstract class Prefab : IDisposable + public abstract class Prefab { public readonly static ImmutableHashSet Types; static Prefab() diff --git a/Barotrauma/BarotraumaShared/SharedSource/Prefabs/PrefabCollection.cs b/Barotrauma/BarotraumaShared/SharedSource/Prefabs/PrefabCollection.cs index 5c3a16671..93fa4d6a7 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Prefabs/PrefabCollection.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Prefabs/PrefabCollection.cs @@ -37,6 +37,14 @@ namespace Barotrauma OnRemoveOverrideFile = onRemoveOverrideFile; } + /// + /// Constructor with only the OnSort callback provided. + /// + public PrefabCollection(Action? onSort) : this() + { + OnSort = onSort; + } + /// /// Method to be called when calling Add(T prefab, bool override). /// If provided, the method is called only if Add succeeds. diff --git a/Barotrauma/BarotraumaShared/SharedSource/Prefabs/PrefabSelector.cs b/Barotrauma/BarotraumaShared/SharedSource/Prefabs/PrefabSelector.cs index 631543c0a..8a0bbb7b3 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Prefabs/PrefabSelector.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Prefabs/PrefabSelector.cs @@ -4,16 +4,20 @@ using System.Collections; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; +using System.Threading; +using Barotrauma.Threading; namespace Barotrauma { public class PrefabSelector : IEnumerable where T : notnull, Prefab { + private readonly ReaderWriterLockSlim rwl = new ReaderWriterLockSlim(); + public T? BasePrefab { get { - lock (overrides) { return basePrefabInternal; } + using (new ReadLock(rwl)) { return basePrefabInternal; } } } @@ -21,51 +25,70 @@ namespace Barotrauma { get { - lock (overrides) { return activePrefabInternal; } + using (new ReadLock(rwl)) { return activePrefabInternal; } } } public void Add(T prefab, bool isOverride) { - lock (overrides) { AddInternal(prefab, isOverride); } + using (new WriteLock(rwl)) { AddInternal(prefab, isOverride); } } public void RemoveIfContains(T prefab) { - lock (overrides) { RemoveIfContainsInternal(prefab); } + using (new WriteLock(rwl)) { RemoveIfContainsInternal(prefab); } } public void Remove(T prefab) { - lock (overrides) { RemoveInternal(prefab); } + using (new WriteLock(rwl)) { RemoveInternal(prefab); } } public void RemoveByFile(ContentFile file, Action? callback = null) { - lock (overrides) { RemoveByFileInternal(file, callback); } + var removed = new List(); + using (new WriteLock(rwl)) + { + for (int i = overrides.Count-1; i >= 0; i--) + { + var prefab = overrides[i]; + if (prefab.ContentFile == file) + { + RemoveInternal(prefab); + removed.Add(prefab); + } + } + + if (basePrefabInternal is { ContentFile: var baseFile } p && baseFile == file) + { + RemoveInternal(basePrefabInternal); + removed.Add(p); + } + } + if (callback != null) { removed.ForEach(callback); } } public void Sort() { - lock (overrides) { SortInternal(); } + using (new WriteLock(rwl)) { SortInternal(); } } public bool IsEmpty { get { - lock (overrides) { return isEmptyInternal; } + using (new ReadLock(rwl)) { return isEmptyInternal; } } } public bool Contains(T prefab) { - lock (overrides) { return ContainsInternal(prefab); } + using (new ReadLock(rwl)) { return ContainsInternal(prefab); } } public bool IsOverride(T prefab) { - lock (overrides) { return IsOverrideInternal(prefab); } + using (new ReadLock(rwl)) { return IsOverrideInternal(prefab); } } @@ -73,7 +96,7 @@ namespace Barotrauma private T? basePrefabInternal; private readonly List overrides = new List(); - private T? activePrefabInternal => overrides.Any() ? overrides.First() : basePrefabInternal; + private T? activePrefabInternal => overrides.Count > 0 ? overrides.First() : basePrefabInternal; private void AddInternal(T prefab, bool isOverride) { @@ -84,7 +107,7 @@ namespace Barotrauma } else { - if (BasePrefab != null) + if (basePrefabInternal != null) { string prefabName = prefab is MapEntityPrefab mapEntityPrefab @@ -92,7 +115,7 @@ namespace Barotrauma : $"\"{prefab.Identifier}\""; throw new InvalidOperationException( $"Failed to add the prefab {prefabName} ({prefab.GetType()}) from \"{prefab.ContentPackage?.Name ?? "[NULL]"}\" ({prefab.ContentPackage?.Dir ?? ""}): " - + $"a prefab with the same identifier from \"{ActivePrefab!.ContentPackage?.Name ?? "[NULL]"}\" ({ActivePrefab!.ContentPackage?.Dir ?? ""}) already exists; try overriding"); + + $"a prefab with the same identifier from \"{activePrefabInternal!.ContentPackage?.Name ?? "[NULL]"}\" ({activePrefabInternal!.ContentPackage?.Dir ?? ""}) already exists; try overriding"); } basePrefabInternal = prefab; } @@ -114,31 +137,12 @@ namespace Barotrauma SortInternal(); } - private void RemoveByFileInternal(ContentFile file, Action? callback) - { - for (int i = overrides.Count-1; i >= 0; i--) - { - var prefab = overrides[i]; - if (prefab.ContentFile == file) - { - RemoveInternal(prefab); - callback?.Invoke(prefab); - } - } - - if (basePrefabInternal is { ContentFile: var baseFile } p && baseFile == file) - { - RemoveInternal(basePrefabInternal); - callback?.Invoke(p); - } - } - private void SortInternal() { overrides.Sort((p1, p2) => (p1.ContentPackage?.Index ?? int.MaxValue) - (p2.ContentPackage?.Index ?? int.MaxValue)); } - private bool isEmptyInternal => basePrefabInternal is null && !overrides.Any(); + private bool isEmptyInternal => basePrefabInternal is null && overrides.Count == 0; private bool ContainsInternal(T prefab) => basePrefabInternal == prefab || overrides.Contains(prefab); @@ -153,7 +157,7 @@ namespace Barotrauma { T? basePrefab; ImmutableArray overrideClone; - lock (overrides) + using (new ReadLock(rwl)) { basePrefab = basePrefabInternal; overrideClone = overrides.ToImmutableArray(); diff --git a/Barotrauma/BarotraumaShared/SharedSource/Serialization/XMLExtensions.cs b/Barotrauma/BarotraumaShared/SharedSource/Serialization/XMLExtensions.cs index c2a73e504..16e5022f4 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Serialization/XMLExtensions.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Serialization/XMLExtensions.cs @@ -315,6 +315,25 @@ namespace Barotrauma return floatValue; } + public static bool TryGetAttributeInt(this XElement element, string name, out int result) + { + var attribute = element?.GetAttribute(name); + result = default; + if (attribute == null) { return false; } + + if (int.TryParse(attribute.Value, NumberStyles.Any, CultureInfo.InvariantCulture, out var intVal)) + { + result = intVal; + return true; + } + if (float.TryParse(attribute.Value, NumberStyles.Any, CultureInfo.InvariantCulture, out var floatVal)) + { + result = (int)floatVal; + return true; + } + return false; + } + public static int GetAttributeInt(this XElement element, string name, int defaultValue) { var attribute = element?.GetAttribute(name); diff --git a/Barotrauma/BarotraumaShared/SharedSource/Settings/GameSettings.cs b/Barotrauma/BarotraumaShared/SharedSource/Settings/GameSettings.cs index 4ba71d446..e1ec4e598 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Settings/GameSettings.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Settings/GameSettings.cs @@ -353,7 +353,7 @@ namespace Barotrauma // Check for duplicate binds when introducing new binds foreach (var defaultBinding in defaultBindings) { - if (!savedBindings.ContainsKey(defaultBinding.Key)) + if (!IsSetToNone(defaultBinding.Value) && !savedBindings.ContainsKey(defaultBinding.Key)) { foreach (var savedBinding in savedBindings) { @@ -373,6 +373,8 @@ namespace Barotrauma } } } + + static bool IsSetToNone(KeyOrMouse keyOrMouse) => keyOrMouse == Keys.None && keyOrMouse == MouseButton.None; } // Clear the old chat binds for configs saved before the introduction of the new chat binds diff --git a/Barotrauma/BarotraumaShared/SharedSource/StatusEffects/DelayedEffect.cs b/Barotrauma/BarotraumaShared/SharedSource/StatusEffects/DelayedEffect.cs index ebd8a0b36..94e6c7bef 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/StatusEffects/DelayedEffect.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/StatusEffects/DelayedEffect.cs @@ -119,8 +119,6 @@ namespace Barotrauma if (!HasRequiredConditions(currentTargets)) { return; } - if (Entity.Spawner != null && Entity.Spawner.IsInRemoveQueue(entity)) { return; } - switch (delayType) { case DelayTypes.Timer: diff --git a/Barotrauma/BarotraumaShared/SharedSource/Steam/Workshop.cs b/Barotrauma/BarotraumaShared/SharedSource/Steam/Workshop.cs index 3c274b2c3..b4aa8a883 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Steam/Workshop.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Steam/Workshop.cs @@ -3,6 +3,7 @@ using Barotrauma.IO; using System; using System.Collections.Concurrent; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Text; using System.Threading; @@ -20,6 +21,16 @@ namespace Barotrauma.Steam public const string PreviewImageName = "PreviewImage.png"; public const string DefaultPreviewImagePath = "Content/DefaultWorkshopPreviewImage.png"; + public static bool TryExtractSteamWorkshopId(this ContentPackage contentPackage, [NotNullWhen(true)]out SteamWorkshopId? workshopId) + { + workshopId = null; + if (!contentPackage.UgcId.TryUnwrap(out var ugcId)) { return false; } + if (!(ugcId is SteamWorkshopId steamWorkshopId)) { return false; } + + workshopId = steamWorkshopId; + return true; + } + public static partial class Workshop { private struct ItemEqualityComparer : IEqualityComparer @@ -110,7 +121,10 @@ namespace Barotrauma.Steam { NukeDownload(workshopItem); var toUninstall - = ContentPackageManager.WorkshopPackages.Where(p => p.SteamWorkshopId == workshopItem.Id) + = ContentPackageManager.WorkshopPackages.Where(p => + p.UgcId.TryUnwrap(out var ugcId) + && ugcId is SteamWorkshopId { Value: var itemId } + && itemId == workshopItem.Id) .ToHashSet(); ContentPackageManager.EnabledPackages.DisableMods(toUninstall); toUninstall.Select(p => p.Dir).ForEach(d => Directory.Delete(d)); diff --git a/Barotrauma/BarotraumaShared/SharedSource/Text/TextManager.cs b/Barotrauma/BarotraumaShared/SharedSource/Text/TextManager.cs index 823d7fd28..78cc321f7 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Text/TextManager.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Text/TextManager.cs @@ -9,6 +9,7 @@ using System.Linq; using System.Text.RegularExpressions; using System.Xml.Linq; using System.Globalization; +using System.Text.Unicode; namespace Barotrauma { @@ -30,18 +31,22 @@ namespace Barotrauma public static int LanguageVersion { get; private set; } = 0; - private readonly static Regex isCJK = new Regex( - @"\p{IsHangulJamo}|" + - @"\p{IsHiragana}|" + - @"\p{IsKatakana}|" + - @"\p{IsCJKRadicalsSupplement}|" + - @"\p{IsCJKSymbolsandPunctuation}|" + - @"\p{IsEnclosedCJKLettersandMonths}|" + - @"\p{IsCJKCompatibility}|" + - @"\p{IsCJKUnifiedIdeographsExtensionA}|" + - @"\p{IsCJKUnifiedIdeographs}|" + - @"\p{IsHangulSyllables}|" + - @"\p{IsCJKCompatibilityForms}"); + private static readonly ImmutableArray> CjkRanges = new[] + { + UnicodeRanges.HangulJamo, + UnicodeRanges.Hiragana, + UnicodeRanges.Katakana, + UnicodeRanges.CjkRadicalsSupplement, + UnicodeRanges.CjkSymbolsandPunctuation, + UnicodeRanges.EnclosedCjkLettersandMonths, + UnicodeRanges.CjkCompatibility, + UnicodeRanges.CjkUnifiedIdeographsExtensionA, + UnicodeRanges.CjkUnifiedIdeographs, + UnicodeRanges.HangulSyllables, + UnicodeRanges.CjkCompatibilityForms + }.Select(r => new Range(r.FirstCodePoint, r.FirstCodePoint+r.Length-1)) + .OrderBy(r => r.Start) + .ToImmutableArray(); /// /// Does the string contain symbols from Chinese, Japanese or Korean languages @@ -54,7 +59,24 @@ namespace Barotrauma public static bool IsCJK(string text) { if (string.IsNullOrEmpty(text)) { return false; } - return isCJK.IsMatch(text); + + for (int i = 0; i < text.Length; i++) + { + char chr = text[i]; + for (int j = 0; j < CjkRanges.Length; j++) + { + var range = CjkRanges[j]; + + // If chr < range.Start, we know that it can't + // be in any of the following ranges, so let's + // not even bother checking them + if (chr < range.Start) { break; } + + // This character is in a range, return true + if (range.Contains(chr)) { return true; } + } + } + return false; } /// diff --git a/Barotrauma/BarotraumaShared/SharedSource/Upgrades/UpgradePrefab.cs b/Barotrauma/BarotraumaShared/SharedSource/Upgrades/UpgradePrefab.cs index 9ca176167..f66cdcfe5 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Upgrades/UpgradePrefab.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Upgrades/UpgradePrefab.cs @@ -50,10 +50,7 @@ namespace Barotrauma if (level > maxLevel) { maxLevel = level; } int price = BasePrice; - for (int i = 1; i <= level; i++) - { - price += (int)(price * MathHelper.Lerp(IncreaseLow, IncreaseHigh, i / (float)maxLevel) / 100); - } + price += (int)(price * MathHelper.Lerp(IncreaseLow, IncreaseHigh, level / (float)maxLevel) / 100); return location?.GetAdjustedMechanicalCost(price) ?? price; } } @@ -331,8 +328,6 @@ namespace Barotrauma public ContentXElement SourceElement { get; } - private bool disposed; - public bool SuppressWarnings { get; } public bool HideInMenus { get; } @@ -525,18 +520,12 @@ namespace Barotrauma public override void Dispose() { - if (!disposed) - { - Prefabs.Remove(this); #if CLIENT - Sprite?.Remove(); - Sprite = null; - DecorativeSprites.ForEach(sprite => sprite.Remove()); - targetProperties.Clear(); + Sprite?.Remove(); + Sprite = null; + DecorativeSprites.ForEach(sprite => sprite.Remove()); + targetProperties.Clear(); #endif - } - - disposed = true; } } } \ No newline at end of file diff --git a/Barotrauma/BarotraumaShared/SharedSource/Utils/Option/Option.cs b/Barotrauma/BarotraumaShared/SharedSource/Utils/Option/Option.cs index 30a219a32..3d19c61ab 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Utils/Option/Option.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Utils/Option/Option.cs @@ -16,18 +16,18 @@ namespace Barotrauma public bool IsNone() => this is None; public bool IsSome() => this is Some; - public bool TryUnwrap(out T outValue) + public bool TryUnwrap(out T outValue) => TryUnwrap(out outValue); + + public bool TryUnwrap(out T1 outValue) where T1 : T { switch (this) { - case Some { Value: var value }: + case Some { Value: T1 value }: outValue = value; return true; - case None _: + default: outValue = default!; return false; - default: - throw new ArgumentOutOfRangeException(); } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Utils/ReflectionUtils.cs b/Barotrauma/BarotraumaShared/SharedSource/Utils/ReflectionUtils.cs index e02fe1c68..f65b53aab 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Utils/ReflectionUtils.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Utils/ReflectionUtils.cs @@ -23,16 +23,16 @@ namespace Barotrauma return cachedNonAbstractTypes[assembly].Where(t => t.IsSubclassOf(typeof(T))); } - public static Option ParseDerived(string str) + public static Option ParseDerived(TInput input) where TInput : notnull { - static Option none() => Option.None(); + static Option none() => Option.None(); - var derivedTypes = GetDerivedNonAbstract(); + var derivedTypes = GetDerivedNonAbstract(); - Option parseOfType(Type t) + Option parseOfType(Type t) { - //every T1 type is expected to have a method with the following signature: - // public static Option Parse(string str) + //every TBase type is expected to have a method with the following signature: + // public static Option Parse(TInput str) var parseFunc = t.GetMethod("Parse", BindingFlags.Public | BindingFlags.Static); if (parseFunc is null) { return none(); } @@ -44,14 +44,17 @@ namespace Barotrauma if (returnType.GetGenericTypeDefinition() != typeof(Option<>)) { return none(); } if (returnType.GenericTypeArguments[0] != t) { return none(); } - //some hacky business to convert from Option to Option when we only know T2 at runtime - static Option convert(Option option) where T2 : T1 - => option.Select(v => (T1)v); - Func, Option> f = convert; - var constructedConverter = f.Method.GetGenericMethodDefinition().MakeGenericMethod(typeof(T1), t); + //some hacky business to convert from Option to Option when we only know T2 at runtime + static Option convert(Option option) where T2 : TBase + => option.Select(v => (TBase)v); + Func, Option> f = convert; + var genericArgs = f.Method.GetGenericArguments(); + genericArgs[^1] = t; + var constructedConverter = + f.Method.GetGenericMethodDefinition().MakeGenericMethod(genericArgs); - return constructedConverter.Invoke(null, new object?[] { parseFunc.Invoke(null, new object[] { str }) }) - as Option ?? none(); + return constructedConverter.Invoke(null, new[] { parseFunc.Invoke(null, new object[] { input }) }) + as Option ?? none(); } return derivedTypes.Select(parseOfType).FirstOrDefault(t => t.IsSome()) ?? none(); diff --git a/Barotrauma/BarotraumaShared/SharedSource/Utils/Threading.cs b/Barotrauma/BarotraumaShared/SharedSource/Utils/Threading.cs new file mode 100644 index 000000000..25a2ac7fa --- /dev/null +++ b/Barotrauma/BarotraumaShared/SharedSource/Utils/Threading.cs @@ -0,0 +1,34 @@ +using System.Threading; + +namespace Barotrauma.Threading +{ + internal readonly ref struct ReadLock + { + private readonly ReaderWriterLockSlim rwl; + public ReadLock(ReaderWriterLockSlim rwl) + { + this.rwl = rwl; + rwl.EnterReadLock(); + } + + public void Dispose() + { + rwl.ExitReadLock(); + } + } + + internal readonly ref struct WriteLock + { + private readonly ReaderWriterLockSlim rwl; + public WriteLock(ReaderWriterLockSlim rwl) + { + this.rwl = rwl; + rwl.EnterWriteLock(); + } + + public void Dispose() + { + rwl.ExitWriteLock(); + } + } +} \ No newline at end of file diff --git a/Barotrauma/BarotraumaShared/changelog.txt b/Barotrauma/BarotraumaShared/changelog.txt index 1e642870f..6dd03983d 100644 --- a/Barotrauma/BarotraumaShared/changelog.txt +++ b/Barotrauma/BarotraumaShared/changelog.txt @@ -1,3 +1,87 @@ +--------------------------------------------------------------------------------------------------------- +v0.19.5.0 +--------------------------------------------------------------------------------------------------------- + +Unstable only: +- Progress on the new tutorials, the Roles tutorials in particular. Still a work in progress, but feedback is again more than welcome! +- Cleaned up networking and server list code to make them less error-prone and easier to work with in the future. Should not cause any functional differences, but please let us know if you notice any issues or oddities! +- Fixes and improvements to Camel. +- Fixed skill texts not being colored according to the user's skills in the repair UI. +- Fixed outpost service NPCs' titles (which are also used as the tooltips on the icons) not showing up in the multiplayer campaign. +- Further fixes to dragging animations. +- Fixed warning about duplicate keybinds being displayed for things set to None. +- Fixed clients who've gotten vote kicked getting vote kicked again when they join. +- Fixed favorited localhost servers causing a crash. +- Fixed respawn shuttle setting toggling on and off when adjusting other settings. +- Fixed skills increasing on death if the skill level is under the maximum initial skill. +- Fixes duplicate Captain Hognoses occasionally appearing in the crew list when selecting the Hognose mission in the multiplayer campaign. +- Fixed wrecked coilgun and railgun launch impulses. +- Fixed delayed status effects not working after the parent entity has been removed (breaking many medical items, e.g. ethanol). +- Fixed inability to buy anything from other stores when you've bought something from one of the stores in an outpost in the multiplayer campaign. + +Changes: +- Made crates deconstruct much faster to make them easier to get rid of. +- Sonar disruptions hide minerals. +- Gray out RangedWeapon's crosshair when reloading (similar to turret crosshairs). + +Fixes: +- Fixed clients downloading submarines they already have from the server if the mods those submarines are in are not currently enabled. +- Fixed submarines always saving in the root folder of a local mod, instead of the subfolder they were originally in. +- Fixed Reaper's Tax not stacking. +- Fixed turrets linked to the same loader messing up the upgrade store UI and causing item swaps to cost more than they should. +- Fixed status monitor calculating linked hulls' water amounts incorrectly (displaying the average of their water percentages, which isn't correct if the hulls aren't the same size). +- Fixes to messed up ruin decals in a bunch of ruin modules. +- Fixed a waypoint issue in the Alien_Entrance3 ruin module. +- Removed oxygen tanks from DockingModule_01_Colony. +- Tweaked the hulls and waypoints around Herja's top docking hatch to make it easier for bots to reach and weld. +- Fixed a waypoint/hull issue in Typhon's stowage compartment (waypoint in such a tight space the bots couldn't reach it). +- Fixed inactive components (components not currently sending any signal) not reactivating if their output is set to a non-empty value. +- Fixed duct block's misaligned broken sprite. + +Submarine editor: +- Fixed door gaps not appearing in the sub editor until you select the door + +Modding: +- Added CheckTalentAction, which can be used in events to check whether a target has unlocked a specific talent. +- Fixed ExtraLoad working the wrong way around on PowerTransfer components that generate/consume power (the extra load would supply power to the grid). Does not affect the vanilla game, because neither junction boxes or relays generate or consume power. + +--------------------------------------------------------------------------------------------------------- +v0.19.4.0 +--------------------------------------------------------------------------------------------------------- + +Unstable only: +- Fixed networking issues that prevented joining SteamP2P servers. +- Fixed crashing on startup if GameAnalytics is enabled. +- Fixed sub editor background images not saving if you leave the editor and quit the game without exiting the image editing mode first. +- Camel hull fixes. +- Fixed a draw order issue in unit load device. +- Fixed unit load device's inventory slot layout. +- Fixed submarine tier set in the sub editor not being saved, causing all subs to use the default tier determined by the price. + +Changes: +- Made extra sales from "traveling tradesman" talent stack. + +Fixes: +- Made bots better at figuring out which button controls a door when there's some complex circuit involved. Previously the bots would try to find a button connected to any of the door's connections via wires/circuits, now only the toggle and set_state inputs are considered. +- Bots now heavily prefer using buttons linked to the door in the sub editor. Can be used as another way to help the bots figure out which button they should press in situations with multiple buttons and complex door control logic. +- Fixed bots failing to find a path to a couple of spots in Herja. +- Fixed alien materials (physicorium, incendium, fulgurium, dementonite, paralyxis) not being shown on the mineral scanner. +- Another fix to cave generation to prevent it from creating impassable paths. +- Fixed inability to use manual assignment for bot orders with options. +- Fixed all boolean components (And, Or, Xor) using the And Component's tooltip for the "timeframe" property. +- Fixed boolean operator component (And, Or, Xor) timeframes not working correctly in some situations (non-zero timeframe, empty false output). The component would deactivate as soon as it stops sending an output, which could prevent some inputs from timing out (meaning that the component could send a signal again as soon as it receives signal A, even if signal B hasn't been received within the timeframe). +- Fixed PUCS consuming the medical item inside it when a welding fuel or incendium tank is inserted. + +Multiplayer: +- Fixed inventory and wallet resetting if a campaign round ends when a client's character has spawned, but the client is not currently controlling it (e.g. due to getting kicked to the lobby). +- Fixed spectator checkbox overlapping with the character info if you get kicked to the lobby mid-round. + +Modding: +- Fixed items/structures now falling back to the description defined in the xml even if it's empty, if the description is not defined for the selected language (instead of using English instead). +- Fixed using the "reloadwearables" and "loadwearable" console commands outside the character editor crashing the game. +- Fixed character editor crash if you first reload textures and then recreate the ragdoll. +- Changed how submarine upgrades are calculated, now no longer adds previous levels' costs to the price, but rather relies on higher increasehigh values + --------------------------------------------------------------------------------------------------------- v0.19.3.0 --------------------------------------------------------------------------------------------------------- @@ -44,7 +128,6 @@ Fixes: - Fixed chaingun rotation speed not being affected by the weapons skill. - Fixed crashing when using ':' in item assembly names on Linux platforms. - Fixed ImmuneToPressure ability flag being ignored on characters who don't need air (in practice meaning that you can get killed by pressure if you get huskified even if you have a talent that makes you immune to pressure). -- Disallow using the "reloadwearables" and "loadwearable" when a gamesession is active because it leads to a crash. These commands are intended to be used in the character editor. - Fixed geneticmaterialcrawler_unresearched3 producing mudraptor genes. Submarine editor: diff --git a/Libraries/Facepunch.Steamworks/ServerList/Base.cs b/Libraries/Facepunch.Steamworks/ServerList/Base.cs index 9a6868702..9a5cb1125 100644 --- a/Libraries/Facepunch.Steamworks/ServerList/Base.cs +++ b/Libraries/Facepunch.Steamworks/ServerList/Base.cs @@ -23,17 +23,17 @@ namespace Steamworks.ServerList /// /// When a new server is added, this function will get called /// - public event Action OnChanges; + public Action OnChanges; /// /// Called for every responsive server /// - public event Action OnResponsiveServer; + public Action OnResponsiveServer; /// /// Called for every unresponsive server /// - public event Action OnUnresponsiveServer; + public Action OnUnresponsiveServer; /// /// A list of servers that responded. If you're only interested in servers that responded since you @@ -65,14 +65,14 @@ namespace Steamworks.ServerList var thisRequest = request; - while ( IsRefreshing ) + while ( true ) { await Task.Delay( 33 ); // // The request has been cancelled or changed in some way // - if ( request.Value == IntPtr.Zero || thisRequest.Value != request.Value ) + if ( request.Value == IntPtr.Zero || thisRequest.Value != request.Value || !IsRefreshing ) return false; if ( !SteamClient.IsValid ) diff --git a/Libraries/Facepunch.Steamworks/Structs/Friend.cs b/Libraries/Facepunch.Steamworks/Structs/Friend.cs index 0561b8dd5..510227bbf 100644 --- a/Libraries/Facepunch.Steamworks/Structs/Friend.cs +++ b/Libraries/Facepunch.Steamworks/Structs/Friend.cs @@ -114,9 +114,9 @@ namespace Steamworks public struct FriendGameInfo { - internal ulong GameID; // m_gameID class CGameID - internal uint GameIP; // m_unGameIP uint32 - internal ulong SteamIDLobby; // m_steamIDLobby class CSteamID + public ulong GameID; // m_gameID class CGameID + public uint GameIP; // m_unGameIP uint32 + public ulong SteamIDLobby; // m_steamIDLobby class CSteamID public int ConnectionPort; public int QueryPort; diff --git a/Libraries/Facepunch.Steamworks/Structs/Lobby.cs b/Libraries/Facepunch.Steamworks/Structs/Lobby.cs index 1a3b3fb2d..2b0fdb57a 100644 --- a/Libraries/Facepunch.Steamworks/Structs/Lobby.cs +++ b/Libraries/Facepunch.Steamworks/Structs/Lobby.cs @@ -153,13 +153,13 @@ namespace Steamworks.Data } /// - /// Refreshes metadata for a lobby you're not necessarily in right now - /// you never do this for lobbies you're a member of, only if your - /// this will send down all the metadata associated with a lobby - /// this is an asynchronous call - /// returns false if the local user is not connected to the Steam servers - /// results will be returned by a LobbyDataUpdate_t callback - /// if the specified lobby doesn't exist, LobbyDataUpdate_t::m_bSuccess will be set to false + /// Refreshes metadata for a lobby you're not necessarily in right now. + /// You never do this for lobbies you're a member of, only if your + /// this will send down all the metadata associated with a lobby. + /// This is an asynchronous call. + /// Returns false if the local user is not connected to the Steam servers. + /// Results will be returned by a LobbyDataUpdate_t callback. + /// If the specified lobby doesn't exist, LobbyDataUpdate_t::m_bSuccess will be set to false. /// public bool Refresh() { From 2efdead44bf2fd76adebe19ee881d3c1eb147455 Mon Sep 17 00:00:00 2001 From: Joonas Rikkonen Date: Fri, 23 Sep 2022 17:57:07 +0300 Subject: [PATCH 09/11] Update bug_report.yml --- .github/ISSUE_TEMPLATE/bug_report.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 735822bb9..bac0ca4f8 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -53,7 +53,7 @@ body: description: Which version of the game did the bug happen in? You can see the current version number in the bottom left corner of your screen in the main menu. options: - 0.18.15.1 / 0.18.15.2 on macOS - - 0.19.5.0 (unstable) + - 0.19.6.0 (unstable) - Other validations: required: true From 982df298ec0f313de248965624da1f6c92686bc6 Mon Sep 17 00:00:00 2001 From: Joonas Rikkonen Date: Wed, 28 Sep 2022 21:48:53 +0300 Subject: [PATCH 10/11] Update bug_report.yml --- .github/ISSUE_TEMPLATE/bug_report.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index bac0ca4f8..bb7b4999c 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -53,7 +53,7 @@ body: description: Which version of the game did the bug happen in? You can see the current version number in the bottom left corner of your screen in the main menu. options: - 0.18.15.1 / 0.18.15.2 on macOS - - 0.19.6.0 (unstable) + - 0.19.8.0 (unstable) - Other validations: required: true From 3ca584f2fc2c9f3f6e9aeea67a2a3694f230b492 Mon Sep 17 00:00:00 2001 From: Juan Pablo Arce Date: Wed, 28 Sep 2022 21:30:52 -0300 Subject: [PATCH 11/11] v0.19.8.0 --- .../ClientSource/Characters/CharacterHUD.cs | 33 +- .../Characters/CharacterNetworking.cs | 47 +- .../Characters/Health/CharacterHealth.cs | 13 +- .../Events/EventActions/ConversationAction.cs | 10 +- .../EventActions/InventoryHighlightAction.cs | 58 ++ .../Events/EventActions/MessageBoxAction.cs | 10 +- .../EventActions/TutorialHighlightAction.cs | 18 +- .../EventActions/TutorialSegmentAction.cs | 14 +- .../Events/EventActions/UIHighlightAction.cs | 46 ++ .../ClientSource/Events/EventManager.cs | 4 +- .../BarotraumaClient/ClientSource/GUI/GUI.cs | 7 +- .../ClientSource/GUI/GUIComponent.cs | 3 +- .../ClientSource/GUI/GUIImage.cs | 4 +- .../ClientSource/GUI/GUIListBox.cs | 9 +- .../ClientSource/GUI/GUIMessageBox.cs | 2 +- .../ClientSource/GUI/GUIStyle.cs | 9 +- .../ClientSource/GUI/Store.cs | 16 +- .../ClientSource/GUI/TabMenu.cs | 18 +- .../ClientSource/GUI/UpgradeStore.cs | 12 +- .../ClientSource/GameSession/CargoManager.cs | 4 +- .../ClientSource/GameSession/CrewManager.cs | 30 +- .../GameModes/MultiPlayerCampaign.cs | 1 + .../GameModes/Tutorials/Tutorial.cs | 80 ++- .../ClientSource/Items/Components/Door.cs | 13 +- .../Items/Components/ItemComponent.cs | 5 +- .../Items/Components/ItemContainer.cs | 4 +- .../Components/Machines/Deconstructor.cs | 20 +- .../Items/Components/Machines/Fabricator.cs | 2 + .../Items/Components/Machines/MiniMap.cs | 8 +- .../Items/Components/Machines/Pump.cs | 4 +- .../Items/Components/Machines/Reactor.cs | 6 +- .../Items/Components/Machines/Sonar.cs | 24 +- .../Items/Components/Machines/Steering.cs | 10 +- .../Items/Components/Power/PowerContainer.cs | 3 +- .../Items/Components/Repairable.cs | 1 + .../Components/Signal/CustomInterface.cs | 2 +- .../ClientSource/Items/Item.cs | 17 +- .../ClientSource/Items/ItemPrefab.cs | 1 + .../BarotraumaClient/ClientSource/Map/Gap.cs | 4 - .../ClientSource/Networking/BanList.cs | 6 +- .../ClientSource/Networking/Client.cs | 7 +- .../ClientSource/Networking/GameClient.cs | 22 +- .../Networking/Primitives/Peers/ClientPeer.cs | 2 +- .../Primitives/Peers/SteamP2PClientPeer.cs | 3 + .../Primitives/Peers/SteamP2POwnerPeer.cs | 2 +- .../Networking/ServerList/PingUtils.cs | 35 +- .../Networking/ServerList/ServerInfo.cs | 12 +- .../ClientSource/Screens/CampaignUI.cs | 2 +- .../ClientSource/Screens/MainMenuScreen.cs | 80 ++- .../ClientSource/Screens/SubEditorScreen.cs | 2 +- .../ClientSource/Sounds/SoundManager.cs | 79 +-- .../BarotraumaClient/LinuxClient.csproj | 2 +- Barotrauma/BarotraumaClient/MacClient.csproj | 2 +- .../BarotraumaClient/WindowsClient.csproj | 2 +- .../BarotraumaServer/LinuxServer.csproj | 2 +- Barotrauma/BarotraumaServer/MacServer.csproj | 2 +- .../Characters/CharacterNetworking.cs | 11 +- .../ServerSource/Networking/GameServer.cs | 7 +- .../Peers/Server/LidgrenServerPeer.cs | 6 +- .../Primitives/Peers/Server/ServerPeer.cs | 9 +- .../Peers/Server/SteamP2PServerPeer.cs | 50 +- .../BarotraumaServer/WindowsServer.csproj | 2 +- .../Characters/AI/HumanAIController.cs | 7 +- .../AI/Objectives/AIObjectiveCombat.cs | 9 +- .../AI/Objectives/AIObjectiveGoTo.cs | 4 + .../AI/Objectives/AIObjectiveLoadItem.cs | 4 +- .../AI/Objectives/AIObjectiveLoadItems.cs | 2 +- .../AI/Objectives/AIObjectiveOperateItem.cs | 21 +- .../AI/Objectives/AIObjectiveRescue.cs | 2 +- .../SharedSource/Characters/AI/Order.cs | 7 +- .../Animation/HumanoidAnimController.cs | 18 +- .../SharedSource/Characters/Attack.cs | 9 +- .../SharedSource/Characters/Character.cs | 26 +- .../Characters/CharacterEventData.cs | 34 +- .../Characters/CharacterNetworking.cs | 6 +- .../Characters/Health/CharacterHealth.cs | 21 +- .../Characters/Health/DamageModifier.cs | 22 + .../CharacterAbilityTandemFire.cs | 8 +- .../SharedSource/DebugConsole.cs | 10 +- .../Events/EventActions/BinaryOptionAction.cs | 1 - .../EventActions/CheckAfflictionAction.cs | 10 +- .../EventActions/CheckConditionalAction.cs | 6 +- .../EventActions/CheckConnectionAction.cs | 26 +- .../Events/EventActions/CheckDataAction.cs | 24 +- .../Events/EventActions/CheckItemAction.cs | 92 ++- .../Events/EventActions/CheckOrderAction.cs | 14 +- .../EventActions/CheckSelectedAction.cs | 89 +++ .../EventActions/CheckSelectedItemAction.cs | 13 +- .../Events/EventActions/EventAction.cs | 2 +- .../Events/EventActions/GodModeAction.cs | 19 +- .../EventActions/InventoryHighlightAction.cs | 33 ++ .../Events/EventActions/MessageBoxAction.cs | 10 +- .../Events/EventActions/MissionAction.cs | 36 +- .../EventActions/NPCChangeTeamAction.cs | 42 +- .../Events/EventActions/NPCFollowAction.cs | 19 +- .../EventActions/NPCOperateItemAction.cs | 122 ++++ .../Events/EventActions/NPCWaitAction.cs | 4 +- .../Events/EventActions/SpawnAction.cs | 9 +- .../Events/EventActions/TutorialIconAction.cs | 6 +- .../EventActions/TutorialSegmentAction.cs | 10 +- .../Events/EventActions/UIHighlightAction.cs | 62 ++ .../Missions/AbandonedOutpostMission.cs | 21 +- .../Events/Missions/AlienRuinMission.cs | 15 +- .../Events/Missions/BeaconMission.cs | 20 +- .../Events/Missions/CargoMission.cs | 17 +- .../Events/Missions/CombatMission.cs | 10 +- .../Events/Missions/EscortMission.cs | 9 +- .../Events/Missions/GoToMission.cs | 21 +- .../Events/Missions/MineralMission.cs | 23 +- .../SharedSource/Events/Missions/Mission.cs | 29 +- .../Events/Missions/MissionPrefab.cs | 64 ++- .../Events/Missions/MonsterMission.cs | 26 +- .../Events/Missions/NestMission.cs | 19 +- .../Events/Missions/PirateMission.cs | 12 +- .../Events/Missions/SalvageMission.cs | 19 +- .../Events/Missions/ScanMission.cs | 34 +- .../SharedSource/Events/MonsterEvent.cs | 8 +- .../SharedSource/GameSession/CargoManager.cs | 4 +- .../SharedSource/GameSession/CrewManager.cs | 28 + .../GameModes/Tutorials/TutorialPrefab.cs | 8 + .../GameSession/UpgradeManager.cs | 8 +- .../Items/Components/DockingPort.cs | 16 +- .../Items/Components/ElectricalDischarger.cs | 2 +- .../Items/Components/Holdable/Throwable.cs | 6 + .../Items/Components/ItemContainer.cs | 12 +- .../Items/Components/Machines/Sonar.cs | 7 + .../Items/Components/Power/PowerTransfer.cs | 3 +- .../Items/Components/Power/Powered.cs | 38 +- .../SharedSource/Items/Components/Quality.cs | 13 +- .../Items/Components/Repairable.cs | 3 + .../BooleanOperatorComponent.cs | 4 + .../Items/Components/Signal/MotionSensor.cs | 11 +- .../SharedSource/Items/Components/Turret.cs | 10 +- .../SharedSource/Items/Item.cs | 17 +- .../SharedSource/Items/ItemPrefab.cs | 2 +- .../SharedSource/Map/Levels/Level.cs | 15 +- .../SharedSource/Map/LinkedSubmarine.cs | 4 + .../SharedSource/Map/Map/Location.cs | 10 +- .../SharedSource/Map/Map/Map.cs | 7 + .../SharedSource/Map/Submarine.cs | 2 +- .../SharedSource/Map/SubmarineBody.cs | 4 +- .../SharedSource/Networking/Client.cs | 1 - .../Primitives/NetworkPeerStructs.cs | 32 +- .../StatusEffects/DelayedEffect.cs | 8 +- .../StatusEffects/StatusEffect.cs | 2 +- Barotrauma/BarotraumaShared/changelog.txt | 544 ++++++++---------- CONTRIBUTING.md | 6 +- .../GA_SDK_NETSTANDARD.csproj | 2 +- LinuxSolution.sln | 15 + MacSolution.sln | 18 + README.md | 6 +- WindowsSolution.sln | 9 + 152 files changed, 1931 insertions(+), 1071 deletions(-) create mode 100644 Barotrauma/BarotraumaClient/ClientSource/Events/EventActions/InventoryHighlightAction.cs create mode 100644 Barotrauma/BarotraumaClient/ClientSource/Events/EventActions/UIHighlightAction.cs create mode 100644 Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/CheckSelectedAction.cs create mode 100644 Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/InventoryHighlightAction.cs create mode 100644 Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/NPCOperateItemAction.cs create mode 100644 Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/UIHighlightAction.cs diff --git a/Barotrauma/BarotraumaClient/ClientSource/Characters/CharacterHUD.cs b/Barotrauma/BarotraumaClient/ClientSource/Characters/CharacterHUD.cs index 9ef84bc9e..f4742ac64 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Characters/CharacterHUD.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Characters/CharacterHUD.cs @@ -399,12 +399,9 @@ namespace Barotrauma progressBar.Draw(spriteBatch, cam); } - void DrawInteractionIcon(Entity entity, string iconStyle) + void DrawInteractionIcon(Entity entity, Identifier iconStyle) { if (entity == null || entity.Removed) { return; } - var characterEntity = entity as Character; - if (characterEntity is not null && (characterEntity.IsDead || characterEntity.IsIncapacitated)) { return; } - if (GUIStyle.GetComponentStyle(iconStyle) is not GUIComponentStyle style) { return; } Hull currentHull = entity switch { @@ -412,20 +409,28 @@ namespace Barotrauma Item item => item.CurrentHull, _ => null }; - Range visibleRange = new Range(currentHull == Character.Controlled.CurrentHull ? 500.0f : 100.0f, float.PositiveInfinity); - if (characterEntity?.CampaignInteractionType == CampaignMode.InteractionType.Examine) + LocalizedString label = null; + if (entity is Character characterEntity) { - //TODO: we could probably do better than just hardcoding - //a check for InteractionType.Examine here. + if (characterEntity.IsDead || characterEntity.IsIncapacitated) { return; } + if (characterEntity?.CampaignInteractionType == CampaignMode.InteractionType.Examine) + { + //TODO: we could probably do better than just hardcoding + //a check for InteractionType.Examine here. - if (Vector2.DistanceSquared(character.Position, entity.Position) > 500f * 500f) { return; } + if (Vector2.DistanceSquared(character.Position, entity.Position) > 500f * 500f) { return; } - var body = Submarine.CheckVisibility(character.SimPosition, entity.SimPosition, ignoreLevel: true); - if (body != null && body.UserData != entity) { return; } + var body = Submarine.CheckVisibility(character.SimPosition, entity.SimPosition, ignoreLevel: true); + if (body != null && body.UserData != entity) { return; } - visibleRange = new Range(-100f, 500f); + visibleRange = new Range(-100f, 500f); + } + label = characterEntity?.Info?.Title; } + + if (GUIStyle.GetComponentStyle(iconStyle) is not GUIComponentStyle style) { return; } + float dist = Vector2.Distance(character.WorldPosition, entity.WorldPosition); float distFactor = 1.0f - MathUtils.InverseLerp(1000.0f, 3000.0f, dist); float alpha = MathHelper.Lerp(0.3f, 1.0f, distFactor); @@ -436,13 +441,13 @@ namespace Barotrauma visibleRange, style.GetDefaultSprite(), style.Color * alpha, - label: characterEntity?.Info?.Title); + label: label); } foreach (Character npc in Character.CharacterList) { if (npc.CampaignInteractionType == CampaignMode.InteractionType.None) { continue; } - DrawInteractionIcon(npc, "CampaignInteractionIcon." + npc.CampaignInteractionType); + DrawInteractionIcon(npc, ("CampaignInteractionIcon." + npc.CampaignInteractionType).ToIdentifier()); } if (GameMain.GameSession?.GameMode is TutorialMode tutorialMode && tutorialMode.Tutorial is not null) diff --git a/Barotrauma/BarotraumaClient/ClientSource/Characters/CharacterNetworking.cs b/Barotrauma/BarotraumaClient/ClientSource/Characters/CharacterNetworking.cs index 4ad12a2d4..4a9a99547 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Characters/CharacterNetworking.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Characters/CharacterNetworking.cs @@ -2,6 +2,7 @@ using Barotrauma.Networking; using Microsoft.Xna.Framework; using System; +using System.Collections.Immutable; using System.Linq; namespace Barotrauma @@ -141,7 +142,7 @@ namespace Barotrauma public virtual void ClientEventWrite(IWriteMessage msg, NetEntityEvent.IData extraData = null) { - if (!(extraData is IEventData eventData)) { throw new Exception($"Malformed character event: expected {nameof(Character)}.{nameof(IEventData)}"); } + if (extraData is not IEventData eventData) { throw new Exception($"Malformed character event: expected {nameof(Character)}.{nameof(IEventData)}"); } msg.WriteRangedInteger((int)eventData.EventType, (int)EventType.MinValue, (int)EventType.MaxValue); switch (eventData) @@ -471,25 +472,11 @@ namespace Barotrauma break; case EventType.AddToCrew: GameMain.GameSession.CrewManager.AddCharacter(this); - CharacterTeamType teamID = (CharacterTeamType)msg.ReadByte(); - ushort itemCount = msg.ReadUInt16(); - for (int i = 0; i < itemCount; i++) - { - ushort itemID = msg.ReadUInt16(); - if (!(Entity.FindEntityByID(itemID) is Item item)) { continue; } - item.AllowStealing = true; - var wifiComponent = item.GetComponent(); - if (wifiComponent != null) - { - wifiComponent.TeamID = teamID; - } - var idCard = item.GetComponent(); - if (idCard != null) - { - idCard.TeamID = teamID; - idCard.SubmarineSpecificID = 0; - } - } + ReadItemTeamChange(msg, true); + break; + case EventType.RemoveFromCrew: + GameMain.GameSession.CrewManager.RemoveCharacter(this, removeInfo: true); + ReadItemTeamChange(msg, false); break; case EventType.UpdateExperience: int experienceAmount = msg.ReadInt32(); @@ -520,9 +507,27 @@ namespace Barotrauma info?.ChangeSavedStatValue(statType, statValue, statIdentifier, removeOnDeath, setValue: true); } break; - } msg.ReadPadBits(); + + static void ReadItemTeamChange(IReadMessage msg, bool allowStealing) + { + var itemTeamChange = INetSerializableStruct.Read(msg); + foreach (var itemID in itemTeamChange.ItemIds) + { + if (FindEntityByID(itemID) is not Item item) { continue; } + item.AllowStealing = allowStealing; + if (item.GetComponent() is { } wifiComponent) + { + wifiComponent.TeamID = itemTeamChange.TeamId; + } + if (item.GetComponent() is { } idCard) + { + idCard.TeamID = itemTeamChange.TeamId; + idCard.SubmarineSpecificID = 0; + } + } + } } public static Character ReadSpawnData(IReadMessage inc) diff --git a/Barotrauma/BarotraumaClient/ClientSource/Characters/Health/CharacterHealth.cs b/Barotrauma/BarotraumaClient/ClientSource/Characters/Health/CharacterHealth.cs index b5acfe2e8..983906c72 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Characters/Health/CharacterHealth.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Characters/Health/CharacterHealth.cs @@ -280,6 +280,7 @@ namespace Barotrauma cprButton = new GUIButton(new RectTransform(new Vector2(0.17f, 0.17f), characterIndicatorArea.RectTransform, Anchor.BottomLeft, scaleBasis: ScaleBasis.Smallest), text: "", style: "CPRButton") { + UserData = UIHighlightAction.ElementId.CPRButton, OnClicked = (button, userData) => { Character selectedCharacter = Character.Controlled?.SelectedCharacter; @@ -690,7 +691,7 @@ namespace Barotrauma { distortTimer = (distortTimer + deltaTime * distortSpeed) % MathHelper.TwoPi; Character.BlurStrength = (float)(Math.Sin(distortTimer) + 1.5f) * 0.25f * blurStrength; - Character.DistortStrength = (float)(Math.Sin(distortTimer) + 1.0f) * 0.1f * distortStrength; + Character.DistortStrength = (float)(Math.Sin(distortTimer) + 1.0f) * 0.05f * distortStrength; } else { @@ -1294,6 +1295,7 @@ namespace Barotrauma Dictionary treatmentSuitability = new Dictionary(); GetSuitableTreatments(treatmentSuitability, normalize: true, + user: Character.Controlled, ignoreHiddenAfflictions: true, limb: selectedLimbIndex == -1 ? null : Character.AnimController.Limbs.Find(l => l.HealthIndex == selectedLimbIndex)); @@ -1337,13 +1339,13 @@ namespace Barotrauma }; var innerFrame = new GUIButton(new RectTransform(Vector2.One, itemSlot.RectTransform, Anchor.Center, Pivot.Center, scaleBasis: ScaleBasis.Smallest), style: "SubtreeHeader") - { + { UserData = item, DisabledColor = Color.White * 0.1f, PlaySoundOnSelect = false, OnClicked = (btn, userdata) => { - if (!(userdata is ItemPrefab itemPrefab)) { return false; } + if (userdata is not ItemPrefab itemPrefab) { return false; } var item = Character.Controlled.Inventory.FindItem(it => it.Prefab == itemPrefab, recursive: true); if (item == null) { return false; } Limb targetLimb = Character.AnimController.Limbs.FirstOrDefault(l => l.HealthIndex == selectedLimbIndex); @@ -1900,6 +1902,7 @@ namespace Barotrauma public void ClientRead(IReadMessage inc) { newAfflictions.Clear(); + newPeriodicEffects.Clear(); byte afflictionCount = inc.ReadByte(); for (int i = 0; i < afflictionCount; i++) { @@ -1921,7 +1924,7 @@ namespace Barotrauma int periodicAfflictionCount = inc.ReadByte(); for (int j = 0; j < periodicAfflictionCount; j++) { - float periodicAfflictionTimer = inc.ReadRangedSingle(afflictionPrefab.PeriodicEffects[j].MinInterval, afflictionPrefab.PeriodicEffects[j].MaxInterval, 8); + float periodicAfflictionTimer = inc.ReadRangedSingle(0, afflictionPrefab.PeriodicEffects[j].MaxInterval, 8); newPeriodicEffects.Add((afflictionPrefab.PeriodicEffects[j], periodicAfflictionTimer)); } newAfflictions.Add((null, afflictionPrefab, afflictionStrength)); @@ -1991,13 +1994,13 @@ namespace Barotrauma //timer has wrapped around, apply the effect if (periodicEffect.timer - existingAffliction.PeriodicEffectTimers[periodicEffect.effect] > periodicEffect.effect.MinInterval / 2) { - existingAffliction.PeriodicEffectTimers[periodicEffect.effect] = periodicEffect.timer; foreach (StatusEffect effect in periodicEffect.effect.StatusEffects) { Limb targetLimb = Character.AnimController.Limbs.FirstOrDefault(l => l.HealthIndex == limbHealths.IndexOf(limb)); existingAffliction.ApplyStatusEffect(ActionType.OnActive, effect, deltaTime: 1.0f, this, targetLimb: targetLimb); } } + existingAffliction.PeriodicEffectTimers[periodicEffect.effect] = periodicEffect.timer; } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Events/EventActions/ConversationAction.cs b/Barotrauma/BarotraumaClient/ClientSource/Events/EventActions/ConversationAction.cs index 065feb05f..865634dd1 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Events/EventActions/ConversationAction.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Events/EventActions/ConversationAction.cs @@ -92,11 +92,13 @@ namespace Barotrauma } } + float prevSize = conversationList.TotalSize; + List extraButtons = CreateConversation(conversationList, text, speaker, options, string.IsNullOrWhiteSpace(spriteIdentifier)); AssignActionsToButtons(extraButtons, lastMessageBox); RecalculateLastMessage(conversationList, true); - - conversationList.ScrollToEnd(0.5f); + conversationList.BarScroll = (prevSize - conversationList.Content.Rect.Height) / (conversationList.TotalSize - conversationList.Content.Rect.Height); + conversationList.ScrollToEnd(duration: 0.5f); lastMessageBox.SetBackgroundIcon(eventSprite); return; } @@ -112,7 +114,7 @@ namespace Barotrauma }; messageBox.OnAddedToGUIUpdateList += (GUIComponent component) => { - if (!(Screen.Selected is GameScreen)) { messageBox.Close(); } + if (Screen.Selected is not GameScreen) { messageBox.Close(); } }; lastMessageBox = messageBox; @@ -321,7 +323,7 @@ namespace Barotrauma AlwaysOverrideCursor = true }; - LocalizedString translatedText = TextManager.Get(text).Fallback(text); + LocalizedString translatedText = TextManager.ParseInputTypes(TextManager.Get(text)).Fallback(text); if (speaker?.Info != null && drawChathead) { diff --git a/Barotrauma/BarotraumaClient/ClientSource/Events/EventActions/InventoryHighlightAction.cs b/Barotrauma/BarotraumaClient/ClientSource/Events/EventActions/InventoryHighlightAction.cs new file mode 100644 index 000000000..cdcede52f --- /dev/null +++ b/Barotrauma/BarotraumaClient/ClientSource/Events/EventActions/InventoryHighlightAction.cs @@ -0,0 +1,58 @@ +using Microsoft.Xna.Framework; +using System.Linq; + +namespace Barotrauma; + +partial class InventoryHighlightAction : EventAction +{ + private static readonly Color highlightColor = Color.Orange; + + partial void UpdateProjSpecific() + { + foreach (var target in ParentEvent.GetTargets(TargetTag)) + { + SetHighlight(target); + } + } + + private void SetHighlight(Entity entity) + { + if (entity is Item item) + { + int i = 0; + foreach (var itemContainer in item.GetComponents()) + { + if (ItemContainerIndex == -1 || i == ItemContainerIndex) + { + SetHighlight(itemContainer.Inventory); + } + i++; + } + } + else if (entity is Character c) + { + SetHighlight(c.Inventory); + } + } + + private void SetHighlight(Inventory inventory) + { + if (inventory?.visualSlots == null) { return; } + for (int i = 0; i < inventory.visualSlots.Length; i++) + { + if (inventory.visualSlots[i].HighlightTimer > 0) { continue; } + Item item = inventory.GetItemAt(i); + if (IsSuitableItem(item) || + (Recursive && item?.OwnInventory != null && item.OwnInventory.FindAllItems(it => IsSuitableItem(it), recursive: true).Any())) + { + inventory.visualSlots[i].ShowBorderHighlight(highlightColor, 0.5f, 0.5f, 0.1f); + } + } + } + + private bool IsSuitableItem(Item item) + { + return (ItemIdentifier.IsEmpty && item == null) || + (item != null && (item.Prefab.Identifier == ItemIdentifier || item.HasTag(ItemIdentifier))); + } +} \ No newline at end of file diff --git a/Barotrauma/BarotraumaClient/ClientSource/Events/EventActions/MessageBoxAction.cs b/Barotrauma/BarotraumaClient/ClientSource/Events/EventActions/MessageBoxAction.cs index e2bd6f963..b75a1af4a 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Events/EventActions/MessageBoxAction.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Events/EventActions/MessageBoxAction.cs @@ -8,20 +8,24 @@ partial class MessageBoxAction : EventAction { partial void UpdateProjSpecific() { - if (Type == ActionType.Create) + if (Type == ActionType.Create || Type == ActionType.ConnectObjective) { CreateMessageBox(); if (!ObjectiveTag.IsEmpty && GameMain.GameSession?.GameMode is TutorialMode tutorialMode) { - Identifier id = Identifier.IsEmpty ? Text : Identifier; + Identifier id = Identifier.IfEmpty(Text); var segment = Tutorial.Segment.CreateMessageBoxSegment(id, ObjectiveTag, CreateMessageBox); - tutorialMode.Tutorial?.TriggerTutorialSegment(segment); + tutorialMode.Tutorial?.TriggerTutorialSegment(segment, connectObjective: Type == ActionType.ConnectObjective); } } else if (Type == ActionType.Close) { GUIMessageBox.Close(Tag); } + else if (Type == ActionType.Clear) + { + GUIMessageBox.CloseAll(); + } } public void CreateMessageBox() diff --git a/Barotrauma/BarotraumaClient/ClientSource/Events/EventActions/TutorialHighlightAction.cs b/Barotrauma/BarotraumaClient/ClientSource/Events/EventActions/TutorialHighlightAction.cs index beb14498a..732c1a480 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Events/EventActions/TutorialHighlightAction.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Events/EventActions/TutorialHighlightAction.cs @@ -4,7 +4,7 @@ namespace Barotrauma; partial class TutorialHighlightAction : EventAction { - private static readonly Color highlightColor = Color.OrangeRed; + private static readonly Color highlightColor = Color.Orange; partial void UpdateProjSpecific() { @@ -19,32 +19,32 @@ partial class TutorialHighlightAction : EventAction { if (entity is Item i) { - SetHighlight(i); + SetItemHighlight(i); } else if (entity is Structure s) { - SetHighlight(s); + SetStructureHighlight(s); } else if (entity is Character c) { - SetHighlight(c); + SetCharacterHighlight(c); } } - private void SetHighlight(Item item) + private void SetItemHighlight(Item item) { if (item.ExternalHighlight == State) { return; } - item.SpriteColor = (State) ? highlightColor : Color.White; + item.HighlightColor = State ? highlightColor : null; item.ExternalHighlight = State; } - private void SetHighlight(Structure structure) + private void SetStructureHighlight(Structure structure) { - structure.SpriteColor = (State) ? highlightColor : Color.White; + structure.SpriteColor = State ? highlightColor : Color.White; structure.ExternalHighlight = State; } - private void SetHighlight(Character character) + private void SetCharacterHighlight(Character character) { character.ExternalHighlight = State; } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Events/EventActions/TutorialSegmentAction.cs b/Barotrauma/BarotraumaClient/ClientSource/Events/EventActions/TutorialSegmentAction.cs index d39340d05..ab9b097d3 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Events/EventActions/TutorialSegmentAction.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Events/EventActions/TutorialSegmentAction.cs @@ -11,13 +11,13 @@ partial class TutorialSegmentAction : EventAction // Only need to create the segment when it's being triggered (otherwise the tutorial already has the segment instance) if (Type == SegmentActionType.Trigger) { - segment = Tutorial.Segment.CreateInfoBoxSegment(Id, ObjectiveTag, AutoPlayVideo ? Tutorials.AutoPlayVideo.Yes : Tutorials.AutoPlayVideo.No, + segment = Tutorial.Segment.CreateInfoBoxSegment(Identifier, ObjectiveTag, AutoPlayVideo ? Tutorials.AutoPlayVideo.Yes : Tutorials.AutoPlayVideo.No, new Tutorial.Segment.Text(TextTag, Width, Height, Anchor.Center), new Tutorial.Segment.Video(VideoFile, TextTag, Width, Height)); } else if (Type == SegmentActionType.Add) { - segment = Tutorial.Segment.CreateObjectiveSegment(Id, !ObjectiveTag.IsEmpty ? ObjectiveTag : Id); + segment = Tutorial.Segment.CreateObjectiveSegment(Identifier, !ObjectiveTag.IsEmpty ? ObjectiveTag : Identifier); } if (GameMain.GameSession?.GameMode is TutorialMode tutorialMode) { @@ -30,21 +30,21 @@ partial class TutorialSegmentAction : EventAction tutorial.TriggerTutorialSegment(segment); break; case SegmentActionType.Complete: - tutorial.CompleteTutorialSegment(Id); + tutorial.CompleteTutorialSegment(Identifier); break; case SegmentActionType.Remove: - tutorial.RemoveTutorialSegment(Id); + tutorial.RemoveTutorialSegment(Identifier); break; case SegmentActionType.CompleteAndRemove: - tutorial.CompleteTutorialSegment(Id); - tutorial.RemoveTutorialSegment(Id); + tutorial.CompleteTutorialSegment(Identifier); + tutorial.RemoveTutorialSegment(Identifier); break; } } } else { - DebugConsole.ShowError($"Error in event \"{ParentEvent.Prefab.Identifier}\": attempting to use TutorialSegmentAction during a non-Tutorial game mode!"); + DebugConsole.ThrowError($"Error in event \"{ParentEvent.Prefab.Identifier}\": attempting to use TutorialSegmentAction during a non-Tutorial game mode!"); } } } \ No newline at end of file diff --git a/Barotrauma/BarotraumaClient/ClientSource/Events/EventActions/UIHighlightAction.cs b/Barotrauma/BarotraumaClient/ClientSource/Events/EventActions/UIHighlightAction.cs new file mode 100644 index 000000000..2826454ca --- /dev/null +++ b/Barotrauma/BarotraumaClient/ClientSource/Events/EventActions/UIHighlightAction.cs @@ -0,0 +1,46 @@ +using Microsoft.Xna.Framework; +using System.Linq; + +namespace Barotrauma; + +partial class UIHighlightAction : EventAction +{ + private static readonly Color highlightColor = Color.Orange; + + partial void UpdateProjSpecific() + { + bool useCircularFlash = false; + GUIComponent component = null; + + if (Id != ElementId.None) + { + component = GUI.GetAdditions().FirstOrDefault(c => Equals(Id, c.UserData)); + } + else if (!EntityIdentifier.IsEmpty) + { + component = GUI.GetAdditions().FirstOrDefault(c => + c.UserData is MapEntityPrefab mep && mep.Identifier == EntityIdentifier || c.UserData is MapEntity me && me.Prefab.Identifier == EntityIdentifier); + } + else if (!OrderIdentifier.IsEmpty) + { + useCircularFlash = true; + if (!OrderTargetTag.IsEmpty) + { + component = + GUI.GetAdditions().FirstOrDefault(c => + c.UserData is CrewManager.MinimapNodeData nodeData && nodeData.Order is Order order && + order.Identifier == OrderIdentifier && order.Option == OrderOption && order.TargetEntity is Item item && item.HasTag(OrderTargetTag)); + } + component ??= + GUI.GetAdditions().FirstOrDefault(c => c.UserData is Order order && order.Identifier == OrderIdentifier && order.Option == OrderOption) ?? + GUI.GetAdditions().FirstOrDefault(c => c.UserData is Order order && order.Identifier == OrderIdentifier) ?? + GUI.GetAdditions().FirstOrDefault(c => Equals(OrderCategory, c.UserData)); + } + + if (component != null && component.FlashTimer <= 0.0f) + { + component.Flash(highlightColor, useCircularFlash: useCircularFlash); + component.Bounce |= Bounce; + } + } +} \ No newline at end of file diff --git a/Barotrauma/BarotraumaClient/ClientSource/Events/EventManager.cs b/Barotrauma/BarotraumaClient/ClientSource/Events/EventManager.cs index 103e2cd2c..9093450ec 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Events/EventManager.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Events/EventManager.cs @@ -651,11 +651,11 @@ namespace Barotrauma break; case NetworkEventType.MISSION: Identifier missionIdentifier = msg.ReadIdentifier(); - + string missionName = msg.ReadString(); MissionPrefab? prefab = MissionPrefab.Prefabs.Find(mp => mp.Identifier == missionIdentifier); if (prefab != null) { - new GUIMessageBox(string.Empty, TextManager.GetWithVariable("missionunlocked", "[missionname]", prefab.Name), + new GUIMessageBox(string.Empty, TextManager.GetWithVariable("missionunlocked", "[missionname]", missionName), Array.Empty(), type: GUIMessageBox.Type.InGame, icon: prefab.Icon, relativeSize: new Vector2(0.3f, 0.15f), minSize: new Point(512, 128)) { IconColor = prefab.IconColor diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUI.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUI.cs index cbe1cb50d..c158fc21d 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUI.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUI.cs @@ -410,7 +410,7 @@ namespace Barotrauma { y += yStep; DrawString(spriteBatch, new Vector2(10, y), - "Sub pos: " + Submarine.MainSub.Position.ToPoint(), + "Sub pos: " + Submarine.MainSub.WorldPosition.ToPoint(), Color.White, Color.Black * 0.5f, 0, GUIStyle.SmallFont); } @@ -879,6 +879,11 @@ namespace Barotrauma } } } + + public static IEnumerable GetAdditions() + { + return additions; + } #endregion public static GUIComponent MouseOn { get; private set; } diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIComponent.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIComponent.cs index 73ba38a9c..926e5520b 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIComponent.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIComponent.cs @@ -486,7 +486,7 @@ namespace Barotrauma { if (bounceTimer > 3.0f || bounceDown) { - RectTransform.ScreenSpaceOffset = new Point(RectTransform.ScreenSpaceOffset.X, (int) -(bounceJump * 10f)); + RectTransform.ScreenSpaceOffset = new Point(RectTransform.ScreenSpaceOffset.X, (int) -(bounceJump * 15f * GUI.Scale)); if (!bounceDown) { bounceJump += deltaTime * 4; @@ -503,6 +503,7 @@ namespace Barotrauma bounceJump = 0.0f; bounceTimer = 0.0f; bounceDown = false; + Bounce = false; } } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIImage.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIImage.cs index c19bcc378..ea44140e7 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIImage.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIImage.cs @@ -85,11 +85,11 @@ namespace Barotrauma get { return sprite; } set { - if (sprite == value) return; + if (sprite == value) { return; } sprite = value; sourceRect = value == null ? Rectangle.Empty : value.SourceRect; origin = value == null ? Vector2.Zero : value.size / 2; - if (scaleToFit) RecalculateScale(); + if (scaleToFit) { RecalculateScale(); } } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIListBox.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIListBox.cs index b532b7900..71173d75d 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIListBox.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIListBox.cs @@ -601,16 +601,13 @@ namespace Barotrauma yield return CoroutineStatus.Success; } float t = 0.0f; - float startScroll = BarScroll * BarSize; + float startScroll = BarScroll; float distanceToTravel = ScrollBar.MaxValue - startScroll; - float progress = startScroll; float speed = distanceToTravel / duration; - - while (t < duration && !MathUtils.NearlyEqual(ScrollBar.MaxValue, progress)) + while (t < duration && !MathUtils.NearlyEqual(ScrollBar.MaxValue, BarScroll)) { t += CoroutineManager.DeltaTime; - progress += speed * CoroutineManager.DeltaTime; - BarScroll = progress; + BarScroll += speed * CoroutineManager.DeltaTime; yield return CoroutineStatus.Running; } diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIMessageBox.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIMessageBox.cs index b67fd7713..3aa1cff1c 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIMessageBox.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIMessageBox.cs @@ -207,7 +207,7 @@ namespace Barotrauma { InnerFrame.RectTransform.AbsoluteOffset = new Point(0, GameMain.GraphicsHeight); CanBeFocused = false; - AutoClose = true; + AutoClose = type == Type.InGame; GUIStyle.Apply(InnerFrame, "", this); var horizontalLayoutGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.98f, 0.95f), InnerFrame.RectTransform, Anchor.Center), diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIStyle.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIStyle.cs index 4737c85f7..07e976ada 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIStyle.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIStyle.cs @@ -160,8 +160,13 @@ namespace Barotrauma public static Point ItemFrameOffset => new Point(0, 3).Multiply(GUI.SlicedSpriteScale); - public static GUIComponentStyle GetComponentStyle(string name) - => ComponentStyles.TryGet(name, out var style) ? style : null; + public static GUIComponentStyle GetComponentStyle(string styleName) + { + return GetComponentStyle(styleName.ToIdentifier()); + } + + public static GUIComponentStyle GetComponentStyle(Identifier identifier) + => ComponentStyles.TryGet(identifier, out var style) ? style : null; public static void Apply(GUIComponent targetComponent, string styleName = "", GUIComponent parent = null) { diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/Store.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/Store.cs index f32e5de6e..eca7c4334 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/Store.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/Store.cs @@ -238,7 +238,7 @@ namespace Barotrauma errorId = "Store.SelectStore:StoreDoesntExist"; msg = $"Error selecting store with identifier \"{identifier}\" at {CurrentLocation}: store with the identifier doesn't exist at the location."; } - DebugConsole.ShowError(msg); + DebugConsole.LogError(msg); GameAnalyticsManager.AddErrorEventOnce(errorId, GameAnalyticsManager.ErrorSeverity.Error, msg); } } @@ -263,7 +263,7 @@ namespace Barotrauma } if (!msg.IsNullOrEmpty()) { - DebugConsole.ShowError(msg); + DebugConsole.LogError(msg); GameAnalyticsManager.AddErrorEventOnce(errorId, GameAnalyticsManager.ErrorSeverity.Error, msg); } } @@ -1250,7 +1250,7 @@ namespace Barotrauma } catch (NotImplementedException e) { - DebugConsole.ShowError($"Error getting item price: Uknown store tab type. {e.StackTrace.CleanupStackTrace()}"); + DebugConsole.LogError($"Error getting item price: Uknown store tab type. {e.StackTrace.CleanupStackTrace()}"); } } @@ -1808,7 +1808,7 @@ namespace Barotrauma { string errorMsg = $"Error creating a store quantity label text: unknown store tab.\n{e.StackTrace.CleanupStackTrace()}"; #if DEBUG - DebugConsole.ShowError(errorMsg); + DebugConsole.LogError(errorMsg); #else DebugConsole.AddWarning(errorMsg); #endif @@ -1882,7 +1882,7 @@ namespace Barotrauma } catch (NotImplementedException e) { - DebugConsole.ShowError($"Error getting item availability: Uknown store tab type. {e.StackTrace.CleanupStackTrace()}"); + DebugConsole.LogError($"Error getting item availability: Uknown store tab type. {e.StackTrace.CleanupStackTrace()}"); } if (list != null && list.Find(i => i.ItemPrefab == itemPrefab) is PurchasedItem item) { @@ -1962,7 +1962,7 @@ namespace Barotrauma } catch (NotImplementedException e) { - DebugConsole.ShowError($"Error adding an item to the shopping crate: Uknown store tab type. {e.StackTrace.CleanupStackTrace()}"); + DebugConsole.LogError($"Error adding an item to the shopping crate: Uknown store tab type. {e.StackTrace.CleanupStackTrace()}"); return false; } } @@ -1982,7 +1982,7 @@ namespace Barotrauma } catch (NotImplementedException e) { - DebugConsole.ShowError($"Error clearing the shopping crate: Uknown store tab type. {e.StackTrace.CleanupStackTrace()}"); + DebugConsole.LogError($"Error clearing the shopping crate: Uknown store tab type. {e.StackTrace.CleanupStackTrace()}"); return false; } } @@ -2029,7 +2029,7 @@ namespace Barotrauma } catch (NotImplementedException e) { - DebugConsole.ShowError($"Error confirming the store transaction: Uknown store tab type. {e.StackTrace.CleanupStackTrace()}"); + DebugConsole.LogError($"Error confirming the store transaction: Uknown store tab type. {e.StackTrace.CleanupStackTrace()}"); return false; } var itemsToRemove = new List(); diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/TabMenu.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/TabMenu.cs index 4b17d15d3..8a9d4e8c1 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/TabMenu.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/TabMenu.cs @@ -206,9 +206,9 @@ namespace Barotrauma transferMenuButton.RectTransform.AbsoluteOffset = new Point(0, -pos - transferMenu.Rect.Height); } GameSession.UpdateTalentNotificationIndicator(talentPointNotification); - if (Character.Controlled is { } controlled && talentResetButton != null && talentApplyButton != null) + if (Character.Controlled?.Info is { } characterInfo && talentResetButton != null && talentApplyButton != null) { - int talentCount = selectedTalents.Count - controlled.Info.GetUnlockedTalentsInTree().Count(); + int talentCount = selectedTalents.Count - characterInfo.GetUnlockedTalentsInTree().Count(); talentResetButton.Enabled = talentApplyButton.Enabled = talentCount > 0; if (talentApplyButton.Enabled && talentApplyButton.FlashTimer <= 0.0f) { @@ -1918,14 +1918,18 @@ namespace Barotrauma skillListBox = new GUIListBox(new RectTransform(new Vector2(1f, 1f - skillBlock.RectTransform.RelativeSize.Y), skillLayout.RectTransform), style: null); CreateSkillList(controlledCharacter, info, skillListBox); - if (controlledCharacter != null) + new GUIFrame(new RectTransform(new Vector2(1f, 1f), contentLayout.RectTransform), style: "HorizontalLine"); + + GUIListBox talentTreeListBox = new GUIListBox(new RectTransform(new Vector2(1f, 0.6f), contentLayout.RectTransform, Anchor.TopCenter), isHorizontal: true, style: null); + + if (controlledCharacter == null) + { + talentTreeListBox.Enabled = false; + } + else { if (!TalentTree.JobTalentTrees.TryGet(info.Job.Prefab.Identifier, out TalentTree talentTree)) { return; } - new GUIFrame(new RectTransform(new Vector2(1f, 1f), contentLayout.RectTransform), style: "HorizontalLine"); - - GUIListBox talentTreeListBox = new GUIListBox(new RectTransform(new Vector2(1f, 0.6f), contentLayout.RectTransform, Anchor.TopCenter), isHorizontal: true, style: null); - selectedTalents = info.GetUnlockedTalentsInTree().ToList(); List subTreeNames = new List(); diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/UpgradeStore.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/UpgradeStore.cs index ad7358468..08a186081 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/UpgradeStore.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/UpgradeStore.cs @@ -874,7 +874,7 @@ namespace Barotrauma itemPrefab.SwappableItem.CanBeBought && itemPrefab.SwappableItem.SwapIdentifier.Equals(item.Prefab.SwappableItem.SwapIdentifier, StringComparison.OrdinalIgnoreCase)).Cast(); - var linkedItems = Campaign.UpgradeManager.GetLinkedItemsToSwap(item) ?? new List() { item }; + var linkedItems = UpgradeManager.GetLinkedItemsToSwap(item) ?? new List() { item }; //create the swap entry only for one of the items (the one with the smallest ID) if (linkedItems.Min(it => it.ID) < item.ID) { return; } @@ -910,7 +910,7 @@ namespace Barotrauma GUILayoutGroup buttonLayout = new GUILayoutGroup(rectT(1f, 1f, toggleButton.Frame), isHorizontal: true); LocalizedString slotText = ""; - if (linkedItems.Count > 1) + if (linkedItems.Count() > 1) { slotText = TextManager.GetWithVariable("weaponslot", "[number]", string.Join(", ", linkedItems.Select(it => (swappableEntities.IndexOf(it) + 1).ToString()))); } @@ -982,7 +982,7 @@ namespace Barotrauma bool isPurchased = item.AvailableSwaps.Contains(replacement); - int price = isPurchased || replacement == item.Prefab ? 0 : replacement.SwappableItem.GetPrice(Campaign.Map?.CurrentLocation) * linkedItems.Count; + int price = isPurchased || replacement == item.Prefab ? 0 : replacement.SwappableItem.GetPrice(Campaign.Map?.CurrentLocation) * linkedItems.Count(); frames.Add(CreateUpgradeEntry(rectT(1f, 0.25f, parent.Content), replacement.UpgradePreviewSprite, replacement.Name, replacement.Description, price, replacement, @@ -998,7 +998,7 @@ namespace Barotrauma { LocalizedString promptBody = TextManager.GetWithVariables(isPurchased ? "upgrades.itemswappromptbody" : "upgrades.purchaseitemswappromptbody", ("[itemtoinstall]", replacement.Name), - ("[amount]", (replacement.SwappableItem.GetPrice(Campaign?.Map?.CurrentLocation) * linkedItems.Count).ToString())); + ("[amount]", (replacement.SwappableItem.GetPrice(Campaign?.Map?.CurrentLocation) * linkedItems.Count()).ToString())); currectConfirmation = EventEditorScreen.AskForConfirmation(TextManager.Get("Upgrades.PurchasePromptTitle"), promptBody, () => { if (GameMain.NetworkMember != null) @@ -1042,7 +1042,7 @@ namespace Barotrauma } if (toggleButton.Selected) { - var linkedItems = Campaign.UpgradeManager.GetLinkedItemsToSwap(item); + var linkedItems = UpgradeManager.GetLinkedItemsToSwap(item); foreach (var itemPreview in itemPreviews) { itemPreview.Value.OutlineColor = itemPreview.Value.Color = linkedItems.Contains(itemPreview.Key) ? GUIStyle.Orange : previewWhite; @@ -1391,7 +1391,7 @@ namespace Barotrauma { if (selectedUpgradeCategoryLayout != null) { - var linkedItems = HoveredEntity is Item hoveredItem ? Campaign.UpgradeManager.GetLinkedItemsToSwap(hoveredItem) : new List(); + var linkedItems = HoveredEntity is Item hoveredItem ? UpgradeManager.GetLinkedItemsToSwap(hoveredItem) : new List(); if (selectedUpgradeCategoryLayout.FindChild(c => c.UserData is Item item && (item == HoveredEntity || linkedItems.Contains(item)), recursive: true) is GUIButton itemElement) { if (!itemElement.Selected) { itemElement.OnClicked(itemElement, itemElement.UserData); } diff --git a/Barotrauma/BarotraumaClient/ClientSource/GameSession/CargoManager.cs b/Barotrauma/BarotraumaClient/ClientSource/GameSession/CargoManager.cs index bbdde97f2..dd4ca114b 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GameSession/CargoManager.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GameSession/CargoManager.cs @@ -139,7 +139,7 @@ namespace Barotrauma } catch (NotImplementedException e) { - DebugConsole.ShowError($"Error selling items: uknown store tab type \"{sellingMode}\".\n{e.StackTrace.CleanupStackTrace()}"); + DebugConsole.LogError($"Error selling items: uknown store tab type \"{sellingMode}\".\n{e.StackTrace.CleanupStackTrace()}"); return; } bool canAddToRemoveQueue = campaign.IsSinglePlayer && Entity.Spawner != null; @@ -148,7 +148,7 @@ namespace Barotrauma var sellValues = GetSellValuesAtCurrentLocation(storeIdentifier, itemsToSell.Select(i => i.ItemPrefab)); if (!(Location.GetStore(storeIdentifier) is { } store)) { - DebugConsole.ShowError($"Error selling items at {Location}: no store with identifier \"{storeIdentifier}\" exists.\n{Environment.StackTrace.CleanupStackTrace()}"); + DebugConsole.LogError($"Error selling items at {Location}: no store with identifier \"{storeIdentifier}\" exists.\n{Environment.StackTrace.CleanupStackTrace()}"); return; } var storeSpecificSoldItems = GetSoldItems(storeIdentifier, create: true); diff --git a/Barotrauma/BarotraumaClient/ClientSource/GameSession/CrewManager.cs b/Barotrauma/BarotraumaClient/ClientSource/GameSession/CrewManager.cs index a1f3594bf..5820ca4cd 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GameSession/CrewManager.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GameSession/CrewManager.cs @@ -291,29 +291,13 @@ namespace Barotrauma return crewArea.Rect; } - /// - /// Remove the character from the crew (and crew menus). - /// - /// The character to remove - /// If the character info is also removed, the character will not be visible in the round summary. - public void RemoveCharacter(Character character, bool removeInfo = false, bool resetCrewListIndex = true) - { - if (character == null) - { - DebugConsole.ThrowError("Tried to remove a null character from CrewManager.\n" + Environment.StackTrace.CleanupStackTrace()); - return; - } - characters.Remove(character); - if (removeInfo) { characterInfos.Remove(character.Info); } - if (resetCrewListIndex) { ResetCrewListIndex(character); } - } - /// /// Add character to the list without actually adding it to the crew /// public GUIComponent AddCharacterToCrewList(Character character) { if (character == null) { return null; } + if (crewList.Content.Children.Any(c => c.UserData as Character == character)) { return null; } var background = new GUIFrame( new RectTransform(crewListEntrySize, parent: crewList.Content.RectTransform, anchor: Anchor.TopRight), @@ -509,7 +493,15 @@ namespace Barotrauma return background; } - private void SetCharacterComponentTooltip(GUIComponent characterComponent) + public void RemoveCharacterFromCrewList(Character character) + { + if (crewList?.Content.GetChildByUserData(character) is { } component) + { + crewList.RemoveChild(component); + } + } + + private static void SetCharacterComponentTooltip(GUIComponent characterComponent) { if (!(characterComponent?.UserData is Character character)) { return; } if (character.Info?.Job?.Prefab == null) { return; } @@ -2821,7 +2813,7 @@ namespace Barotrauma return node; } - private struct MinimapNodeData + public struct MinimapNodeData { public Order Order; } diff --git a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/MultiPlayerCampaign.cs b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/MultiPlayerCampaign.cs index 6fff8e5e9..94ba1b79a 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/MultiPlayerCampaign.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/MultiPlayerCampaign.cs @@ -761,6 +761,7 @@ namespace Barotrauma item.PendingItemSwap = null; } } + campaign.CampaignUI?.UpgradeStore?.RequestRefresh(); } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/Tutorial.cs b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/Tutorial.cs index 3dbc348f4..a9c7f14e8 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/Tutorial.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/Tutorial.cs @@ -78,7 +78,7 @@ namespace Barotrauma.Tutorials public Action OnClickObjective; - public readonly TutorialSegmentType SegmentType; + public TutorialSegmentType SegmentType { get; private set; } public static Segment CreateInfoBoxSegment(Identifier id, Identifier objectiveTextTag, AutoPlayVideo autoPlayVideo, Text textContent = default, Video videoContent = default) { @@ -119,6 +119,12 @@ namespace Barotrauma.Tutorials ObjectiveText = TextManager.ParseInputTypes(TextManager.Get(objectiveTextTag)); SegmentType = TutorialSegmentType.Objective; } + + public void ConnectMessageBox(Segment messageBoxSegment) + { + SegmentType = TutorialSegmentType.MessageBox; + OnClickObjective = messageBoxSegment.OnClickObjective; + } } private bool completed; @@ -144,6 +150,7 @@ namespace Barotrauma.Tutorials private readonly EventPrefab eventPrefab; private CoroutineHandle tutorialCoroutine; + private CoroutineHandle completedCoroutine; private Character character; @@ -154,7 +161,7 @@ namespace Barotrauma.Tutorials private SubmarineInfo startOutpost = null; - public readonly List<(Entity entity, string iconStyle)> Icons = new List<(Entity entity, string iconStyle)>(); + public readonly List<(Entity entity, Identifier iconStyle)> Icons = new List<(Entity entity, Identifier iconStyle)>(); #endregion @@ -331,13 +338,16 @@ namespace Barotrauma.Tutorials { CoroutineManager.StopCoroutines(tutorialCoroutine); } - GUI.PreventPauseMenuToggle = false; + if (completedCoroutine == null && !CoroutineManager.IsCoroutineRunning(completedCoroutine)) + { + GUI.PreventPauseMenuToggle = false; + } ContentRunning = false; infoBox = null; } - else if (Character.Controlled.IsDead) + else { - CoroutineManager.StartCoroutine(Dead()); + character = Character.Controlled; } } } @@ -385,7 +395,7 @@ namespace Barotrauma.Tutorials if (eventPrefab == null) { - DebugConsole.ShowError($"No tutorial event defined for the tutorial (identifier: \"{TutorialPrefab?.Identifier.ToString() ?? "null"})\""); + DebugConsole.LogError($"No tutorial event defined for the tutorial (identifier: \"{TutorialPrefab?.Identifier.ToString() ?? "null"})\""); yield return CoroutineStatus.Failure; } @@ -399,7 +409,7 @@ namespace Barotrauma.Tutorials } else { - DebugConsole.ShowError($"Failed to create an instance for a tutorial event (identifier: \"{eventPrefab.Identifier}\""); + DebugConsole.LogError($"Failed to create an instance for a tutorial event (identifier: \"{eventPrefab.Identifier}\""); yield return CoroutineStatus.Failure; } @@ -409,10 +419,12 @@ namespace Barotrauma.Tutorials public void Complete() { GameAnalyticsManager.AddDesignEvent($"Tutorial:{Identifier}:Completed"); - CoroutineManager.StartCoroutine(TutorialCompleted()); + completedCoroutine = CoroutineManager.StartCoroutine(TutorialCompleted()); IEnumerable TutorialCompleted() { + while (GUI.PauseMenuOpen) { yield return CoroutineStatus.Running; } + GUI.PreventPauseMenuToggle = true; Character.Controlled.ClearInputs(); Character.Controlled = null; @@ -423,7 +435,7 @@ namespace Barotrauma.Tutorials var endCinematic = new CameraTransition(Submarine.MainSub, GameMain.GameScreen.Cam, null, Alignment.Center, panDuration: FadeOutTime); Completed = true; - while (endCinematic.Running) { yield return null; } + while (endCinematic.Running) { yield return CoroutineStatus.Running; } Stop(); GameMain.MainMenuScreen.ReturnToMainMenu(null, null); @@ -432,16 +444,18 @@ namespace Barotrauma.Tutorials private bool Restart(GUIButton button, object obj) { - GUI.PreventPauseMenuToggle = false; + GUIMessageBox.MessageBoxes.Clear(); + GameMain.MainMenuScreen.ReturnToMainMenu(button, obj); + Start(); return true; } - public void TriggerTutorialSegment(Segment segment) + public void TriggerTutorialSegment(Segment segment, bool connectObjective = false) { if (segment.SegmentType != TutorialSegmentType.InfoBox) { ActiveObjectives.Add(segment); - AddToObjectiveList(segment); + AddToObjectiveList(segment, connectObjective); return; } @@ -488,11 +502,14 @@ namespace Barotrauma.Tutorials } if (GUIStyle.GetComponentStyle("ObjectiveIndicatorCompleted") is GUIComponentStyle style) { + //return if already completed + if (segment.ObjectiveStateIndicator.Style == style) { return; } segment.ObjectiveStateIndicator.ApplyStyle(style); } segment.ObjectiveStateIndicator.Parent.Flash(color: GUIStyle.Green, flashDuration: 0.35f, useRectangleFlash: true); segment.ObjectiveButton.OnClicked = null; segment.ObjectiveButton.CanBeFocused = false; + GameAnalyticsManager.AddDesignEvent($"Tutorial:{Identifier}:{segmentId}:Completed"); } public void RemoveTutorialSegment(Identifier segmentId) @@ -568,8 +585,18 @@ namespace Barotrauma.Tutorials /// /// Adds the segment to the objective list /// - private void AddToObjectiveList(Segment segment) + private void AddToObjectiveList(Segment segment, bool connectExisting = false) { + if (connectExisting) + { + if (ActiveObjectives.Find(o => o.Id == segment.Id) is { } existingSegment) + { + existingSegment.ConnectMessageBox(segment); + SetButtonBehavior(existingSegment); + } + return; + } + var frameRt = new RectTransform(new Vector2(1.0f, 0.1f), objectiveGroup.RectTransform) { AbsoluteOffset = GetObjectiveHiddenPosition(), @@ -595,15 +622,25 @@ namespace Barotrauma.Tutorials frame.RectTransform.IsFixedSize = true; var indicatorRt = new RectTransform(new Point(objectiveGroup.AbsoluteSpacing), frame.RectTransform, isFixedSize: true); - segment.ObjectiveStateIndicator = new GUIImage(indicatorRt, "ObjectiveIndicatorIncomplete");; + segment.ObjectiveStateIndicator = new GUIImage(indicatorRt, "ObjectiveIndicatorIncomplete"); SetTransparent(segment.LinkedTextBlock); segment.ObjectiveButton = new GUIButton(new RectTransform(Vector2.One, segment.LinkedTextBlock.RectTransform, Anchor.TopLeft, Pivot.TopLeft), style: null) { - CanBeFocused = segment.SegmentType != TutorialSegmentType.Objective, - ToolTip = objectiveTextTranslated, - OnClicked = (GUIButton btn, object userdata) => + ToolTip = objectiveTextTranslated + }; + SetButtonBehavior(segment); + SetTransparent(segment.ObjectiveButton); + + frameRt.MoveOverTime(new Point(0, frameRt.AbsoluteOffset.Y), ObjectiveComponentAnimationTime, onDoneMoving: () => objectiveGroup?.Recalculate()); + + static void SetTransparent(GUIComponent component) => component.Color = component.HoverColor = component.PressedColor = component.SelectedColor = Color.Transparent; + + void SetButtonBehavior(Segment segment) + { + segment.ObjectiveButton.CanBeFocused = segment.SegmentType != TutorialSegmentType.Objective; + segment.ObjectiveButton.OnClicked = (GUIButton btn, object userdata) => { if (segment.SegmentType == TutorialSegmentType.InfoBox) { @@ -621,13 +658,8 @@ namespace Barotrauma.Tutorials segment.OnClickObjective?.Invoke(); } return true; - } - }; - SetTransparent(segment.ObjectiveButton); - - frameRt.MoveOverTime(new Point(0, frameRt.AbsoluteOffset.Y), ObjectiveComponentAnimationTime, onDoneMoving: () => objectiveGroup?.Recalculate()); - - static void SetTransparent(GUIComponent component) => component.Color = component.HoverColor = component.PressedColor = component.SelectedColor = Color.Transparent; + }; + } } private void ReplaySegmentVideo(Segment segment) diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Door.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Door.cs index 88bd89496..aa7baf8be 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Door.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Door.cs @@ -4,6 +4,7 @@ using Barotrauma.Networking; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using System; +using System.Linq; namespace Barotrauma.Items.Components { @@ -177,7 +178,7 @@ namespace Barotrauma.Items.Components public void Draw(SpriteBatch spriteBatch, bool editing, float itemDepth = -1) { - Color color = item.SpriteColor; + Color color = item.GetSpriteColor(withHighlight: true); if (brokenSprite == null) { //broken doors turn black if no broken sprite has been configured @@ -220,11 +221,15 @@ namespace Barotrauma.Items.Components color, 0.0f, doorSprite.Origin, item.Scale, item.SpriteEffects, doorSprite.Depth); } - if (brokenSprite != null && item.Health < item.MaxCondition) + float maxCondition = item.Repairables.Any() ? + item.Repairables.Min(r => r.RepairThreshold) / 100.0f * item.MaxCondition : + item.MaxCondition; + float healthRatio = item.Health / maxCondition; + if (brokenSprite != null && healthRatio < 1.0f) { - Vector2 scale = scaleBrokenSprite ? new Vector2(1.0f - item.Health / item.MaxCondition) : Vector2.One; + Vector2 scale = scaleBrokenSprite ? new Vector2(1.0f - healthRatio) : Vector2.One; if (IsHorizontal) { scale.X = 1; } else { scale.Y = 1; } - float alpha = fadeBrokenSprite ? 1.0f - item.Health / item.MaxCondition : 1.0f; + float alpha = fadeBrokenSprite ? 1.0f - healthRatio : 1.0f; spriteBatch.Draw(brokenSprite.Texture, pos, getSourceRect(brokenSprite, openState, IsHorizontal), color * alpha, 0.0f, brokenSprite.Origin, scale * item.Scale, item.SpriteEffects, diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/ItemComponent.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/ItemComponent.cs index 77e267d14..345411caa 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/ItemComponent.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/ItemComponent.cs @@ -580,7 +580,7 @@ namespace Barotrauma.Items.Components GameMain.Instance.ResolutionChanged += OnResolutionChangedPrivate; } - protected void TryCreateDragHandle() + protected virtual void TryCreateDragHandle() { if (GuiFrame != null && GuiFrameSource.GetAttributeBool("draggable", true)) { @@ -593,6 +593,7 @@ namespace Barotrauma.Items.Components int iconHeight = GUIStyle.ItemFrameMargin.Y / 4; var dragIcon = new GUIImage(new RectTransform(new Point(GuiFrame.Rect.Width, iconHeight), handle.RectTransform, Anchor.TopCenter) { AbsoluteOffset = new Point(0, iconHeight / 2) }, style: "GUIDragIndicatorHorizontal"); + dragIcon.RectTransform.MinSize = new Point(0, iconHeight); handle.ValidatePosition = (RectTransform rectT) => { @@ -622,7 +623,7 @@ namespace Barotrauma.Items.Components }; int buttonHeight = (int)(GUIStyle.ItemFrameMargin.Y * 0.4f); - new GUIButton(new RectTransform(new Point(buttonHeight), handle.RectTransform, Anchor.TopLeft) { AbsoluteOffset = new Point(buttonHeight / 4) }, + new GUIButton(new RectTransform(new Point(buttonHeight), handle.RectTransform, Anchor.TopLeft) { AbsoluteOffset = new Point(buttonHeight / 4), MinSize = new Point(buttonHeight) }, style: "GUIButtonSettings") { OnClicked = (btn, userdata) => diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/ItemContainer.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/ItemContainer.cs index a759f9ac7..d43d947fd 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/ItemContainer.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/ItemContainer.cs @@ -324,6 +324,8 @@ namespace Barotrauma.Items.Components int i = 0; foreach (Item containedItem in Inventory.AllItems) { + if (containedItem?.Sprite == null) { continue; } + if (AutoInteractWithContained) { containedItem.IsHighlighted = item.IsHighlighted; @@ -344,7 +346,7 @@ namespace Barotrauma.Items.Components containedItem.Sprite.Draw( spriteBatch, new Vector2(currentItemPos.X, -currentItemPos.Y), - isWiringMode ? containedItem.GetSpriteColor() * 0.15f : containedItem.GetSpriteColor(), + isWiringMode ? containedItem.GetSpriteColor(withHighlight: true) * 0.15f : containedItem.GetSpriteColor(withHighlight: true), origin, -(containedItem.body == null ? 0.0f : containedItem.body.DrawRotation ), containedItem.Scale, diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Deconstructor.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Deconstructor.cs index 5a31e20c3..dd3b30b66 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Deconstructor.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Deconstructor.cs @@ -96,6 +96,7 @@ namespace Barotrauma.Items.Components var buttonContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.4f, 0.8f), inputArea.RectTransform), childAnchor: Anchor.CenterLeft); activateButton = new GUIButton(new RectTransform(new Vector2(0.95f, 0.8f), buttonContainer.RectTransform), TextManager.Get("DeconstructorDeconstruct"), style: "DeviceButton") { + UserData = UIHighlightAction.ElementId.DeconstructButton, TextBlock = { AutoScaleHorizontal = true }, OnClicked = OnActivateButtonClicked }; @@ -432,17 +433,22 @@ namespace Barotrauma.Items.Components private bool OnActivateButtonClicked(GUIButton button, object obj) { - var disallowedItem = inputContainer.Inventory.FindItem(i => !i.AllowDeconstruct, recursive: false); - if (disallowedItem != null && !DeconstructItemsSimultaneously) + if (!IsActive) { - int index = inputContainer.Inventory.FindIndex(disallowedItem); - if (index >= 0 && index < inputContainer.Inventory.visualSlots.Length) + //don't allow turning on if there's non-deconstructable items in the queue + var disallowedItem = inputContainer.Inventory.FindItem(i => !i.AllowDeconstruct, recursive: false); + if (disallowedItem != null && !DeconstructItemsSimultaneously) { - var slot = inputContainer.Inventory.visualSlots[index]; - slot?.ShowBorderHighlight(GUIStyle.Red, 0.1f, 0.9f); + int index = inputContainer.Inventory.FindIndex(disallowedItem); + if (index >= 0 && index < inputContainer.Inventory.visualSlots.Length) + { + var slot = inputContainer.Inventory.visualSlots[index]; + slot?.ShowBorderHighlight(GUIStyle.Red, 0.1f, 0.9f); + } + return true; } - return true; } + if (GameMain.Client != null) { pendingState = !IsActive; diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Fabricator.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Fabricator.cs index 0f81a432a..16e766617 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Fabricator.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Fabricator.cs @@ -32,6 +32,8 @@ namespace Barotrauma.Items.Components } private FabricationRecipe selectedItem; + public Identifier SelectedItemIdentifier => SelectedItem?.TargetItem.Identifier ?? Identifier.Empty; + private GUIComponent inSufficientPowerWarning; private FabricationRecipe pendingFabricatedItem; diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/MiniMap.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/MiniMap.cs index fce57ab20..3b25c87b0 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/MiniMap.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/MiniMap.cs @@ -1013,12 +1013,14 @@ namespace Barotrauma.Items.Components } else if (hullData.LinkedHulls.Any()) { - hullData.HullWaterAmount = 0.0f; + float waterVolume = 0.0f; + float totalVolume = 0.0f; foreach (Hull linkedHull in hullData.LinkedHulls) { - hullData.HullWaterAmount += WaterDetector.GetWaterPercentage(linkedHull); + waterVolume += linkedHull.WaterVolume; + totalVolume += linkedHull.Volume; } - hullData.HullWaterAmount /= hullData.LinkedHulls.Count; + hullData.HullWaterAmount = MathHelper.Clamp((int)Math.Ceiling(waterVolume / totalVolume * 100), 0, 100); } else { diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Pump.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Pump.cs index 4ca36908c..d3076f105 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Pump.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Pump.cs @@ -1,10 +1,8 @@ using Barotrauma.Networking; using Barotrauma.Particles; using Microsoft.Xna.Framework; -using Microsoft.Xna.Framework.Graphics; using System; using System.Collections.Generic; -using System.Xml.Linq; namespace Barotrauma.Items.Components { @@ -58,6 +56,7 @@ namespace Barotrauma.Items.Components RelativeOffset = new Vector2(0, 0.1f) }, style: "PowerButton") { + UserData = UIHighlightAction.ElementId.PowerButton, OnClicked = (button, data) => { TargetLevel = null; @@ -114,6 +113,7 @@ namespace Barotrauma.Items.Components return true; } }; + pumpSpeedSlider.Frame.UserData = UIHighlightAction.ElementId.PumpSpeedSlider; var textsArea = new GUIFrame(new RectTransform(new Vector2(1, 0.25f), sliderArea.RectTransform, Anchor.BottomCenter), style: null); var outLabel = new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), textsArea.RectTransform, Anchor.CenterLeft), TextManager.Get("PumpOut"), textColor: GUIStyle.TextColorNormal, textAlignment: Alignment.CenterLeft, wrap: false, font: GUIStyle.SubHeadingFont); diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Reactor.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Reactor.cs index 30a3a35ba..b229b2142 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Reactor.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Reactor.cs @@ -234,6 +234,7 @@ namespace Barotrauma.Items.Components return false; } }; + FissionRateScrollBar.Frame.UserData = UIHighlightAction.ElementId.FissionRateSlider; TurbineOutputScrollBar = new GUIScrollBar(new RectTransform(sliderSize, rightArea.RectTransform, Anchor.TopCenter) { @@ -252,6 +253,7 @@ namespace Barotrauma.Items.Components return false; } }; + TurbineOutputScrollBar.Frame.UserData = UIHighlightAction.ElementId.TurbineOutputSlider; var buttonArea = new GUILayoutGroup(new RectTransform(new Vector2(1, 0.2f), columnLeft.RectTransform)) { @@ -302,9 +304,10 @@ namespace Barotrauma.Items.Components new GUIFrame(new RectTransform(new Vector2(0.01f, 1.0f), topRightArea.RectTransform), style: "VerticalLine"); - AutoTempSwitch = new GUIButton(new RectTransform(new Vector2(0.15f, 0.9f), topRightArea.RectTransform), + AutoTempSwitch = new GUIButton(new RectTransform(new Vector2(0.15f, 0.9f), topRightArea.RectTransform), style: "SwitchVertical") { + UserData = UIHighlightAction.ElementId.AutoTempSwitch, Enabled = false, Selected = AutoTemp, ClickSound = GUISoundType.UISwitch, @@ -347,6 +350,7 @@ namespace Barotrauma.Items.Components RelativeOffset = new Vector2(0, 0.1f) }, style: "PowerButton") { + UserData = UIHighlightAction.ElementId.PowerButton, OnClicked = (button, data) => { PowerOn = !PowerOn; diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Sonar.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Sonar.cs index dbac05552..188c75cf9 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Sonar.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Sonar.cs @@ -216,6 +216,7 @@ namespace Barotrauma.Items.Components var sonarModeArea = new GUIFrame(new RectTransform(new Vector2(1, 0.4f + extraHeight), paddedControlContainer.RectTransform, Anchor.TopCenter), style: null); SonarModeSwitch = new GUIButton(new RectTransform(new Vector2(0.2f, 1), sonarModeArea.RectTransform), string.Empty, style: "SwitchVertical") { + UserData = UIHighlightAction.ElementId.SonarModeSwitch, Selected = false, Enabled = true, ClickSound = GUISoundType.UISwitch, @@ -238,6 +239,7 @@ namespace Barotrauma.Items.Components passiveTickBox = new GUITickBox(new RectTransform(new Vector2(1, 0.45f), sonarModeRightSide.RectTransform, Anchor.TopLeft), TextManager.Get("SonarPassive"), font: GUIStyle.SubHeadingFont, style: "IndicatorLightRedSmall") { + UserData = UIHighlightAction.ElementId.PassiveSonarIndicator, ToolTip = TextManager.Get("SonarTipPassive"), Selected = true, Enabled = false @@ -245,6 +247,7 @@ namespace Barotrauma.Items.Components activeTickBox = new GUITickBox(new RectTransform(new Vector2(1, 0.45f), sonarModeRightSide.RectTransform, Anchor.BottomLeft), TextManager.Get("SonarActive"), font: GUIStyle.SubHeadingFont, style: "IndicatorLightRedSmall") { + UserData = UIHighlightAction.ElementId.ActiveSonarIndicator, ToolTip = TextManager.Get("SonarTipActive"), Selected = false, Enabled = false @@ -279,9 +282,14 @@ namespace Barotrauma.Items.Components }; new GUIFrame(new RectTransform(new Vector2(0.8f, 0.01f), paddedControlContainer.RectTransform, Anchor.Center), style: "HorizontalLine") - { UserData = "horizontalline" }; + { + UserData = "horizontalline" + }; - var directionalModeFrame = new GUIFrame(new RectTransform(new Vector2(1, 0.45f), lowerAreaFrame.RectTransform, Anchor.BottomCenter), style: null); + var directionalModeFrame = new GUIFrame(new RectTransform(new Vector2(1, 0.45f), lowerAreaFrame.RectTransform, Anchor.BottomCenter), style: null) + { + UserData = UIHighlightAction.ElementId.DirectionalSonarFrame + }; directionalModeSwitch = new GUIButton(new RectTransform(new Vector2(0.3f, 0.8f), directionalModeFrame.RectTransform, Anchor.CenterLeft), string.Empty, style: "SwitchHorizontal") { OnClicked = (button, data) => @@ -334,6 +342,18 @@ namespace Barotrauma.Items.Components sonarView.RectTransform.RelativeOffset = new Vector2(0.13f * GUI.RelativeHorizontalAspectRatio, 0); sonarView.RectTransform.SetPosition(Anchor.BottomRight); } + var handle = GuiFrame.GetChild(); + if (handle != null) + { + handle.RectTransform.Parent = controlContainer.RectTransform; + handle.RectTransform.Resize(Vector2.One); + handle.RectTransform.SetAsFirstChild(); + } + } + + protected override void TryCreateDragHandle() + { + base.TryCreateDragHandle(); } private void SetPingDirection(Vector2 direction) diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Steering.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Steering.cs index d4d043455..7f06e5dbf 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Steering.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Steering.cs @@ -1,13 +1,11 @@ -using Barotrauma.Networking; +using Barotrauma.Extensions; +using Barotrauma.Networking; using FarseerPhysics; using Microsoft.Xna.Framework; -using Microsoft.Xna.Framework.Input; using Microsoft.Xna.Framework.Graphics; using System; -using System.Linq; using System.Collections.Generic; -using System.Xml.Linq; -using Barotrauma.Extensions; +using System.Linq; namespace Barotrauma.Items.Components { @@ -141,6 +139,7 @@ namespace Barotrauma.Items.Components var steeringModeArea = new GUIFrame(new RectTransform(new Vector2(1, 0.4f), paddedControlContainer.RectTransform, Anchor.TopLeft), style: null); steeringModeSwitch = new GUIButton(new RectTransform(new Vector2(0.2f, 1), steeringModeArea.RectTransform), string.Empty, style: "SwitchVertical") { + UserData = UIHighlightAction.ElementId.SteeringModeSwitch, Selected = autoPilot, Enabled = true, ClickSound = GUISoundType.UISwitch, @@ -182,6 +181,7 @@ namespace Barotrauma.Items.Components maintainPosTickBox = new GUITickBox(new RectTransform(new Vector2(1, 0.333f), paddedAutoPilotControls.RectTransform, Anchor.TopCenter), TextManager.Get("SteeringMaintainPos"), font: GUIStyle.SmallFont, style: "GUIRadioButton") { + UserData = UIHighlightAction.ElementId.MaintainPosTickBox, Enabled = autoPilot, Selected = maintainPos, OnSelected = tickBox => diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Power/PowerContainer.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Power/PowerContainer.cs index cd6883441..72070c051 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Power/PowerContainer.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Power/PowerContainer.cs @@ -83,7 +83,8 @@ namespace Barotrauma.Items.Components } }; rechargeSpeedSlider.Bar.RectTransform.MaxSize = new Point(rechargeSpeedSlider.Bar.Rect.Height); - + rechargeSpeedSlider.Frame.UserData = UIHighlightAction.ElementId.RechargeSpeedSlider; + // lower area -------------------------- var chargeTextContainer = new GUIFrame(new RectTransform(new Vector2(1, 0.4f), lowerArea.RectTransform), style: null); diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Repairable.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Repairable.cs index a6c9f47da..afaeb2dca 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Repairable.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Repairable.cs @@ -165,6 +165,7 @@ namespace Barotrauma.Items.Components repairingText = TextManager.Get("Repairing"); RepairButton = new GUIButton(new RectTransform(new Vector2(0.4f, 1.0f), progressBarHolder.RectTransform, Anchor.TopCenter), repairButtonText) { + UserData = UIHighlightAction.ElementId.RepairButton, OnClicked = (btn, obj) => { requestStartFixAction = FixActions.Repair; diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Signal/CustomInterface.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Signal/CustomInterface.cs index cdb1d4ac9..17b151087 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Signal/CustomInterface.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Signal/CustomInterface.cs @@ -135,7 +135,7 @@ namespace Barotrauma.Items.Components } else { - DebugConsole.ShowError($"Error creating a CustomInterface component: unexpected NumberType \"{(ciElement.NumberType.HasValue ? ciElement.NumberType.Value.ToString() : "none")}\""); + DebugConsole.LogError($"Error creating a CustomInterface component: unexpected NumberType \"{(ciElement.NumberType.HasValue ? ciElement.NumberType.Value.ToString() : "none")}\""); } if (numberInput != null) { diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Item.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Item.cs index 8950850cc..0c35c29eb 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Item.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Item.cs @@ -118,7 +118,7 @@ namespace Barotrauma return GetDrawDepth(SpriteDepth + DrawDepthOffset, Sprite); } - public Color GetSpriteColor() + public Color GetSpriteColor(bool withHighlight = false) { Color color = spriteColor; if (Prefab.UseContainedSpriteColor && ownInventory != null) @@ -129,6 +129,17 @@ namespace Barotrauma break; } } + if (withHighlight) + { + if (IsHighlighted && !GUI.DisableItemHighlights && Screen.Selected != GameMain.GameScreen) + { + color = GUIStyle.Orange * Math.Max(GetSpriteColor().A / (float)byte.MaxValue, 0.1f); + } + else if (IsHighlighted && HighlightColor.HasValue) + { + color = Color.Lerp(color, HighlightColor.Value, (MathF.Sin((float)Timing.TotalTime * 3.0f) + 1.0f) / 2.0f); + } + } return color; } @@ -281,9 +292,7 @@ namespace Barotrauma else if (!ShowItems) { return; } } - Color color = IsIncludedInSelection && editing ? GUIStyle.Blue : IsHighlighted && !GUI.DisableItemHighlights && Screen.Selected != GameMain.GameScreen ? GUIStyle.Orange * Math.Max(GetSpriteColor().A / (float) byte.MaxValue, 0.1f) : GetSpriteColor(); - - //if (IsSelected && editing) color = Color.Lerp(color, Color.Gold, 0.5f); + Color color = IsIncludedInSelection && editing ? GUIStyle.Blue : GetSpriteColor(withHighlight: true); bool isWiringMode = editing && SubEditorScreen.TransparentWiringMode && SubEditorScreen.IsWiringMode() && !isWire && parentInventory == null; bool renderTransparent = isWiringMode && GetComponent() == null; diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/ItemPrefab.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/ItemPrefab.cs index bab357ba1..8c6aed81b 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/ItemPrefab.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/ItemPrefab.cs @@ -229,6 +229,7 @@ namespace Barotrauma Submarine = Submarine.MainSub }; item.SetTransform(ConvertUnits.ToSimUnits(Submarine.MainSub == null ? item.Position : item.Position - Submarine.MainSub.Position), 0.0f); + item.GetComponent()?.RefreshLinkedGap(); item.FindHull(); item.Submarine = Submarine.MainSub; diff --git a/Barotrauma/BarotraumaClient/ClientSource/Map/Gap.cs b/Barotrauma/BarotraumaClient/ClientSource/Map/Gap.cs index 8da238592..77189d2d9 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Map/Gap.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Map/Gap.cs @@ -264,10 +264,6 @@ namespace Barotrauma { Vector2 velocity = flowForce; if (!IsHorizontal) - { - velocity.X = Rand.Range(-100.0f, 100.0f) * open; - } - else { velocity.X *= Rand.Range(1.0f, 3.0f); } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/BanList.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/BanList.cs index 8d0f64b01..94e3da6c4 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Networking/BanList.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/BanList.cs @@ -2,7 +2,6 @@ using Microsoft.Xna.Framework; using System; using System.Collections.Generic; -using System.Linq; namespace Barotrauma.Networking { @@ -88,12 +87,13 @@ namespace Barotrauma.Networking TextManager.Get("BanPermanent") : TextManager.GetWithVariable("BanExpires", "[time]", bannedPlayer.ExpirationTime.Value.ToString()), font: GUIStyle.SmallFont); + LocalizedString reason = TextManager.GetServerMessage(bannedPlayer.Reason).Fallback(bannedPlayer.Reason); var reasonText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedPlayerFrame.RectTransform), TextManager.Get("BanReason") + " " + - (string.IsNullOrEmpty(bannedPlayer.Reason) ? TextManager.Get("None") : bannedPlayer.Reason), + (string.IsNullOrEmpty(bannedPlayer.Reason) ? TextManager.Get("None") : reason), font: GUIStyle.SmallFont, wrap: true) { - ToolTip = bannedPlayer.Reason + ToolTip = reason }; paddedPlayerFrame.Recalculate(); diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/Client.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/Client.cs index 3c72ee33a..21b119c40 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Networking/Client.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/Client.cs @@ -31,12 +31,17 @@ namespace Barotrauma.Networking public bool IsOwner; - public bool AllowKicking; public bool IsDownloading; public float Karma; + public bool AllowKicking => + !IsOwner && + !HasPermission(ClientPermissions.Ban) && + !HasPermission(ClientPermissions.Kick) && + !HasPermission(ClientPermissions.Unban); + public void UpdateSoundPosition() { if (VoipSound == null) { return; } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/GameClient.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/GameClient.cs index c78321411..76040fcd3 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Networking/GameClient.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/GameClient.cs @@ -362,8 +362,7 @@ namespace Barotrauma.Networking // When this is set to true, we are approved and ready to go canStart = false; - DateTime timeOut = DateTime.Now + new TimeSpan(0, 0, 40); - DateTime reqAuthTime = DateTime.Now + new TimeSpan(0, 0, 0, 0, 200); + DateTime timeOut = DateTime.Now + new TimeSpan(0, 0, 200); // Loop until we are approved LocalizedString connectingText = TextManager.Get("Connecting"); @@ -489,7 +488,10 @@ namespace Barotrauma.Networking } GameAnalyticsManager.AddErrorEventOnce("GameClient.Update:CheckServerMessagesException" + e.TargetSite.ToString(), GameAnalyticsManager.ErrorSeverity.Error, errorMsg); DebugConsole.ThrowError("Error while reading a message from server.", e); - new GUIMessageBox(TextManager.Get("Error"), TextManager.GetWithVariables("MessageReadError", ("[message]", e.Message), ("[targetsite]", e.TargetSite.ToString()))); + new GUIMessageBox(TextManager.Get("Error"), TextManager.GetWithVariables("MessageReadError", ("[message]", e.Message), ("[targetsite]", e.TargetSite.ToString()))) + { + DisplayInLoadingScreens = true + }; Quit(); GameMain.ServerListScreen.Select(); return; @@ -965,10 +967,10 @@ namespace Barotrauma.Networking } AttemptReconnect(disconnectPacket); } - else if (disconnectPacket.ShouldShowMessage) + else { ReturnToPreviousMenu(null, null); - var msgBox = new GUIMessageBox(TextManager.Get(wasConnected ? "ConnectionLost" : "CouldNotConnectToServer"), disconnectPacket.PopupMessage) + new GUIMessageBox(TextManager.Get(wasConnected ? "ConnectionLost" : "CouldNotConnectToServer"), disconnectPacket.PopupMessage) { DisplayInLoadingScreens = true }; @@ -1033,6 +1035,7 @@ namespace Barotrauma.Networking if (ClientPeer != null) { //restore the previous list of content packages so we can reconnect immediately without having to recheck that the packages match + ClientPeer.ContentPackageOrderReceived = true; ClientPeer.ServerContentPackages = prevContentPackages; } } @@ -1721,6 +1724,7 @@ namespace Barotrauma.Networking string subName = inc.ReadString(); string subHash = inc.ReadString(); byte subClass = inc.ReadByte(); + bool isShuttle = inc.ReadBoolean(); bool requiredContentPackagesInstalled = inc.ReadBoolean(); var matchingSub = SubmarineInfo.SavedSubmarines.FirstOrDefault(s => s.Name == subName && s.MD5Hash.StringRepresentation == subHash); @@ -1730,6 +1734,7 @@ namespace Barotrauma.Networking { SubmarineClass = (SubmarineClass)subClass }; + if (isShuttle) { matchingSub.AddTag(SubmarineTag.Shuttle); } } matchingSub.RequiredContentPackagesInstalled = requiredContentPackagesInstalled; ServerSubmarines.Add(matchingSub); @@ -1780,7 +1785,6 @@ namespace Barotrauma.Networking AccountInfo = tc.AccountInfo, Muted = tc.Muted, InGame = tc.InGame, - AllowKicking = tc.AllowKicking, IsOwner = tc.IsOwner }; otherClients.Add(existingClient); @@ -1795,7 +1799,6 @@ namespace Barotrauma.Networking existingClient.Muted = tc.Muted; existingClient.InGame = tc.InGame; existingClient.IsOwner = tc.IsOwner; - existingClient.AllowKicking = tc.AllowKicking; existingClient.IsDownloading = tc.IsDownloading; GameMain.NetLobbyScreen.SetPlayerNameAndJobPreference(existingClient); if (Screen.Selected != GameMain.NetLobbyScreen && tc.CharacterId > 0) @@ -2404,7 +2407,7 @@ namespace Barotrauma.Networking var subElement = subListChildren.FirstOrDefault(c => ((SubmarineInfo)c.UserData).Name == newSub.Name && ((SubmarineInfo)c.UserData).MD5Hash.StringRepresentation == newSub.MD5Hash.StringRepresentation); - if (subElement == null) continue; + if (subElement == null) { continue; } Color newSubTextColor = new Color(subElement.GetChild().TextColor, 1.0f); subElement.GetChild().TextColor = newSubTextColor; @@ -2429,7 +2432,7 @@ namespace Barotrauma.Networking if (GameMain.NetLobbyScreen.FailedSelectedShuttle.HasValue && GameMain.NetLobbyScreen.FailedSelectedShuttle.Value.Name == newSub.Name && - GameMain.NetLobbyScreen.FailedSelectedShuttle.Value.Name == newSub.MD5Hash.StringRepresentation) + GameMain.NetLobbyScreen.FailedSelectedShuttle.Value.Hash == newSub.MD5Hash.StringRepresentation) { GameMain.NetLobbyScreen.TrySelectSub(newSub.Name, newSub.MD5Hash.StringRepresentation, GameMain.NetLobbyScreen.ShuttleList.ListBox); } @@ -2583,6 +2586,7 @@ namespace Barotrauma.Networking } } ChildServerRelay.ShutDown(); + GUIMessageBox.MessageBoxes.RemoveAll(c => c?.UserData is RoundSummary); characterInfo?.Remove(); diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/Primitives/Peers/ClientPeer.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/Primitives/Peers/ClientPeer.cs index e6b45ac85..b2cf3a633 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Networking/Primitives/Peers/ClientPeer.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/Primitives/Peers/ClientPeer.cs @@ -49,7 +49,7 @@ namespace Barotrauma.Networking protected abstract void SendMsgInternal(PeerPacketHeaders headers, INetSerializableStruct? body); protected ConnectionInitialization initializationStep; - public bool ContentPackageOrderReceived { get; protected set; } + public bool ContentPackageOrderReceived { get; set; } protected int passwordSalt; protected Steamworks.AuthTicket? steamAuthTicket; private GUIMessageBox? passwordMsgBox; diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/Primitives/Peers/SteamP2PClientPeer.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/Primitives/Peers/SteamP2PClientPeer.cs index e817616b2..35e579d2a 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Networking/Primitives/Peers/SteamP2PClientPeer.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/Primitives/Peers/SteamP2PClientPeer.cs @@ -36,6 +36,8 @@ namespace Barotrauma.Networking public override void Start() { + if (isActive) { return; } + ContentPackageOrderReceived = false; steamAuthTicket = SteamManager.GetAuthSessionTicket(); @@ -189,6 +191,7 @@ namespace Barotrauma.Networking if (packet is { SteamId: var steamId, Data: var data }) { OnP2PData(steamId, data, data.Length); + if (!isActive) { return; } receivedBytes += data.Length; } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/Primitives/Peers/SteamP2POwnerPeer.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/Primitives/Peers/SteamP2POwnerPeer.cs index 440e3126e..48fe24b0e 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Networking/Primitives/Peers/SteamP2POwnerPeer.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/Primitives/Peers/SteamP2POwnerPeer.cs @@ -391,7 +391,7 @@ namespace Barotrauma.Networking for (int i = remotePeers.Count - 1; i >= 0; i--) { - DisconnectPeer(remotePeers[i], peerDisconnectPacket); + DisconnectPeer(remotePeers[i], PeerDisconnectPacket.WithReason(DisconnectReason.ServerShutdown)); } Thread.Sleep(100); diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerList/PingUtils.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerList/PingUtils.cs index 4f099bf4e..fc23c4df9 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerList/PingUtils.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerList/PingUtils.cs @@ -37,6 +37,7 @@ namespace Barotrauma.Networking switch (serverInfo.Endpoint) { case LidgrenEndpoint { NetEndpoint: { Address: var address } }: + GetIPAddressPing(serverInfo, address, onPingDiscovered); break; case SteamP2PEndpoint steamP2PEndpoint: @@ -132,24 +133,30 @@ namespace Barotrauma.Networking private static void GetIPAddressPing(ServerInfo serverInfo, IPAddress address, Action onPingDiscovered) { - lock (activePings) + if (IPAddress.IsLoopback(address)) { - if (activePings.ContainsKey(address)) { return; } - activePings.Add(address, activePings.Any() ? activePings.Values.Max() + 1 : 0); + serverInfo.Ping = Option.Some(0); + onPingDiscovered(serverInfo); } - - serverInfo.Ping = Option.None(); - - TaskPool.Add($"PingServerAsync ({address})", PingServerAsync(address, 1000), - rtt => + else + { + lock (activePings) { - if (!rtt.TryGetResult(out serverInfo.Ping)) { serverInfo.Ping = Option.None(); } - onPingDiscovered(serverInfo); - lock (activePings) + if (activePings.ContainsKey(address)) { return; } + activePings.Add(address, activePings.Any() ? activePings.Values.Max() + 1 : 0); + } + serverInfo.Ping = Option.None(); + TaskPool.Add($"PingServerAsync ({address})", PingServerAsync(address, 1000), + rtt => { - activePings.Remove(address); - } - }); + if (!rtt.TryGetResult(out serverInfo.Ping)) { serverInfo.Ping = Option.None(); } + onPingDiscovered(serverInfo); + lock (activePings) + { + activePings.Remove(address); + } + }); + } } private static async Task> PingServerAsync(IPAddress ipAddress, int timeOut) diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerList/ServerInfo.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerList/ServerInfo.cs index 8b1e9e2d3..adbf863df 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerList/ServerInfo.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerList/ServerInfo.cs @@ -70,7 +70,7 @@ namespace Barotrauma.Networking [Serialize(PlayStyle.Casual, IsPropertySaveable.Yes)] public PlayStyle PlayStyle { get; set; } - public Version GameVersion { get; set; } = new Version(0,0,0,0); + public Version GameVersion { get; set; } = new Version(0, 0, 0, 0); public Option Ping = Option.None(); @@ -200,7 +200,7 @@ namespace Barotrauma.Networking new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), frame.RectTransform), TextManager.AddPunctuation(':', TextManager.Get("ServerListVersion"), - GameVersion.ToString())) + GameVersion == new Version(0, 0, 0, 0) ? TextManager.Get("Unknown") : GameVersion.ToString())) { CanBeFocused = false }; @@ -397,10 +397,10 @@ namespace Barotrauma.Networking public void UpdateInfo(Func valueGetter) { ServerMessage = valueGetter("message") ?? ""; - GameVersion = Version.TryParse(valueGetter("version"), out var version) - ? version - : GameMain.Version; - + if (Version.TryParse(valueGetter("version"), out var version)) + { + GameVersion = version; + } if (int.TryParse(valueGetter("playercount"), out int playerCount)) { PlayerCount = playerCount; } if (int.TryParse(valueGetter("maxplayernum"), out int maxPlayers)) { MaxPlayers = maxPlayers; } if (Enum.TryParse(valueGetter("modeselectionmode"), out SelectionMode modeSelectionMode)) { ModeSelectionMode = modeSelectionMode; } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Screens/CampaignUI.cs b/Barotrauma/BarotraumaClient/ClientSource/Screens/CampaignUI.cs index 5fc6deb6c..a405d730e 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Screens/CampaignUI.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Screens/CampaignUI.cs @@ -346,7 +346,7 @@ namespace Barotrauma }; var missionName = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextContent.RectTransform), mission?.Name ?? TextManager.Get("NoMission"), font: GUIStyle.SubHeadingFont, wrap: true); - // missionName.RectTransform.MinSize = new Point(0, (int)(missionName.Rect.Height * 1.5f)); + missionName.RectTransform.MinSize = new Point(0, GUI.IntScale(15)); if (mission != null) { var tickBox = new GUITickBox(new RectTransform(Vector2.One * 0.9f, missionName.RectTransform, anchor: Anchor.CenterLeft, scaleBasis: ScaleBasis.Smallest) { AbsoluteOffset = new Point((int)missionName.Padding.X, 0) }, label: string.Empty) diff --git a/Barotrauma/BarotraumaClient/ClientSource/Screens/MainMenuScreen.cs b/Barotrauma/BarotraumaClient/ClientSource/Screens/MainMenuScreen.cs index 01f4b8506..420328bc7 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Screens/MainMenuScreen.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Screens/MainMenuScreen.cs @@ -67,7 +67,9 @@ namespace Barotrauma public static readonly Queue WorkshopItemsToUpdate = new Queue(); - private readonly GUIListBox tutorialList; + private GUIImage tutorialBanner; + private GUITextBlock tutorialHeader, tutorialDescription; + private GUIListBox tutorialList; #region Creation public MainMenuScreen(GameMain game) @@ -429,20 +431,7 @@ namespace Barotrauma //---------------------------------------------------------------------- menuTabs[Tab.Tutorials] = new GUIFrame(new RectTransform(relativeSize, GUI.Canvas, anchor, pivot, minSize, maxSize) { RelativeOffset = relativeSpacing }); - - //PLACEHOLDER - tutorialList = new GUIListBox( - new RectTransform(new Vector2(0.95f, 0.85f), menuTabs[Tab.Tutorials].RectTransform, Anchor.TopCenter) { RelativeOffset = new Vector2(0.0f, 0.1f) }) - { - PlaySoundOnSelect = true, - }; - tutorialList.OnSelected += (component, obj) => - { - (obj as Tutorial)?.Start(); - return true; - }; - - CreateTutorialButtons(); + CreateTutorialTab(); this.game = game; @@ -459,24 +448,68 @@ namespace Barotrauma creditsPlayer = new CreditsPlayer(new RectTransform(Vector2.One, creditsContainer.RectTransform), "Content/Texts/Credits.xml"); } - private void CreateTutorialButtons() + private void CreateTutorialTab() { + var tutorialInnerFrame = new GUIFrame(new RectTransform(new Vector2(0.9f, 0.9f), menuTabs[Tab.Tutorials].RectTransform, Anchor.Center), style: "InnerFrame"); + var tutorialContent = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.95f), tutorialInnerFrame.RectTransform, Anchor.Center), isHorizontal: true) { RelativeSpacing = 0.02f, Stretch = true }; + + tutorialList = new GUIListBox(new RectTransform(new Vector2(0.4f, 1.0f), tutorialContent.RectTransform)) + { + PlaySoundOnSelect = true, + OnSelected = (component, obj) => + { + SelectTutorial(obj as Tutorial); + return true; + } + }; + var tutorialPreview = new GUILayoutGroup(new RectTransform(new Vector2(0.6f, 1.0f), tutorialContent.RectTransform)) { RelativeSpacing = 0.05f, Stretch = true }; + var imageContainer = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.6f), tutorialPreview.RectTransform), style: "InnerFrame"); + tutorialBanner = new GUIImage(new RectTransform(Vector2.One, imageContainer.RectTransform), style: null, scaleToFit: true); + + var infoContainer = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.4f), tutorialPreview.RectTransform), style: "GUIFrameListBox"); + var infoContent = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.9f), infoContainer.RectTransform, Anchor.Center), childAnchor: Anchor.TopCenter); + + tutorialHeader = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.75f), infoContent.RectTransform), string.Empty, font: GUIStyle.SubHeadingFont, textAlignment: Alignment.Center); + + var startButton = new GUIButton(new RectTransform(new Vector2(0.5f, 0.0f), infoContent.RectTransform, Anchor.BottomRight), text: TextManager.Get("startgamebutton")) + { + IgnoreLayoutGroups = true, + OnClicked = (component, obj) => + { + (tutorialList.SelectedData as Tutorial)?.Start(); + return true; + } + }; + + Tutorial firstTutorial = null; foreach (var tutorialPrefab in TutorialPrefab.Prefabs.OrderBy(p => p.Order)) { var tutorial = new Tutorial(tutorialPrefab); - var tutorialText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.15f), tutorialList.Content.RectTransform), tutorial.DisplayName, textAlignment: Alignment.Center, font: GUIStyle.LargeFont) + firstTutorial ??= tutorial; + var tutorialText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), tutorialList.Content.RectTransform), tutorial.DisplayName) { - TextColor = GUIStyle.Green, + Padding = new Vector4(30.0f * GUI.Scale, 0,0,0), UserData = tutorial }; + tutorialText.RectTransform.MinSize = new Point(0, (int)(tutorialText.TextSize.Y * 2)); } + GUITextBlock.AutoScaleAndNormalize(tutorialList.Content.Children.Select(c => c as GUITextBlock)); + tutorialList.Select(firstTutorial); + } + + private void SelectTutorial(Tutorial tutorial) + { + tutorialHeader.Text = tutorial.DisplayName; + tutorial.TutorialPrefab.Banner?.EnsureLazyLoaded(); + tutorialBanner.Sprite = tutorial.TutorialPrefab.Banner; + tutorialBanner.Color = tutorial.TutorialPrefab.Banner == null ? Color.Black : Color.White; } public static void UpdateInstanceTutorialButtons() { if (GameMain.MainMenuScreen is not MainMenuScreen menuScreen) { return; } menuScreen.tutorialList.ClearChildren(); - menuScreen.CreateTutorialButtons(); + menuScreen.CreateTutorialTab(); } #endregion @@ -746,12 +779,13 @@ namespace Barotrauma private void UpdateTutorialList() { - foreach (GUITextBlock tutorialText in menuTabs[Tab.Tutorials].GetChild().Content.Children) + foreach (GUITextBlock tutorialText in tutorialList.Content.Children) { var tutorial = (Tutorial)tutorialText.UserData; - tutorialText.Text = CompletedTutorials.Instance.Contains(tutorial.Identifier) ? - TextManager.GetWithVariable("tutorialcompleted", "[tutorialname]", tutorial.DisplayName) : - tutorial.DisplayName; + if (CompletedTutorials.Instance.Contains(tutorial.Identifier) && tutorialText.GetChild() == null) + { + new GUIImage(new RectTransform(new Point((int)(tutorialText.Padding.X * 0.8f)), tutorialText.RectTransform, Anchor.CenterLeft), style: "ObjectiveIndicatorCompleted"); + } } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Screens/SubEditorScreen.cs b/Barotrauma/BarotraumaClient/ClientSource/Screens/SubEditorScreen.cs index 9bff7dac0..0952422e7 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Screens/SubEditorScreen.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Screens/SubEditorScreen.cs @@ -1862,7 +1862,7 @@ namespace Barotrauma SubmarineType.Wreck => "Content/Map/Wrecks/{0}", SubmarineType.BeaconStation => "Content/Map/BeaconStations/{0}", SubmarineType.EnemySubmarine => "Content/Map/EnemySubmarines/{0}", - SubmarineType.OutpostModule => "Content/Map/Outposts/{0}", + SubmarineType.OutpostModule => MainSub.Info.FilePath.Contains("RuinModules") ? "Content/Map/RuinModules/{0}" : "Content/Map/Outposts/{0}", _ => throw new InvalidOperationException() }, savePath); modProject.ModVersion = ""; diff --git a/Barotrauma/BarotraumaClient/ClientSource/Sounds/SoundManager.cs b/Barotrauma/BarotraumaClient/ClientSource/Sounds/SoundManager.cs index 8cfa4a8f7..835981330 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Sounds/SoundManager.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Sounds/SoundManager.cs @@ -195,13 +195,13 @@ namespace Barotrauma.Sounds GainMultipliers[index] = gain; } } - private Dictionary categoryModifiers; + + private readonly Dictionary categoryModifiers = new Dictionary(); public SoundManager() { loadedSounds = new List(); streamingThread = null; - categoryModifiers = null; sourcePools = new SoundSourcePool[2]; playingChannels[(int)SourcePoolIndex.Default] = new SoundChannel[SOURCE_COUNT]; @@ -235,7 +235,7 @@ namespace Barotrauma.Sounds CompressionDynamicRangeGain = 1.0f; } - private void SetAudioOutputDevice(string deviceName) + private static void SetAudioOutputDevice(string deviceName) { var config = GameSettings.CurrentConfig; config.Audio.AudioOutputDevice = deviceName; @@ -249,7 +249,7 @@ namespace Barotrauma.Sounds DebugConsole.NewMessage($"Attempting to open ALC device \"{deviceName}\""); alcDevice = IntPtr.Zero; - int alcError = Al.NoError; + int alcError; for (int i = 0; i < 3; i++) { alcDevice = Alc.OpenDevice(deviceName); @@ -371,8 +371,10 @@ namespace Barotrauma.Sounds throw new System.IO.FileNotFoundException($"Sound file \"{filePath}\" doesn't exist! Content package \"{(element.ContentPackage?.Name ?? "Unknown")}\"."); } - var newSound = new OggSound(this, filePath, stream, xElement: element); - newSound.BaseGain = element.GetAttributeFloat("volume", 1.0f); + var newSound = new OggSound(this, filePath, stream, xElement: element) + { + BaseGain = element.GetAttributeFloat("volume", 1.0f) + }; float range = element.GetAttributeFloat("range", 1000.0f); newSound.BaseNear = range * 0.4f; newSound.BaseFar = range; @@ -537,14 +539,16 @@ namespace Barotrauma.Sounds { if (Disabled) { return; } category = category.ToLower(); - if (categoryModifiers == null) categoryModifiers = new Dictionary(); - if (!categoryModifiers.ContainsKey(category)) + lock (categoryModifiers) { - categoryModifiers.Add(category, new CategoryModifier(index, gain, false)); - } - else - { - categoryModifiers[category].SetGainMultiplier(index, gain); + if (!categoryModifiers.ContainsKey(category)) + { + categoryModifiers.Add(category, new CategoryModifier(index, gain, false)); + } + else + { + categoryModifiers[category].SetGainMultiplier(index, gain); + } } for (int i = 0; i < playingChannels.Length; i++) @@ -562,23 +566,26 @@ namespace Barotrauma.Sounds } } - public float GetCategoryGainMultiplier(string category, int index=-1) + public float GetCategoryGainMultiplier(string category, int index = -1) { if (Disabled) { return 0.0f; } category = category.ToLower(); - if (categoryModifiers == null || !categoryModifiers.ContainsKey(category)) return 1.0f; - if (index < 0) + lock (categoryModifiers) { - float accumulatedMultipliers = 1.0f; - for (int i = 0; i < categoryModifiers[category].GainMultipliers.Length; i++) + if (categoryModifiers == null || !categoryModifiers.TryGetValue(category, out CategoryModifier categoryModifier)) { return 1.0f; } + if (index < 0) { - accumulatedMultipliers *= categoryModifiers[category].GainMultipliers[i]; + float accumulatedMultipliers = 1.0f; + for (int i = 0; i < categoryModifier.GainMultipliers.Length; i++) + { + accumulatedMultipliers *= categoryModifier.GainMultipliers[i]; + } + return accumulatedMultipliers; + } + else + { + return categoryModifier.GainMultipliers[index]; } - return accumulatedMultipliers; - } - else - { - return categoryModifiers[category].GainMultipliers[index]; } } @@ -587,15 +594,16 @@ namespace Barotrauma.Sounds if (Disabled) { return; } category = category.ToLower(); - - if (categoryModifiers == null) { categoryModifiers = new Dictionary(); } - if (!categoryModifiers.ContainsKey(category)) + lock (categoryModifiers) { - categoryModifiers.Add(category, new CategoryModifier(0, 1.0f, muffle)); - } - else - { - categoryModifiers[category].Muffle = muffle; + if (!categoryModifiers.ContainsKey(category)) + { + categoryModifiers.Add(category, new CategoryModifier(0, 1.0f, muffle)); + } + else + { + categoryModifiers[category].Muffle = muffle; + } } for (int i = 0; i < playingChannels.Length; i++) @@ -618,8 +626,11 @@ namespace Barotrauma.Sounds if (Disabled) { return false; } category = category.ToLower(); - if (categoryModifiers == null || !categoryModifiers.ContainsKey(category)) { return false; } - return categoryModifiers[category].Muffle; + lock (categoryModifiers) + { + if (categoryModifiers == null || !categoryModifiers.TryGetValue(category, out CategoryModifier categoryModifier)) { return false; } + return categoryModifier.Muffle; + } } public void Update() diff --git a/Barotrauma/BarotraumaClient/LinuxClient.csproj b/Barotrauma/BarotraumaClient/LinuxClient.csproj index 50cde2d74..88b2f6e49 100644 --- a/Barotrauma/BarotraumaClient/LinuxClient.csproj +++ b/Barotrauma/BarotraumaClient/LinuxClient.csproj @@ -6,7 +6,7 @@ Barotrauma FakeFish, Undertow Games Barotrauma - 0.19.5.0 + 0.19.8.0 Copyright © FakeFish 2018-2022 AnyCPU;x64 Barotrauma diff --git a/Barotrauma/BarotraumaClient/MacClient.csproj b/Barotrauma/BarotraumaClient/MacClient.csproj index a6511a7d3..8af641319 100644 --- a/Barotrauma/BarotraumaClient/MacClient.csproj +++ b/Barotrauma/BarotraumaClient/MacClient.csproj @@ -6,7 +6,7 @@ Barotrauma FakeFish, Undertow Games Barotrauma - 0.19.5.0 + 0.19.8.0 Copyright © FakeFish 2018-2022 AnyCPU;x64 Barotrauma diff --git a/Barotrauma/BarotraumaClient/WindowsClient.csproj b/Barotrauma/BarotraumaClient/WindowsClient.csproj index 97e542512..e0cc010d5 100644 --- a/Barotrauma/BarotraumaClient/WindowsClient.csproj +++ b/Barotrauma/BarotraumaClient/WindowsClient.csproj @@ -6,7 +6,7 @@ Barotrauma FakeFish, Undertow Games Barotrauma - 0.19.5.0 + 0.19.8.0 Copyright © FakeFish 2018-2022 AnyCPU;x64 Barotrauma diff --git a/Barotrauma/BarotraumaServer/LinuxServer.csproj b/Barotrauma/BarotraumaServer/LinuxServer.csproj index be1d93bfe..27981fc58 100644 --- a/Barotrauma/BarotraumaServer/LinuxServer.csproj +++ b/Barotrauma/BarotraumaServer/LinuxServer.csproj @@ -6,7 +6,7 @@ Barotrauma FakeFish, Undertow Games Barotrauma Dedicated Server - 0.19.5.0 + 0.19.8.0 Copyright © FakeFish 2018-2022 AnyCPU;x64 DedicatedServer diff --git a/Barotrauma/BarotraumaServer/MacServer.csproj b/Barotrauma/BarotraumaServer/MacServer.csproj index 52c412583..8403b2fcd 100644 --- a/Barotrauma/BarotraumaServer/MacServer.csproj +++ b/Barotrauma/BarotraumaServer/MacServer.csproj @@ -6,7 +6,7 @@ Barotrauma FakeFish, Undertow Games Barotrauma Dedicated Server - 0.19.5.0 + 0.19.8.0 Copyright © FakeFish 2018-2022 AnyCPU;x64 DedicatedServer diff --git a/Barotrauma/BarotraumaServer/ServerSource/Characters/CharacterNetworking.cs b/Barotrauma/BarotraumaServer/ServerSource/Characters/CharacterNetworking.cs index 953e09573..a3e74f054 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Characters/CharacterNetworking.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Characters/CharacterNetworking.cs @@ -512,13 +512,10 @@ namespace Barotrauma msg.WriteByte((byte)TeamID); break; case AddToCrewEventData addToCrewEventData: - msg.WriteByte((byte)addToCrewEventData.TeamType); // team id - ushort[] inventoryItemIDs = addToCrewEventData.InventoryItems.Select(item => item.ID).ToArray(); - msg.WriteUInt16((ushort)inventoryItemIDs.Length); - for (int i = 0; i < inventoryItemIDs.Length; i++) - { - msg.WriteUInt16(inventoryItemIDs[i]); - } + msg.WriteNetSerializableStruct(addToCrewEventData.ItemTeamChange); + break; + case RemoveFromCrewEventData removeFromCrewEventData: + msg.WriteNetSerializableStruct(removeFromCrewEventData.ItemTeamChange); break; case UpdateExperienceEventData _: msg.WriteInt32(Info.ExperiencePoints); diff --git a/Barotrauma/BarotraumaServer/ServerSource/Networking/GameServer.cs b/Barotrauma/BarotraumaServer/ServerSource/Networking/GameServer.cs index 116010200..370627ddb 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Networking/GameServer.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Networking/GameServer.cs @@ -1613,6 +1613,7 @@ namespace Barotrauma.Networking outmsg.WriteString(sub.Name); outmsg.WriteString(sub.MD5Hash.ToString()); outmsg.WriteByte((byte)sub.SubmarineClass); + outmsg.WriteBoolean(sub.HasTag(SubmarineTag.Shuttle)); outmsg.WriteBoolean(sub.RequiredContentPackagesInstalled); } @@ -1836,10 +1837,6 @@ namespace Barotrauma.Networking InGame = client.InGame, HasPermissions = client.Permissions != ClientPermissions.None, IsOwner = client.Connection == OwnerConnection, - AllowKicking = client.Connection != OwnerConnection && - !client.HasPermission(ClientPermissions.Ban) && - !client.HasPermission(ClientPermissions.Kick) && - !client.HasPermission(ClientPermissions.Unban), IsDownloading = FileSender.ActiveTransfers.Any(t => t.Connection == client.Connection) }; @@ -3383,7 +3380,7 @@ namespace Barotrauma.Networking private IEnumerable SendClientPermissionsAfterClientListSynced(Client recipient, Client client) { DateTime timeOut = DateTime.Now + new TimeSpan(0, 0, 10); - while (recipient.LastRecvClientListUpdate < LastClientListUpdateID) + while (NetIdUtils.IdMoreRecent(LastClientListUpdateID, recipient.LastRecvClientListUpdate)) { if (DateTime.Now > timeOut || GameMain.Server == null || !connectedClients.Contains(recipient)) { diff --git a/Barotrauma/BarotraumaServer/ServerSource/Networking/Primitives/Peers/Server/LidgrenServerPeer.cs b/Barotrauma/BarotraumaServer/ServerSource/Networking/Primitives/Peers/Server/LidgrenServerPeer.cs index c49417f23..b231a8672 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Networking/Primitives/Peers/Server/LidgrenServerPeer.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Networking/Primitives/Peers/Server/LidgrenServerPeer.cs @@ -225,7 +225,7 @@ namespace Barotrauma.Networking } else if (!packetHeader.IsConnectionInitializationStep()) { - if (!(connectedClients.Find(c => c is LidgrenConnection l && l.NetConnection == lidgrenMsg.SenderConnection) is LidgrenConnection conn)) + if (connectedClients.Find(c => c is LidgrenConnection l && l.NetConnection == lidgrenMsg.SenderConnection) is not LidgrenConnection conn) { if (pendingClient != null) { @@ -373,7 +373,7 @@ namespace Barotrauma.Networking { if (netServer == null) { return; } - if (!(conn is LidgrenConnection lidgrenConn)) { return; } + if (conn is not LidgrenConnection lidgrenConn) { return; } if (connectedClients.Contains(lidgrenConn)) { @@ -432,7 +432,7 @@ namespace Barotrauma.Networking } else { - if (!packet.SteamId.TryUnwrap(out var id) || !(id is SteamId steamId)) + if (!packet.SteamId.TryUnwrap(out var id) || id is not SteamId steamId) { if (requireSteamAuth) { diff --git a/Barotrauma/BarotraumaServer/ServerSource/Networking/Primitives/Peers/Server/ServerPeer.cs b/Barotrauma/BarotraumaServer/ServerSource/Networking/Primitives/Peers/Server/ServerPeer.cs index bc8acf2d6..4e16b15bb 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Networking/Primitives/Peers/Server/ServerPeer.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Networking/Primitives/Peers/Server/ServerPeer.cs @@ -167,7 +167,14 @@ namespace Barotrauma.Networking if (pendingClient.AccountInfo.AccountId.TryUnwrap(out var id)) { banAccountId(id); } pendingClient.AccountInfo.OtherMatchingIds.ForEach(banAccountId); - serverSettings.BanList.BanPlayer(pendingClient.Name ?? "Player", pendingClient.Connection.Endpoint, banReason, duration); + if (pendingClient.AccountInfo.AccountId.TryUnwrap(out var accountId)) + { + serverSettings.BanList.BanPlayer(pendingClient.Name ?? "Player", accountId, banReason, duration); + } + else + { + serverSettings.BanList.BanPlayer(pendingClient.Name ?? "Player", pendingClient.Connection.Endpoint, banReason, duration); + } } protected bool IsPendingClientBanned(PendingClient pendingClient, out string? banReason) diff --git a/Barotrauma/BarotraumaServer/ServerSource/Networking/Primitives/Peers/Server/SteamP2PServerPeer.cs b/Barotrauma/BarotraumaServer/ServerSource/Networking/Primitives/Peers/Server/SteamP2PServerPeer.cs index 8bf68f4b5..b51065601 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Networking/Primitives/Peers/Server/SteamP2PServerPeer.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Networking/Primitives/Peers/Server/SteamP2PServerPeer.cs @@ -1,8 +1,6 @@ #nullable enable using System; using System.Collections.Generic; -using System.Linq; -using Microsoft.Xna.Framework; namespace Barotrauma.Networking { @@ -139,7 +137,27 @@ namespace Barotrauma.Networking pendingClient?.Heartbeat(); connectedClient?.Heartbeat(); - if (serverSettings.BanList.IsBanned(senderSteamId, out string banReason) || + if (packetHeader.IsConnectionInitializationStep()) + { + if (!initialization.HasValue) { return; } + ConnectionInitialization initializationStep = initialization.Value; + + if (pendingClient != null) + { + pendingClient.Connection.SetAccountInfo(new AccountInfo(senderSteamId, sentOwnerSteamId)); + ReadConnectionInitializationStep( + pendingClient, + new ReadWriteMessage(inc.Buffer, inc.BitPosition, inc.LengthBits, false), + initializationStep); + } + else if (initializationStep == ConnectionInitialization.ConnectionStarted) + { + pendingClient = new PendingClient(new SteamP2PConnection(senderSteamId)); + pendingClient.Connection.SetAccountInfo(new AccountInfo(senderSteamId, sentOwnerSteamId)); + pendingClients.Add(pendingClient); + } + } + else if (serverSettings.BanList.IsBanned(senderSteamId, out string banReason) || serverSettings.BanList.IsBanned(sentOwnerSteamId, out banReason)) { if (pendingClient != null) @@ -167,24 +185,6 @@ namespace Barotrauma.Networking //message exists solely as a heartbeat, ignore its contents return; } - else if (packetHeader.IsConnectionInitializationStep()) - { - if (!initialization.HasValue) { return; } - ConnectionInitialization initializationStep = initialization.Value; - - if (pendingClient != null) - { - pendingClient.Connection.SetAccountInfo(new AccountInfo(senderSteamId, sentOwnerSteamId)); - ReadConnectionInitializationStep( - pendingClient, - new ReadWriteMessage(inc.Buffer, inc.BitPosition, inc.LengthBits, false), - initializationStep); - } - else if (initializationStep == ConnectionInitialization.ConnectionStarted) - { - pendingClients.Add(new PendingClient(new SteamP2PConnection(senderSteamId))); - } - } else if (connectedClient != null) { var packet = INetSerializableStruct.Read(inc); @@ -248,7 +248,7 @@ namespace Barotrauma.Networking { if (!started) { return; } - if (!(conn is SteamP2PConnection steamP2PConn)) { return; } + if (conn is not SteamP2PConnection steamP2PConn) { return; } if (!connectedClients.Contains(steamP2PConn) && conn != OwnerConnection) { @@ -256,7 +256,7 @@ namespace Barotrauma.Networking return; } - if (!conn.AccountInfo.AccountId.TryUnwrap(out var connAccountId) || !(connAccountId is SteamId connSteamId)) { return; } + if (!conn.AccountInfo.AccountId.TryUnwrap(out var connAccountId) || connAccountId is not SteamId) { return; } byte[] bufAux = msg.PrepareForSending(compressPastThreshold, out bool isCompressed, out _); @@ -292,9 +292,9 @@ namespace Barotrauma.Networking { if (!started) { return; } - if (!(conn is SteamP2PConnection steamp2pConn)) { return; } + if (conn is not SteamP2PConnection steamp2pConn) { return; } - if (!conn.AccountInfo.AccountId.TryUnwrap(out var connAccountId) || !(connAccountId is SteamId connSteamId)) { return; } + if (!conn.AccountInfo.AccountId.TryUnwrap(out var connAccountId) || connAccountId is not SteamId connSteamId) { return; } SendDisconnectMessage(connSteamId, peerDisconnectPacket); diff --git a/Barotrauma/BarotraumaServer/WindowsServer.csproj b/Barotrauma/BarotraumaServer/WindowsServer.csproj index 68ab0885b..ac8ceabb6 100644 --- a/Barotrauma/BarotraumaServer/WindowsServer.csproj +++ b/Barotrauma/BarotraumaServer/WindowsServer.csproj @@ -6,7 +6,7 @@ Barotrauma FakeFish, Undertow Games Barotrauma Dedicated Server - 0.19.5.0 + 0.19.8.0 Copyright © FakeFish 2018-2022 AnyCPU;x64 DedicatedServer diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/HumanAIController.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/HumanAIController.cs index 62f664d39..3ed35dd0a 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/HumanAIController.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/HumanAIController.cs @@ -466,7 +466,12 @@ namespace Barotrauma } } } - steeringManager.Update(Character.AnimController.GetCurrentSpeed(run && Character.CanRun)); + + //if someone is grabbing the bot and the bot isn't trying to run anywhere, let them keep dragging and "control" the bot + if (Character.SelectedBy == null || run) + { + steeringManager.Update(Character.AnimController.GetCurrentSpeed(run && Character.CanRun)); + } bool ignorePlatforms = Character.AnimController.TargetMovement.Y < -0.5f && (-Character.AnimController.TargetMovement.Y > Math.Abs(Character.AnimController.TargetMovement.X)); if (steeringManager == insideSteering) diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveCombat.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveCombat.cs index 625a177a7..c0c6f9c69 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveCombat.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveCombat.cs @@ -913,11 +913,14 @@ namespace Barotrauma private void RemoveFollowTarget() { - if (arrestingRegistered) + if (followTargetObjective != null) { - followTargetObjective.Completed -= OnArrestTargetReached; + if (arrestingRegistered) + { + followTargetObjective.Completed -= OnArrestTargetReached; + } + RemoveSubObjective(ref followTargetObjective); } - RemoveSubObjective(ref followTargetObjective); arrestingRegistered = false; } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveGoTo.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveGoTo.cs index ff815f159..d8607e729 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveGoTo.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveGoTo.cs @@ -595,6 +595,10 @@ namespace Barotrauma { return c.CurrentHull; } + else if (target is Structure structure) + { + return Hull.FindHull(structure.Position, useWorldCoordinates: false); + } else if (target is Gap g) { return g.FlowTargetHull; diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveLoadItem.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveLoadItem.cs index cfd3e7ca9..b8c94aca0 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveLoadItem.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveLoadItem.cs @@ -54,7 +54,7 @@ namespace Barotrauma if (ValidContainableItemIdentifiers.None()) { #if DEBUG - DebugConsole.ShowError($"No valid containable item identifiers found for the Load Item objective targeting {Container}"); + DebugConsole.LogError($"No valid containable item identifiers found for the Load Item objective targeting {Container}"); #endif Abandon = true; return; @@ -250,7 +250,7 @@ namespace Barotrauma catch (NotImplementedException) { #if DEBUG - DebugConsole.ShowError($"Unexpected target condition \"{TargetItemCondition}\" in local function GetConditionBasedProperty"); + DebugConsole.LogError($"Unexpected target condition \"{TargetItemCondition}\" in local function GetConditionBasedProperty"); #endif return 0.0f; } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveLoadItems.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveLoadItems.cs index a5b9338dc..c54980f2e 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveLoadItems.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveLoadItems.cs @@ -90,7 +90,7 @@ namespace Barotrauma catch (NotImplementedException) { #if DEBUG - DebugConsole.ShowError($"Unexpected target condition \"{targetCondition}\" in AIObjectiveLoadItems.ItemMatchesTargetCondition"); + DebugConsole.LogError($"Unexpected target condition \"{targetCondition}\" in AIObjectiveLoadItems.ItemMatchesTargetCondition"); #endif return false; } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveOperateItem.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveOperateItem.cs index 56a453007..aed77cb77 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveOperateItem.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveOperateItem.cs @@ -37,6 +37,8 @@ namespace Barotrauma public Func completionCondition; private bool isDoneOperating; + public float? OverridePriority = null; + protected override float GetPriority() { bool isOrder = objectiveManager.IsOrder(this); @@ -52,7 +54,11 @@ namespace Barotrauma } else { - if (isOrder) + if (OverridePriority.HasValue) + { + Priority = OverridePriority.Value; + } + else if (isOrder) { Priority = objectiveManager.GetOrderPriority(this); } @@ -135,7 +141,7 @@ namespace Barotrauma float value = CumulatedDevotion + (max * PriorityModifier); Priority = MathHelper.Clamp(value, 0, max); } - else + else if (!OverridePriority.HasValue) { float value = CumulatedDevotion + (AIObjectiveManager.LowestOrderPriority * PriorityModifier); float max = AIObjectiveManager.LowestOrderPriority - 1; @@ -204,8 +210,15 @@ namespace Barotrauma { if (!character.IsClimbing && character.CanInteractWith(target.Item, out _, checkLinked: false)) { - HumanAIController.FaceTarget(target.Item); - if (character.SelectedItem != target.Item) + if (target.Item.GetComponent() is not Controller { ControlCharacterPose: true }) + { + HumanAIController.FaceTarget(target.Item); + } + else + { + HumanAIController.SteeringManager.Reset(); + } + if (character.SelectedItem != target.Item && character.SelectedSecondaryItem != target.Item) { target.Item.TryInteract(character, forceSelectKey: true); } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveRescue.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveRescue.cs index c700ff0ad..30d687a2a 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveRescue.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveRescue.cs @@ -278,7 +278,7 @@ namespace Barotrauma float cprSuitability = targetCharacter.Oxygen < 0.0f ? -targetCharacter.Oxygen * 100.0f : 0.0f; //find which treatments are the most suitable to treat the character's current condition - targetCharacter.CharacterHealth.GetSuitableTreatments(currentTreatmentSuitabilities, normalize: false, predictFutureDuration: 10.0f); + targetCharacter.CharacterHealth.GetSuitableTreatments(currentTreatmentSuitabilities, user: character, normalize: false, predictFutureDuration: 10.0f); //check if we already have a suitable treatment for any of the afflictions foreach (Affliction affliction in GetSortedAfflictions(targetCharacter)) diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Order.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Order.cs index b9c716c78..042e913cd 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Order.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Order.cs @@ -3,9 +3,8 @@ using Barotrauma.Items.Components; using Microsoft.Xna.Framework; using System; using System.Collections.Generic; -using System.Xml.Linq; -using System.Linq; using System.Collections.Immutable; +using System.Linq; namespace Barotrauma { @@ -151,7 +150,7 @@ namespace Barotrauma public OrderPrefab(ContentXElement orderElement, OrdersFile file) : base(file, orderElement.GetAttributeIdentifier("identifier", "")) { Name = TextManager.Get($"OrderName.{Identifier}"); - ContextualName = TextManager.Get($"OrderNameContextual.{Identifier}"); + ContextualName = TextManager.Get($"OrderNameContextual.{Identifier}").Fallback(Name); string targetItemType = orderElement.GetAttributeString("targetitemtype", ""); if (!string.IsNullOrWhiteSpace(targetItemType)) @@ -435,7 +434,7 @@ namespace Barotrauma } catch (NotImplementedException e) { - DebugConsole.ShowError($"Error creating a new Order instance: unexpected target type \"{targetType}\".\n{e.StackTrace.CleanupStackTrace()}"); + DebugConsole.LogError($"Error creating a new Order instance: unexpected target type \"{targetType}\".\n{e.StackTrace.CleanupStackTrace()}"); return null; } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/Animation/HumanoidAnimController.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/Animation/HumanoidAnimController.cs index 02bb65dd5..e2d69fe08 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/Animation/HumanoidAnimController.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/Animation/HumanoidAnimController.cs @@ -336,7 +336,7 @@ namespace Barotrauma { ApplyTestPose(); } - else + else if (character.SelectedBy == null) { if (character.LockHands) { @@ -356,7 +356,7 @@ namespace Barotrauma HandIK(rightHand, midPos, CurrentAnimationParams.ArmIKStrength, CurrentAnimationParams.HandIKStrength); HandIK(leftHand, midPos, CurrentAnimationParams.ArmIKStrength, CurrentAnimationParams.HandIKStrength); } - if (Anim != Animation.UsingItem && character.SelectedBy == null) + if (Anim != Animation.UsingItem) { if (Anim != Animation.UsingItemWhileClimbing) { @@ -1716,9 +1716,17 @@ namespace Barotrauma } else if (target is AICharacter && target != Character.Controlled) { - target.AnimController.TargetDir = WorldPosition.X > target.WorldPosition.X ? Direction.Right : Direction.Left; - Vector2 movement = (character.SimPosition + Vector2.UnitX * 0.5f * Dir) - target.SimPosition; - target.AnimController.TargetMovement = movement.LengthSquared() > 0.01f ? movement : Vector2.Zero; + if (target.AnimController.Dir > 0 == WorldPosition.X > target.WorldPosition.X) + { + target.AnimController.LockFlippingUntil = (float)Timing.TotalTime + 0.5f; + } + else + { + target.AnimController.TargetDir = WorldPosition.X > target.WorldPosition.X ? Direction.Right : Direction.Left; + } + //make the target stand 0.5 meters away from this character, on the side they're currently at + Vector2 movement = (character.SimPosition + Vector2.UnitX * 0.5f * Math.Sign(target.SimPosition.X - character.SimPosition.X)) - target.SimPosition; + target.AnimController.TargetMovement = movement.LengthSquared() > 0.01f ? movement : Vector2.Zero; } } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/Attack.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/Attack.cs index ee7cdc224..d5d02d2d4 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/Attack.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/Attack.cs @@ -402,9 +402,8 @@ namespace Barotrauma } else { - string afflictionIdentifier = subElement.GetAttributeString("identifier", "").ToLowerInvariant(); - afflictionPrefab = AfflictionPrefab.Prefabs[afflictionIdentifier]; - if (afflictionPrefab == null) + Identifier afflictionIdentifier = subElement.GetAttributeIdentifier("identifier", ""); + if (!AfflictionPrefab.Prefabs.TryGet(afflictionIdentifier, out afflictionPrefab)) { DebugConsole.ThrowError("Error in Attack (" + parentDebugName + ") - Affliction prefab \"" + afflictionIdentifier + "\" not found."); continue; @@ -430,15 +429,13 @@ namespace Barotrauma Afflictions.Clear(); foreach (var subElement in element.GetChildElements("affliction")) { - AfflictionPrefab afflictionPrefab; Affliction affliction; Identifier afflictionIdentifier = subElement.GetAttributeIdentifier("identifier", ""); - if (!AfflictionPrefab.Prefabs.ContainsKey(afflictionIdentifier)) + if (!AfflictionPrefab.Prefabs.TryGet(afflictionIdentifier, out AfflictionPrefab afflictionPrefab)) { DebugConsole.ThrowError($"Error in an Attack defined in \"{parentDebugName}\" - could not find an affliction with the identifier \"{afflictionIdentifier}\"."); continue; } - afflictionPrefab = AfflictionPrefab.Prefabs[afflictionIdentifier]; affliction = afflictionPrefab.Instantiate(0.0f); affliction.Deserialize(subElement); //backwards compatibility diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/Character.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/Character.cs index dcb2deff3..b03d51803 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/Character.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/Character.cs @@ -549,6 +549,10 @@ namespace Barotrauma set { lockHandsTimer = MathHelper.Clamp(lockHandsTimer + (value ? 1.0f : -0.5f), 0.0f, 10.0f); + if (value) + { + SelectedCharacter = null; + } #if CLIENT HintManager.OnHandcuffed(this); #endif @@ -599,13 +603,10 @@ namespace Barotrauma get { return selectedCharacter; } set { - if (value == selectedCharacter) return; - if (selectedCharacter != null) - selectedCharacter.selectedBy = null; + if (value == selectedCharacter) { return; } + if (selectedCharacter != null) { selectedCharacter.selectedBy = null; } selectedCharacter = value; - if (selectedCharacter != null) - selectedCharacter.selectedBy = this; - + if (selectedCharacter != null) {selectedCharacter.selectedBy = this; } #if CLIENT CharacterHealth.SetHealthBarVisibility(value == null); #endif @@ -707,6 +708,14 @@ namespace Barotrauma get { return CurrentHull == null || CurrentHull.LethalPressure > 5.0f; } } + /// + /// Can be used by status effects + /// + public AnimController.Animation Anim + { + get { return AnimController?.Anim ?? AnimController.Animation.None; } + } + public const float KnockbackCooldown = 5.0f; public float KnockbackCooldownTimer; @@ -2620,7 +2629,7 @@ namespace Barotrauma if (!AllowInput) { FocusedCharacter = null; - if (SelectedCharacter != null) DeselectCharacter(); + if (SelectedCharacter != null) { DeselectCharacter(); } return; } } @@ -3636,7 +3645,7 @@ namespace Barotrauma string modifiedMessage = ChatMessage.ApplyDistanceEffect(message.Message, message.MessageType.Value, this, Controlled); if (!string.IsNullOrEmpty(modifiedMessage)) { - GameMain.GameSession.CrewManager.AddSinglePlayerChatMessage(info.Name, modifiedMessage, message.MessageType.Value, this); + GameMain.GameSession.CrewManager.AddSinglePlayerChatMessage(Name, modifiedMessage, message.MessageType.Value, this); } } #endif @@ -4020,6 +4029,7 @@ namespace Barotrauma if (newStun > 0.0f) { SelectedItem = SelectedSecondaryItem = null; + if (SelectedCharacter != null) { DeselectCharacter(); } } HealthUpdateInterval = 0.0f; } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/CharacterEventData.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/CharacterEventData.cs index e8b58578b..9786888d3 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/CharacterEventData.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/CharacterEventData.cs @@ -1,8 +1,9 @@ -using System.Collections.Generic; -using System.Collections.Immutable; -using Barotrauma.Items.Components; -using Barotrauma.Networking; +using Barotrauma.Networking; using Microsoft.Xna.Framework; +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; namespace Barotrauma { @@ -25,9 +26,10 @@ namespace Barotrauma UpdateSkills = 12, UpdateMoney = 13, UpdatePermanentStats = 14, + RemoveFromCrew = 15, MinValue = 0, - MaxValue = 14 + MaxValue = 15 } private interface IEventData : NetEntityEvent.IData @@ -133,18 +135,30 @@ namespace Barotrauma public EventType EventType => EventType.TeamChange; } + [NetworkSerialize] + public readonly record struct ItemTeamChange(CharacterTeamType TeamId, ImmutableArray ItemIds) : INetSerializableStruct; + + public struct AddToCrewEventData : IEventData { public EventType EventType => EventType.AddToCrew; - public readonly CharacterTeamType TeamType; - public readonly ImmutableArray InventoryItems; + public readonly ItemTeamChange ItemTeamChange; public AddToCrewEventData(CharacterTeamType teamType, IEnumerable inventoryItems) { - TeamType = teamType; - InventoryItems = inventoryItems.ToImmutableArray(); + ItemTeamChange = new ItemTeamChange(teamType, inventoryItems.Select(it => it.ID).ToImmutableArray()); + } + } + + public struct RemoveFromCrewEventData : IEventData + { + public EventType EventType => EventType.RemoveFromCrew; + public readonly ItemTeamChange ItemTeamChange; + + public RemoveFromCrewEventData(CharacterTeamType teamType, IEnumerable inventoryItems) + { + ItemTeamChange = new ItemTeamChange(teamType, inventoryItems.Select(it => it.ID).ToImmutableArray()); } - } public struct UpdateExperienceEventData : IEventData diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/CharacterNetworking.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/CharacterNetworking.cs index 29250acfd..5d8e294ec 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/CharacterNetworking.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/CharacterNetworking.cs @@ -82,10 +82,10 @@ namespace Barotrauma public UInt16 networkUpdateID; } - private List memInput = new List(); + private readonly List memInput = new List(); - private List memState = new List(); - private List memLocalState = new List(); + private readonly List memState = new List(); + private readonly List memLocalState = new List(); public float healthUpdateTimer; diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/Health/CharacterHealth.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/Health/CharacterHealth.cs index 685429eb9..cd028c9ca 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/Health/CharacterHealth.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/Health/CharacterHealth.cs @@ -1038,7 +1038,7 @@ namespace Barotrauma /// A dictionary where the key is the identifier of the item and the value the suitability /// If true, the suitability values are normalized between 0 and 1. If not, they're arbitrary values defined in the medical item XML, where negative values are unsuitable, and positive ones suitable. /// If above 0, the method will take into account how much currently active status effects while affect the afflictions in the next x seconds. - public void GetSuitableTreatments(Dictionary treatmentSuitability, bool normalize, Limb limb = null, bool ignoreHiddenAfflictions = false, float predictFutureDuration = 0.0f) + public void GetSuitableTreatments(Dictionary treatmentSuitability, bool normalize, Character user, Limb limb = null, bool ignoreHiddenAfflictions = false, float predictFutureDuration = 0.0f) { //key = item identifier //float = suitability @@ -1062,7 +1062,18 @@ namespace Barotrauma } if (strength <= affliction.Prefab.TreatmentThreshold) { continue; } - if (ignoreHiddenAfflictions && strength < affliction.Prefab.ShowIconThreshold) { continue; } + + if (ignoreHiddenAfflictions) + { + if (user == Character) + { + if (strength < affliction.Prefab.ShowIconThreshold) { continue; } + } + else + { + if (strength < affliction.Prefab.ShowIconToOthersThreshold) { continue; } + } + } foreach (KeyValuePair treatment in affliction.Prefab.TreatmentSuitability) { @@ -1153,10 +1164,10 @@ namespace Barotrauma msg.WriteRangedSingle( MathHelper.Clamp(affliction.Strength, 0.0f, affliction.Prefab.MaxStrength), 0.0f, affliction.Prefab.MaxStrength, 8); - msg.WriteByte((byte)affliction.Prefab.PeriodicEffects.Count()); + msg.WriteByte((byte)affliction.Prefab.PeriodicEffects.Count); foreach (AfflictionPrefab.PeriodicEffect periodicEffect in affliction.Prefab.PeriodicEffects) { - msg.WriteRangedSingle(affliction.PeriodicEffectTimers[periodicEffect], periodicEffect.MinInterval, periodicEffect.MaxInterval, 8); + msg.WriteRangedSingle(affliction.PeriodicEffectTimers[periodicEffect], 0, periodicEffect.MaxInterval, 8); } } @@ -1178,7 +1189,7 @@ namespace Barotrauma msg.WriteRangedSingle( MathHelper.Clamp(affliction.Strength, 0.0f, affliction.Prefab.MaxStrength), 0.0f, affliction.Prefab.MaxStrength, 8); - msg.WriteByte((byte)affliction.Prefab.PeriodicEffects.Count()); + msg.WriteByte((byte)affliction.Prefab.PeriodicEffects.Count); foreach (AfflictionPrefab.PeriodicEffect periodicEffect in affliction.Prefab.PeriodicEffects) { msg.WriteRangedSingle(affliction.PeriodicEffectTimers[periodicEffect], periodicEffect.MinInterval, periodicEffect.MaxInterval, 8); diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/Health/DamageModifier.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/Health/DamageModifier.cs index 07f16e007..a71d1e73e 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/Health/DamageModifier.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/Health/DamageModifier.cs @@ -86,6 +86,28 @@ namespace Barotrauma { DebugConsole.ThrowError("Error in DamageModifier config (" + parentDebugName + ") - define afflictions using identifiers or types instead of names."); } + foreach (var afflictionType in parsedAfflictionTypes) + { + if (!AfflictionPrefab.Prefabs.Any(p => p.AfflictionType == afflictionType)) + { + createWarningOrError($"Potentially invalid damage modifier in \"{parentDebugName}\". Could not find any afflictions of the type \"{afflictionType}\". Did you mean to use an affliction identifier instead?"); + } + } + foreach (var afflictionIdentifier in parsedAfflictionIdentifiers) + { + if (!AfflictionPrefab.Prefabs.ContainsKey(afflictionIdentifier)) + { + createWarningOrError($"Potentially invalid damage modifier in \"{parentDebugName}\". Could not find any afflictions with the identifier \"{afflictionIdentifier}\". Did you mean to use an affliction type instead?"); + } + } + static void createWarningOrError(string msg) + { +#if DEBUG + DebugConsole.ThrowError(msg); +#else + DebugConsole.AddWarning(msg); +#endif + } } private void ParseAfflictionTypes() diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/Talents/Abilities/CustomAbilities/CharacterAbilityTandemFire.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/Talents/Abilities/CustomAbilities/CharacterAbilityTandemFire.cs index a534df7f5..d58d73b49 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/Talents/Abilities/CustomAbilities/CharacterAbilityTandemFire.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/Talents/Abilities/CustomAbilities/CharacterAbilityTandemFire.cs @@ -1,8 +1,4 @@ -using Barotrauma.Items.Components; -using Microsoft.Xna.Framework; -using System.Collections.Generic; -using System.Linq; -using System.Xml.Linq; +using Microsoft.Xna.Framework; namespace Barotrauma.Abilities { @@ -31,7 +27,7 @@ namespace Barotrauma.Abilities } } - if (!SelectedItemHasTag(closestCharacter)) { return; } + if (closestCharacter == null || !SelectedItemHasTag(closestCharacter)) { return; } if (closestDistance < squaredMaxDistance) { diff --git a/Barotrauma/BarotraumaShared/SharedSource/DebugConsole.cs b/Barotrauma/BarotraumaShared/SharedSource/DebugConsole.cs index 3899632f6..9a7710898 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/DebugConsole.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/DebugConsole.cs @@ -1267,7 +1267,11 @@ namespace Barotrauma } }, () => { - return new[] { FactionPrefab.Prefabs.Select(f => f.Identifier.Value).ToArray() }; + return new[] + { + FactionPrefab.Prefabs.Select(f => f.Identifier.Value).ToArray(), + GameMain.GameSession?.Campaign.Factions.Select(f => f.Prefab.Identifier.ToString()).ToArray() ?? Array.Empty() + }; }, true)); commands.Add(new Command("fixitems", "fixitems: Repairs all items and restores them to full condition.", (string[] args) => @@ -2235,7 +2239,7 @@ namespace Barotrauma } } - public static void ShowError(string msg, Color? color = null) + public static void LogError(string msg, Color? color = null) { color ??= Color.Red; NewMessage(msg, color.Value, isCommand: false, isError: true); @@ -2407,7 +2411,7 @@ namespace Barotrauma } #endif - ShowError(error); + LogError(error); } public static void AddWarning(string warning) diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/BinaryOptionAction.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/BinaryOptionAction.cs index 05f27d592..ae088e51c 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/BinaryOptionAction.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/BinaryOptionAction.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Xml.Linq; namespace Barotrauma { diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/CheckAfflictionAction.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/CheckAfflictionAction.cs index 953d6f31f..ca7fcad9d 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/CheckAfflictionAction.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/CheckAfflictionAction.cs @@ -38,10 +38,12 @@ namespace Barotrauma } IEnumerable afflictions = target.CharacterHealth.GetAllAfflictions().Where(affliction => { - LimbType? limbType = target.CharacterHealth.GetAfflictionLimb(affliction)?.type; - if (limbType == null) { return false; } - - return limbType == TargetLimb && affliction.Strength >= MinStrength; + if (affliction.Prefab.LimbSpecific) + { + LimbType? limbType = target.CharacterHealth.GetAfflictionLimb(affliction)?.type; + if (limbType == null || limbType != TargetLimb) { return false; } + } + return affliction.Strength >= MinStrength; }); if (afflictions.Any(a => a.Identifier == Identifier)) { return true; } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/CheckConditionalAction.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/CheckConditionalAction.cs index 1cda074e2..cce7bd22c 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/CheckConditionalAction.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/CheckConditionalAction.cs @@ -13,7 +13,7 @@ namespace Barotrauma { if (TargetTag.IsEmpty) { - DebugConsole.ShowError($"CheckConditionalAction error: {GetEventName()} uses a CheckConditionalAction with no target tag! This will cause the check to automatically succeed."); + DebugConsole.LogError($"CheckConditionalAction error: {GetEventName()} uses a CheckConditionalAction with no target tag! This will cause the check to automatically succeed."); } foreach (var attribute in element.Attributes()) { @@ -25,7 +25,7 @@ namespace Barotrauma } if (Conditional == null) { - DebugConsole.ShowError($"CheckConditionalAction error: {GetEventName()} uses a CheckConditionalAction with no valid PropertyConditional! This will cause the check to automatically succeed."); + DebugConsole.LogError($"CheckConditionalAction error: {GetEventName()} uses a CheckConditionalAction with no valid PropertyConditional! This will cause the check to automatically succeed."); } static bool IsTargetTagAttribute(XAttribute attribute) => attribute.NameAsIdentifier() == "targettag"; @@ -52,7 +52,7 @@ namespace Barotrauma } if (target == null) { - DebugConsole.ShowError($"CheckConditionalAction error: {GetEventName()} uses a CheckConditionalAction but no valid target was found for tag \"{TargetTag}\"! This will cause the check to automatically succeed."); + DebugConsole.LogError($"CheckConditionalAction error: {GetEventName()} uses a CheckConditionalAction but no valid target was found for tag \"{TargetTag}\"! This will cause the check to automatically succeed."); } if (target == null || Conditional == null) { diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/CheckConnectionAction.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/CheckConnectionAction.cs index f2d7af787..56f6b82e2 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/CheckConnectionAction.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/CheckConnectionAction.cs @@ -18,10 +18,14 @@ class CheckConnectionAction : BinaryOptionAction [Serialize("", IsPropertySaveable.Yes)] public Identifier OtherConnectionName { get; set; } + [Serialize(1, IsPropertySaveable.Yes)] + public int MinAmount { get; set; } + public CheckConnectionAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element) { } protected override bool? DetermineSuccess() { + int amount = 0; var connectTargets = !ConnectedItemTag.IsEmpty ? ParentEvent.GetTargets(ConnectedItemTag) : Enumerable.Empty(); foreach (var target in ParentEvent.GetTargets(ItemTag)) { @@ -33,27 +37,17 @@ class CheckConnectionAction : BinaryOptionAction if (!IsCorrectConnection(connection, ConnectionName)) { continue; } if (ConnectedItemTag.IsEmpty && OtherConnectionName.IsEmpty) { - if (connection.Wires.Any()) { return true; } + amount += connection.Wires.Count(); + if (amount >= MinAmount) { return true; } continue; } foreach (var wire in connection.Wires) { if (wire.OtherConnection(connection) is not Connection otherConnection) { continue; } - if (ConnectedItemTag.IsEmpty) - { - if (IsCorrectConnection(otherConnection, OtherConnectionName)) { return true; } - } - else if (OtherConnectionName.IsEmpty) - { - if (IsCorrectItem()) { return true; } - } - else - { - if (!IsCorrectConnection(otherConnection, OtherConnectionName)) { continue; } - if (!IsCorrectItem()) { continue; } - return true; - } - + if (!ConnectedItemTag.IsEmpty && !IsCorrectConnection(otherConnection, OtherConnectionName)) { continue; } + if (!ConnectedItemTag.IsEmpty && !IsCorrectItem()) { continue; } + amount++; + if (amount >= MinAmount) { return true; } bool IsCorrectItem() => connectTargets.Contains(otherConnection.Item); } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/CheckDataAction.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/CheckDataAction.cs index 92ff33999..47c205aee 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/CheckDataAction.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/CheckDataAction.cs @@ -1,7 +1,6 @@ #nullable enable using System; using System.Linq; -using System.Xml.Linq; namespace Barotrauma { @@ -36,15 +35,32 @@ namespace Barotrauma } } + public CheckDataAction(ContentXElement element, string parentDebugString) : base(null, element) + { + if (string.IsNullOrEmpty(Condition)) + { + Condition = element.GetAttributeString("value", string.Empty)!; + if (string.IsNullOrEmpty(Condition)) + { + DebugConsole.ThrowError($"Error in scripted event \"{parentDebugString}\". CheckDataAction with no condition set ({element})."); + } + } + } + + public bool GetSuccess() + { + return DetermineSuccess() ?? false; + } + protected override bool? DetermineSuccess() { - if (!(GameMain.GameSession?.GameMode is CampaignMode campaignMode)) { return false; } + if (GameMain.GameSession?.GameMode is not CampaignMode campaignMode) { return false; } string[] splitString = Condition.Split(' '); - string value = Condition; + string value; if (splitString.Length > 0) { - #warning Is this correct? + //the first part of the string is the operator, skip it value = string.Join(" ", splitString.Skip(1)); } else diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/CheckItemAction.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/CheckItemAction.cs index dba8364ef..9413193d1 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/CheckItemAction.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/CheckItemAction.cs @@ -1,4 +1,5 @@ -using System; +using Barotrauma.Items.Components; +using System.Collections.Generic; using System.Linq; using System.Xml.Linq; @@ -15,8 +16,19 @@ namespace Barotrauma [Serialize("", IsPropertySaveable.Yes)] public string ItemTags { get; set; } + [Serialize(1, IsPropertySaveable.Yes)] + public int Amount { get; set; } + + [Serialize("", IsPropertySaveable.Yes, description: "Tag to apply to the first target when the check succeeds.")] + public Identifier ApplyTagToTarget { get; set; } + [Serialize(false, IsPropertySaveable.Yes)] public bool RequireEquipped { get; set; } + + [Serialize(-1, IsPropertySaveable.Yes)] + public int ItemContainerIndex { get; set; } + + private readonly IReadOnlyList conditionals; private readonly Identifier[] itemIdentifierSplit; private readonly Identifier[] itemTags; @@ -25,6 +37,19 @@ namespace Barotrauma { itemIdentifierSplit = ItemIdentifiers.Split(',').ToIdentifiers(); itemTags = ItemTags.Split(",").ToIdentifiers(); + var conditionalList = new List(); + foreach (ContentXElement subElement in element.GetChildElements("conditional")) + { + foreach (XAttribute attribute in subElement.Attributes()) + { + if (PropertyConditional.IsValid(attribute)) + { + conditionalList.Add(new PropertyConditional(attribute)); + } + } + break; + } + conditionals = conditionalList; } protected override bool? DetermineSuccess() @@ -35,25 +60,70 @@ namespace Barotrauma { if (target is Character character) { - if (RequireEquipped) + Inventory inventory = character.Inventory; + if (CheckInventory(character.Inventory, character)) { - if (itemTags.Any(tag => character.HasEquippedItem(tag))) { return true; } - if (itemIdentifierSplit.Any(identifier => character.HasEquippedItem(identifier))) { return true; } - return false; + if (!ApplyTagToTarget.IsEmpty) + { + ParentEvent.AddTarget(ApplyTagToTarget, target); + } + return true; } - if (character.Inventory is not CharacterInventory inventory) { continue; } - if (itemTags.Any(tag => inventory.FindItemByTag(tag, recursive: true) is not null)) { return true; } - if (itemIdentifierSplit.Any(identifier => inventory.FindItemByIdentifier(identifier, recursive: true) is not null)) { return true; } } - else if (target is Item item && item.OwnInventory is ItemInventory inventory) + else if (target is Item item) { - if (itemTags.Any(tag => inventory.FindItemByTag(tag, recursive: true) is not null)) { return true; } - if (itemIdentifierSplit.Any(identifier => inventory.FindItemByIdentifier(identifier, recursive: true) is not null)) { return true; } + int i = 0; + foreach (var itemContainer in item.GetComponents()) + { + if (ItemContainerIndex == -1 || i == ItemContainerIndex) + { + if (CheckInventory(itemContainer.Inventory, character: null)) + { + if (!ApplyTagToTarget.IsEmpty) + { + ParentEvent.AddTarget(ApplyTagToTarget, target); + } + return true; + } + } + i++; + } } } return false; } + private bool CheckInventory(Inventory inventory, Character character) + { + if (inventory == null) { return false; } + int count = 0; + foreach (Item item in inventory.FindAllItems(it => itemTags.Any(it.HasTag) || itemIdentifierSplit.Contains(it.Prefab.Identifier))) + { + if (!ConditionalsMatch(item, character)) { continue; } + count++; + if (count >= Amount) { return true; } + } + return false; + } + + private bool ConditionalsMatch(Item item, Character character = null) + { + if (item == null) { return false; } + foreach (PropertyConditional conditional in conditionals) + { + if (!conditional.Matches(item)) + { + return false; + } + } + if (RequireEquipped) + { + if (character == null) { return false; } + return character.HasEquippedItem(item); + } + return true; + } + public override string ToDebugString() { return $"{ToolBox.GetDebugSymbol(HasBeenDetermined())} {nameof(CheckItemAction)} -> (TargetTag: {TargetTag.ColorizeObject()}, " + diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/CheckOrderAction.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/CheckOrderAction.cs index 0803242f1..6723d3abb 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/CheckOrderAction.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/CheckOrderAction.cs @@ -11,6 +11,9 @@ namespace Barotrauma [Serialize("", IsPropertySaveable.Yes)] public Identifier OrderOption { get; set; } + [Serialize("", IsPropertySaveable.Yes)] + public Identifier OrderTargetTag { get; set; } + public CheckOrderAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element) { } protected override bool? DetermineSuccess() @@ -29,20 +32,17 @@ namespace Barotrauma } if (targetCharacter == null) { - DebugConsole.ShowError($"CheckConditionalAction error: {GetEventName()} uses a CheckOrderAction but no valid target character was found for tag \"{TargetTag}\"! This will cause the check to automatically fail."); + DebugConsole.LogError($"CheckConditionalAction error: {GetEventName()} uses a CheckOrderAction but no valid target character was found for tag \"{TargetTag}\"! This will cause the check to automatically fail."); return false; } var currentOrderInfo = targetCharacter.GetCurrentOrderWithTopPriority(); if (currentOrderInfo?.Identifier == OrderIdentifier) { - if (OrderOption.IsEmpty) + if (!OrderTargetTag.IsEmpty) { - return true; - } - else - { - return currentOrderInfo?.Option == OrderOption; + if (currentOrderInfo.TargetEntity is not Item targetItem || !targetItem.HasTag(OrderTargetTag)) { return false; } } + return OrderOption.IsEmpty || currentOrderInfo?.Option == OrderOption; } return false; } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/CheckSelectedAction.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/CheckSelectedAction.cs new file mode 100644 index 000000000..6f1cb5867 --- /dev/null +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/CheckSelectedAction.cs @@ -0,0 +1,89 @@ +using Barotrauma.Extensions; +using System.Collections.Generic; + +namespace Barotrauma +{ + class CheckSelectedItemAction : BinaryOptionAction + { + public enum SelectedItemType { Primary, Secondary, Any }; + + [Serialize("", IsPropertySaveable.Yes)] + public Identifier CharacterTag { get; set; } + + [Serialize("", IsPropertySaveable.Yes)] + public Identifier TargetTag { get; set; } + + [Serialize(SelectedItemType.Any, IsPropertySaveable.Yes)] + public SelectedItemType ItemType { get; set; } + + public CheckSelectedItemAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element) { } + + protected override bool? DetermineSuccess() + { + Character character = null; + if (!CharacterTag.IsEmpty) + { + foreach (var t in ParentEvent.GetTargets(CharacterTag)) + { + if (t is Character c) + { + character = c; + break; + } + } + } + if (character == null) + { + DebugConsole.LogError($"CheckSelectedItemAction error: {GetEventName()} uses a CheckSelectedItemAction but no valid character was found for tag \"{CharacterTag}\"! This will cause the check to automatically fail."); + return false; + } + if (!TargetTag.IsEmpty) + { + IEnumerable targets = ParentEvent.GetTargets(TargetTag); + if (targets.None()) + { + DebugConsole.LogError($"CheckSelectedItemAction error: {GetEventName()} uses a CheckSelectedItemAction but no valid targets were found for tag \"{TargetTag}\"! This will cause the check to automatically fail."); + return false; + } + foreach (var target in targets) + { + if (target is not Item targetItem) + { + continue; + } + if (IsSelected(targetItem)) + { + return true; + } + } + return false; + + bool IsSelected(Item item) + { + return ItemType switch + { + SelectedItemType.Any => character.IsAnySelectedItem(item), + SelectedItemType.Primary => character.SelectedItem == item, + SelectedItemType.Secondary => character.SelectedSecondaryItem == item, + _ => false + }; + } + } + else + { + return ItemType switch + { + SelectedItemType.Any => !character.HasSelectedAnyItem, + SelectedItemType.Primary => character.SelectedItem == null, + SelectedItemType.Secondary => character.SelectedSecondaryItem == null, + _ => false + }; + } + } + + private string GetEventName() + { + return ParentEvent?.Prefab?.Identifier is { IsEmpty: false } identifier ? $"the event \"{identifier}\"" : "an unknown event"; + } + } +} \ No newline at end of file diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/CheckSelectedItemAction.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/CheckSelectedItemAction.cs index 1c9903f6a..6de01c0e8 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/CheckSelectedItemAction.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/CheckSelectedItemAction.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; namespace Barotrauma { - class CheckSelectedItemAction : BinaryOptionAction + class CheckSelectedAction : BinaryOptionAction { public enum SelectedItemType { Primary, Secondary, Any }; @@ -16,7 +16,7 @@ namespace Barotrauma [Serialize(SelectedItemType.Any, IsPropertySaveable.Yes)] public SelectedItemType ItemType { get; set; } - public CheckSelectedItemAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element) { } + public CheckSelectedAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element) { } protected override bool? DetermineSuccess() { @@ -34,7 +34,7 @@ namespace Barotrauma } if (character == null) { - DebugConsole.ShowError($"CheckSelectedItemAction error: {GetEventName()} uses a CheckSelectedItemAction but no valid character was found for tag \"{CharacterTag}\"! This will cause the check to automatically fail."); + DebugConsole.LogError($"CheckSelectedItemAction error: {GetEventName()} uses a CheckSelectedItemAction but no valid character was found for tag \"{CharacterTag}\"! This will cause the check to automatically fail."); return false; } if (!TargetTag.IsEmpty) @@ -42,11 +42,16 @@ namespace Barotrauma IEnumerable targets = ParentEvent.GetTargets(TargetTag); if (targets.None()) { - DebugConsole.ShowError($"CheckSelectedItemAction error: {GetEventName()} uses a CheckSelectedItemAction but no valid targets were found for tag \"{TargetTag}\"! This will cause the check to automatically fail."); + DebugConsole.LogError($"CheckSelectedItemAction error: {GetEventName()} uses a CheckSelectedItemAction but no valid targets were found for tag \"{TargetTag}\"! This will cause the check to automatically fail."); return false; } foreach (var target in targets) { + if (target is Character targetCharacter) + { + if (ItemType == SelectedItemType.Any && character.SelectedCharacter == targetCharacter) { return true; } + continue; + } if (target is not Item targetItem) { continue; diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/EventAction.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/EventAction.cs index b01ede512..c0fc93a5b 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/EventAction.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/EventAction.cs @@ -134,7 +134,7 @@ namespace Barotrauma public static EventAction Instantiate(ScriptedEvent scriptedEvent, ContentXElement element) { - Type actionType = null; + Type actionType; try { actionType = Type.GetType("Barotrauma." + element.Name, true, true); diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/GodModeAction.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/GodModeAction.cs index 47ff662f2..e9995190f 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/GodModeAction.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/GodModeAction.cs @@ -1,8 +1,3 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Xml.Linq; - namespace Barotrauma { class GodModeAction : EventAction @@ -10,6 +5,9 @@ namespace Barotrauma [Serialize(true, IsPropertySaveable.Yes)] public bool Enabled { get; set; } + [Serialize(false, IsPropertySaveable.Yes, description: "Should the character's active afflictions be updated (e.g. applying visual effects of the afflictions)")] + public bool UpdateAfflictions { get; set; } + [Serialize("", IsPropertySaveable.Yes)] public Identifier TargetTag { get; set; } @@ -35,9 +33,16 @@ namespace Barotrauma { if (target != null && target is Character character) { - character.GodMode = Enabled; + if (UpdateAfflictions) + { + character.CharacterHealth.Unkillable = Enabled; + } + else + { + character.GodMode = Enabled; + } } - } + } isFinished = true; } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/InventoryHighlightAction.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/InventoryHighlightAction.cs new file mode 100644 index 000000000..7eecbbbb2 --- /dev/null +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/InventoryHighlightAction.cs @@ -0,0 +1,33 @@ +namespace Barotrauma; + +partial class InventoryHighlightAction : EventAction +{ + [Serialize("", IsPropertySaveable.Yes)] + public Identifier TargetTag { get; set; } + + [Serialize("", IsPropertySaveable.Yes)] + public Identifier ItemIdentifier { get; set; } + + [Serialize(-1, IsPropertySaveable.Yes)] + public int ItemContainerIndex { get; set; } + + [Serialize(false, IsPropertySaveable.Yes)] + public bool Recursive { get; set; } + + private bool isFinished; + + public InventoryHighlightAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element) { } + + public override void Update(float deltaTime) + { + if (isFinished) { return; } + UpdateProjSpecific(); + isFinished = true; + } + + partial void UpdateProjSpecific(); + + public override bool IsFinished(ref string goToLabel) => isFinished; + + public override void Reset() => isFinished = false; +} \ No newline at end of file diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/MessageBoxAction.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/MessageBoxAction.cs index 2056c9656..2834b8b84 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/MessageBoxAction.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/MessageBoxAction.cs @@ -2,7 +2,7 @@ namespace Barotrauma { partial class MessageBoxAction : EventAction { - public enum ActionType { Create, Close } + public enum ActionType { Create, ConnectObjective, Close, Clear } [Serialize(ActionType.Create, IsPropertySaveable.Yes)] public ActionType Type { get; set; } @@ -51,7 +51,13 @@ namespace Barotrauma private bool isFinished = false; - public MessageBoxAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element) { } + public MessageBoxAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element) + { + if (Identifier.IsEmpty) + { + Identifier = element.GetAttributeIdentifier("id", Identifier.Empty); + } + } public override void Update(float deltaTime) { diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/MissionAction.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/MissionAction.cs index ff3d4d9bb..2c298853d 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/MissionAction.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/MissionAction.cs @@ -55,7 +55,7 @@ namespace Barotrauma if (GameMain.GameSession.GameMode is CampaignMode campaign) { - MissionPrefab prefab = null; + Mission unlockedMission = null; var unlockLocation = FindUnlockLocation(); if (unlockLocation == null && CreateLocationIfNotFound) { @@ -72,27 +72,34 @@ namespace Barotrauma { if (!MissionIdentifier.IsEmpty) { - prefab = unlockLocation.UnlockMissionByIdentifier(MissionIdentifier); + unlockedMission = unlockLocation.UnlockMissionByIdentifier(MissionIdentifier); } else if (!MissionTag.IsEmpty) { - prefab = unlockLocation.UnlockMissionByTag(MissionTag); + unlockedMission = unlockLocation.UnlockMissionByTag(MissionTag); } if (campaign is MultiPlayerCampaign mpCampaign) { mpCampaign.IncrementLastUpdateIdForFlag(MultiPlayerCampaign.NetFlags.MapAndMissions); } - if (prefab != null) + if (unlockedMission != null) { - DebugConsole.NewMessage($"Unlocked mission \"{prefab.Name}\" in the location \"{unlockLocation.Name}\"."); - #if CLIENT - new GUIMessageBox(string.Empty, TextManager.GetWithVariable("missionunlocked", "[missionname]", prefab.Name), - Array.Empty(), type: GUIMessageBox.Type.InGame, icon: prefab.Icon, relativeSize: new Vector2(0.3f, 0.15f), minSize: new Point(512, 128)) + if (unlockedMission.Locations[0] == unlockedMission.Locations[1] || unlockedMission.Locations[1] ==null) { - IconColor = prefab.IconColor + DebugConsole.NewMessage($"Unlocked mission \"{unlockedMission.Name}\" in the location \"{unlockLocation.Name}\"."); + } + else + { + DebugConsole.NewMessage($"Unlocked mission \"{unlockedMission.Name}\" in the connection from \"{unlockedMission.Locations[0].Name}\" to \"{unlockedMission.Locations[1].Name}\"."); + } +#if CLIENT + new GUIMessageBox(string.Empty, TextManager.GetWithVariable("missionunlocked", "[missionname]", unlockedMission.Name), + Array.Empty(), type: GUIMessageBox.Type.InGame, icon: unlockedMission.Prefab.Icon, relativeSize: new Vector2(0.3f, 0.15f), minSize: new Point(512, 128)) + { + IconColor = unlockedMission.Prefab.IconColor }; - #else - NotifyMissionUnlock(prefab); +#else + NotifyMissionUnlock(unlockedMission); #endif } } @@ -138,16 +145,17 @@ namespace Barotrauma { return $"{ToolBox.GetDebugSymbol(isFinished)} {nameof(MissionAction)} -> ({(MissionIdentifier.IsEmpty ? MissionTag : MissionIdentifier)})"; } - + #if SERVER - private void NotifyMissionUnlock(MissionPrefab prefab) + private void NotifyMissionUnlock(Mission mission) { foreach (Client client in GameMain.Server.ConnectedClients) { IWriteMessage outmsg = new WriteOnlyMessage(); outmsg.WriteByte((byte)ServerPacketHeader.EVENTACTION); outmsg.WriteByte((byte)EventManager.NetworkEventType.MISSION); - outmsg.WriteIdentifier(prefab.Identifier); + outmsg.WriteIdentifier(mission.Prefab.Identifier); + outmsg.WriteString(mission.Name.Value); GameMain.Server.ServerPeer.Send(outmsg, client.Connection, DeliveryMethod.Reliable); } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/NPCChangeTeamAction.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/NPCChangeTeamAction.cs index 90e6eb540..143563584 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/NPCChangeTeamAction.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/NPCChangeTeamAction.cs @@ -16,6 +16,9 @@ namespace Barotrauma [Serialize(false, IsPropertySaveable.Yes)] public bool AddToCrew { get; set; } + [Serialize(false, IsPropertySaveable.Yes)] + public bool RemoveFromCrew { get; set; } + private bool isFinished = false; public NPCChangeTeamAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element) { } @@ -35,34 +38,47 @@ namespace Barotrauma if (AddToCrew && (TeamTag == CharacterTeamType.Team1 || TeamTag == CharacterTeamType.Team2)) { npc.Info.StartItemsGiven = true; - GameMain.GameSession.CrewManager.AddCharacter(npc); + ChangeItemTeam(Submarine.MainSub, true); + if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsServer) + { + GameMain.NetworkMember.CreateEntityEvent(npc, new Character.AddToCrewEventData(TeamTag, npc.Inventory.AllItems)); + } + } + else if (RemoveFromCrew && (npc.TeamID == CharacterTeamType.Team1 || npc.TeamID == CharacterTeamType.Team2)) + { + npc.Info.StartItemsGiven = true; + GameMain.GameSession.CrewManager.RemoveCharacter(npc, removeInfo: true); + var sub = Submarine.Loaded.FirstOrDefault(s => s.TeamID == TeamTag); + ChangeItemTeam(sub, false); + if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsServer) + { + GameMain.NetworkMember.CreateEntityEvent(npc, new Character.RemoveFromCrewEventData(TeamTag, npc.Inventory.AllItems)); + } + } + + void ChangeItemTeam(Submarine sub, bool allowStealing) + { foreach (Item item in npc.Inventory.AllItems) { - item.AllowStealing = true; - var wifiComponent = item.GetComponent(); - if (wifiComponent != null) + item.AllowStealing = allowStealing; + if (item.GetComponent() is { } wifiComponent) { wifiComponent.TeamID = TeamTag; } - var idCard = item.GetComponent(); - if (idCard != null) + if (item.GetComponent() is { } idCard) { idCard.TeamID = TeamTag; idCard.SubmarineSpecificID = 0; } } - - WayPoint subWaypoint = - WayPoint.WayPointList.Find(wp => wp.Submarine == Submarine.MainSub && wp.SpawnType == SpawnType.Human && wp.AssignedJob == npc.Info.Job?.Prefab) ?? - WayPoint.WayPointList.Find(wp => wp.Submarine == Submarine.MainSub && wp.SpawnType == SpawnType.Human); + WayPoint subWaypoint = + WayPoint.WayPointList.Find(wp => wp.Submarine == sub && wp.SpawnType == SpawnType.Human && wp.AssignedJob == npc.Info.Job?.Prefab) ?? + WayPoint.WayPointList.Find(wp => wp.Submarine == sub && wp.SpawnType == SpawnType.Human); if (subWaypoint != null) { npc.GiveIdCardTags(subWaypoint, createNetworkEvent: true); } -#if SERVER - GameMain.NetworkMember.CreateEntityEvent(npc, new Character.AddToCrewEventData(TeamTag, npc.Inventory.AllItems)); -#endif } } isFinished = true; diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/NPCFollowAction.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/NPCFollowAction.cs index 7cc2f28ef..cee49e531 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/NPCFollowAction.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/NPCFollowAction.cs @@ -1,8 +1,5 @@ -using Barotrauma.Extensions; -using Microsoft.Xna.Framework; using System.Collections.Generic; using System.Linq; -using System.Xml.Linq; namespace Barotrauma { @@ -17,6 +14,12 @@ namespace Barotrauma [Serialize(true, IsPropertySaveable.Yes)] public bool Follow { get; set; } + [Serialize(-1, IsPropertySaveable.Yes)] + public int MaxTargets { get; set; } + + [Serialize(true, IsPropertySaveable.Yes)] + public bool AbandonOnReset { get; set; } + private bool isFinished = false; public NPCFollowAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element) { } @@ -32,6 +35,7 @@ namespace Barotrauma target = ParentEvent.GetTargets(TargetTag).FirstOrDefault(); if (target == null) { return; } + int targetCount = 0; affectedNpcs = ParentEvent.GetTargets(NPCTag).Where(c => c is Character).Select(c => c as Character).ToList(); foreach (var npc in affectedNpcs) { @@ -56,6 +60,11 @@ namespace Barotrauma } } } + targetCount++; + if (MaxTargets > -1 && targetCount >= MaxTargets) + { + break; + } } isFinished = true; } @@ -67,11 +76,11 @@ namespace Barotrauma public override void Reset() { - if (affectedNpcs != null && target != null) + if (affectedNpcs != null && target != null && AbandonOnReset) { foreach (var npc in affectedNpcs) { - if (npc.Removed || !(npc.AIController is HumanAIController humanAiController)) { continue; } + if (npc.Removed || npc.AIController is not HumanAIController humanAiController) { continue; } foreach (var goToObjective in humanAiController.ObjectiveManager.GetActiveObjectives()) { if (goToObjective.Target == target) diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/NPCOperateItemAction.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/NPCOperateItemAction.cs new file mode 100644 index 000000000..b39eb465f --- /dev/null +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/NPCOperateItemAction.cs @@ -0,0 +1,122 @@ +using System.Collections.Generic; +using System.Linq; + +namespace Barotrauma +{ + class NPCOperateItemAction : EventAction + { + [Serialize("", IsPropertySaveable.Yes)] + public Identifier NPCTag { get; set; } + + [Serialize("", IsPropertySaveable.Yes)] + public Identifier TargetTag { get; set; } + + [Serialize("", IsPropertySaveable.Yes)] + public Identifier ItemComponentName { get; set; } + + [Serialize("", IsPropertySaveable.Yes)] + public Identifier OrderOption { get; set; } + + [Serialize(false, IsPropertySaveable.Yes)] + public bool RequireEquip { get; set; } + + [Serialize(true, IsPropertySaveable.Yes)] + public bool Operate { get; set; } + + [Serialize(-1, IsPropertySaveable.Yes)] + public int MaxTargets { get; set; } + + [Serialize(true, IsPropertySaveable.Yes)] + public bool AbandonOnReset { get; set; } + + private bool isFinished = false; + + public NPCOperateItemAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element) { } + + + private List affectedNpcs = null; + private Item target = null; + + public override void Update(float deltaTime) + { + if (isFinished) { return; } + + target = ParentEvent.GetTargets(TargetTag).FirstOrDefault() as Item; + if (target == null) { return; } + + int targetCount = 0; + affectedNpcs = ParentEvent.GetTargets(NPCTag).Where(c => c is Character).Select(c => c as Character).ToList(); + foreach (var npc in affectedNpcs) + { + if (npc.AIController is not HumanAIController humanAiController) { continue; } + + if (Operate) + { + ItemComponentName = "Controller".ToIdentifier(); + var itemComponent = target.Components.FirstOrDefault(ic => ItemComponentName == ic.Name); + if (itemComponent == null) + { + DebugConsole.AddWarning($"Error in NPCOperateItemAction: could not find the component \"{ItemComponentName}\" in item \"{target.Name}\"."); + } + else + { + var newObjective = new AIObjectiveOperateItem(itemComponent, npc, humanAiController.ObjectiveManager, OrderOption, RequireEquip) + { + OverridePriority = 100.0f + }; + humanAiController.ObjectiveManager.AddObjective(newObjective); + humanAiController.ObjectiveManager.WaitTimer = 0.0f; + humanAiController.ObjectiveManager.Objectives.RemoveAll(o => o is AIObjectiveGoTo gotoOjective); + } + } + else + { + foreach (var objective in humanAiController.ObjectiveManager.Objectives) + { + if (objective is AIObjectiveOperateItem operateItemObjective && operateItemObjective.OperateTarget == target) + { + objective.Abandon = true; + } + } + } + targetCount++; + if (MaxTargets > -1 && targetCount >= MaxTargets) + { + break; + } + } + isFinished = true; + } + + public override bool IsFinished(ref string goTo) + { + return isFinished; + } + + public override void Reset() + { + if (affectedNpcs != null && target != null && AbandonOnReset) + { + foreach (var npc in affectedNpcs) + { + if (npc.Removed || npc.AIController is not HumanAIController humanAiController) { continue; } + foreach (var operateItemObjective in humanAiController.ObjectiveManager.GetActiveObjectives()) + { + if (operateItemObjective.OperateTarget == target) + { + operateItemObjective.Abandon = true; + } + } + } + target = null; + affectedNpcs = null; + } + isFinished = false; + } + + public override string ToDebugString() + { + return $"{ToolBox.GetDebugSymbol(isFinished)} {nameof(AIObjectiveOperateItem)} -> (NPCTag: {NPCTag.ColorizeObject()}, TargetTag: {TargetTag.ColorizeObject()}, Operate: {Operate.ColorizeObject()})"; + } + } +} \ No newline at end of file diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/NPCWaitAction.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/NPCWaitAction.cs index aa2bee231..fa3b3d2f8 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/NPCWaitAction.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/NPCWaitAction.cs @@ -29,7 +29,7 @@ namespace Barotrauma foreach (var npc in affectedNpcs) { - if (!(npc.AIController is HumanAIController humanAiController)) { continue; } + if (npc.AIController is not HumanAIController humanAiController) { continue; } if (Wait) { @@ -62,7 +62,7 @@ namespace Barotrauma { foreach (var npc in affectedNpcs) { - if (npc.Removed || !(npc.AIController is HumanAIController)) { continue; } + if (npc.Removed || npc.AIController is not HumanAIController) { continue; } if (gotoObjective != null) { gotoObjective.Abandon = true; diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/SpawnAction.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/SpawnAction.cs index 3bd798efd..657c6af21 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/SpawnAction.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/SpawnAction.cs @@ -60,6 +60,9 @@ namespace Barotrauma [Serialize(true, IsPropertySaveable.Yes, description: "If false, we won't spawn another character if one with the same identifier has already been spawned.")] public bool AllowDuplicates { get; set; } + [Serialize(100.0f, IsPropertySaveable.Yes)] + public float Offset { get; set; } + [Serialize("", IsPropertySaveable.Yes, "What outpost module tags does the entity prefer to spawn in.")] public string TargetModuleTags { @@ -127,7 +130,7 @@ namespace Barotrauma ISpatialEntity spawnPos = GetSpawnPos(); if (spawnPos != null) { - Entity.Spawner.AddCharacterToSpawnQueue(CharacterPrefab.HumanSpeciesName, OffsetSpawnPos(spawnPos.WorldPosition, 100.0f), humanPrefab.CreateCharacterInfo(), onSpawn: newCharacter => + Entity.Spawner.AddCharacterToSpawnQueue(CharacterPrefab.HumanSpeciesName, OffsetSpawnPos(spawnPos.WorldPosition, Offset), humanPrefab.CreateCharacterInfo(), onSpawn: newCharacter => { if (newCharacter == null) { return; } newCharacter.HumanPrefab = humanPrefab; @@ -162,7 +165,7 @@ namespace Barotrauma ISpatialEntity spawnPos = GetSpawnPos(); if (spawnPos != null) { - Entity.Spawner.AddCharacterToSpawnQueue(SpeciesName, OffsetSpawnPos(spawnPos.WorldPosition, 100.0f), onSpawn: newCharacter => + Entity.Spawner.AddCharacterToSpawnQueue(SpeciesName, OffsetSpawnPos(spawnPos.WorldPosition, Offset), onSpawn: newCharacter => { if (!TargetTag.IsEmpty && newCharacter != null) { @@ -208,7 +211,7 @@ namespace Barotrauma ISpatialEntity spawnPos = GetSpawnPos(); if (spawnPos != null) { - Entity.Spawner.AddItemToSpawnQueue(itemPrefab, OffsetSpawnPos(spawnPos.WorldPosition, 100.0f), onSpawned: onSpawned); + Entity.Spawner.AddItemToSpawnQueue(itemPrefab, OffsetSpawnPos(spawnPos.WorldPosition, Offset), onSpawned: onSpawned); } } else diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/TutorialIconAction.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/TutorialIconAction.cs index 317966346..a47d4e932 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/TutorialIconAction.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/TutorialIconAction.cs @@ -13,7 +13,7 @@ class TutorialIconAction : EventAction public Identifier TargetTag { get; set; } [Serialize("", IsPropertySaveable.Yes)] - public string IconStyle { get; set; } + public Identifier IconStyle { get; set; } private bool isFinished; @@ -33,7 +33,7 @@ class TutorialIconAction : EventAction } else if(Type == ActionType.Remove) { - tutorialMode.Tutorial?.Icons.RemoveAll(i => i.entity == target && i.iconStyle.Equals(IconStyle, System.StringComparison.OrdinalIgnoreCase)); + tutorialMode.Tutorial?.Icons.RemoveAll(i => i.entity == target && i.iconStyle == IconStyle); } else if (Type == ActionType.RemoveTarget) { @@ -41,7 +41,7 @@ class TutorialIconAction : EventAction } else if (Type == ActionType.RemoveIcon) { - tutorialMode.Tutorial?.Icons.RemoveAll(i => i.iconStyle.Equals(IconStyle, System.StringComparison.OrdinalIgnoreCase)); + tutorialMode.Tutorial?.Icons.RemoveAll(i => i.iconStyle == IconStyle); } else if (Type == ActionType.Clear) { diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/TutorialSegmentAction.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/TutorialSegmentAction.cs index b447875bc..587fb20a7 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/TutorialSegmentAction.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/TutorialSegmentAction.cs @@ -8,7 +8,7 @@ namespace Barotrauma public SegmentActionType Type { get; set; } [Serialize("", IsPropertySaveable.Yes)] - public Identifier Id { get; set; } + public Identifier Identifier { get; set; } [Serialize("", IsPropertySaveable.Yes)] public Identifier ObjectiveTag { get; set; } @@ -30,7 +30,13 @@ namespace Barotrauma private bool isFinished; - public TutorialSegmentAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element) { } + public TutorialSegmentAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element) + { + if (Identifier.IsEmpty) + { + Identifier = element.GetAttributeIdentifier("id", Identifier.Empty); + } + } public override void Update(float deltaTime) { diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/UIHighlightAction.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/UIHighlightAction.cs new file mode 100644 index 000000000..b990fdf66 --- /dev/null +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/UIHighlightAction.cs @@ -0,0 +1,62 @@ +namespace Barotrauma; + +partial class UIHighlightAction : EventAction +{ + public enum ElementId + { + None, + RepairButton, + PumpSpeedSlider, + PassiveSonarIndicator, + ActiveSonarIndicator, + SonarModeSwitch, + DirectionalSonarFrame, + SteeringModeSwitch, + MaintainPosTickBox, + AutoTempSwitch, + PowerButton, + FissionRateSlider, + TurbineOutputSlider, + DeconstructButton, + RechargeSpeedSlider, + CPRButton + } + + [Serialize(ElementId.None, IsPropertySaveable.Yes)] + public ElementId Id { get; set; } + + [Serialize("", IsPropertySaveable.Yes)] + public Identifier EntityIdentifier { get; set; } + + [Serialize(OrderCategory.Emergency, IsPropertySaveable.Yes)] + public OrderCategory OrderCategory { get; set; } + + [Serialize("", IsPropertySaveable.Yes)] + public Identifier OrderIdentifier { get; set; } + + [Serialize("", IsPropertySaveable.Yes)] + public Identifier OrderOption { get; set; } + + [Serialize("", IsPropertySaveable.Yes)] + public Identifier OrderTargetTag { get; set; } + + [Serialize(true, IsPropertySaveable.Yes)] + public bool Bounce { get; set; } + + private bool isFinished; + + public UIHighlightAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element) { } + + public override void Update(float deltaTime) + { + if (isFinished) { return; } + UpdateProjSpecific(); + isFinished = true; + } + + partial void UpdateProjSpecific(); + + public override bool IsFinished(ref string goToLabel) => isFinished; + + public override void Reset() => isFinished = false; +} \ No newline at end of file diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/AbandonedOutpostMission.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/AbandonedOutpostMission.cs index 9665b6b90..7e4da0ea5 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/AbandonedOutpostMission.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/AbandonedOutpostMission.cs @@ -329,21 +329,14 @@ namespace Barotrauma } - public override void End() + protected override bool DetermineCompleted() { - completed = State > 0 && State != HostagesKilledState; - if (completed) - { - if (Prefab.LocationTypeChangeOnCompleted != null) - { - ChangeLocationType(Prefab.LocationTypeChangeOnCompleted); - } - GiveReward(); - } - else - { - failed = requireRescue.Any(r => r.Removed || r.IsDead); - } + return State > 0 && State != HostagesKilledState; + } + + protected override void EndMissionSpecific(bool completed) + { + failed = !completed && requireRescue.Any(r => r.Removed || r.IsDead); } } } \ No newline at end of file diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/AlienRuinMission.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/AlienRuinMission.cs index 2ed692fa5..2bfb34391 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/AlienRuinMission.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/AlienRuinMission.cs @@ -156,22 +156,21 @@ namespace Barotrauma return true; } - private bool IsItemDestroyed(Item item) => item == null || item.Removed || item.Condition <= 0.0f; + private static bool IsItemDestroyed(Item item) => item == null || item.Removed || item.Condition <= 0.0f; - private bool IsEnemyDefeated(Character enemy) => enemy == null ||enemy.Removed || enemy.IsDead; + private static bool IsEnemyDefeated(Character enemy) => enemy == null ||enemy.Removed || enemy.IsDead; - public override void End() + protected override bool DetermineCompleted() { bool exitingLevel = GameMain.GameSession?.GameMode is CampaignMode campaign ? campaign.GetAvailableTransition() != CampaignMode.TransitionType.None : Submarine.MainSub is { } sub && (sub.AtEndExit || sub.AtStartExit); - if (State > 0 && exitingLevel) - { - GiveReward(); - completed = true; - } + return State > 0 && exitingLevel; + } + protected override void EndMissionSpecific(bool completed) + { failed = !completed && State > 0; } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/BeaconMission.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/BeaconMission.cs index d2770b68b..6e46b3c5b 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/BeaconMission.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/BeaconMission.cs @@ -163,20 +163,16 @@ namespace Barotrauma #endif } - public override void End() + protected override bool DetermineCompleted() { - completed = level.CheckBeaconActive(); - if (completed) + return level.CheckBeaconActive(); + } + + protected override void EndMissionSpecific(bool completed) + { + if (completed && level.LevelData != null) { - if (Prefab.LocationTypeChangeOnCompleted != null) - { - ChangeLocationType(Prefab.LocationTypeChangeOnCompleted); - } - GiveReward(); - if (level.LevelData != null) - { - level.LevelData.IsBeaconActive = true; - } + level.LevelData.IsBeaconActive = true; } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/CargoMission.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/CargoMission.cs index 58aae000c..7ead29659 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/CargoMission.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/CargoMission.cs @@ -219,7 +219,7 @@ namespace Barotrauma else if (sub != this.currentSub || missionsChanged) { this.currentSub = sub; - this.nextRoundSubInfo = sub.Info; + this.nextRoundSubInfo = sub?.Info; DetermineCargo(); } @@ -294,22 +294,21 @@ namespace Barotrauma } } - public override void End() + protected override bool DetermineCompleted() { if (Submarine.MainSub != null && Submarine.MainSub.AtEndExit) { int deliveredItemCount = items.Count(it => IsItemDelivered(it)); if (deliveredItemCount / (float)items.Count >= requiredDeliveryAmount) { - GiveReward(); - completed = true; - if (Prefab.LocationTypeChangeOnCompleted != null) - { - ChangeLocationType(Prefab.LocationTypeChangeOnCompleted); - } + return true; } } + return false; + } + protected override void EndMissionSpecific(bool completed) + { foreach (Item item in items) { if (!item.Removed) { item.Remove(); } @@ -318,7 +317,7 @@ namespace Barotrauma failed = !completed; } - private bool IsItemDelivered(Item item) + private static bool IsItemDelivered(Item item) { if (item.Removed || item.Condition <= 0.0f || Submarine.MainSub == null) { return false; } var submarine = item.Submarine ?? item.GetRootContainer()?.Submarine; diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/CombatMission.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/CombatMission.cs index 4812d5085..917b31d90 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/CombatMission.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/CombatMission.cs @@ -113,15 +113,9 @@ namespace Barotrauma #endif } - public override void End() + protected override bool DetermineCompleted() { - if (GameMain.NetworkMember == null) { return; } - - if (Winner != CharacterTeamType.None) - { - GiveReward(); - completed = true; - } + return Winner != CharacterTeamType.None; } } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/EscortMission.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/EscortMission.cs index e94c4432c..fe7c3ff84 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/EscortMission.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/EscortMission.cs @@ -305,7 +305,7 @@ namespace Barotrauma return character.LockHands && character.HasTeamChange(TerroristTeamChangeIdentifier); } - public override void End() + protected override bool DetermineCompleted() { if (Submarine.MainSub != null && Submarine.MainSub.AtEndExit) { @@ -321,11 +321,14 @@ namespace Barotrauma if (friendliesSurvived && !terroristsSurvived && !vipDied) { - GiveReward(); - completed = true; + return true; } } + return false; + } + protected override void EndMissionSpecific(bool completed) + { if (!IsClient) { foreach (Character character in characters) diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/GoToMission.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/GoToMission.cs index cb8508f9d..f0fa3a328 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/GoToMission.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/GoToMission.cs @@ -1,6 +1,4 @@ -using Barotrauma.Networking; - -namespace Barotrauma +namespace Barotrauma { partial class GoToMission : Mission { @@ -11,7 +9,22 @@ namespace Barotrauma protected override void UpdateMissionSpecific(float deltaTime) { - State = 1; + if (Level.Loaded?.Type == LevelData.LevelType.Outpost) + { + State = 1; + } + } + + protected override bool DetermineCompleted() + { + if (Level.Loaded?.Type == LevelData.LevelType.Outpost) + { + return true; + } + else + { + return Submarine.MainSub is { AtEndExit: true }; + } } } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/MineralMission.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/MineralMission.cs index d0a99fe80..0d136f64f 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/MineralMission.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/MineralMission.cs @@ -131,13 +131,13 @@ namespace Barotrauma foreach ((Identifier identifier, ResourceCluster cluster) in resourceClusters) { - if (!(MapEntityPrefab.FindByIdentifier(identifier) is ItemPrefab prefab)) + if (MapEntityPrefab.FindByIdentifier(identifier) is not ItemPrefab prefab) { DebugConsole.ThrowError($"Error in MineralMission: couldn't find an item prefab (identifier: \"{identifier}\")"); continue; } - var spawnedResources = level.GenerateMissionResources(prefab, cluster.Amount, positionType, out float rotation); + var spawnedResources = level.GenerateMissionResources(prefab, cluster.Amount, positionType, out float rotation, caves); if (spawnedResources.Count < cluster.Amount) { DebugConsole.ThrowError($"Error in MineralMission: spawned only {spawnedResources.Count}/{cluster.Amount} of {prefab.Name}"); @@ -181,14 +181,16 @@ namespace Barotrauma } } - public override void End() + protected override bool DetermineCompleted() { - if (EnoughHaveBeenCollected()) + return EnoughHaveBeenCollected(); + } + + protected override void EndMissionSpecific(bool completed) + { + failed = !completed && state > 0; + if (completed) { - if (Prefab.LocationTypeChangeOnCompleted != null) - { - ChangeLocationType(Prefab.LocationTypeChangeOnCompleted); - } if (!IsClient) { // When mission is completed successfully, half of the resources will be removed from the player (i.e. given to the outpost as a part of the mission) @@ -198,7 +200,7 @@ namespace Barotrauma if (relevantLevelResources.TryGetValue(identifier, out var availableResources)) { var collectedResources = availableResources.Where(HasBeenCollected); - if (collectedResources.Count() < 1) { continue; } + if (!collectedResources.Any()) { continue; } int handoverCount = (int)MathF.Round(resourceHandoverAmount * collectedResources.Count()); for (int i = 0; i < handoverCount; i++) { @@ -211,8 +213,6 @@ namespace Barotrauma resource.Remove(); } } - GiveReward(); - completed = true; } foreach (var kvp in spawnedResources) { @@ -227,7 +227,6 @@ namespace Barotrauma spawnedResources.Clear(); relevantLevelResources.Clear(); missionClusterPositions.Clear(); - failed = !completed && state > 0; } private void FindRelevantLevelResources() diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/Mission.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/Mission.cs index 497992319..138b3b9f5 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/Mission.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/Mission.cs @@ -13,7 +13,8 @@ namespace Barotrauma abstract partial class Mission { public readonly MissionPrefab Prefab; - protected bool completed, failed; + private bool completed; + protected bool failed; protected Level level; @@ -36,7 +37,9 @@ namespace Barotrauma } } - protected bool IsClient => GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient; + protected static bool IsClient => GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient; + + private readonly CheckDataAction completeCheckDataAction; public readonly ImmutableArray Headers; public readonly ImmutableArray Messages; @@ -156,6 +159,12 @@ namespace Barotrauma Locations = locations; + var endConditionElement = prefab.ConfigElement.GetChildElement(nameof(completeCheckDataAction)); + if (endConditionElement != null) + { + completeCheckDataAction = new CheckDataAction(endConditionElement, $"Mission ({prefab.Identifier.ToString()})"); + } + for (int n = 0; n < 2; n++) { string locationName = $"‖color:gui.orange‖{locations[n].Name}‖end‖"; @@ -334,19 +343,27 @@ namespace Barotrauma /// /// End the mission and give a reward if it was completed successfully /// - public virtual void End() + public void End() { - completed = true; + completed = + DetermineCompleted() && + (completeCheckDataAction == null ||completeCheckDataAction.GetSuccess()); if (Prefab.LocationTypeChangeOnCompleted != null) { ChangeLocationType(Prefab.LocationTypeChangeOnCompleted); } GiveReward(); + EndMissionSpecific(completed); } - public void GiveReward() + protected abstract bool DetermineCompleted(); + + protected virtual void EndMissionSpecific(bool completed) { } + + + private void GiveReward() { - if (!(GameMain.GameSession.GameMode is CampaignMode campaign)) { return; } + if (GameMain.GameSession.GameMode is not CampaignMode campaign) { return; } int reward = GetReward(Submarine.MainSub); float baseExperienceGain = reward * 0.09f; diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/MissionPrefab.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/MissionPrefab.cs index 1be2ee4d3..92f08baec 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/MissionPrefab.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/MissionPrefab.cs @@ -146,14 +146,24 @@ namespace Barotrauma tags = element.GetAttributeStringArray("tags", Array.Empty(), convertToLowerInvariant: true); - Name = - TextManager.Get($"MissionName.{TextIdentifier}") - .Fallback(TextManager.Get(element.GetAttributeString("name", ""))) - .Fallback(element.GetAttributeString("name", "")); - Description = - TextManager.Get($"MissionDescription.{TextIdentifier}") - .Fallback(TextManager.Get(element.GetAttributeString("description", ""))) - .Fallback(element.GetAttributeString("description", "")); + string nameTag = element.GetAttributeString("name", ""); + Name = TextManager.Get($"MissionName.{TextIdentifier}"); + if (!string.IsNullOrEmpty(nameTag)) + { + Name = Name + .Fallback(TextManager.Get(nameTag)) + .Fallback(nameTag); + } + + string descriptionTag = element.GetAttributeString("description", ""); + Description = + TextManager.Get($"MissionDescription.{TextIdentifier}"); + if (!string.IsNullOrEmpty(descriptionTag)) + { + Description = Description + .Fallback(TextManager.Get(descriptionTag)) + .Fallback(descriptionTag); + } Reward = element.GetAttributeInt("reward", 1); AllowRetry = element.GetAttributeBool("allowretry", false); @@ -167,23 +177,35 @@ namespace Barotrauma Difficulty = Math.Clamp(difficulty, MinDifficulty, MaxDifficulty); } - SuccessMessage = - TextManager.Get($"MissionSuccess.{TextIdentifier}") - .Fallback(TextManager.Get(element.GetAttributeString("successmessage", ""))) - .Fallback(element.GetAttributeString("successmessage", "Mission completed successfully")); - FailureMessage = - TextManager.Get($"MissionFailure.{TextIdentifier}") - .Fallback(TextManager.Get(element.GetAttributeString("missionfailed", ""))) - .Fallback(TextManager.Get("missionfailed")) - .Fallback(GameSettings.CurrentConfig.Language == TextManager.DefaultLanguage ? element.GetAttributeString("failuremessage", "") : ""); + string successMessageTag = element.GetAttributeString("successmessage", ""); + SuccessMessage = TextManager.Get($"MissionSuccess.{TextIdentifier}"); + if (!string.IsNullOrEmpty(successMessageTag)) + { + SuccessMessage = SuccessMessage + .Fallback(TextManager.Get(successMessageTag)) + .Fallback(successMessageTag); + } + SuccessMessage = SuccessMessage.Fallback(TextManager.Get("missioncompleted")); + + string failureMessageTag = element.GetAttributeString("failuremessage", ""); + FailureMessage = TextManager.Get($"MissionFailure.{TextIdentifier}"); + if (!string.IsNullOrEmpty(failureMessageTag)) + { + FailureMessage = FailureMessage + .Fallback(TextManager.Get(failureMessageTag)) + .Fallback(failureMessageTag); + } + FailureMessage = FailureMessage.Fallback(TextManager.Get("missionfailed")); string sonarLabelTag = element.GetAttributeString("sonarlabel", ""); - - SonarLabel = + SonarLabel = TextManager.Get($"MissionSonarLabel.{sonarLabelTag}") .Fallback(TextManager.Get(sonarLabelTag)) - .Fallback(TextManager.Get($"MissionSonarLabel.{TextIdentifier}")) - .Fallback(element.GetAttributeString("sonarlabel", "")); + .Fallback(TextManager.Get($"MissionSonarLabel.{TextIdentifier}")); + if (!string.IsNullOrEmpty(sonarLabelTag)) + { + SonarLabel = SonarLabel.Fallback(sonarLabelTag); + } SonarIconIdentifier = element.GetAttributeIdentifier("sonaricon", ""); diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/MonsterMission.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/MonsterMission.cs index eb296dad9..9b3641502 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/MonsterMission.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/MonsterMission.cs @@ -223,26 +223,26 @@ namespace Barotrauma break; } } - - public override void End() + + protected override bool DetermineCompleted() + { + return state > 0; + } + + protected override void EndMissionSpecific(bool completed) { tempSonarPositions.Clear(); monsters.Clear(); - if (State < 1) { return; } - - if (Prefab.LocationTypeChangeOnCompleted != null) + if (completed) { - ChangeLocationType(Prefab.LocationTypeChangeOnCompleted); - } - GiveReward(); - completed = true; - if (level?.LevelData != null && Prefab.Tags.Any(t => t.Equals("huntinggrounds", StringComparison.OrdinalIgnoreCase))) - { - level.LevelData.HasHuntingGrounds = false; + if (level?.LevelData != null && Prefab.Tags.Contains("huntinggrounds")) + { + level.LevelData.HasHuntingGrounds = false; + } } } - public bool IsEliminated(Character enemy) => + public static bool IsEliminated(Character enemy) => enemy == null || enemy.Removed || enemy.IsDead || diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/NestMission.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/NestMission.cs index 5a85ee491..bc71d49dc 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/NestMission.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/NestMission.cs @@ -305,20 +305,13 @@ namespace Barotrauma return true; } - public override void End() + protected override bool DetermineCompleted() + { + return AllItemsDestroyedOrRetrieved(); + } + + protected override void EndMissionSpecific(bool completed) { - if (AllItemsDestroyedOrRetrieved()) - { - GiveReward(); - completed = true; - if (completed) - { - if (Prefab.LocationTypeChangeOnCompleted != null) - { - ChangeLocationType(Prefab.LocationTypeChangeOnCompleted); - } - } - } foreach (Item item in items) { if (item != null && !item.Removed) diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/PirateMission.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/PirateMission.cs index 20d26fbf5..ff33e7ec9 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/PirateMission.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/PirateMission.cs @@ -401,13 +401,13 @@ namespace Barotrauma return character == null || character.Removed || character.Submarine == null || (character.LockHands && character.Submarine == Submarine.MainSub) || character.IsIncapacitated; } - public override void End() + protected override bool DetermineCompleted() + { + return state == 2; + } + + protected override void EndMissionSpecific(bool completed) { - if (state == 2) - { - GiveReward(); - completed = true; - } characters.Clear(); characterItems.Clear(); failed = !completed; diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/SalvageMission.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/SalvageMission.cs index 858e8a74d..0d1b41b98 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/SalvageMission.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/SalvageMission.cs @@ -242,7 +242,7 @@ namespace Barotrauma Submarine parentSub = item.CurrentHull?.Submarine ?? item.GetRootInventoryOwner()?.Submarine; if (parentSub == null || parentSub.Info.Type != SubmarineType.Player) { - return; + return; } } State = 1; @@ -254,23 +254,16 @@ namespace Barotrauma } } - public override void End() + protected override bool DetermineCompleted() { var root = item?.GetRootContainer() ?? item; - if (root?.CurrentHull?.Submarine == null || (!root.CurrentHull.Submarine.AtEndExit && !root.CurrentHull.Submarine.AtStartExit) || item.Removed) - { - return; - } - - if (Prefab.LocationTypeChangeOnCompleted != null) - { - ChangeLocationType(Prefab.LocationTypeChangeOnCompleted); - } + return root?.CurrentHull?.Submarine != null && (root.CurrentHull.Submarine.AtEndExit || root.CurrentHull.Submarine.AtStartExit) && !item.Removed; + } + protected override void EndMissionSpecific(bool completed) + { item?.Remove(); item = null; - GiveReward(); - completed = true; failed = !completed && state > 0; } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/ScanMission.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/ScanMission.cs index 132767396..a59c69f8d 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/ScanMission.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/ScanMission.cs @@ -247,24 +247,9 @@ namespace Barotrauma } } - public override void End() + protected override bool DetermineCompleted() { - if (State == 2 && AllScannersReturned()) - { - GiveReward(); - completed = true; - } - foreach (var scanner in scanners) - { - if (scanner.Item != null && !scanner.Item.Removed) - { - scanner.OnScanStarted -= OnScanStarted; - scanner.OnScanCompleted -= OnScanCompleted; - scanner.Item.Remove(); - } - } - Reset(); - failed = !completed && state > 0; + return State == 2 && AllScannersReturned(); bool AllScannersReturned() { @@ -285,5 +270,20 @@ namespace Barotrauma return true; } } + + protected override void EndMissionSpecific(bool completed) + { + foreach (var scanner in scanners) + { + if (scanner.Item != null && !scanner.Item.Removed) + { + scanner.OnScanStarted -= OnScanStarted; + scanner.OnScanCompleted -= OnScanCompleted; + scanner.Item.Remove(); + } + } + Reset(); + failed = !completed && state > 0; + } } } \ No newline at end of file diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/MonsterEvent.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/MonsterEvent.cs index e76ab4c70..1bdbade40 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Events/MonsterEvent.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/MonsterEvent.cs @@ -11,7 +11,7 @@ namespace Barotrauma { public readonly Identifier SpeciesName; public readonly int MinAmount, MaxAmount; - private List monsters; + private readonly List monsters = new List(); private readonly float scatter; private readonly float offset; @@ -30,7 +30,7 @@ namespace Barotrauma public readonly int MaxAmountPerLevel = int.MaxValue; - public List Monsters => monsters; + public IReadOnlyList Monsters => monsters; public Vector2? SpawnPos => spawnPos; public bool SpawnPending => spawnPending; @@ -115,7 +115,7 @@ namespace Barotrauma } } - private Submarine GetReferenceSub() + private static Submarine GetReferenceSub() { return EventManager.GetRefEntity() as Submarine ?? Submarine.MainSub; } @@ -147,7 +147,7 @@ namespace Barotrauma DebugConsole.NewMessage("Initialized MonsterEvent (" + SpeciesName + ")", Color.White); } - monsters = new List(); + monsters.Clear(); //+1 because Range returns an integer less than the max value int amount = Rand.Range(MinAmount, MaxAmount + 1); diff --git a/Barotrauma/BarotraumaShared/SharedSource/GameSession/CargoManager.cs b/Barotrauma/BarotraumaShared/SharedSource/GameSession/CargoManager.cs index cab2c43d6..6fa21d9ae 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/GameSession/CargoManager.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/GameSession/CargoManager.cs @@ -80,7 +80,7 @@ namespace Barotrauma { if (ID != Entity.NullEntityID) { - DebugConsole.ShowError("Error setting SoldItem.ID: ID has already been set and should not be changed."); + DebugConsole.LogError("Error setting SoldItem.ID: ID has already been set and should not be changed."); return; } ID = id; @@ -128,7 +128,7 @@ namespace Barotrauma { if (Item != null) { - DebugConsole.ShowError($"Trying to set SoldEntity.Item, but it's already set!\n{Environment.StackTrace.CleanupStackTrace()}"); + DebugConsole.LogError($"Trying to set SoldEntity.Item, but it's already set!\n{Environment.StackTrace.CleanupStackTrace()}"); return; } Item = item; diff --git a/Barotrauma/BarotraumaShared/SharedSource/GameSession/CrewManager.cs b/Barotrauma/BarotraumaShared/SharedSource/GameSession/CrewManager.cs index 8671f08d3..06ab5566e 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/GameSession/CrewManager.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/GameSession/CrewManager.cs @@ -198,6 +198,34 @@ namespace Barotrauma } } + /// + /// Remove the character from the crew (and crew menus). + /// + /// The character to remove + /// If the character info is also removed, the character will not be visible in the round summary. + public void RemoveCharacter(Character character, bool removeInfo = false, bool resetCrewListIndex = true) + { + if (character == null) + { + DebugConsole.ThrowError("Tried to remove a null character from CrewManager.\n" + Environment.StackTrace.CleanupStackTrace()); + return; + } + characters.Remove(character); + if (removeInfo) + { + characterInfos.Remove(character.Info); +#if CLIENT + RemoveCharacterFromCrewList(character); +#endif + } +#if CLIENT + if (resetCrewListIndex) + { + ResetCrewListIndex(character); + } +#endif + } + public void AddCharacterInfo(CharacterInfo characterInfo) { if (characterInfos.Contains(characterInfo)) diff --git a/Barotrauma/BarotraumaShared/SharedSource/GameSession/GameModes/Tutorials/TutorialPrefab.cs b/Barotrauma/BarotraumaShared/SharedSource/GameSession/GameModes/Tutorials/TutorialPrefab.cs index ad6dec773..a9942470b 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/GameSession/GameModes/Tutorials/TutorialPrefab.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/GameSession/GameModes/Tutorials/TutorialPrefab.cs @@ -27,6 +27,8 @@ namespace Barotrauma public readonly Identifier EventIdentifier; + public readonly Sprite Banner; + public TutorialPrefab(ContentFile file, ContentXElement element) : base(file, element.GetAttributeIdentifier("identifier", "")) { Order = element.GetAttributeInt("order", int.MaxValue); @@ -50,6 +52,12 @@ namespace Barotrauma StartingItemTags = ImmutableArray.Empty; } + var bannerElement = element.GetChildElement("banner"); + if (bannerElement != null) + { + Banner = new Sprite(bannerElement, lazyLoad: true); + } + EventIdentifier = element.GetChildElement("scriptedevent")?.GetAttributeIdentifier("identifier", "") ?? Identifier.Empty; } diff --git a/Barotrauma/BarotraumaShared/SharedSource/GameSession/UpgradeManager.cs b/Barotrauma/BarotraumaShared/SharedSource/GameSession/UpgradeManager.cs index 37d8c9369..a35b86654 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/GameSession/UpgradeManager.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/GameSession/UpgradeManager.cs @@ -412,14 +412,14 @@ namespace Barotrauma #endif } - public List GetLinkedItemsToSwap(Item item) + public static ICollection GetLinkedItemsToSwap(Item item) { - List linkedItems = new List() { item }; + HashSet linkedItems = new HashSet() { item }; foreach (MapEntity linkedEntity in item.linkedTo) { foreach (MapEntity secondLinkedEntity in linkedEntity.linkedTo) { - if (!(secondLinkedEntity is Item linkedItem) || linkedItem == item) { continue; } + if (secondLinkedEntity is not Item linkedItem || linkedItem == item) { continue; } if (linkedItem.AllowSwapping && linkedItem.Prefab.SwappableItem != null && (linkedItem.Prefab.SwappableItem.CanBeBought || item.Prefab.SwappableItem.ReplacementOnUninstall == ((MapEntity)linkedItem).Prefab.Identifier) && linkedItem.Prefab.SwappableItem.SwapIdentifier.Equals(item.Prefab.SwappableItem.SwapIdentifier, StringComparison.OrdinalIgnoreCase)) @@ -709,7 +709,7 @@ namespace Barotrauma SavePendingUpgrades(upgradeManagerElement, PendingUpgrades); } - private void SavePendingUpgrades(XElement? parent, List upgrades) + private static void SavePendingUpgrades(XElement? parent, List upgrades) { if (parent == null) { return; } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/DockingPort.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/DockingPort.cs index 4952f01f9..8ef6c05ad 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/DockingPort.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/DockingPort.cs @@ -46,7 +46,7 @@ namespace Barotrauma.Items.Components private float forceLockTimer; //if the submarine isn't in the correct position to lock within this time after docking has been activated, //force the sub to the correct position - const float ForceLockDelay = 1.0f; + const float ForceLockDelay = 1.0f; public int DockingDir { get; set; } @@ -81,12 +81,18 @@ namespace Barotrauma.Items.Components set; } - [Editable, Serialize(DirectionType.None, IsPropertySaveable.No, description: "Which direction the port is allowed to dock in. For example, \"Top\" would mean the port can dock to another port above it.\n"+ + [Editable, Serialize(DirectionType.None, IsPropertySaveable.No, description: "Which direction the port is allowed to dock in. For example, \"Top\" would mean the port can dock to another port above it.\n" + "Normally there's no need to touch this setting, but if you notice the docking position is incorrect (for example due to some unusual docking port configuration without hulls or doors), you can use this to enforce the direction.")] public DirectionType ForceDockingDirection { get; set; } - + public DockingPort DockingTarget { get; private set; } + /// + /// Can be used by status effects + /// + public bool AtStartExit => Item.Submarine is { AtStartExit: true}; + public bool AtEndExit => Item.Submarine is { AtEndExit: true }; + public Door Door { get; private set; } public bool Docked @@ -116,6 +122,8 @@ namespace Barotrauma.Items.Components get { return joint is WeldJoint || DockingTarget?.joint is WeldJoint; } } + public bool AnotherPortInProximity => FindAdjacentPort() != null; + /// /// Automatically cleared after docking -> no need to unregister /// @@ -989,7 +997,7 @@ namespace Barotrauma.Items.Components dockingState = MathHelper.Lerp(dockingState, 0.0f, deltaTime * 10.0f); if (dockingState < 0.01f) { docked = false; } item.SendSignal("0", "state_out"); - item.SendSignal((FindAdjacentPort() != null) ? "1" : "0", "proximity_sensor"); + item.SendSignal(AnotherPortInProximity ? "1" : "0", "proximity_sensor"); } else { diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/ElectricalDischarger.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/ElectricalDischarger.cs index 0d2f9e1e1..8188d52c9 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/ElectricalDischarger.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/ElectricalDischarger.cs @@ -153,7 +153,7 @@ namespace Barotrauma.Items.Components { if (GetAvailableInstantaneousBatteryPower() >= PowerConsumption) { - List batteries = GetConnectedBatteries(); + List batteries = GetDirectlyConnectedBatteries(); float neededPower = PowerConsumption; while (neededPower > 0.0001f && batteries.Count > 0) { diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Holdable/Throwable.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Holdable/Throwable.cs index 40d209d5b..df595ca57 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Holdable/Throwable.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Holdable/Throwable.cs @@ -111,6 +111,12 @@ namespace Barotrauma.Items.Components } ApplyStatusEffects(ActionType.OnActive, deltaTime, picker); + //return if the status effect got rid of the picker somehow + if (picker == null || picker.Removed || !picker.HeldItems.Contains(item)) + { + IsActive = false; + return; + } if (item.body.Dir != picker.AnimController.Dir) { item.FlipX(relativeToSub: false); } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/ItemContainer.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/ItemContainer.cs index 7ca37cb5e..a1d69ce93 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/ItemContainer.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/ItemContainer.cs @@ -53,7 +53,7 @@ namespace Barotrauma.Items.Components private bool alwaysContainedItemsSpawned; - public ItemInventory Inventory; + public readonly ItemInventory Inventory; private readonly List activeContainedItems = new List(); @@ -189,6 +189,16 @@ namespace Barotrauma.Items.Components [Serialize(false, IsPropertySaveable.No)] public bool RemoveContainedItemsOnDeconstruct { get; set; } + + /// + /// Can be used by status effects to lock the inventory + /// + public bool Locked + { + get { return Inventory.Locked; } + set { Inventory.Locked = value; } + } + private readonly ImmutableArray slotRestrictions; readonly List targets = new List(); diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Sonar.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Sonar.cs index 07d3b598c..077ae053f 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Sonar.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Sonar.cs @@ -136,6 +136,13 @@ namespace Barotrauma.Items.Components public float Zoom { get { return zoom; } + set + { + zoom = MathHelper.Clamp(value, MinZoom, MaxZoom); +#if CLIENT + zoomSlider.BarScroll = MathUtils.InverseLerp(MinZoom, MaxZoom, zoom); +#endif + } } public Mode CurrentMode diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Power/PowerTransfer.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Power/PowerTransfer.cs index f123939d7..8c15f3019 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Power/PowerTransfer.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Power/PowerTransfer.cs @@ -278,7 +278,8 @@ namespace Barotrauma.Items.Components public override float GetConnectionPowerOut(Connection conn, float power, PowerRange minMaxPower, float load) { - return conn == powerOut ? PowerConsumption + ExtraLoad : 0; + //not used in the vanilla game (junction boxes or relays don't output power) + return conn == powerOut ? MathHelper.Max(-(PowerConsumption + ExtraLoad), 0) : 0; } public override bool Pick(Character picker) diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Power/Powered.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Power/Powered.cs index 330c6bd50..e355ccb14 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Power/Powered.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Power/Powered.cs @@ -690,43 +690,21 @@ namespace Barotrauma.Items.Components } /// - /// Efficient method to retrieve the batteries connected to the device + /// Returns a list of batteries directly connected to the item /// - /// All connected PowerContainers - protected List GetConnectedBatteries(bool outputOnly = true) + protected List GetDirectlyConnectedBatteries() { List batteries = new List(); - GridInfo supplyingGrid = null; - - //Determine supplying grid, prefer PowerIn connection - if (powerIn != null) + if (item.Connections == null || powerIn == null) { return batteries; } + foreach (Connection recipient in powerIn.Recipients) { - if (powerIn.Grid != null) + if (!recipient.IsPower || !recipient.IsOutput) { continue; } + var battery = recipient.Item?.GetComponent(); + if (battery != null) { - supplyingGrid = powerIn.Grid; + batteries.Add(battery); } } - else if (powerOut != null) - { - if (powerOut.Grid != null) - { - supplyingGrid = powerOut.Grid; - } - } - - if (supplyingGrid != null) - { - //Iterate through all connections to fine powerContainers - foreach (Connection c in supplyingGrid.Connections) - { - PowerContainer pc = c.Item.GetComponent(); - if (pc != null && (!outputOnly || pc.powerOut == c)) - { - batteries.Add(pc); - } - } - } - return batteries; } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Quality.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Quality.cs index bd2becdac..fbdb9e7c4 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Quality.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Quality.cs @@ -29,18 +29,7 @@ namespace Barotrauma.Items.Components FirepowerMultiplier, StrikingPowerMultiplier, StrikingSpeedMultiplier, - FiringRateMultiplier, - // unused as of now - AttackMultiplier, - // unused as of now - AttackSpeedMultiplier, - ForceDoorsOpenSpeedMultiplier, - RangedSpreadReduction, - ChargeSpeedMultiplier, - MovementSpeedMultiplier, - EffectivenessMultiplier, - PowerOutputMultiplier, - ConsumptionReductionMultiplier, + FiringRateMultiplier } private readonly Dictionary statValues = new Dictionary(); diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Repairable.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Repairable.cs index b8a0436e3..e486300c6 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Repairable.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Repairable.cs @@ -603,6 +603,9 @@ namespace Barotrauma.Items.Components private bool ShouldDeteriorate() { if (Level.IsLoadedFriendlyOutpost) { return false; } +#if CLIENT + if (GameMain.GameSession?.GameMode is TutorialMode) { return false; } +#endif if (LastActiveTime > Timing.TotalTime) { return true; } foreach (ItemComponent ic in item.Components) diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/BooleanOperatorComponent/BooleanOperatorComponent.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/BooleanOperatorComponent/BooleanOperatorComponent.cs index 3803e5b16..35b4a9d10 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/BooleanOperatorComponent/BooleanOperatorComponent.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/BooleanOperatorComponent/BooleanOperatorComponent.cs @@ -48,6 +48,8 @@ namespace Barotrauma.Items.Components { if (value == null) { return; } output = value; + //reactivate (we may not have been previously sending a signal, but might now) + IsActive = true; if (output.Length > MaxOutputLength && (item.Submarine == null || !item.Submarine.Loading)) { output = output.Substring(0, MaxOutputLength); @@ -63,6 +65,8 @@ namespace Barotrauma.Items.Components { if (value == null) { return; } falseOutput = value; + //reactivate (we may not have been previously sending a signal, but might now) + IsActive = true; if (falseOutput.Length > MaxOutputLength && (item.Submarine == null || !item.Submarine.Loading)) { falseOutput = falseOutput.Substring(0, MaxOutputLength); diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/MotionSensor.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/MotionSensor.cs index e278206b7..6ebfe3fc8 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/MotionSensor.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/MotionSensor.cs @@ -19,7 +19,8 @@ namespace Barotrauma.Items.Components Human = 1, Monster = 2, Wall = 4, - Any = Human | Monster | Wall, + Pet = 8, + Any = Human | Monster | Wall | Pet, } [Serialize(false, IsPropertySaveable.No, description: "Has the item currently detected movement. Intended to be used by StatusEffect conditionals (setting this value in XML has no effect).")] @@ -253,7 +254,7 @@ namespace Barotrauma.Items.Components } } - if (Target.HasFlag(TargetType.Human) || Target.HasFlag(TargetType.Monster)) + if (Target.HasFlag(TargetType.Human) || Target.HasFlag(TargetType.Pet) || Target.HasFlag(TargetType.Monster)) { foreach (Character c in Character.CharacterList) { @@ -267,7 +268,11 @@ namespace Barotrauma.Items.Components { if (!Target.HasFlag(TargetType.Human)) { continue; } } - else if (!c.IsPet) + else if (c.IsPet) + { + if (!Target.HasFlag(TargetType.Pet)) { continue; } + } + else { if (!Target.HasFlag(TargetType.Monster)) { continue; } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Turret.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Turret.cs index 18ab28faf..df767e009 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Turret.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Turret.cs @@ -702,7 +702,7 @@ namespace Barotrauma.Items.Components if (!ignorePower) { - List batteries = GetConnectedBatteries(); + List batteries = GetDirectlyConnectedBatteries(); float neededPower = GetPowerRequiredToShoot(); // tinkering is currently not factored into the common method as it is checked only when shooting @@ -1066,7 +1066,7 @@ namespace Barotrauma.Items.Components bool canShoot = true; if (!HasPowerToShoot()) { - List batteries = GetConnectedBatteries(); + List batteries = GetDirectlyConnectedBatteries(); float lowestCharge = 0.0f; PowerContainer batteryToLoad = null; foreach (PowerContainer battery in batteries) @@ -1308,9 +1308,13 @@ namespace Barotrauma.Items.Components } } float dist = Vector2.Distance(closestPoint, item.WorldPosition); + + //add one px to make sure the visibility raycast doesn't miss the cell due to the end position being right at the edge of the cell + closestPoint += (closestPoint - item.WorldPosition) / Math.Max(dist, 1); + if (dist > AIRange + 1000) { continue; } float dot = 0; - if (item.Submarine.Velocity != Vector2.Zero) + if (!MathUtils.NearlyEqual(item.Submarine.Velocity, Vector2.Zero)) { dot = Vector2.Dot(Vector2.Normalize(item.Submarine.Velocity), Vector2.Normalize(closestPoint - item.Submarine.WorldPosition)); } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Item.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Item.cs index 278b4a102..fdbe12a51 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Item.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Item.cs @@ -422,6 +422,8 @@ namespace Barotrauma } } + public Color? HighlightColor; + [Serialize("", IsPropertySaveable.Yes)] @@ -523,6 +525,7 @@ namespace Barotrauma { float prevConditionPercentage = ConditionPercentage; healthMultiplier = MathHelper.Clamp(value, 0.0f, float.PositiveInfinity); + RecalculateConditionValues(); condition = MaxCondition * prevConditionPercentage / 100.0f; RecalculateConditionValues(); } @@ -751,6 +754,9 @@ namespace Barotrauma get { return Prefab.Linkable; } } + public float WorldPositionX => WorldPosition.X; + public float WorldPositionY => WorldPosition.Y; + /// /// Can be used to move the item from XML (e.g. to correct the positions of items whose sprite origin has been changed) /// @@ -1913,8 +1919,11 @@ namespace Barotrauma if (!wasInWater && CurrentHull != null && body != null && body.LinearVelocity.Y < -1.0f) { Splash(); - //slow the item down (not physically accurate, but looks good enough) - body.LinearVelocity *= 0.2f; + if (GetComponent() is not { IsActive: true }) + { + //slow the item down (not physically accurate, but looks good enough) + body.LinearVelocity *= 0.2f; + } } Item container = this.Container; @@ -3340,10 +3349,8 @@ namespace Barotrauma item.PurchasedNewSwap = false; } - float condition = element.GetAttributeFloat("condition", item.MaxCondition); - item.condition = MathHelper.Clamp(condition, 0, item.MaxCondition); + item.condition = MathHelper.Clamp(item.condition, 0, item.MaxCondition); item.lastSentCondition = item.condition; - item.RecalculateConditionValues(); item.SetActiveSprite(); diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/ItemPrefab.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/ItemPrefab.cs index 79d80014d..59ee01824 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/ItemPrefab.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/ItemPrefab.cs @@ -1123,7 +1123,7 @@ namespace Barotrauma { string message = $"Tried to get price info for \"{Identifier}\" with a null store parameter!\n{Environment.StackTrace.CleanupStackTrace()}"; #if DEBUG - DebugConsole.ShowError(message); + DebugConsole.LogError(message); #else DebugConsole.AddWarning(message); GameAnalyticsManager.AddErrorEventOnce("ItemPrefab.GetPriceInfo:StoreParameterNull", GameAnalyticsManager.ErrorSeverity.Error, message); diff --git a/Barotrauma/BarotraumaShared/SharedSource/Map/Levels/Level.cs b/Barotrauma/BarotraumaShared/SharedSource/Map/Levels/Level.cs index 181f60281..e864b0a9e 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Map/Levels/Level.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Map/Levels/Level.cs @@ -2932,7 +2932,7 @@ namespace Barotrauma } /// Used by clients to set the rotation for the resources - public List GenerateMissionResources(ItemPrefab prefab, int requiredAmount, PositionType positionType, out float rotation) + public List GenerateMissionResources(ItemPrefab prefab, int requiredAmount, PositionType positionType, out float rotation, IEnumerable targetCaves = null) { var allValidLocations = GetAllValidClusterLocations(); var placedResources = new List(); @@ -2995,6 +2995,12 @@ namespace Barotrauma DebugConsole.ThrowError($"Unexpected PositionType (\"{positionType}\") for mineral mission resources: mineral spawning might not work as expected."); } + if (targetCaves != null && targetCaves.Any()) + { + // If resources are placed inside a cave, make sure all of them are placed inside the same one + allValidLocations.RemoveAll(l => targetCaves.None(c => c.Area.Contains(l.EdgeCenter))); + } + var poi = PositionsOfInterest.GetRandom(p => p.PositionType == positionType, randSync: Rand.RandSync.ServerAndClient); Vector2 poiPos = poi.Position.ToVector2(); allValidLocations.Sort((x, y) => Vector2.DistanceSquared(poiPos, x.EdgeCenter) @@ -3002,7 +3008,10 @@ namespace Barotrauma float maxResourceOverlap = 0.4f; var selectedLocation = allValidLocations.FirstOrDefault(l => Vector2.Distance(l.Edge.Point1, l.Edge.Point2) is float edgeLength && + !l.Edge.OutsideLevel && requiredAmount <= (int)Math.Floor(edgeLength / ((1.0f - maxResourceOverlap) * prefab.Size.X))); + + if (selectedLocation.Edge == null) { //couldn't find a long enough edge, find the largest one @@ -3028,10 +3037,10 @@ namespace Barotrauma static bool IsOnMainPath(ClusterLocation location) => location.Edge.NextToMainPath; static bool IsOnSidePath(ClusterLocation location) => location.Edge.NextToSidePath; static bool IsInCave(ClusterLocation location) => location.Edge.NextToCave; - bool IsInAbyssCave(ClusterLocation location) => location.EdgeCenter.Y > AbyssArea.Bottom; + bool IsInAbyssCave(ClusterLocation location) => location.EdgeCenter.Y < AbyssStart; void RemoveInvalidLocations(Predicate match) { - allValidLocations.RemoveAll(match); + allValidLocations.RemoveAll(l => !match(l)); } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Map/LinkedSubmarine.cs b/Barotrauma/BarotraumaShared/SharedSource/Map/LinkedSubmarine.cs index 46d549e2f..52bc59f55 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Map/LinkedSubmarine.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Map/LinkedSubmarine.cs @@ -281,6 +281,10 @@ namespace Barotrauma IdRemap parentRemap = new IdRemap(Submarine.Info.SubmarineElement, Submarine.IdOffset); sub = Submarine.Load(info, false, parentRemap); sub.Info.SubmarineClass = Submarine.Info.SubmarineClass; + if (Submarine.Info.IsOutpost && Submarine.TeamID == CharacterTeamType.FriendlyNPC) + { + sub.TeamID = CharacterTeamType.FriendlyNPC; + } IdRemap childRemap = new IdRemap(saveElement, sub.IdOffset); diff --git a/Barotrauma/BarotraumaShared/SharedSource/Map/Map/Location.cs b/Barotrauma/BarotraumaShared/SharedSource/Map/Map/Location.cs index d90c90e99..cb1861ec7 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Map/Map/Location.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Map/Map/Location.cs @@ -700,7 +700,7 @@ namespace Barotrauma #endif } - public MissionPrefab UnlockMissionByIdentifier(Identifier identifier) + public Mission UnlockMissionByIdentifier(Identifier identifier) { if (AvailableMissions.Any(m => m.Prefab.Identifier == identifier)) { return null; } @@ -721,17 +721,17 @@ namespace Barotrauma #if CLIENT GameMain.GameSession?.Campaign?.CampaignUI?.RefreshLocationInfo(); #endif - return missionPrefab; + return mission; } return null; } - public MissionPrefab UnlockMissionByTag(Identifier tag) + public Mission UnlockMissionByTag(Identifier tag) { var matchingMissions = MissionPrefab.Prefabs.Where(mp => mp.Tags.Any(t => t == tag)); if (!matchingMissions.Any()) { - DebugConsole.ThrowError($"Failed to unlock a mission with the tag \"{tag}\": no matching missions not found."); + DebugConsole.ThrowError($"Failed to unlock a mission with the tag \"{tag}\": no matching missions found."); } else { @@ -754,7 +754,7 @@ namespace Barotrauma #if CLIENT GameMain.GameSession?.Campaign?.CampaignUI?.RefreshLocationInfo(); #endif - return missionPrefab; + return mission; } else { diff --git a/Barotrauma/BarotraumaShared/SharedSource/Map/Map/Map.cs b/Barotrauma/BarotraumaShared/SharedSource/Map/Map/Map.cs index 925f45e66..ff196b2d6 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Map/Map/Map.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Map/Map/Map.cs @@ -462,6 +462,13 @@ namespace Barotrauma } } + //make sure the connections are in the same order on the locations and the Connections list + //otherwise their order will change when loading the game (as they're added to the locations in the same order they're loaded) + foreach (var location in Locations) + { + location.Connections.Sort((c1, c2) => Connections.IndexOf(c1).CompareTo(Connections.IndexOf(c2))); + } + for (int i = Connections.Count - 1; i >= 0; i--) { i = Math.Min(i, Connections.Count - 1); diff --git a/Barotrauma/BarotraumaShared/SharedSource/Map/Submarine.cs b/Barotrauma/BarotraumaShared/SharedSource/Map/Submarine.cs index 6ffee8449..5ae404712 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Map/Submarine.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Map/Submarine.cs @@ -1234,7 +1234,7 @@ namespace Barotrauma public List<(ItemContainer container, int freeSlots)> GetCargoContainers() { List<(ItemContainer container, int freeSlots)> containers = new List<(ItemContainer container, int freeSlots)>(); - var connectedSubs = GetConnectedSubs(); + var connectedSubs = GetConnectedSubs().Where(sub => sub.Info?.Type == Info.Type); foreach (Item item in Item.ItemList.ToList()) { if (!connectedSubs.Contains(item.Submarine)) { continue; } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Map/SubmarineBody.cs b/Barotrauma/BarotraumaShared/SharedSource/Map/SubmarineBody.cs index b8b2fd544..b9af39add 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Map/SubmarineBody.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Map/SubmarineBody.cs @@ -447,11 +447,13 @@ namespace Barotrauma private Vector2 CalculateBuoyancy() { + if (Submarine.LockY) { return Vector2.Zero; } + float waterVolume = 0.0f; float volume = 0.0f; foreach (Hull hull in Hull.HullList) { - if (hull.Submarine != submarine) continue; + if (hull.Submarine != submarine) { continue; } waterVolume += hull.WaterVolume; volume += hull.Volume; diff --git a/Barotrauma/BarotraumaShared/SharedSource/Networking/Client.cs b/Barotrauma/BarotraumaShared/SharedSource/Networking/Client.cs index 84fb06106..93a7b09eb 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Networking/Client.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Networking/Client.cs @@ -20,7 +20,6 @@ namespace Barotrauma.Networking public bool InGame; public bool HasPermissions; public bool IsOwner; - public bool AllowKicking; public bool IsDownloading; } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/NetworkPeerStructs.cs b/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/NetworkPeerStructs.cs index 893bed235..0a042c27f 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/NetworkPeerStructs.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/NetworkPeerStructs.cs @@ -101,34 +101,45 @@ namespace Barotrauma.Networking } public LocalizedString ChatMessage(Client c) - => DisconnectReason switch + { + LocalizedString message = DisconnectReason switch { DisconnectReason.Disconnected => TextManager.GetWithVariable("ServerMessage.ClientLeftServer", "[client]", c.Name), + DisconnectReason.Banned => TextManager.GetWithVariable("servermessage.bannedfromserver", "[client]", c.Name), + DisconnectReason.Kicked => TextManager.GetWithVariable("servermessage.kickedfromserver", "[client]", c.Name), _ => TextManager.GetWithVariables("ChatMsg.DisconnectedWithReason", ("[client]", c.Name), ("[reason]", TextManager.Get($"ChatMsg.DisconnectReason.{DisconnectReason}"))) }; + if (!string.IsNullOrEmpty(AdditionalInformation) && + DisconnectReason is DisconnectReason.Banned or DisconnectReason.Kicked) + { + message += " "+ TextManager.Get("banreason") + " " + TextManager.GetServerMessage(AdditionalInformation); + } + return message; + } - private LocalizedString msgWithReason + + private LocalizedString MsgWithReason => TextManager.Get($"DisconnectReason.{DisconnectReason}") + "\n\n" - + TextManager.Get("banreason") + " " + AdditionalInformation; + + TextManager.Get("banreason") + " " + TextManager.GetServerMessage(AdditionalInformation); - private LocalizedString serverMessage + private LocalizedString ServerMessage => TextManager.Get($"ServerMessage.{DisconnectReason}"); public LocalizedString PopupMessage => DisconnectReason switch { - DisconnectReason.Banned => msgWithReason, - DisconnectReason.Kicked => msgWithReason, + DisconnectReason.Banned => MsgWithReason, + DisconnectReason.Kicked => MsgWithReason, DisconnectReason.InvalidVersion => TextManager.GetWithVariables("DisconnectMessage.InvalidVersion", ("[version]", AdditionalInformation), ("[clientversion]", GameMain.Version.ToString())), - DisconnectReason.ExcessiveDesyncOldEvent => serverMessage, - DisconnectReason.ExcessiveDesyncRemovedEvent => serverMessage, - DisconnectReason.SyncTimeout => serverMessage, + DisconnectReason.ExcessiveDesyncOldEvent => ServerMessage, + DisconnectReason.ExcessiveDesyncRemovedEvent => ServerMessage, + DisconnectReason.SyncTimeout => ServerMessage, _ => TextManager.Get($"DisconnectReason.{DisconnectReason}").Fallback(TextManager.Get("ConnectionLost")) }; @@ -165,9 +176,6 @@ namespace Barotrauma.Networking or DisconnectReason.TooManyFailedLogins or DisconnectReason.InvalidVersion); - public bool ShouldShowMessage - => DisconnectReason is not DisconnectReason.Disconnected; - private const string lidgrenSeparator = ":hankey:"; /// diff --git a/Barotrauma/BarotraumaShared/SharedSource/StatusEffects/DelayedEffect.cs b/Barotrauma/BarotraumaShared/SharedSource/StatusEffects/DelayedEffect.cs index 94e6c7bef..6435eebf4 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/StatusEffects/DelayedEffect.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/StatusEffects/DelayedEffect.cs @@ -77,13 +77,13 @@ namespace Barotrauma Projectile projectile = (entity as Item)?.GetComponent(); if (projectile == null) { - DebugConsole.ShowError("Non-projectile using a delaytype of reachcursor"); + DebugConsole.LogError("Non-projectile using a delaytype of reachcursor"); return; } if (projectile.User == null) { - DebugConsole.ShowError("Projectile: '" + projectile.Name + "' missing user to determine distance"); + DebugConsole.LogError("Projectile: '" + projectile.Name + "' missing user to determine distance"); return; } @@ -129,7 +129,7 @@ namespace Barotrauma if (projectile == null) { #if DEBUG - DebugConsole.ShowError("Non-projectile using a delaytype of reachcursor"); + DebugConsole.LogError("Non-projectile using a delaytype of reachcursor"); #endif return; } @@ -137,7 +137,7 @@ namespace Barotrauma if (projectile.User == null) { #if DEBUG - DebugConsole.ShowError("Projectile " + projectile.Name + "missing user"); + DebugConsole.LogError("Projectile " + projectile.Name + "missing user"); #endif return; } diff --git a/Barotrauma/BarotraumaShared/SharedSource/StatusEffects/StatusEffect.cs b/Barotrauma/BarotraumaShared/SharedSource/StatusEffects/StatusEffect.cs index 9c1ce5c71..4b625e9e8 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/StatusEffects/StatusEffect.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/StatusEffects/StatusEffect.cs @@ -1770,7 +1770,7 @@ namespace Barotrauma case ItemSpawnInfo.SpawnRotationType.Random: if (projectile != null) { - DebugConsole.ShowError("Random rotation is not supported for Projectiles."); + DebugConsole.LogError("Random rotation is not supported for Projectiles."); } else { diff --git a/Barotrauma/BarotraumaShared/changelog.txt b/Barotrauma/BarotraumaShared/changelog.txt index 6dd03983d..49a90c5db 100644 --- a/Barotrauma/BarotraumaShared/changelog.txt +++ b/Barotrauma/BarotraumaShared/changelog.txt @@ -1,401 +1,305 @@ --------------------------------------------------------------------------------------------------------- -v0.19.5.0 +v0.19.8.0 --------------------------------------------------------------------------------------------------------- -Unstable only: -- Progress on the new tutorials, the Roles tutorials in particular. Still a work in progress, but feedback is again more than welcome! -- Cleaned up networking and server list code to make them less error-prone and easier to work with in the future. Should not cause any functional differences, but please let us know if you notice any issues or oddities! -- Fixes and improvements to Camel. -- Fixed skill texts not being colored according to the user's skills in the repair UI. -- Fixed outpost service NPCs' titles (which are also used as the tooltips on the icons) not showing up in the multiplayer campaign. -- Further fixes to dragging animations. -- Fixed warning about duplicate keybinds being displayed for things set to None. -- Fixed clients who've gotten vote kicked getting vote kicked again when they join. -- Fixed favorited localhost servers causing a crash. -- Fixed respawn shuttle setting toggling on and off when adjusting other settings. -- Fixed skills increasing on death if the skill level is under the maximum initial skill. -- Fixes duplicate Captain Hognoses occasionally appearing in the crew list when selecting the Hognose mission in the multiplayer campaign. -- Fixed wrecked coilgun and railgun launch impulses. -- Fixed delayed status effects not working after the parent entity has been removed (breaking many medical items, e.g. ethanol). -- Fixed inability to buy anything from other stores when you've bought something from one of the stores in an outpost in the multiplayer campaign. +- Minor improvements and fixes to the tutorials (e.g. safeguards to prevent dying or getting stuck). +- Fixed Typhon 2's chaingun being placed inside solid walls. +- Fixed Tandem Fire talent causing a crash if there's no allies alive. +- Fixed bots being unable to shoot at ice spires with pulse laser or chaingun. +- Removed outdated Deep Diver loading screen tip. +- Fixed misaligned connection panel interface when repairing a status monitor. +- Fixed Winterhalter battery recharge speed being limited by the relay that supplies power to them, making recharge speed upgrades useless. +- Fixed a networking issue that caused afflictions' periodic effects (e.g. nausea-induced vomiting) to happen too frequently client-side. +- Fixed none of the contextual orders except "wait here" showing the name of the order in the tooltip. +- Fixed inconsistencies in some crawler swarm mission names (large swarms not being described as large). +- Fixed mineral mission resources sometimes spawning in separate caves. +- Fixed minerals mission resources sometimes spawning outside the level. +- Moved handheld sonar's drag icon to a more appropriate position. +- Fixed buoyancy making locked subs slowly move vertically. +- Reactors don't explode if they reach 0 condition without fuel. +- Fixed motion sensor not detecting pets. +- Fixed cargo capacity displayed in the mission selection screen including the cargo containers in the outpost the sub is docked. +- Fixed clients being unable to select the respawn shuttle if they have to download it from the server. +- Fixed duplicate banlist entires when a client gets banned due to an incorrect password. +- Some wire and waypoint cleanup to R-29 and Remora. +- Removed a wall in Remora to allow for better movement inside. +- Changed one railgun shelf to boxes shelf on Remora. +- Added a coilgun and a couple more diving suit cabinets to R-29. +- Fixed "completed initialization before receiving content package order" error when trying to reconnect to a SteamP2P server. -Changes: +--------------------------------------------------------------------------------------------------------- +v0.19.7.0 +--------------------------------------------------------------------------------------------------------- + +Changes and additions: +- Completely remade tutorials. There is now a Basics Tutorial to cover basics like moving, inventory and repairs. More specific tasks are explained in the Roles Tutorial, where every job has their own tutorial to go through, explaining what it means to be e.g. an Engineer or a Captain. +- Added new mining missions, including some in the abyss. +- Reintroduced separate local/radio voice chat keys as a legacy option. Now it's again possible to speak with voice activation by default and use a push-to-talk button for radio, the same way as before, by setting the chat mode to Local and using the new radio voice chat hotkey. +- Device/item UIs can be moved around by dragging. +- Allow using devices while on a ladder or sitting on a chair. +- Changed reactor temperature bar colors (from blue to red). +- Higher quality stun batons cause heavier stun. +- Changed unit load device capacity to 12 (because the sprite has space for 12) and made them waterproof. +- Changed fabricator skill calculations: the most inadequate of the required skills determines the fabrication time (instead of the average). +- Made dying drop a characters' skills towards the maximum initial skill instead of minimum. +- Added a new keybind for opening and closing the chat box. The default bind is B. +- Added a warning if a new keybind overlaps with any of the player's existing binds. +- Overvoltage makes devices perform better, increasing the output of engines, making fabricators, deconstructors and pumps operate faster, electrical discharge coils do more damage, batteries recharge faster and oxygen generators generate more oxygen. Encourages operating the reactor manually and hopefully makes it a little more engaging. +- Added more randomness to junction box overvoltage damage, and made partially damaged boxes take more damage from overvoltage. Prevents all boxes from breaking at the same time, making overvoltage less of a pain to deal with and intentionally overvolting devices more worthwhile. +- Added manual temperature adjustment buttons which immediately increase/decrease the temperature of the reactor for a brief amount of time on manual control (bumps the gauge up/down by a fifth, and the boost fades out in 20 seconds). Allows reacting to load fluctuations very quickly, and conserving fuel by operating the reactor at a lower fission rate a new benefit to operating reactors manually. +- Signals no longer set the fission and turbine rates of the reactor instantaneously, making automated reactor circuits less overpowered. They are still viable, but especially now with the addition of the extra incentives for operating the reactor manually, they're no longer as clearly the best and most efficient way to operate the reactor, making manual operation more worthwhile. +- Made the "distort" camera effect a little less obtrusive and glitchy-looking (smoother texture + less heavy effect). +- Made water-sensitive materials (lithium, potassium, sodium) spawn in waterproof chemical crates. - Made crates deconstruct much faster to make them easier to get rid of. -- Sonar disruptions hide minerals. -- Gray out RangedWeapon's crosshair when reloading (similar to turret crosshairs). +- Sonar disruptions now hide minerals. +- Grayed out ranged weapons' crosshair when reloading (similar to turret crosshairs). +- Disabled the autodocking prompt (which verifies whether you actually want to dock when docking is initiated by an automated circuit) in single player. +- Improved the way drag is applied on submerged items. Fixes heavy items dropping at unnaturally high speeds in water. +- Added a splash effect when an item falls into water. +- The deconstructor UI shows what the input items deconstruct to (particularly important now with the lossy deconstruction recipes - it can be risky to deconstruct something just to see what materials it gives out if that results in material loss). +- Wall and device repair costs in outposts are calculated based on the amount of damage on your sub, instead of always having a fixed price. +- Inflamed lung doesn't affect characters that don't need oxygen. +- Added swarm behavior for crawler husks. +- Added some more oomph to nuclear explosions. +- Adjust the alpha of the outpost service icons according to distance to make it easier to estimate where the NPC is at. Show the title of the NPC when hovering the cursor over the icon. +- Added "unlockmission" console command. +- Added "setcampaignmetadata" console command (may be useful for modders creating custom scripted events for the campaign). +- Changed how NPC "titles" work. Previously we defined "titles" for the pirates (e.g. "Pirate Lord" and such), and the title replaced the name of the NPC (which made their dialog a little awkward). Now we display both the name and the title over the character, and special outpost NPCs also have titles. +- Gave diving masks to most NPCs. +- Changed the burn overlay formula: now also the non-affected limbs get half of the effect, because the sharp contrast between limbs looked weird. +- Restored the 3-shell Railgun rack as a legacy option. +- Reworded the "respawn with penalty" prompt to make it less confusing: you always get a penalty to your skills when you die now, and Reaper's Tax is an "extra penalty" you get on top of that if you opt to respawn mid-round. The intention behind this is to incur a cost to respawning, as it shouldn't be possible to get unlimited free reinforcements and supplies mid-round. +- Made SIGTERM close the linux server gracefully. +- Made respawn items (suits, scooters) spawn in the respawn shuttle's cabinets when possible. +- Show a healthbar on items (e.g. eggs and thalamus organs) when damaging them with handheld weapons (melee or ranged). -Fixes: -- Fixed clients downloading submarines they already have from the server if the mods those submarines are in are not currently enabled. -- Fixed submarines always saving in the root folder of a local mod, instead of the subfolder they were originally in. -- Fixed Reaper's Tax not stacking. -- Fixed turrets linked to the same loader messing up the upgrade store UI and causing item swaps to cost more than they should. -- Fixed status monitor calculating linked hulls' water amounts incorrectly (displaying the average of their water percentages, which isn't correct if the hulls aren't the same size). -- Fixes to messed up ruin decals in a bunch of ruin modules. -- Fixed a waypoint issue in the Alien_Entrance3 ruin module. -- Removed oxygen tanks from DockingModule_01_Colony. +Submarines: +- Added a new intermediate transport sub, Camel. +- Added submarine tiers. Higher-tier submarines can be upgraded further than lower-tier submarines. +- Overhauled and balanced submarine upgrades. +- Added Large Weapon Hardpoints. +- Added Flak Cannon and Double Coilgun as new Large Weapons. +- Railgun is now considered a Large Weapon. +- Added an upgrade that adds a mineral scanner to nav terminals and sonar monitors.cannon +- Submarine class now affects which upgrades are available for the sub. +- Removed the Deep Diver class: the way we see it, Deep Divers didn't have a clear enough role in the game, especially considering that hull upgrades served pretty much the same purpose. In practice, the only clear benefit of a Deep Diver was being able to get through the very last levels of the campaign, and having to switch to one just for that purpose wasn't fun. Now any submarine with full hull upgrades can get all the way to the end of the campaign. +- Fixed messy wiring in Typhon 2's bottom left hardpoint. +- Winterhalter and Remora are now Scout class ships. +- Added some loose vents and panels to Herja, Winterhalter and Barsuk, fixed invisible "loose panel" (news stand) in Orca 2. +- Fixed floating light component in Orca 2. +- Medical fabricator now consumes 500 power on all submarines, to be consistent with other fabricators. +- Updated prices of all submarines to match tiers. +- Gave Typhon 2 better stats and even more firepower, to outclass the original Typhon. +- Improved R-29's speed and gave it a Flak Cannon. +- Added Large Weapon hardpoints to Berilia to make it a Tier 3 transport. - Tweaked the hulls and waypoints around Herja's top docking hatch to make it easier for bots to reach and weld. - Fixed a waypoint/hull issue in Typhon's stowage compartment (waypoint in such a tight space the bots couldn't reach it). -- Fixed inactive components (components not currently sending any signal) not reactivating if their output is set to a non-empty value. -- Fixed duct block's misaligned broken sprite. + +Balance: +- "Mission cheesing" by repeatedly undocking and redocking to an outpost to reroll the mission events no longer works: new mission events don't reappear until one "world step" has passed (~10 minutes or traversing through one level). +- Balance pass on handheld weapons: adjusted reload times, damages, stun durations, recoil and ammo stack sizes. +- Reduced tools' structure damage (dual-wielded storage containers no longer chew through submarine walls in seconds). +- Increased heavy ruin wall health to make it less easy to cheese your way into the artifact room in ruins. +- Made boomstick fire in bursts of 2 (similar to deadeye carbide) to prevent ridiculous fire rates with quick-reloading. +- Added EMP effect to nuclear depth charges for consistency. +- Pulse Laser and Railgun now have similar power consumption as other turrets. +- Changed how skill levels affect the quality of fabricated items. Previously having a skill level equal to or higher than the item's skill requirement would result in a good quality item, meaning that practically everyone could e.g. fabricate good quality oxygen tanks. Now your skill needs to be >20% from the minimum skill requirement towards 100 (e.g. if the item requires 20 skill to fabricate, 36 results in a higher quality item). +- Reduced PUCS's radiation resistance from 100% to 90%. Complete invulnerability to radiation has way too much potential for exploits and overpowered strategies. +- Adjusted supplies in pirate submarines. +- Turned some weapons' burn damage into explosion damage. +- Made the extra sales from "traveling tradesman" talent stack. +- Terminal ignores empty signals. +- Reduced commonness of molochs (as they can take a lot of time to kill, running into multiple of them can quickly become a chore) +- Removed steel requirement for depth charges. Fabricate decoy depth charges from depth charges, rather than from the base material. +- Reduced the Pulse Laser tri-laser bolt spread. +- Explosions are now calculated differently, using the number of limbs to divide the damage (up to a maximum of 15 limbs). Adjusted explosion damage values to match new calculations. +- Coilgun costs 5000 marks to install, Pulse Laser and Chaingun 6000. Large turrets each cost 7500 each. +- Made mudraptor eggs modestly profitable for farming (decreased cost from shop, increased deconstruction yields). +- Mineral yield and spawn rates rebalance: minerals found are now much more dependent on location (biome, cave, abyss). +- Balanced existing mineral missions: adjusted rewards & required minerals, and required some minerals to be handed over to the outposts as proof of their existence. +- Rebalanced Engine Force values to better match hull size. Most Scouts (Azimuth, Orca2, Remora, Winterhalter) are now faster. Humpback, Typhon and Orca are slightly slower. + +Multiplayer: +- Fixed missions sometimes unlocking in incorrect locations in MP campaign, making them either unselectable or causing a "mission mismatch" error when the round starts. +- Fixed clients downloading submarines they already have from the server if the mods those submarines are in are not currently enabled. +- Significantly sped up file transfers (mods, submarine files, campaign saves). +- Clients who've recently joined (by default 2 minutes) are not allowed to vote to kick others, and vote kicking someone always requires at least 2 votes. +- Servers don't allow selecting hidden jobs (jobs only used by NPCs) as job preferences. +- The minimum kick vote counts are no longer rounded down. Previously if you had for example four players on the server and the minimum vote count set to 60%, kicking would require 2 votes, now it requires 3. +- Fixed inventory and wallet resetting if a campaign round ends when a client's character has spawned, but the client is not currently controlling it (e.g. due to getting kicked to the lobby). +- Fixed spectator checkbox overlapping with the character info if you get kicked to the lobby mid-round. +- Fixed "kick" button staying disabled indefinitely if you vote to kick someone and the vote doesn't go through. +- Fixed Steamworks publish tab showing the "free weekend" message when using Steam family sharing. +- Minor tweaks to the end of PvP missions to make them a little less underwhelming: instead of ending the round immediately when one team is dead (without even giving enough time to see the enemy die), there's a brief delay, a message box and a camera transition to let the players see what happened. +- Fixed PvP team assignment sometimes being wildly imbalanced, even when there were enough players with no preference to make the team sizes equal. +- Fixed clients getting stuck in the loading screen if they happen to disconnect at the right moment between rounds. +- Fixed bank balance not getting corrected if it's become desynced by e.g. client-side commands. +- Fixed server not registering a client's character as disconnected if the client disconnects and reconnects before the round has fully started, causing the client to get stuck as a spectator when they rejoin. +- Fixed clients disabling their client-side-only mods when they join a server. +- Fixed hull/item repairs purchased from an outpost sometimes not getting applied client-side. +- Fixed "missing entity" errors in a specific situation in multiplayer. Occurred when a respawn shuttle was enabled and loaded on the server (= i.e. in a non-outpost level), and a client disconnected and immediately reconnected. This would cause the client to deselect the respawn shuttle and make them start the round without loading one, leading to the "missing entity" issues due to the shuttle only existing server-side. +- Fixed damage visuals not showing on characters who've died off-screen. +- Fixed ability to upgrade the sub when there's a switch pending in multiplayer. +- Fixed friendly fire and karma always showing up as disabled on dedicated servers in the server list. +- Fixed spineling spikes fired by a human with spineling genes not damaging any human characters (enemies in PvP, pirates in pirate missions) when friendly fire is disabled. +- Fixed "invalid ExecuteAttack message: limb index out of bounds" errors when you join a server where a character has fired spineling spikes with spineling genes mid-round. +- Fixed "entity not found" errors if a shuttle or submarine ends up absurdly deep in multiplayer (>100 km). We don't even know how someone managed to pull this off. +- Fixed rapidly clicking on the mission giver sometimes not giving all the available missions when the "Use" input is set to LMB. Happened because the conversation logic didn't check if there's another conversation active, causing the server to show a new conversation when clicking the NPC, without interrupting/continuing the previous conversation. +- Made shockjock event only show for the player triggering the event (making it visible for everyone works kind of weirdly, when the event involves talking to an NPC next to the character who triggered the event). +- Fixed outpost events getting stuck at the last ConversationAction if another client has finished the action. + +Optimization: +- Updated our runtime to .NET 6, which should yield significant performance improvements. Do note that this unfortunately means we'll have to drop support for macOS versions older than 10.15, but we have taken some measures to help the affected Mac players continue having access to Barotrauma. More info here https://store.steampowered.com/news/app/602960/view/3367025204056277713. +- Optimized afflictions that apply other afflictions on the character (e.g. radiation sickness, drunkenness, opiate withdrawal). +- Optimizations to the talent system, particularly when the talent menu is open and when there's a large number of talents (e.g. when using mods that make all talents available to every class). +- Physics optimization: fixed submerged items' physics bodies staying active indefinitely even after they've come to rest due to buoyant forces being applied on them constantly. Now we stop updating bodies that have come to rest on the floor and aren't light enough to float. +- Optimized AI objectives that make bots fetch items (combat, contain item, decontain item, get item). Submarine editor: -- Fixed door gaps not appearing in the sub editor until you select the door - -Modding: -- Added CheckTalentAction, which can be used in events to check whether a target has unlocked a specific talent. -- Fixed ExtraLoad working the wrong way around on PowerTransfer components that generate/consume power (the extra load would supply power to the grid). Does not affect the vanilla game, because neither junction boxes or relays generate or consume power. - ---------------------------------------------------------------------------------------------------------- -v0.19.4.0 ---------------------------------------------------------------------------------------------------------- - -Unstable only: -- Fixed networking issues that prevented joining SteamP2P servers. -- Fixed crashing on startup if GameAnalytics is enabled. -- Fixed sub editor background images not saving if you leave the editor and quit the game without exiting the image editing mode first. -- Camel hull fixes. -- Fixed a draw order issue in unit load device. -- Fixed unit load device's inventory slot layout. -- Fixed submarine tier set in the sub editor not being saved, causing all subs to use the default tier determined by the price. - -Changes: -- Made extra sales from "traveling tradesman" talent stack. +- Fixed door gaps not appearing in the sub editor until you select the door. +- Fixed sub editor background images not saving. +- Fixed turret lightsource rotation not refreshing in the sub editor when flipping the item. +- Fixed prefab placement breaking in the sub editor if LMB is held while moving the cursor outside of the selection panel. +- Fixed several instances of janky UI interactions in the submarine editor: dragging the selection rectangle now works even if the cursor reaches into the prefab list; letting go of a dragged entity works even if the cursor reaches into the prefab list; the dragged entity no longer goes invisible when reaching into the prefab list. +- Made PowerContainer recharge speed always default to 0. +- Fixed adding resizeable items (like ladders) not being registered in the sub editor's command history, preventing undoing it. +- Changed default reactor output from 10,000 kW to 5000 kW. +- Decreased Winterhalter reactor output and increased its fuel consumption rate. +- Fixed some gap issues in Winterhalter. +- Fixed medics not having access to the toxin cabinet in Barsuk. +- Fixed medic, engineer and mechanic spawnpoints having no tags in Typhon. +- Fixed crashing when trying to multi-edit a string value in the sub editor. +- Fixed dragged objects becoming invisible if you bring the cursor over a UI element in the sub editor. +- Fixed screwdrivers and wires in your "inventory" being included in the total item count in the sub editor's wiring mode. +- Fixed entities that were below the cursor when starting to resize a structure staying highlighted during resizing. +- Fixed sub editor treating the autosave interval as minutes instead of seconds (saving every 300 minutes instead of 300 seconds). Fixes: +- Fixed "power flowback" issue in turrets. As of the power rework, wires connected to the same input or output pin of a device are considered to be in the same grid, which in practice meant a turret could be connected to another supercapacitor through the power_in connection of another turret, even if there was no direct connection between the 1st turret and the supercapacitor. Now the turrets (and electrical discharge coils) need to be wired directly to the supercapacitor. +- Fixed brief freezes when monsters spawn mid-round. +- Fixed turrets linked to the same loader messing up the upgrade store UI and causing item swaps to cost more than they should. +- Fixed submarines always saving in the root folder of a local mod, instead of the subfolder they were originally in. +- Fixed Reaper's Tax not stacking. +- Fixes to ruin decals in a bunch of ruin modules. +- Fixed a waypoint issue in the Alien_Entrance3 ruin module. +- Removed oxygen tanks from DockingModule_01_Colony. +- Fixed duct block's misaligned broken sprite. +- Fixed status monitor calculating linked hulls' water amounts incorrectly (displaying the average of their water percentages, which isn't correct if the hulls aren't the same size). +- Fixed inactive components (components not currently sending any signal) not reactivating if their output is set to a non-empty value. +- Fixed missing gap in SecurityModule_02. +- Fixed lack of outpost events in difficulties past 80 (which no longer occur normally but still exist in old saves and mods). +- Fixed lithium and magnesium descriptions. +- Adjusted hulls in DockingModule_02_Colony to prevent bots from jumping off the ledge. +- Fixed motion sensors detecting pets as monsters (pets are now a separate target type). +- Fixed helmets not protecting against concussions. +- Fixed safety harness not protecting against lacerations. +- Fixed increasing an item's HealthMultiplier not increasing the current condition (so e.g. doubling the item's max health would cause it to have 50% condition). +- Fixed successive event dialogs in the same prompt scrolling the prompt back up and then down. +- Fixed missing "pirateclothes" inventory icon. - Made bots better at figuring out which button controls a door when there's some complex circuit involved. Previously the bots would try to find a button connected to any of the door's connections via wires/circuits, now only the toggle and set_state inputs are considered. -- Bots now heavily prefer using buttons linked to the door in the sub editor. Can be used as another way to help the bots figure out which button they should press in situations with multiple buttons and complex door control logic. -- Fixed bots failing to find a path to a couple of spots in Herja. +- Bots now clearly prefer using buttons linked to the door in the sub editor. Can be used as another way to help bots figure out which button they should press in situations with multiple buttons and complex door control logic. +- Fixed bots failing to find a path to a couple of spots on Herja. - Fixed alien materials (physicorium, incendium, fulgurium, dementonite, paralyxis) not being shown on the mineral scanner. - Another fix to cave generation to prevent it from creating impassable paths. - Fixed inability to use manual assignment for bot orders with options. - Fixed all boolean components (And, Or, Xor) using the And Component's tooltip for the "timeframe" property. - Fixed boolean operator component (And, Or, Xor) timeframes not working correctly in some situations (non-zero timeframe, empty false output). The component would deactivate as soon as it stops sending an output, which could prevent some inputs from timing out (meaning that the component could send a signal again as soon as it receives signal A, even if signal B hasn't been received within the timeframe). - Fixed PUCS consuming the medical item inside it when a welding fuel or incendium tank is inserted. - -Multiplayer: -- Fixed inventory and wallet resetting if a campaign round ends when a client's character has spawned, but the client is not currently controlling it (e.g. due to getting kicked to the lobby). -- Fixed spectator checkbox overlapping with the character info if you get kicked to the lobby mid-round. - -Modding: -- Fixed items/structures now falling back to the description defined in the xml even if it's empty, if the description is not defined for the selected language (instead of using English instead). -- Fixed using the "reloadwearables" and "loadwearable" console commands outside the character editor crashing the game. -- Fixed character editor crash if you first reload textures and then recreate the ragdoll. -- Changed how submarine upgrades are calculated, now no longer adds previous levels' costs to the price, but rather relies on higher increasehigh values - ---------------------------------------------------------------------------------------------------------- -v0.19.3.0 ---------------------------------------------------------------------------------------------------------- - -Unstable only: -- Fixed deconstructors and research stations showing what unidentified genetic materials are. -- Fixed fabricator not showing the number of required items on recipes. -- Fixed a crash in Fabriactor.DrawInputOverLay. -- Visual improvements to draggable item UIs. -- Fixed reactor sliders adjusting to the received signals until the received value has been matched, leading to buggy-looking behavior when the sliders adjust by themselves after the signal wires have been disconnected. Now the reactor stops following the signals if nothing is received in 1 second. -- Misc fixes and improvements to Camel. -- Fixed vote-kicked players being unable to rejoin when they're unbanned. - -Changes: -- Updated our runtime to .NET 6, which should yield significant performance improvements. Do note that this unfortunately means we'll have to drop support for macOS versions older than 10.15, but we have taken some measures to help the affected Mac players continue having access to Barotrauma. More info here https://store.steampowered.com/news/app/602960/view/3367025204056277713. -- First version of reworked tutorials. Still very much a work in progress (only the 1st tutorial that teaches you the very basics is close to done), but would still appreciate feedback! -- Changed unit load device capacity to 12 (because the sprite has space for 12) and made them waterproof. -- Changed fabricator skill calculations: the most inadequate of the required skills determines the fabrication time (instead of the average). -- Made dying drop a characters' skills towards the maximum initial skill instead of minimum. -- Added a new keybind for opening and closing the chat box. The default bind is B. -- Added a warning if a new keybind overlaps with any of player's existing binds. -- Balanced existing mineral missions: adjusted rewards & required minerals and required some minerals to be handed over to the outposts as proof of their existence. -- Added new mining missions, including some in the abyss. - -Submarines: -- Added submarine tiers. Higher-tier submarines can be upgraded futher than lower-tier submarines. -- Overhauled and balanced submarine upgrades. -- Added an upgrade that adds a mineral scanner to nav terminals and sonar monitors. -- Submarine class now affects which upgrades are available for the sub. -- Removed the Deep Diver class: the way we see it, Deep Divers didn't have a clear enough role in the game, especially considering that hull upgrades served pretty much the same purpose. In practice, the only clear benefit of a Deep Diver was being able to get through the very last levels of the campaign, and having to switch to one just for that purpose wasn't fun. Now any submarine with full hull upgrades can get all the way to the end of the campaign. - -Fixes: - Fixed a level generation issue that sometimes made the level impassable if there happened to be a cave right above the outpost. - Fixed holes on sloped walls being impossible to pass through when you're swimming straight down/up (or straight right/left depending on the wall): the walls are technically considered either horizontal or vertical (depending on the angle of the slope), and you would have to swim in a direction perpendicular to this "technical" direction of the wall. - Fixed retrying the Hognose mission making a new Hognose join your crew every time. - Fixed idling NPCs sometimes getting stuck on ladders. -- Fixed mirrored turrets being displayed backwards on status monitor. +- Fixed mirrored turrets being displayed backwards on the status monitor. - Fixed character's hands getting "stuck" if you handcuff yourself while dragging someone. - Fixed dragged character's arms not being pulled towards you, making it look like you're dragging them without touching if you run or walk away while dragging. - Fixed dragged bots slowly moving constantly, preventing them from switching to the normal standing pose. - Fixed bots having trouble fixing leaks in multi-hull rooms: they were required to be in the same hull as the leak, which prevented them from fixing leaks in e.g. R-29's bilge. - Fixed combat missions not ending the round if both crews are dead. - Fixed bots stating the name of the character they're firing at with turrets, making it seem like they know the name of every pirate they come across and magically recognize them through the walls of the enemy sub. -- Fixed chaingun rotation speed not being affected by the weapons skill. +- Fixed Chaingun rotation speed not being affected by the weapons skill. - Fixed crashing when using ':' in item assembly names on Linux platforms. - Fixed ImmuneToPressure ability flag being ignored on characters who don't need air (in practice meaning that you can get killed by pressure if you get huskified even if you have a talent that makes you immune to pressure). - Fixed geneticmaterialcrawler_unresearched3 producing mudraptor genes. - -Submarine editor: -- Fixed sub editor background images not saving. - -Optimization: -- Optimized affliction that apply other afflictions on the character (e.g. radiation sickness, drunkenness, opiate withdrawal). -- Physics optimization: fixed submerged items' physics bodies staying active indefinitely even after they've come to rest due to buoyant forces being applied on them constantly. Now we stop updating bodies that have come to rest on the floor and aren't light enough to float. -- Optimized AI objectives that make the bots fetch items (combat, contain item, decontain item, get item). - -Multiplayer: -- Fixed "kick" button staying disabled indefinitely if you vote to kick someone and the vote doesn't go through. -- Fixed Steamworks publish tab showing the "free weekend" message when using Steam family sharing. - -Modding: -- Fixed inability to localize item names if the name is defined directly in the item config. -- Allowed defining where mineral mission resources are spawned using the "positiontype" attribute. The supported types are "MainPath", "SidePath", "Cave", and "AbyssCave". - ---------------------------------------------------------------------------------------------------------- -v0.19.2.0 ---------------------------------------------------------------------------------------------------------- - -Unstable only: -- Fixed an item getting placed in the sub editor when you select one from the entity list. -- Made flak cannon ammo proximity-triggered. -- Made flak cannon's sounds and visual effects more powerful. -- Fixed LightComponents turning themselves on when the round starts. -- Fixed "Input string was not in a correct format" when loading favorite/recent servers with an empty QueryPort. -- Fixed deconstructor showing contained items in the deconstruction output. -- Fixed double coilgun sometimes not playing a sound on every shot. -- Change the cursor to a hand on draggable item UIs. -- Fixed crashing during level generation if abyss resources have not been configured. -- Fixed hull & item repairs (and presumably replacing lost shuttles) not working in single player unless you save and reload. -- Visual improvements to Camel. -- Fixed timer that prevents recently joined players from voting to kick working the wrong way around. -- Fixed inability to resize a resizeable structure when placing it in the sub editor. - -Changes: -- Reintroduced separate local/radio voice chat keys as a legacy option. Now it's again possible to speak with voice activation by default and use a push-to-talk button for radio, the same way as before, by setting the chat mode to Local and using the new radio voice chat hotkey. -- Changed reactor temperature bar colors (from blue to red). -- Higher quality stun batons cause heavier stun. -- Disabled the autodocking prompt (which verifies whether you actually want to dock when docking is initiated by an automated circuit) in single player. -- Minor tweaks to the end of PvP missions to make them a little less underwhelming: instead of ending the round immediately when one team is dead (without even giving enough time to see the enemy die), there's a bried delay, a message box and a camera transition to let the players see what happened. - -Submarines: -- Fixed floating light component in Orca 2. -- Medical fabricator now consumes 500 power on all submarines, to be consistent with other fabricators -- Rebalanced Engine Force values to better match hull size. Most Scouts (Azimuth, Orca2, Remora, Winterhalter) are now faster. Humpback, Typhon and Orca slightly slower. -- Winterhalter and Remora are now Scout class ships, Deep Diver class will be removed. -- Introduced submarine tiers. Submarine tiers and class affect the max level of submarine upgrades that apply / can be bought. -- Updated prices of all submarines to match tiers. -- Gave Typhon 2 better stats and even more firepower, to outclass the original Typhon. -- Improved R-29 speed and gave a Flak cannon -- Added Large weapon hardpoints to Berilia to make it a Tier 3 transport. - -Optimization: -- Optimizations to the talent system, particularly when the talent menu is open and when there's a large number of talents (e.g. when using mods that make all talents available to every class). - -Multiplayer: -- Significantly sped up file transfers (mods, submarine files, campaign saves). -- The minimum kick vote counts are no longer rounded down. Previously if you had for example four players on the server and the minimum vote count set to 60%, kicking would require 2 votes, now it requires 3. - -Submarine editor: -- Fixed turret lightsource rotation not refreshing in the sub editor when flipping the item. -- Fixed turret lightsource rotation not refreshing in the sub editor when flipping the item. - -Fixes: - Fixed linked subs still sometimes getting placed on the wrong side of the docking port when switching subs. -- Fixed PvP team assignment sometimes being wildly imbalanced, even if there's enough players with no preference to make the team sizes equal. - Fixes to ruin door connections, wiring and connection panels. - Fixed "insurance policy" giving the money to the dead character instead of the bank. - Fixed damage to mirrored wall pieces resetting between rounds. - Increased the minimum width of cave tunnels to prevent impassable paths. - Fixed deconstructor input slots becoming unlocked when starting a new round while the deconstructor is running. - -Modding: -- Fixed console errors when trying to check int values with PropertyConditionals. -- Fixed melee weapon's StrikingPowerMultiplier only affecting the afflictions defined in the Attack, not ones defined in the status effect. - ---------------------------------------------------------------------------------------------------------- -v0.19.1.0 ---------------------------------------------------------------------------------------------------------- - -Unstable only: -- Option to lock or reset draggable item UIs. -- Force item UI layout update when resolution changes. Fixes item repositioned item UIs potentially getting left outside the window when switching to a smaller resolution. -- Item UIs can't be dragged under each other. -- Fixed dragging a wire in a connection panel dragging the panel too if you bring the cursor close to the edges of the panel. -- Fixed seated bots being unable to get up from the chair. -- Fixed some more unwired lights in ResearchModule_02_Colony. -- Fixed another minor gap issue in Winterhalter. -- Fixed hull/item repairs and the money spent on them appearing to reset if you join mid-round after repairs have been purchased. -- Fixed light source staying in place after detaching a glowing item (e.g. mineral) from a wall. -- Fixed server trying to place all previously spawned respawn items into containers on every respawn, even if the items have already been removed. Happened because we never cleared respawnItems, and because we used that list when placing new respawn items into containers. - -Changes and additions: -- Overvoltage makes devices perform better, increasing the output of engines, making fabricators, deconstructors and pumps operate faster, electrical discharge coils do more damage, batteries recharge faster and oxygen generators generate more oxygen. Incentivizes operating the reactor manually and hopefully makes it a little more engaging. -- Added more randomness to junction box overvoltage damage, and made partially damaged boxes take more damage from overvoltage. Prevents all boxes from breaking at the same time, making overvoltage less of a pain in the ass to deal with and intentionally overvolting the devices more worthwhile. -- Experimental: Added a way to immediately increase/decrease the temperature of the reactor for a brief amount of time (atm bumps the gauge up/down by a fifth, and the boost fades out in 20 seconds). Allows reacting to load fluctuations very quickly, and to conserve fuel by operating the reactor at a lower fission rate = serves as another incentive to operate it manually. -- Signals no longer set the fission and turbine rates of the reactor instantaneously, making automated reactor circuits less overpowered. They are still viable, but especially now with the addition of the extra incentives for operating the reactor manually, they're no longer as clearly the best and most efficient way to operate the reactor, making manual operation more worthwhile. -- Added a Large Weapon Hardpoint. -- Railgun is now considered a large weapon. -- Added Flak Cannon and Double Coilgun as large weapons. -- Pulse Laser and Railgun now have similar power consumption as other turrets. -- Improved the way drag is applied on submerged items. Fixes heavy items dropping at unnaturally high speeds in water. -- Added a splash effect when an item falls into water. - -Balance: -- Reduced the pulse laser tri-laser bolt spread. -- Explosions are now calculated differently, using the number of limbs to divide the damage (to a max of 15 limbs). Adjusted explosion damage values to match new calculations. -- Coilgun costs 5000 to install, Pulse Laser and Chaingun 6000. Large turrets all cost 7500. -- Make mudraptor eggs slightly viable for farming (decreased cost from shop, increased deconstruction yields) -- Mineral yield and spawn rates rebalance, minerals found are now much more dependant on location (biome, cave, abyss) - -Submarines: -- Added a new intermediate transport sub, Camel. Still WIP, but feedback is welcome. -- Fixed messy wiring in Typhon 2's bottom left hardpoint. -- Added some loose vents and panels to Herja, Winterhalter and Barsuk, fixed invisible "loose panel" (news stand) in Orca 2. - -Fixes: -- Fixed brief freezes when monsters spawn mid-round. +- Fixed Grenade Launcher quality doing basically nothing, because it increased the minuscule amount of blunt force trauma the grenade causes on impact instead of the explosion damage. - Fixed vitality modifiers not being taken into account in the readings in the health interface. For example, gunshot wounds on the head cause a x2 larger vitality drop than on other limbs, but this wasn't displayed on the health interface. - Fixed Planet Neon Sign sprite bleed. -- Fixed Grenade Launcher quality doing basically nothing, because it increased the minuscule amount of blunt force trauma the grenade causes on impact instead of the explosion damage. -- Fixed level resource spawn rate not properly respecting level generations parameters' resource spawn chance values. +- Fixed level resource spawn rate not properly respecting the resource spawn chance values of level generation parameters. - Fixed some text overflows in the hiring menu when using a small HUD scale. - Fixed name on an ID card resetting to the original name if you rename a character and then start a new round. - Fixed handcuffs in the backmost hand being drawn in front of the character. - Fixed water splashes appearing in an incorrect hull when a character's limb moves from a flooded hull to another hull, where the limb is no longer underwater. -- Fixed crashing when a signal causes a wired item to get dropped (e.g. when you attach a detonator to a destructible ice wall and blow it up). +- Fixed crashing when a signal causes a wired item to be dropped (e.g. when you attach a detonator to a destructible ice wall and blow it up). - Oxygen generators and shelves don't fill up oxygen tanks when on fire. Caused repeated explosions when the tank constantly refilled and re-exploded. - Fixed "gene harvester" and "deep sea slayer" working on all enemies, not just monsters. -- Fixed floating point inaccuracy sometimes preventing items from being used as fabrication ingredients (e.g. oxygen generator may sometimes only fill tanks up to something like 99.9998%, which prevented it from being used in recipes that require a full tank). +- Fixed floating point inaccuracy sometimes preventing items from being used as fabrication ingredients (e.g. an oxygen generator may sometimes only fill tanks up to something like 99.9998%, which prevented it from being used in recipes that require a full tank). - Fixed item picking timer (e.g. detaching an item from a wall) ticking down when the game is paused. -- Fixed outpost supply cabs missing the oxygen tank spawns. -- Made the water current outside the levels start from the same point where monsters start heading towards the level, to make sure monsters can't escape too far from sub with a weak engine. +- Fixed outpost supply cabinets missing the oxygen tank spawns. +- Made the water current outside the levels start from the same point where monsters start heading towards the level, to make sure monsters can't escape too far from subs with a weak engine. - Fixed hardened diving knife recipe. - Fixed probability multiplier not being shown in wearable tooltip if the damage multiplier is 1. - Yet another attempt to prevent beacon missions from failing for apparently no reason: sonar monitors won't get damaged by water after the beacon's been activated. -- Don't stop selecting text in a textbox if the cursor goes outside the box. - -Multiplayer: -- Fixed clients getting stuck in the loading screen if they happen to disconnect at the right moment between rounds. -- Fixed bank balance not getting corrected if it's gotten desynced by e.g. client-side commands. -- Fixed server not registering a client's character as disconnected if the client disconnects and reconnects before the round has fully started, causing the client to get stuck as a spectator when they rejoin. -- Fixed clients disabling their client-side-only mods when they join a server. -- Fixed hull/item repairs purchased from an outpost sometimes not getting applied client-side. - -Submarine editor: -- Fixed prefab placement breaking in the sub editor if LMB is held while moving the cursor outside of the selection panel. -- Fixed several instances of janky UI interactions in the submarine editor: dragging selection rectangle now works even if cursor reaches into the prefab list, letting go of a dragged entity works even if cursor reaches into the prefab list, dragged entity no longer goes invisible when reaching into the prefab list. -- Made PowerContainer recharge speed always default to 0. -- Fixed adding resizeable items (like ladders) not being registered in sub editor's command history, preventing undoing it. - -Modding: -- Added DamageMultiplier and LaunchImpulse to Turret. LaunchImpulse is now defined on turrets instead of ammunition (total impulse is the sum of turret + ammunition). -- Added SnapRopeOnNewAttack property to Attacks: allows characters to switch attacks without snapping ropes from previous attacks. -- Added dividebylimbcount to Explosion, which determines whether the damage is spread out among limbs (if set to true). -- UpgradeCategories with no upgrades in them are hidden from the upgrade menu (i.e. if you modify the upgrades so some of the vanilla categories no longer contain any upgrades, those categories won't be shown). -- Fixed affliction names and descriptions being empty if they're not available in the selected language nor configured in the affliction xml directly. -- Fix custom infected husks seeking for any husk infection targeting the matching species instead of checking that also the husk affliction prefab matches the husk. - ---------------------------------------------------------------------------------------------------------- -v0.19.0.0 ---------------------------------------------------------------------------------------------------------- - -Changes: -- Device/item UIs can be moved around by dragging. -- Allow using devices while on a ladder or sitting on a chair. -- Readded the option to have separate push-to-talk binds for local and radio voice chat (by default not bind to anything). -- The deconstructor UI shows what the input items deconstruct to (particularly important now with the lossy deconstruction recipes - it can be risky to deconstruct something just to see what materials it gives out if that results in material loss). -- Wall and device repair costs in outposts are calculated based on the amount of damage in your sub, instead of always having a fixed price. -- Inflamed lung doesn't affect characters that don't need oxygen. -- Added swarm behavior for crawler husks. -- Added some more oomph to nuclear explosions. -- Adjust the alpha of the outpost service icons according to distance to make it easier to estimate where the NPC is at, show the title of the NPC when hovering the cursor over the icon. -- Added "unlockmission" console command. -- Added "setcampaignmetadata" console command (may be useful for modders creating custom scripted events for the campaign?). -- Changed how NPC "titles" work. Previously we defined "titles" for the pirates (e.g. "Pirate Lord" and such), and the title replaced the name of the NPC (which made their dialog a little awkward). Now we display both the name and the title over the character, and special outpost NPCs also have titles. -- Gave diving masks to most NPCs. -- Changed the burn overlay formula: now also the non-affected limbs get half of the effect, because it looks weird if there's a sharp contrast between the limbs. -- Restored the 3 shell railgun rack as a legacy option. -- Reworded the "respawn with penalty" prompt to make it less confusing: you always get a penalty to your skills when you die now, and Reaper's Tax is an "extra penalty" you get on top of that if you opt to respawn mid-round. The intention behind this is to incur a cost to respawning: it shouldn't be possible to get unlimited free reinforcements and supplies mid-round. -- Made SIGTERM close the linux server gracefully. -- Made respawn items (suits, scooters) spawn in the respawn shuttle's cabinets when possible. -- Show a healthbar on items (e.g. eggs and thalamus organs) when damaging them with handheld weapons (melee or ranged). - -Balance: -- "Mission cheesing" by repeatedly undocking and redocking to an outpost to reroll the mission events no longer works: new mission events don't reappear until one "world step" has passed (~10 minutes or traversing through one level). -- Balance pass on handheld weapons: adjusted reload times, damages, stun durations, recoil and ammo stack sizes. -- Reduced tools' structure damages (dual-wielded storage containers no longer chew through submarine walls in seconds). -- Increased heavy ruin wall health to make it less easy to cheese your way in to the artifact room in ruins. -- Made boomstick fire in bursts of 2 (similar to deadeye carbide) to prevent ridiculous fire rates with quick-reloading. -- Added EMP effect to nuclear depth charges for consistency. -- Changed how skill levels affect the quality of fabricated items. Previously having a skill level equal to or higher than the item's skill requirement would result in a good quality item, meaning that practically everyone could e.g. fabricate good quality oxygen tanks. Now your skill needs to be >20% from the minimum skill requirement towards 100, (e.g. if the item requires 20 skill to fabricate, 36 results in a higher quality item). -- Reduced PUCS's radiation resistance from 100% to 90%. Complete invulnerability to radiation has way too much potential for exploits and overpowered strategies. -- Adjusted supplies in pirate submarines. -- Turn some weapons' burn damage into explosion damage (wip). -- Terminal ignores empty signals. -- Reduce commonness of Molochs (as they can take a lot of time to kill, running into multiple of them can quickly become a chore) -- Remove steel requirement for depth charges. Fabricate decoy depth charges from depth charge, rather than base material. - -Multiplayer: -- Clients who've recently joined (by default 2 minutes) are not allowed to vote to kick others, and vote kicking someone always requires at least 2 votes. -- Fixed "missing entity" errors in a specific situation in multiplayer. Occurred when a respawn shuttle was enabled and loaded on the server (= i.e. in a non-outpost level), and a client disconnected and immediately reconnected. This would cause the client to deselect the respawn shuttle, and make them start the round without loading one, leading to the "missing entity" issues due to the shuttle only existing server-side. -- Fixes damage visuals not showing on characters who've died off-screen. -- Servers doent allow selecting hidden jobs (jobs only used by NPCs) as job preferences. -- Fixed ability to upgrade the sub when there's a switch pending in multiplayer. -- Fixed friendly fire and karma always showing up as disabled on dedicated servers in the server list. -- Fixed spineling spikes fired by a human with spineling genes not damaging any human characters (enemies in PvP, pirates in pirate missions) when friendly fire is disabled. -- Fixed "invalid ExecuteAttack message: limb index out of bounds" errors when you join a server where a character has fired spineling spikes with spineling genes mid-round. -- Fixed "entity not found" errors if a shuttle or submarine ends up absurdly deep in multiplayer (> 100 km). I don't even know how someone managed to pull this off. -- Fixed rapidly clicking on the mission giver with the Use input set to LMB sometimes not giving all the available missions. Happened because the conversation logic didn't check if there's another conversation active, causing the server to show a new conversation when clicking the NPC, without interrupting/continuing the previous conversation. -- Made shockjock event only show for the player triggering the event (making it visible for everyone works kind of weirdly, when the event involves talking to an NPC next to the character who triggered the event). -- Fixed outpost events getting stuck at the last ConversationAction if another client has finished the action. - -Submarines: -- Changed default reactor output from 10,000 kW to 5000 kW. -- Decreased Winterhalter reactor output, increased fuel consumption rate. -- Fixed some gap issues in Winterhalter. -- Fixed medics not having access to the toxin cabinet in Barsuk. -- Fixed medic, engineer and mechanic spawnpoints having no tags in Typhon. - -Fixes: +- Fixed text selection in a textbox stopping when the cursor goes outside the box. - Fixed fire, breach and intruder report icons not being shown to anyone. - Fixed missing/unwired lighting in ResearchModule_02_Colony. - Remove particles when switching screens (otherwise e.g. particles from the previous round are still in the level if you happen to be looking at the right spot). - Thalamus or ice walls can't be welded. - Quick-reloading tries to reload the item whose contained items have the lowest condition. In other words, if you've equipped 2 weapons, quick-reloading reloads the one with the least ammo instead of the one that's the first in your inventory. -- Fixed messed up dementonite and depleted fuel tool recipes. +- Fixed erroneous dementonite and depleted fuel tool recipes. - Fixed swapping a scaled turret/hardpoint causing the new one to be misplaced. - Fixed inability to upgrade the sub or do maintenance if you buy and opt to switch to a new sub, and then go to the submarine switch terminal to cancel the switching. - Fixed stolen items becoming non-stolen when deconstructed. -- Fixed ItemContainer UI popping up (with no visible inventory slot) when you pick one up. For example when you pick up a detonator from the floor. +- Fixed ItemContainer UI popping up (with no visible inventory slot) when you pick one up, e.g. picking up a detonator from the floor. - Fixed "[E] Rewire" hover text being shown on attachable items that haven't been attached to a wall (even though they can't be rewired until attached). -- Fixed trying to bind multiple console commands to the same key with the "binkey" command crashing the game. -- Fixed high-quality revolvers having no difference to normal-quality ones. They should get a 10% damage boost per quality level, but didn't due to incorrectly configured quality stats. +- Fixed trying to bind multiple console commands to the same key with the "bindkey" command crashing the game. +- Fixed high-quality revolvers having no difference to normal-quality ones. They should get a 10% damage boost per quality level but didn't, due to incorrectly configured quality stats. - Fixed multiple monster missions sometimes spawning the monsters close to each other, causing them to attack each other. -- Fix monsters sometimes using wrong animation parameters while idling (or moving slowly). +- Fixed monsters sometimes using the wrong animation parameters while idling (or moving slowly). - Fixed nuclear depth decoy using the same sprite as the normal depth decoy. - Fixed fractal guardian VitalityMultipliers being configured incorrectly (using the "type" attribute but with affliction identifiers instead of types). - Fixed incorrectly sized thalamus wall colliders, added background sprites to the walls. - Fixed "tried to overwrite a submarine that's not in a local package" error when loading and trying to save a submarine autosave file. - Fixed location portraits sometimes not showing up in the mission tab. Happened when we initialized the mission tab before the portrait had been loaded. -- Fixed coilguns and chainguns not always playing the firing sound when fired. Happened because their audio clips were so long (albeit mostly silence) that firing the them continously lead to a ton of clips playing simultaneously, exhausting the available audio channels. -- Fixed monster missions' sonar marker being placed incorrectly if a monster ends up inside the sub, making it look as if the monster was far outside the level. This often made it look like the monster was moving away from the sub when trying to "approach it". -- Fixed security officer tutorial getting stuck if you equip the weapons and gear before the objective to do so appears. -- Fixed bandolier (and other items that give bonuses when worn) giving the bonuses when the item is held. +- Fixed Coilguns and Chainguns not always playing the firing sound when fired. Happened because their audio clips were so long (albeit mostly silent) that firing them continuously led to a ton of clips playing simultaneously, exhausting the available audio channels. +- Fixed monster missions' sonar marker being placed incorrectly if a monster ends up inside the sub, making it look as if the monster was far outside the level. This often made it look like the monster was moving away from the sub when trying to approach its position as it appeared on the sonar? +- Fixed bandolier (and other items that give bonuses when worn) giving bonuses when the item is held. - Fixed mod texts being briefly misaligned when scrolling down the list of unpublished mods. - Fixed light sprite rotation not getting refreshed when placing an attachable item on a wall when lighting has been disabled with console commands. - Fixed supercapacitors showing 1% as the initial recharge rate because the recharge rate defaulted to 10. - Fixed some ending options of the "good samaritan" outpost event not ending the event. - Fixed random (non-mission) events disappearing from outposts when you save and quit. -Submarine editor: -- Fixed crashing when trying to multi-edit a string value in the sub editor. -- Fixed dragged object becoming invisible if you bring the cursor over an UI element in the sub editor. -- Fixed screwdrivers and wires in your "inventory" being included in the total item count in the sub editor's wiring mode. -- Fixed entities that were below the cursor when starting to resize a structure staying highlighted during resizing. -- Fixed sub editor treating the autosave interval as minutes instead of seconds (saving every 300 minutes instead of 300 seconds). - Modding: +- The tutorials are now implemented using the scripted event system, and are fully moddable. New tutorials can be implemented in xml or using the event editor, and the system could potentially be used for other types of content too (scripted "scenarios" perhaps?). +- Added DamageMultiplier and LaunchImpulse to Turret. LaunchImpulse is now defined on turrets instead of ammunition (total impulse is the sum of turret + ammunition). +- Added SnapRopeOnNewAttack property to Attacks: allows characters to switch attacks without snapping ropes from previous attacks. +- Added dividebylimbcount to Explosion, which determines whether the damage is spread out among limbs (if set to true). +- UpgradeCategories with no upgrades in them are hidden from the upgrade menu (i.e. if you modify the upgrades so some of the vanilla categories no longer contain any upgrades, those categories won't be shown). +- Added CheckTalentAction, which can be used in events to check whether a target has unlocked a specific talent. +- Changed how submarine upgrades are calculated: now no longer adds previous levels' cost to the price, but rather relies on higher increasehigh values. - Made NPC personality traits a separate content type instead of defining them in the localization files. - Fixed OnDeath status effects defined in afflictions not working. Did not affect any vanilla content. - Fixed crash when controlling a character with more than 10 "Any" inventory slots. Did not affect any vanilla content. - Fixed custom husk appendages' textures failing to load. - Added new properties to StatusEffect's SpawnCharacter feature: Stun, AfflictionOnSpawn, AfflictionStrength, TransferControl, RemovePreviousCharacter, TransferBuffs, TransferAfflictions, TransferInventory. - Fixed bots always choosing their "personality trait" from the first 6 even if more are modded in. +- Fixed affliction names and descriptions being empty if they're not available in the selected language or configured in the affliction .xml file directly. +- Fixed custom husk afflictions not always working properly, because the vanilla husk affliction was sometimes used instead of the custom husk affliction. +- Fixed ExtraLoad working the wrong way around on PowerTransfer components that generate/consume power (the extra load would supply power to the grid). Does not affect the vanilla game, because neither junction boxes or relays generate or consume power. +- Fixed crashing if Afflictions defined in an Attack can't be found. +- Fixed crashing if a Throwable has an OnActive StatusEffect that removes or kills the user. +- Fixed items/structures falling back to the description defined in the .xml even if it's empty, if the description is not defined for the selected language. Now descriptions fall back to English when not defined for the selected language. +- Fixed the "reloadwearables" and "loadwearable" console commands crashing the game when used outside the character editor. +- Fixed character editor crash if you first reload textures and then recreate the ragdoll. +- Fixed inability to localize item names if the name is defined directly in the item config. +- Allowed defining where mineral mission resources are spawned using the "positiontype" attribute. The supported types are "MainPath", "SidePath", "Cave", and "AbyssCave". +- Fixed console errors when trying to check int values with PropertyConditionals. +- Fixed melee weapon's StrikingPowerMultiplier only affecting the afflictions defined in the Attack, not the ones defined in the status effect. --------------------------------------------------------------------------------------------------------- v0.18.15.2 (MacOS only) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 770fb43d8..05b530ad5 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -16,12 +16,12 @@ Before you start doing modifications to the code or submitting pull requests to ### Getting started #### Windows and macOS -You need a version of Visual Studio that supports C# 8.0 to compile game. If you don't have a compatible version of Visual Studio installed, you can get the latest version of Visual Studio from the following link: https://visualstudio.microsoft.com/ +You need a version of Visual Studio that supports C# 10 to compile game. If you don't have a compatible version of Visual Studio installed, you can get the latest version of Visual Studio from the following link: https://visualstudio.microsoft.com/ When installing on Windows, make sure you select ".NET desktop development" during the install process to make sure you have the required features to work with Barotrauma. #### Linux -You will need to install the .NET Core 3.0 SDK according to the instructions laid out on Microsoft's docs: https://docs.microsoft.com/en-us/dotnet/core/install/linux-package-manager-ubuntu-1904 +You will need to install the .NET 6 SDK according to the instructions laid out on Microsoft's docs: https://docs.microsoft.com/en-us/dotnet/core/install/linux To edit the source code, we recommend using [Visual Studio Code](https://code.visualstudio.com/) with [Microsoft's C# extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode.csharp). @@ -38,7 +38,7 @@ To develop from Visual Studio, open the solution that corresponds to the platfor You can also use your favorite source editor and build through the command line by navigating to the projects you wish to build and running the following command: `dotnet build [project].csproj -c [Debug/Release] /p:Platform=x64` -To deploy for release, run the scripts in the `Deploy` directory; the resulting binaries you'll want to redistribute should be found at `Barotrauma/bin/Release[Windows/Mac/Linux]/netcoreapp3.0/[win-x64/osx-x64/linux-x64]/publish` +To build for release, run one of the scripts found in the `Deploy` directory. The resulting binaries should be found at `Barotrauma/Deploy/bin/content`. The `BarotraumaShared/Content` folder, which contains Barotrauma's art, item XMLs, sounds, and other assets, is not included in the GitHub repository. If you have a legal copy of the game, you can copy the `Content` folder from the game's files to `BarotraumaShared/Content`. diff --git a/Libraries/GameAnalytics/GA_SDK_NETSTANDARD/GA_SDK_NETSTANDARD.csproj b/Libraries/GameAnalytics/GA_SDK_NETSTANDARD/GA_SDK_NETSTANDARD.csproj index aab701817..6b99d030a 100644 --- a/Libraries/GameAnalytics/GA_SDK_NETSTANDARD/GA_SDK_NETSTANDARD.csproj +++ b/Libraries/GameAnalytics/GA_SDK_NETSTANDARD/GA_SDK_NETSTANDARD.csproj @@ -26,7 +26,7 @@ - + diff --git a/LinuxSolution.sln b/LinuxSolution.sln index 095528d41..6d0f82d4f 100644 --- a/LinuxSolution.sln +++ b/LinuxSolution.sln @@ -41,6 +41,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MonoGame.Framework.Linux.Ne EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LinuxTest", "Barotrauma\BarotraumaTest\LinuxTest.csproj", "{F1B80D94-8BD6-48CE-8D17-BB2A5C98BCA3}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DeployAll", "Deploy\DeployAll\DeployAll.csproj", "{60B82E13-2CDD-4C74-8373-FD7264D6C80B}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -195,6 +197,18 @@ Global {F1B80D94-8BD6-48CE-8D17-BB2A5C98BCA3}.Unstable|Any CPU.Build.0 = Debug|Any CPU {F1B80D94-8BD6-48CE-8D17-BB2A5C98BCA3}.Unstable|x64.ActiveCfg = Debug|Any CPU {F1B80D94-8BD6-48CE-8D17-BB2A5C98BCA3}.Unstable|x64.Build.0 = Debug|Any CPU + {60B82E13-2CDD-4C74-8373-FD7264D6C80B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {60B82E13-2CDD-4C74-8373-FD7264D6C80B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {60B82E13-2CDD-4C74-8373-FD7264D6C80B}.Debug|x64.ActiveCfg = Debug|Any CPU + {60B82E13-2CDD-4C74-8373-FD7264D6C80B}.Debug|x64.Build.0 = Debug|Any CPU + {60B82E13-2CDD-4C74-8373-FD7264D6C80B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {60B82E13-2CDD-4C74-8373-FD7264D6C80B}.Release|Any CPU.Build.0 = Release|Any CPU + {60B82E13-2CDD-4C74-8373-FD7264D6C80B}.Release|x64.ActiveCfg = Release|Any CPU + {60B82E13-2CDD-4C74-8373-FD7264D6C80B}.Release|x64.Build.0 = Release|Any CPU + {60B82E13-2CDD-4C74-8373-FD7264D6C80B}.Unstable|Any CPU.ActiveCfg = Debug|Any CPU + {60B82E13-2CDD-4C74-8373-FD7264D6C80B}.Unstable|Any CPU.Build.0 = Debug|Any CPU + {60B82E13-2CDD-4C74-8373-FD7264D6C80B}.Unstable|x64.ActiveCfg = Debug|Any CPU + {60B82E13-2CDD-4C74-8373-FD7264D6C80B}.Unstable|x64.Build.0 = Debug|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -213,6 +227,7 @@ Global {2B0881F6-9C67-4446-A1F2-FC042763A462} = {68B18BE6-9EE0-49DA-AE3A-4C7326F768F9} {33E95A21-E071-4432-819F-AA64CF3EF3F1} = {DE36F45F-F09E-4719-B953-00D148F7722A} {F1B80D94-8BD6-48CE-8D17-BB2A5C98BCA3} = {68B18BE6-9EE0-49DA-AE3A-4C7326F768F9} + {60B82E13-2CDD-4C74-8373-FD7264D6C80B} = {F35DF9BF-0BED-4FEF-A51C-DD83C531882F} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {17032EAB-554B-4B44-A4F6-EFB177ACAB7A} diff --git a/MacSolution.sln b/MacSolution.sln index 20e699038..77418fa58 100644 --- a/MacSolution.sln +++ b/MacSolution.sln @@ -31,6 +31,9 @@ EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MacServer", "Barotrauma\BarotraumaServer\MacServer.csproj", "{8C3F4314-E5CA-4563-BEE6-69E97CAA0813}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MacClient", "Barotrauma\BarotraumaClient\MacClient.csproj", "{F17FB469-E9E6-4B1C-B887-4FE709D4D771}" + ProjectSection(ProjectDependencies) = postProject + {8C3F4314-E5CA-4563-BEE6-69E97CAA0813} = {8C3F4314-E5CA-4563-BEE6-69E97CAA0813} + EndProjectSection EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MonoGame.Framework.MacOS.NetStandard", "Libraries\MonoGame.Framework\Src\MonoGame.Framework\MonoGame.Framework.MacOS.NetStandard.csproj", "{35DDDA7D-328D-4A5D-BCBB-2E60C830A899}" EndProject @@ -38,6 +41,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Facepunch.Steamworks.Posix" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MacTest", "Barotrauma\BarotraumaTest\MacTest.csproj", "{20BC9336-B439-4BF1-8B65-D587DBF421D1}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DeployAll", "Deploy\DeployAll\DeployAll.csproj", "{36B38D18-3574-4B67-A89C-FD3C2D39F1D6}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -192,6 +197,18 @@ Global {20BC9336-B439-4BF1-8B65-D587DBF421D1}.Unstable|Any CPU.Build.0 = Debug|Any CPU {20BC9336-B439-4BF1-8B65-D587DBF421D1}.Unstable|x64.ActiveCfg = Debug|Any CPU {20BC9336-B439-4BF1-8B65-D587DBF421D1}.Unstable|x64.Build.0 = Debug|Any CPU + {36B38D18-3574-4B67-A89C-FD3C2D39F1D6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {36B38D18-3574-4B67-A89C-FD3C2D39F1D6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {36B38D18-3574-4B67-A89C-FD3C2D39F1D6}.Debug|x64.ActiveCfg = Debug|Any CPU + {36B38D18-3574-4B67-A89C-FD3C2D39F1D6}.Debug|x64.Build.0 = Debug|Any CPU + {36B38D18-3574-4B67-A89C-FD3C2D39F1D6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {36B38D18-3574-4B67-A89C-FD3C2D39F1D6}.Release|Any CPU.Build.0 = Release|Any CPU + {36B38D18-3574-4B67-A89C-FD3C2D39F1D6}.Release|x64.ActiveCfg = Release|Any CPU + {36B38D18-3574-4B67-A89C-FD3C2D39F1D6}.Release|x64.Build.0 = Release|Any CPU + {36B38D18-3574-4B67-A89C-FD3C2D39F1D6}.Unstable|Any CPU.ActiveCfg = Debug|Any CPU + {36B38D18-3574-4B67-A89C-FD3C2D39F1D6}.Unstable|Any CPU.Build.0 = Debug|Any CPU + {36B38D18-3574-4B67-A89C-FD3C2D39F1D6}.Unstable|x64.ActiveCfg = Debug|Any CPU + {36B38D18-3574-4B67-A89C-FD3C2D39F1D6}.Unstable|x64.Build.0 = Debug|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -210,6 +227,7 @@ Global {35DDDA7D-328D-4A5D-BCBB-2E60C830A899} = {DE36F45F-F09E-4719-B953-00D148F7722A} {F10CE3BB-26B8-446E-84D2-86D25E850F61} = {DE36F45F-F09E-4719-B953-00D148F7722A} {20BC9336-B439-4BF1-8B65-D587DBF421D1} = {DFD82BBD-8D05-403D-BEBC-F4C1CF783E18} + {36B38D18-3574-4B67-A89C-FD3C2D39F1D6} = {F35DF9BF-0BED-4FEF-A51C-DD83C531882F} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {17032EAB-554B-4B44-A4F6-EFB177ACAB7A} diff --git a/README.md b/README.md index 7943f78d2..e1bc8861d 100644 --- a/README.md +++ b/README.md @@ -20,8 +20,8 @@ If you're interested in working on the code, either to develop mods or to contri ## Prerequisities: ### Windows -- [Visual Studio](https://www.visualstudio.com/vs/community/) with C# 8.0 support (VS 2019 or later recommended) +- [Visual Studio](https://www.visualstudio.com/vs/community/) with C# 10 support (VS 2022 or later recommended) ### Linux -- [.NET Core 3.1 SDK](https://docs.microsoft.com/en-us/dotnet/core/install/linux-package-manager-ubuntu-1904) +- [.NET 6 SDK](https://docs.microsoft.com/en-us/dotnet/core/install/linux) ### macOS -- [Visual Studio 2019 for Mac](https://visualstudio.microsoft.com/vs/mac/) +- [Visual Studio 2022 for Mac](https://visualstudio.microsoft.com/vs/mac/) diff --git a/WindowsSolution.sln b/WindowsSolution.sln index 515450184..54c1ad98e 100644 --- a/WindowsSolution.sln +++ b/WindowsSolution.sln @@ -41,6 +41,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SharpFont.NetStandard", "Li EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WindowsTest", "Barotrauma\BarotraumaTest\WindowsTest.csproj", "{C7212AE2-A925-4225-A639-AE0653EF65B0}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DeployAll", "Deploy\DeployAll\DeployAll.csproj", "{C98FE0D0-BC7D-4806-B592-734B53016FD8}" +EndProject Global GlobalSection(SharedMSBuildProjectFiles) = preSolution Libraries\GameAnalytics\GA-SDK-MONO-SHARED\GA-SDK-MONO-SHARED.projitems*{95c4d59d-9be4-4278-b4f8-46c0ba1a3916}*SharedItemsImports = 5 @@ -123,6 +125,12 @@ Global {C7212AE2-A925-4225-A639-AE0653EF65B0}.Release|x64.Build.0 = Release|Any CPU {C7212AE2-A925-4225-A639-AE0653EF65B0}.Unstable|x64.ActiveCfg = Debug|Any CPU {C7212AE2-A925-4225-A639-AE0653EF65B0}.Unstable|x64.Build.0 = Debug|Any CPU + {C98FE0D0-BC7D-4806-B592-734B53016FD8}.Debug|x64.ActiveCfg = Debug|Any CPU + {C98FE0D0-BC7D-4806-B592-734B53016FD8}.Debug|x64.Build.0 = Debug|Any CPU + {C98FE0D0-BC7D-4806-B592-734B53016FD8}.Release|x64.ActiveCfg = Release|Any CPU + {C98FE0D0-BC7D-4806-B592-734B53016FD8}.Release|x64.Build.0 = Release|Any CPU + {C98FE0D0-BC7D-4806-B592-734B53016FD8}.Unstable|x64.ActiveCfg = Debug|Any CPU + {C98FE0D0-BC7D-4806-B592-734B53016FD8}.Unstable|x64.Build.0 = Debug|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -141,6 +149,7 @@ Global {1F318AC4-F808-4130-867F-B98DF9AA8F95} = {DE36F45F-F09E-4719-B953-00D148F7722A} {6911872D-40EF-400C-B0A1-9985A19ED488} = {DE36F45F-F09E-4719-B953-00D148F7722A} {C7212AE2-A925-4225-A639-AE0653EF65B0} = {78A9F0AA-5519-407A-9B72-2A09F5DF7068} + {C98FE0D0-BC7D-4806-B592-734B53016FD8} = {F35DF9BF-0BED-4FEF-A51C-DD83C531882F} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {17032EAB-554B-4B44-A4F6-EFB177ACAB7A}