From 7168a534eddf3f929a6e36c81dadfeef933e505a Mon Sep 17 00:00:00 2001 From: juanjp600 Date: Fri, 16 Jun 2017 16:02:07 -0300 Subject: [PATCH] Further separation of client-specific code Still not done here, just gonna push a commit now so I can pull this from elsewhere. --- BarotraumaClient/BarotraumaClient.csproj | 26 + .../Source/Characters/Character.cs | 256 +++++++++ .../Source/Characters/CharacterHUD.cs | 0 .../Source/Characters/CharacterInfo.cs | 75 +++ .../Source/Characters/CharacterSound.cs | 0 .../Source/Characters/HUDProgressBar.cs | 0 .../Source/Characters/Jobs/JobPrefab.cs | 57 ++ BarotraumaClient/Source/Characters/Limb.cs | 95 ++++ BarotraumaClient/Source/DebugConsole.cs | 496 ++++++++++++++++++ .../Source/GameSession/CrewManager.cs | 0 .../GameSession/GameModes/SinglePlayerMode.cs | 0 .../GameModes/Tutorials/BasicTutorial.cs | 0 .../GameModes/Tutorials/EditorTutorial.cs | 0 .../GameModes/Tutorials/TutorialMode.cs | 0 .../GameModes/Tutorials/TutorialType.cs | 0 .../Source/GameSession/GameSession.cs | 197 +++++++ .../Source/GameSession/ShiftSummary.cs | 0 BarotraumaClient/Source/GameSettings.cs | 479 +++++++++++++++++ .../Source/Items/CharacterInventory.cs | 82 +++ .../Source/Items/Components/ItemLabel.cs | 89 ++++ .../Source/Items/FixRequirement.cs | 191 +++++++ BarotraumaClient/Source/Items/Inventory.cs | 203 +++++++ BarotraumaClient/Source/Map/MapEntity.cs | 10 - BarotraumaClient/Source/Map/Structure.cs | 138 +++++ .../Source/Map/StructurePrefab.cs | 44 ++ BarotraumaClient/Source/Map/WayPoint.cs | 249 +++++++++ .../Source/Networking/GameServer.cs | 217 ++++++++ BarotraumaClient/Source/Networking/Voting.cs | 169 ++++++ BarotraumaClient/Source/Program.cs | 2 +- .../Source/Screens/NetLobbyScreen.cs | 19 +- BarotraumaServer/BarotraumaServer.csproj | 12 + .../Source/Characters/Character.cs | 42 ++ BarotraumaServer/Source/DebugConsole.cs | 23 + BarotraumaServer/Source/GameMain.cs | 64 ++- .../Source/GameSession/GameSession.cs | 12 + BarotraumaServer/Source/GameSettings.cs | 49 ++ .../Source/Items/CharacterInventory.cs | 20 + .../Source/Items/Components/ItemLabel.cs | 39 ++ .../Source/Networking/GameServer.cs | 35 ++ BarotraumaServer/Source/Networking/Voting.cs | 25 + BarotraumaServer/Source/Program.cs | 107 +--- .../Source/Screens/NetLobbyScreen.cs | 62 +++ BarotraumaShared/BarotraumaShared.projitems | 11 - BarotraumaShared/Source/Characters/Attack.cs | 11 +- .../Source/Characters/Character.cs | 266 +--------- .../Source/Characters/CharacterInfo.cs | 63 +-- .../Source/Characters/Jobs/JobPrefab.cs | 48 +- BarotraumaShared/Source/Characters/Limb.cs | 106 +--- .../Source/Characters/StatusEffect.cs | 45 +- BarotraumaShared/Source/DebugConsole.cs | 482 +---------------- .../Source/GameSession/GameSession.cs | 229 ++------ BarotraumaShared/Source/GameSettings.cs | 455 +--------------- .../Source/Items/CharacterInventory.cs | 69 +-- .../Items/Components/Holdable/Propulsion.cs | 28 +- .../Source/Items/Components/ItemComponent.cs | 2 + .../Source/Items/Components/ItemLabel.cs | 83 +-- .../Source/Items/FixRequirement.cs | 164 +----- BarotraumaShared/Source/Items/Inventory.cs | 215 +------- BarotraumaShared/Source/Map/MapEntity.cs | 9 + BarotraumaShared/Source/Map/Structure.cs | 138 +---- .../Source/Map/StructurePrefab.cs | 35 +- BarotraumaShared/Source/Map/WayPoint.cs | 242 +-------- .../Source/Networking/GameServer.cs | 242 ++------- BarotraumaShared/Source/Networking/Voting.cs | 160 +----- 64 files changed, 3733 insertions(+), 2954 deletions(-) create mode 100644 BarotraumaClient/Source/Characters/Character.cs rename {BarotraumaShared => BarotraumaClient}/Source/Characters/CharacterHUD.cs (100%) create mode 100644 BarotraumaClient/Source/Characters/CharacterInfo.cs rename {BarotraumaShared => BarotraumaClient}/Source/Characters/CharacterSound.cs (100%) rename {BarotraumaShared => BarotraumaClient}/Source/Characters/HUDProgressBar.cs (100%) create mode 100644 BarotraumaClient/Source/Characters/Jobs/JobPrefab.cs create mode 100644 BarotraumaClient/Source/Characters/Limb.cs create mode 100644 BarotraumaClient/Source/DebugConsole.cs rename {BarotraumaShared => BarotraumaClient}/Source/GameSession/CrewManager.cs (100%) rename {BarotraumaShared => BarotraumaClient}/Source/GameSession/GameModes/SinglePlayerMode.cs (100%) rename {BarotraumaShared => BarotraumaClient}/Source/GameSession/GameModes/Tutorials/BasicTutorial.cs (100%) rename {BarotraumaShared => BarotraumaClient}/Source/GameSession/GameModes/Tutorials/EditorTutorial.cs (100%) rename {BarotraumaShared => BarotraumaClient}/Source/GameSession/GameModes/Tutorials/TutorialMode.cs (100%) rename {BarotraumaShared => BarotraumaClient}/Source/GameSession/GameModes/Tutorials/TutorialType.cs (100%) create mode 100644 BarotraumaClient/Source/GameSession/GameSession.cs rename {BarotraumaShared => BarotraumaClient}/Source/GameSession/ShiftSummary.cs (100%) create mode 100644 BarotraumaClient/Source/GameSettings.cs create mode 100644 BarotraumaClient/Source/Items/CharacterInventory.cs create mode 100644 BarotraumaClient/Source/Items/Components/ItemLabel.cs create mode 100644 BarotraumaClient/Source/Items/FixRequirement.cs create mode 100644 BarotraumaClient/Source/Items/Inventory.cs create mode 100644 BarotraumaClient/Source/Map/Structure.cs create mode 100644 BarotraumaClient/Source/Map/StructurePrefab.cs create mode 100644 BarotraumaClient/Source/Map/WayPoint.cs create mode 100644 BarotraumaClient/Source/Networking/GameServer.cs create mode 100644 BarotraumaClient/Source/Networking/Voting.cs create mode 100644 BarotraumaServer/Source/Characters/Character.cs create mode 100644 BarotraumaServer/Source/DebugConsole.cs create mode 100644 BarotraumaServer/Source/GameSession/GameSession.cs create mode 100644 BarotraumaServer/Source/GameSettings.cs create mode 100644 BarotraumaServer/Source/Items/CharacterInventory.cs create mode 100644 BarotraumaServer/Source/Items/Components/ItemLabel.cs create mode 100644 BarotraumaServer/Source/Networking/GameServer.cs create mode 100644 BarotraumaServer/Source/Networking/Voting.cs create mode 100644 BarotraumaServer/Source/Screens/NetLobbyScreen.cs diff --git a/BarotraumaClient/BarotraumaClient.csproj b/BarotraumaClient/BarotraumaClient.csproj index debbea126..50f7f43e8 100644 --- a/BarotraumaClient/BarotraumaClient.csproj +++ b/BarotraumaClient/BarotraumaClient.csproj @@ -68,10 +68,27 @@ + + + + + + + + + + + + + + + + + @@ -89,10 +106,19 @@ + + + + + + + + + diff --git a/BarotraumaClient/Source/Characters/Character.cs b/BarotraumaClient/Source/Characters/Character.cs new file mode 100644 index 000000000..f55956cac --- /dev/null +++ b/BarotraumaClient/Source/Characters/Character.cs @@ -0,0 +1,256 @@ +using FarseerPhysics; +using FarseerPhysics.Dynamics; +using FarseerPhysics.Dynamics.Joints; +using Barotrauma.Networking; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Xml.Linq; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using Barotrauma.Particles; + +namespace Barotrauma +{ + partial class Character : Entity, IDamageable, IPropertyObject, IClientSerializable, IServerSerializable + { + private List sounds; + + //the Character that the player is currently controlling + private static Character controlled; + + public static Character Controlled + { + get { return controlled; } + set + { + if (controlled == value) return; + controlled = value; + CharacterHUD.Reset(); + + if (controlled != null) + { + controlled.Enabled = true; + } + } + } + + private Dictionary hudProgressBars; + + public Dictionary HUDProgressBars + { + get { return hudProgressBars; } + } + + private void InitProjSpecific(XDocument doc) + { + for (int i = 0; i < Enum.GetNames(typeof(InputType)).Length; i++) + { + keys[i] = new Key(GameMain.Config.KeyBind((InputType)i)); + } + + var soundElements = doc.Root.Elements("sound").ToList(); + + sounds = new List(); + foreach (XElement soundElement in soundElements) + { + sounds.Add(new CharacterSound(soundElement)); + } + + hudProgressBars = new Dictionary(); + } + + public static void AddAllToGUIUpdateList() + { + for (int i = 0; i < CharacterList.Count; i++) + { + CharacterList[i].AddToGUIUpdateList(); + } + } + + public virtual void AddToGUIUpdateList() + { + if (controlled == this) + { + CharacterHUD.AddToGUIUpdateList(this); + } + } + + private void UpdateControlled(float deltaTime) + { + if (controlled == this) + { + Lights.LightManager.ViewTarget = this; + CharacterHUD.Update(deltaTime, this); + + foreach (HUDProgressBar progressBar in hudProgressBars.Values) + { + progressBar.Update(deltaTime); + } + + foreach (var pb in hudProgressBars.Where(pb => pb.Value.FadeTimer <= 0.0f).ToList()) + { + hudProgressBars.Remove(pb.Key); + } + } + } + + public void Draw(SpriteBatch spriteBatch) + { + if (!Enabled) return; + + AnimController.Draw(spriteBatch); + } + + public void DrawHUD(SpriteBatch spriteBatch, Camera cam) + { + CharacterHUD.Draw(spriteBatch, this, cam); + } + + public virtual void DrawFront(SpriteBatch spriteBatch, Camera cam) + { + if (!Enabled) return; + + if (GameMain.DebugDraw) + { + AnimController.DebugDraw(spriteBatch); + + if (aiTarget != null) aiTarget.Draw(spriteBatch); + } + + /*if (memPos != null && memPos.Count > 0 && controlled == this) + { + PosInfo serverPos = memPos.Last(); + Vector2 remoteVec = ConvertUnits.ToDisplayUnits(serverPos.Position); + if (Submarine != null) + { + remoteVec += Submarine.DrawPosition; + } + remoteVec.Y = -remoteVec.Y; + + PosInfo localPos = memLocalPos.Find(m => m.ID == serverPos.ID); + int mpind = memLocalPos.FindIndex(lp => lp.ID == localPos.ID); + PosInfo localPos1 = mpind > 0 ? memLocalPos[mpind - 1] : null; + PosInfo localPos2 = mpind < memLocalPos.Count-1 ? memLocalPos[mpind + 1] : null; + + Vector2 localVec = ConvertUnits.ToDisplayUnits(localPos.Position); + Vector2 localVec1 = localPos1 != null ? ConvertUnits.ToDisplayUnits(((PosInfo)localPos1).Position) : Vector2.Zero; + Vector2 localVec2 = localPos2 != null ? ConvertUnits.ToDisplayUnits(((PosInfo)localPos2).Position) : Vector2.Zero; + if (Submarine != null) + { + localVec += Submarine.DrawPosition; + localVec1 += Submarine.DrawPosition; + localVec2 += Submarine.DrawPosition; + } + localVec.Y = -localVec.Y; + localVec1.Y = -localVec1.Y; + localVec2.Y = -localVec2.Y; + + //GUI.DrawLine(spriteBatch, remoteVec, localVec, Color.Yellow, 0, 10); + if (localPos1 != null) GUI.DrawLine(spriteBatch, remoteVec, localVec1, Color.Lime, 0, 2); + if (localPos2 != null) GUI.DrawLine(spriteBatch, remoteVec + Vector2.One, localVec2 + Vector2.One, Color.Red, 0, 2); + } + + Vector2 mouseDrawPos = CursorWorldPosition; + mouseDrawPos.Y = -mouseDrawPos.Y; + GUI.DrawLine(spriteBatch, mouseDrawPos - new Vector2(0, 5), mouseDrawPos + new Vector2(0, 5), Color.Red, 0, 10); + + Vector2 closestItemPos = closestItem != null ? closestItem.DrawPosition : Vector2.Zero; + closestItemPos.Y = -closestItemPos.Y; + GUI.DrawLine(spriteBatch, closestItemPos - new Vector2(0, 5), closestItemPos + new Vector2(0, 5), Color.Lime, 0, 10);*/ + + if (this == controlled || GUI.DisableHUD) return; + + Vector2 pos = DrawPosition; + pos.Y = -pos.Y; + + if (speechBubbleTimer > 0.0f) + { + GUI.SpeechBubbleIcon.Draw(spriteBatch, pos - Vector2.UnitY * 100.0f, + speechBubbleColor * Math.Min(speechBubbleTimer, 1.0f), 0.0f, + Math.Min((float)speechBubbleTimer, 1.0f)); + } + + if (this == controlled) return; + + if (info != null) + { + Vector2 namePos = new Vector2(pos.X, pos.Y - 110.0f - (5.0f / cam.Zoom)) - GUI.Font.MeasureString(Info.Name) * 0.5f / cam.Zoom; + Color nameColor = Color.White; + + if (Character.Controlled != null && TeamID != Character.Controlled.TeamID) + { + nameColor = Color.Red; + } + GUI.Font.DrawString(spriteBatch, Info.Name, namePos + new Vector2(1.0f / cam.Zoom, 1.0f / cam.Zoom), Color.Black, 0.0f, Vector2.Zero, 1.0f / cam.Zoom, SpriteEffects.None, 0.001f); + GUI.Font.DrawString(spriteBatch, Info.Name, namePos, nameColor, 0.0f, Vector2.Zero, 1.0f / cam.Zoom, SpriteEffects.None, 0.0f); + + if (GameMain.DebugDraw) + { + GUI.Font.DrawString(spriteBatch, ID.ToString(), namePos - new Vector2(0.0f, 20.0f), Color.White); + } + } + + if (isDead) return; + + if (health < maxHealth * 0.98f) + { + Vector2 healthBarPos = new Vector2(pos.X - 50, DrawPosition.Y + 100.0f); + + GUI.DrawProgressBar(spriteBatch, healthBarPos, new Vector2(100.0f, 15.0f), health / maxHealth, Color.Lerp(Color.Red, Color.Green, health / maxHealth) * 0.8f); + } + } + + /// + /// Creates a progress bar that's "linked" to the specified object (or updates an existing one if there's one already linked to the object) + /// The progress bar will automatically fade out after 1 sec if the method hasn't been called during that time + /// + public HUDProgressBar UpdateHUDProgressBar(object linkedObject, Vector2 worldPosition, float progress, Color emptyColor, Color fullColor) + { + if (controlled != this) return null; + + HUDProgressBar progressBar = null; + if (!hudProgressBars.TryGetValue(linkedObject, out progressBar)) + { + progressBar = new HUDProgressBar(worldPosition, Submarine, emptyColor, fullColor); + hudProgressBars.Add(linkedObject, progressBar); + } + + progressBar.WorldPosition = worldPosition; + progressBar.FadeTimer = Math.Max(progressBar.FadeTimer, 1.0f); + progressBar.Progress = progress; + + return progressBar; + } + + public void PlaySound(CharacterSound.SoundType soundType) + { + if (sounds == null || sounds.Count == 0) return; + + var matchingSounds = sounds.FindAll(s => s.Type == soundType); + if (matchingSounds.Count == 0) return; + + var selectedSound = matchingSounds[Rand.Int(matchingSounds.Count)]; + selectedSound.Sound.Play(1.0f, selectedSound.Range, AnimController.WorldPosition); + } + + private void ImplodeFX() + { + Vector2 centerOfMass = AnimController.GetCenterOfMass(); + + SoundPlayer.PlaySound("implode", 1.0f, 150.0f, WorldPosition); + + for (int i = 0; i < 10; i++) + { + Particle p = GameMain.ParticleManager.CreateParticle("waterblood", + ConvertUnits.ToDisplayUnits(centerOfMass) + Rand.Vector(5.0f), + Rand.Vector(10.0f)); + if (p != null) p.Size *= 2.0f; + + GameMain.ParticleManager.CreateParticle("bubbles", + ConvertUnits.ToDisplayUnits(centerOfMass) + Rand.Vector(5.0f), + new Vector2(Rand.Range(-50f, 50f), Rand.Range(-100f, 50f))); + } + } + } +} diff --git a/BarotraumaShared/Source/Characters/CharacterHUD.cs b/BarotraumaClient/Source/Characters/CharacterHUD.cs similarity index 100% rename from BarotraumaShared/Source/Characters/CharacterHUD.cs rename to BarotraumaClient/Source/Characters/CharacterHUD.cs diff --git a/BarotraumaClient/Source/Characters/CharacterInfo.cs b/BarotraumaClient/Source/Characters/CharacterInfo.cs new file mode 100644 index 000000000..348b94069 --- /dev/null +++ b/BarotraumaClient/Source/Characters/CharacterInfo.cs @@ -0,0 +1,75 @@ +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Xml.Linq; + +namespace Barotrauma +{ + partial class CharacterInfo + { + + public GUIFrame CreateInfoFrame(Rectangle rect) + { + GUIFrame frame = new GUIFrame(rect, Color.Transparent); + frame.Padding = new Vector4(10.0f, 10.0f, 10.0f, 10.0f); + + return CreateInfoFrame(frame); + } + + public GUIFrame CreateInfoFrame(GUIFrame frame) + { + new GUIImage(new Rectangle(0, 0, 30, 30), HeadSprite, Alignment.TopLeft, frame); + + ScalableFont font = frame.Rect.Width < 280 ? GUI.SmallFont : GUI.Font; + + int x = 0, y = 0; + new GUITextBlock(new Rectangle(x + 60, y, 200, 20), Name, "", frame, font); + y += 20; + + if (Job != null) + { + new GUITextBlock(new Rectangle(x + 60, y, 200, 20), Job.Name, "", frame, font); + y += 30; + + var skills = Job.Skills; + skills.Sort((s1, s2) => -s1.Level.CompareTo(s2.Level)); + + new GUITextBlock(new Rectangle(x, y, 200, 20), "Skills:", "", frame, font); + y += 20; + foreach (Skill skill in skills) + { + Color textColor = Color.White * (0.5f + skill.Level / 200.0f); + new GUITextBlock(new Rectangle(x, y, 200, 20), skill.Name, Color.Transparent, textColor, Alignment.Left, "", frame).Font = font; + new GUITextBlock(new Rectangle(x, y, 200, 20), skill.Level.ToString(), Color.Transparent, textColor, Alignment.Right, "", frame).Font = font; + y += 20; + } + } + + + return frame; + } + + public GUIFrame CreateCharacterFrame(GUIComponent parent, string text, object userData) + { + GUIFrame frame = new GUIFrame(new Rectangle(0, 0, 0, 40), Color.Transparent, "ListBoxElement", parent); + frame.UserData = userData; + + GUITextBlock textBlock = new GUITextBlock( + new Rectangle(40, 0, 0, 25), + text, + null, null, + Alignment.Left, Alignment.Left, + "", frame, false); + textBlock.Font = GUI.SmallFont; + textBlock.Padding = new Vector4(5.0f, 0.0f, 5.0f, 0.0f); + + new GUIImage(new Rectangle(-5, -5, 0, 0), HeadSprite, Alignment.Left, frame); + + return frame; + } + + } +} diff --git a/BarotraumaShared/Source/Characters/CharacterSound.cs b/BarotraumaClient/Source/Characters/CharacterSound.cs similarity index 100% rename from BarotraumaShared/Source/Characters/CharacterSound.cs rename to BarotraumaClient/Source/Characters/CharacterSound.cs diff --git a/BarotraumaShared/Source/Characters/HUDProgressBar.cs b/BarotraumaClient/Source/Characters/HUDProgressBar.cs similarity index 100% rename from BarotraumaShared/Source/Characters/HUDProgressBar.cs rename to BarotraumaClient/Source/Characters/HUDProgressBar.cs diff --git a/BarotraumaClient/Source/Characters/Jobs/JobPrefab.cs b/BarotraumaClient/Source/Characters/Jobs/JobPrefab.cs new file mode 100644 index 000000000..71ece5041 --- /dev/null +++ b/BarotraumaClient/Source/Characters/Jobs/JobPrefab.cs @@ -0,0 +1,57 @@ +using Microsoft.Xna.Framework; +using System.Collections.Generic; +using System.Globalization; +using System.Xml.Linq; +using System.Linq; + +namespace Barotrauma +{ + partial class JobPrefab + { + public GUIFrame CreateInfoFrame() + { + int width = 500, height = 400; + + GUIFrame backFrame = new GUIFrame(Rectangle.Empty, Color.Black * 0.5f); + backFrame.Padding = Vector4.Zero; + + GUIFrame frame = new GUIFrame(new Rectangle(GameMain.GraphicsWidth / 2 - width / 2, GameMain.GraphicsHeight / 2 - height / 2, width, height), "", backFrame); + frame.Padding = new Vector4(30.0f, 30.0f, 30.0f, 30.0f); + + new GUITextBlock(new Rectangle(0, 0, 100, 20), Name, "", Alignment.TopLeft, Alignment.TopLeft, frame, false, GUI.LargeFont); + + var descriptionBlock = new GUITextBlock(new Rectangle(0, 40, 0, 0), Description, "", Alignment.TopLeft, Alignment.TopLeft, frame, true, GUI.SmallFont); + + new GUITextBlock(new Rectangle(0, 40 + descriptionBlock.Rect.Height + 20, 100, 20), "Skills: ", "", Alignment.TopLeft, Alignment.TopLeft, frame, false, GUI.LargeFont); + + int y = 40 + descriptionBlock.Rect.Height + 50; + foreach (SkillPrefab skill in Skills) + { + string skillDescription = Skill.GetLevelName((int)skill.LevelRange.X); + string skillDescription2 = Skill.GetLevelName((int)skill.LevelRange.Y); + + if (skillDescription2 != skillDescription) + { + skillDescription += "/" + skillDescription2; + } + new GUITextBlock(new Rectangle(0, y, 100, 20), + " - " + skill.Name + ": " + skillDescription, "", Alignment.TopLeft, Alignment.TopLeft, frame, false, GUI.SmallFont); + + y += 20; + } + + new GUITextBlock(new Rectangle(250, 40 + descriptionBlock.Rect.Height + 20, 0, 20), "Items: ", "", Alignment.TopLeft, Alignment.TopLeft, frame, false, GUI.LargeFont); + + y = 40 + descriptionBlock.Rect.Height + 50; + foreach (string itemName in ItemNames) + { + new GUITextBlock(new Rectangle(250, y, 100, 20), + " - " + itemName, "", Alignment.TopLeft, Alignment.TopLeft, frame, false, GUI.SmallFont); + + y += 20; + } + + return backFrame; + } + } +} diff --git a/BarotraumaClient/Source/Characters/Limb.cs b/BarotraumaClient/Source/Characters/Limb.cs new file mode 100644 index 000000000..1e5fe7d4c --- /dev/null +++ b/BarotraumaClient/Source/Characters/Limb.cs @@ -0,0 +1,95 @@ +using System; +using System.Xml.Linq; +using FarseerPhysics; +using FarseerPhysics.Dynamics; +using FarseerPhysics.Dynamics.Joints; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using Barotrauma.Items.Components; +using System.Collections.Generic; +using Barotrauma.Lights; +using System.Linq; +using System.IO; + +namespace Barotrauma +{ + partial class Limb + { + Sound hitSound; + + public Sound HitSound + { + get { return hitSound; } + } + + public void Draw(SpriteBatch spriteBatch) + { + float brightness = 1.0f - (burnt / 100.0f) * 0.5f; + Color color = new Color(brightness, brightness, brightness); + + body.Dir = Dir; + + bool hideLimb = wearingItems.Any(w => w != null && w.HideLimb); + + if (!hideLimb) + { + body.Draw(spriteBatch, sprite, color, null, scale); + } + else + { + body.UpdateDrawPosition(); + } + + if (LightSource != null) + { + LightSource.Position = body.DrawPosition; + } + + foreach (WearableSprite wearable in wearingItems) + { + SpriteEffects spriteEffect = (dir == Direction.Right) ? SpriteEffects.None : SpriteEffects.FlipHorizontally; + + Vector2 origin = wearable.Sprite.Origin; + if (body.Dir == -1.0f) origin.X = wearable.Sprite.SourceRect.Width - origin.X; + + float depth = sprite.Depth - 0.000001f; + + if (wearable.DepthLimb != LimbType.None) + { + Limb depthLimb = character.AnimController.GetLimb(wearable.DepthLimb); + if (depthLimb != null) + { + depth = depthLimb.sprite.Depth - 0.000001f; + } + } + + wearable.Sprite.Draw(spriteBatch, + new Vector2(body.DrawPosition.X, -body.DrawPosition.Y), + color, origin, + -body.DrawRotation, + scale, spriteEffect, depth); + } + + if (damage > 0.0f && damagedSprite != null && !hideLimb) + { + SpriteEffects spriteEffect = (dir == Direction.Right) ? SpriteEffects.None : SpriteEffects.FlipHorizontally; + + float depth = sprite.Depth - 0.0000015f; + + damagedSprite.Draw(spriteBatch, + new Vector2(body.DrawPosition.X, -body.DrawPosition.Y), + color * Math.Min(damage / 50.0f, 1.0f), sprite.Origin, + -body.DrawRotation, + 1.0f, spriteEffect, depth); + } + + if (!GameMain.DebugDraw) return; + + if (pullJoint != null) + { + Vector2 pos = ConvertUnits.ToDisplayUnits(pullJoint.WorldAnchorB); + GUI.DrawRectangle(spriteBatch, new Rectangle((int)pos.X, (int)-pos.Y, 5, 5), Color.Red, true); + } + } + } +} diff --git a/BarotraumaClient/Source/DebugConsole.cs b/BarotraumaClient/Source/DebugConsole.cs new file mode 100644 index 000000000..60ff53d55 --- /dev/null +++ b/BarotraumaClient/Source/DebugConsole.cs @@ -0,0 +1,496 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using Microsoft.Xna.Framework.Input; +using Barotrauma.Networking; +using Barotrauma.Items.Components; +using System.Text; +using FarseerPhysics; + +namespace Barotrauma +{ + static partial class DebugConsole + { + static bool isOpen; + + //used for keeping track of the message entered when pressing up/down + static int selectedIndex; + + public static bool IsOpen + { + get + { + return isOpen; + } + } + + static GUIFrame frame; + static GUIListBox listBox; + static GUITextBox textBox; + + private static string InputText + { + get { return textBox.Text; } + set { textBox.Text = value; } + } + + public static void Init(GameWindow window) + { + int x = 20, y = 20; + int width = 800, height = 500; + + frame = new GUIFrame(new Rectangle(x, y, width, height), new Color(0.4f, 0.4f, 0.4f, 0.8f)); + frame.Padding = new Vector4(5.0f, 5.0f, 5.0f, 5.0f); + + listBox = new GUIListBox(new Rectangle(0, 0, 0, frame.Rect.Height - 40), Color.Black, "", frame); + //listBox.Color = Color.Black * 0.7f; + + textBox = new GUITextBox(new Rectangle(0, 0, 0, 20), Color.Black, Color.White, Alignment.BottomLeft, Alignment.Left, "", frame); + //textBox.Color = Color.Black * 0.7f; + + //messages already added before initialization -> add them to the listbox + List unInitializedMessages = new List(Messages); + Messages.Clear(); + + foreach (ColoredText msg in unInitializedMessages) + { + NewMessage(msg.Text, msg.Color); + } + + NewMessage("Press F3 to open/close the debug console", Color.Cyan); + NewMessage("Enter \"help\" for a list of available console commands", Color.Cyan); + + } + + public static void AddToGUIUpdateList() + { + if (isOpen) + { + frame.AddToGUIUpdateList(); + } + } + + public static void Update(GameMain game, float deltaTime) + { + if (PlayerInput.KeyHit(Keys.F3)) + { + isOpen = !isOpen; + if (isOpen) + { + textBox.Select(); + AddToGUIUpdateList(); + } + else + { + GUIComponent.ForceMouseOn(null); + textBox.Deselect(); + } + + //keyboardDispatcher.Subscriber = (isOpen) ? textBox : null; + } + + if (isOpen) + { + frame.Update(deltaTime); + + Character.DisableControls = true; + + if (PlayerInput.KeyHit(Keys.Up)) + { + SelectMessage(-1); + } + else if (PlayerInput.KeyHit(Keys.Down)) + { + SelectMessage(1); + } + + //textBox.Update(deltaTime); + + if (PlayerInput.KeyDown(Keys.Enter) && textBox.Text != "") + { + ExecuteCommand(textBox.Text, game); + textBox.Text = ""; + + //selectedIndex = messages.Count; + } + } + } + + private static void SelectMessage(int direction) + { + int messageCount = listBox.children.Count; + if (messageCount == 0) return; + + direction = Math.Min(Math.Max(-1, direction), 1); + + selectedIndex += direction; + if (selectedIndex < 0) selectedIndex = messageCount - 1; + selectedIndex = selectedIndex % messageCount; + + textBox.Text = (listBox.children[selectedIndex] as GUITextBlock).Text; + } + + public static void Draw(SpriteBatch spriteBatch) + { + if (!isOpen) return; + + frame.Draw(spriteBatch); + } + + private static bool IsCommandPermitted(string command, GameClient client) + { + switch (command) + { + case "kick": + return client.HasPermission(ClientPermissions.Kick); + case "ban": + case "banip": + return client.HasPermission(ClientPermissions.Ban); + case "netstats": + case "help": + case "dumpids": + case "admin": + return true; + default: + return false; + } + } + + private static bool ExecProjSpecific(string[] commands) + { + switch (commands[0].ToLowerInvariant()) + { + case "startclient": + if (commands.Length == 1) return true; + if (GameMain.Client == null) + { + GameMain.NetworkMember = new GameClient("Name"); + GameMain.Client.ConnectToServer(commands[1]); + } + break; + case "mainmenuscreen": + case "mainmenu": + case "menu": + GameMain.GameSession = null; + + List characters = new List(Character.CharacterList); + foreach (Character c in characters) + { + c.Remove(); + } + + GameMain.MainMenuScreen.Select(); + break; + case "gamescreen": + case "game": + GameMain.GameScreen.Select(); + break; + case "editmapscreen": + case "editmap": + case "edit": + if (commands.Length > 1) + { + Submarine.Load(string.Join(" ", commands.Skip(1)), true); + } + GameMain.EditMapScreen.Select(); + break; + case "editcharacter": + case "editchar": + GameMain.EditCharacterScreen.Select(); + break; + case "controlcharacter": + case "control": + { + if (commands.Length < 2) break; + + var character = FindMatchingCharacter(commands, true); + + if (character != null) + { + Character.Controlled = character; + } + } + break; + case "setclientcharacter": + { + if (GameMain.Server == null) break; + + int separatorIndex = Array.IndexOf(commands, ";"); + + if (separatorIndex == -1 || commands.Length < 4) + { + ThrowError("Invalid parameters. The command should be formatted as \"setclientcharacter [client] ; [character]\""); + break; + } + + string[] commandsLeft = commands.Take(separatorIndex).ToArray(); + string[] commandsRight = commands.Skip(separatorIndex).ToArray(); + + string clientName = String.Join(" ", commandsLeft.Skip(1)); + + var client = GameMain.Server.ConnectedClients.Find(c => c.name == clientName); + if (client == null) + { + ThrowError("Client \"" + clientName + "\" not found."); + } + + var character = FindMatchingCharacter(commandsRight, false); + GameMain.Server.SetClientCharacter(client, character); + } + break; + case "test": + Submarine.Load("aegir mark ii", true); + GameMain.DebugDraw = true; + GameMain.LightManager.LosEnabled = false; + GameMain.EditMapScreen.Select(); + break; + case "shake": + GameMain.GameScreen.Cam.Shake = 10.0f; + break; + case "losenabled": + case "los": + case "drawlos": + GameMain.LightManager.LosEnabled = !GameMain.LightManager.LosEnabled; + break; + case "lighting": + case "lightingenabled": + case "light": + case "lights": + GameMain.LightManager.LightingEnabled = !GameMain.LightManager.LightingEnabled; + break; + case "tutorial": + TutorialMode.StartTutorial(Tutorials.TutorialType.TutorialTypes[0]); + break; + case "editortutorial": + GameMain.EditMapScreen.Select(); + GameMain.EditMapScreen.StartTutorial(); + break; + case "lobbyscreen": + case "lobby": + GameMain.LobbyScreen.Select(); + break; + case "savemap": + case "savesub": + case "save": + if (commands.Length < 2) break; + + if (GameMain.EditMapScreen.CharacterMode) + { + GameMain.EditMapScreen.ToggleCharacterMode(); + } + + string fileName = string.Join(" ", commands.Skip(1)); + if (fileName.Contains("../")) + { + DebugConsole.ThrowError("Illegal symbols in filename (../)"); + return true; + } + + if (Submarine.SaveCurrent(System.IO.Path.Combine(Submarine.SavePath, fileName + ".sub"))) + { + NewMessage("Sub saved", Color.Green); + //Submarine.Loaded.First().CheckForErrors(); + } + + break; + case "loadmap": + case "loadsub": + case "load": + if (commands.Length < 2) break; + + Submarine.Load(string.Join(" ", commands.Skip(1)), true); + break; + case "cleansub": + for (int i = MapEntity.mapEntityList.Count - 1; i >= 0; i--) + { + MapEntity me = MapEntity.mapEntityList[i]; + + if (me.SimPosition.Length() > 2000.0f) + { + DebugConsole.NewMessage("Removed " + me.Name + " (simposition " + me.SimPosition + ")", Color.Orange); + MapEntity.mapEntityList.RemoveAt(i); + } + else if (me.MoveWithLevel) + { + DebugConsole.NewMessage("Removed " + me.Name + " (MoveWithLevel==true)", Color.Orange); + MapEntity.mapEntityList.RemoveAt(i); + } + else if (me is Item) + { + Item item = me as Item; + var wire = item.GetComponent(); + if (wire == null) continue; + + if (wire.GetNodes().Count > 0 && !wire.Connections.Any(c => c != null)) + { + wire.Item.Drop(null); + DebugConsole.NewMessage("Dropped wire (ID: " + wire.Item.ID + ") - attached on wall but no connections found", Color.Orange); + } + } + + } + break; + case "messagebox": + if (commands.Length < 3) break; + new GUIMessageBox(commands[1], commands[2]); + break; + case "debugdraw": + GameMain.DebugDraw = !GameMain.DebugDraw; + break; + case "disablehud": + case "hud": + GUI.DisableHUD = !GUI.DisableHUD; + GameMain.Instance.IsMouseVisible = !GameMain.Instance.IsMouseVisible; + break; + case "followsub": + Camera.FollowSub = !Camera.FollowSub; + break; + case "drawaitargets": + case "showaitargets": + AITarget.ShowAITargets = !AITarget.ShowAITargets; + break; +#if DEBUG + case "spamevents": + foreach (Item item in Item.ItemList) + { + for (int i = 0; i(); + if (itemContainer != null) + { + GameMain.Server.CreateEntityEvent(item, new object[] { NetEntityEvent.Type.InventoryState }); + } + + GameMain.Server.CreateEntityEvent(item, new object[] { NetEntityEvent.Type.Status }); + + item.NeedsPositionUpdate = true; + } + } + + foreach (Character c in Character.CharacterList) + { + GameMain.Server.CreateEntityEvent(c, new object[] { NetEntityEvent.Type.Status }); + } + + foreach (Structure wall in Structure.WallList) + { + GameMain.Server.CreateEntityEvent(wall); + } + break; + case "spamchatmessages": + int msgCount = 1000; + if (commands.Length > 1) int.TryParse(commands[1], out msgCount); + int msgLength = 50; + if (commands.Length > 2) int.TryParse(commands[2], out msgLength); + + for (int i = 0; i < msgCount; i++) + { + if (GameMain.Server != null) + { + GameMain.Server.SendChatMessage(ToolBox.RandomSeed(msgLength), ChatMessageType.Default); + } + else + { + GameMain.Client.SendChatMessage(ToolBox.RandomSeed(msgLength)); + } + } + break; +#endif + case "cleanbuild": + GameMain.Config.MusicVolume = 0.5f; + GameMain.Config.SoundVolume = 0.5f; + DebugConsole.NewMessage("Music and sound volume set to 0.5", Color.Green); + + GameMain.Config.GraphicsWidth = 0; + GameMain.Config.GraphicsHeight = 0; + GameMain.Config.WindowMode = WindowMode.Fullscreen; + DebugConsole.NewMessage("Resolution set to 0 x 0 (screen resolution will be used)", Color.Green); + DebugConsole.NewMessage("Fullscreen enabled", Color.Green); + + GameSettings.VerboseLogging = false; + + if (GameMain.Config.MasterServerUrl != "http://www.undertowgames.com/baromaster") + { + DebugConsole.ThrowError("MasterServerUrl \"" + GameMain.Config.MasterServerUrl + "\"!"); + } + + GameMain.Config.Save("config.xml"); + + var saveFiles = System.IO.Directory.GetFiles(SaveUtil.SaveFolder); + + foreach (string saveFile in saveFiles) + { + System.IO.File.Delete(saveFile); + DebugConsole.NewMessage("Deleted " + saveFile, Color.Green); + } + + if (System.IO.Directory.Exists(System.IO.Path.Combine(SaveUtil.SaveFolder, "temp"))) + { + System.IO.Directory.Delete(System.IO.Path.Combine(SaveUtil.SaveFolder, "temp"), true); + DebugConsole.NewMessage("Deleted temp save folder", Color.Green); + } + + if (System.IO.Directory.Exists(ServerLog.SavePath)) + { + var logFiles = System.IO.Directory.GetFiles(ServerLog.SavePath); + + foreach (string logFile in logFiles) + { + System.IO.File.Delete(logFile); + DebugConsole.NewMessage("Deleted " + logFile, Color.Green); + } + } + + if (System.IO.File.Exists("filelist.xml")) + { + System.IO.File.Delete("filelist.xml"); + DebugConsole.NewMessage("Deleted filelist", Color.Green); + } + + + if (System.IO.File.Exists("Submarines/TutorialSub.sub")) + { + System.IO.File.Delete("Submarines/TutorialSub.sub"); + + DebugConsole.NewMessage("Deleted TutorialSub from the submarine folder", Color.Green); + } + + if (System.IO.File.Exists(GameServer.SettingsFile)) + { + System.IO.File.Delete(GameServer.SettingsFile); + DebugConsole.NewMessage("Deleted server settings", Color.Green); + } + + if (System.IO.File.Exists(GameServer.ClientPermissionsFile)) + { + System.IO.File.Delete(GameServer.ClientPermissionsFile); + DebugConsole.NewMessage("Deleted client permission file", Color.Green); + + } + + if (System.IO.File.Exists("crashreport.txt")) + { + System.IO.File.Delete("crashreport.txt"); + DebugConsole.NewMessage("Deleted crashreport.txt", Color.Green); + } + + if (!System.IO.File.Exists("Content/Map/TutorialSub.sub")) + { + DebugConsole.ThrowError("TutorialSub.sub not found!"); + } + + break; + default: + return false; //command not found + break; + } + return true; //command found + } + } +} diff --git a/BarotraumaShared/Source/GameSession/CrewManager.cs b/BarotraumaClient/Source/GameSession/CrewManager.cs similarity index 100% rename from BarotraumaShared/Source/GameSession/CrewManager.cs rename to BarotraumaClient/Source/GameSession/CrewManager.cs diff --git a/BarotraumaShared/Source/GameSession/GameModes/SinglePlayerMode.cs b/BarotraumaClient/Source/GameSession/GameModes/SinglePlayerMode.cs similarity index 100% rename from BarotraumaShared/Source/GameSession/GameModes/SinglePlayerMode.cs rename to BarotraumaClient/Source/GameSession/GameModes/SinglePlayerMode.cs diff --git a/BarotraumaShared/Source/GameSession/GameModes/Tutorials/BasicTutorial.cs b/BarotraumaClient/Source/GameSession/GameModes/Tutorials/BasicTutorial.cs similarity index 100% rename from BarotraumaShared/Source/GameSession/GameModes/Tutorials/BasicTutorial.cs rename to BarotraumaClient/Source/GameSession/GameModes/Tutorials/BasicTutorial.cs diff --git a/BarotraumaShared/Source/GameSession/GameModes/Tutorials/EditorTutorial.cs b/BarotraumaClient/Source/GameSession/GameModes/Tutorials/EditorTutorial.cs similarity index 100% rename from BarotraumaShared/Source/GameSession/GameModes/Tutorials/EditorTutorial.cs rename to BarotraumaClient/Source/GameSession/GameModes/Tutorials/EditorTutorial.cs diff --git a/BarotraumaShared/Source/GameSession/GameModes/Tutorials/TutorialMode.cs b/BarotraumaClient/Source/GameSession/GameModes/Tutorials/TutorialMode.cs similarity index 100% rename from BarotraumaShared/Source/GameSession/GameModes/Tutorials/TutorialMode.cs rename to BarotraumaClient/Source/GameSession/GameModes/Tutorials/TutorialMode.cs diff --git a/BarotraumaShared/Source/GameSession/GameModes/Tutorials/TutorialType.cs b/BarotraumaClient/Source/GameSession/GameModes/Tutorials/TutorialType.cs similarity index 100% rename from BarotraumaShared/Source/GameSession/GameModes/Tutorials/TutorialType.cs rename to BarotraumaClient/Source/GameSession/GameModes/Tutorials/TutorialType.cs diff --git a/BarotraumaClient/Source/GameSession/GameSession.cs b/BarotraumaClient/Source/GameSession/GameSession.cs new file mode 100644 index 000000000..1254f63e8 --- /dev/null +++ b/BarotraumaClient/Source/GameSession/GameSession.cs @@ -0,0 +1,197 @@ +using System; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using System.Xml.Linq; + +namespace Barotrauma +{ + partial class GameSession + { + private InfoFrameTab selectedTab; + private GUIButton infoButton; + private GUIFrame infoFrame; + + public Map Map + { + get + { + SinglePlayerMode mode = (gameMode as SinglePlayerMode); + return (mode == null) ? null : mode.Map; + } + } + + private ShiftSummary shiftSummary; + + public ShiftSummary ShiftSummary + { + get { return shiftSummary; } + } + + public bool LoadPrevious(GUIButton button, object obj) + { + Submarine.Unload(); + + SaveUtil.LoadGame(saveFile); + + GameMain.LobbyScreen.Select(); + + return true; + } + + private bool ToggleInfoFrame(GUIButton button, object obj) + { + if (infoFrame == null) + { + if (CrewManager != null && CrewManager.CrewCommander != null && CrewManager.CrewCommander.IsOpen) + { + CrewManager.CrewCommander.ToggleGUIFrame(); + } + + CreateInfoFrame(); + SelectInfoFrameTab(null, selectedTab); + } + else + { + infoFrame = null; + } + + return true; + } + + public void CreateInfoFrame() + { + int width = 600, height = 400; + + + infoFrame = new GUIFrame( + Rectangle.Empty, Color.Black * 0.8f, null); + + var innerFrame = new GUIFrame( + new Rectangle(GameMain.GraphicsWidth / 2 - width / 2, GameMain.GraphicsHeight / 2 - height / 2, width, height), "", infoFrame); + + innerFrame.Padding = new Vector4(10.0f, 10.0f, 10.0f, 10.0f); + + var crewButton = new GUIButton(new Rectangle(0, -30, 100, 20), "Crew", "", innerFrame); + crewButton.UserData = InfoFrameTab.Crew; + crewButton.OnClicked = SelectInfoFrameTab; + + var missionButton = new GUIButton(new Rectangle(100, -30, 100, 20), "Mission", "", innerFrame); + missionButton.UserData = InfoFrameTab.Mission; + missionButton.OnClicked = SelectInfoFrameTab; + + if (GameMain.Server != null) + { + var manageButton = new GUIButton(new Rectangle(200, -30, 130, 20), "Manage players", "", innerFrame); + manageButton.UserData = InfoFrameTab.ManagePlayers; + manageButton.OnClicked = SelectInfoFrameTab; + } + + var closeButton = new GUIButton(new Rectangle(0, 0, 80, 20), "Close", Alignment.BottomCenter, "", innerFrame); + closeButton.OnClicked = ToggleInfoFrame; + + } + + private bool SelectInfoFrameTab(GUIButton button, object userData) + { + selectedTab = (InfoFrameTab)userData; + + CreateInfoFrame(); + + switch (selectedTab) + { + case InfoFrameTab.Crew: + CrewManager.CreateCrewFrame(CrewManager.characters, infoFrame.children[0] as GUIFrame); + break; + case InfoFrameTab.Mission: + CreateMissionInfo(infoFrame.children[0] as GUIFrame); + break; + case InfoFrameTab.ManagePlayers: + GameMain.Server.ManagePlayersFrame(infoFrame.children[0] as GUIFrame); + break; + } + + return true; + } + + private void CreateMissionInfo(GUIFrame infoFrame) + { + if (Mission == null) + { + new GUITextBlock(new Rectangle(0, 0, 0, 50), "No mission", "", infoFrame, true); + return; + } + + new GUITextBlock(new Rectangle(0, 0, 0, 40), Mission.Name, "", infoFrame, GUI.LargeFont); + + new GUITextBlock(new Rectangle(0, 50, 0, 20), "Reward: " + Mission.Reward, "", infoFrame, true); + new GUITextBlock(new Rectangle(0, 70, 0, 50), Mission.Description, "", infoFrame, true); + + + } + + public void AddToGUIUpdateList() + { + infoButton.AddToGUIUpdateList(); + + if (gameMode != null) gameMode.AddToGUIUpdateList(); + + if (infoFrame != null) infoFrame.AddToGUIUpdateList(); + } + + public void Update(float deltaTime) + { + TaskManager.Update(deltaTime); + + if (GUI.DisableHUD) return; + + //guiRoot.Update(deltaTime); + infoButton.Update(deltaTime); + + if (gameMode != null) gameMode.Update(deltaTime); + if (Mission != null) Mission.Update(deltaTime); + if (infoFrame != null) + { + infoFrame.Update(deltaTime); + + if (CrewManager != null && CrewManager.CrewCommander != null && CrewManager.CrewCommander.IsOpen) + { + infoFrame = null; + } + } + } + + public void Draw(SpriteBatch spriteBatch) + { + if (GUI.DisableHUD) return; + + infoButton.Draw(spriteBatch); + + if (gameMode != null) gameMode.Draw(spriteBatch); + if (infoFrame != null) infoFrame.Draw(spriteBatch); + } + + public void Save(string filePath) + { + XDocument doc = new XDocument( + new XElement("Gamesession")); + + var now = DateTime.Now; + doc.Root.Add(new XAttribute("savetime", now.ToShortTimeString() + ", " + now.ToShortDateString())); + + doc.Root.Add(new XAttribute("submarine", submarine == null ? "" : submarine.Name)); + + doc.Root.Add(new XAttribute("mapseed", Map.Seed)); + + ((SinglePlayerMode)gameMode).Save(doc.Root); + + try + { + doc.Save(filePath); + } + catch + { + DebugConsole.ThrowError("Saving gamesession to \"" + filePath + "\" failed!"); + } + } + } +} diff --git a/BarotraumaShared/Source/GameSession/ShiftSummary.cs b/BarotraumaClient/Source/GameSession/ShiftSummary.cs similarity index 100% rename from BarotraumaShared/Source/GameSession/ShiftSummary.cs rename to BarotraumaClient/Source/GameSession/ShiftSummary.cs diff --git a/BarotraumaClient/Source/GameSettings.cs b/BarotraumaClient/Source/GameSettings.cs new file mode 100644 index 000000000..3d6ff6597 --- /dev/null +++ b/BarotraumaClient/Source/GameSettings.cs @@ -0,0 +1,479 @@ +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using Microsoft.Xna.Framework.Input; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Xml.Linq; + +namespace Barotrauma +{ + public enum WindowMode + { + Windowed, Fullscreen, BorderlessWindowed + } + + public partial class GameSettings + { + private GUIFrame settingsFrame; + private GUIButton applyButton; + + public GUIFrame SettingsFrame + { + get + { + if (settingsFrame == null) CreateSettingsFrame(); + return settingsFrame; + } + } + + private float soundVolume, musicVolume; + + private WindowMode windowMode; + + private KeyOrMouse[] keyMapping; + + public KeyOrMouse KeyBind(InputType inputType) + { + return keyMapping[(int)inputType]; + } + + public int GraphicsWidth { get; set; } + public int GraphicsHeight { get; set; } + + public bool VSyncEnabled { get; set; } + + public bool EnableSplashScreen { get; set; } + + //public bool FullScreenEnabled { get; set; } + + public WindowMode WindowMode + { + get { return windowMode; } + set { windowMode = value; } + } + + private bool unsavedSettings; + + public bool UnsavedSettings + { + get + { + return unsavedSettings; + } + private set + { + unsavedSettings = value; + if (applyButton != null) + { + //applyButton.Selected = unsavedSettings; + applyButton.Enabled = unsavedSettings; + applyButton.Text = unsavedSettings ? "Apply*" : "Apply"; + } + } + } + + public float SoundVolume + { + get { return soundVolume; } + set + { + soundVolume = MathHelper.Clamp(value, 0.0f, 1.0f); + Sounds.SoundManager.MasterVolume = soundVolume; + } + } + + public float MusicVolume + { + get { return musicVolume; } + set + { + musicVolume = MathHelper.Clamp(value, 0.0f, 1.0f); + SoundPlayer.MusicVolume = musicVolume; + } + } + + private void InitProjSpecific(XDocument doc) + { + if (doc == null) + { + GraphicsWidth = 1024; + GraphicsHeight = 678; + + return; + } + + XElement graphicsMode = doc.Root.Element("graphicsmode"); + GraphicsWidth = ToolBox.GetAttributeInt(graphicsMode, "width", 0); + GraphicsHeight = ToolBox.GetAttributeInt(graphicsMode, "height", 0); + VSyncEnabled = ToolBox.GetAttributeBool(graphicsMode, "vsync", true); + + if (GraphicsWidth == 0 || GraphicsHeight == 0) + { + GraphicsWidth = GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Width; + GraphicsHeight = GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Height; + } + + //FullScreenEnabled = ToolBox.GetAttributeBool(graphicsMode, "fullscreen", true); + + var windowModeStr = ToolBox.GetAttributeString(graphicsMode, "displaymode", "Fullscreen"); + if (!Enum.TryParse(windowModeStr, out windowMode)) + { + windowMode = WindowMode.Fullscreen; + } + + SoundVolume = ToolBox.GetAttributeFloat(doc.Root, "soundvolume", 1.0f); + MusicVolume = ToolBox.GetAttributeFloat(doc.Root, "musicvolume", 0.3f); + + EnableSplashScreen = ToolBox.GetAttributeBool(doc.Root, "enablesplashscreen", true); + + keyMapping = new KeyOrMouse[Enum.GetNames(typeof(InputType)).Length]; + keyMapping[(int)InputType.Up] = new KeyOrMouse(Keys.W); + keyMapping[(int)InputType.Down] = new KeyOrMouse(Keys.S); + keyMapping[(int)InputType.Left] = new KeyOrMouse(Keys.A); + keyMapping[(int)InputType.Right] = new KeyOrMouse(Keys.D); + keyMapping[(int)InputType.Run] = new KeyOrMouse(Keys.LeftShift); + + + keyMapping[(int)InputType.Chat] = new KeyOrMouse(Keys.Tab); + keyMapping[(int)InputType.CrewOrders] = new KeyOrMouse(Keys.C); + + keyMapping[(int)InputType.Select] = new KeyOrMouse(Keys.E); + + keyMapping[(int)InputType.Use] = new KeyOrMouse(0); + keyMapping[(int)InputType.Aim] = new KeyOrMouse(1); + + foreach (XElement subElement in doc.Root.Elements()) + { + switch (subElement.Name.ToString().ToLowerInvariant()) + { + case "keymapping": + foreach (XAttribute attribute in subElement.Attributes()) + { + InputType inputType; + if (Enum.TryParse(attribute.Name.ToString(), true, out inputType)) + { + int mouseButton; + if (int.TryParse(attribute.Value.ToString(), out mouseButton)) + { + keyMapping[(int)inputType] = new KeyOrMouse(mouseButton); + } + else + { + Keys key; + if (Enum.TryParse(attribute.Value.ToString(), true, out key)) + { + keyMapping[(int)inputType] = new KeyOrMouse(key); + } + } + } + } + break; + } + } + + foreach (InputType inputType in Enum.GetValues(typeof(InputType))) + { + if (keyMapping[(int)inputType] == null) + { + DebugConsole.ThrowError("Key binding for the input type \"" + inputType + " not set!"); + keyMapping[(int)inputType] = new KeyOrMouse(Keys.D1); + } + } + + + UnsavedSettings = false; + } + + public void Save(string filePath) + { + UnsavedSettings = false; + + XDocument doc = new XDocument(); + + if (doc.Root == null) + { + doc.Add(new XElement("config")); + } + + doc.Root.Add( + new XAttribute("masterserverurl", MasterServerUrl), + new XAttribute("autocheckupdates", AutoCheckUpdates), + new XAttribute("musicvolume", musicVolume), + new XAttribute("soundvolume", soundVolume), + new XAttribute("verboselogging", VerboseLogging), + new XAttribute("enablesplashscreen", EnableSplashScreen)); + + if (WasGameUpdated) + { + doc.Root.Add(new XAttribute("wasgameupdated", true)); + } + + XElement gMode = doc.Root.Element("graphicsmode"); + if (gMode == null) + { + gMode = new XElement("graphicsmode"); + doc.Root.Add(gMode); + } + + if (GraphicsWidth == 0 || GraphicsHeight == 0) + { + gMode.ReplaceAttributes(new XAttribute("displaymode", windowMode)); + } + else + { + gMode.ReplaceAttributes( + new XAttribute("width", GraphicsWidth), + new XAttribute("height", GraphicsHeight), + new XAttribute("vsync", VSyncEnabled), + new XAttribute("displaymode", windowMode)); + } + + + if (SelectedContentPackage != null) + { + doc.Root.Add(new XElement("contentpackage", + new XAttribute("path", SelectedContentPackage.Path))); + } + + var keyMappingElement = new XElement("keymapping"); + doc.Root.Add(keyMappingElement); + for (int i = 0; i < keyMapping.Length; i++) + { + if (keyMapping[i].MouseButton == null) + { + keyMappingElement.Add(new XAttribute(((InputType)i).ToString(), keyMapping[i].Key)); + } + else + { + keyMappingElement.Add(new XAttribute(((InputType)i).ToString(), keyMapping[i].MouseButton)); + } + + + } + + doc.Save(filePath); + } + + private bool ChangeSoundVolume(GUIScrollBar scrollBar, float barScroll) + { + UnsavedSettings = true; + SoundVolume = barScroll; + + return true; + } + + private bool ChangeMusicVolume(GUIScrollBar scrollBar, float barScroll) + { + UnsavedSettings = true; + MusicVolume = barScroll; + + return true; + } + + public void ResetSettingsFrame() + { + settingsFrame = null; + } + + private void CreateSettingsFrame() + { + settingsFrame = new GUIFrame(new Rectangle(0, 0, 500, 500), null, Alignment.Center, ""); + + new GUITextBlock(new Rectangle(0, -30, 0, 30), "Settings", "", Alignment.TopCenter, Alignment.TopCenter, settingsFrame, false, GUI.LargeFont); + + int x = 0, y = 10; + + new GUITextBlock(new Rectangle(0, y, 20, 20), "Resolution", "", Alignment.TopLeft, Alignment.TopLeft, settingsFrame); + var resolutionDD = new GUIDropDown(new Rectangle(0, y + 20, 180, 20), "", "", settingsFrame); + resolutionDD.OnSelected = SelectResolution; + + var supportedModes = new List(); + foreach (DisplayMode mode in GraphicsAdapter.DefaultAdapter.SupportedDisplayModes) + { + if (supportedModes.FirstOrDefault(m => m.Width == mode.Width && m.Height == mode.Height) != null) continue; + + resolutionDD.AddItem(mode.Width + "x" + mode.Height, mode); + supportedModes.Add(mode); + + if (GraphicsWidth == mode.Width && GraphicsHeight == mode.Height) resolutionDD.SelectItem(mode); + } + + if (resolutionDD.SelectedItemData == null) + { + resolutionDD.SelectItem(GraphicsAdapter.DefaultAdapter.SupportedDisplayModes.Last()); + } + + y += 50; + + //var fullScreenTick = new GUITickBox(new Rectangle(x, y, 20, 20), "Fullscreen", Alignment.TopLeft, settingsFrame); + //fullScreenTick.OnSelected = ToggleFullScreen; + //fullScreenTick.Selected = FullScreenEnabled; + + new GUITextBlock(new Rectangle(x, y, 20, 20), "Display mode", "", Alignment.TopLeft, Alignment.TopLeft, settingsFrame); + var displayModeDD = new GUIDropDown(new Rectangle(x, y + 20, 180, 20), "", "", settingsFrame); + displayModeDD.AddItem("Fullscreen", WindowMode.Fullscreen); + displayModeDD.AddItem("Windowed", WindowMode.Windowed); + displayModeDD.AddItem("Borderless windowed", WindowMode.BorderlessWindowed); + + displayModeDD.SelectItem(GameMain.Config.WindowMode); + + displayModeDD.OnSelected = (guiComponent, obj) => { GameMain.Config.WindowMode = (WindowMode)guiComponent.UserData; return true; }; + + y += 70; + + GUITickBox vsyncTickBox = new GUITickBox(new Rectangle(0, y, 20, 20), "Enable vertical sync", Alignment.CenterY | Alignment.Left, settingsFrame); + vsyncTickBox.OnSelected = (GUITickBox box) => + { + VSyncEnabled = !VSyncEnabled; + GameMain.GraphicsDeviceManager.SynchronizeWithVerticalRetrace = VSyncEnabled; + GameMain.GraphicsDeviceManager.ApplyChanges(); + UnsavedSettings = true; + + return true; + }; + vsyncTickBox.Selected = VSyncEnabled; + + y += 70; + + new GUITextBlock(new Rectangle(0, y, 100, 20), "Sound volume:", "", settingsFrame); + GUIScrollBar soundScrollBar = new GUIScrollBar(new Rectangle(0, y + 20, 150, 20), "", 0.1f, settingsFrame); + soundScrollBar.BarScroll = SoundVolume; + soundScrollBar.OnMoved = ChangeSoundVolume; + soundScrollBar.Step = 0.05f; + + new GUITextBlock(new Rectangle(0, y + 40, 100, 20), "Music volume:", "", settingsFrame); + GUIScrollBar musicScrollBar = new GUIScrollBar(new Rectangle(0, y + 60, 150, 20), "", 0.1f, settingsFrame); + musicScrollBar.BarScroll = MusicVolume; + musicScrollBar.OnMoved = ChangeMusicVolume; + musicScrollBar.Step = 0.05f; + + x = 200; + y = 10; + + new GUITextBlock(new Rectangle(x, y, 20, 20), "Content package", "", Alignment.TopLeft, Alignment.TopLeft, settingsFrame); + var contentPackageDD = new GUIDropDown(new Rectangle(x, y + 20, 200, 20), "", "", settingsFrame); + + foreach (ContentPackage contentPackage in ContentPackage.list) + { + contentPackageDD.AddItem(contentPackage.Name, contentPackage); + + if (SelectedContentPackage == contentPackage) contentPackageDD.SelectItem(contentPackage); + } + + y += 50; + new GUITextBlock(new Rectangle(x, y, 100, 20), "Controls:", "", settingsFrame); + y += 30; + var inputNames = Enum.GetNames(typeof(InputType)); + for (int i = 0; i < inputNames.Length; i++) + { + new GUITextBlock(new Rectangle(x, y, 100, 18), inputNames[i] + ": ", "", Alignment.TopLeft, Alignment.CenterLeft, settingsFrame); + var keyBox = new GUITextBox(new Rectangle(x + 100, y, 120, 18), null, null, Alignment.TopLeft, Alignment.CenterLeft, "", settingsFrame); + + keyBox.Text = keyMapping[i].ToString(); + keyBox.UserData = i; + keyBox.OnSelected += KeyBoxSelected; + keyBox.SelectedColor = Color.Gold * 0.3f; + + y += 20; + } + + applyButton = new GUIButton(new Rectangle(0, 0, 100, 20), "Apply", Alignment.BottomRight, "", settingsFrame); + applyButton.OnClicked = ApplyClicked; + } + + private void KeyBoxSelected(GUITextBox textBox, Keys key) + { + textBox.Text = ""; + CoroutineManager.StartCoroutine(WaitForKeyPress(textBox)); + } + + private bool MarkUnappliedChanges(GUIButton button, object obj) + { + UnsavedSettings = true; + + return true; + } + + private bool SelectResolution(GUIComponent selected, object userData) + { + DisplayMode mode = selected.UserData as DisplayMode; + if (mode == null) return false; + + if (GraphicsWidth == mode.Width && GraphicsHeight == mode.Height) return false; + + GraphicsWidth = mode.Width; + GraphicsHeight = mode.Height; + + + //GameMain.Graphics.PreferredBackBufferWidth = GraphicsWidth; + //GameMain.Graphics.PreferredBackBufferHeight = GraphicsHeight; + //GameMain.Graphics.ApplyChanges(); + + //CoroutineManager.StartCoroutine(GameMain.Instance.Load()); + + UnsavedSettings = true; + + return true; + } + + + + private IEnumerable WaitForKeyPress(GUITextBox keyBox) + { + yield return CoroutineStatus.Running; + + while (keyBox.Selected && PlayerInput.GetKeyboardState.GetPressedKeys().Length == 0 + && !PlayerInput.LeftButtonClicked() && !PlayerInput.RightButtonClicked()) + { + if (Screen.Selected != GameMain.MainMenuScreen && !GUI.SettingsMenuOpen) yield return CoroutineStatus.Success; + + yield return CoroutineStatus.Running; + } + + UnsavedSettings = true; + + int keyIndex = (int)keyBox.UserData; + + if (PlayerInput.LeftButtonClicked()) + { + keyMapping[keyIndex] = new KeyOrMouse(0); + keyBox.Text = "Mouse1"; + } + else if (PlayerInput.LeftButtonClicked()) + { + keyMapping[keyIndex] = new KeyOrMouse(1); + keyBox.Text = "Mouse2"; + } + else if (PlayerInput.GetKeyboardState.GetPressedKeys().Length > 0) + { + Keys key = PlayerInput.GetKeyboardState.GetPressedKeys()[0]; + keyMapping[keyIndex] = new KeyOrMouse(key); + keyBox.Text = key.ToString("G"); + } + else + { + yield return CoroutineStatus.Success; + } + + keyBox.Deselect(); + + yield return CoroutineStatus.Success; + } + + private bool ApplyClicked(GUIButton button, object userData) + { + Save("config.xml"); + + settingsFrame.Flash(Color.Green); + + if (GameMain.GraphicsWidth != GameMain.Config.GraphicsWidth || GameMain.GraphicsHeight != GameMain.Config.GraphicsHeight) + { + new GUIMessageBox("Restart required", "You need to restart the game for the resolution changes to take effect."); + } + + return true; + } + } +} diff --git a/BarotraumaClient/Source/Items/CharacterInventory.cs b/BarotraumaClient/Source/Items/CharacterInventory.cs new file mode 100644 index 000000000..c509c3201 --- /dev/null +++ b/BarotraumaClient/Source/Items/CharacterInventory.cs @@ -0,0 +1,82 @@ +using System; +using System.Linq; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using Microsoft.Xna.Framework.Input; +using Barotrauma.Networking; +using Lidgren.Network; +using System.Collections.Generic; +using Barotrauma.Items.Components; + +namespace Barotrauma +{ + partial class CharacterInventory : Inventory + { + public Vector2[] SlotPositions; + + private GUIButton[] useOnSelfButton; + + void InitProjSpecific() + { + useOnSelfButton = new GUIButton[2]; + + if (icons == null) icons = TextureLoader.FromFile("Content/UI/inventoryIcons.png"); + + SlotPositions = new Vector2[limbSlots.Length]; + + int rectWidth = 40, rectHeight = 40; + int spacing = 10; + for (int i = 0; i < SlotPositions.Length; i++) + { + switch (i) + { + //head, torso, legs + case 0: + case 1: + case 2: + SlotPositions[i] = new Vector2( + spacing, + GameMain.GraphicsHeight - (spacing + rectHeight) * (3 - i)); + break; + //lefthand, righthand + case 3: + case 4: + SlotPositions[i] = new Vector2( + spacing * 2 + rectWidth + (spacing + rectWidth) * (i - 2), + GameMain.GraphicsHeight - (spacing + rectHeight) * 3); + + useOnSelfButton[i - 3] = new GUIButton( + new Rectangle((int)SlotPositions[i].X, (int)(SlotPositions[i].Y - spacing - rectHeight), + rectWidth, rectHeight), "Use", "") + { + UserData = i, + OnClicked = UseItemOnSelf + }; + + + break; + case 5: + SlotPositions[i] = new Vector2( + spacing * 2 + rectWidth + (spacing + rectWidth) * (i - 5), + GameMain.GraphicsHeight - (spacing + rectHeight) * 3); + + break; + default: + SlotPositions[i] = new Vector2( + spacing * 2 + rectWidth + (spacing + rectWidth) * ((i - 6) % 5), + GameMain.GraphicsHeight - (spacing + rectHeight) * ((i > 10) ? 2 : 1)); + break; + } + } + } + + private bool UseItemOnSelf(GUIButton button, object obj) + { + if (!(obj is int)) return false; + + int slotIndex = (int)obj; + + return UseItemOnSelf(slotIndex); + } + } +} diff --git a/BarotraumaClient/Source/Items/Components/ItemLabel.cs b/BarotraumaClient/Source/Items/Components/ItemLabel.cs new file mode 100644 index 000000000..76793efee --- /dev/null +++ b/BarotraumaClient/Source/Items/Components/ItemLabel.cs @@ -0,0 +1,89 @@ +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using System.Xml.Linq; + +namespace Barotrauma.Items.Components +{ + partial class ItemLabel : ItemComponent, IDrawableComponent + { + private GUITextBlock textBlock; + + private Color textColor; + + [HasDefaultValue("", true), Editable(100)] + public string Text + { + get { return textBlock.Text.Replace("\n", ""); } + set + { + if (value == TextBlock.Text || item.Rect.Width < 5) return; + + if (textBlock.Rect.Width != item.Rect.Width || textBlock.Rect.Height != item.Rect.Height) + { + textBlock = null; + } + + TextBlock.Text = value; + } + } + + [Editable, HasDefaultValue("0.0,0.0,0.0,1.0", true)] + public string TextColor + { + get { return ToolBox.Vector4ToString(textColor.ToVector4()); } + set + { + textColor = new Color(ToolBox.ParseToVector4(value)); + if (textBlock != null) textBlock.TextColor = textColor; + } + } + + [Editable, HasDefaultValue(1.0f, true)] + public float TextScale + { + get { return textBlock == null ? 1.0f : textBlock.TextScale; } + set + { + if (textBlock != null) textBlock.TextScale = MathHelper.Clamp(value, 0.1f, 10.0f); + } + } + + private GUITextBlock TextBlock + { + get + { + if (textBlock == null) + { + textBlock = new GUITextBlock(new Rectangle(item.Rect.X, -item.Rect.Y, item.Rect.Width, item.Rect.Height), "", + Color.Transparent, textColor, + Alignment.TopLeft, Alignment.Center, + null, null, true); + textBlock.Font = GUI.SmallFont; + textBlock.Padding = new Vector4(5.0f, 5.0f, 5.0f, 5.0f); + textBlock.TextDepth = item.Sprite.Depth - 0.0001f; + textBlock.TextScale = TextScale; + } + return textBlock; + } + } + + public override void Move(Vector2 amount) + { + textBlock.Rect = new Rectangle(item.Rect.X, -item.Rect.Y, item.Rect.Width, item.Rect.Height); + } + + public ItemLabel(Item item, XElement element) + : base(item, element) + { + } + + public void Draw(SpriteBatch spriteBatch, bool editing = false) + { + var drawPos = new Vector2( + item.DrawPosition.X - item.Rect.Width / 2.0f, + -(item.DrawPosition.Y + item.Rect.Height / 2.0f)); + + textBlock.Draw(spriteBatch, drawPos - textBlock.Rect.Location.ToVector2()); + } + } +} diff --git a/BarotraumaClient/Source/Items/FixRequirement.cs b/BarotraumaClient/Source/Items/FixRequirement.cs new file mode 100644 index 000000000..bd3a3b9c6 --- /dev/null +++ b/BarotraumaClient/Source/Items/FixRequirement.cs @@ -0,0 +1,191 @@ +using Barotrauma.Networking; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Xml.Linq; + +namespace Barotrauma +{ + partial class FixRequirement + { + private static GUIFrame frame; + + public bool CanBeFixed(Character character, GUIComponent reqFrame = null) + { + foreach (string itemName in requiredItems) + { + Item item = character.Inventory.FindItem(itemName); + bool itemFound = (item != null); + + if (reqFrame != null) + { + GUIComponent component = reqFrame.children.Find(c => c.UserData as string == itemName); + GUITextBlock text = component as GUITextBlock; + if (text != null) text.TextColor = itemFound ? Color.LightGreen : Color.Red; + } + } + + foreach (Skill skill in requiredSkills) + { + float characterSkill = character.GetSkillLevel(skill.Name); + bool sufficientSkill = characterSkill >= skill.Level; + + if (reqFrame != null) + { + GUIComponent component = reqFrame.children.Find(c => c.UserData as Skill == skill); + GUITextBlock text = component as GUITextBlock; + if (text != null) text.TextColor = sufficientSkill ? Color.LightGreen : Color.Red; + } + } + + return CanBeFixed(character); + } + + private static void CreateGUIFrame(Item item) + { + int width = 400, height = 500; + int y = 0; + + frame = new GUIFrame(new Rectangle(0, 0, width, height), null, Alignment.Center, ""); + frame.Padding = new Vector4(20.0f, 20.0f, 20.0f, 20.0f); + frame.UserData = item; + + new GUITextBlock(new Rectangle(0, 0, 200, 20), "Attempting to fix " + item.Name, "", frame); + + y = y + 40; + foreach (FixRequirement requirement in item.FixRequirements) + { + GUIFrame reqFrame = new GUIFrame( + new Rectangle(0, y, 0, 20 + Math.Max(requirement.requiredItems.Count, requirement.requiredSkills.Count) * 15), + Color.Transparent, null, frame); + reqFrame.UserData = requirement; + + + var fixButton = new GUIButton(new Rectangle(0, 0, 50, 20), "Fix", "", reqFrame); + fixButton.OnClicked = FixButtonPressed; + fixButton.UserData = requirement; + + var tickBox = new GUITickBox(new Rectangle(70, 0, 20, 20), requirement.name, Alignment.Left, reqFrame); + tickBox.Enabled = false; + + int y2 = 20; + foreach (string itemName in requirement.requiredItems) + { + var itemBlock = new GUITextBlock(new Rectangle(30, y2, 200, 15), itemName, "", reqFrame); + itemBlock.Font = GUI.SmallFont; + itemBlock.UserData = itemName; + + y2 += 15; + } + + y2 = 20; + foreach (Skill skill in requirement.requiredSkills) + { + var skillBlock = new GUITextBlock(new Rectangle(0, y2, 200, 15), skill.Name + " - " + skill.Level, "", Alignment.Right, Alignment.TopLeft, reqFrame); + skillBlock.Font = GUI.SmallFont; + skillBlock.UserData = skill; + + + y2 += 15; + } + + y += reqFrame.Rect.Height; + } + } + + private static bool FixButtonPressed(GUIButton button, object obj) + { + FixRequirement requirement = obj as FixRequirement; + if (requirement == null) return true; + + Item item = frame.UserData as Item; + if (item == null) return true; + + if (!requirement.CanBeFixed(Character.Controlled, button.Parent)) return true; + + if (GameMain.Client != null) + { + GameMain.Client.CreateEntityEvent(item, new object[] { NetEntityEvent.Type.Repair, item.FixRequirements.IndexOf(requirement) }); + } + else if (GameMain.Server != null) + { + GameMain.Server.CreateEntityEvent(item, new object[] { NetEntityEvent.Type.Status }); + requirement.Fixed = true; + } + else + { + requirement.Fixed = true; + } + + return true; + } + + private static void UpdateGUIFrame(Item item, Character character) + { + if (frame == null) return; + + bool unfixedFound = false; + foreach (GUIComponent child in frame.children) + { + FixRequirement requirement = child.UserData as FixRequirement; + if (requirement == null) continue; + + if (requirement.Fixed) + { + child.Color = Color.LightGreen * 0.3f; + child.GetChild().Selected = true; + } + else + { + bool canBeFixed = requirement.CanBeFixed(character, child); + unfixedFound = true; + //child.GetChild().Selected = canBeFixed; + GUITickBox tickBox = child.GetChild(); + if (tickBox.Selected) + { + tickBox.Selected = canBeFixed; + requirement.Fixed = canBeFixed; + + } + child.Color = Color.Red * 0.2f; + //tickBox.State = GUIComponent.ComponentState.None; + } + } + if (!unfixedFound) + { + item.Condition = 100.0f; + frame = null; + } + } + + public static void DrawHud(SpriteBatch spriteBatch, Item item, Character character) + { + if (frame == null) return; + + frame.Draw(spriteBatch); + } + + public static void AddToGUIUpdateList() + { + if (frame == null) return; + + frame.AddToGUIUpdateList(); + } + + public static void UpdateHud(Item item, Character character) + { + if (frame == null || frame.UserData != item) + { + CreateGUIFrame(item); + } + UpdateGUIFrame(item, character); + + if (frame == null) return; + + frame.Update((float)Timing.Step); + } + } +} diff --git a/BarotraumaClient/Source/Items/Inventory.cs b/BarotraumaClient/Source/Items/Inventory.cs new file mode 100644 index 000000000..58dc4034f --- /dev/null +++ b/BarotraumaClient/Source/Items/Inventory.cs @@ -0,0 +1,203 @@ +using System.Linq; +using Lidgren.Network; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using Microsoft.Xna.Framework.Input; +using Barotrauma.Networking; +using System; +using System.Collections.Generic; +using Barotrauma.Items.Components; + +namespace Barotrauma +{ + partial class InventorySlot + { + public GUIComponent.ComponentState State; + + public bool IsHighlighted + { + get + { + return State == GUIComponent.ComponentState.Hover; + } + } + + public Color Color; + + public Color BorderHighlightColor; + private CoroutineHandle BorderHighlightCoroutine; + + public void ShowBorderHighlight(Color color, float fadeInDuration, float fadeOutDuration) + { + if (BorderHighlightCoroutine != null) + { + BorderHighlightCoroutine = null; + } + + BorderHighlightCoroutine = CoroutineManager.StartCoroutine(UpdateBorderHighlight(color, fadeInDuration, fadeOutDuration)); + } + + private IEnumerable UpdateBorderHighlight(Color color, float fadeInDuration, float fadeOutDuration) + { + float t = 0.0f; + while (t < fadeInDuration + fadeOutDuration) + { + BorderHighlightColor = (t < fadeInDuration) ? + Color.Lerp(Color.Transparent, color, t / fadeInDuration) : + Color.Lerp(color, Color.Transparent, (t - fadeInDuration) / fadeOutDuration); + + t += CoroutineManager.DeltaTime; + + yield return CoroutineStatus.Running; + } + + yield return CoroutineStatus.Success; + } + } + + partial class Inventory + { + public virtual void Draw(SpriteBatch spriteBatch, bool subInventory = false) + { + if (slots == null || isSubInventory != subInventory) return; + + for (int i = 0; i < capacity; i++) + { + if (slots[i].Disabled) continue; + + //don't draw the item if it's being dragged out of the slot + bool drawItem = draggingItem == null || draggingItem != Items[i] || slots[i].IsHighlighted; + + DrawSlot(spriteBatch, slots[i], Items[i], drawItem); + } + + if (draggingItem != null && + (draggingSlot == null || (!draggingSlot.Rect.Contains(PlayerInput.MousePosition) && draggingItem.ParentInventory == this))) + { + Rectangle dragRect = new Rectangle( + (int)PlayerInput.MousePosition.X - 10, + (int)PlayerInput.MousePosition.Y - 10, + 40, 40); + + DrawSlot(spriteBatch, new InventorySlot(dragRect), draggingItem); + } + + for (int i = 0; i < capacity; i++) + { + if (slots[i].IsHighlighted && !slots[i].Disabled && Items[i] != null) + { + string toolTip = ""; + if (GameMain.DebugDraw) + { + toolTip = Items[i].ToString(); + } + else + { + toolTip = string.IsNullOrEmpty(Items[i].Description) ? + Items[i].Name : + Items[i].Name + '\n' + Items[i].Description; + } + + DrawToolTip(spriteBatch, toolTip, slots[i].Rect); + break; + } + } + } + + protected void DrawToolTip(SpriteBatch spriteBatch, string toolTip, Rectangle highlightedSlot) + { + int maxWidth = 300; + + toolTip = ToolBox.WrapText(toolTip, maxWidth, GUI.Font); + + Vector2 textSize = GUI.Font.MeasureString(toolTip); + Vector2 rectSize = textSize * 1.2f; + + Vector2 pos = new Vector2(highlightedSlot.Right, highlightedSlot.Y - rectSize.Y); + pos.X = (int)(pos.X + 3); + pos.Y = (int)pos.Y; + + GUI.DrawRectangle(spriteBatch, pos, rectSize, Color.Black * 0.8f, true); + GUI.Font.DrawString(spriteBatch, toolTip, + new Vector2((int)(pos.X + rectSize.X * 0.5f), (int)(pos.Y + rectSize.Y * 0.5f)), + Color.White, 0.0f, + new Vector2((int)(textSize.X * 0.5f), (int)(textSize.Y * 0.5f)), + 1.0f, SpriteEffects.None, 0.0f); + } + + + public void DrawSubInventory(SpriteBatch spriteBatch, int slotIndex) + { + var item = Items[slotIndex]; + if (item == null) return; + + var container = item.GetComponent(); + if (container == null) return; + + if (container.Inventory.slots == null || !container.Inventory.isSubInventory) return; + + int itemCapacity = container.Capacity; + +#if DEBUG + System.Diagnostics.Debug.Assert(slotIndex >= 0 && slotIndex < Items.Length); +#else + if (slotIndex < 0 || slotIndex >= Items.Length) return; +#endif + + var slot = slots[slotIndex]; + Rectangle containerRect = new Rectangle(slot.Rect.X - 5, slot.Rect.Y - (40 + 10) * itemCapacity - 5, + slot.Rect.Width + 10, slot.Rect.Height + (40 + 10) * itemCapacity + 10); + + GUI.DrawRectangle(spriteBatch, new Rectangle(containerRect.X, containerRect.Y, containerRect.Width, containerRect.Height - slot.Rect.Height - 5), Color.Black * 0.8f, true); + GUI.DrawRectangle(spriteBatch, containerRect, Color.White); + + container.Inventory.Draw(spriteBatch, true); + + if (!containerRect.Contains(PlayerInput.MousePosition)) + { + if (draggingItem == null || draggingItem.Container != item) selectedSlot = -1; + } + } + + protected void DrawSlot(SpriteBatch spriteBatch, InventorySlot slot, Item item, bool drawItem = true) + { + Rectangle rect = slot.Rect; + + GUI.DrawRectangle(spriteBatch, rect, (slot.IsHighlighted ? Color.Red * 0.4f : slot.Color), true); + + if (item != null && drawItem) + { + if (item.Condition < 100.0f) + { + GUI.DrawRectangle(spriteBatch, new Rectangle(rect.X, rect.Bottom - 8, rect.Width, 8), Color.Black * 0.8f, true); + GUI.DrawRectangle(spriteBatch, + new Rectangle(rect.X, rect.Bottom - 8, (int)(rect.Width * item.Condition / 100.0f), 8), + Color.Lerp(Color.Red, Color.Green, item.Condition / 100.0f) * 0.8f, true); + } + + var containedItems = item.ContainedItems; + if (containedItems != null && containedItems.Length == 1 && containedItems[0].Condition < 100.0f) + { + GUI.DrawRectangle(spriteBatch, new Rectangle(rect.X, rect.Y, rect.Width, 8), Color.Black * 0.8f, true); + GUI.DrawRectangle(spriteBatch, + new Rectangle(rect.X, rect.Y, (int)(rect.Width * containedItems[0].Condition / 100.0f), 8), + Color.Lerp(Color.Red, Color.Green, containedItems[0].Condition / 100.0f) * 0.8f, true); + } + } + + GUI.DrawRectangle(spriteBatch, rect, (slot.IsHighlighted ? Color.Red * 0.4f : slot.Color), false); + + if (slot.BorderHighlightColor != Color.Transparent) + { + Rectangle highlightRect = slot.Rect; + highlightRect.Inflate(3, 3); + + GUI.DrawRectangle(spriteBatch, highlightRect, slot.BorderHighlightColor, false, 0, 5); + } + + if (item == null || !drawItem) return; + + item.Sprite.Draw(spriteBatch, new Vector2(rect.X + rect.Width / 2, rect.Y + rect.Height / 2), item.Color); + } + } +} diff --git a/BarotraumaClient/Source/Map/MapEntity.cs b/BarotraumaClient/Source/Map/MapEntity.cs index daef42ec3..28a7f85cc 100644 --- a/BarotraumaClient/Source/Map/MapEntity.cs +++ b/BarotraumaClient/Source/Map/MapEntity.cs @@ -50,9 +50,6 @@ namespace Barotrauma } } - //is the mouse inside the rect - protected bool isHighlighted; - //protected bool isSelected; private static bool disableSelect; @@ -76,13 +73,6 @@ namespace Barotrauma get { return selectedList.Count > 0; } } - - public bool IsHighlighted - { - get { return isHighlighted; } - set { isHighlighted = value; } - } - public bool IsSelected { get { return selectedList.Contains(this); } diff --git a/BarotraumaClient/Source/Map/Structure.cs b/BarotraumaClient/Source/Map/Structure.cs new file mode 100644 index 000000000..354ef7e73 --- /dev/null +++ b/BarotraumaClient/Source/Map/Structure.cs @@ -0,0 +1,138 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Xml.Linq; +using FarseerPhysics; +using FarseerPhysics.Dynamics; +using FarseerPhysics.Dynamics.Contacts; +using FarseerPhysics.Factories; +using Lidgren.Network; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using Barotrauma.Networking; +using Barotrauma.Lights; + +namespace Barotrauma +{ + partial class Structure : MapEntity, IDamageable, IServerSerializable + { + + public override void Draw(SpriteBatch spriteBatch, bool editing, bool back = true) + { + if (prefab.sprite == null) return; + + Draw(spriteBatch, editing, back, null); + } + + public override void DrawDamage(SpriteBatch spriteBatch, Effect damageEffect) + { + Draw(spriteBatch, false, false, damageEffect); + } + + private void Draw(SpriteBatch spriteBatch, bool editing, bool back = true, Effect damageEffect = null) + { + if (prefab.sprite == null) return; + + Color color = (isHighlighted) ? Color.Orange : Color.White; + if (IsSelected && editing) + { + color = Color.Red; + + GUI.DrawRectangle(spriteBatch, new Rectangle(rect.X, -rect.Y, rect.Width, rect.Height), color); + } + + Vector2 drawOffset = Submarine == null ? Vector2.Zero : Submarine.DrawPosition; + + float depth = prefab.sprite.Depth; + depth -= (ID % 255) * 0.000001f; + + if (back && damageEffect == null) + { + if (prefab.BackgroundSprite != null) + { + prefab.BackgroundSprite.DrawTiled( + spriteBatch, + new Vector2(rect.X + drawOffset.X, -(rect.Y + drawOffset.Y)), + new Vector2(rect.Width, rect.Height), + color, Point.Zero); + } + } + + SpriteEffects oldEffects = prefab.sprite.effects; + prefab.sprite.effects ^= SpriteEffects; + + if (back == prefab.sprite.Depth > 0.5f || editing) + { + for (int i = 0; i < sections.Length; i++) + { + if (damageEffect != null) + { + float newCutoff = Math.Min((sections[i].damage / prefab.MaxHealth), 0.65f); + + if (Math.Abs(newCutoff - Submarine.DamageEffectCutoff) > 0.01f) + { + damageEffect.Parameters["aCutoff"].SetValue(newCutoff); + damageEffect.Parameters["cCutoff"].SetValue(newCutoff * 1.2f); + + damageEffect.CurrentTechnique.Passes[0].Apply(); + + Submarine.DamageEffectCutoff = newCutoff; + } + } + + Point textureOffset = new Point( + Math.Abs(rect.Location.X - sections[i].rect.Location.X), + Math.Abs(rect.Location.Y - sections[i].rect.Location.Y)); + + if (flippedX && isHorizontal) + { + textureOffset.X = rect.Width - textureOffset.X - sections[i].rect.Width; + } + + prefab.sprite.DrawTiled( + spriteBatch, + new Vector2(sections[i].rect.X + drawOffset.X, -(sections[i].rect.Y + drawOffset.Y)), + new Vector2(sections[i].rect.Width, sections[i].rect.Height), + color, + textureOffset, depth); + } + } + + prefab.sprite.effects = oldEffects; + } + + + public override XElement Save(XElement parentElement) + { + XElement element = new XElement("Structure"); + + element.Add(new XAttribute("name", prefab.Name), + new XAttribute("ID", ID), + new XAttribute("rect", + (int)(rect.X - Submarine.HiddenSubPosition.X) + "," + + (int)(rect.Y - Submarine.HiddenSubPosition.Y) + "," + + rect.Width + "," + rect.Height)); + + for (int i = 0; i < sections.Length; i++) + { + if (sections[i].damage == 0.0f) continue; + + var sectionElement = + new XElement("section", + new XAttribute("i", i), + new XAttribute("damage", sections[i].damage)); + + if (sections[i].gap != null) + { + sectionElement.Add(new XAttribute("gap", sections[i].gap.ID)); + } + + element.Add(sectionElement); + } + + parentElement.Add(element); + + return element; + } + } +} diff --git a/BarotraumaClient/Source/Map/StructurePrefab.cs b/BarotraumaClient/Source/Map/StructurePrefab.cs new file mode 100644 index 000000000..61af7e934 --- /dev/null +++ b/BarotraumaClient/Source/Map/StructurePrefab.cs @@ -0,0 +1,44 @@ +using System; +using System.Xml.Linq; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using System.Collections.Generic; + +namespace Barotrauma +{ + partial class StructurePrefab : MapEntityPrefab + { + public override void DrawPlacing(SpriteBatch spriteBatch, Camera cam) + { + Vector2 position = Submarine.MouseToWorldGrid(cam, Submarine.MainSub); + //Vector2 placeSize = size; + + Rectangle newRect = new Rectangle((int)position.X, (int)position.Y, (int)size.X, (int)size.Y); + + + if (placePosition == Vector2.Zero) + { + if (PlayerInput.LeftButtonHeld()) + placePosition = Submarine.MouseToWorldGrid(cam, Submarine.MainSub); + + newRect.X = (int)position.X; + newRect.Y = (int)position.Y; + + //sprite.Draw(spriteBatch, new Vector2(position.X, -position.Y), placeSize, Color.White); + } + else + { + Vector2 placeSize = size; + if (resizeHorizontal) placeSize.X = position.X - placePosition.X; + if (resizeVertical) placeSize.Y = placePosition.Y - position.Y; + + newRect = Submarine.AbsRect(placePosition, placeSize); + } + + sprite.DrawTiled(spriteBatch, new Vector2(newRect.X, -newRect.Y), new Vector2(newRect.Width, newRect.Height), Color.White); + + GUI.DrawRectangle(spriteBatch, new Rectangle(newRect.X - GameMain.GraphicsWidth, -newRect.Y, newRect.Width + GameMain.GraphicsWidth * 2, newRect.Height), Color.White); + GUI.DrawRectangle(spriteBatch, new Rectangle(newRect.X, -newRect.Y - GameMain.GraphicsHeight, newRect.Width, newRect.Height + GameMain.GraphicsHeight * 2), Color.White); + } + } +} diff --git a/BarotraumaClient/Source/Map/WayPoint.cs b/BarotraumaClient/Source/Map/WayPoint.cs new file mode 100644 index 000000000..03a84a51b --- /dev/null +++ b/BarotraumaClient/Source/Map/WayPoint.cs @@ -0,0 +1,249 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Xml.Linq; +using FarseerPhysics; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +//using Microsoft.Xna.Framework.Input; +using System.Collections.ObjectModel; +using Barotrauma.Items.Components; +using FarseerPhysics.Dynamics; + +namespace Barotrauma +{ + partial class WayPoint : MapEntity + { + private static Texture2D iconTexture; + private const int IconSize = 32; + private static int[] iconIndices = { 3, 0, 1, 2 }; + + public override void Draw(SpriteBatch spriteBatch, bool editing, bool back = true) + { + if (!editing && !GameMain.DebugDraw) return; + + if (IsHidden()) return; + + //Rectangle drawRect = + // Submarine == null ? rect : new Rectangle((int)(Submarine.DrawPosition.X + rect.X), (int)(Submarine.DrawPosition.Y + rect.Y), rect.Width, rect.Height); + + Vector2 drawPos = Position; + if (Submarine != null) drawPos += Submarine.DrawPosition; + drawPos.Y = -drawPos.Y; + + Color clr = currentHull == null ? Color.Blue : Color.White; + if (IsSelected) clr = Color.Red; + if (isHighlighted) clr = Color.DarkRed; + + int iconX = iconIndices[(int)spawnType] * IconSize % iconTexture.Width; + int iconY = (int)(Math.Floor(iconIndices[(int)spawnType] * IconSize / (float)iconTexture.Width)) * IconSize; + + int iconSize = ConnectedGap == null && Ladders == null ? IconSize : (int)(IconSize * 1.5f); + + spriteBatch.Draw(iconTexture, + new Rectangle((int)(drawPos.X - iconSize / 2), (int)(drawPos.Y - iconSize / 2), iconSize, iconSize), + new Rectangle(iconX, iconY, IconSize, IconSize), clr); + + //GUI.DrawRectangle(spriteBatch, new Rectangle(drawRect.X, -drawRect.Y, rect.Width, rect.Height), clr, true); + + //GUI.SmallFont.DrawString(spriteBatch, Position.ToString(), new Vector2(Position.X, -Position.Y), Color.White); + + foreach (MapEntity e in linkedTo) + { + GUI.DrawLine(spriteBatch, + drawPos, + new Vector2(e.DrawPosition.X, -e.DrawPosition.Y), + Color.Green); + } + } + + private bool IsHidden() + { + if (spawnType == SpawnType.Path) + { + return (!GameMain.DebugDraw && !ShowWayPoints); + } + else + { + return (!GameMain.DebugDraw && !ShowSpawnPoints); + } + } + + public override void UpdateEditing(Camera cam) + { + if (editingHUD == null || editingHUD.UserData != this) + { + editingHUD = CreateEditingHUD(); + } + + editingHUD.Update((float)Timing.Step); + + if (PlayerInput.LeftButtonClicked()) + { + Vector2 position = cam.ScreenToWorld(PlayerInput.MousePosition); + + foreach (MapEntity e in mapEntityList) + { + if (e.GetType() != typeof(WayPoint)) continue; + if (e == this) continue; + + if (!Submarine.RectContains(e.Rect, position)) continue; + + linkedTo.Add(e); + e.linkedTo.Add(this); + } + } + } + + public override void DrawEditing(SpriteBatch spriteBatch, Camera cam) + { + if (editingHUD != null) editingHUD.Draw(spriteBatch); + } + + private bool ChangeSpawnType(GUIButton button, object obj) + { + GUITextBlock spawnTypeText = button.Parent as GUITextBlock; + + spawnType += (int)button.UserData; + + if (spawnType > SpawnType.Cargo) spawnType = SpawnType.Human; + if (spawnType < SpawnType.Human) spawnType = SpawnType.Cargo; + + spawnTypeText.Text = spawnType.ToString(); + + return true; + } + + private bool EnterIDCardTags(GUITextBox textBox, string text) + { + IdCardTags = text.Split(','); + textBox.Text = text; + textBox.Color = Color.Green; + + textBox.Deselect(); + + return true; + } + + private bool EnterAssignedJob(GUITextBox textBox, string text) + { + string trimmedName = text.ToLowerInvariant().Trim(); + assignedJob = JobPrefab.List.Find(jp => jp.Name.ToLowerInvariant() == trimmedName); + + if (assignedJob != null && trimmedName != "none") + { + textBox.Color = Color.Green; + textBox.Text = (assignedJob == null) ? "None" : assignedJob.Name; + } + + textBox.Deselect(); + + return true; + } + + private bool TextBoxChanged(GUITextBox textBox, string text) + { + textBox.Color = Color.Red; + + return true; + } + + private GUIComponent CreateEditingHUD(bool inGame = false) + { + int width = 500; + int height = spawnType == SpawnType.Path ? 100 : 140; + int x = GameMain.GraphicsWidth / 2 - width / 2, y = 10; + + editingHUD = new GUIFrame(new Rectangle(x, y, width, height), Color.Black * 0.5f); + editingHUD.Padding = new Vector4(10, 10, 0, 0); + editingHUD.UserData = this; + + if (spawnType == SpawnType.Path) + { + new GUITextBlock(new Rectangle(0, 0, 100, 20), "Editing waypoint", "", editingHUD); + new GUITextBlock(new Rectangle(0, 20, 100, 20), "Hold space to link to another waypoint", "", editingHUD); + } + else + { + new GUITextBlock(new Rectangle(0, 0, 100, 20), "Editing spawnpoint", "", editingHUD); + new GUITextBlock(new Rectangle(0, 25, 100, 20), "Spawn type: ", "", editingHUD); + + var spawnTypeText = new GUITextBlock(new Rectangle(0, 25, 200, 20), spawnType.ToString(), "", Alignment.Right, Alignment.TopLeft, editingHUD); + + var button = new GUIButton(new Rectangle(-30, 0, 20, 20), "-", Alignment.Right, "", spawnTypeText); + button.UserData = -1; + button.OnClicked = ChangeSpawnType; + + button = new GUIButton(new Rectangle(0, 0, 20, 20), "+", Alignment.Right, "", spawnTypeText); + button.UserData = 1; + button.OnClicked = ChangeSpawnType; + + y = 40 + 20; + + new GUITextBlock(new Rectangle(0, y, 100, 20), "ID Card tags:", Color.Transparent, Color.White, Alignment.TopLeft, null, editingHUD); + GUITextBox propertyBox = new GUITextBox(new Rectangle(100, y, 200, 20), "", editingHUD); + propertyBox.Text = string.Join(", ", idCardTags); + propertyBox.OnEnterPressed = EnterIDCardTags; + propertyBox.OnTextChanged = TextBoxChanged; + propertyBox.ToolTip = "Characters spawning at this spawnpoint will have the specified tags added to their ID card. You can, for example, use these tags to limit access to some parts of the sub."; + + y = y + 30; + + new GUITextBlock(new Rectangle(0, y, 100, 20), "Assigned job:", Color.Transparent, Color.White, Alignment.TopLeft, null, editingHUD); + propertyBox = new GUITextBox(new Rectangle(100, y, 200, 20), "", editingHUD); + propertyBox.Text = (assignedJob == null) ? "None" : assignedJob.Name; + propertyBox.OnEnterPressed = EnterAssignedJob; + propertyBox.OnTextChanged = TextBoxChanged; + propertyBox.ToolTip = "Only characters with the specified job will spawn at this spawnpoint."; + + } + + + + + + //GUI.Font.DrawString(spriteBatch, "Spawnpoint: " + spawnType.ToString() + " +/-", new Vector2(x, y + 40), Color.Black); + + + y = y + 30; + + return editingHUD; + } + + public override XElement Save(XElement parentElement) + { + if (MoveWithLevel) return null; + XElement element = new XElement("WayPoint"); + + element.Add(new XAttribute("ID", ID), + new XAttribute("x", (int)(rect.X - Submarine.HiddenSubPosition.X)), + new XAttribute("y", (int)(rect.Y - Submarine.HiddenSubPosition.Y)), + new XAttribute("spawn", spawnType)); + + if (idCardTags.Length > 0) + { + element.Add(new XAttribute("idcardtags", string.Join(",", idCardTags))); + } + + if (assignedJob != null) element.Add(new XAttribute("job", assignedJob.Name)); + + + if (ConnectedGap != null) element.Add(new XAttribute("gap", ConnectedGap.ID)); + if (Ladders != null) element.Add(new XAttribute("ladders", Ladders.Item.ID)); + + parentElement.Add(element); + + if (linkedTo != null) + { + int i = 0; + foreach (MapEntity e in linkedTo) + { + element.Add(new XAttribute("linkedto" + i, e.ID)); + i += 1; + } + } + + return element; + } + } +} diff --git a/BarotraumaClient/Source/Networking/GameServer.cs b/BarotraumaClient/Source/Networking/GameServer.cs new file mode 100644 index 000000000..7d6ac3bd8 --- /dev/null +++ b/BarotraumaClient/Source/Networking/GameServer.cs @@ -0,0 +1,217 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using Lidgren.Network; +using Microsoft.Xna.Framework; +using RestSharp; +using Barotrauma.Items.Components; + +namespace Barotrauma.Networking +{ + partial class GameServer : NetworkMember + { + private GUIButton showLogButton; + + private GUIScrollBar clientListScrollBar; + + void InitProjSpecific() + { + //---------------------------------------- + + var endRoundButton = new GUIButton(new Rectangle(GameMain.GraphicsWidth - 170, 20, 150, 20), "End round", Alignment.TopLeft, "", inGameHUD); + endRoundButton.OnClicked = (btn, userdata) => { EndGame(); return true; }; + + log = new ServerLog(name); + showLogButton = new GUIButton(new Rectangle(GameMain.GraphicsWidth - 170 - 170, 20, 150, 20), "Server Log", Alignment.TopLeft, "", inGameHUD); + showLogButton.OnClicked = (GUIButton button, object userData) => + { + if (log.LogFrame == null) + { + log.CreateLogFrame(); + } + else + { + log.LogFrame = null; + GUIComponent.KeyboardDispatcher.Subscriber = null; + } + return true; + }; + + GUIButton settingsButton = new GUIButton(new Rectangle(GameMain.GraphicsWidth - 170 - 170 - 170, 20, 150, 20), "Settings", Alignment.TopLeft, "", inGameHUD); + settingsButton.OnClicked = ToggleSettingsFrame; + settingsButton.UserData = "settingsButton"; + + entityEventManager = new ServerEntityEventManager(this); + + whitelist = new WhiteList(); + banList = new BanList(); + + LoadSettings(); + LoadClientPermissions(); + + //---------------------------------------- + } + + + public override void Draw(Microsoft.Xna.Framework.Graphics.SpriteBatch spriteBatch) + { + base.Draw(spriteBatch); + + if (settingsFrame != null) + { + settingsFrame.Draw(spriteBatch); + } + else if (log.LogFrame != null) + { + log.LogFrame.Draw(spriteBatch); + } + + if (!ShowNetStats) return; + + GUI.Font.DrawString(spriteBatch, "Unique Events: " + entityEventManager.UniqueEvents.Count, new Vector2(10, 50), Color.White); + + int width = 200, height = 300; + int x = GameMain.GraphicsWidth - width, y = (int)(GameMain.GraphicsHeight * 0.3f); + + + if (clientListScrollBar == null) + { + clientListScrollBar = new GUIScrollBar(new Rectangle(x + width - 10, y, 10, height), "", 1.0f); + } + + + GUI.DrawRectangle(spriteBatch, new Rectangle(x, y, width, height), Color.Black * 0.7f, true); + GUI.Font.DrawString(spriteBatch, "Network statistics:", new Vector2(x + 10, y + 10), Color.White); + + GUI.SmallFont.DrawString(spriteBatch, "Connections: " + server.ConnectionsCount, new Vector2(x + 10, y + 30), Color.White); + GUI.SmallFont.DrawString(spriteBatch, "Received bytes: " + MathUtils.GetBytesReadable(server.Statistics.ReceivedBytes), new Vector2(x + 10, y + 45), Color.White); + GUI.SmallFont.DrawString(spriteBatch, "Received packets: " + server.Statistics.ReceivedPackets, new Vector2(x + 10, y + 60), Color.White); + + GUI.SmallFont.DrawString(spriteBatch, "Sent bytes: " + MathUtils.GetBytesReadable(server.Statistics.SentBytes), new Vector2(x + 10, y + 75), Color.White); + GUI.SmallFont.DrawString(spriteBatch, "Sent packets: " + server.Statistics.SentPackets, new Vector2(x + 10, y + 90), Color.White); + + int resentMessages = 0; + + int clientListHeight = connectedClients.Count * 40; + float scrollBarHeight = (height - 110) / (float)Math.Max(clientListHeight, 110); + + if (clientListScrollBar.BarSize != scrollBarHeight) + { + clientListScrollBar.BarSize = scrollBarHeight; + } + + int startY = y + 110; + y = (startY - (int)(clientListScrollBar.BarScroll * (clientListHeight - (height - 110)))); + foreach (Client c in connectedClients) + { + Color clientColor = c.Connection.AverageRoundtripTime > 0.3f ? Color.Red : Color.White; + + if (y >= startY && y < startY + height - 120) + { + GUI.SmallFont.DrawString(spriteBatch, c.name + " (" + c.Connection.RemoteEndPoint.Address.ToString() + ")", new Vector2(x + 10, y), clientColor); + GUI.SmallFont.DrawString(spriteBatch, "Ping: " + (int)(c.Connection.AverageRoundtripTime * 1000.0f) + " ms", new Vector2(x + 20, y + 10), clientColor); + } + if (y + 25 >= startY && y < startY + height - 130) GUI.SmallFont.DrawString(spriteBatch, "Resent messages: " + c.Connection.Statistics.ResentMessages, new Vector2(x + 20, y + 20), clientColor); + + resentMessages += (int)c.Connection.Statistics.ResentMessages; + + y += 40; + } + + clientListScrollBar.Update(1.0f / 60.0f); + clientListScrollBar.Draw(spriteBatch); + + netStats.AddValue(NetStats.NetStatType.ResentMessages, Math.Max(resentMessages, 0)); + netStats.AddValue(NetStats.NetStatType.SentBytes, server.Statistics.SentBytes); + netStats.AddValue(NetStats.NetStatType.ReceivedBytes, server.Statistics.ReceivedBytes); + + netStats.Draw(spriteBatch, new Rectangle(200, 0, 800, 200), this); + } + + + private void UpdateFileTransferIndicator(Client client) + { + var transfers = fileSender.ActiveTransfers.FindAll(t => t.Connection == client.Connection); + + var clientNameBox = GameMain.NetLobbyScreen.PlayerList.FindChild(client.name); + + var clientInfo = clientNameBox.FindChild("filetransfer"); + if (clientInfo == null) + { + clientNameBox.ClearChildren(); + clientInfo = new GUIFrame(new Rectangle(0, 0, 180, 0), Color.Transparent, Alignment.TopRight, null, clientNameBox); + clientInfo.UserData = "filetransfer"; + } + else if (transfers.Count == 0) + { + clientInfo.Parent.RemoveChild(clientInfo); + } + + clientInfo.ClearChildren(); + + var progressBar = new GUIProgressBar(new Rectangle(0, 4, 160, clientInfo.Rect.Height - 8), Color.Green, "", 0.0f, Alignment.Left, clientInfo); + progressBar.IsHorizontal = true; + progressBar.ProgressGetter = () => { return transfers.Sum(t => t.Progress) / transfers.Count; }; + + var textBlock = new GUITextBlock(new Rectangle(0, 2, 160, 0), "", "", Alignment.TopLeft, Alignment.Left | Alignment.CenterY, clientInfo, true, GUI.SmallFont); + textBlock.TextGetter = () => + { return MathUtils.GetBytesReadable(transfers.Sum(t => t.SentOffset)) + " / " + MathUtils.GetBytesReadable(transfers.Sum(t => t.Data.Length)); }; + + var cancelButton = new GUIButton(new Rectangle(-5, 0, 14, 0), "X", Alignment.Right, "", clientInfo); + cancelButton.OnClicked = (GUIButton button, object userdata) => + { + transfers.ForEach(t => fileSender.CancelTransfer(t)); + return true; + }; + } + + public override bool SelectCrewCharacter(Character character, GUIComponent crewFrame) + { + if (character == null) return false; + + var characterFrame = crewFrame.FindChild("selectedcharacter"); + if (character != myCharacter) + { + var banButton = new GUIButton(new Rectangle(0, 0, 100, 20), "Ban", Alignment.BottomRight, "", characterFrame); + banButton.UserData = character.Name; + banButton.OnClicked += GameMain.NetLobbyScreen.BanPlayer; + + var rangebanButton = new GUIButton(new Rectangle(0, -25, 100, 20), "Ban range", Alignment.BottomRight, "", characterFrame); + rangebanButton.UserData = character.Name; + rangebanButton.OnClicked += GameMain.NetLobbyScreen.BanPlayerRange; + + var kickButton = new GUIButton(new Rectangle(0, 0, 100, 20), "Kick", Alignment.BottomLeft, "", characterFrame); + kickButton.UserData = character.Name; + kickButton.OnClicked += GameMain.NetLobbyScreen.KickPlayer; + } + + return true; + } + + private GUIMessageBox upnpBox; + void InitUPnP() + { + server.UPnP.ForwardPort(config.Port, "barotrauma"); + + upnpBox = new GUIMessageBox("Please wait...", "Attempting UPnP port forwarding", new string[] { "Cancel" }); + upnpBox.Buttons[0].OnClicked = upnpBox.Close; + } + + bool DiscoveringUPnP() + { + return server.UPnP.Status == UPnPStatus.Discovering && GUIMessageBox.VisibleBox == upnpBox; + } + + void FinishUPnP() + { + upnpBox.Close(null, null); + } + + public bool StartGameClicked(GUIButton button, object obj) + { + return StartGame(); + } + } +} diff --git a/BarotraumaClient/Source/Networking/Voting.cs b/BarotraumaClient/Source/Networking/Voting.cs new file mode 100644 index 000000000..dcf11f2f2 --- /dev/null +++ b/BarotraumaClient/Source/Networking/Voting.cs @@ -0,0 +1,169 @@ +using Barotrauma.Networking; +using Lidgren.Network; +using Microsoft.Xna.Framework; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Barotrauma +{ + partial class Voting + { + public bool AllowSubVoting + { + get { return allowSubVoting; } + set + { + if (value == allowSubVoting) return; + allowSubVoting = value; + GameMain.NetLobbyScreen.SubList.Enabled = value || GameMain.Server != null; + GameMain.NetLobbyScreen.InfoFrame.FindChild("subvotes").Visible = value; + + if (GameMain.Server != null) + { + UpdateVoteTexts(GameMain.Server.ConnectedClients, VoteType.Sub); + GameMain.Server.UpdateVoteStatus(); + } + else + { + GameMain.NetLobbyScreen.SubList.Deselect(); + } + } + } + public bool AllowModeVoting + { + get { return allowModeVoting; } + set + { + if (value == allowModeVoting) return; + allowModeVoting = value; + GameMain.NetLobbyScreen.ModeList.Enabled = value || GameMain.Server != null; + GameMain.NetLobbyScreen.InfoFrame.FindChild("modevotes").Visible = value; + if (GameMain.Server != null) + { + UpdateVoteTexts(GameMain.Server.ConnectedClients, VoteType.Mode); + GameMain.Server.UpdateVoteStatus(); + } + else + { + GameMain.NetLobbyScreen.ModeList.Deselect(); + } + } + } + + public void UpdateVoteTexts(List clients, VoteType voteType) + { + GUIListBox listBox = (voteType == VoteType.Sub) ? + GameMain.NetLobbyScreen.SubList : GameMain.NetLobbyScreen.ModeList; + + foreach (GUIComponent comp in listBox.children) + { + GUITextBlock voteText = comp.FindChild("votes") as GUITextBlock; + if (voteText != null) comp.RemoveChild(voteText); + } + + List> voteList = GetVoteList(voteType, clients); + foreach (Pair votable in voteList) + { + SetVoteText(listBox, votable.First, votable.Second); + } + } + + private void SetVoteText(GUIListBox listBox, object userData, int votes) + { + if (userData == null) return; + foreach (GUIComponent comp in listBox.children) + { + if (comp.UserData != userData) continue; + GUITextBlock voteText = comp.FindChild("votes") as GUITextBlock; + if (voteText == null) + { + voteText = new GUITextBlock(new Rectangle(0, 0, 30, 0), "", "", Alignment.Right, Alignment.Right, comp); + voteText.UserData = "votes"; + } + + voteText.Text = votes == 0 ? "" : votes.ToString(); + } + } + + public void ClientWrite(NetBuffer msg, VoteType voteType, object data) + { + if (GameMain.Server != null) return; + + msg.Write((byte)voteType); + + switch (voteType) + { + case VoteType.Sub: + Submarine sub = data as Submarine; + if (sub == null) return; + + msg.Write(sub.Name); + break; + case VoteType.Mode: + GameModePreset gameMode = data as GameModePreset; + if (gameMode == null) return; + + msg.Write(gameMode.Name); + break; + case VoteType.EndRound: + if (!(data is bool)) return; + + msg.Write((bool)data); + break; + case VoteType.Kick: + Client votedClient = data as Client; + if (votedClient == null) return; + + msg.Write(votedClient.ID); + break; + } + + msg.WritePadBits(); + } + + public void ClientRead(NetIncomingMessage inc) + { + if (GameMain.Server != null) return; + + AllowSubVoting = inc.ReadBoolean(); + if (allowSubVoting) + { + foreach (Submarine sub in Submarine.SavedSubmarines) + { + SetVoteText(GameMain.NetLobbyScreen.SubList, sub, 0); + } + int votableCount = inc.ReadByte(); + for (int i = 0; i < votableCount; i++) + { + int votes = inc.ReadByte(); + string subName = inc.ReadString(); + Submarine sub = Submarine.SavedSubmarines.Find(sm => sm.Name == subName); + SetVoteText(GameMain.NetLobbyScreen.SubList, sub, votes); + } + } + AllowModeVoting = inc.ReadBoolean(); + if (allowModeVoting) + { + int votableCount = inc.ReadByte(); + for (int i = 0; i < votableCount; i++) + { + int votes = inc.ReadByte(); + string modeName = inc.ReadString(); + GameModePreset mode = GameModePreset.list.Find(m => m.Name == modeName); + SetVoteText(GameMain.NetLobbyScreen.ModeList, mode, votes); + } + } + AllowEndVoting = inc.ReadBoolean(); + if (AllowEndVoting) + { + GameMain.NetworkMember.EndVoteCount = inc.ReadByte(); + GameMain.NetworkMember.EndVoteMax = inc.ReadByte(); + } + AllowVoteKick = inc.ReadBoolean(); + + inc.ReadPadBits(); + } + } +} diff --git a/BarotraumaClient/Source/Program.cs b/BarotraumaClient/Source/Program.cs index eaf57c560..1cb5e0f3f 100644 --- a/BarotraumaClient/Source/Program.cs +++ b/BarotraumaClient/Source/Program.cs @@ -125,7 +125,7 @@ namespace Barotrauma StreamWriter sw = new StreamWriter(filePath); StringBuilder sb = new StringBuilder(); - sb.AppendLine("Barotrauma crash report (generated on " + DateTime.Now + ")"); + sb.AppendLine("Barotrauma Client crash report (generated on " + DateTime.Now + ")"); sb.AppendLine("\n"); sb.AppendLine("Barotrauma seems to have crashed. Sorry for the inconvenience! "); sb.AppendLine("If you'd like to help fix the bug that caused the crash, please send this file to the developers on the Undertow Games forums."); diff --git a/BarotraumaClient/Source/Screens/NetLobbyScreen.cs b/BarotraumaClient/Source/Screens/NetLobbyScreen.cs index bba259f11..ce488fc57 100644 --- a/BarotraumaClient/Source/Screens/NetLobbyScreen.cs +++ b/BarotraumaClient/Source/Screens/NetLobbyScreen.cs @@ -54,6 +54,12 @@ namespace Barotrauma get { return serverMessage; } } + public string ServerMessageText + { + get { return serverMessage.Text; } + set { serverMessage.Text = value; } + } + public GUIListBox SubList { get { return subList; } @@ -68,6 +74,11 @@ namespace Barotrauma { get { return modeList; } } + public int SelectedModeIndex + { + get { return modeList.SelectedIndex; } + set { modeList.Select(value); } + } public GUIListBox PlayerList { @@ -80,6 +91,12 @@ namespace Barotrauma private set; } + public bool StartButtonEnabled + { + get { return StartButton.Enabled; } + set { StartButton.Enabled = value; } + } + public GUIFrame InfoFrame { get { return infoFrame; } @@ -454,7 +471,7 @@ namespace Barotrauma base.Select(); } - + public void ShowSpectateButton() { if (GameMain.Client == null) return; diff --git a/BarotraumaServer/BarotraumaServer.csproj b/BarotraumaServer/BarotraumaServer.csproj index 2228e5daf..6d9fb2068 100644 --- a/BarotraumaServer/BarotraumaServer.csproj +++ b/BarotraumaServer/BarotraumaServer.csproj @@ -35,6 +35,9 @@ + + ..\packages\RestSharp.105.2.3\lib\net45\RestSharp.dll + @@ -47,10 +50,19 @@ + + + + + + + + + diff --git a/BarotraumaServer/Source/Characters/Character.cs b/BarotraumaServer/Source/Characters/Character.cs new file mode 100644 index 000000000..b4b52b0ee --- /dev/null +++ b/BarotraumaServer/Source/Characters/Character.cs @@ -0,0 +1,42 @@ +using FarseerPhysics; +using FarseerPhysics.Dynamics; +using FarseerPhysics.Dynamics.Joints; +using Barotrauma.Networking; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Xml.Linq; +using Microsoft.Xna.Framework; + +namespace Barotrauma +{ + partial class Character : Entity, IDamageable, IPropertyObject, IClientSerializable, IServerSerializable + { + //the Character that the player is currently controlling + private const Character controlled = null; + + public static Character Controlled + { + get { return controlled; } + set + { + //do nothing + } + } + + private void InitProjSpecific(XDocument doc) + { + //do nothing + } + + private void UpdateControlled(float deltaTime) + { + //do nothing + } + + private void ImplodeFX() + { + //do nothing + } + } +} diff --git a/BarotraumaServer/Source/DebugConsole.cs b/BarotraumaServer/Source/DebugConsole.cs new file mode 100644 index 000000000..00f6c1bcc --- /dev/null +++ b/BarotraumaServer/Source/DebugConsole.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using Microsoft.Xna.Framework.Input; +using Barotrauma.Networking; +using Barotrauma.Items.Components; +using System.Text; +using FarseerPhysics; + +namespace Barotrauma +{ + static partial class DebugConsole + { + private static string InputText; + + private static bool ExecProjSpecific(string[] commands) + { + return false; //command not found + } + } +} diff --git a/BarotraumaServer/Source/GameMain.cs b/BarotraumaServer/Source/GameMain.cs index bea55f9b9..3f9c5fc6f 100644 --- a/BarotraumaServer/Source/GameMain.cs +++ b/BarotraumaServer/Source/GameMain.cs @@ -11,25 +11,69 @@ namespace Barotrauma { class GameMain { + public static readonly Version Version = Assembly.GetEntryAssembly().GetName().Version; + public static World World; + public static GameSettings Config; public static GameServer Server; - - public static GameSession GameSession; - - public static GameClient Client - { - get { return null; } - } - + public const GameClient Client = null; public static NetworkMember NetworkMember { get { return Server as NetworkMember; } } - public static Screen EditMapScreen + public static GameSession GameSession; + + public static GameMain Instance { - get { return null; } + get; + private set; + } + + //only screens the server implements + public static GameScreen GameScreen; + public static NetLobbyScreen NetLobbyScreen; + + //null screens because they are not implemented by the server, + //but they're checked for all over the place + //TODO: maybe clean up instead of having these constants + public const Screen MainMenuScreen = null; + public const Screen LobbyScreen = null; + + public const Screen ServerListScreen = null; + + public const Screen EditMapScreen = null; + public const Screen EditCharacterScreen = null; + + // + + public static ContentPackage SelectedPackage + { + get { return Config.SelectedContentPackage; } + } + + public GameMain() + { + Instance = this; + + Config = new GameSettings("serverconfig.xml"); + if (Config.WasGameUpdated) + { + UpdaterUtil.CleanOldFiles(); + Config.WasGameUpdated = false; + Config.Save("serverconfig.xml"); + } + } + + public void Run() + { + //TODO: implement + } + + public CoroutineHandle ShowLoading(IEnumerable loader, bool waitKeyHit = true) + { + return CoroutineManager.StartCoroutine(loader); } } } diff --git a/BarotraumaServer/Source/GameSession/GameSession.cs b/BarotraumaServer/Source/GameSession/GameSession.cs new file mode 100644 index 000000000..fd607435e --- /dev/null +++ b/BarotraumaServer/Source/GameSession/GameSession.cs @@ -0,0 +1,12 @@ +using System; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using System.Xml.Linq; + +namespace Barotrauma +{ + partial class GameSession + { + public const Map Map = null; + } +} diff --git a/BarotraumaServer/Source/GameSettings.cs b/BarotraumaServer/Source/GameSettings.cs new file mode 100644 index 000000000..09c70e14b --- /dev/null +++ b/BarotraumaServer/Source/GameSettings.cs @@ -0,0 +1,49 @@ +using Microsoft.Xna.Framework; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Xml.Linq; + +namespace Barotrauma +{ + public enum WindowMode + { + Windowed, Fullscreen, BorderlessWindowed + } + + public partial class GameSettings + { + private void InitProjSpecific(XDocument doc) + { + //do nothing + } + public void Save(string filePath) + { + XDocument doc = new XDocument(); + + if (doc.Root == null) + { + doc.Add(new XElement("config")); + } + + doc.Root.Add( + new XAttribute("masterserverurl", MasterServerUrl), + new XAttribute("autocheckupdates", AutoCheckUpdates), + new XAttribute("verboselogging", VerboseLogging)); + + if (WasGameUpdated) + { + doc.Root.Add(new XAttribute("wasgameupdated", true)); + } + + if (SelectedContentPackage != null) + { + doc.Root.Add(new XElement("contentpackage", + new XAttribute("path", SelectedContentPackage.Path))); + } + + doc.Save(filePath); + } + } +} diff --git a/BarotraumaServer/Source/Items/CharacterInventory.cs b/BarotraumaServer/Source/Items/CharacterInventory.cs new file mode 100644 index 000000000..0d1e32a0e --- /dev/null +++ b/BarotraumaServer/Source/Items/CharacterInventory.cs @@ -0,0 +1,20 @@ +using System; +using System.Linq; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using Microsoft.Xna.Framework.Input; +using Barotrauma.Networking; +using Lidgren.Network; +using System.Collections.Generic; +using Barotrauma.Items.Components; + +namespace Barotrauma +{ + partial class CharacterInventory : Inventory + { + void InitProjSpecific() + { + //do nothing + } + } +} diff --git a/BarotraumaServer/Source/Items/Components/ItemLabel.cs b/BarotraumaServer/Source/Items/Components/ItemLabel.cs new file mode 100644 index 000000000..d402d04be --- /dev/null +++ b/BarotraumaServer/Source/Items/Components/ItemLabel.cs @@ -0,0 +1,39 @@ +using Microsoft.Xna.Framework; +using System.Xml.Linq; + +namespace Barotrauma.Items.Components +{ + partial class ItemLabel : ItemComponent, IDrawableComponent + { + [HasDefaultValue("", true), Editable(100)] + public string Text + { + get; + set; + } + + [Editable, HasDefaultValue("0.0,0.0,0.0,1.0", true)] + public string TextColor + { + get; + set; + } + + [Editable, HasDefaultValue(1.0f, true)] + public float TextScale + { + get; + set; + } + + public override void Move(Vector2 amount) + { + //do nothing + } + + public ItemLabel(Item item, XElement element) + : base(item, element) + { + } + } +} diff --git a/BarotraumaServer/Source/Networking/GameServer.cs b/BarotraumaServer/Source/Networking/GameServer.cs new file mode 100644 index 000000000..bca8dad3c --- /dev/null +++ b/BarotraumaServer/Source/Networking/GameServer.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using Lidgren.Network; +using Microsoft.Xna.Framework; +using RestSharp; +using Barotrauma.Items.Components; + +namespace Barotrauma.Networking +{ + partial class GameServer : NetworkMember + { + void InitProjSpecific() + { + //do nothing + } + + void InitUPnP() + { + server.UPnP.ForwardPort(config.Port, "barotrauma"); + } + + bool DiscoveringUPnP() + { + return server.UPnP.Status == UPnPStatus.Discovering; + } + + void FinishUPnP() + { + //do nothing + } + } +} diff --git a/BarotraumaServer/Source/Networking/Voting.cs b/BarotraumaServer/Source/Networking/Voting.cs new file mode 100644 index 000000000..9b64e7198 --- /dev/null +++ b/BarotraumaServer/Source/Networking/Voting.cs @@ -0,0 +1,25 @@ +using Barotrauma.Networking; +using Lidgren.Network; +using Microsoft.Xna.Framework; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Barotrauma +{ + partial class Voting + { + public bool AllowSubVoting + { + get { return allowSubVoting; } + set { allowSubVoting = value; } + } + public bool AllowModeVoting + { + get { return allowModeVoting; } + set { allowModeVoting = value; } + } + + } +} diff --git a/BarotraumaServer/Source/Program.cs b/BarotraumaServer/Source/Program.cs index eaf57c560..bf0553c9a 100644 --- a/BarotraumaServer/Source/Program.cs +++ b/BarotraumaServer/Source/Program.cs @@ -7,8 +7,6 @@ using System.Text; #if WINDOWS using System.Management; -using System.Windows.Forms; -using Microsoft.Xna.Framework.Graphics; #endif #endregion @@ -29,109 +27,29 @@ namespace Barotrauma [STAThread] static void Main() { - using (var game = new GameMain()) - { -#if DEBUG - game.Run(); -#else - bool attemptRestart = false; - - do - { - try - { - game.Run(); - attemptRestart = false; - } - catch (Exception e) - { - if (restartAttempts < 5 && CheckException(game, e)) - { - attemptRestart = true; - restartAttempts++; - } - else - { - CrashDump(game, "crashreport.txt", e); - attemptRestart = false; - } - - } - } while (attemptRestart); -#endif - } - } - - private static bool CheckException(GameMain game, Exception e) - { -#if WINDOWS - - if (e is SharpDX.SharpDXException) + GameMain game = null; + try { - switch ((uint)((SharpDX.SharpDXException)e).ResultCode.Code) - { - case 0x887A0022: //DXGI_ERROR_NOT_CURRENTLY_AVAILABLE - switch (restartAttempts) - { - case 0: - //just wait and try again - System.Threading.Thread.Sleep(100); - return true; - case 1: - //force focus to this window - var myForm = (System.Windows.Forms.Form)System.Windows.Forms.Form.FromHandle(game.Window.Handle); - myForm.Focus(); - return true; - case 2: - //try disabling hardware mode switch - if (GameMain.Config.WindowMode == WindowMode.Fullscreen) - { - DebugConsole.NewMessage("Failed to set fullscreen mode, switching configuration to borderless windowed", Microsoft.Xna.Framework.Color.Red); - GameMain.Config.WindowMode = WindowMode.BorderlessWindowed; - GameMain.Config.Save("config.xml"); - } - return false; - default: - return false; - - } - case 0x80070057: //E_INVALIDARG/Invalid Arguments - DebugConsole.NewMessage("Invalid graphics settings, attempting to fix", Microsoft.Xna.Framework.Color.Red); - - GameMain.Config.GraphicsWidth = GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Width; - GameMain.Config.GraphicsHeight = GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Height; - game.ApplyGraphicsSettings(); - - return true; - default: - return false; - } + game = new GameMain(); + game.Run(); + } + catch (Exception e) + { + CrashDump(game, "servercrashreport.txt", e); } - -#endif - - return false; } - - public static void CrashMessageBox(string message) - { -#if WINDOWS - MessageBox.Show(message, "Oops! Barotrauma just crashed.", MessageBoxButtons.OK, MessageBoxIcon.Error); -#endif - } - + static void CrashDump(GameMain game, string filePath, Exception exception) { StreamWriter sw = new StreamWriter(filePath); StringBuilder sb = new StringBuilder(); - sb.AppendLine("Barotrauma crash report (generated on " + DateTime.Now + ")"); + sb.AppendLine("Barotrauma Dedicated Server crash report (generated on " + DateTime.Now + ")"); sb.AppendLine("\n"); sb.AppendLine("Barotrauma seems to have crashed. Sorry for the inconvenience! "); sb.AppendLine("If you'd like to help fix the bug that caused the crash, please send this file to the developers on the Undertow Games forums."); sb.AppendLine("\n"); sb.AppendLine("Game version " + GameMain.Version); - sb.AppendLine("Graphics mode: " + GameMain.Config.GraphicsWidth + "x" + GameMain.Config.GraphicsHeight + " (" + GameMain.Config.WindowMode.ToString() + ")"); sb.AppendLine("Selected content package: " + GameMain.SelectedPackage.Name); sb.AppendLine("Level seed: " + ((Level.Loaded == null) ? "no level loaded" : Level.Loaded.Seed)); sb.AppendLine("Loaded submarine: " + ((Submarine.MainSub == null) ? "None" : Submarine.MainSub.Name + " (" + Submarine.MainSub.MD5Hash + ")")); @@ -164,10 +82,7 @@ namespace Barotrauma sw.WriteLine(sb.ToString()); - sw.Close(); - - CrashMessageBox( "A crash report (\"crashreport.txt\") was saved in the root folder of the game."+ - " If you'd like to help fix this bug, please post the report on the Undertow Games forums."); + sw.Close(); } } #endif diff --git a/BarotraumaServer/Source/Screens/NetLobbyScreen.cs b/BarotraumaServer/Source/Screens/NetLobbyScreen.cs new file mode 100644 index 000000000..fa241bb6a --- /dev/null +++ b/BarotraumaServer/Source/Screens/NetLobbyScreen.cs @@ -0,0 +1,62 @@ +using System; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using Barotrauma.Networking; +using System.Linq; +using System.Collections.Generic; +using System.Reflection; +using System.ComponentModel; + +namespace Barotrauma +{ + partial class NetLobbyScreen : Screen + { + public Submarine SelectedSub; + public Submarine SelectedShuttle; + + private GameModePreset[] GameModes; + public int SelectedModeIndex; + public GameModePreset SelectedMode + { + get { return GameModes[SelectedModeIndex]; } + } + + public string ServerMessageText; + + public int MissionTypeIndex; + + public List JobPreferences + { + get + { + return null; + } + } + + private List subs = new List(); + public List GetSubList() + { + return subs; + } + + public string LevelSeed + { + get + { + return levelSeed; + } + set + { + if (levelSeed == value) return; + + levelSeed = value; + } + } + + public bool StartButtonEnabled + { + get { return true; } + set { /* do nothing */ } + } + } +} diff --git a/BarotraumaShared/BarotraumaShared.projitems b/BarotraumaShared/BarotraumaShared.projitems index cabe8ea8b..ea08fc73a 100644 --- a/BarotraumaShared/BarotraumaShared.projitems +++ b/BarotraumaShared/BarotraumaShared.projitems @@ -1271,7 +1271,6 @@ PreserveNewest - @@ -1309,12 +1308,9 @@ - - - @@ -1340,20 +1336,13 @@ - - - - - - - diff --git a/BarotraumaShared/Source/Characters/Attack.cs b/BarotraumaShared/Source/Characters/Attack.cs index 6489d4347..7fe48fc98 100644 --- a/BarotraumaShared/Source/Characters/Attack.cs +++ b/BarotraumaShared/Source/Characters/Attack.cs @@ -1,9 +1,10 @@ using Microsoft.Xna.Framework; -using Barotrauma.Particles; using System; using System.Xml.Linq; using System.Collections.Generic; - +#if CLIENT +using Barotrauma.Particles; +#endif namespace Barotrauma { @@ -49,9 +50,11 @@ namespace Barotrauma public readonly float TargetForce; +#if CLIENT private Sound sound; private ParticleEmitterPrefab particleEmitterPrefab; +#endif public readonly float Stun; @@ -95,11 +98,13 @@ namespace Barotrauma Stun = ToolBox.GetAttributeFloat(element, "stun", 0.0f); +#if CLIENT string soundPath = ToolBox.GetAttributeString(element, "sound", ""); if (!string.IsNullOrWhiteSpace(soundPath)) { sound = Sound.Load(soundPath); } +#endif Range = ToolBox.GetAttributeFloat(element, "range", 0.0f); @@ -113,9 +118,11 @@ namespace Barotrauma { switch (subElement.Name.ToString().ToLowerInvariant()) { +#if CLIENT case "particleemitter": particleEmitterPrefab = new ParticleEmitterPrefab(subElement); break; +#endif case "statuseffect": statusEffects.Add(StatusEffect.Load(subElement)); break; diff --git a/BarotraumaShared/Source/Characters/Character.cs b/BarotraumaShared/Source/Characters/Character.cs index 0e133f1fa..03bbb99c1 100644 --- a/BarotraumaShared/Source/Characters/Character.cs +++ b/BarotraumaShared/Source/Characters/Character.cs @@ -1,14 +1,12 @@ using FarseerPhysics; using FarseerPhysics.Dynamics; using FarseerPhysics.Dynamics.Joints; -using Microsoft.Xna.Framework; -using Microsoft.Xna.Framework.Graphics; using Barotrauma.Networking; -using Barotrauma.Particles; using System; using System.Collections.Generic; using System.Linq; using System.Xml.Linq; +using Microsoft.Xna.Framework; namespace Barotrauma { @@ -17,26 +15,6 @@ namespace Barotrauma public static List CharacterList = new List(); public static bool DisableControls; - - - //the Character that the player is currently controlling - private static Character controlled; - - public static Character Controlled - { - get { return controlled; } - set - { - if (controlled == value) return; - controlled = value; - CharacterHUD.Reset(); - - if (controlled != null) - { - controlled.Enabled = true; - } - } - } private bool enabled = true; public bool Enabled @@ -97,8 +75,6 @@ namespace Barotrauma protected Item closestItem; private Character closestCharacter, selectedCharacter; - private Dictionary hudProgressBars; - private bool isDead; private CauseOfDeath lastAttackCauseOfDeath; private CauseOfDeath causeOfDeath; @@ -113,8 +89,6 @@ namespace Barotrauma private float bleeding; - private List sounds; - private float attackCoolDown; public Entity ViewTarget @@ -337,12 +311,7 @@ namespace Barotrauma GameMain.Server.CreateEntityEvent(this, new object[] { NetEntityEvent.Type.Status }); } } - - public Dictionary HUDProgressBars - { - get { return hudProgressBars; } - } - + public HuskInfection huskInfection; public float HuskInfectionState { @@ -540,18 +509,11 @@ namespace Barotrauma : base(null) { keys = new Key[Enum.GetNames(typeof(InputType)).Length]; - - for (int i = 0; i < Enum.GetNames(typeof(InputType)).Length; i++) - { - keys[i] = new Key(GameMain.Config.KeyBind((InputType)i)); - } - + ConfigPath = file; selectedItems = new Item[2]; - hudProgressBars = new Dictionary(); - IsRemotePlayer = isRemotePlayer; oxygen = 100.0f; @@ -570,7 +532,9 @@ namespace Barotrauma XDocument doc = ToolBox.TryLoadXml(file); if (doc == null || doc.Root == null) return; - + + InitProjSpecific(doc); + SpeciesName = ToolBox.GetAttributeString(doc.Root, "name", "Unknown"); IsHumanoid = ToolBox.GetAttributeBool(doc.Root, "humanoid", false); @@ -599,16 +563,7 @@ namespace Barotrauma drowningTime = ToolBox.GetAttributeFloat(doc.Root, "drowningtime", 10.0f); soundInterval = ToolBox.GetAttributeFloat(doc.Root, "soundinterval", 10.0f); - - var soundElements = doc.Root.Elements("sound").ToList(); - - sounds = new List(); - foreach (XElement soundElement in soundElements) - { - sounds.Add(new CharacterSound(soundElement)); - } - if (file == humanConfigFile) { if (Info.PickedItemIDs.Any()) @@ -1275,14 +1230,6 @@ namespace Barotrauma } } - public static void AddAllToGUIUpdateList() - { - for (int i = 0; i < CharacterList.Count; i++) - { - CharacterList[i].AddToGUIUpdateList(); - } - } - public static void UpdateAll(Camera cam, float deltaTime) { if (GameMain.Client == null) @@ -1315,14 +1262,6 @@ namespace Barotrauma } } - public virtual void AddToGUIUpdateList() - { - if (controlled == this) - { - CharacterHUD.AddToGUIUpdateList(this); - } - } - public virtual void Update(Camera cam, float deltaTime) { if (GameMain.Client != null && this == Controlled && !isSynced) return; @@ -1388,21 +1327,7 @@ namespace Barotrauma } } - if (controlled == this) - { - Lights.LightManager.ViewTarget = this; - CharacterHUD.Update(deltaTime, this); - - foreach (HUDProgressBar progressBar in hudProgressBars.Values) - { - progressBar.Update(deltaTime); - } - - foreach (var pb in hudProgressBars.Where(pb => pb.Value.FadeTimer<=0.0f).ToList()) - { - hudProgressBars.Remove(pb.Key); - } - } + UpdateControlled(deltaTime); if (Stun > 0.0f) { @@ -1522,10 +1447,12 @@ namespace Barotrauma float prevOxygen = oxygen; Oxygen += deltaTime * (oxygenAvailable < 30.0f ? -5.0f : 10.0f); +#if CLIENT if (prevOxygen > 0.0f && Oxygen <= 0.0f && controlled == this) { SoundPlayer.PlaySound("drown"); } +#endif PressureProtection -= deltaTime * 100.0f; @@ -1569,152 +1496,15 @@ namespace Barotrauma speechBubbleColor = color; } - public void Draw(SpriteBatch spriteBatch) - { - if (!Enabled) return; - - AnimController.Draw(spriteBatch); - } - - public void DrawHUD(SpriteBatch spriteBatch, Camera cam) - { - CharacterHUD.Draw(spriteBatch, this, cam); - } - - public virtual void DrawFront(SpriteBatch spriteBatch, Camera cam) - { - if (!Enabled) return; - - if (GameMain.DebugDraw) - { - AnimController.DebugDraw(spriteBatch); - - if (aiTarget != null) aiTarget.Draw(spriteBatch); - } - - /*if (memPos != null && memPos.Count > 0 && controlled == this) - { - PosInfo serverPos = memPos.Last(); - Vector2 remoteVec = ConvertUnits.ToDisplayUnits(serverPos.Position); - if (Submarine != null) - { - remoteVec += Submarine.DrawPosition; - } - remoteVec.Y = -remoteVec.Y; - - PosInfo localPos = memLocalPos.Find(m => m.ID == serverPos.ID); - int mpind = memLocalPos.FindIndex(lp => lp.ID == localPos.ID); - PosInfo localPos1 = mpind > 0 ? memLocalPos[mpind - 1] : null; - PosInfo localPos2 = mpind < memLocalPos.Count-1 ? memLocalPos[mpind + 1] : null; - - Vector2 localVec = ConvertUnits.ToDisplayUnits(localPos.Position); - Vector2 localVec1 = localPos1 != null ? ConvertUnits.ToDisplayUnits(((PosInfo)localPos1).Position) : Vector2.Zero; - Vector2 localVec2 = localPos2 != null ? ConvertUnits.ToDisplayUnits(((PosInfo)localPos2).Position) : Vector2.Zero; - if (Submarine != null) - { - localVec += Submarine.DrawPosition; - localVec1 += Submarine.DrawPosition; - localVec2 += Submarine.DrawPosition; - } - localVec.Y = -localVec.Y; - localVec1.Y = -localVec1.Y; - localVec2.Y = -localVec2.Y; - - //GUI.DrawLine(spriteBatch, remoteVec, localVec, Color.Yellow, 0, 10); - if (localPos1 != null) GUI.DrawLine(spriteBatch, remoteVec, localVec1, Color.Lime, 0, 2); - if (localPos2 != null) GUI.DrawLine(spriteBatch, remoteVec + Vector2.One, localVec2 + Vector2.One, Color.Red, 0, 2); - } - - Vector2 mouseDrawPos = CursorWorldPosition; - mouseDrawPos.Y = -mouseDrawPos.Y; - GUI.DrawLine(spriteBatch, mouseDrawPos - new Vector2(0, 5), mouseDrawPos + new Vector2(0, 5), Color.Red, 0, 10); - - Vector2 closestItemPos = closestItem != null ? closestItem.DrawPosition : Vector2.Zero; - closestItemPos.Y = -closestItemPos.Y; - GUI.DrawLine(spriteBatch, closestItemPos - new Vector2(0, 5), closestItemPos + new Vector2(0, 5), Color.Lime, 0, 10);*/ - - if (this == controlled || GUI.DisableHUD) return; - - Vector2 pos = DrawPosition; - pos.Y = -pos.Y; - - if (speechBubbleTimer > 0.0f) - { - GUI.SpeechBubbleIcon.Draw(spriteBatch, pos - Vector2.UnitY * 100.0f, - speechBubbleColor * Math.Min(speechBubbleTimer, 1.0f), 0.0f, - Math.Min((float)speechBubbleTimer, 1.0f)); - } - - if (this == controlled) return; - - if (info != null) - { - Vector2 namePos = new Vector2(pos.X, pos.Y - 110.0f - (5.0f / cam.Zoom)) - GUI.Font.MeasureString(Info.Name) * 0.5f / cam.Zoom; - Color nameColor = Color.White; - - if (Character.Controlled != null && TeamID != Character.Controlled.TeamID) - { - nameColor = Color.Red; - } - GUI.Font.DrawString(spriteBatch, Info.Name, namePos + new Vector2(1.0f / cam.Zoom, 1.0f / cam.Zoom), Color.Black, 0.0f, Vector2.Zero, 1.0f / cam.Zoom, SpriteEffects.None, 0.001f); - GUI.Font.DrawString(spriteBatch, Info.Name, namePos, nameColor, 0.0f, Vector2.Zero, 1.0f / cam.Zoom, SpriteEffects.None, 0.0f); - - if (GameMain.DebugDraw) - { - GUI.Font.DrawString(spriteBatch, ID.ToString(), namePos - new Vector2(0.0f, 20.0f), Color.White); - } - } - - if (isDead) return; - - if (health < maxHealth * 0.98f) - { - Vector2 healthBarPos = new Vector2(pos.X - 50, DrawPosition.Y + 100.0f); - - GUI.DrawProgressBar(spriteBatch, healthBarPos, new Vector2(100.0f, 15.0f), health / maxHealth, Color.Lerp(Color.Red, Color.Green, health / maxHealth) * 0.8f); - } - } - - /// - /// Creates a progress bar that's "linked" to the specified object (or updates an existing one if there's one already linked to the object) - /// The progress bar will automatically fade out after 1 sec if the method hasn't been called during that time - /// - public HUDProgressBar UpdateHUDProgressBar(object linkedObject, Vector2 worldPosition, float progress, Color emptyColor, Color fullColor) - { - if (controlled != this) return null; - - HUDProgressBar progressBar = null; - if (!hudProgressBars.TryGetValue(linkedObject, out progressBar)) - { - progressBar = new HUDProgressBar(worldPosition, Submarine, emptyColor, fullColor); - hudProgressBars.Add(linkedObject, progressBar); - } - - progressBar.WorldPosition = worldPosition; - progressBar.FadeTimer = Math.Max(progressBar.FadeTimer, 1.0f); - progressBar.Progress = progress; - - return progressBar; - } - - public void PlaySound(CharacterSound.SoundType soundType) - { - if (sounds == null || sounds.Count == 0) return; - - var matchingSounds = sounds.FindAll(s => s.Type == soundType); - if (matchingSounds.Count == 0) return; - - var selectedSound = matchingSounds[Rand.Int(matchingSounds.Count)]; - selectedSound.Sound.Play(1.0f, selectedSound.Range, AnimController.WorldPosition); - } - public virtual void AddDamage(CauseOfDeath causeOfDeath, float amount, IDamageable attacker) { Health = health-amount; if (amount > 0.0f) { lastAttackCauseOfDeath = causeOfDeath; +#if CLIENT if (controlled == this) CharacterHUD.TakeDamage(amount); +#endif } if (health <= minHealth) Kill(causeOfDeath); } @@ -1820,19 +1610,7 @@ namespace Barotrauma // limb.Damage = 100.0f; } - SoundPlayer.PlaySound("implode", 1.0f, 150.0f, WorldPosition); - - for (int i = 0; i < 10; i++) - { - Particle p = GameMain.ParticleManager.CreateParticle("waterblood", - ConvertUnits.ToDisplayUnits(centerOfMass) + Rand.Vector(5.0f), - Rand.Vector(10.0f)); - if (p != null) p.Size *= 2.0f; - - GameMain.ParticleManager.CreateParticle("bubbles", - ConvertUnits.ToDisplayUnits(centerOfMass) + Rand.Vector(5.0f), - new Vector2(Rand.Range(-50f, 50f), Rand.Range(-100f, 50f))); - } + ImplodeFX(); foreach (var joint in AnimController.limbJoints) { @@ -1852,6 +1630,7 @@ namespace Barotrauma if (GameMain.NetworkMember != null) { +#if CLIENT if (Character.controlled == this) { string chatMessage = InfoTextManager.GetInfoText("Self_CauseOfDeath." + causeOfDeath.ToString()); @@ -1861,6 +1640,7 @@ namespace Barotrauma GameMain.LightManager.LosEnabled = false; controlled = null; } +#endif if (GameMain.Server != null) GameMain.Server.CreateEntityEvent(this, new object[] { NetEntityEvent.Type.Status }); @@ -1871,8 +1651,10 @@ namespace Barotrauma GameServer.Log(Name+" has died (Cause of death: "+causeOfDeath+")", ServerLog.MessageType.Attack); if (OnDeath != null) OnDeath(this, causeOfDeath); - + +#if CLIENT PlaySound(CharacterSound.SoundType.Die); +#endif isDead = true; @@ -1935,7 +1717,15 @@ namespace Barotrauma CharacterList.Remove(this); +#if CLIENT if (controlled == this) controlled = null; + + if (GameMain.GameSession?.CrewManager != null && + GameMain.GameSession.CrewManager.characters.Contains(this)) + { + GameMain.GameSession.CrewManager.characters.Remove(this); + } +#endif if (GameMain.Client != null && GameMain.Client.Character == this) GameMain.Client.Character = null; @@ -1948,12 +1738,6 @@ namespace Barotrauma if (selectedItems[0] != null) selectedItems[0].Drop(this); if (selectedItems[1] != null) selectedItems[1].Drop(this); - if (GameMain.GameSession?.CrewManager != null && - GameMain.GameSession.CrewManager.characters.Contains(this)) - { - GameMain.GameSession.CrewManager.characters.Remove(this); - } - foreach (Character c in CharacterList) { if (c.closestCharacter == this) c.closestCharacter = null; diff --git a/BarotraumaShared/Source/Characters/CharacterInfo.cs b/BarotraumaShared/Source/Characters/CharacterInfo.cs index f67043f6e..a4ca802de 100644 --- a/BarotraumaShared/Source/Characters/CharacterInfo.cs +++ b/BarotraumaShared/Source/Characters/CharacterInfo.cs @@ -1,5 +1,4 @@ using Microsoft.Xna.Framework; -using Microsoft.Xna.Framework.Graphics; using System; using System.Collections.Generic; using System.IO; @@ -10,7 +9,7 @@ namespace Barotrauma { public enum Gender { None, Male, Female }; - class CharacterInfo + partial class CharacterInfo { public string Name; @@ -211,66 +210,6 @@ namespace Barotrauma } } - public GUIFrame CreateInfoFrame(Rectangle rect) - { - GUIFrame frame = new GUIFrame(rect, Color.Transparent); - frame.Padding = new Vector4(10.0f,10.0f,10.0f,10.0f); - - return CreateInfoFrame(frame); - } - - public GUIFrame CreateInfoFrame(GUIFrame frame) - { - new GUIImage(new Rectangle(0,0,30,30), HeadSprite, Alignment.TopLeft, frame); - - ScalableFont font = frame.Rect.Width<280 ? GUI.SmallFont : GUI.Font; - - int x = 0, y = 0; - new GUITextBlock(new Rectangle(x+60, y, 200, 20), Name, "", frame, font); - y += 20; - - if (Job!=null) - { - new GUITextBlock(new Rectangle(x + 60, y, 200, 20), Job.Name, "", frame, font); - y += 30; - - var skills = Job.Skills; - skills.Sort((s1, s2) => -s1.Level.CompareTo(s2.Level)); - - new GUITextBlock(new Rectangle(x, y, 200, 20), "Skills:", "", frame, font); - y += 20; - foreach (Skill skill in skills) - { - Color textColor = Color.White * (0.5f + skill.Level/200.0f); - new GUITextBlock(new Rectangle(x, y, 200, 20), skill.Name, Color.Transparent, textColor, Alignment.Left, "", frame).Font = font; - new GUITextBlock(new Rectangle(x, y, 200, 20), skill.Level.ToString(), Color.Transparent, textColor, Alignment.Right, "", frame).Font = font; - y += 20; - } - } - - - return frame; - } - - public GUIFrame CreateCharacterFrame(GUIComponent parent, string text, object userData) - { - GUIFrame frame = new GUIFrame(new Rectangle(0, 0, 0, 40), Color.Transparent, "ListBoxElement", parent); - frame.UserData = userData; - - GUITextBlock textBlock = new GUITextBlock( - new Rectangle(40, 0, 0, 25), - text, - null, null, - Alignment.Left, Alignment.Left, - "", frame, false); - textBlock.Font = GUI.SmallFont; - textBlock.Padding = new Vector4(5.0f, 0.0f, 5.0f, 0.0f); - - new GUIImage(new Rectangle(-5, -5, 0, 0), HeadSprite, Alignment.Left, frame); - - return frame; - } - public void UpdateCharacterItems() { pickedItems.Clear(); diff --git a/BarotraumaShared/Source/Characters/Jobs/JobPrefab.cs b/BarotraumaShared/Source/Characters/Jobs/JobPrefab.cs index f75993dc0..ef2bb924a 100644 --- a/BarotraumaShared/Source/Characters/Jobs/JobPrefab.cs +++ b/BarotraumaShared/Source/Characters/Jobs/JobPrefab.cs @@ -6,7 +6,7 @@ using System.Linq; namespace Barotrauma { - class JobPrefab + partial class JobPrefab { public static List List; @@ -102,52 +102,6 @@ namespace Barotrauma return List[Rand.Int(List.Count)]; } - public GUIFrame CreateInfoFrame() - { - int width = 500, height = 400; - - GUIFrame backFrame = new GUIFrame(Rectangle.Empty, Color.Black*0.5f); - backFrame.Padding = Vector4.Zero; - - GUIFrame frame = new GUIFrame(new Rectangle(GameMain.GraphicsWidth / 2 - width / 2, GameMain.GraphicsHeight / 2 - height / 2, width, height), "", backFrame); - frame.Padding = new Vector4(30.0f, 30.0f, 30.0f, 30.0f); - - new GUITextBlock(new Rectangle(0,0,100,20), Name, "", Alignment.TopLeft, Alignment.TopLeft, frame, false, GUI.LargeFont); - - var descriptionBlock = new GUITextBlock(new Rectangle(0, 40, 0, 0), Description, "", Alignment.TopLeft, Alignment.TopLeft, frame, true, GUI.SmallFont); - - new GUITextBlock(new Rectangle(0, 40 + descriptionBlock.Rect.Height + 20, 100, 20), "Skills: ", "", Alignment.TopLeft, Alignment.TopLeft, frame, false, GUI.LargeFont); - - int y = 40 + descriptionBlock.Rect.Height + 50; - foreach (SkillPrefab skill in Skills) - { - string skillDescription = Skill.GetLevelName((int)skill.LevelRange.X); - string skillDescription2 = Skill.GetLevelName((int)skill.LevelRange.Y); - - if (skillDescription2!= skillDescription) - { - skillDescription += "/"+skillDescription2; - } - new GUITextBlock(new Rectangle(0, y, 100, 20), - " - " + skill.Name + ": " + skillDescription, "", Alignment.TopLeft, Alignment.TopLeft, frame, false, GUI.SmallFont); - - y += 20; - } - - new GUITextBlock(new Rectangle(250, 40 + descriptionBlock.Rect.Height + 20, 0, 20), "Items: ", "", Alignment.TopLeft, Alignment.TopLeft, frame, false, GUI.LargeFont); - - y = 40 + descriptionBlock.Rect.Height + 50; - foreach (string itemName in ItemNames) - { - new GUITextBlock(new Rectangle(250, y, 100, 20), - " - " + itemName, "", Alignment.TopLeft, Alignment.TopLeft, frame, false, GUI.SmallFont); - - y += 20; - } - - return backFrame; - } - public static void LoadAll(List filePaths) { List = new List(); diff --git a/BarotraumaShared/Source/Characters/Limb.cs b/BarotraumaShared/Source/Characters/Limb.cs index 2fa474003..854e7a188 100644 --- a/BarotraumaShared/Source/Characters/Limb.cs +++ b/BarotraumaShared/Source/Characters/Limb.cs @@ -4,7 +4,7 @@ using FarseerPhysics; using FarseerPhysics.Dynamics; using FarseerPhysics.Dynamics.Joints; using Microsoft.Xna.Framework; -using Microsoft.Xna.Framework.Graphics; +//using Microsoft.Xna.Framework.Graphics; using Barotrauma.Items.Components; using System.Collections.Generic; using Barotrauma.Lights; @@ -19,7 +19,7 @@ namespace Barotrauma LeftLeg, RightLeg, LeftFoot, RightFoot, Head, Torso, Tail, Legs, RightThigh, LeftThigh, Waist }; - class Limb + partial class Limb { private const float LimbDensity = 15; private const float LimbAngularDamping = 7; @@ -54,7 +54,6 @@ namespace Barotrauma private readonly Vector2 armorSector; private readonly float armorValue; - Sound hitSound; //a timer for delaying when a hitsound/attacksound can be played again public float soundTimer; public const float SoundInterval = 0.4f; @@ -109,12 +108,7 @@ namespace Barotrauma } public bool Disabled { get; set; } - - public Sound HitSound - { - get { return hitSound; } - } - + public Vector2 LinearVelocity { get { return body.LinearVelocity; } @@ -313,9 +307,11 @@ namespace Barotrauma case "attack": attack = new Attack(subElement); break; +#if CLIENT case "sound": hitSound = Sound.Load(ToolBox.GetAttributeString(subElement, "file", "")); break; +#endif } } } @@ -335,8 +331,6 @@ namespace Barotrauma public AttackResult AddDamage(Vector2 position, DamageType damageType, float amount, float bleedingAmount, bool playSound) { - DamageSoundType damageSoundType = (damageType == DamageType.Blunt) ? DamageSoundType.LimbBlunt : DamageSoundType.LimbSlash; - bool hitArmor = false; float totalArmorValue = 0.0f; @@ -355,8 +349,15 @@ namespace Barotrauma totalArmorValue += wearable.WearableComponent.ArmorValue; } } - - + + //Bleeding += bleedingAmount; + //Damage += amount; + +#if CLIENT + float bloodAmount = hitArmor || bleedingAmount <= 0.0f ? 0 : (int)Math.Min((int)(amount * 2.0f), 20); + + DamageSoundType damageSoundType = (damageType == DamageType.Blunt) ? DamageSoundType.LimbBlunt : DamageSoundType.LimbSlash; + if (hitArmor) { totalArmorValue = Math.Max(totalArmorValue, 0.0f); @@ -371,11 +372,6 @@ namespace Barotrauma SoundPlayer.PlayDamageSound(damageSoundType, amount, position); } - //Bleeding += bleedingAmount; - //Damage += amount; - - float bloodAmount = hitArmor || bleedingAmount<=0.0f ? 0 : (int)Math.Min((int)(amount * 2.0f), 20); - for (int i = 0; i < bloodAmount; i++) { Vector2 particleVel = SimPosition - position; @@ -390,6 +386,7 @@ namespace Barotrauma { GameMain.ParticleManager.CreateParticle("waterblood", WorldPosition, Vector2.Zero, 0.0f, character.AnimController.CurrentHull); } +#endif damage += Math.Max(amount,bleedingAmount) / character.MaxHealth * 100.0f; @@ -479,77 +476,6 @@ namespace Barotrauma } } - public void Draw(SpriteBatch spriteBatch) - { - float brightness = 1.0f - (burnt / 100.0f) * 0.5f; - Color color = new Color(brightness, brightness, brightness); - - body.Dir = Dir; - - bool hideLimb = wearingItems.Any(w => w != null && w.HideLimb); - - if (!hideLimb) - { - body.Draw(spriteBatch, sprite, color, null, scale); - } - else - { - body.UpdateDrawPosition(); - } - - if (LightSource != null) - { - LightSource.Position = body.DrawPosition; - } - - foreach (WearableSprite wearable in wearingItems) - { - SpriteEffects spriteEffect = (dir == Direction.Right) ? SpriteEffects.None : SpriteEffects.FlipHorizontally; - - Vector2 origin = wearable.Sprite.Origin; - if (body.Dir == -1.0f) origin.X = wearable.Sprite.SourceRect.Width - origin.X; - - float depth = sprite.Depth - 0.000001f; - - if (wearable.DepthLimb != LimbType.None) - { - Limb depthLimb = character.AnimController.GetLimb(wearable.DepthLimb); - if (depthLimb != null) - { - depth = depthLimb.sprite.Depth - 0.000001f; - } - } - - wearable.Sprite.Draw(spriteBatch, - new Vector2(body.DrawPosition.X, -body.DrawPosition.Y), - color, origin, - -body.DrawRotation, - scale, spriteEffect, depth); - } - - if (damage > 0.0f && damagedSprite != null && !hideLimb) - { - SpriteEffects spriteEffect = (dir == Direction.Right) ? SpriteEffects.None : SpriteEffects.FlipHorizontally; - - float depth = sprite.Depth - 0.0000015f; - - damagedSprite.Draw(spriteBatch, - new Vector2(body.DrawPosition.X, -body.DrawPosition.Y), - color * Math.Min(damage / 50.0f, 1.0f), sprite.Origin, - -body.DrawRotation, - 1.0f, spriteEffect, depth); - } - - if (!GameMain.DebugDraw) return; - - if (pullJoint != null) - { - Vector2 pos = ConvertUnits.ToDisplayUnits(pullJoint.WorldAnchorB); - GUI.DrawRectangle(spriteBatch, new Rectangle((int)pos.X, (int)-pos.Y, 5, 5), Color.Red, true); - } - } - - public void Remove() { if (sprite != null) @@ -574,11 +500,13 @@ namespace Barotrauma body = null; } +#if CLIENT if (hitSound != null) { hitSound.Remove(); hitSound = null; } +#endif } } } diff --git a/BarotraumaShared/Source/Characters/StatusEffect.cs b/BarotraumaShared/Source/Characters/StatusEffect.cs index 1ff504b28..cebeb9e1e 100644 --- a/BarotraumaShared/Source/Characters/StatusEffect.cs +++ b/BarotraumaShared/Source/Characters/StatusEffect.cs @@ -1,13 +1,15 @@ -using Barotrauma.Particles; -using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework; using System; using System.Collections.Generic; using System.Linq; using System.Xml.Linq; +#if CLIENT +using Barotrauma.Particles; +#endif namespace Barotrauma { - class StatusEffect + partial class StatusEffect { [Flags] public enum TargetType @@ -20,6 +22,12 @@ namespace Barotrauma private List requiredItems; +#if CLIENT + private List particleEmitters; + + private Sound sound; +#endif + public string[] propertyNames; private object[] propertyEffects; @@ -37,12 +45,8 @@ namespace Barotrauma private Explosion explosion; - private List particleEmitters; - public readonly float FireSize; - private Sound sound; - public TargetType Targets { get { return targetTypes; } @@ -71,7 +75,10 @@ namespace Barotrauma protected StatusEffect(XElement element) { requiredItems = new List(); + +#if CLIENT particleEmitters = new List(); +#endif IEnumerable attributes = element.Attributes(); List propertyAttributes = new List(); @@ -122,12 +129,14 @@ namespace Barotrauma targetNames.Add(names[i].Trim()); } break; - case "sound": - sound = Sound.Load(attribute.Value.ToString()); - break; case "duration": duration = ToolBox.GetAttributeFloat(attribute, 0.0f); break; +#if CLIENT + case "sound": + sound = Sound.Load(attribute.Value.ToString()); + break; +#endif default: propertyAttributes.Add(attribute); break; @@ -160,9 +169,6 @@ namespace Barotrauma case "useitem": useItem = true; break; - case "particleemitter": - particleEmitters.Add(new ParticleEmitterPrefab(subElement)); - break; case "requireditem": case "requireditems": RelatedItem newRequiredItem = RelatedItem.Load(subElement); @@ -171,6 +177,11 @@ namespace Barotrauma requiredItems.Add(newRequiredItem); break; +#if CLIENT + case "particleemitter": + particleEmitters.Add(new ParticleEmitterPrefab(subElement)); + break; +#endif } } } @@ -214,8 +225,10 @@ namespace Barotrauma } protected void Apply(float deltaTime, Entity entity, List targets) - { + { +#if CLIENT if (sound != null) sound.Play(1.0f, 1000.0f, entity.WorldPosition); +#endif if (useItem) { @@ -264,12 +277,14 @@ namespace Barotrauma var fire = new FireSource(entity.WorldPosition, hull); fire.Size = new Vector2(FireSize, fire.Size.Y); - } + } +#if CLIENT foreach (ParticleEmitterPrefab emitter in particleEmitters) { emitter.Emit(entity.WorldPosition, hull); } +#endif } private IEnumerable ApplyToPropertyOverDuration(float duration, ObjectProperty property, object value) diff --git a/BarotraumaShared/Source/DebugConsole.cs b/BarotraumaShared/Source/DebugConsole.cs index 288d04a4a..b4918a132 100644 --- a/BarotraumaShared/Source/DebugConsole.cs +++ b/BarotraumaShared/Source/DebugConsole.cs @@ -27,152 +27,12 @@ namespace Barotrauma } } - static class DebugConsole + static partial class DebugConsole { const int MaxMessages = 200; public static List Messages = new List(); - static bool isOpen; - - - static GUIFrame frame; - static GUIListBox listBox; - static GUITextBox textBox; - - //used for keeping track of the message entered when pressing up/down - static int selectedIndex; - - public static bool IsOpen - { - get - { - return isOpen; - } - } - - public static void Init(GameWindow window) - { - int x = 20, y = 20; - int width = 800, height = 500; - - frame = new GUIFrame(new Rectangle(x, y, width, height), new Color(0.4f, 0.4f, 0.4f, 0.8f)); - frame.Padding = new Vector4(5.0f, 5.0f, 5.0f, 5.0f); - - listBox = new GUIListBox(new Rectangle(0, 0, 0, frame.Rect.Height - 40), Color.Black, "", frame); - //listBox.Color = Color.Black * 0.7f; - - textBox = new GUITextBox(new Rectangle(0,0,0,20), Color.Black, Color.White, Alignment.BottomLeft, Alignment.Left, "", frame); - //textBox.Color = Color.Black * 0.7f; - - //messages already added before initialization -> add them to the listbox - List unInitializedMessages = new List(Messages); - Messages.Clear(); - - foreach (ColoredText msg in unInitializedMessages) - { - NewMessage(msg.Text, msg.Color); - } - - NewMessage("Press F3 to open/close the debug console", Color.Cyan); - NewMessage("Enter \"help\" for a list of available console commands", Color.Cyan); - - } - - public static void AddToGUIUpdateList() - { - if (isOpen) - { - frame.AddToGUIUpdateList(); - } - } - - public static void Update(GameMain game, float deltaTime) - { - if (PlayerInput.KeyHit(Keys.F3)) - { - isOpen = !isOpen; - if (isOpen) - { - textBox.Select(); - AddToGUIUpdateList(); - } - else - { - GUIComponent.ForceMouseOn(null); - textBox.Deselect(); - } - - //keyboardDispatcher.Subscriber = (isOpen) ? textBox : null; - } - - if (isOpen) - { - frame.Update(deltaTime); - - Character.DisableControls = true; - - if (PlayerInput.KeyHit(Keys.Up)) - { - SelectMessage(-1); - } - else if (PlayerInput.KeyHit(Keys.Down)) - { - SelectMessage(1); - } - - //textBox.Update(deltaTime); - - if (PlayerInput.KeyDown(Keys.Enter) && textBox.Text != "") - { - ExecuteCommand(textBox.Text, game); - textBox.Text = ""; - - //selectedIndex = messages.Count; - } - } - } - - private static void SelectMessage(int direction) - { - int messageCount = listBox.children.Count; - if (messageCount == 0) return; - - direction = Math.Min(Math.Max(-1, direction), 1); - - selectedIndex += direction; - if (selectedIndex < 0) selectedIndex = messageCount - 1; - selectedIndex = selectedIndex % messageCount; - - textBox.Text = (listBox.children[selectedIndex] as GUITextBlock).Text; - } - - public static void Draw(SpriteBatch spriteBatch) - { - if (!isOpen) return; - - frame.Draw(spriteBatch); - } - - private static bool IsCommandPermitted(string command, GameClient client) - { - switch (command) - { - case "kick": - return client.HasPermission(ClientPermissions.Kick); - case "ban": - case "banip": - return client.HasPermission(ClientPermissions.Ban); - case "netstats": - case "help": - case "dumpids": - case "admin": - return true; - default: - return false; - } - } - public static void ExecuteCommand(string command, GameMain game) { if (string.IsNullOrWhiteSpace(command)) return; @@ -180,15 +40,17 @@ namespace Barotrauma if (!commands[0].ToLowerInvariant().Equals("admin")) { - NewMessage(textBox.Text, Color.White); + NewMessage(InputText, Color.White); } #if !DEBUG +#if CLIENT if (GameMain.Client != null && !IsCommandPermitted(commands[0].ToLowerInvariant(), GameMain.Client)) { ThrowError("You're not permitted to use the command \"" + commands[0].ToLowerInvariant()+"\"!"); return; } +#endif #endif switch (commands[0].ToLowerInvariant()) @@ -304,8 +166,9 @@ namespace Barotrauma if (commands[1].ToLowerInvariant()=="human") { - spawnedCharacter = Character.Create(Character.HumanConfigFile, spawnPosition); + spawnedCharacter = Character.Create(Character.HumanConfigFile, spawnPosition); +#if CLIENT if (GameMain.GameSession != null) { SinglePlayerMode mode = GameMain.GameSession.gameMode as SinglePlayerMode; @@ -316,6 +179,7 @@ namespace Barotrauma GameMain.GameSession.CrewManager.SelectCharacter(null, Character.Controlled); } } +#endif } else { @@ -418,90 +282,6 @@ namespace Barotrauma } } break; - case "startclient": - if (commands.Length == 1) return; - if (GameMain.Client == null) - { - GameMain.NetworkMember = new GameClient("Name"); - GameMain.Client.ConnectToServer(commands[1]); - } - break; - case "mainmenuscreen": - case "mainmenu": - case "menu": - GameMain.GameSession = null; - - List characters = new List(Character.CharacterList); - foreach (Character c in characters) - { - c.Remove(); - } - - GameMain.MainMenuScreen.Select(); - break; - case "gamescreen": - case "game": - GameMain.GameScreen.Select(); - break; - case "editmapscreen": - case "editmap": - case "edit": - if (commands.Length>1) - { - Submarine.Load(string.Join(" ", commands.Skip(1)), true); - } - GameMain.EditMapScreen.Select(); - break; - case "test": - Submarine.Load("aegir mark ii", true); - GameMain.DebugDraw = true; - GameMain.LightManager.LosEnabled = false; - GameMain.EditMapScreen.Select(); - break; - case "editcharacter": - case "editchar": - GameMain.EditCharacterScreen.Select(); - break; - case "controlcharacter": - case "control": - { - if (commands.Length < 2) break; - - var character = FindMatchingCharacter(commands, true); - - if (character != null) - { - Character.Controlled = character; - } - } - break; - case "setclientcharacter": - { - if (GameMain.Server == null) break; - - int separatorIndex = Array.IndexOf(commands, ";"); - - if (separatorIndex == -1 || commands.Length < 4) - { - ThrowError("Invalid parameters. The command should be formatted as \"setclientcharacter [client] ; [character]\""); - break; - } - - string[] commandsLeft = commands.Take(separatorIndex).ToArray(); - string[] commandsRight = commands.Skip(separatorIndex).ToArray(); - - string clientName = String.Join(" ", commandsLeft.Skip(1)); - - var client = GameMain.Server.ConnectedClients.Find(c => c.name == clientName); - if (client == null) - { - ThrowError("Client \"" + clientName + "\" not found."); - } - - var character = FindMatchingCharacter(commandsRight, false); - GameMain.Server.SetClientCharacter(client, character); - } - break; case "teleportcharacter": case "teleport": var tpCharacter = FindMatchingCharacter(commands, false); @@ -638,20 +418,6 @@ namespace Barotrauma reactorItem.CreateServerEvent(reactor); } break; - case "shake": - GameMain.GameScreen.Cam.Shake = 10.0f; - break; - case "losenabled": - case "los": - case "drawlos": - GameMain.LightManager.LosEnabled = !GameMain.LightManager.LosEnabled; - break; - case "lighting": - case "lightingenabled": - case "light": - case "lights": - GameMain.LightManager.LightingEnabled = !GameMain.LightManager.LightingEnabled; - break; case "oxygen": case "air": foreach (Hull hull in Hull.hullList) @@ -659,99 +425,7 @@ namespace Barotrauma hull.OxygenPercentage = 100.0f; } break; - case "tutorial": - TutorialMode.StartTutorial(Tutorials.TutorialType.TutorialTypes[0]); - - - break; - case "editortutorial": - GameMain.EditMapScreen.Select(); - GameMain.EditMapScreen.StartTutorial(); - break; - case "lobbyscreen": - case "lobby": - GameMain.LobbyScreen.Select(); - break; - case "savemap": - case "savesub": - case "save": - if (commands.Length < 2) break; - - if (GameMain.EditMapScreen.CharacterMode) - { - GameMain.EditMapScreen.ToggleCharacterMode(); - } - - string fileName = string.Join(" ", commands.Skip(1)); - if (fileName.Contains("../")) - { - DebugConsole.ThrowError("Illegal symbols in filename (../)"); - return; - } - - if (Submarine.SaveCurrent(System.IO.Path.Combine(Submarine.SavePath, fileName + ".sub"))) - { - NewMessage("Sub saved", Color.Green); - //Submarine.Loaded.First().CheckForErrors(); - } - - break; - case "loadmap": - case "loadsub": - case "load": - if (commands.Length < 2) break; - - Submarine.Load(string.Join(" ", commands.Skip(1)), true); - break; - case "cleansub": - for (int i = MapEntity.mapEntityList.Count - 1; i >= 0; i--) - { - MapEntity me = MapEntity.mapEntityList[i]; - - if (me.SimPosition.Length()>2000.0f) - { - DebugConsole.NewMessage("Removed "+me.Name+" (simposition "+me.SimPosition+")", Color.Orange); - MapEntity.mapEntityList.RemoveAt(i); - } - else if (me.MoveWithLevel) - { - DebugConsole.NewMessage("Removed " + me.Name + " (MoveWithLevel==true)", Color.Orange); - MapEntity.mapEntityList.RemoveAt(i); - } - else if (me is Item) - { - Item item = me as Item; - var wire = item.GetComponent(); - if (wire == null) continue; - - if (wire.GetNodes().Count > 0 && !wire.Connections.Any(c => c != null)) - { - wire.Item.Drop(null); - DebugConsole.NewMessage("Dropped wire (ID: "+wire.Item.ID+") - attached on wall but no connections found", Color.Orange); - } - } - - } - break; - case "messagebox": - if (commands.Length < 3) break; - new GUIMessageBox(commands[1], commands[2]); - break; - case "debugdraw": - GameMain.DebugDraw = !GameMain.DebugDraw; - break; - case "disablehud": - case "hud": - GUI.DisableHUD = !GUI.DisableHUD; - GameMain.Instance.IsMouseVisible = !GameMain.Instance.IsMouseVisible; - break; - case "followsub": - Camera.FollowSub = !Camera.FollowSub; - break; - case "drawaitargets": - case "showaitargets": - AITarget.ShowAITargets = !AITarget.ShowAITargets; - break; + case "killmonsters": foreach (Character c in Character.CharacterList) { @@ -764,143 +438,9 @@ namespace Barotrauma GameMain.Server.ShowNetStats = !GameMain.Server.ShowNetStats; break; -#if DEBUG - case "spamevents": - foreach (Item item in Item.ItemList) - { - for (int i = 0; i(); - if (itemContainer != null) - { - GameMain.Server.CreateEntityEvent(item, new object[] { NetEntityEvent.Type.InventoryState }); - } - GameMain.Server.CreateEntityEvent(item, new object[] { NetEntityEvent.Type.Status }); - - item.NeedsPositionUpdate = true; - } - } - - foreach (Character c in Character.CharacterList) - { - GameMain.Server.CreateEntityEvent(c, new object[] { NetEntityEvent.Type.Status }); - } - - foreach (Structure wall in Structure.WallList) - { - GameMain.Server.CreateEntityEvent(wall); - } - break; - case "spamchatmessages": - int msgCount = 1000; - if (commands.Length > 1) int.TryParse(commands[1], out msgCount); - int msgLength = 50; - if (commands.Length > 2) int.TryParse(commands[2], out msgLength); - - for (int i = 0; i < msgCount; i++) - { - if (GameMain.Server != null) - { - GameMain.Server.SendChatMessage(ToolBox.RandomSeed(msgLength), ChatMessageType.Default); - } - else - { - GameMain.Client.SendChatMessage(ToolBox.RandomSeed(msgLength)); - } - } - break; -#endif - case "cleanbuild": - GameMain.Config.MusicVolume = 0.5f; - GameMain.Config.SoundVolume = 0.5f; - DebugConsole.NewMessage("Music and sound volume set to 0.5", Color.Green); - - GameMain.Config.GraphicsWidth = 0; - GameMain.Config.GraphicsHeight = 0; - GameMain.Config.WindowMode = WindowMode.Fullscreen; - DebugConsole.NewMessage("Resolution set to 0 x 0 (screen resolution will be used)", Color.Green); - DebugConsole.NewMessage("Fullscreen enabled", Color.Green); - - GameSettings.VerboseLogging = false; - - if (GameMain.Config.MasterServerUrl != "http://www.undertowgames.com/baromaster") - { - DebugConsole.ThrowError("MasterServerUrl \""+GameMain.Config.MasterServerUrl+"\"!"); - } - - GameMain.Config.Save("config.xml"); - - var saveFiles = System.IO.Directory.GetFiles(SaveUtil.SaveFolder); - - foreach (string saveFile in saveFiles) - { - System.IO.File.Delete(saveFile); - DebugConsole.NewMessage("Deleted "+saveFile, Color.Green); - } - - if (System.IO.Directory.Exists(System.IO.Path.Combine(SaveUtil.SaveFolder, "temp"))) - { - System.IO.Directory.Delete(System.IO.Path.Combine(SaveUtil.SaveFolder, "temp"), true); - DebugConsole.NewMessage("Deleted temp save folder", Color.Green); - } - - if (System.IO.Directory.Exists(ServerLog.SavePath)) - { - var logFiles = System.IO.Directory.GetFiles(ServerLog.SavePath); - - foreach (string logFile in logFiles) - { - System.IO.File.Delete(logFile); - DebugConsole.NewMessage("Deleted "+logFile, Color.Green); - } - } - - if (System.IO.File.Exists("filelist.xml")) - { - System.IO.File.Delete("filelist.xml"); - DebugConsole.NewMessage("Deleted filelist", Color.Green); - } - - - if (System.IO.File.Exists("Submarines/TutorialSub.sub")) - { - System.IO.File.Delete("Submarines/TutorialSub.sub"); - - DebugConsole.NewMessage("Deleted TutorialSub from the submarine folder", Color.Green); - } - - if (System.IO.File.Exists(GameServer.SettingsFile)) - { - System.IO.File.Delete(GameServer.SettingsFile); - DebugConsole.NewMessage("Deleted server settings", Color.Green); - } - - if (System.IO.File.Exists(GameServer.ClientPermissionsFile)) - { - System.IO.File.Delete(GameServer.ClientPermissionsFile); - DebugConsole.NewMessage("Deleted client permission file", Color.Green); - - } - - if (System.IO.File.Exists("crashreport.txt")) - { - System.IO.File.Delete("crashreport.txt"); - DebugConsole.NewMessage("Deleted crashreport.txt", Color.Green); - } - - if (!System.IO.File.Exists("Content/Map/TutorialSub.sub")) - { - DebugConsole.ThrowError("TutorialSub.sub not found!"); - } - - break; default: - NewMessage("Command not found", Color.Red); + if (!ExecProjSpecific(commands)) NewMessage("Command not found", Color.Red); break; } } @@ -963,6 +503,7 @@ namespace Barotrauma Messages.RemoveRange(0, Messages.Count - MaxMessages); } +#if CLIENT //listbox not created yet, don't attempt to add if (listBox == null) return; @@ -986,6 +527,7 @@ namespace Barotrauma } selectedIndex = listBox.children.Count; +#endif } public static void Log(string message) @@ -1001,7 +543,9 @@ namespace Barotrauma } System.Diagnostics.Debug.WriteLine(error); NewMessage(error, Color.Red); +#if CLIENT isOpen = true; +#endif } } } diff --git a/BarotraumaShared/Source/GameSession/GameSession.cs b/BarotraumaShared/Source/GameSession/GameSession.cs index 79b825f85..d5bbc2bd8 100644 --- a/BarotraumaShared/Source/GameSession/GameSession.cs +++ b/BarotraumaShared/Source/GameSession/GameSession.cs @@ -5,7 +5,7 @@ using System.Xml.Linq; namespace Barotrauma { - class GameSession + partial class GameSession { public enum InfoFrameTab { Crew, Mission, ManagePlayers }; @@ -16,17 +16,13 @@ namespace Barotrauma //two locations used as the start and end in the MP mode private Location[] dummyLocations; - private InfoFrameTab selectedTab; - private GUIButton infoButton; - private GUIFrame infoFrame; - private string saveFile; private Submarine submarine; +#if CLIENT public CrewManager CrewManager; - - private ShiftSummary shiftSummary; +#endif private Mission currentMission; @@ -44,16 +40,7 @@ namespace Barotrauma { get { return level; } } - - public Map Map - { - get - { - SinglePlayerMode mode = (gameMode as SinglePlayerMode); - return (mode == null) ? null : mode.Map; - } - } - + public Location StartLocation { get @@ -94,26 +81,23 @@ namespace Barotrauma { get { return saveFile; } } - - public ShiftSummary ShiftSummary - { - get { return shiftSummary; } - } - + public GameSession(Submarine submarine, string saveFile, GameModePreset gameModePreset = null, string missionType="") { Submarine.MainSub = submarine; GameMain.GameSession = this; - - CrewManager = new CrewManager(); - + TaskManager = new TaskManager(this); this.saveFile = saveFile; +#if CLIENT + CrewManager = new CrewManager(); + infoButton = new GUIButton(new Rectangle(10, 10, 100, 20), "Info", "", null); infoButton.OnClicked = ToggleInfoFrame; +#endif if (gameModePreset != null) gameMode = gameModePreset.Instantiate(missionType); this.submarine = submarine; @@ -125,17 +109,19 @@ namespace Barotrauma Submarine.MainSub = submarine; GameMain.GameSession = this; - - CrewManager = new CrewManager(); - + selectedSub.Name = ToolBox.GetAttributeString(doc.Root, "submarine", selectedSub.Name); +#if CLIENT + CrewManager = new CrewManager(); + foreach (XElement subElement in doc.Root.Elements()) { if (subElement.Name.ToString().ToLowerInvariant() != "gamemode") continue; gameMode = new SinglePlayerMode(subElement); } +#endif } private void CreateDummyLocations() @@ -168,7 +154,9 @@ namespace Barotrauma public void StartShift(Level level, bool reloadSub = true, bool loadSecondSub = false) { +#if CLIENT GameMain.LightManager.LosEnabled = GameMain.NetworkMember == null || GameMain.NetworkMember.CharacterInfo != null; +#endif this.level = level; @@ -198,8 +186,10 @@ namespace Barotrauma level.Generate(); submarine.SetPosition(submarine.FindSpawnPos(level.StartPosition - new Vector2(0.0f, 2000.0f))); - + +#if CLIENT GameMain.GameScreen.BackgroundCreatureManager.SpawnSprites(80); +#endif } if (gameMode.Mission != null) @@ -207,8 +197,6 @@ namespace Barotrauma currentMission = gameMode.Mission; } - shiftSummary = new ShiftSummary(this); - if (gameMode!=null) gameMode.Start(); if (gameMode.Mission != null) Mission.Start(Level.Loaded); @@ -219,8 +207,12 @@ namespace Barotrauma Entity.Spawner = new EntitySpawner(); +#if CLIENT + shiftSummary = new ShiftSummary(this); + GameMain.GameScreen.ColorFade(Color.Black, Color.TransparentBlack, 5.0f); SoundPlayer.SwitchMusic(); +#endif } public void EndShift(string endMessage) @@ -238,6 +230,7 @@ namespace Barotrauma GameMain.LobbyScreen.Select(); } +#if CLIENT if (shiftSummary != null) { GUIFrame summaryFrame = shiftSummary.CreateSummaryFrame(endMessage); @@ -245,6 +238,7 @@ namespace Barotrauma var okButton = new GUIButton(new Rectangle(0, 0, 100, 30), "Ok", Alignment.BottomRight, "", summaryFrame.children[0]); okButton.OnClicked = (GUIButton button, object obj) => { GUIMessageBox.MessageBoxes.Remove(summaryFrame); return true; }; } +#endif TaskManager.EndShift(); @@ -253,182 +247,19 @@ namespace Barotrauma StatusEffect.StopAll(); } - public void KillCharacter(Character character) { +#if CLIENT CrewManager.KillCharacter(character); +#endif } public void ReviveCharacter(Character character) { +#if CLIENT CrewManager.ReviveCharacter(character); +#endif } - public bool LoadPrevious(GUIButton button, object obj) - { - Submarine.Unload(); - - SaveUtil.LoadGame(saveFile); - - GameMain.LobbyScreen.Select(); - - return true; - } - - private bool ToggleInfoFrame(GUIButton button, object obj) - { - if (infoFrame == null) - { - if (CrewManager != null && CrewManager.CrewCommander!= null && CrewManager.CrewCommander.IsOpen) - { - CrewManager.CrewCommander.ToggleGUIFrame(); - } - - CreateInfoFrame(); - SelectInfoFrameTab(null, selectedTab); - } - else - { - infoFrame = null; - } - - return true; - } - - public void CreateInfoFrame() - { - int width = 600, height = 400; - - - infoFrame = new GUIFrame( - Rectangle.Empty, Color.Black * 0.8f, null); - - var innerFrame = new GUIFrame( - new Rectangle(GameMain.GraphicsWidth / 2 - width / 2, GameMain.GraphicsHeight / 2 - height / 2, width, height), "", infoFrame); - - innerFrame.Padding = new Vector4(10.0f, 10.0f, 10.0f, 10.0f); - - var crewButton = new GUIButton(new Rectangle(0, -30, 100, 20), "Crew", "", innerFrame); - crewButton.UserData = InfoFrameTab.Crew; - crewButton.OnClicked = SelectInfoFrameTab; - - var missionButton = new GUIButton(new Rectangle(100, -30, 100, 20), "Mission", "", innerFrame); - missionButton.UserData = InfoFrameTab.Mission; - missionButton.OnClicked = SelectInfoFrameTab; - - if (GameMain.Server != null) - { - var manageButton = new GUIButton(new Rectangle(200, -30, 130, 20), "Manage players", "", innerFrame); - manageButton.UserData = InfoFrameTab.ManagePlayers; - manageButton.OnClicked = SelectInfoFrameTab; - } - - var closeButton = new GUIButton(new Rectangle(0, 0, 80, 20), "Close", Alignment.BottomCenter, "", innerFrame); - closeButton.OnClicked = ToggleInfoFrame; - - } - - private bool SelectInfoFrameTab(GUIButton button, object userData) - { - selectedTab = (InfoFrameTab)userData; - - CreateInfoFrame(); - - switch (selectedTab) - { - case InfoFrameTab.Crew: - CrewManager.CreateCrewFrame(CrewManager.characters, infoFrame.children[0] as GUIFrame); - break; - case InfoFrameTab.Mission: - CreateMissionInfo(infoFrame.children[0] as GUIFrame); - break; - case InfoFrameTab.ManagePlayers: - GameMain.Server.ManagePlayersFrame(infoFrame.children[0] as GUIFrame); - break; - } - - return true; - } - - private void CreateMissionInfo(GUIFrame infoFrame) - { - if (Mission == null) - { - new GUITextBlock(new Rectangle(0,0,0,50), "No mission", "", infoFrame, true); - return; - } - - new GUITextBlock(new Rectangle(0, 0, 0, 40), Mission.Name, "", infoFrame, GUI.LargeFont); - - new GUITextBlock(new Rectangle(0, 50, 0, 20), "Reward: "+Mission.Reward, "", infoFrame, true); - new GUITextBlock(new Rectangle(0, 70, 0, 50), Mission.Description, "", infoFrame, true); - - - } - - public void AddToGUIUpdateList() - { - infoButton.AddToGUIUpdateList(); - - if (gameMode != null) gameMode.AddToGUIUpdateList(); - - if (infoFrame != null) infoFrame.AddToGUIUpdateList(); - } - - public void Update(float deltaTime) - { - TaskManager.Update(deltaTime); - - if (GUI.DisableHUD) return; - - //guiRoot.Update(deltaTime); - infoButton.Update(deltaTime); - - if (gameMode != null) gameMode.Update(deltaTime); - if (Mission != null) Mission.Update(deltaTime); - if (infoFrame != null) - { - infoFrame.Update(deltaTime); - - if (CrewManager != null && CrewManager.CrewCommander != null && CrewManager.CrewCommander.IsOpen) - { - infoFrame = null; - } - } - } - - public void Draw(SpriteBatch spriteBatch) - { - if (GUI.DisableHUD) return; - - infoButton.Draw(spriteBatch); - - if (gameMode != null) gameMode.Draw(spriteBatch); - if (infoFrame != null) infoFrame.Draw(spriteBatch); - } - - public void Save(string filePath) - { - XDocument doc = new XDocument( - new XElement("Gamesession")); - - var now = DateTime.Now; - doc.Root.Add(new XAttribute("savetime", now.ToShortTimeString() + ", " + now.ToShortDateString())); - - doc.Root.Add(new XAttribute("submarine", submarine==null ? "" : submarine.Name)); - - doc.Root.Add(new XAttribute("mapseed", Map.Seed)); - - ((SinglePlayerMode)gameMode).Save(doc.Root); - - try - { - doc.Save(filePath); - } - catch - { - DebugConsole.ThrowError("Saving gamesession to \"" + filePath + "\" failed!"); - } - } } } diff --git a/BarotraumaShared/Source/GameSettings.cs b/BarotraumaShared/Source/GameSettings.cs index 92031d217..0985b7e7d 100644 --- a/BarotraumaShared/Source/GameSettings.cs +++ b/BarotraumaShared/Source/GameSettings.cs @@ -1,6 +1,4 @@ using Microsoft.Xna.Framework; -using Microsoft.Xna.Framework.Graphics; -using Microsoft.Xna.Framework.Input; using System; using System.Collections.Generic; using System.Linq; @@ -9,51 +7,10 @@ using System.Xml.Linq; namespace Barotrauma { - public enum WindowMode + + public partial class GameSettings { - Windowed, Fullscreen, BorderlessWindowed - } - - public class GameSettings - { - private GUIFrame settingsFrame; - private GUIButton applyButton; - - private float soundVolume, musicVolume; - - private WindowMode windowMode; - - private KeyOrMouse[] keyMapping; - - private bool unsavedSettings; - - public GUIFrame SettingsFrame - { - get - { - if (settingsFrame == null) CreateSettingsFrame(); - return settingsFrame; - } - } - - public KeyOrMouse KeyBind(InputType inputType) - { - return keyMapping[(int)inputType]; - } - - public int GraphicsWidth { get; set; } - public int GraphicsHeight { get; set; } - - public bool VSyncEnabled { get; set; } - - //public bool FullScreenEnabled { get; set; } - - public WindowMode WindowMode - { - get { return windowMode; } - set { windowMode = value; } - } - + public ContentPackage SelectedContentPackage { get; set; } public string MasterServerUrl { get; set; } @@ -62,46 +19,6 @@ namespace Barotrauma public static bool VerboseLogging { get; set; } - public bool EnableSplashScreen { get; set; } - - public bool UnsavedSettings - { - get - { - return unsavedSettings; - } - private set - { - unsavedSettings = value; - if (applyButton != null) - { - //applyButton.Selected = unsavedSettings; - applyButton.Enabled = unsavedSettings; - applyButton.Text = unsavedSettings ? "Apply*" : "Apply"; - } - } - } - - public float SoundVolume - { - get { return soundVolume; } - set - { - soundVolume = MathHelper.Clamp(value, 0.0f, 1.0f); - Sounds.SoundManager.MasterVolume = soundVolume; - } - } - - public float MusicVolume - { - get { return musicVolume; } - set - { - musicVolume = MathHelper.Clamp(value, 0.0f, 1.0f); - SoundPlayer.MusicVolume = musicVolume; - } - } - public GameSettings(string filePath) { ContentPackage.LoadAll(ContentPackage.Folder); @@ -117,9 +34,6 @@ namespace Barotrauma { DebugConsole.ThrowError("No config file found"); - GraphicsWidth = 1024; - GraphicsHeight = 678; - MasterServerUrl = ""; SelectedContentPackage = ContentPackage.list.Any() ? ContentPackage.list[0] : new ContentPackage(""); @@ -127,53 +41,15 @@ namespace Barotrauma return; } - XElement graphicsMode = doc.Root.Element("graphicsmode"); - GraphicsWidth = ToolBox.GetAttributeInt(graphicsMode, "width", 0); - GraphicsHeight = ToolBox.GetAttributeInt(graphicsMode, "height", 0); - VSyncEnabled = ToolBox.GetAttributeBool(graphicsMode, "vsync", true); - - if (GraphicsWidth==0 || GraphicsHeight==0) - { - GraphicsWidth = GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Width; - GraphicsHeight = GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Height; - } - - //FullScreenEnabled = ToolBox.GetAttributeBool(graphicsMode, "fullscreen", true); - - var windowModeStr = ToolBox.GetAttributeString(graphicsMode, "displaymode", "Fullscreen"); - if (!Enum.TryParse(windowModeStr, out windowMode)) - { - windowMode = WindowMode.Fullscreen; - } - MasterServerUrl = ToolBox.GetAttributeString(doc.Root, "masterserverurl", ""); AutoCheckUpdates = ToolBox.GetAttributeBool(doc.Root, "autocheckupdates", true); WasGameUpdated = ToolBox.GetAttributeBool(doc.Root, "wasgameupdated", false); - SoundVolume = ToolBox.GetAttributeFloat(doc.Root, "soundvolume", 1.0f); - MusicVolume = ToolBox.GetAttributeFloat(doc.Root, "musicvolume", 0.3f); - VerboseLogging = ToolBox.GetAttributeBool(doc.Root, "verboselogging", false); - EnableSplashScreen = ToolBox.GetAttributeBool(doc.Root, "enablesplashscreen", true); + InitProjSpecific(doc); - keyMapping = new KeyOrMouse[Enum.GetNames(typeof(InputType)).Length]; - keyMapping[(int)InputType.Up] = new KeyOrMouse(Keys.W); - keyMapping[(int)InputType.Down] = new KeyOrMouse(Keys.S); - keyMapping[(int)InputType.Left] = new KeyOrMouse(Keys.A); - keyMapping[(int)InputType.Right] = new KeyOrMouse(Keys.D); - keyMapping[(int)InputType.Run] = new KeyOrMouse(Keys.LeftShift); - - - keyMapping[(int)InputType.Chat] = new KeyOrMouse(Keys.Tab); - keyMapping[(int)InputType.CrewOrders] = new KeyOrMouse(Keys.C); - - keyMapping[(int)InputType.Select] = new KeyOrMouse(Keys.E); - - keyMapping[(int)InputType.Use] = new KeyOrMouse(0); - keyMapping[(int)InputType.Aim] = new KeyOrMouse(1); - foreach (XElement subElement in doc.Root.Elements()) { switch (subElement.Name.ToString().ToLowerInvariant()) @@ -186,332 +62,9 @@ namespace Barotrauma if (SelectedContentPackage == null) SelectedContentPackage = new ContentPackage(path); break; - case "keymapping": - foreach (XAttribute attribute in subElement.Attributes()) - { - InputType inputType; - if (Enum.TryParse(attribute.Name.ToString(), true, out inputType)) - { - int mouseButton; - if (int.TryParse(attribute.Value.ToString(), out mouseButton)) - { - keyMapping[(int)inputType] = new KeyOrMouse(mouseButton); - } - else - { - Keys key; - if (Enum.TryParse(attribute.Value.ToString(), true, out key)) - { - keyMapping[(int)inputType] = new KeyOrMouse(key); - } - } - } - } - break; } } - - foreach (InputType inputType in Enum.GetValues(typeof(InputType))) - { - if (keyMapping[(int)inputType]==null) - { - DebugConsole.ThrowError("Key binding for the input type \"" + inputType + " not set!"); - keyMapping[(int)inputType] = new KeyOrMouse(Keys.D1); - } - } - - - UnsavedSettings = false; } - public void Save(string filePath) - { - UnsavedSettings = false; - - XDocument doc = new XDocument(); - - if (doc.Root == null) - { - doc.Add(new XElement("config")); - } - - doc.Root.Add( - new XAttribute("masterserverurl", MasterServerUrl), - new XAttribute("autocheckupdates", AutoCheckUpdates), - new XAttribute("musicvolume", musicVolume), - new XAttribute("soundvolume", soundVolume), - new XAttribute("verboselogging", VerboseLogging), - new XAttribute("enablesplashscreen", EnableSplashScreen)); - - if (WasGameUpdated) - { - doc.Root.Add(new XAttribute("wasgameupdated", true)); - } - - XElement gMode = doc.Root.Element("graphicsmode"); - if (gMode == null) - { - gMode = new XElement("graphicsmode"); - doc.Root.Add(gMode); - } - - if (GraphicsWidth==0 || GraphicsHeight==0) - { - gMode.ReplaceAttributes(new XAttribute("displaymode", windowMode)); - } - else - { - gMode.ReplaceAttributes( - new XAttribute("width", GraphicsWidth), - new XAttribute("height", GraphicsHeight), - new XAttribute("vsync", VSyncEnabled), - new XAttribute("displaymode", windowMode)); - } - - - if (SelectedContentPackage != null) - { - doc.Root.Add(new XElement("contentpackage", - new XAttribute("path", SelectedContentPackage.Path))); - } - - var keyMappingElement = new XElement("keymapping"); - doc.Root.Add(keyMappingElement); - for (int i = 0; i(); - foreach (DisplayMode mode in GraphicsAdapter.DefaultAdapter.SupportedDisplayModes) - { - if (supportedModes.FirstOrDefault(m => m.Width == mode.Width && m.Height == mode.Height) != null) continue; - - resolutionDD.AddItem(mode.Width + "x" + mode.Height, mode); - supportedModes.Add(mode); - - if (GraphicsWidth == mode.Width && GraphicsHeight == mode.Height) resolutionDD.SelectItem(mode); - } - - if (resolutionDD.SelectedItemData == null) - { - resolutionDD.SelectItem(GraphicsAdapter.DefaultAdapter.SupportedDisplayModes.Last()); - } - - y += 50; - - //var fullScreenTick = new GUITickBox(new Rectangle(x, y, 20, 20), "Fullscreen", Alignment.TopLeft, settingsFrame); - //fullScreenTick.OnSelected = ToggleFullScreen; - //fullScreenTick.Selected = FullScreenEnabled; - - new GUITextBlock(new Rectangle(x, y, 20, 20), "Display mode", "", Alignment.TopLeft, Alignment.TopLeft, settingsFrame); - var displayModeDD = new GUIDropDown(new Rectangle(x, y + 20, 180, 20), "", "", settingsFrame); - displayModeDD.AddItem("Fullscreen", WindowMode.Fullscreen); - displayModeDD.AddItem("Windowed", WindowMode.Windowed); - displayModeDD.AddItem("Borderless windowed", WindowMode.BorderlessWindowed); - - displayModeDD.SelectItem(GameMain.Config.WindowMode); - - displayModeDD.OnSelected = (guiComponent, obj) => { GameMain.Config.WindowMode = (WindowMode)guiComponent.UserData; return true; }; - - y += 70; - - GUITickBox vsyncTickBox = new GUITickBox(new Rectangle(0, y, 20, 20), "Enable vertical sync",Alignment.CenterY | Alignment.Left,settingsFrame); - vsyncTickBox.OnSelected = (GUITickBox box) => - { - VSyncEnabled = !VSyncEnabled; - GameMain.GraphicsDeviceManager.SynchronizeWithVerticalRetrace = VSyncEnabled; - GameMain.GraphicsDeviceManager.ApplyChanges(); - UnsavedSettings = true; - - return true; - }; - vsyncTickBox.Selected = VSyncEnabled; - - y += 70; - - new GUITextBlock(new Rectangle(0, y, 100, 20), "Sound volume:", "", settingsFrame); - GUIScrollBar soundScrollBar = new GUIScrollBar(new Rectangle(0, y + 20, 150, 20), "", 0.1f, settingsFrame); - soundScrollBar.BarScroll = SoundVolume; - soundScrollBar.OnMoved = ChangeSoundVolume; - soundScrollBar.Step = 0.05f; - - new GUITextBlock(new Rectangle(0, y + 40, 100, 20), "Music volume:", "", settingsFrame); - GUIScrollBar musicScrollBar = new GUIScrollBar(new Rectangle(0, y + 60, 150, 20), "", 0.1f, settingsFrame); - musicScrollBar.BarScroll = MusicVolume; - musicScrollBar.OnMoved = ChangeMusicVolume; - musicScrollBar.Step = 0.05f; - - x = 200; - y = 10; - - new GUITextBlock(new Rectangle(x, y, 20, 20), "Content package", "", Alignment.TopLeft, Alignment.TopLeft, settingsFrame); - var contentPackageDD = new GUIDropDown(new Rectangle(x, y + 20, 200, 20), "", "", settingsFrame); - - foreach (ContentPackage contentPackage in ContentPackage.list) - { - contentPackageDD.AddItem(contentPackage.Name, contentPackage); - - if (SelectedContentPackage == contentPackage) contentPackageDD.SelectItem(contentPackage); - } - - y += 50; - new GUITextBlock(new Rectangle(x, y, 100, 20), "Controls:", "", settingsFrame); - y += 30; - var inputNames = Enum.GetNames(typeof(InputType)); - for (int i = 0; i< inputNames.Length; i++) - { - new GUITextBlock(new Rectangle(x, y, 100, 18), inputNames[i]+": ", "", Alignment.TopLeft, Alignment.CenterLeft, settingsFrame); - var keyBox = new GUITextBox(new Rectangle(x + 100, y, 120, 18), null,null, Alignment.TopLeft, Alignment.CenterLeft, "", settingsFrame); - - keyBox.Text = keyMapping[i].ToString(); - keyBox.UserData = i; - keyBox.OnSelected += KeyBoxSelected; - keyBox.SelectedColor = Color.Gold * 0.3f; - - y += 20; - } - - applyButton = new GUIButton(new Rectangle(0, 0, 100, 20), "Apply", Alignment.BottomRight, "", settingsFrame); - applyButton.OnClicked = ApplyClicked; - } - - private void KeyBoxSelected(GUITextBox textBox, Keys key) - { - textBox.Text = ""; - CoroutineManager.StartCoroutine(WaitForKeyPress(textBox)); - } - - private bool MarkUnappliedChanges(GUIButton button, object obj) - { - UnsavedSettings = true; - - return true; - } - - private bool SelectResolution(GUIComponent selected, object userData) - { - DisplayMode mode = selected.UserData as DisplayMode; - if (mode == null) return false; - - if (GraphicsWidth == mode.Width && GraphicsHeight == mode.Height) return false; - - GraphicsWidth = mode.Width; - GraphicsHeight = mode.Height; - - - //GameMain.Graphics.PreferredBackBufferWidth = GraphicsWidth; - //GameMain.Graphics.PreferredBackBufferHeight = GraphicsHeight; - //GameMain.Graphics.ApplyChanges(); - - //CoroutineManager.StartCoroutine(GameMain.Instance.Load()); - - UnsavedSettings = true; - - return true; - } - - - - private IEnumerable WaitForKeyPress(GUITextBox keyBox) - { - yield return CoroutineStatus.Running; - - while (keyBox.Selected && PlayerInput.GetKeyboardState.GetPressedKeys().Length==0 - && !PlayerInput.LeftButtonClicked() && !PlayerInput.RightButtonClicked()) - { - if (Screen.Selected != GameMain.MainMenuScreen && !GUI.SettingsMenuOpen) yield return CoroutineStatus.Success; - - yield return CoroutineStatus.Running; - } - - UnsavedSettings = true; - - int keyIndex = (int)keyBox.UserData; - - if (PlayerInput.LeftButtonClicked()) - { - keyMapping[keyIndex] = new KeyOrMouse(0); - keyBox.Text = "Mouse1"; - } - else if (PlayerInput.LeftButtonClicked()) - { - keyMapping[keyIndex] = new KeyOrMouse(1); - keyBox.Text = "Mouse2"; - } - else if (PlayerInput.GetKeyboardState.GetPressedKeys().Length > 0) - { - Keys key = PlayerInput.GetKeyboardState.GetPressedKeys()[0]; - keyMapping[keyIndex] = new KeyOrMouse(key); - keyBox.Text = key.ToString("G"); - } - else - { - yield return CoroutineStatus.Success; - } - - keyBox.Deselect(); - - yield return CoroutineStatus.Success; - } - - private bool ApplyClicked(GUIButton button, object userData) - { - Save("config.xml"); - - settingsFrame.Flash(Color.Green); - - if (GameMain.GraphicsWidth != GameMain.Config.GraphicsWidth || GameMain.GraphicsHeight != GameMain.Config.GraphicsHeight) - { - new GUIMessageBox("Restart required", "You need to restart the game for the resolution changes to take effect."); - } - - return true; - } } } diff --git a/BarotraumaShared/Source/Items/CharacterInventory.cs b/BarotraumaShared/Source/Items/CharacterInventory.cs index f04985292..1d1decdbc 100644 --- a/BarotraumaShared/Source/Items/CharacterInventory.cs +++ b/BarotraumaShared/Source/Items/CharacterInventory.cs @@ -16,7 +16,7 @@ namespace Barotrauma None = 0, Any = 1, RightHand = 2, LeftHand = 4, Head = 8, Torso = 16, Legs = 32, Face=64 }; - class CharacterInventory : Inventory + partial class CharacterInventory : Inventory { private static Texture2D icons; @@ -26,81 +26,26 @@ namespace Barotrauma InvSlotType.Head, InvSlotType.Torso, InvSlotType.Legs, InvSlotType.LeftHand, InvSlotType.RightHand, InvSlotType.Face, InvSlotType.Any, InvSlotType.Any, InvSlotType.Any, InvSlotType.Any, InvSlotType.Any, InvSlotType.Any, InvSlotType.Any, InvSlotType.Any, InvSlotType.Any, InvSlotType.Any}; - - public Vector2[] SlotPositions; - - private GUIButton[] useOnSelfButton; - + public CharacterInventory(int capacity, Character character) : base(character, capacity) { this.character = character; - useOnSelfButton = new GUIButton[2]; - - if (icons == null) icons = TextureLoader.FromFile("Content/UI/inventoryIcons.png"); - - SlotPositions = new Vector2[limbSlots.Length]; - - int rectWidth = 40, rectHeight = 40; - int spacing = 10; - for (int i = 0; i < SlotPositions.Length; i++) - { - switch (i) - { - //head, torso, legs - case 0: - case 1: - case 2: - SlotPositions[i] = new Vector2( - spacing, - GameMain.GraphicsHeight - (spacing + rectHeight) * (3 - i)); - break; - //lefthand, righthand - case 3: - case 4: - SlotPositions[i] = new Vector2( - spacing * 2 + rectWidth + (spacing + rectWidth) * (i - 2), - GameMain.GraphicsHeight - (spacing + rectHeight)*3); - - useOnSelfButton[i - 3] = new GUIButton( - new Rectangle((int) SlotPositions[i].X, (int) (SlotPositions[i].Y - spacing - rectHeight), - rectWidth, rectHeight), "Use", "") - { - UserData = i, - OnClicked = UseItemOnSelf - }; - - - break; - case 5: - SlotPositions[i] = new Vector2( - spacing * 2 + rectWidth + (spacing + rectWidth) * (i - 5), - GameMain.GraphicsHeight - (spacing + rectHeight) * 3); - - break; - default: - SlotPositions[i] = new Vector2( - spacing * 2 + rectWidth + (spacing + rectWidth) * ((i - 6)%5), - GameMain.GraphicsHeight - (spacing + rectHeight) * ((i>10) ? 2 : 1)); - break; - } - } + InitProjSpecific(); } - private bool UseItemOnSelf(GUIButton button, object obj) + private bool UseItemOnSelf(int slotIndex) { - if (!(obj is int)) return false; - - int slotIndex = (int)obj; - if (Items[slotIndex] == null) return false; - + +#if CLIENT if (GameMain.Client != null) { GameMain.Client.CreateEntityEvent(Items[slotIndex], new object[] { NetEntityEvent.Type.ApplyStatusEffect }); return true; } +#endif if (GameMain.Server != null) { diff --git a/BarotraumaShared/Source/Items/Components/Holdable/Propulsion.cs b/BarotraumaShared/Source/Items/Components/Holdable/Propulsion.cs index 25f730f0d..ade46f88b 100644 --- a/BarotraumaShared/Source/Items/Components/Holdable/Propulsion.cs +++ b/BarotraumaShared/Source/Items/Components/Holdable/Propulsion.cs @@ -1,19 +1,26 @@ using System.Xml.Linq; using Microsoft.Xna.Framework; +#if CLIENT using Microsoft.Xna.Framework.Graphics; using Barotrauma.Particles; +#endif namespace Barotrauma.Items.Components { class Propulsion : ItemComponent { + enum UsableIn + { + Air,Water,Both + }; + private float force; private string particles; private float useState; - - private ParticlePrefab.DrawTargetType usableIn; + + private UsableIn usableIn; [HasDefaultValue(0.0f, false)] public float Force @@ -21,13 +28,15 @@ namespace Barotrauma.Items.Components get { return force; } set { force = value; } } - + +#if CLIENT [HasDefaultValue("", false)] public string Particles { get { return particles; } set { particles = value; } } +#endif public Propulsion(Item item, XElement element) : base(item,element) @@ -35,14 +44,14 @@ namespace Barotrauma.Items.Components switch (ToolBox.GetAttributeString(element, "usablein", "both").ToLowerInvariant()) { case "air": - usableIn = ParticlePrefab.DrawTargetType.Air; + usableIn = UsableIn.Air; break; case "water": - usableIn = ParticlePrefab.DrawTargetType.Water; + usableIn = UsableIn.Water; break; case "both": default: - usableIn = ParticlePrefab.DrawTargetType.Both; + usableIn = UsableIn.Both; break; } } @@ -58,11 +67,11 @@ namespace Barotrauma.Items.Components if (character.AnimController.InWater) { - if (usableIn == ParticlePrefab.DrawTargetType.Air) return true; + if (usableIn == UsableIn.Air) return true; } else { - if (usableIn == ParticlePrefab.DrawTargetType.Water) return true; + if (usableIn == UsableIn.Water) return true; } Vector2 dir = Vector2.Normalize(character.CursorPosition - character.Position); @@ -82,13 +91,14 @@ namespace Barotrauma.Items.Components if (character.SelectedItems[0] == item) character.AnimController.GetLimb(LimbType.RightHand).body.ApplyForce(propulsion); if (character.SelectedItems[1] == item) character.AnimController.GetLimb(LimbType.LeftHand).body.ApplyForce(propulsion); - +#if CLIENT if (!string.IsNullOrWhiteSpace(particles)) { GameMain.ParticleManager.CreateParticle(particles, item.WorldPosition, item.body.Rotation + ((item.body.Dir > 0.0f) ? 0.0f : MathHelper.Pi), 0.0f, item.CurrentHull); } +#endif return true; } diff --git a/BarotraumaShared/Source/Items/Components/ItemComponent.cs b/BarotraumaShared/Source/Items/Components/ItemComponent.cs index 502832d43..993f73485 100644 --- a/BarotraumaShared/Source/Items/Components/ItemComponent.cs +++ b/BarotraumaShared/Source/Items/Components/ItemComponent.cs @@ -13,7 +13,9 @@ namespace Barotrauma.Items.Components { interface IDrawableComponent { +#if CLIENT void Draw(SpriteBatch spriteBatch, bool editing); +#endif } class ItemSound diff --git a/BarotraumaShared/Source/Items/Components/ItemLabel.cs b/BarotraumaShared/Source/Items/Components/ItemLabel.cs index 7452f2f84..f6a08169a 100644 --- a/BarotraumaShared/Source/Items/Components/ItemLabel.cs +++ b/BarotraumaShared/Source/Items/Components/ItemLabel.cs @@ -1,87 +1,8 @@ using Microsoft.Xna.Framework; -using Microsoft.Xna.Framework.Graphics; -using System.Xml.Linq; + namespace Barotrauma.Items.Components { - class ItemLabel : ItemComponent, IDrawableComponent + partial class ItemLabel : ItemComponent, IDrawableComponent { - private GUITextBlock textBlock; - - [HasDefaultValue("", true), Editable(100)] - public string Text - { - get { return textBlock.Text.Replace("\n", ""); } - set - { - if (value == TextBlock.Text || item.Rect.Width < 5) return; - - if (textBlock.Rect.Width != item.Rect.Width || textBlock.Rect.Height != item.Rect.Height) - { - textBlock = null; - } - - TextBlock.Text = value; - } - } - - private Color textColor; - [Editable, HasDefaultValue("0.0,0.0,0.0,1.0", true)] - public string TextColor - { - get { return ToolBox.Vector4ToString(textColor.ToVector4()); } - set - { - textColor = new Color(ToolBox.ParseToVector4(value)); - if (textBlock != null) textBlock.TextColor = textColor; - } - } - - [Editable, HasDefaultValue(1.0f, true)] - public float TextScale - { - get { return textBlock == null ? 1.0f : textBlock.TextScale; } - set - { - if (textBlock != null) textBlock.TextScale = MathHelper.Clamp(value, 0.1f, 10.0f); - } - } - - private GUITextBlock TextBlock - { - get - { - if (textBlock == null) - { - textBlock = new GUITextBlock(new Rectangle(item.Rect.X,-item.Rect.Y,item.Rect.Width, item.Rect.Height), "", - Color.Transparent, textColor, - Alignment.TopLeft, Alignment.Center, - null, null, true); - textBlock.Font = GUI.SmallFont; - textBlock.Padding = new Vector4(5.0f, 5.0f, 5.0f, 5.0f); - textBlock.TextDepth = item.Sprite.Depth - 0.0001f; - textBlock.TextScale = TextScale; - } - return textBlock; - } - } - - public override void Move(Vector2 amount) - { - textBlock.Rect = new Rectangle(item.Rect.X, -item.Rect.Y, item.Rect.Width, item.Rect.Height); - } - - public ItemLabel(Item item, XElement element) - : base(item, element) - { - } - - public void Draw(SpriteBatch spriteBatch, bool editing = false) - { - var drawPos = new Vector2( - item.DrawPosition.X - item.Rect.Width/2.0f, - -(item.DrawPosition.Y + item.Rect.Height/2.0f)); - - textBlock.Draw(spriteBatch, drawPos - textBlock.Rect.Location.ToVector2()); - } } } \ No newline at end of file diff --git a/BarotraumaShared/Source/Items/FixRequirement.cs b/BarotraumaShared/Source/Items/FixRequirement.cs index 15ae83dbb..b90539c9a 100644 --- a/BarotraumaShared/Source/Items/FixRequirement.cs +++ b/BarotraumaShared/Source/Items/FixRequirement.cs @@ -9,12 +9,10 @@ using System.Xml.Linq; namespace Barotrauma { - class FixRequirement + partial class FixRequirement { string name; - private static GUIFrame frame; - List requiredSkills; List requiredItems; @@ -46,7 +44,7 @@ namespace Barotrauma } } - public bool CanBeFixed(Character character, GUIComponent reqFrame = null) + public bool CanBeFixed(Character character) { if (character == null) return false; @@ -57,13 +55,6 @@ namespace Barotrauma bool itemFound = (item != null); if (!itemFound) success = false; - - if (reqFrame != null) - { - GUIComponent component = reqFrame.children.Find(c => c.UserData as string == itemName); - GUITextBlock text = component as GUITextBlock; - if (text != null) text.TextColor = itemFound ? Color.LightGreen : Color.Red; - } } foreach (Skill skill in requiredSkills) @@ -72,160 +63,9 @@ namespace Barotrauma bool sufficientSkill = characterSkill >= skill.Level; if (!sufficientSkill) success = false; - - if (reqFrame != null) - { - GUIComponent component = reqFrame.children.Find(c => c.UserData as Skill == skill); - GUITextBlock text = component as GUITextBlock; - if (text != null) text.TextColor = sufficientSkill ? Color.LightGreen : Color.Red; - } } return success; } - - private static void CreateGUIFrame(Item item) - { - int width = 400, height = 500; - int y = 0; - - frame = new GUIFrame(new Rectangle(0, 0, width, height), null, Alignment.Center, ""); - frame.Padding = new Vector4(20.0f, 20.0f, 20.0f, 20.0f); - frame.UserData = item; - - new GUITextBlock(new Rectangle(0,0,200,20), "Attempting to fix " + item.Name, "", frame); - - y = y + 40; - foreach (FixRequirement requirement in item.FixRequirements) - { - GUIFrame reqFrame = new GUIFrame( - new Rectangle(0, y, 0, 20 + Math.Max(requirement.requiredItems.Count, requirement.requiredSkills.Count) * 15), - Color.Transparent, null, frame); - reqFrame.UserData = requirement; - - - var fixButton = new GUIButton(new Rectangle(0, 0, 50, 20), "Fix", "", reqFrame); - fixButton.OnClicked = FixButtonPressed; - fixButton.UserData = requirement; - - var tickBox = new GUITickBox(new Rectangle(70, 0, 20,20), requirement.name, Alignment.Left, reqFrame); - tickBox.Enabled = false; - - int y2 = 20; - foreach (string itemName in requirement.requiredItems) - { - var itemBlock = new GUITextBlock(new Rectangle(30, y2, 200, 15), itemName, "", reqFrame); - itemBlock.Font = GUI.SmallFont; - itemBlock.UserData = itemName; - - y2 += 15; - } - - y2 = 20; - foreach (Skill skill in requirement.requiredSkills) - { - var skillBlock = new GUITextBlock(new Rectangle(0, y2, 200, 15), skill.Name + " - " + skill.Level, "", Alignment.Right, Alignment.TopLeft, reqFrame); - skillBlock.Font = GUI.SmallFont; - skillBlock.UserData = skill; - - - y2 += 15; - } - - y += reqFrame.Rect.Height; - } - } - - private static bool FixButtonPressed(GUIButton button, object obj) - { - FixRequirement requirement = obj as FixRequirement; - if (requirement == null) return true; - - Item item = frame.UserData as Item; - if (item == null) return true; - - if (!requirement.CanBeFixed(Character.Controlled, button.Parent)) return true; - - if (GameMain.Client != null) - { - GameMain.Client.CreateEntityEvent(item, new object[] { NetEntityEvent.Type.Repair, item.FixRequirements.IndexOf(requirement)}); - } - else if (GameMain.Server != null) - { - GameMain.Server.CreateEntityEvent(item, new object[] { NetEntityEvent.Type.Status }); - requirement.Fixed = true; - } - else - { - requirement.Fixed = true; - } - - return true; - } - - private static void UpdateGUIFrame(Item item, Character character) - { - if (frame == null) return; - - bool unfixedFound = false; - foreach (GUIComponent child in frame.children) - { - FixRequirement requirement = child.UserData as FixRequirement; - if (requirement == null) continue; - - if (requirement.Fixed) - { - child.Color = Color.LightGreen * 0.3f; - child.GetChild().Selected = true; - } - else - { - bool canBeFixed = requirement.CanBeFixed(character, child); - unfixedFound = true; - //child.GetChild().Selected = canBeFixed; - GUITickBox tickBox = child.GetChild(); - if (tickBox.Selected) - { - tickBox.Selected = canBeFixed; - requirement.Fixed = canBeFixed; - - } - child.Color = Color.Red * 0.2f; - //tickBox.State = GUIComponent.ComponentState.None; - } - } - if (!unfixedFound) - { - item.Condition = 100.0f; - frame = null; - } - } - - public static void DrawHud(SpriteBatch spriteBatch, Item item, Character character) - { - if (frame == null) return; - - frame.Draw(spriteBatch); - } - - public static void AddToGUIUpdateList() - { - if (frame == null) return; - - frame.AddToGUIUpdateList(); - } - - public static void UpdateHud(Item item, Character character) - { - if (frame == null || frame.UserData != item) - { - CreateGUIFrame(item); - } - UpdateGUIFrame(item, character); - - if (frame == null) return; - - frame.Update((float)Timing.Step); - } } } diff --git a/BarotraumaShared/Source/Items/Inventory.cs b/BarotraumaShared/Source/Items/Inventory.cs index caeeaf480..eb4a3fac6 100644 --- a/BarotraumaShared/Source/Items/Inventory.cs +++ b/BarotraumaShared/Source/Items/Inventory.cs @@ -1,8 +1,6 @@ using System.Linq; using Lidgren.Network; using Microsoft.Xna.Framework; -using Microsoft.Xna.Framework.Graphics; -using Microsoft.Xna.Framework.Input; using Barotrauma.Networking; using System; using System.Collections.Generic; @@ -10,65 +8,26 @@ using Barotrauma.Items.Components; namespace Barotrauma { - class InventorySlot + partial class InventorySlot { public Rectangle Rect; - - public GUIComponent.ComponentState State; - + public bool Disabled; - public bool IsHighlighted - { - get - { - return State == GUIComponent.ComponentState.Hover; - } - } - - public Color Color; - - public Color BorderHighlightColor; - private CoroutineHandle BorderHighlightCoroutine; - public InventorySlot(Rectangle rect) { Rect = rect; +#if CLIENT State = GUIComponent.ComponentState.None; Color = Color.White * 0.4f; +#endif } - public void ShowBorderHighlight(Color color, float fadeInDuration, float fadeOutDuration) - { - if (BorderHighlightCoroutine != null) - { - BorderHighlightCoroutine = null; - } - - BorderHighlightCoroutine = CoroutineManager.StartCoroutine(UpdateBorderHighlight(color, fadeInDuration, fadeOutDuration)); - } - - private IEnumerable UpdateBorderHighlight(Color color, float fadeInDuration, float fadeOutDuration) - { - float t = 0.0f; - while (t < fadeInDuration + fadeOutDuration) - { - BorderHighlightColor = (t < fadeInDuration) ? - Color.Lerp(Color.Transparent, color, t / fadeInDuration) : - Color.Lerp(color, Color.Transparent, (t - fadeInDuration) / fadeOutDuration); - - t += CoroutineManager.DeltaTime; - - yield return CoroutineStatus.Running; - } - - yield return CoroutineStatus.Success; - } } - class Inventory : IServerSerializable, IClientSerializable + partial class Inventory : IServerSerializable, IClientSerializable { public static InventorySlot draggingSlot; public static Item draggingItem; @@ -86,8 +45,6 @@ namespace Barotrauma protected int capacity; - private Vector2 centerPos; - protected int selectedSlot = -1; protected InventorySlot[] slots; @@ -101,14 +58,18 @@ namespace Barotrauma private float syncItemsDelay; private CoroutineHandle syncItemsCoroutine; + private Vector2 centerPos; + public Vector2 CenterPos { get { return centerPos; } set { centerPos = value; +#if CLIENT centerPos.X *= GameMain.GraphicsWidth; centerPos.Y *= GameMain.GraphicsHeight; +#endif } } @@ -195,7 +156,9 @@ namespace Barotrauma } else { +#if CLIENT if (slots != null && createNetworkEvent) slots[i].ShowBorderHighlight(Color.Red, 0.1f, 0.9f); +#endif return false; } } @@ -213,7 +176,9 @@ namespace Barotrauma Items[i] = item; item.ParentInventory = this; +#if CLIENT if (slots != null) slots[i].ShowBorderHighlight(Color.White, 0.1f, 0.4f); +#endif if (item.body != null) { @@ -232,10 +197,12 @@ namespace Barotrauma { GameMain.Server.CreateEntityEvent(Owner as IServerSerializable, new object[] { NetEntityEvent.Type.InventoryState }); } +#if CLIENT else if (GameMain.Client != null) { GameMain.Client.CreateEntityEvent(Owner as IClientSerializable, new object[] { NetEntityEvent.Type.InventoryState }); } +#endif } public Item FindItem(string itemName) @@ -311,79 +278,13 @@ namespace Barotrauma } - public virtual void Draw(SpriteBatch spriteBatch, bool subInventory = false) - { - if (slots == null || isSubInventory != subInventory) return; - - for (int i = 0; i < capacity; i++) - { - if (slots[i].Disabled) continue; - - //don't draw the item if it's being dragged out of the slot - bool drawItem = draggingItem == null || draggingItem != Items[i] || slots[i].IsHighlighted; - - DrawSlot(spriteBatch, slots[i], Items[i], drawItem); - } - - if (draggingItem != null && - (draggingSlot == null || (!draggingSlot.Rect.Contains(PlayerInput.MousePosition) && draggingItem.ParentInventory == this))) - { - Rectangle dragRect = new Rectangle( - (int)PlayerInput.MousePosition.X - 10, - (int)PlayerInput.MousePosition.Y - 10, - 40, 40); - - DrawSlot(spriteBatch, new InventorySlot(dragRect), draggingItem); - } - - for (int i = 0; i < capacity; i++) - { - if (slots[i].IsHighlighted && !slots[i].Disabled && Items[i] != null) - { - string toolTip = ""; - if (GameMain.DebugDraw) - { - toolTip = Items[i].ToString(); - } - else - { - toolTip = string.IsNullOrEmpty(Items[i].Description) ? - Items[i].Name : - Items[i].Name + '\n' + Items[i].Description; - } - - DrawToolTip(spriteBatch, toolTip, slots[i].Rect); - break; - } - } - } - - protected void DrawToolTip(SpriteBatch spriteBatch, string toolTip, Rectangle highlightedSlot) - { - int maxWidth = 300; - - toolTip = ToolBox.WrapText(toolTip, maxWidth, GUI.Font); - - Vector2 textSize = GUI.Font.MeasureString(toolTip); - Vector2 rectSize = textSize * 1.2f; - - Vector2 pos = new Vector2(highlightedSlot.Right, highlightedSlot.Y-rectSize.Y); - pos.X = (int)(pos.X + 3); - pos.Y = (int)pos.Y; - - GUI.DrawRectangle(spriteBatch, pos, rectSize, Color.Black * 0.8f, true); - GUI.Font.DrawString(spriteBatch, toolTip, - new Vector2((int)(pos.X + rectSize.X * 0.5f), (int)(pos.Y + rectSize.Y * 0.5f)), - Color.White, 0.0f, - new Vector2((int)(textSize.X * 0.5f), (int)(textSize.Y * 0.5f)), - 1.0f, SpriteEffects.None, 0.0f); - } - protected void UpdateSlot(InventorySlot slot, int slotIndex, Item item, bool isSubSlot) { bool mouseOn = slot.Rect.Contains(PlayerInput.MousePosition) && !Locked; +#if CLIENT slot.State = GUIComponent.ComponentState.None; +#endif if (!(this is CharacterInventory) && !mouseOn && selectedSlot==slotIndex) { @@ -393,7 +294,9 @@ namespace Barotrauma if (mouseOn && (draggingItem!=null || selectedSlot==slotIndex || selectedSlot==-1)) { +#if CLIENT slot.State = GUIComponent.ComponentState.Hover; +#endif if (!isSubSlot && selectedSlot == -1) { @@ -420,11 +323,15 @@ namespace Barotrauma //selectedSlot = slotIndex; if (TryPutItem(draggingItem, slotIndex, true)) { +#if CLIENT if (slots != null) slots[slotIndex].ShowBorderHighlight(Color.White, 0.1f, 0.4f); +#endif } else { +#if CLIENT if (slots != null) slots[slotIndex].ShowBorderHighlight(Color.Red, 0.1f, 0.9f); +#endif } draggingItem = null; draggingSlot = null; @@ -460,83 +367,11 @@ namespace Barotrauma container.Inventory.isSubInventory = true; +#if CLIENT slots[slotIndex].State = GUIComponent.ComponentState.Hover; - - container.Inventory.Update(deltaTime, true); - } - - public void DrawSubInventory(SpriteBatch spriteBatch, int slotIndex) - { - var item = Items[slotIndex]; - if (item == null) return; - - var container = item.GetComponent(); - if (container == null) return; - - if (container.Inventory.slots == null || !container.Inventory.isSubInventory) return; - - int itemCapacity = container.Capacity; - -#if DEBUG - System.Diagnostics.Debug.Assert(slotIndex >= 0 && slotIndex < Items.Length); -#else - if (slotIndex < 0 || slotIndex >= Items.Length) return; #endif - var slot = slots[slotIndex]; - Rectangle containerRect = new Rectangle(slot.Rect.X - 5, slot.Rect.Y - (40 + 10) * itemCapacity - 5, - slot.Rect.Width + 10, slot.Rect.Height + (40 + 10) * itemCapacity + 10); - - GUI.DrawRectangle(spriteBatch, new Rectangle(containerRect.X, containerRect.Y, containerRect.Width, containerRect.Height - slot.Rect.Height - 5), Color.Black * 0.8f, true); - GUI.DrawRectangle(spriteBatch, containerRect, Color.White); - - container.Inventory.Draw(spriteBatch, true); - - if (!containerRect.Contains(PlayerInput.MousePosition)) - { - if (draggingItem == null || draggingItem.Container != item) selectedSlot = -1; - } - } - - protected void DrawSlot(SpriteBatch spriteBatch, InventorySlot slot, Item item, bool drawItem=true) - { - Rectangle rect = slot.Rect; - - GUI.DrawRectangle(spriteBatch, rect, (slot.IsHighlighted ? Color.Red * 0.4f : slot.Color), true); - - if (item != null && drawItem) - { - if (item.Condition < 100.0f) - { - GUI.DrawRectangle(spriteBatch, new Rectangle(rect.X, rect.Bottom - 8, rect.Width, 8), Color.Black*0.8f, true); - GUI.DrawRectangle(spriteBatch, - new Rectangle(rect.X, rect.Bottom - 8, (int)(rect.Width * item.Condition / 100.0f), 8), - Color.Lerp(Color.Red, Color.Green, item.Condition / 100.0f)*0.8f, true); - } - - var containedItems = item.ContainedItems; - if (containedItems != null && containedItems.Length == 1 && containedItems[0].Condition < 100.0f) - { - GUI.DrawRectangle(spriteBatch, new Rectangle(rect.X, rect.Y, rect.Width, 8), Color.Black*0.8f, true); - GUI.DrawRectangle(spriteBatch, - new Rectangle(rect.X, rect.Y, (int)(rect.Width * containedItems[0].Condition / 100.0f), 8), - Color.Lerp(Color.Red, Color.Green, containedItems[0].Condition / 100.0f)*0.8f, true); - } - } - - GUI.DrawRectangle(spriteBatch, rect, (slot.IsHighlighted ? Color.Red * 0.4f : slot.Color), false); - - if (slot.BorderHighlightColor != Color.Transparent) - { - Rectangle highlightRect = slot.Rect; - highlightRect.Inflate(3,3); - - GUI.DrawRectangle(spriteBatch, highlightRect, slot.BorderHighlightColor, false, 0, 5); - } - - if (item == null || !drawItem) return; - - item.Sprite.Draw(spriteBatch, new Vector2(rect.X + rect.Width / 2, rect.Y + rect.Height / 2), item.Color); + container.Inventory.Update(deltaTime, true); } public void ClientWrite(NetBuffer msg, object[] extraData = null) diff --git a/BarotraumaShared/Source/Map/MapEntity.cs b/BarotraumaShared/Source/Map/MapEntity.cs index 16c9e889f..cd63c52f8 100644 --- a/BarotraumaShared/Source/Map/MapEntity.cs +++ b/BarotraumaShared/Source/Map/MapEntity.cs @@ -34,6 +34,15 @@ namespace Barotrauma //the position and dimensions of the entity protected Rectangle rect; + + //is the mouse inside the rect + protected bool isHighlighted; + + public bool IsHighlighted + { + get { return isHighlighted; } + set { isHighlighted = value; } + } private static bool resizing; private int resizeDirX, resizeDirY; diff --git a/BarotraumaShared/Source/Map/Structure.cs b/BarotraumaShared/Source/Map/Structure.cs index 1ec5885a4..30c338f09 100644 --- a/BarotraumaShared/Source/Map/Structure.cs +++ b/BarotraumaShared/Source/Map/Structure.cs @@ -43,7 +43,7 @@ namespace Barotrauma } } - class Structure : MapEntity, IDamageable, IServerSerializable + partial class Structure : MapEntity, IDamageable, IServerSerializable { public static int wallSectionSize = 96; public static List WallList = new List(); @@ -517,91 +517,6 @@ namespace Barotrauma return true; } - public override void Draw(SpriteBatch spriteBatch, bool editing, bool back = true) - { - if (prefab.sprite == null) return; - - Draw(spriteBatch, editing, back, null); - } - - public override void DrawDamage(SpriteBatch spriteBatch, Effect damageEffect) - { - Draw(spriteBatch, false, false, damageEffect); - } - - - private void Draw(SpriteBatch spriteBatch, bool editing, bool back = true, Effect damageEffect = null) - { - if (prefab.sprite == null) return; - - Color color = (isHighlighted) ? Color.Orange : Color.White; - if (IsSelected && editing) - { - color = Color.Red; - - GUI.DrawRectangle(spriteBatch, new Rectangle(rect.X, -rect.Y, rect.Width, rect.Height), color); - } - - Vector2 drawOffset = Submarine == null ? Vector2.Zero : Submarine.DrawPosition; - - float depth = prefab.sprite.Depth; - depth -= (ID % 255) * 0.000001f; - - if (back && damageEffect == null) - { - if (prefab.BackgroundSprite != null) - { - prefab.BackgroundSprite.DrawTiled( - spriteBatch, - new Vector2(rect.X + drawOffset.X, -(rect.Y + drawOffset.Y)), - new Vector2(rect.Width, rect.Height), - color, Point.Zero); - } - } - - SpriteEffects oldEffects = prefab.sprite.effects; - prefab.sprite.effects ^= SpriteEffects; - - if (back == prefab.sprite.Depth > 0.5f || editing) - { - for (int i = 0; i < sections.Length; i++) - { - if (damageEffect != null) - { - float newCutoff = Math.Min((sections[i].damage / prefab.MaxHealth), 0.65f); - - if (Math.Abs(newCutoff - Submarine.DamageEffectCutoff) > 0.01f) - { - damageEffect.Parameters["aCutoff"].SetValue(newCutoff); - damageEffect.Parameters["cCutoff"].SetValue(newCutoff * 1.2f); - - damageEffect.CurrentTechnique.Passes[0].Apply(); - - Submarine.DamageEffectCutoff = newCutoff; - } - } - - Point textureOffset = new Point( - Math.Abs(rect.Location.X - sections[i].rect.Location.X), - Math.Abs(rect.Location.Y - sections[i].rect.Location.Y)); - - if (flippedX && isHorizontal) - { - textureOffset.X = rect.Width - textureOffset.X - sections[i].rect.Width; - } - - prefab.sprite.DrawTiled( - spriteBatch, - new Vector2(sections[i].rect.X + drawOffset.X, -(sections[i].rect.Y + drawOffset.Y)), - new Vector2(sections[i].rect.Width, sections[i].rect.Height), - color, - textureOffset, depth); - } - } - - prefab.sprite.effects = oldEffects; - } - private bool OnWallCollision(Fixture f1, Fixture f2, Contact contact) { if (prefab.IsPlatform) @@ -632,10 +547,12 @@ namespace Barotrauma if (impact < 10.0f) return true; +#if CLIENT SoundPlayer.PlayDamageSound(DamageSoundType.StructureBlunt, impact, new Vector2( sections[section].rect.X + sections[section].rect.Width / 2, sections[section].rect.Y - sections[section].rect.Height / 2)); +#endif AddDamage(section, impact); } @@ -685,6 +602,7 @@ namespace Barotrauma var section = sections[sectionIndex]; +#if CLIENT float particleAmount = Math.Min(Health - section.damage, damage) * Rand.Range(0.01f, 1.0f); particleAmount = Math.Min(particleAmount + Rand.Range(-5,1), 100); @@ -695,10 +613,11 @@ namespace Barotrauma Rand.Range(section.rect.Y - section.rect.Height, section.rect.Y)); if (Submarine != null) particlePos += Submarine.DrawPosition; - + var particle = GameMain.ParticleManager.CreateParticle("shrapnel", particlePos, Rand.Vector(Rand.Range(1.0f, 50.0f))); if (particle == null) break; } +#endif if (GameMain.Client == null) SetDamage(sectionIndex, section.damage + damage); } @@ -753,18 +672,20 @@ namespace Barotrauma int i = FindSectionIndex(transformedPos); if (i == -1) return new AttackResult(0.0f, 0.0f); - GameMain.ParticleManager.CreateParticle("dustcloud", SectionPosition(i), 0.0f, 0.0f); - float damageAmount = attack.GetStructureDamage(deltaTime); + AddDamage(i, damageAmount); + +#if CLIENT + GameMain.ParticleManager.CreateParticle("dustcloud", SectionPosition(i), 0.0f, 0.0f); + if (playSound && !SectionBodyDisabled(i)) { DamageSoundType damageSoundType = (attack.DamageType == DamageType.Blunt) ? DamageSoundType.StructureBlunt : DamageSoundType.StructureSlash; SoundPlayer.PlayDamageSound(damageSoundType, damageAmount, worldPosition); } - - AddDamage(i, damageAmount); - +#endif + return new AttackResult(damageAmount, 0.0f); } @@ -928,39 +849,6 @@ namespace Barotrauma CreateSections(); } - public override XElement Save(XElement parentElement) - { - XElement element = new XElement("Structure"); - - element.Add(new XAttribute("name", prefab.Name), - new XAttribute("ID", ID), - new XAttribute("rect", - (int)(rect.X - Submarine.HiddenSubPosition.X) + "," + - (int)(rect.Y - Submarine.HiddenSubPosition.Y) + "," + - rect.Width + "," + rect.Height)); - - for (int i = 0; i < sections.Length; i++) - { - if (sections[i].damage == 0.0f) continue; - - var sectionElement = - new XElement("section", - new XAttribute("i", i), - new XAttribute("damage", sections[i].damage)); - - if (sections[i].gap!=null) - { - sectionElement.Add(new XAttribute("gap", sections[i].gap.ID)); - } - - element.Add(sectionElement); - } - - parentElement.Add(element); - - return element; - } - public static void Load(XElement element, Submarine submarine) { string rectString = ToolBox.GetAttributeString(element, "rect", "0,0,0,0"); diff --git a/BarotraumaShared/Source/Map/StructurePrefab.cs b/BarotraumaShared/Source/Map/StructurePrefab.cs index ed551a158..da1c24422 100644 --- a/BarotraumaShared/Source/Map/StructurePrefab.cs +++ b/BarotraumaShared/Source/Map/StructurePrefab.cs @@ -6,7 +6,7 @@ using System.Collections.Generic; namespace Barotrauma { - class StructurePrefab : MapEntityPrefab + partial class StructurePrefab : MapEntityPrefab { //public static List list = new List(); @@ -188,38 +188,5 @@ namespace Barotrauma if (PlayerInput.RightButtonHeld()) selected = null; } - - public override void DrawPlacing(SpriteBatch spriteBatch, Camera cam) - { - Vector2 position = Submarine.MouseToWorldGrid(cam, Submarine.MainSub); - //Vector2 placeSize = size; - - Rectangle newRect = new Rectangle((int)position.X, (int)position.Y, (int)size.X, (int)size.Y); - - - if (placePosition == Vector2.Zero) - { - if (PlayerInput.LeftButtonHeld()) - placePosition = Submarine.MouseToWorldGrid(cam, Submarine.MainSub); - - newRect.X = (int)position.X; - newRect.Y = (int)position.Y; - - //sprite.Draw(spriteBatch, new Vector2(position.X, -position.Y), placeSize, Color.White); - } - else - { - Vector2 placeSize = size; - if (resizeHorizontal) placeSize.X = position.X - placePosition.X; - if (resizeVertical) placeSize.Y = placePosition.Y - position.Y; - - newRect = Submarine.AbsRect(placePosition, placeSize); - } - - sprite.DrawTiled(spriteBatch, new Vector2(newRect.X, -newRect.Y), new Vector2(newRect.Width, newRect.Height), Color.White); - - GUI.DrawRectangle(spriteBatch, new Rectangle(newRect.X - GameMain.GraphicsWidth, -newRect.Y, newRect.Width + GameMain.GraphicsWidth * 2, newRect.Height), Color.White); - GUI.DrawRectangle(spriteBatch, new Rectangle(newRect.X, -newRect.Y - GameMain.GraphicsHeight, newRect.Width, newRect.Height + GameMain.GraphicsHeight * 2), Color.White); - } } } diff --git a/BarotraumaShared/Source/Map/WayPoint.cs b/BarotraumaShared/Source/Map/WayPoint.cs index 8e7417812..5332d845f 100644 --- a/BarotraumaShared/Source/Map/WayPoint.cs +++ b/BarotraumaShared/Source/Map/WayPoint.cs @@ -4,8 +4,8 @@ using System.Linq; using System.Xml.Linq; using FarseerPhysics; using Microsoft.Xna.Framework; -using Microsoft.Xna.Framework.Graphics; -using Microsoft.Xna.Framework.Input; +//using Microsoft.Xna.Framework.Graphics; +//using Microsoft.Xna.Framework.Input; using System.Collections.ObjectModel; using Barotrauma.Items.Components; using FarseerPhysics.Dynamics; @@ -13,16 +13,12 @@ using FarseerPhysics.Dynamics; namespace Barotrauma { public enum SpawnType { Path, Human, Enemy, Cargo }; - class WayPoint : MapEntity + partial class WayPoint : MapEntity { public static List WayPointList = new List(); public static bool ShowWayPoints = true, ShowSpawnPoints = true; - private static Texture2D iconTexture; - private const int IconSize = 32; - private static int[] iconIndices = { 3, 0, 1, 2 }; - protected SpawnType spawnType; //characters spawning at the waypoint will be given an ID card with these tags @@ -102,10 +98,12 @@ namespace Barotrauma linkedTo = new ObservableCollection(); idCardTags = new string[0]; +#if CLIENT if (iconTexture==null) { iconTexture = Sprite.LoadTexture("Content/Map/waypointIcons.png"); } +#endif InsertToList(); WayPointList.Add(this); @@ -125,203 +123,13 @@ namespace Barotrauma public override bool IsMouseOn(Vector2 position) { +#if CLIENT if (IsHidden()) return false; +#endif return base.IsMouseOn(position); } - public override void Draw(SpriteBatch spriteBatch, bool editing, bool back=true) - { - if (!editing && !GameMain.DebugDraw) return; - - if (IsHidden()) return; - - //Rectangle drawRect = - // Submarine == null ? rect : new Rectangle((int)(Submarine.DrawPosition.X + rect.X), (int)(Submarine.DrawPosition.Y + rect.Y), rect.Width, rect.Height); - - Vector2 drawPos = Position; - if (Submarine!=null) drawPos += Submarine.DrawPosition; - drawPos.Y = -drawPos.Y; - - Color clr = currentHull == null ? Color.Blue : Color.White; - if (IsSelected) clr = Color.Red; - if (isHighlighted) clr = Color.DarkRed; - - int iconX = iconIndices[(int)spawnType]*IconSize % iconTexture.Width; - int iconY = (int)(Math.Floor(iconIndices[(int)spawnType]*IconSize / (float)iconTexture.Width))*IconSize; - - int iconSize = ConnectedGap == null && Ladders == null ? IconSize : (int)(IconSize * 1.5f); - - spriteBatch.Draw(iconTexture, - new Rectangle((int)(drawPos.X - iconSize/2), (int)(drawPos.Y - iconSize/2), iconSize, iconSize), - new Rectangle(iconX, iconY, IconSize,IconSize), clr); - - //GUI.DrawRectangle(spriteBatch, new Rectangle(drawRect.X, -drawRect.Y, rect.Width, rect.Height), clr, true); - - //GUI.SmallFont.DrawString(spriteBatch, Position.ToString(), new Vector2(Position.X, -Position.Y), Color.White); - - foreach (MapEntity e in linkedTo) - { - GUI.DrawLine(spriteBatch, - drawPos, - new Vector2(e.DrawPosition.X, -e.DrawPosition.Y), - Color.Green); - } - } - - private bool IsHidden() - { - if (spawnType == SpawnType.Path) - { - return (!GameMain.DebugDraw && !ShowWayPoints); - } - else - { - return (!GameMain.DebugDraw && !ShowSpawnPoints); - } - } - - public override void UpdateEditing(Camera cam) - { - if (editingHUD == null || editingHUD.UserData != this) - { - editingHUD = CreateEditingHUD(); - } - - editingHUD.Update((float)Timing.Step); - - if (PlayerInput.LeftButtonClicked()) - { - Vector2 position = cam.ScreenToWorld(PlayerInput.MousePosition); - - foreach (MapEntity e in mapEntityList) - { - if (e.GetType() != typeof(WayPoint)) continue; - if (e == this) continue; - - if (!Submarine.RectContains(e.Rect, position)) continue; - - linkedTo.Add(e); - e.linkedTo.Add(this); - } - } - } - - public override void DrawEditing(SpriteBatch spriteBatch, Camera cam) - { - if (editingHUD != null) editingHUD.Draw(spriteBatch); - } - - private bool ChangeSpawnType(GUIButton button, object obj) - { - GUITextBlock spawnTypeText = button.Parent as GUITextBlock; - - spawnType += (int)button.UserData; - - if (spawnType > SpawnType.Cargo) spawnType = SpawnType.Human; - if (spawnType < SpawnType.Human) spawnType = SpawnType.Cargo; - - spawnTypeText.Text = spawnType.ToString(); - - return true; - } - - private bool EnterIDCardTags(GUITextBox textBox, string text) - { - IdCardTags = text.Split(','); - textBox.Text = text; - textBox.Color = Color.Green; - - textBox.Deselect(); - - return true; - } - - private bool EnterAssignedJob(GUITextBox textBox, string text) - { - string trimmedName = text.ToLowerInvariant().Trim(); - assignedJob = JobPrefab.List.Find(jp => jp.Name.ToLowerInvariant() == trimmedName); - - if (assignedJob !=null && trimmedName!="none") - { - textBox.Color = Color.Green; - textBox.Text = (assignedJob == null) ? "None" : assignedJob.Name; - } - - textBox.Deselect(); - - return true; - } - - private bool TextBoxChanged(GUITextBox textBox, string text) - { - textBox.Color = Color.Red; - - return true; - } - - private GUIComponent CreateEditingHUD(bool inGame = false) - { - int width = 500; - int height = spawnType == SpawnType.Path ? 100 : 140; - int x = GameMain.GraphicsWidth / 2 - width / 2, y = 10; - - editingHUD = new GUIFrame(new Rectangle(x, y, width, height), Color.Black * 0.5f); - editingHUD.Padding = new Vector4(10, 10, 0, 0); - editingHUD.UserData = this; - - if (spawnType == SpawnType.Path) - { - new GUITextBlock(new Rectangle(0, 0, 100, 20), "Editing waypoint", "", editingHUD); - new GUITextBlock(new Rectangle(0, 20, 100, 20), "Hold space to link to another waypoint", "", editingHUD); - } - else - { - new GUITextBlock(new Rectangle(0, 0, 100, 20), "Editing spawnpoint", "", editingHUD); - new GUITextBlock(new Rectangle(0, 25, 100, 20), "Spawn type: ", "", editingHUD); - - var spawnTypeText = new GUITextBlock(new Rectangle(0, 25, 200, 20), spawnType.ToString(), "", Alignment.Right, Alignment.TopLeft, editingHUD); - - var button = new GUIButton(new Rectangle(-30,0,20,20), "-", Alignment.Right, "", spawnTypeText); - button.UserData = -1; - button.OnClicked = ChangeSpawnType; - - button = new GUIButton(new Rectangle(0, 0, 20, 20), "+", Alignment.Right, "", spawnTypeText); - button.UserData = 1; - button.OnClicked = ChangeSpawnType; - - y = 40 + 20; - - new GUITextBlock(new Rectangle(0, y, 100, 20), "ID Card tags:", Color.Transparent, Color.White, Alignment.TopLeft, null, editingHUD); - GUITextBox propertyBox = new GUITextBox(new Rectangle(100, y, 200, 20), "", editingHUD); - propertyBox.Text = string.Join(", ", idCardTags); - propertyBox.OnEnterPressed = EnterIDCardTags; - propertyBox.OnTextChanged = TextBoxChanged; - propertyBox.ToolTip = "Characters spawning at this spawnpoint will have the specified tags added to their ID card. You can, for example, use these tags to limit access to some parts of the sub."; - - y = y + 30; - - new GUITextBlock(new Rectangle(0, y, 100, 20), "Assigned job:", Color.Transparent, Color.White, Alignment.TopLeft, null, editingHUD); - propertyBox = new GUITextBox(new Rectangle(100, y, 200, 20), "", editingHUD); - propertyBox.Text = (assignedJob == null) ? "None" : assignedJob.Name; - propertyBox.OnEnterPressed = EnterAssignedJob; - propertyBox.OnTextChanged = TextBoxChanged; - propertyBox.ToolTip = "Only characters with the specified job will spawn at this spawnpoint."; - - } - - - - - - //GUI.Font.DrawString(spriteBatch, "Spawnpoint: " + spawnType.ToString() + " +/-", new Vector2(x, y + 40), Color.Black); - - - y = y + 30; - - return editingHUD; - } - public static void GenerateSubWaypoints(Submarine submarine) { if (!Hull.hullList.Any()) @@ -747,42 +555,6 @@ namespace Barotrauma } } - public override XElement Save(XElement parentElement) - { - if (MoveWithLevel) return null; - XElement element = new XElement("WayPoint"); - - element.Add(new XAttribute("ID", ID), - new XAttribute("x", (int)(rect.X - Submarine.HiddenSubPosition.X)), - new XAttribute("y", (int)(rect.Y - Submarine.HiddenSubPosition.Y)), - new XAttribute("spawn", spawnType)); - - if (idCardTags.Length > 0) - { - element.Add(new XAttribute("idcardtags", string.Join(",", idCardTags))); - } - - if (assignedJob != null) element.Add(new XAttribute("job", assignedJob.Name)); - - - if (ConnectedGap != null) element.Add(new XAttribute("gap", ConnectedGap.ID)); - if (Ladders != null) element.Add(new XAttribute("ladders", Ladders.Item.ID)); - - parentElement.Add(element); - - if (linkedTo != null) - { - int i = 0; - foreach (MapEntity e in linkedTo) - { - element.Add(new XAttribute("linkedto" + i, e.ID)); - i += 1; - } - } - - return element; - } - public static void Load(XElement element, Submarine submarine) { Rectangle rect = new Rectangle( diff --git a/BarotraumaShared/Source/Networking/GameServer.cs b/BarotraumaShared/Source/Networking/GameServer.cs index 766d5a11d..e10b18a65 100644 --- a/BarotraumaShared/Source/Networking/GameServer.cs +++ b/BarotraumaShared/Source/Networking/GameServer.cs @@ -39,13 +39,10 @@ namespace Barotrauma.Networking private IRestResponse masterServerResponse; private ServerLog log; - private GUIButton showLogButton; private bool initiatedStartGame; private CoroutineHandle startGameCoroutine; - private GUIScrollBar clientListScrollBar; - public TraitorManager TraitorManager; private ServerEntityEventManager entityEventManager; @@ -122,40 +119,7 @@ namespace Barotrauma.Networking config.EnableMessageType(NetIncomingMessageType.ConnectionApproval); - //---------------------------------------- - - var endRoundButton = new GUIButton(new Rectangle(GameMain.GraphicsWidth - 170, 20, 150, 20), "End round", Alignment.TopLeft, "", inGameHUD); - endRoundButton.OnClicked = (btn, userdata) => { EndGame(); return true; }; - - log = new ServerLog(name); - showLogButton = new GUIButton(new Rectangle(GameMain.GraphicsWidth - 170 - 170, 20, 150, 20), "Server Log", Alignment.TopLeft, "", inGameHUD); - showLogButton.OnClicked = (GUIButton button, object userData) => - { - if (log.LogFrame == null) - { - log.CreateLogFrame(); - } - else - { - log.LogFrame = null; - GUIComponent.KeyboardDispatcher.Subscriber = null; - } - return true; - }; - - GUIButton settingsButton = new GUIButton(new Rectangle(GameMain.GraphicsWidth - 170 - 170 - 170, 20, 150, 20), "Settings", Alignment.TopLeft, "", inGameHUD); - settingsButton.OnClicked = ToggleSettingsFrame; - settingsButton.UserData = "settingsButton"; - - entityEventManager = new ServerEntityEventManager(this); - - whitelist = new WhiteList(); - banList = new BanList(); - - LoadSettings(); - LoadClientPermissions(); - - //---------------------------------------- + InitProjSpecific(); CoroutineManager.StartCoroutine(StartServer(isPublic)); } @@ -181,6 +145,7 @@ namespace Barotrauma.Networking System.Net.Sockets.SocketException socketException = e as System.Net.Sockets.SocketException; +#if CLIENT if (socketException != null && socketException.SocketErrorCode == System.Net.Sockets.SocketError.AddressAlreadyInUse) { new GUIMessageBox("Starting the server failed", e.Message + ". Are you trying to run multiple servers on the same port?"); @@ -189,6 +154,7 @@ namespace Barotrauma.Networking { new GUIMessageBox("Starting the server failed", e.Message); } +#endif error = true; } @@ -197,26 +163,27 @@ namespace Barotrauma.Networking { if (server != null) server.Shutdown("Error while starting the server"); +#if CLIENT GameMain.NetworkMember = null; +#elif SERVER + Environment.Exit(-1); +#endif yield return CoroutineStatus.Success; } if (config.EnableUPnP) { - server.UPnP.ForwardPort(config.Port, "barotrauma"); - - GUIMessageBox upnpBox = new GUIMessageBox("Please wait...", "Attempting UPnP port forwarding", new string[] {"Cancel"} ); - upnpBox.Buttons[0].OnClicked = upnpBox.Close; + InitUPnP(); //DateTime upnpTimeout = DateTime.Now + new TimeSpan(0,0,5); - while (server.UPnP.Status == UPnPStatus.Discovering - && GUIMessageBox.VisibleBox == upnpBox)// && upnpTimeout>DateTime.Now) + while (DiscoveringUPnP())// && upnpTimeout>DateTime.Now) { yield return null; } - upnpBox.Close(null,null); - + FinishUPnP(); + +#if CLIENT if (server.UPnP.Status == UPnPStatus.NotAvailable) { new GUIMessageBox("Error", "UPnP not available"); @@ -225,6 +192,7 @@ namespace Barotrauma.Networking { new GUIMessageBox("Error", "UPnP discovery timed out"); } +#endif } if (isPublic) @@ -430,7 +398,7 @@ namespace Barotrauma.Networking if (startGameCoroutine != null && !CoroutineManager.IsCoroutineRunning(startGameCoroutine)) { if (autoRestart) AutoRestartTimer = Math.Max(AutoRestartInterval, 5.0f); - GameMain.NetLobbyScreen.StartButton.Enabled = true; + GameMain.NetLobbyScreen.StartButtonEnabled = true; GameMain.NetLobbyScreen.LastUpdateID++; @@ -441,9 +409,9 @@ namespace Barotrauma.Networking else if (autoRestart && Screen.Selected == GameMain.NetLobbyScreen && connectedClients.Count>0) { AutoRestartTimer -= deltaTime; - if (AutoRestartTimer < 0.0f && GameMain.NetLobbyScreen.StartButton.Enabled) + if (AutoRestartTimer < 0.0f && GameMain.NetLobbyScreen.StartButtonEnabled) { - StartGameClicked(null,null); + StartGame(); } } @@ -930,7 +898,7 @@ namespace Barotrauma.Networking outmsg.Write(GameMain.NetLobbyScreen.LastUpdateID); outmsg.Write(GameMain.NetLobbyScreen.GetServerName()); - outmsg.Write(GameMain.NetLobbyScreen.ServerMessage.Text); + outmsg.Write(GameMain.NetLobbyScreen.ServerMessageText); outmsg.Write(c.lastRecvGeneralUpdate < 1); if (c.lastRecvGeneralUpdate < 1) @@ -938,10 +906,10 @@ namespace Barotrauma.Networking isInitialUpdate = true; ClientWriteInitial(c, outmsg); } - outmsg.Write((GameMain.NetLobbyScreen.SubList.SelectedData as Submarine).Name); - outmsg.Write((GameMain.NetLobbyScreen.SubList.SelectedData as Submarine).MD5Hash.ToString()); - outmsg.Write((GameMain.NetLobbyScreen.ShuttleList.SelectedData as Submarine).Name); - outmsg.Write((GameMain.NetLobbyScreen.ShuttleList.SelectedData as Submarine).MD5Hash.ToString()); + outmsg.Write(GameMain.NetLobbyScreen.SelectedSub.Name); + outmsg.Write(GameMain.NetLobbyScreen.SelectedSub.MD5Hash.ToString()); + outmsg.Write(GameMain.NetLobbyScreen.SelectedShuttle.Name); + outmsg.Write(GameMain.NetLobbyScreen.SelectedShuttle.MD5Hash.ToString()); outmsg.Write(Voting.AllowSubVoting); outmsg.Write(Voting.AllowModeVoting); @@ -950,7 +918,7 @@ namespace Barotrauma.Networking outmsg.WriteRangedInteger(0, Mission.MissionTypes.Count - 1, (GameMain.NetLobbyScreen.MissionTypeIndex)); - outmsg.Write((byte)GameMain.NetLobbyScreen.ModeList.SelectedIndex); + outmsg.Write((byte)GameMain.NetLobbyScreen.SelectedModeIndex); outmsg.Write(GameMain.NetLobbyScreen.LevelSeed); outmsg.Write(AutoRestart); @@ -1015,8 +983,8 @@ namespace Barotrauma.Networking c.chatMsgQueue[i].ServerWrite(outmsg, c); } } - - public bool StartGameClicked(GUIButton button, object obj) + + public bool StartGame() { Submarine selectedSub = null; Submarine selectedShuttle = GameMain.NetLobbyScreen.SelectedShuttle; @@ -1033,13 +1001,17 @@ namespace Barotrauma.Networking if (selectedSub == null) { +#if CLIENT GameMain.NetLobbyScreen.SubList.Flash(); +#endif return false; } if (selectedShuttle == null) { +#if CLIENT GameMain.NetLobbyScreen.ShuttleList.Flash(); +#endif return false; } @@ -1048,7 +1020,9 @@ namespace Barotrauma.Networking if (selectedMode == null) { +#if CLIENT GameMain.NetLobbyScreen.ModeList.Flash(); +#endif return false; } @@ -1059,7 +1033,7 @@ namespace Barotrauma.Networking private IEnumerable InitiateStartGame(Submarine selectedSub, Submarine selectedShuttle, GameModePreset selectedMode) { - GameMain.NetLobbyScreen.StartButton.Enabled = false; + GameMain.NetLobbyScreen.StartButtonEnabled = false; if (connectedClients.Any()) { @@ -1086,19 +1060,23 @@ namespace Barotrauma.Networking if (fileSender.ActiveTransfers.Count > 0) { +#if CLIENT var msgBox = new GUIMessageBox("", "Waiting for file transfers to finish before starting the round...", new string[] { "Start now" }); msgBox.Buttons[0].OnClicked += msgBox.Close; +#endif float waitForTransfersTimer = 20.0f; while (fileSender.ActiveTransfers.Count > 0 && waitForTransfersTimer > 0.0f) { waitForTransfersTimer -= CoroutineManager.UnscaledDeltaTime; +#if CLIENT //message box close, break and start the round immediately if (!GUIMessageBox.MessageBoxes.Contains(msgBox)) { break; } +#endif yield return CoroutineStatus.Running; } @@ -1116,9 +1094,11 @@ namespace Barotrauma.Networking entityEventManager.Clear(); - GameMain.NetLobbyScreen.StartButton.Enabled = false; + GameMain.NetLobbyScreen.StartButtonEnabled = false; +#if CLIENT GUIMessageBox.CloseAll(); +#endif roundStartSeed = DateTime.Now.Millisecond; Rand.SetSyncedSeed(roundStartSeed); @@ -1261,7 +1241,7 @@ namespace Barotrauma.Networking AddChatMessage("Press TAB to chat. Use ''r;'' to talk through the radio.", ChatMessageType.Server); - GameMain.NetLobbyScreen.StartButton.Enabled = true; + GameMain.NetLobbyScreen.StartButtonEnabled = true; gameStarted = true; initiatedStartGame = false; @@ -1350,7 +1330,9 @@ namespace Barotrauma.Networking Character.Controlled = null; myCharacter = null; GameMain.GameScreen.Cam.TargetPos = Vector2.Zero; +#if CLIENT GameMain.LightManager.LosEnabled = false; +#endif entityEventManager.Clear(); foreach (Client c in connectedClients) @@ -1486,7 +1468,9 @@ namespace Barotrauma.Networking client.Connection.Disconnect(targetmsg); - GameMain.NetLobbyScreen.RemovePlayer(client.name); +#if CLIENT + GameMain.NetLobbyScreen.RemovePlayer(client.name); +#endif connectedClients.Remove(client); UpdateVoteStatus(); @@ -1744,85 +1728,12 @@ namespace Barotrauma.Networking return message; } - public override void Draw(Microsoft.Xna.Framework.Graphics.SpriteBatch spriteBatch) - { - base.Draw(spriteBatch); - - if (settingsFrame != null) - { - settingsFrame.Draw(spriteBatch); - } - else if (log.LogFrame!=null) - { - log.LogFrame.Draw(spriteBatch); - } - - if (!ShowNetStats) return; - - GUI.Font.DrawString(spriteBatch, "Unique Events: " + entityEventManager.UniqueEvents.Count, new Vector2(10, 50), Color.White); - - int width = 200, height = 300; - int x = GameMain.GraphicsWidth - width, y = (int)(GameMain.GraphicsHeight * 0.3f); - - - if (clientListScrollBar == null) - { - clientListScrollBar = new GUIScrollBar(new Rectangle(x + width - 10, y, 10, height), "", 1.0f); - } - - - GUI.DrawRectangle(spriteBatch, new Rectangle(x, y, width, height), Color.Black * 0.7f, true); - GUI.Font.DrawString(spriteBatch, "Network statistics:", new Vector2(x + 10, y + 10), Color.White); - - GUI.SmallFont.DrawString(spriteBatch, "Connections: "+server.ConnectionsCount, new Vector2(x + 10, y + 30), Color.White); - GUI.SmallFont.DrawString(spriteBatch, "Received bytes: " + MathUtils.GetBytesReadable(server.Statistics.ReceivedBytes), new Vector2(x + 10, y + 45), Color.White); - GUI.SmallFont.DrawString(spriteBatch, "Received packets: " + server.Statistics.ReceivedPackets, new Vector2(x + 10, y + 60), Color.White); - - GUI.SmallFont.DrawString(spriteBatch, "Sent bytes: " + MathUtils.GetBytesReadable(server.Statistics.SentBytes), new Vector2(x + 10, y + 75), Color.White); - GUI.SmallFont.DrawString(spriteBatch, "Sent packets: " + server.Statistics.SentPackets, new Vector2(x + 10, y + 90), Color.White); - - int resentMessages = 0; - - int clientListHeight = connectedClients.Count * 40; - float scrollBarHeight = (height - 110) / (float)Math.Max(clientListHeight, 110); - - if (clientListScrollBar.BarSize != scrollBarHeight) - { - clientListScrollBar.BarSize = scrollBarHeight; - } - - int startY = y + 110; - y = (startY - (int)(clientListScrollBar.BarScroll * (clientListHeight-(height - 110)))); - foreach (Client c in connectedClients) - { - Color clientColor = c.Connection.AverageRoundtripTime > 0.3f ? Color.Red : Color.White; - - if (y >= startY && y < startY + height - 120) - { - GUI.SmallFont.DrawString(spriteBatch, c.name + " ("+c.Connection.RemoteEndPoint.Address.ToString()+")", new Vector2(x + 10, y), clientColor); - GUI.SmallFont.DrawString(spriteBatch, "Ping: " + (int)(c.Connection.AverageRoundtripTime * 1000.0f) + " ms", new Vector2(x+20, y+10), clientColor); - } - if (y + 25 >= startY && y < startY + height - 130) GUI.SmallFont.DrawString(spriteBatch, "Resent messages: " + c.Connection.Statistics.ResentMessages, new Vector2(x + 20, y + 20), clientColor); - - resentMessages += (int)c.Connection.Statistics.ResentMessages; - - y += 40; - } - - clientListScrollBar.Update(1.0f / 60.0f); - clientListScrollBar.Draw(spriteBatch); - - netStats.AddValue(NetStats.NetStatType.ResentMessages, Math.Max(resentMessages, 0)); - netStats.AddValue(NetStats.NetStatType.SentBytes, server.Statistics.SentBytes); - netStats.AddValue(NetStats.NetStatType.ReceivedBytes, server.Statistics.ReceivedBytes); - - netStats.Draw(spriteBatch, new Rectangle(200,0,800,200), this); - } - private void FileTransferChanged(FileSender.FileTransferOut transfer) { Client recipient = connectedClients.Find(c => c.Connection == transfer.Connection); +#if CLIENT UpdateFileTransferIndicator(recipient); +#endif } public void SendCancelTransferMsg(FileSender.FileTransferOut transfer) @@ -1834,42 +1745,6 @@ namespace Barotrauma.Networking server.SendMessage(msg, transfer.Connection, NetDeliveryMethod.ReliableOrdered, transfer.SequenceChannel); } - private void UpdateFileTransferIndicator(Client client) - { - var transfers = fileSender.ActiveTransfers.FindAll(t => t.Connection == client.Connection); - - var clientNameBox = GameMain.NetLobbyScreen.PlayerList.FindChild(client.name); - - var clientInfo = clientNameBox.FindChild("filetransfer"); - if (clientInfo == null) - { - clientNameBox.ClearChildren(); - clientInfo = new GUIFrame(new Rectangle(0, 0, 180, 0), Color.Transparent, Alignment.TopRight, null, clientNameBox); - clientInfo.UserData = "filetransfer"; - } - else if (transfers.Count == 0) - { - clientInfo.Parent.RemoveChild(clientInfo); - } - - clientInfo.ClearChildren(); - - var progressBar = new GUIProgressBar(new Rectangle(0, 4, 160, clientInfo.Rect.Height - 8), Color.Green, "", 0.0f, Alignment.Left, clientInfo); - progressBar.IsHorizontal = true; - progressBar.ProgressGetter = () => { return transfers.Sum(t => t.Progress) / transfers.Count; }; - - var textBlock = new GUITextBlock(new Rectangle(0, 2, 160, 0), "", "", Alignment.TopLeft, Alignment.Left | Alignment.CenterY, clientInfo, true, GUI.SmallFont); - textBlock.TextGetter = () => - { return MathUtils.GetBytesReadable(transfers.Sum(t => t.SentOffset)) + " / " + MathUtils.GetBytesReadable(transfers.Sum(t => t.Data.Length)); }; - - var cancelButton = new GUIButton(new Rectangle(-5, 0, 14, 0), "X", Alignment.Right, "", clientInfo); - cancelButton.OnClicked = (GUIButton button, object userdata) => - { - transfers.ForEach(t => fileSender.CancelTransfer(t)); - return true; - }; - } - public void UpdateVoteStatus() { if (server.Connections.Count == 0|| connectedClients.Count == 0) return; @@ -1920,30 +1795,7 @@ namespace Barotrauma.Networking SaveClientPermissions(); } - - public override bool SelectCrewCharacter(Character character, GUIComponent crewFrame) - { - if (character == null) return false; - - var characterFrame = crewFrame.FindChild("selectedcharacter"); - if (character != myCharacter) - { - var banButton = new GUIButton(new Rectangle(0, 0, 100, 20), "Ban", Alignment.BottomRight, "", characterFrame); - banButton.UserData = character.Name; - banButton.OnClicked += GameMain.NetLobbyScreen.BanPlayer; - - var rangebanButton = new GUIButton(new Rectangle(0, -25, 100, 20), "Ban range", Alignment.BottomRight, "", characterFrame); - rangebanButton.UserData = character.Name; - rangebanButton.OnClicked += GameMain.NetLobbyScreen.BanPlayerRange; - - var kickButton = new GUIButton(new Rectangle(0, 0, 100, 20), "Kick", Alignment.BottomLeft, "", characterFrame); - kickButton.UserData = character.Name; - kickButton.OnClicked += GameMain.NetLobbyScreen.KickPlayer; - } - - return true; - } - + public void SetClientCharacter(Client client, Character newCharacter) { if (client == null) return; diff --git a/BarotraumaShared/Source/Networking/Voting.cs b/BarotraumaShared/Source/Networking/Voting.cs index 77681c37d..6aaacd241 100644 --- a/BarotraumaShared/Source/Networking/Voting.cs +++ b/BarotraumaShared/Source/Networking/Voting.cs @@ -8,7 +8,7 @@ using System.Text; namespace Barotrauma { - class Voting + partial class Voting { private bool allowSubVoting, allowModeVoting; @@ -16,83 +16,6 @@ namespace Barotrauma public bool AllowEndVoting = true; - public bool AllowSubVoting - { - get { return allowSubVoting; } - set - { - if (value == allowSubVoting) return; - allowSubVoting = value; - GameMain.NetLobbyScreen.SubList.Enabled = value || GameMain.Server != null; - GameMain.NetLobbyScreen.InfoFrame.FindChild("subvotes").Visible = value; - - if (GameMain.Server != null) - { - UpdateVoteTexts(GameMain.Server.ConnectedClients, VoteType.Sub); - GameMain.Server.UpdateVoteStatus(); - } - else - { - GameMain.NetLobbyScreen.SubList.Deselect(); - } - } - } - public bool AllowModeVoting - { - get { return allowModeVoting; } - set - { - if (value == allowModeVoting) return; - allowModeVoting = value; - GameMain.NetLobbyScreen.ModeList.Enabled = value || GameMain.Server != null; - GameMain.NetLobbyScreen.InfoFrame.FindChild("modevotes").Visible = value; - if (GameMain.Server != null) - { - UpdateVoteTexts(GameMain.Server.ConnectedClients, VoteType.Mode); - GameMain.Server.UpdateVoteStatus(); - } - else - { - GameMain.NetLobbyScreen.ModeList.Deselect(); - } - } - } - - public void UpdateVoteTexts(List clients, VoteType voteType) - { - GUIListBox listBox = (voteType == VoteType.Sub) ? - GameMain.NetLobbyScreen.SubList : GameMain.NetLobbyScreen.ModeList; - - foreach (GUIComponent comp in listBox.children) - { - GUITextBlock voteText = comp.FindChild("votes") as GUITextBlock; - if (voteText != null) comp.RemoveChild(voteText); - } - - List> voteList = GetVoteList(voteType, clients); - foreach (Pair votable in voteList) - { - SetVoteText(listBox, votable.First, votable.Second); - } - } - - private void SetVoteText(GUIListBox listBox, object userData, int votes) - { - if (userData == null) return; - foreach (GUIComponent comp in listBox.children) - { - if (comp.UserData != userData) continue; - GUITextBlock voteText = comp.FindChild("votes") as GUITextBlock; - if (voteText == null) - { - voteText = new GUITextBlock(new Rectangle(0, 0, 30, 0), "", "", Alignment.Right, Alignment.Right, comp); - voteText.UserData = "votes"; - } - - voteText.Text = votes == 0 ? "" : votes.ToString(); - } - } - private List> GetVoteList(VoteType voteType, List voters) { List> voteList = new List>(); @@ -146,44 +69,10 @@ namespace Barotrauma GameMain.NetworkMember.EndVoteCount = 0; GameMain.NetworkMember.EndVoteMax = 0; +#if CLIENT UpdateVoteTexts(connectedClients, VoteType.Mode); UpdateVoteTexts(connectedClients, VoteType.Sub); - } - - public void ClientWrite(NetBuffer msg, VoteType voteType, object data) - { - if (GameMain.Server != null) return; - - msg.Write((byte)voteType); - - switch (voteType) - { - case VoteType.Sub: - Submarine sub = data as Submarine; - if (sub == null) return; - - msg.Write(sub.Name); - break; - case VoteType.Mode: - GameModePreset gameMode = data as GameModePreset; - if (gameMode == null) return; - - msg.Write(gameMode.Name); - break; - case VoteType.EndRound: - if (!(data is bool)) return; - - msg.Write((bool)data); - break; - case VoteType.Kick: - Client votedClient = data as Client; - if (votedClient == null) return; - - msg.Write(votedClient.ID); - break; - } - - msg.WritePadBits(); +#endif } public void ServerRead(NetIncomingMessage inc, Client sender) @@ -283,48 +172,5 @@ namespace Barotrauma msg.WritePadBits(); } - public void ClientRead(NetIncomingMessage inc) - { - if (GameMain.Server != null) return; - - AllowSubVoting = inc.ReadBoolean(); - if (allowSubVoting) - { - foreach (Submarine sub in Submarine.SavedSubmarines) - { - SetVoteText(GameMain.NetLobbyScreen.SubList, sub, 0); - } - int votableCount = inc.ReadByte(); - for (int i = 0; i < votableCount; i++) - { - int votes = inc.ReadByte(); - string subName = inc.ReadString(); - Submarine sub = Submarine.SavedSubmarines.Find(sm => sm.Name == subName); - SetVoteText(GameMain.NetLobbyScreen.SubList, sub, votes); - } - } - AllowModeVoting = inc.ReadBoolean(); - if (allowModeVoting) - { - int votableCount = inc.ReadByte(); - for (int i = 0; i < votableCount; i++) - { - int votes = inc.ReadByte(); - string modeName = inc.ReadString(); - GameModePreset mode = GameModePreset.list.Find(m => m.Name == modeName); - SetVoteText(GameMain.NetLobbyScreen.ModeList, mode, votes); - } - } - AllowEndVoting = inc.ReadBoolean(); - if (AllowEndVoting) - { - GameMain.NetworkMember.EndVoteCount = inc.ReadByte(); - GameMain.NetworkMember.EndVoteMax = inc.ReadByte(); - } - AllowVoteKick = inc.ReadBoolean(); - - inc.ReadPadBits(); - } - } }