diff --git a/Subsurface/Content/Characters/Human/human.xml b/Subsurface/Content/Characters/Human/human.xml
index c4d03a9ca..28e4be637 100644
--- a/Subsurface/Content/Characters/Human/human.xml
+++ b/Subsurface/Content/Characters/Human/human.xml
@@ -75,20 +75,17 @@
-
-
-
-
+
-
+
-
+
diff --git a/Subsurface/Content/Items/Clothes/clothes.xml b/Subsurface/Content/Items/Clothes/clothes.xml
index 84d4c66d4..59237a2c2 100644
--- a/Subsurface/Content/Items/Clothes/clothes.xml
+++ b/Subsurface/Content/Items/Clothes/clothes.xml
@@ -95,6 +95,24 @@
+ -
+
+
+
+
+
+
+
+
+
+
+
+
+
- 0)
{
@@ -134,10 +164,10 @@ namespace Barotrauma
return;
}
- if (Anim != Animation.UsingConstruction) ResetPullJoints();
-
if (TargetDir != dir) Flip();
+ if (Anim != Animation.UsingConstruction) ResetPullJoints();
+
if (SimplePhysicsEnabled)
{
UpdateStandingSimple();
@@ -815,7 +845,17 @@ namespace Barotrauma
target.AnimController.IgnorePlatforms = IgnorePlatforms;
- target.AnimController.TargetMovement = TargetMovement;
+
+ if (target.Stun > 0.0f || target.IsDead)
+ {
+ target.AnimController.TargetMovement = TargetMovement;
+ }
+ else if (target is AICharacter)
+ {
+ target.AnimController.TargetMovement = Vector2.Lerp(target.AnimController.TargetMovement, (character.SimPosition + Vector2.UnitX*Dir) - target.SimPosition, 0.5f);
+ }
+
+
}
public override void HoldItem(float deltaTime, Item item, Vector2[] handlePos, Vector2 holdPos, Vector2 aimPos, bool aim, float holdAngle)
@@ -994,12 +1034,14 @@ namespace Barotrauma
case LimbType.LeftArm:
case LimbType.RightHand:
case LimbType.RightArm:
- difference = limb.body.SimPosition - torso.SimPosition;
- difference = Vector2.Transform(difference, torsoTransform);
- difference.Y = -difference.Y;
-
- TrySetLimbPosition(limb, limb.SimPosition, torso.SimPosition + Vector2.Transform(difference, -torsoTransform));
+ if (!limb.pullJoint.Enabled)
+ {
+ difference = limb.body.SimPosition - torso.SimPosition;
+ difference = Vector2.Transform(difference, torsoTransform);
+ difference.Y = -difference.Y;
+ TrySetLimbPosition(limb, limb.SimPosition, torso.SimPosition + Vector2.Transform(difference, -torsoTransform));
+ }
limb.body.SetTransform(limb.body.SimPosition, -limb.body.Rotation);
break;
default:
diff --git a/Subsurface/Source/Characters/Character.cs b/Subsurface/Source/Characters/Character.cs
index 80628d056..19204dfcd 100644
--- a/Subsurface/Source/Characters/Character.cs
+++ b/Subsurface/Source/Characters/Character.cs
@@ -149,6 +149,19 @@ namespace Barotrauma
get { return inventory; }
}
+ private float lockHandsTimer;
+ public bool LockHands
+ {
+ get
+ {
+ return lockHandsTimer > 0.0f;
+ }
+ set
+ {
+ lockHandsTimer = MathHelper.Clamp(lockHandsTimer + (value ? 1.0f : -0.5f), 0.0f, 10.0f);
+ }
+ }
+
public Vector2 CursorPosition
{
get { return cursorPosition; }
@@ -244,7 +257,7 @@ namespace Barotrauma
if (!MathUtils.IsValid(value)) return;
health = MathHelper.Clamp(value, 0.0f, maxHealth);
}
- }
+ }
public float MaxHealth
{
@@ -304,14 +317,6 @@ namespace Barotrauma
public bool IsDead
{
get { return isDead; }
- //set
- //{
- // if (isDead == value) return;
- // if (isDead)
- // {
- // Revive(false);
- // }
- //}
}
public CauseOfDeath CauseOfDeath
@@ -319,6 +324,14 @@ namespace Barotrauma
get { return causeOfDeath; }
}
+ public bool CanBeSelected
+ {
+ get
+ {
+ return isDead || Stun > 0.0f || LockHands;
+ }
+ }
+
public override Vector2 SimPosition
{
get { return AnimController.RefLimb.SimPosition; }
@@ -658,8 +671,7 @@ namespace Barotrauma
if (selectedCharacter!=null)
{
- if (Vector2.Distance(selectedCharacter.SimPosition, SimPosition) > 3.0f ||
- (!selectedCharacter.isDead && selectedCharacter.Stun <= 0.0f))
+ if (Vector2.Distance(selectedCharacter.SimPosition, SimPosition) > 2.0f || !selectedCharacter.CanBeSelected)
{
DeselectCharacter();
}
@@ -765,9 +777,7 @@ namespace Barotrauma
selectedCharacter = character;
- if (createNetworkEvent)
- new NetworkEvent(NetworkEventType.SelectCharacter, ID, true, selectedCharacter.ID);
-
+ if (createNetworkEvent) new NetworkEvent(NetworkEventType.SelectCharacter, ID, true, selectedCharacter.ID);
}
private void DeselectCharacter(bool createNetworkEvent = true)
@@ -820,8 +830,6 @@ namespace Barotrauma
(AnimController.CurrentHull.LethalPressure - 50.0f) / 50.0f);
}
cam.OffsetAmount = MathHelper.Lerp(cam.OffsetAmount, (Submarine == null ? 400.0f : 250.0f)+pressureEffect, 0.05f);
-
-
}
cursorPosition = cam.ScreenToWorld(PlayerInput.MousePosition);
@@ -844,69 +852,68 @@ namespace Barotrauma
}
- //find the closest item if selectkey has been hit, or if the Character is being
- //controlled by the player (in order to highlight it)
-
- if (findClosestTimer <= 0.0f || Screen.Selected == GameMain.EditMapScreen)
+ if (!LockHands)
{
- closestCharacter = FindClosestCharacter(mouseSimPos);
- if (closestCharacter != null && closestCharacter.info==null)
- {
- closestCharacter = null;
- }
+ //find the closest item if selectkey has been hit, or if the Character is being
+ //controlled by the player (in order to highlight it)
- closestItem = FindClosestItem(mouseSimPos);
-
- if (closestCharacter != null && closestItem != null)
+ if (findClosestTimer <= 0.0f || Screen.Selected == GameMain.EditMapScreen)
{
- if (Vector2.Distance(closestCharacter.SimPosition, mouseSimPos) < Vector2.Distance(closestItem.SimPosition, mouseSimPos))
- {
- if (selectedConstruction != closestItem) closestItem = null;
- }
- else
+ closestCharacter = FindClosestCharacter(mouseSimPos);
+ if (closestCharacter != null && closestCharacter.info==null)
{
closestCharacter = null;
}
+
+ closestItem = FindClosestItem(mouseSimPos);
+
+ if (closestCharacter != null && closestItem != null)
+ {
+ if (Vector2.Distance(closestCharacter.SimPosition, mouseSimPos) < Vector2.Distance(closestItem.SimPosition, mouseSimPos))
+ {
+ if (selectedConstruction != closestItem) closestItem = null;
+ }
+ else
+ {
+ closestCharacter = null;
+ }
+ }
+
+ findClosestTimer = 0.1f;
+ }
+ else
+ {
+ findClosestTimer -= deltaTime;
}
- findClosestTimer = 0.1f;
- }
- else
- {
- findClosestTimer -= deltaTime;
- }
-
- if (selectedCharacter == null)
- {
- if (closestItem != null)
+ if (selectedCharacter == null && closestItem != null)
{
closestItem.IsHighlighted = true;
- if (closestItem.Pick(this))
+ if (!LockHands && closestItem.Pick(this))
{
new NetworkEvent(NetworkEventType.PickItem, ID, true,
new int[]
- {
- closestItem.ID,
- IsKeyHit(InputType.Select) ? 1 : 0,
- IsKeyHit(InputType.Use) ? 1 : 0
- });
+ {
+ closestItem.ID,
+ IsKeyHit(InputType.Select) ? 1 : 0,
+ IsKeyHit(InputType.Use) ? 1 : 0
+ });
+ }
+ }
+
+ if (IsKeyHit(InputType.Select))
+ {
+ if (selectedCharacter != null)
+ {
+ DeselectCharacter();
+ }
+ else if (closestCharacter != null && closestCharacter.IsHumanoid && closestCharacter.CanBeSelected)
+ {
+ SelectCharacter(closestCharacter);
}
}
}
- if (IsKeyHit(InputType.Select))
- {
- if (selectedCharacter != null)
- {
- DeselectCharacter();
- }
- else if (closestCharacter != null && closestCharacter.IsHumanoid &&
- (closestCharacter.isDead || closestCharacter.AnimController.StunTimer > 0.0f))
- {
- SelectCharacter(closestCharacter);
- }
- }
-
DisableControls = false;
}
@@ -1003,6 +1010,8 @@ namespace Barotrauma
Health -= bleeding*deltaTime;
if (health <= 0.0f) Kill(CauseOfDeath.Bloodloss, false);
+
+ if (!IsDead) LockHands = false;
}
diff --git a/Subsurface/Source/Characters/CharacterHUD.cs b/Subsurface/Source/Characters/CharacterHUD.cs
index f35fb466a..c917b6eaf 100644
--- a/Subsurface/Source/Characters/CharacterHUD.cs
+++ b/Subsurface/Source/Characters/CharacterHUD.cs
@@ -56,16 +56,16 @@ namespace Barotrauma
DrawStatusIcons(spriteBatch, character);
- if (character.Inventory != null) character.Inventory.DrawOwn(spriteBatch);
+ if (character.Inventory != null && !character.LockHands) character.Inventory.DrawOwn(spriteBatch, Vector2.Zero);
if (character.SelectedCharacter != null && character.SelectedCharacter.Inventory!=null)
{
- character.SelectedCharacter.Inventory.Draw(spriteBatch);
+ character.SelectedCharacter.Inventory.DrawOwn(spriteBatch, new Vector2(GameMain.GraphicsWidth - 310, 0.0f));
//if (Vector2.Distance(selectedCharacter.SimPosition, SimPosition) > 2.0f) selectedCharacter = null;
}
- if (character.ClosestCharacter != null && (character.ClosestCharacter.IsDead || character.ClosestCharacter.Stun > 0.0f))
+ if (character.ClosestCharacter != null && character.ClosestCharacter.CanBeSelected)
{
Vector2 startPos = character.DrawPosition + (character.ClosestCharacter.DrawPosition - character.DrawPosition) * 0.7f;
startPos = cam.WorldToScreen(startPos);
diff --git a/Subsurface/Source/Characters/Limb.cs b/Subsurface/Source/Characters/Limb.cs
index 4463aa0b7..37ec28622 100644
--- a/Subsurface/Source/Characters/Limb.cs
+++ b/Subsurface/Source/Characters/Limb.cs
@@ -6,6 +6,7 @@ using FarseerPhysics.Dynamics.Joints;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Barotrauma.Items.Components;
+using System.Collections.Generic;
namespace Barotrauma
{
@@ -64,8 +65,7 @@ namespace Barotrauma
private Direction dir;
- private Wearable wearingItem;
- private WearableSprite wearingItemSprite;
+ private List wearingItems;
private Vector2 animTargetPos;
@@ -172,21 +172,23 @@ namespace Barotrauma
// set { bleeding = MathHelper.Clamp(value, 0.0f, 100.0f); }
//}
- public Wearable WearingItem
+ public List WearingItems
{
- get { return wearingItem; }
- set { wearingItem = value; }
+ get { return wearingItems; }
+ set { wearingItems = value; }
}
- public WearableSprite WearingItemSprite
- {
- get { return wearingItemSprite; }
- set { wearingItemSprite = value; }
- }
+ //public WearableSprite WearingItemSprite
+ //{
+ // get { return wearingItemSprite; }
+ // set { wearingItemSprite = value; }
+ //}
public Limb (Character character, XElement element, float scale = 1.0f)
{
this.character = character;
+
+ WearingItems = new List();
dir = Direction.Right;
@@ -327,13 +329,16 @@ namespace Barotrauma
totalArmorValue += armorValue;
}
- if (wearingItem!=null &&
- wearingItem.ArmorValue>0.0f &&
- SectorHit(wearingItem.ArmorSectorLimits, position))
+ foreach (WearableSprite wearable in wearingItems)
{
- hitArmor = true;
- totalArmorValue += wearingItem.ArmorValue;
- }
+ if (wearable.WearableComponent.ArmorValue > 0.0f &&
+ SectorHit(wearable.WearableComponent.ArmorSectorLimits, position))
+ {
+ hitArmor = true;
+ totalArmorValue += wearable.WearableComponent.ArmorValue;
+ }
+ }
+
if (hitArmor)
{
@@ -456,7 +461,7 @@ namespace Barotrauma
body.Dir = Dir;
- if (wearingItem == null || !wearingItemSprite.HideLimb)
+ if (wearingItems.Find(w => w != null && w.HideLimb) == null)
{
body.Draw(spriteBatch, sprite, color, null, scale);
}
@@ -464,32 +469,32 @@ namespace Barotrauma
{
body.UpdateDrawPosition();
}
-
- if (wearingItem != null)
+
+ foreach (WearableSprite wearable in wearingItems)
{
SpriteEffects spriteEffect = (dir == Direction.Right) ? SpriteEffects.None : SpriteEffects.FlipHorizontally;
- Vector2 origin = wearingItemSprite.Sprite.Origin;
- if (body.Dir == -1.0f) origin.X = wearingItemSprite.Sprite.SourceRect.Width - origin.X;
+ 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 (wearingItemSprite.DepthLimb!=LimbType.None)
+ if (wearable.DepthLimb != LimbType.None)
{
- Limb depthLimb = character.AnimController.GetLimb(wearingItemSprite.DepthLimb);
- if (depthLimb!=null)
+ Limb depthLimb = character.AnimController.GetLimb(wearable.DepthLimb);
+ if (depthLimb != null)
{
depth = depthLimb.sprite.Depth - 0.000001f;
}
}
- wearingItemSprite.Sprite.Draw(spriteBatch,
+ 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)
{
SpriteEffects spriteEffect = (dir == Direction.Right) ? SpriteEffects.None : SpriteEffects.FlipHorizontally;
diff --git a/Subsurface/Source/GameSession/CrewManager.cs b/Subsurface/Source/GameSession/CrewManager.cs
index 225faeb1e..d1b0ba614 100644
--- a/Subsurface/Source/GameSession/CrewManager.cs
+++ b/Subsurface/Source/GameSession/CrewManager.cs
@@ -71,7 +71,7 @@ namespace Barotrauma
//listBox.Select(selection);
Character character = selection as Character;
- if (character == null) return false;
+ if (character == null || character.IsDead) return false;
if (characters.Contains(character))
{
diff --git a/Subsurface/Source/Items/CharacterInventory.cs b/Subsurface/Source/Items/CharacterInventory.cs
index 207ca6863..b7c9697d9 100644
--- a/Subsurface/Source/Items/CharacterInventory.cs
+++ b/Subsurface/Source/Items/CharacterInventory.cs
@@ -210,7 +210,7 @@ namespace Barotrauma
return TryPutItem(item, new List() {placeToSlots}, createNetworkEvent);
}
- public void DrawOwn(SpriteBatch spriteBatch)
+ public void DrawOwn(SpriteBatch spriteBatch, Vector2 offset)
{
string toolTip = "";
Rectangle highlightedSlot = Rectangle.Empty;
@@ -227,8 +227,8 @@ namespace Barotrauma
for (int i = 0; i < capacity; i++)
{
- slotRect.X = (int)SlotPositions[i].X;
- slotRect.Y = (int)SlotPositions[i].Y;
+ slotRect.X = (int)(SlotPositions[i].X + offset.X);
+ slotRect.Y = (int)(SlotPositions[i].Y + offset.Y);
if (i==1) //head
{
@@ -248,8 +248,8 @@ namespace Barotrauma
for (int i = 0; i < capacity; i++)
{
- slotRect.X = (int)SlotPositions[i].X;
- slotRect.Y = (int)SlotPositions[i].Y;
+ slotRect.X = (int)(SlotPositions[i].X + offset.X);
+ slotRect.Y = (int)(SlotPositions[i].Y + offset.Y);
bool multiSlot = false;
//skip if the item is in multiple slots
@@ -295,8 +295,8 @@ namespace Barotrauma
//check if the item is in multiple slots
if (Items[i] != null)
{
- slotRect.X = (int)SlotPositions[i].X;
- slotRect.Y = (int)SlotPositions[i].Y;
+ slotRect.X = (int)(SlotPositions[i].X + offset.X);
+ slotRect.Y = (int)(SlotPositions[i].Y + offset.Y);
slotRect.Width = 40;
slotRect.Height = 40;
@@ -310,7 +310,7 @@ namespace Barotrauma
{
multiSlot = true;
slotRect = Rectangle.Union(
- new Rectangle((int)SlotPositions[n].X, (int)SlotPositions[n].Y, rectWidth, rectHeight), slotRect);
+ new Rectangle((int)(SlotPositions[n].X+offset.X), (int)(SlotPositions[n].Y+offset.Y), rectWidth, rectHeight), slotRect);
}
}
}
diff --git a/Subsurface/Source/Items/Components/Holdable/Propulsion.cs b/Subsurface/Source/Items/Components/Holdable/Propulsion.cs
index bd3f523ad..5b29339db 100644
--- a/Subsurface/Source/Items/Components/Holdable/Propulsion.cs
+++ b/Subsurface/Source/Items/Components/Holdable/Propulsion.cs
@@ -76,7 +76,7 @@ namespace Barotrauma.Items.Components
{
foreach (Limb limb in character.AnimController.Limbs)
{
- if (limb.WearingItem==null || limb.WearingItem.Item != item) continue;
+ if (limb.WearingItems.Find(w => w.WearableComponent.Item != this.item)==null) continue;
limb.body.ApplyForce(propulsion);
}
diff --git a/Subsurface/Source/Items/Components/Wearable.cs b/Subsurface/Source/Items/Components/Wearable.cs
index 6f267bc20..36539d95e 100644
--- a/Subsurface/Source/Items/Components/Wearable.cs
+++ b/Subsurface/Source/Items/Components/Wearable.cs
@@ -12,8 +12,11 @@ namespace Barotrauma.Items.Components
public bool HideLimb;
public LimbType DepthLimb;
- public WearableSprite(Sprite sprite, bool hideLimb, LimbType depthLimb = LimbType.None)
+ public Wearable WearableComponent;
+
+ public WearableSprite(Wearable item, Sprite sprite, bool hideLimb, LimbType depthLimb = LimbType.None)
{
+ WearableComponent = item;
Sprite = sprite;
HideLimb = hideLimb;
@@ -85,7 +88,7 @@ namespace Barotrauma.Items.Components
spritePath = Path.GetDirectoryName( item.Prefab.ConfigFile)+"/"+spritePath;
var sprite = new Sprite(subElement, "", spritePath);
- wearableSprites[i] = new WearableSprite(sprite, ToolBox.GetAttributeBool(subElement, "hidelimb", false),
+ wearableSprites[i] = new WearableSprite(this, sprite, ToolBox.GetAttributeBool(subElement, "hidelimb", false),
(LimbType)Enum.Parse(typeof(LimbType),
ToolBox.GetAttributeString(subElement, "depthlimb", "None"), true));
@@ -105,10 +108,10 @@ namespace Barotrauma.Items.Components
if (equipLimb == null) continue;
//something is already on the limb -> unequip it
- if (equipLimb.WearingItem != null && equipLimb.WearingItem != this)
- {
- equipLimb.WearingItem.Unequip(character);
- }
+ //if (equipLimb.WearingItem != null && equipLimb.WearingItem != this)
+ //{
+ // equipLimb.WearingItem.Unequip(character);
+ //}
//sprite[i].Depth = equipLimb.sprite.Depth - 0.001f;
@@ -117,8 +120,7 @@ namespace Barotrauma.Items.Components
IsActive = true;
limb[i] = equipLimb;
- equipLimb.WearingItem = this;
- equipLimb.WearingItemSprite = wearableSprites[i];
+ equipLimb.WearingItems.Add(wearableSprites[i]);
}
}
@@ -140,11 +142,20 @@ namespace Barotrauma.Items.Components
Limb equipLimb = character.AnimController.GetLimb(limbType[i]);
if (equipLimb == null) continue;
- if (equipLimb.WearingItem != this) continue;
+ //foreach (WearableSprite wearable in equipLimb.WearingItems)
+ //{
+ // if (wearable != wearableSprites[i]) continue;
+
+ // equipLimb.WearingItems.Remove(wearableSprites[i]);
+ //}
+
+ equipLimb.WearingItems.RemoveAll(w=> w!=null && w==wearableSprites[i]);
+
+ //if (equipLimb.WearingItem != this) continue;
limb[i] = null;
- equipLimb.WearingItem = null;
- equipLimb.WearingItemSprite = null;
+ //equipLimb.WearingItem = null;
+ //equipLimb.WearingItemSprite = null;
}
IsActive = false;
diff --git a/Subsurface/Source/Map/FireSource.cs b/Subsurface/Source/Map/FireSource.cs
index 4800ab0d5..24898c8bf 100644
--- a/Subsurface/Source/Map/FireSource.cs
+++ b/Subsurface/Source/Map/FireSource.cs
@@ -236,7 +236,7 @@ namespace Barotrauma
float dmg = (float)Math.Sqrt(size.X) * deltaTime / c.AnimController.Limbs.Count();
foreach (Limb limb in c.AnimController.Limbs)
{
- if (limb.WearingItem != null && limb.WearingItem.Item.FireProof) continue;
+ if (limb.WearingItems.Find(w => w!=null && w.WearableComponent.Item.FireProof)!=null) continue;
limb.Burnt += dmg * 10.0f;
c.AddDamage(limb.SimPosition, DamageType.None, dmg, 0,0,false);
}
diff --git a/Subsurface/Source/Networking/GameServer.cs b/Subsurface/Source/Networking/GameServer.cs
index 3719f4b10..ce544257f 100644
--- a/Subsurface/Source/Networking/GameServer.cs
+++ b/Subsurface/Source/Networking/GameServer.cs
@@ -35,6 +35,8 @@ namespace Barotrauma.Networking
private ServerLog log;
private GUIButton showLogButton;
+ private GUIScrollBar clientListScrollBar;
+
public TraitorManager TraitorManager;
public GameServer(string name, int port, bool isPublic = false, string password = "", bool attemptUPnP = false, int maxPlayers = 10)
@@ -1177,33 +1179,57 @@ namespace Barotrauma.Networking
if (!ShowNetStats) return;
int width = 200, height = 300;
- int x = GameMain.GraphicsWidth - width, y = (int)(GameMain.GraphicsHeight*0.3f);
+ int x = GameMain.GraphicsWidth - width, y = (int)(GameMain.GraphicsHeight * 0.3f);
- GUI.DrawRectangle(spriteBatch, new Rectangle(x,y,width,height), Color.Black*0.7f, true);
- spriteBatch.DrawString(GUI.Font, "Network statistics:", new Vector2(x+10, y+10), Color.White);
+
+ if (clientListScrollBar == null)
+ {
+ clientListScrollBar = new GUIScrollBar(new Rectangle(x + width - 10, y, 10, height), GUI.Style, 1.0f);
+ }
+
+
+ GUI.DrawRectangle(spriteBatch, new Rectangle(x, y, width, height), Color.Black * 0.7f, true);
+ spriteBatch.DrawString(GUI.Font, "Network statistics:", new Vector2(x + 10, y + 10), Color.White);
spriteBatch.DrawString(GUI.SmallFont, "Connections: "+server.ConnectionsCount, new Vector2(x + 10, y + 30), Color.White);
- spriteBatch.DrawString(GUI.SmallFont, "Received bytes: " + server.Statistics.ReceivedBytes, new Vector2(x + 10, y + 45), Color.White);
+ spriteBatch.DrawString(GUI.SmallFont, "Received bytes: " + MathUtils.GetBytesReadable(server.Statistics.ReceivedBytes), new Vector2(x + 10, y + 45), Color.White);
spriteBatch.DrawString(GUI.SmallFont, "Received packets: " + server.Statistics.ReceivedPackets, new Vector2(x + 10, y + 60), Color.White);
- spriteBatch.DrawString(GUI.SmallFont, "Sent bytes: " + server.Statistics.SentBytes, new Vector2(x + 10, y + 75), Color.White);
+ spriteBatch.DrawString(GUI.SmallFont, "Sent bytes: " + MathUtils.GetBytesReadable(server.Statistics.SentBytes), new Vector2(x + 10, y + 75), Color.White);
spriteBatch.DrawString(GUI.SmallFont, "Sent packets: " + server.Statistics.SentPackets, new Vector2(x + 10, y + 90), Color.White);
int resentMessages = 0;
- y += 110;
- foreach (Client c in ConnectedClients)
- {
- spriteBatch.DrawString(GUI.SmallFont, c.name + ":", new Vector2(x + 10, y), Color.White);
- spriteBatch.DrawString(GUI.SmallFont, "- avg roundtrip " + c.Connection.AverageRoundtripTime+" s", new Vector2(x + 20, y + 15), Color.White);
- spriteBatch.DrawString(GUI.SmallFont, "- resent messages " + c.Connection.Statistics.ResentMessages, new Vector2(x + 20, y + 30), Color.White);
+ int clientListHeight = ConnectedClients.Count() * 40;
+ float scrollBarHeight = (height - 110) / (float)Math.Max(clientListHeight, 110);
- resentMessages += (int)c.Connection.Statistics.ResentMessages;
-
- y += 50;
+ if (clientListScrollBar.BarSize != scrollBarHeight)
+ {
+ clientListScrollBar.BarSize = scrollBarHeight;
}
- netStats.AddValue(NetStats.NetStatType.ResentMessages, resentMessages);
+ 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)
+ {
+ spriteBatch.DrawString(GUI.SmallFont, c.name + ":", new Vector2(x + 10, y), clientColor);
+ spriteBatch.DrawString(GUI.SmallFont, "Ping: " + (int)(c.Connection.AverageRoundtripTime * 1000.0f) + " ms", new Vector2(x + width - 100, y), clientColor);
+ }
+ if (y + 10 >= startY && y < startY + height - 130) spriteBatch.DrawString(GUI.SmallFont, "Resent messages: " + c.Connection.Statistics.ResentMessages, new Vector2(x + 10, y + 10), 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);
diff --git a/Subsurface/Source/Networking/NetStats.cs b/Subsurface/Source/Networking/NetStats.cs
index 650012ae5..8fc3c3ddc 100644
--- a/Subsurface/Source/Networking/NetStats.cs
+++ b/Subsurface/Source/Networking/NetStats.cs
@@ -71,14 +71,14 @@ namespace Barotrauma.Networking
graphs[(int)NetStatType.ResentMessages].Draw(spriteBatch, rect, null, 0.0f, Color.Red);
- spriteBatch.DrawString(GUI.SmallFont,
- "Peak received: "+graphs[(int)NetStatType.ReceivedBytes].LargestValue()+" bytes/s " +
- "Avg received: " + graphs[(int)NetStatType.ReceivedBytes].Average() + " bytes/s",
- new Vector2(rect.X + 10, rect.Y+10), Color.Cyan);
+ spriteBatch.DrawString(GUI.SmallFont,
+ "Peak received: " + MathUtils.GetBytesReadable((int)graphs[(int)NetStatType.ReceivedBytes].LargestValue()) + "/s " +
+ "Avg received: " + MathUtils.GetBytesReadable((int)graphs[(int)NetStatType.ReceivedBytes].Average()) + "/s",
+ new Vector2(rect.X + 10, rect.Y + 10), Color.Cyan);
- spriteBatch.DrawString(GUI.SmallFont, "Peak sent: " + graphs[(int)NetStatType.SentBytes].LargestValue() + " bytes/s " +
- "Avg sent: " + graphs[(int)NetStatType.SentBytes].Average() + " bytes/s",
+ spriteBatch.DrawString(GUI.SmallFont, "Peak sent: " + MathUtils.GetBytesReadable((int)graphs[(int)NetStatType.SentBytes].LargestValue()) + "/s " +
+ "Avg sent: " + MathUtils.GetBytesReadable((int)graphs[(int)NetStatType.SentBytes].Average()) + " bytes/s",
new Vector2(rect.X + 10, rect.Y + 30), Color.Orange);
spriteBatch.DrawString(GUI.SmallFont, "Peak resent: " + graphs[(int)NetStatType.ResentMessages].LargestValue() + " messages/s",
diff --git a/Subsurface/Source/Utils/MathUtils.cs b/Subsurface/Source/Utils/MathUtils.cs
index ddba37391..6f8c5788b 100644
--- a/Subsurface/Source/Utils/MathUtils.cs
+++ b/Subsurface/Source/Utils/MathUtils.cs
@@ -273,6 +273,55 @@ namespace Barotrauma
return segments;
}
+
+ // Returns the human-readable file size for an arbitrary, 64-bit file size
+ // The default format is "0.### XB", e.g. "4.2 KB" or "1.434 GB"
+ public static string GetBytesReadable(long i)
+ {
+ // Get absolute value
+ long absolute_i = (i < 0 ? -i : i);
+ // Determine the suffix and readable value
+ string suffix;
+ double readable;
+ if (absolute_i >= 0x1000000000000000) // Exabyte
+ {
+ suffix = "EB";
+ readable = (i >> 50);
+ }
+ else if (absolute_i >= 0x4000000000000) // Petabyte
+ {
+ suffix = "PB";
+ readable = (i >> 40);
+ }
+ else if (absolute_i >= 0x10000000000) // Terabyte
+ {
+ suffix = "TB";
+ readable = (i >> 30);
+ }
+ else if (absolute_i >= 0x40000000) // Gigabyte
+ {
+ suffix = "GB";
+ readable = (i >> 20);
+ }
+ else if (absolute_i >= 0x100000) // Megabyte
+ {
+ suffix = "MB";
+ readable = (i >> 10);
+ }
+ else if (absolute_i >= 0x400) // Kilobyte
+ {
+ suffix = "KB";
+ readable = i;
+ }
+ else
+ {
+ return i.ToString("0 B"); // Byte
+ }
+ // Divide by 1024 to get fractional value
+ readable = (readable / 1024);
+ // Return formatted number with suffix
+ return readable.ToString("0.# ") + suffix;
+ }
}
class CompareCCW : IComparer
diff --git a/Subsurface_Solution.v12.suo b/Subsurface_Solution.v12.suo
index 3427d79bf..64698d302 100644
Binary files a/Subsurface_Solution.v12.suo and b/Subsurface_Solution.v12.suo differ