Merge branch 'master' of bitbucket.org:Regalis11/barotrauma

This commit is contained in:
Sebastian Broberg
2016-03-03 20:18:35 +01:00
111 changed files with 1720 additions and 1204 deletions

View File

@@ -127,11 +127,11 @@ namespace Barotrauma
//UpdateTransform();
}
public void UpdateTransform()
public void UpdateTransform(bool interpolate = true)
{
Vector2 interpolatedPosition = Physics.Interpolate(prevPosition, position);
Vector2 interpolatedPosition = interpolate ? Physics.Interpolate(prevPosition, position) : position;
float interpolatedZoom = Physics.Interpolate(prevZoom, zoom);
float interpolatedZoom = interpolate ? Physics.Interpolate(prevZoom, zoom) : zoom;
worldView.X = (int)(interpolatedPosition.X - worldView.Width / 2.0);
worldView.Y = (int)(interpolatedPosition.Y + worldView.Height / 2.0);
@@ -149,6 +149,12 @@ namespace Barotrauma
viewMatrix;
Sound.CameraPos = new Vector3(WorldViewCenter.X, WorldViewCenter.Y, 0.0f);
if (!interpolate)
{
prevPosition = position;
prevZoom = zoom;
}
}
public void MoveCamera(float deltaTime)

View File

@@ -558,27 +558,12 @@ namespace Barotrauma
bool wallAttack = (wallAttackPos != Vector2.Zero && state == AiState.Attack);
message.Write(wallAttack);
//if (wallAttack)
//{
// Vector2 relativeWallAttackPos = wallAttackPos - Submarine.Loaded.SimPosition;
// message.WriteRangedSingle(MathHelper.Clamp(relativeWallAttackPos.X, -50.0f, 50.0f), -50.0f, 50.0f, 10);
// message.WriteRangedSingle(MathHelper.Clamp(relativeWallAttackPos.Y, -50.0f, 50.0f), -50.0f, 50.0f, 10);
//}
//message.Write(Velocity.X);
//message.Write(Velocity.Y);
//message.Write(Character.AnimController.RefLimb.SimPosition.X);
//message.Write(Character.AnimController.RefLimb.SimPosition.Y);
//message.Write(wallAttack);
message.Write(MathUtils.AngleToByte(steeringManager.WanderAngle));
//message.WriteRangedSingle(MathHelper.Clamp(updateTargetsTimer,0.0f, UpdateTargetsInterval), 0.0f, UpdateTargetsInterval, 8);
//message.WriteRangedSingle(MathHelper.Clamp(raycastTimer, 0.0f, RaycastInterval), 0.0f, RaycastInterval, 8);
//message.WriteRangedSingle(MathHelper.Clamp(coolDownTimer, 0.0f, attackCoolDown * 2.0f), 0.0f, attackCoolDown * 2.0f, 8);
coolDownTimer = MathHelper.Clamp(coolDownTimer, 0.0f, 30.0f);
message.WriteRangedSingle(coolDownTimer, 0.0f, 30.0f, 8);
message.Write(targetEntity==null ? (ushort)0 : (targetEntity as Entity).ID);
}
@@ -612,9 +597,8 @@ namespace Barotrauma
//targetPosition = new Vector2(message.ReadFloat(), message.ReadFloat());
wanderAngle = MathUtils.ByteToAngle(message.ReadByte());
//updateTargetsTimer = message.ReadRangedSingle(0.0f, UpdateTargetsInterval, 8);
//raycastTimer = message.ReadRangedSingle(0.0f, RaycastInterval, 8);
//coolDownTimer = message.ReadRangedSingle(0.0f, attackCoolDown*2.0f, 8);
coolDownTimer = message.ReadRangedSingle(0.0f, 30.0f, 8);
targetID = message.ReadUInt16();
}
@@ -629,14 +613,10 @@ namespace Barotrauma
return;
}
//wallAttackPos = newWallAttackPos;
steeringManager.WanderAngle = wanderAngle;
//this.updateTargetsTimer = updateTargetsTimer;
//this.raycastTimer = raycastTimer;
//this.coolDownTimer = coolDownTimer;
if (targetID > 0) targetEntity = Entity.FindEntityByID(targetID) as IDamageable;
if (targetID > 0) targetEntity = Entity.FindEntityByID(targetID) as IDamageable;
updateTargetsTimer = UpdateTargetsInterval;
}
}
@@ -647,14 +627,8 @@ namespace Barotrauma
//and if the target attacks the Character, the priority increases)
class AITargetMemory
{
//private AITarget target;
private float priority;
//public AITarget Target
//{
// get { return target; }
//}
public float Priority
{
get { return priority; }

View File

@@ -909,9 +909,8 @@ namespace Barotrauma
Vector2 shoulderPos = limbJoints[2].WorldAnchorA;
Vector2 transformedHoldPos = shoulderPos;
if (itemPos == Vector2.Zero || Anim == Animation.Climbing)
if (itemPos == Vector2.Zero || Anim == Animation.Climbing || (leftHand.Disabled && rightHand.Disabled))
{
if (character.SelectedItems[1] == item)
{
transformedHoldPos = leftHand.pullJoint.WorldAnchorA - transformedHandlePos[1];

View File

@@ -815,25 +815,35 @@ namespace Barotrauma
{
if (inWater)
{
if (character is AICharacter)
if (targetMovement.LengthSquared() > 0.01f)
{
correctionMovement =
Vector2.Lerp(targetMovement, Vector2.Normalize(diff) * MathHelper.Clamp(dist * 8.0f, 0.1f, 8.0f), 0.5f);
Vector2.Lerp(targetMovement, Vector2.Normalize(diff) * MathHelper.Clamp(dist * 5.0f, 0.1f, 5.0f), 0.2f);
}
else
{
foreach (Limb limb in Limbs)
{
//if (limb.body.TargetPosition == Vector2.Zero) continue;
refLimb.body.LinearVelocity = Vector2.Lerp(
refLimb.LinearVelocity,
Vector2.Normalize(diff) * MathHelper.Clamp(dist, 0.0f, 5.0f),
0.2f);
limb.body.SetTransform(limb.SimPosition + Vector2.Normalize(diff) * 0.1f, limb.Rotation);
}
//foreach (Limb limb in Limbs)
//{
// //if (limb.body.TargetPosition == Vector2.Zero) continue;
// // Vector2.Lerp(limb.LinearVelocity, Vector2.Normalize(diff) * MathHelper.Clamp(dist, 0.0f, 1.0f))
// limb.body.LinearVelocity = Vector2.Lerp(
// limb.LinearVelocity,
// Vector2.Normalize(diff) * MathHelper.Clamp(dist, 0.0f, 5.0f),
// 0.2f);
// //limb.body.TargetVelocity .SetTransform(limb.SimPosition + Vector2.Normalize(diff) * 0.1f, limb.Rotation);
//}
}
}
else
{
//clamp the magnitude of the correction movement between 0.5f - 5.0f
Vector2 newCorrectionMovement = Vector2.Normalize(diff) * MathHelper.Clamp(dist * 5.0f, 0.5f, 5.0f);
Vector2 newCorrectionMovement = Vector2.Normalize(diff) * MathHelper.Clamp(dist*2.0f, 0.5f, 5.0f);
//heading in the right direction -> use the ''normal'' movement if it's faster than correctionMovement
//i.e. the character is close to the targetposition but the character is still running

View File

@@ -53,6 +53,8 @@ namespace Barotrauma
public readonly bool IsNetworkPlayer;
private bool networkUpdateSent;
private CharacterInventory inventory;
public float LastNetworkUpdate;
@@ -955,6 +957,17 @@ namespace Barotrauma
if (isDead) return;
if (networkUpdateSent)
{
foreach (Key key in keys)
{
key.DequeueHit();
key.DequeueHeld();
}
networkUpdateSent = false;
}
if (needsAir)
{
bool protectedFromPressure = PressureProtection > 0.0f;
@@ -1421,9 +1434,9 @@ namespace Barotrauma
return true;
case NetworkEventType.EntityUpdate:
message.Write(keys[(int)InputType.Use].DequeueHeld);
message.Write(keys[(int)InputType.Use].GetHeldQueue);
bool secondaryHeld = keys[(int)InputType.Aim].DequeueHeld;
bool secondaryHeld = keys[(int)InputType.Aim].GetHeldQueue;
message.Write(secondaryHeld);
message.Write(keys[(int)InputType.Left].Held);
@@ -1469,6 +1482,8 @@ namespace Barotrauma
message.Write(SimPosition.X);
message.Write(SimPosition.Y);
networkUpdateSent = true;
return true;
default:
#if DEBUG

View File

@@ -10,9 +10,9 @@ namespace Barotrauma
class StatusEffect
{
[Flags]
public enum TargetType
public enum TargetType
{
This = 1, Parent = 2, Character = 4, Contained = 8, Nearby = 16, UseTarget=32
This = 1, Parent = 2, Character = 4, Contained = 8, Nearby = 16, UseTarget = 32, Hull = 64
}
private TargetType targetTypes;
@@ -273,20 +273,21 @@ namespace Barotrauma
if (disableDeltaTime) deltaTime = 1.0f;
Type type = value.GetType();
if (type == typeof(float))
if (type == typeof(float) ||
(type == typeof(int) && property.GetValue().GetType() == typeof(float)))
{
float floatValue = (float)value * deltaTime;
float floatValue = Convert.ToSingle(value) * deltaTime;
if (!setValue) floatValue += (float)property.GetValue();
property.TrySetValue(floatValue);
}
else if (type == typeof(int))
else if (type == typeof(int) && value.GetType()==typeof(int))
{
int intValue = (int)((int)value * deltaTime);
if (!setValue) intValue += (int)property.GetValue();
property.TrySetValue(intValue);
}
else if (type == typeof(bool))
else if (type == typeof(bool) && value.GetType() == typeof(bool))
{
property.TrySetValue((bool)value);
}
@@ -294,6 +295,11 @@ namespace Barotrauma
{
property.TrySetValue((string)value);
}
else
{
DebugConsole.ThrowError("Couldn't apply value "+value.ToString()+" ("+type+") to property ''"+property.Name+"'' ("+property.GetValue().GetType()+")! "
+"Make sure the type of the value set in the config files matches the type of the property.");
}
}
public static void UpdateAll(float deltaTime)

View File

@@ -381,7 +381,8 @@ namespace Barotrauma
DebugConsole.ThrowError("Illegal symbols in filename (../)");
return;
}
if (Submarine.SaveCurrent(fileName +".sub")) NewMessage("map saved", Color.Green);
if (Submarine.SaveCurrent(System.IO.Path.Combine(Submarine.SavePath, fileName +".sub"))) NewMessage("map saved", Color.Green);
Submarine.Loaded.CheckForErrors();
break;
@@ -417,6 +418,20 @@ namespace Barotrauma
//Hull.DebugDraw = !Hull.DebugDraw;
//Ragdoll.DebugDraw = !Ragdoll.DebugDraw;
GameMain.DebugDraw = !GameMain.DebugDraw;
break;
case "sendrandomdata":
int messageCount = 1;
if (commands.Length>1) int.TryParse(commands[1], out messageCount);
for (int i = 0; i < messageCount; i++ )
{
if (GameMain.Server!=null)
{
GameMain.Server.SendRandomData();
}
}
break;
case "netstats":
if (GameMain.Server == null) return;
@@ -479,6 +494,12 @@ namespace Barotrauma
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("crashreport.txt"))
{
System.IO.File.Delete("crashreport.txt");

View File

@@ -43,6 +43,18 @@ namespace Barotrauma
public static Color ScreenOverlayColor;
private static Sprite submarineIcon, arrow;
public static Sprite SubmarineIcon
{
get { return submarineIcon; }
}
public static Sprite Arrow
{
get { return arrow; }
}
public static void Init(ContentManager content)
{
GUI.Font = ToolBox.TryLoadFont("SpriteFont1", content);
@@ -72,6 +84,12 @@ namespace Barotrauma
t = new Texture2D(graphicsDevice, 1, 1);
t.SetData(new Color[] { Color.White });// fill the texture with white
submarineIcon = new Sprite("Content/UI/uiIcons.png", new Rectangle(0, 192, 64, 64), null);
submarineIcon.Origin = submarineIcon.size / 2;
arrow = new Sprite("Content/UI/uiIcons.png", new Rectangle(80, 240, 16, 16), null);
arrow.Origin = arrow.size / 2;
Style = new GUIStyle("Content/UI/style.xml");
}
@@ -304,24 +322,34 @@ namespace Barotrauma
return texture;
}
public static bool DrawButton(SpriteBatch sb, Rectangle rect, string text, bool isHoldable = false)
public static bool DrawButton(SpriteBatch sb, Rectangle rect, string text, Color color, bool isHoldable = false)
{
Color color = new Color(200, 200, 200);
bool clicked = false;
if (rect.Contains(PlayerInput.MousePosition))
{
clicked = PlayerInput.LeftButtonHeld();
color = clicked ? new Color(100, 100, 100) : new Color(250, 250, 250);
color = clicked ?
new Color((int)(color.R * 0.8f), (int)(color.G * 0.8f), (int)(color.B * 0.8f), color.A) :
new Color((int)(color.R * 1.2f), (int)(color.G * 1.2f), (int)(color.B * 1.2f), color.A);
if (!isHoldable)
clicked = PlayerInput.LeftButtonClicked();
if (!isHoldable) clicked = PlayerInput.LeftButtonClicked();
}
DrawRectangle(sb, rect, color, true);
sb.DrawString(Font, text, new Vector2(rect.X + 10, rect.Y + 10), Color.White);
Vector2 origin;
try
{
origin = Font.MeasureString(text)/2;
}
catch
{
origin = Vector2.Zero;
}
sb.DrawString(Font, text, new Vector2(rect.Center.X, rect.Center.Y) , Color.White, 0.0f, origin, 1.0f, SpriteEffects.None, 0.0f);
return clicked;
}

View File

@@ -7,7 +7,7 @@ namespace Barotrauma
{
public static Queue<GUIComponent> MessageBoxes = new Queue<GUIComponent>();
const int DefaultWidth=400, DefaultHeight=200;
const int DefaultWidth=400, DefaultHeight=250;
//public delegate bool OnClickedHandler(GUIButton button, object obj);
//public OnClickedHandler OnClicked;

View File

@@ -157,8 +157,8 @@ namespace Barotrauma
Hyper.ComponentModel.HyperTypeDescriptionProvider.Add(typeof(Character));
Hyper.ComponentModel.HyperTypeDescriptionProvider.Add(typeof(Item));
//Event.Init("Content/randomevents.xml");
Hyper.ComponentModel.HyperTypeDescriptionProvider.Add(typeof(Items.Components.ItemComponent));
Hyper.ComponentModel.HyperTypeDescriptionProvider.Add(typeof(Hull));
}
/// <summary>
@@ -195,7 +195,7 @@ namespace Barotrauma
Hull.renderer = new WaterRenderer(GraphicsDevice);
Hull.renderer = new WaterRenderer(GraphicsDevice, Content);
TitleScreen.LoadState = 1.0f;
yield return CoroutineStatus.Running;
@@ -353,7 +353,7 @@ namespace Barotrauma
protected override void OnExiting(object sender, EventArgs args)
{
if (NetworkMember != null) NetworkMember.Disconnect();
base.OnExiting(sender, args);
}

View File

@@ -172,6 +172,29 @@ namespace Barotrauma
combined = true;
}
//if moving the item between slots in the same inventory
else if (item.ParentInventory == this)
{
int currentIndex = Array.IndexOf(Items, item);
Item existingItem = Items[index];
Items[currentIndex] = null;
Items[index] = null;
//if the item in the slot can be moved to the slot of the moved item
if (TryPutItem(existingItem, currentIndex, false) &&
TryPutItem(item, index, false))
{
new Networking.NetworkEvent(Networking.NetworkEventType.InventoryUpdate, Owner.ID, true, true);
}
else
{
//swapping the items failed -> move them back to where they were
TryPutItem(item, currentIndex, false);
TryPutItem(existingItem, index, false);
}
}
return combined;
}

View File

@@ -252,7 +252,7 @@ namespace Barotrauma.Items.Components
item.Submarine = picker.Submarine;
if (picker.SelectedConstruction != null && picker.SelectedConstruction.GetComponent<Controller>() != null) return;
//if (picker.SelectedConstruction != null && picker.SelectedConstruction.GetComponent<Controller>() != null) return;
//item.sprite.Depth = picker.AnimController.GetLimb(LimbType.RightHand).sprite.Depth + 0.01f;

View File

@@ -76,7 +76,7 @@ namespace Barotrauma.Items.Components
{
foreach (Limb limb in character.AnimController.Limbs)
{
if (limb.WearingItems.Find(w => w.WearableComponent.Item != this.item)==null) continue;
if (limb.WearingItems.Find(w => w.WearableComponent.Item == this.item)==null) continue;
limb.body.ApplyForce(propulsion);
}

View File

@@ -210,6 +210,8 @@ namespace Barotrauma.Items.Components
limb.pullJoint.Enabled = false;
}
if (character.SelectedConstruction == this.item) character.SelectedConstruction = null;
character.AnimController.Anim = AnimController.Animation.None;
}
@@ -225,9 +227,6 @@ namespace Barotrauma.Items.Components
IsActive = false;
CancelUsing(character);
character = null;
}
else
{
return false;
}
}

View File

@@ -48,6 +48,24 @@ namespace Barotrauma.Items.Components
: base(item, element)
{
IsActive = true;
var button = new GUIButton(new Rectangle(160, 50, 30, 30), "-", GUI.Style, GuiFrame);
button.OnClicked = (GUIButton btn, object obj) =>
{
targetForce -= 1.0f;
item.NewComponentEvent(this, true, false);
return true;
};
button = new GUIButton(new Rectangle(200, 50, 30, 30), "+", GUI.Style, GuiFrame);
button.OnClicked = (GUIButton btn, object obj) =>
{
targetForce += 1.0f;
item.NewComponentEvent(this, true, false);
return true;
};
}
public float CurrentVolume
@@ -80,7 +98,7 @@ namespace Barotrauma.Items.Components
voltage = 0.0f;
}
public override void DrawHUD(SpriteBatch spriteBatch, Character character)
{
//isActive = true;
@@ -93,18 +111,7 @@ namespace Barotrauma.Items.Components
//GUI.DrawRectangle(spriteBatch, new Rectangle(x, y, width, height), Color.Black, true);
spriteBatch.DrawString(GUI.Font, "Force: " + (int)(targetForce) + " %", new Vector2(GuiFrame.Rect.X + 30, GuiFrame.Rect.Y + 30), Color.White);
if (GUI.DrawButton(spriteBatch, new Rectangle(GuiFrame.Rect.X + 280, GuiFrame.Rect.Y + 80, 40, 40), "-", true))
{
targetForce -= 1.0f;
item.NewComponentEvent(this, true, false);
}
if (GUI.DrawButton(spriteBatch, new Rectangle(GuiFrame.Rect.X + 280, GuiFrame.Rect.Y + 30, 40, 40), "+", true))
{
targetForce += 1.0f;
item.NewComponentEvent(this, true, false);
}
}
public override void UpdateBroken(float deltaTime, Camera cam)

View File

@@ -286,7 +286,7 @@ namespace Barotrauma
}
public Item(Rectangle newRect, ItemPrefab itemPrefab, Submarine submarine)
: base(submarine)
: base(itemPrefab, submarine)
{
prefab = itemPrefab;
@@ -487,7 +487,8 @@ namespace Barotrauma
public void ApplyStatusEffect(StatusEffect effect, ActionType type, float deltaTime, Character character = null)
{
if (condition == 0.0f && effect.type != ActionType.OnBroken) return;
if (effect.type != type) return;
bool hasTargets = (effect.TargetNames == null);
Item[] containedItems = ContainedItems;
@@ -501,10 +502,10 @@ namespace Barotrauma
List<IPropertyObject> targets = new List<IPropertyObject>();
if (containedItems!=null)
if (containedItems != null)
{
if (effect.Targets.HasFlag(StatusEffect.TargetType.Contained))
{
{
foreach (Item containedItem in containedItems)
{
if (containedItem == null) continue;
@@ -528,9 +529,14 @@ namespace Barotrauma
}
}
if (!hasTargets) return;
if (effect.Targets.HasFlag(StatusEffect.TargetType.Hull) && CurrentHull != null)
{
targets.Add(CurrentHull);
}
if (effect.Targets.HasFlag(StatusEffect.TargetType.This))
{
foreach (var pobject in AllPropertyObjects)
@@ -550,7 +556,7 @@ namespace Barotrauma
// effect.Apply(type, deltaTime, container);
// //container.ApplyStatusEffect(effect, type, deltaTime, container);
//}
effect.Apply(type, deltaTime, this, targets);
}
@@ -575,7 +581,10 @@ namespace Barotrauma
public override void Update(Camera cam, float deltaTime)
{
{
ApplyStatusEffects(ActionType.Always, deltaTime, null);
foreach (ItemComponent ic in components)
{
if (ic.Parent != null) ic.IsActive = ic.Parent.IsActive;
@@ -1210,7 +1219,7 @@ namespace Barotrauma
element.Add(new XAttribute("name", prefab.Name),
new XAttribute("ID", ID));
if (prefab.ResizeHorizontal || prefab.ResizeVertical)
if (ResizeHorizontal || ResizeVertical)
{
element.Add(new XAttribute("rect",
(int)(rect.X - Submarine.HiddenSubPosition.X) + "," +

View File

@@ -116,11 +116,13 @@ namespace Barotrauma
if (!fireSources[i].CheckOverLap(fireSources[j])) continue;
fireSources[j].position.X = Math.Min(fireSources[i].position.X, fireSources[j].position.X);
float leftEdge = Math.Min(fireSources[i].position.X, fireSources[j].position.X);
fireSources[j].size.X =
Math.Max(fireSources[i].position.X + fireSources[i].size.X, fireSources[j].position.X + fireSources[j].size.X)
- fireSources[j].position.X;
- leftEdge;
fireSources[j].position.X = leftEdge;
fireSources[i].Remove();
}
@@ -140,7 +142,7 @@ namespace Barotrauma
public void Update(float deltaTime)
{
float count = Rand.Range(0.0f, (float)Math.Sqrt(size.X)/3.0f);
float count = Rand.Range(0.0f, size.X/50.0f);
if (fireSoundBasic != null)
{
@@ -173,10 +175,10 @@ namespace Barotrauma
spawnPos, speed, 0.0f, hull);
if (particle == null) continue;
if (Rand.Int(20) == 1) particle.OnChangeHull = OnChangeHull;
particle.Size *= MathHelper.Clamp(size.X/100.0f * Math.Max(hull.Oxygen/hull.FullVolume, 0.4f), 0.5f, 4.0f);
particle.Size *= MathHelper.Clamp(size.X/60.0f * Math.Max(hull.Oxygen/hull.FullVolume, 0.4f), 0.5f, 3.0f);
if (size.X < 100.0f) continue;
@@ -218,7 +220,7 @@ namespace Barotrauma
if (particleHull.FireSources.Find(fs => pos.X > fs.position.X-100.0f && pos.X < fs.position.X+fs.size.X+100.0f)!=null) return;
new FireSource(new Vector2(pos.X, particleHull.Rect.Y-particleHull.Rect.Height + 5.0f));
new FireSource(new Vector2(pos.X, particleHull.WorldRect.Y-particleHull.Rect.Height + 5.0f));
}
private void DamageCharacters(float deltaTime)

View File

@@ -20,15 +20,15 @@ namespace Barotrauma
//private Sound waterSound;
//a value between 0.0f-1.0f (0.0 = closed, 1.0f = open)
float open;
private float open;
//the force of the water flow which is exerted on physics bodies
Vector2 flowForce;
private Vector2 flowForce;
Hull flowTargetHull;
private Hull flowTargetHull;
float higherSurface;
float lowerSurface;
private float higherSurface;
private float lowerSurface;
public float Open
@@ -39,11 +39,6 @@ namespace Barotrauma
public Door ConnectedDoor;
//public Vector2 FlowForce
//{
// get { return flowForce*soundVolume; }
//}
public Vector2 LerpedFlowForce
{
get { return lerpedFlowForce; }
@@ -64,6 +59,20 @@ namespace Barotrauma
}
}
public override Rectangle Rect
{
get
{
return base.Rect;
}
set
{
base.Rect = value;
FindHulls();
}
}
public Gap(MapEntityPrefab prefab, Rectangle rectangle)
: this (rectangle, Submarine.Loaded)
{ }
@@ -73,7 +82,7 @@ namespace Barotrauma
{ }
public Gap(Rectangle newRect, bool isHorizontal, Submarine submarine)
: base (submarine)
: base (MapEntityPrefab.list.Find(m=> m.Name == "Gap"), submarine)
{
rect = newRect;
linkedTo = new ObservableCollection<MapEntity>();
@@ -154,9 +163,12 @@ namespace Barotrauma
if (GameMain.DebugDraw)
{
Vector2 center = new Vector2(WorldRect.X + rect.Width / 2.0f, -(WorldRect.Y - rect.Height/ 2.0f));
GUI.DrawLine(sb, center, center + flowForce/10.0f, Color.Red);
GUI.DrawLine(sb, center + Vector2.One * 5.0f, center + lerpedFlowForce / 10.0f + Vector2.One * 5.0f, Color.Orange);
GUI.DrawLine(sb, center, center + new Vector2(flowForce.X, -flowForce.Y)/10.0f, Color.Red);
GUI.DrawLine(sb, center + Vector2.One * 5.0f, center + new Vector2(lerpedFlowForce.X, -lerpedFlowForce.Y) / 10.0f + Vector2.One * 5.0f, Color.Orange);
}
if (!editing || !ShowGaps) return;
@@ -166,34 +178,21 @@ namespace Barotrauma
GUI.DrawRectangle(sb, new Rectangle(WorldRect.X, -WorldRect.Y, rect.Width, rect.Height), clr * 0.5f, true);
if (isHorizontal)
for (int i = 0; i < linkedTo.Count; i++)
{
for (int i = 0; i < linkedTo.Count; i++ )
{
if (linkedTo[i].Rect.Center.X > rect.Center.X)
{
GUI.DrawRectangle(sb, new Rectangle(WorldRect.Right, -WorldRect.Y, 10, rect.Height), Color.Green * 0.3f, true);
}
else
{
GUI.DrawRectangle(sb, new Rectangle(WorldRect.X - 10, -WorldRect.Y, 10, rect.Height), Color.Green * 0.3f, true);
}
}
}
else
{
for (int i = 0; i < linkedTo.Count; i++)
{
if (linkedTo[i].Rect.Y - linkedTo[i].Rect.Height / 2.0f > rect.Y-rect.Height/2.0f)
{
GUI.DrawRectangle(sb, new Rectangle(WorldRect.X, -WorldRect.Y - 10, rect.Width, 10), Color.Green * 0.3f, true);
}
else
{
GUI.DrawRectangle(sb, new Rectangle(WorldRect.X, -WorldRect.Y + rect.Height, rect.Width, 10), Color.Green * 0.3f, true);
}
}
}
Vector2 dir = isHorizontal ?
new Vector2(Math.Sign(linkedTo[i].Rect.Center.X - rect.Center.X), 0.0f)
: new Vector2(0.0f, Math.Sign((linkedTo[i].Rect.Y - linkedTo[i].Rect.Height / 2.0f) - (rect.Y - rect.Height / 2.0f)));
Vector2 arrowPos = new Vector2(WorldRect.Center.X, -(WorldRect.Y - WorldRect.Height / 2));
arrowPos += new Vector2(dir.X * (WorldRect.Width / 2 + 10), dir.Y * (WorldRect.Height / 2 + 10));
GUI.Arrow.Draw(sb,
arrowPos,
clr * 0.8f,
GUI.Arrow.Origin, MathUtils.VectorToAngle(dir) + MathHelper.PiOver2,
isHorizontal ? new Vector2(rect.Height / 16.0f, 1.0f) : new Vector2(rect.Width / 16.0f, 1.0f));
}
if (isSelected)
{
@@ -288,6 +287,25 @@ namespace Barotrauma
}
}
if (flowTargetHull != null && lerpedFlowForce != Vector2.Zero)
{
foreach (Character character in Character.CharacterList)
{
if (character.AnimController.CurrentHull != flowTargetHull) continue;
foreach (Limb limb in character.AnimController.Limbs)
{
if (!limb.inWater) continue;
float dist = Vector2.Distance(limb.WorldPosition, WorldPosition);
if (dist > lerpedFlowForce.Length()) continue;
limb.body.ApplyForce(lerpedFlowForce / dist/10.0f);
}
}
}
}
@@ -444,7 +462,7 @@ namespace Barotrauma
if (open > 0.0f)
{
if (hull1.Volume>hull1.FullVolume && hull2.Volume>hull2.FullVolume)
if (hull1.Volume > hull1.FullVolume - Hull.MaxCompress && hull2.Volume > hull2.FullVolume - Hull.MaxCompress)
{
float avgLethality = (hull1.LethalPressure + hull2.LethalPressure) / 2.0f;
hull1.LethalPressure = avgLethality;
@@ -497,21 +515,31 @@ namespace Barotrauma
lowerSurface = rect.Y;
if (hull1.Volume < hull1.FullVolume - Hull.MaxCompress &&
hull1.Surface > -rect.Y)
hull1.Surface < rect.Y)
{
float vel = (rect.Y + hull1.Surface) * 0.03f;
if (rect.X > hull1.Rect.X + hull1.Rect.Width / 2.0f)
{
float vel = ((rect.Y - rect.Height / 2) - (hull1.Surface + hull1.WaveY[hull1.WaveY.Length - 1])) * 0.1f;
hull1.WaveVel[hull1.WaveY.Length - 1] += vel;
hull1.WaveVel[hull1.WaveY.Length - 2] += vel;
}
else
{
float vel = ((rect.Y - rect.Height / 2) - (hull1.Surface + hull1.WaveY[0])) * 0.1f;
hull1.WaveVel[0] += vel;
hull1.WaveVel[1] += vel;
}
}
else
{
hull1.LethalPressure += (Submarine.Loaded != null && Submarine.Loaded.AtDamageDepth) ? 100.0f * deltaTime : 10.0f * deltaTime;
}
}
else
{
@@ -523,7 +551,12 @@ namespace Barotrauma
{
flowForce = new Vector2(0.0f, delta);
}
if (hull1.Volume >= hull1.FullVolume - Hull.MaxCompress)
{
hull1.LethalPressure += (Submarine.Loaded != null && Submarine.Loaded.AtDamageDepth) ? 100.0f * deltaTime : 10.0f * deltaTime;
}
}
}
private void UpdateOxygen()

View File

@@ -12,7 +12,7 @@ using Lidgren.Network;
namespace Barotrauma
{
class Hull : MapEntity
class Hull : MapEntity, IPropertyObject
{
public static List<Hull> hullList = new List<Hull>();
private static EntityGrid entityGrid;
@@ -20,7 +20,7 @@ namespace Barotrauma
public static bool ShowHulls = true;
public static bool EditWater, EditFire;
public static WaterRenderer renderer;
private List<FireSource> fireSources;
@@ -37,7 +37,11 @@ namespace Barotrauma
//how much excess water the room can contain (= more than the volume of the room)
public const float MaxCompress = 10000f;
public readonly Dictionary<string, PropertyDescriptor> properties;
public readonly Dictionary<string, ObjectProperty> properties;
public Dictionary<string, ObjectProperty> ObjectProperties
{
get { return properties; }
}
private float lethalPressure;
@@ -71,6 +75,21 @@ namespace Barotrauma
}
}
public override Rectangle Rect
{
get
{
return base.Rect;
}
set
{
base.Rect = value;
Item.UpdateHulls();
Gap.UpdateHulls();
}
}
public override bool IsLinkable
{
get { return true; }
@@ -148,13 +167,13 @@ namespace Barotrauma
}
public Hull(MapEntityPrefab prefab, Rectangle rectangle)
: this (rectangle, Submarine.Loaded)
: this (prefab, rectangle, Submarine.Loaded)
{
}
public Hull(Rectangle rectangle, Submarine submarine)
: base (submarine)
public Hull(MapEntityPrefab prefab, Rectangle rectangle, Submarine submarine)
: base (prefab, submarine)
{
rect = rectangle;
@@ -162,9 +181,7 @@ namespace Barotrauma
fireSources = new List<FireSource>();
properties = TypeDescriptor.GetProperties(GetType())
.Cast<PropertyDescriptor>()
.ToDictionary(pr => pr.Name);
properties = ObjectProperty.GetProperties(this);
int arraySize = (rectangle.Width / WaveWidth + 1);
waveY = new float[arraySize];
@@ -434,11 +451,6 @@ namespace Barotrauma
update = false;
}
}
else
{
LethalPressure += ( Submarine.Loaded!=null && Submarine.Loaded.AtDamageDepth) ? 100.0f*deltaTime : 10.0f * deltaTime;
}
}
public void HandleItems(float deltaTime, Item body)
@@ -720,7 +732,7 @@ namespace Barotrauma
int.Parse(element.Attribute("height").Value));
}
Hull h = new Hull(rect, submarine);
Hull h = new Hull(MapEntityPrefab.list.Find(m => m.Name == "Hull"), rect, submarine);
h.volume = ToolBox.GetAttributeFloat(element, "pressure", 0.0f);

View File

@@ -2,6 +2,7 @@
using System.IO;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;
namespace Barotrauma
{
@@ -25,20 +26,20 @@ namespace Barotrauma
get { return waterTexture; }
}
public WaterRenderer(GraphicsDevice graphicsDevice)
public WaterRenderer(GraphicsDevice graphicsDevice, ContentManager content)
{
#if WINDOWS
byte[] bytecode = File.ReadAllBytes("Content/watershader.mgfx");
waterEffect = content.Load<Effect>("watershader");
#endif
#if LINUX
byte[] bytecode = File.ReadAllBytes("Content/watershader_opengl.mgfx");
#endif
waterEffect = new Effect(graphicsDevice, bytecode);
waterEffect = content.Load<Effect>("watershader_opengl");
#endif
waterTexture = TextureLoader.FromFile("Content/waterbump.png");
waterEffect.Parameters["xWaveWidth"].SetValue(0.05f);
waterEffect.Parameters["xWaveHeight"].SetValue(0.05f);
#if WINDOWS
//waterEffect.Parameters["xTexture"].SetValue(waterTexture);
#endif

View File

@@ -23,7 +23,9 @@ namespace Barotrauma
protected static Vector2 selectionSize = Vector2.Zero;
protected static Vector2 startMovingPos = Vector2.Zero;
private MapEntityPrefab prefab;
protected List<ushort> linkedToID;
//observable collection because some entities may need to be notified when the collection is modified
@@ -66,6 +68,9 @@ namespace Barotrauma
//the position and dimensions of the entity
protected Rectangle rect;
private static bool resizing;
private int resizeDirX, resizeDirY;
public virtual Rectangle Rect {
get { return rect; }
@@ -139,12 +144,24 @@ namespace Barotrauma
set { isSelected = value; }
}
protected bool ResizeHorizontal
{
get { return prefab == null ? false : prefab.ResizeHorizontal; }
}
protected bool ResizeVertical
{
get { return prefab == null ? false : prefab.ResizeVertical; }
}
public virtual string Name
{
get { return ""; }
}
public MapEntity(Submarine submarine) : base(submarine) { }
public MapEntity(MapEntityPrefab prefab, Submarine submarine) : base(submarine)
{
this.prefab = prefab;
}
public virtual void Move(Vector2 amount)
{
@@ -232,6 +249,12 @@ namespace Barotrauma
/// </summary>
public static void UpdateSelecting(Camera cam)
{
if (resizing)
{
if (selectedList.Count == 0) resizing = false;
return;
}
foreach (MapEntity e in mapEntityList)
{
e.isHighlighted = false;
@@ -245,7 +268,7 @@ namespace Barotrauma
}
if (GUIComponent.MouseOn != null || !PlayerInput.MouseInsideWindow) return;
if (MapEntityPrefab.Selected != null)
{
selectionPos = Vector2.Zero;
@@ -412,6 +435,11 @@ namespace Barotrauma
if (selectedList.Count == 1)
{
selectedList[0].DrawEditing(spriteBatch, cam);
if (selectedList[0].ResizeHorizontal || selectedList[0].ResizeVertical)
{
selectedList[0].DrawResizing(spriteBatch, cam);
}
}
else
{
@@ -443,6 +471,89 @@ namespace Barotrauma
public virtual void DrawEditing(SpriteBatch spriteBatch, Camera cam) {}
private void DrawResizing(SpriteBatch spriteBatch, Camera cam)
{
isHighlighted = true;
int startX = ResizeHorizontal ? -1 : 0;
int StartY = ResizeVertical ? -1 : 0;
for (int x = startX; x < 2; x += 2)
{
for (int y = StartY; y < 2; y += 2)
{
Vector2 handlePos = cam.WorldToScreen(Position + new Vector2(x * (rect.Width * 0.5f + 5), y * (rect.Height * 0.5f + 5)));
bool highlighted = Vector2.Distance(PlayerInput.MousePosition, handlePos)<5.0f;
GUI.DrawRectangle(spriteBatch, handlePos - new Vector2(3.0f, 3.0f), new Vector2(6.0f, 6.0f), Color.White * (highlighted ? 1.0f : 0.6f), true);
if (highlighted)
{
if (PlayerInput.LeftButtonDown())
{
selectionPos = Vector2.Zero;
resizeDirX = x;
resizeDirY = y;
resizing = true;
}
}
}
}
if (resizing)
{
Vector2 placePosition = new Vector2(rect.X, rect.Y);
Vector2 placeSize = new Vector2(rect.Width, rect.Height);
Vector2 mousePos = Submarine.MouseToWorldGrid(cam);
if (resizeDirX >0)
{
mousePos.X = Math.Max(mousePos.X, rect.X + Submarine.GridSize.X);
placeSize.X = mousePos.X - placePosition.X;
}
else if (resizeDirX <0)
{
mousePos.X = Math.Min(mousePos.X, rect.Right - Submarine.GridSize.X);
placeSize.X = (placePosition.X + placeSize.X)-mousePos.X;
placePosition.X = mousePos.X;
}
if (resizeDirY < 0)
{
mousePos.Y = Math.Min(mousePos.Y, rect.Y - Submarine.GridSize.Y);
placeSize.Y = placePosition.Y-mousePos.Y;
}
else if (resizeDirY > 0)
{
mousePos.Y = Math.Max(mousePos.Y, rect.Y - rect.Height + Submarine.GridSize.X);
placeSize.Y = mousePos.Y - (rect.Y - rect.Height);
placePosition.Y = mousePos.Y;
}
if ((int)placePosition.X != rect.X || (int)placePosition.Y != rect.Y || (int)placeSize.X != rect.Width || (int)placeSize.Y != rect.Height)
{
Rect = new Rectangle((int)placePosition.X, (int)placePosition.Y, (int)placeSize.X, (int)placeSize.Y);
}
if (!PlayerInput.LeftButtonHeld())
{
resizing = false;
}
//if (resizeHorizontal) placeSize.X = position.X - placePosition.X;
//if (resizeVertical) placeSize.Y = placePosition.Y - position.Y;
//Rectangle newRect = Submarine.AbsRect(placePosition, placeSize);
//newRect.Width = (int)Math.Max(newRect.Width, Submarine.GridSize.X);
//newRect.Height = (int)Math.Max(newRect.Height, Submarine.GridSize.Y);
}
}
public static List<MapEntity> FindMapEntities(Vector2 pos)
{
List<MapEntity> foundEntities = new List<MapEntity>();
@@ -518,13 +629,6 @@ namespace Barotrauma
{
mapEntityList[i].OnMapLoaded();
}
//mapEntityList.Sort((x, y) =>
//{
// return x.Name.CompareTo(y.Name);
//});
}

View File

@@ -142,7 +142,7 @@ namespace Barotrauma
}
public Structure(Rectangle rectangle, StructurePrefab sp, Submarine submarine)
: base(submarine)
: base(sp, submarine)
{
if (rectangle.Width == 0 || rectangle.Height == 0) return;

View File

@@ -511,17 +511,17 @@ namespace Barotrauma
return true;
}
public static bool SaveCurrent(string fileName)
public static bool SaveCurrent(string filePath)
{
if (loaded==null)
{
loaded = new Submarine(fileName);
loaded = new Submarine(filePath);
// return;
}
loaded.filePath = SavePath + System.IO.Path.DirectorySeparatorChar + fileName;
loaded.filePath = filePath;
return loaded.SaveAs(SavePath+System.IO.Path.DirectorySeparatorChar+fileName);
return loaded.SaveAs(filePath);
}
public void CheckForErrors()
@@ -590,7 +590,7 @@ namespace Barotrauma
{
try
{
filePaths.AddRange(Directory.GetDirectories(subDirectory));
filePaths.AddRange(Directory.GetFiles(subDirectory).ToList());
}
catch (Exception e)
{
@@ -604,6 +604,8 @@ namespace Barotrauma
//Map savedMap = new Map(mapPath);
SavedSubmarines.Add(new Submarine(path));
}
if (GameMain.NetLobbyScreen!=null) GameMain.NetLobbyScreen.UpdateSubList();
}
private XDocument OpenDoc(string file)
@@ -629,12 +631,16 @@ namespace Barotrauma
if (extension == ".sub")
{
Stream stream = SaveUtil.DecompressFiletoStream(file);
if (stream == null)
Stream stream = null;
try
{
DebugConsole.ThrowError("Loading submarine ''" + file + "'' failed!");
return null;
stream = SaveUtil.DecompressFiletoStream(file);
}
catch (Exception e)
{
DebugConsole.ThrowError("Loading submarine ''" + file + "'' failed!", e);
return null;
}
try
{
@@ -713,37 +719,42 @@ namespace Barotrauma
}
}
Vector2 topLeft = new Vector2(Hull.hullList[0].Rect.X, Hull.hullList[0].Rect.Y);
Vector2 bottomRight = new Vector2(Hull.hullList[0].Rect.X, Hull.hullList[0].Rect.Y);
foreach (Hull hull in Hull.hullList)
Vector2 center = Vector2.Zero;
if (Hull.hullList.Any())
{
if (hull.Rect.X < topLeft.X) topLeft.X = hull.Rect.X;
if (hull.Rect.Y > topLeft.Y) topLeft.Y = hull.Rect.Y;
if (hull.Rect.Right > bottomRight.X) bottomRight.X = hull.Rect.Right;
if (hull.Rect.Y - hull.Rect.Height < bottomRight.Y) bottomRight.Y = hull.Rect.Y - hull.Rect.Height;
}
Vector2 center = (topLeft + bottomRight) / 2.0f;
center.X -= center.X % GridSize.X;
center.Y -= center.Y % GridSize.Y;
foreach (Item item in Item.ItemList)
{
var wire = item.GetComponent<Items.Components.Wire>();
if (wire == null) continue;
for (int i = 0; i < wire.Nodes.Count; i++)
Vector2 topLeft = new Vector2(Hull.hullList[0].Rect.X, Hull.hullList[0].Rect.Y);
Vector2 bottomRight = new Vector2(Hull.hullList[0].Rect.X, Hull.hullList[0].Rect.Y);
foreach (Hull hull in Hull.hullList)
{
wire.Nodes[i] -= center;
}
}
if (hull.Rect.X < topLeft.X) topLeft.X = hull.Rect.X;
if (hull.Rect.Y > topLeft.Y) topLeft.Y = hull.Rect.Y;
for (int i = 0; i < MapEntity.mapEntityList.Count; i++)
{
if (MapEntity.mapEntityList[i].Submarine == null) continue;
if (hull.Rect.Right > bottomRight.X) bottomRight.X = hull.Rect.Right;
if (hull.Rect.Y - hull.Rect.Height < bottomRight.Y) bottomRight.Y = hull.Rect.Y - hull.Rect.Height;
}
center = (topLeft + bottomRight) / 2.0f;
center.X -= center.X % GridSize.X;
center.Y -= center.Y % GridSize.Y;
foreach (Item item in Item.ItemList)
{
var wire = item.GetComponent<Items.Components.Wire>();
if (wire == null) continue;
for (int i = 0; i < wire.Nodes.Count; i++)
{
wire.Nodes[i] -= center;
}
}
for (int i = 0; i < MapEntity.mapEntityList.Count; i++)
{
if (MapEntity.mapEntityList[i].Submarine == null) continue;
MapEntity.mapEntityList[i].Move(-center);
MapEntity.mapEntityList[i].Move(-center);
}
}
subBody = new SubmarineBody(this);

View File

@@ -226,25 +226,32 @@ namespace Barotrauma
if (dist > 1000.0f)
{
Vector2 moveAmount = ConvertUnits.ToSimUnits((Vector2)targetPosition) - body.Position;
Vector2 displayerMoveAmount = ConvertUnits.ToDisplayUnits(moveAmount);
Vector2 displayMoveAmount = ConvertUnits.ToDisplayUnits(moveAmount);
body.SetTransform(body.Position + moveAmount, 0.0f);
if (Character.Controlled != null) Character.Controlled.CursorPosition += displayerMoveAmount;
if (Character.Controlled != null) Character.Controlled.CursorPosition += displayMoveAmount;
GameMain.GameScreen.Cam.Position += displayerMoveAmount;
GameMain.GameScreen.Cam.UpdateTransform();
GameMain.GameScreen.Cam.Position += displayMoveAmount;
if (GameMain.GameScreen.Cam.TargetPos!=Vector2.Zero) GameMain.GameScreen.Cam.TargetPos += displayMoveAmount;
GameMain.GameScreen.Cam.UpdateTransform(false);
submarine.SetPrevTransform(submarine.Position);
submarine.UpdateTransform();
targetPosition = null;
}
else if (dist > 50.0f)
{
Vector2 moveAmount = Vector2.Normalize((Vector2)targetPosition - Position);
moveAmount *= ConvertUnits.ToSimUnits(Math.Min(dist, 100.0f));
Vector2 displayerMoveAmount = ConvertUnits.ToDisplayUnits(moveAmount);
Vector2 displayMoveAmount = ConvertUnits.ToDisplayUnits(moveAmount);
body.SetTransform(body.Position + moveAmount * deltaTime, 0.0f);
GameMain.GameScreen.Cam.Position += displayerMoveAmount * deltaTime;
if (Character.Controlled != null) Character.Controlled.CursorPosition += displayerMoveAmount;
GameMain.GameScreen.Cam.Position += displayMoveAmount * deltaTime;
if (GameMain.GameScreen.Cam.TargetPos != Vector2.Zero) GameMain.GameScreen.Cam.TargetPos += displayMoveAmount;
if (Character.Controlled != null) Character.Controlled.CursorPosition += displayMoveAmount;
//GameMain.GameScreen.Cam.UpdateTransform(false);
}
else
{

View File

@@ -96,7 +96,7 @@ namespace Barotrauma
}
public WayPoint(Rectangle newRect, Submarine submarine)
: base (submarine)
: base (null, submarine)
{
rect = newRect;
linkedTo = new ObservableCollection<MapEntity>();

View File

@@ -1,70 +1,313 @@
using Lidgren.Network;
using System;
using System.IO;
using System.Text.RegularExpressions;
using System.Xml;
using System.Xml.Linq;
namespace Barotrauma.Networking
{
class FileStreamReceiver
class FileStreamReceiver : IDisposable
{
private NetClient s_client;
private ulong s_length;
private ulong s_received;
private FileStream s_writeStream;
private int s_timeStarted;
const int MaxFileSize = 1000000;
public delegate void OnFinished(FileStreamReceiver fileStreamReceiver);
private OnFinished onFinished;
private NetClient client;
private ulong length;
private ulong received;
private FileStream writeStream;
private int timeStarted;
private string downloadFolder;
private FileTransferMessageType fileType;
public string FileName
{
get;
private set;
}
public ulong FileSize
{
get { return length; }
}
public ulong Received
{
get { return received; }
}
public FileTransferMessageType FileType
{
get { return fileType; }
}
public FileTransferStatus Status
{
get;
private set;
}
public string ErrorMessage
{
get;
private set;
}
public float BytesPerSecond
{
get;
private set;
}
public FileStreamReceiver(NetClient client)
public float Progress
{
s_client = client;
get { return (float)received / (float)length; }
}
public FileStreamReceiver(NetClient client, string filePath, FileTransferMessageType fileType, OnFinished onFinished)
{
this.client = client;
this.downloadFolder = filePath;
this.fileType = fileType;
this.onFinished = onFinished;
Status = FileTransferStatus.NotStarted;
}
public void ReadMessage(NetIncomingMessage inc)
{
int chunkLen = inc.LengthBytes;
if (s_length == 0)
try
{
s_length = inc.ReadUInt64();
string filename = inc.ReadString();
s_writeStream = new FileStream(filename, FileMode.Create, FileAccess.Write, FileShare.None);
s_timeStarted = Environment.TickCount;
TryReadMessage(inc);
}
catch (Exception e)
{
ErrorMessage = "Error while receiving file ''"+FileName+"'' {"+e.Message+"}";
DeleteFile();
if (onFinished != null) onFinished(this);
}
}
private bool ValidateInitialData(byte type, string fileName, ulong fileSize)
{
if (fileSize > MaxFileSize)
{
ErrorMessage = "File too large (" + MathUtils.GetBytesReadable((long)fileSize) + ")";
return false;
}
if (type != (byte)fileType)
{
ErrorMessage = "Unexpected file type ''" + type + "'' (expected " + fileType + ")";
return false;
}
if (!Regex.Match(fileName, @"^[\w\- ]+[\w\-. ]*$").Success)
{
ErrorMessage = "Illegal characters in file name ''" + fileName + "''";
return false;
}
switch (type)
{
case (byte)FileTransferMessageType.Submarine:
if (Path.GetExtension(fileName) != ".sub")
{
ErrorMessage = "Wrong file extension ''" + Path.GetExtension(fileName) + "''! (Expected .sub)";
return false;
}
break;
}
return true;
}
public void DeleteFile()
{
if (FileName == null) return;
string file = Path.Combine(downloadFolder, FileName);
if (writeStream!=null)
{
writeStream.Flush();
writeStream.Close();
writeStream.Dispose();
writeStream = null;
}
Status = FileTransferStatus.Canceled;
if (File.Exists(file))
{
try
{
File.Delete(file);
}
catch (Exception e)
{
DebugConsole.ThrowError("Couldn't delete file ''" + file + "''!", e);
}
}
}
private void TryReadMessage(NetIncomingMessage inc)
{
if (Status == FileTransferStatus.Error ||
Status == FileTransferStatus.Finished ||
Status == FileTransferStatus.Canceled) return;
byte transferMessageType = inc.ReadByte();
//int chunkLen = inc.LengthBytes;
if (length == 0)
{
if (transferMessageType != (byte)FileTransferMessageType.Initiate) return;
if (!string.IsNullOrWhiteSpace(downloadFolder) && !Directory.Exists(downloadFolder))
{
Directory.CreateDirectory(downloadFolder);
}
byte fileTypeByte = inc.ReadByte();
length = inc.ReadUInt64();
FileName = inc.ReadString();
if (!ValidateInitialData(fileTypeByte, FileName, length))
{
Status = FileTransferStatus.Error;
DeleteFile();
if (onFinished != null) onFinished(this);
return;
}
writeStream = new FileStream(Path.Combine(downloadFolder, FileName), FileMode.Create, FileAccess.Write, FileShare.None);
timeStarted = Environment.TickCount;
Status = FileTransferStatus.NotStarted;
return;
}
byte[] all = inc.ReadBytes(inc.LengthBytes);
s_received += (ulong)all.Length;
s_writeStream.Write(all, 0, all.Length);
if (received + (ulong)inc.LengthBytes > length*1.1f)
{
ErrorMessage = "Receiving more data than expected (> " + MathUtils.GetBytesReadable((long)(received + (ulong)inc.LengthBytes)) + ")";
Status = FileTransferStatus.Error;
if (onFinished != null) onFinished(this);
return;
}
byte[] all = inc.ReadBytes(inc.LengthBytes - inc.PositionInBytes);
received += (ulong)all.Length;
writeStream.Write(all, 0, all.Length);
int passed = Environment.TickCount - s_timeStarted;
int passed = Environment.TickCount - timeStarted;
float psec = passed / 1000.0f;
BytesPerSecond = s_received / psec;
BytesPerSecond = received / psec;
Status = FileTransferStatus.Receiving;
if (s_received >= s_length)
{
s_writeStream.Flush();
s_writeStream.Close();
s_writeStream.Dispose();
Status = FileTransferStatus.Finished;
if (received >= length)
{
writeStream.Flush();
writeStream.Close();
writeStream.Dispose();
writeStream = null;
Status = IsReceivedFileValid() ? FileTransferStatus.Finished : FileTransferStatus.Error;
if (onFinished!=null) onFinished(this);
if (Status == FileTransferStatus.Error) DeleteFile();
Dispose();
}
}
private bool IsReceivedFileValid()
{
switch (fileType)
{
case FileTransferMessageType.Submarine:
string file = Path.Combine(downloadFolder, FileName);
Stream stream = null;
try
{
stream = SaveUtil.DecompressFiletoStream(file);
}
catch (Exception e)
{
ErrorMessage = "Loading submarine ''" + file + "'' failed! {"+ e.Message + "}";
return false;
}
if (stream == null)
{
ErrorMessage = "Decompressing submarine file''" + file + "'' failed!";
return false;
}
try
{
stream.Position = 0;
XmlReaderSettings settings = new XmlReaderSettings();
settings.DtdProcessing = DtdProcessing.Prohibit;
settings.IgnoreProcessingInstructions = true;
using (var reader = XmlReader.Create(stream, settings))
{
while (reader.Read())
{
}
}
}
catch
{
stream.Close();
stream.Dispose();
ErrorMessage = "Parsing file ''"+file+"'' failed! The file may not be a valid submarine file.";
return false;
}
stream.Close();
stream.Dispose();
break;
}
return true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (writeStream != null)
{
writeStream.Flush();
writeStream.Close();
writeStream.Dispose();
}
}
}
}

View File

@@ -1,21 +1,35 @@
using Lidgren.Network;
using System;
using System.IO;
namespace Barotrauma.Networking
{
enum FileTransferStatus
{
NotStarted, Sending, Receiving, Finished, Error
NotStarted, Sending, Receiving, Finished, Error, Canceled
}
class FileStreamSender
enum FileTransferMessageType
{
Unknown, Initiate, Submarine, Cancel
}
class FileStreamSender : IDisposable
{
public static TimeSpan MaxTransferDuration = new TimeSpan(0, 2, 0);
private FileStream inputStream;
private int sentOffset;
private int chunkLen;
private byte[] tempBuffer;
private NetConnection connection;
float waitTimer;
DateTime startingTime;
private FileTransferMessageType fileType;
public FileTransferStatus Status
{
get;
@@ -28,35 +42,84 @@ namespace Barotrauma.Networking
private set;
}
public static FileStreamSender Create(NetConnection conn, string fileName)
public string FilePath
{
if (!File.Exists(fileName))
get;
private set;
}
public float Progress
{
get { return inputStream == null ? 0.0f : (float)sentOffset / (float)inputStream.Length; }
}
public int Sent
{
get { return sentOffset; }
}
public long FileSize
{
get { return inputStream == null ? 0 : inputStream.Length; }
}
public static FileStreamSender Create(NetConnection conn, string filePath, FileTransferMessageType fileType)
{
if (!File.Exists(filePath))
{
DebugConsole.ThrowError("Sending a file failed. File ''"+fileName+"'' not found.");
DebugConsole.ThrowError("Sending a file failed. File ''"+filePath+"'' not found.");
return null;
}
return new FileStreamSender(conn, fileName);
FileStreamSender sender = null;
try
{
sender = new FileStreamSender(conn, filePath, fileType);
}
catch (Exception e)
{
DebugConsole.ThrowError("Couldn't open file ''"+filePath+"''",e);
}
return sender;
}
private FileStreamSender(NetConnection conn, string fileName)
private FileStreamSender(NetConnection conn, string filePath, FileTransferMessageType fileType)
{
connection = conn;
inputStream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read);
chunkLen = connection.Peer.Configuration.MaximumTransmissionUnit - 20;
inputStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
chunkLen = connection.Peer.Configuration.MaximumTransmissionUnit - 100;
tempBuffer = new byte[chunkLen];
sentOffset = 0;
FileName = fileName;
FilePath = filePath;
FileName = Path.GetFileName(filePath);
this.fileType = fileType;
Status = FileTransferStatus.NotStarted;
startingTime = DateTime.Now;
}
public void Update()
public void Update(float deltaTime)
{
if (inputStream == null) return;
if (inputStream == null ||
Status == FileTransferStatus.Canceled ||
Status == FileTransferStatus.Error ||
Status == FileTransferStatus.Finished) return;
if (DateTime.Now > startingTime + MaxTransferDuration)
{
CancelTransfer();
return;
}
waitTimer -= deltaTime;
if (waitTimer > 0.0f) return;
if (!connection.CanSendImmediately(NetDeliveryMethod.ReliableOrdered, 1)) return;
// send another part of the file!
@@ -70,7 +133,10 @@ namespace Barotrauma.Networking
if (sentOffset == 0)
{
// first message; send length, chunk length and file name
message = connection.Peer.CreateMessage(sendBytes + 8);
message = connection.Peer.CreateMessage(sendBytes + 8 + 1);
message.Write((byte)PacketTypes.FileStream);
message.Write((byte)FileTransferMessageType.Initiate);
message.Write((byte)fileType);
message.Write((ulong)inputStream.Length);
message.Write(Path.GetFileName(inputStream.Name));
connection.SendMessage(message, NetDeliveryMethod.ReliableOrdered, 1);
@@ -78,22 +144,44 @@ namespace Barotrauma.Networking
Status = FileTransferStatus.Sending;
}
message = connection.Peer.CreateMessage(sendBytes + 8);
message = connection.Peer.CreateMessage(sendBytes + 8 + 1);
message.Write((byte)PacketTypes.FileStream);
message.Write((byte)fileType);
message.Write(tempBuffer, 0, sendBytes);
connection.SendMessage(message, NetDeliveryMethod.ReliableOrdered, 1);
sentOffset += sendBytes;
waitTimer = connection.AverageRoundtripTime;
//Program.Output("Sent " + m_sentOffset + "/" + m_inputStream.Length + " bytes to " + m_connection);
if (remaining - sendBytes <= 0)
{
inputStream.Close();
inputStream.Dispose();
inputStream = null;
//Dispose();
Status = FileTransferStatus.Finished;
}
}
}
public void CancelTransfer()
{
Status = FileTransferStatus.Canceled;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
inputStream.Close();
inputStream.Dispose();
inputStream = null;
}
}
}

View File

@@ -4,6 +4,7 @@ using Microsoft.Xna.Framework;
using System.Collections.Generic;
using Barotrauma.Networking.ReliableMessages;
using FarseerPhysics;
using System.IO;
namespace Barotrauma.Networking
{
@@ -15,6 +16,8 @@ namespace Barotrauma.Networking
private ReliableChannel reliableChannel;
private FileStreamReceiver fileStreamReceiver;
private GUITickBox endRoundButton;
private bool connected;
@@ -35,6 +38,11 @@ namespace Barotrauma.Networking
get { return otherClients; }
}
public string ActiveFileTransferName
{
get { return (fileStreamReceiver == null || fileStreamReceiver.Status == FileTransferStatus.Finished) ? "" : fileStreamReceiver.FileName; }
}
public GameClient(string newName)
{
endRoundButton = new GUITickBox(new Rectangle(GameMain.GraphicsWidth - 170, 20, 20, 20), "End round", Alignment.TopLeft, inGameHUD);
@@ -99,7 +107,7 @@ namespace Barotrauma.Networking
NetOutgoingMessage outmsg = client.CreateMessage();
client.Start();
outmsg.WriteEnum(PacketTypes.Login);
outmsg.Write((byte)PacketTypes.Login);
outmsg.Write(myID);
outmsg.Write(password);
outmsg.Write(GameMain.Version.ToString());
@@ -221,7 +229,7 @@ namespace Barotrauma.Networking
{
// All manually sent messages are type of "Data"
case NetIncomingMessageType.Data:
byte packetType = (byte)inc.ReadEnum<PacketTypes>();
byte packetType = inc.ReadByte();
if (packetType == (byte)PacketTypes.LoggedIn)
{
myID = inc.ReadByte();
@@ -262,7 +270,7 @@ namespace Barotrauma.Networking
CanStart = true;
NetOutgoingMessage lobbyUpdateRequest = client.CreateMessage();
lobbyUpdateRequest.WriteEnum(PacketTypes.RequestNetLobbyUpdate);
lobbyUpdateRequest.Write((byte)PacketTypes.RequestNetLobbyUpdate);
client.SendMessage(lobbyUpdateRequest, NetDeliveryMethod.ReliableUnordered);
}
else if (packetType == (byte)PacketTypes.KickedOut)
@@ -445,12 +453,12 @@ namespace Barotrauma.Networking
{
if (inc.MessageType != NetIncomingMessageType.Data) continue;
byte packetType = (byte)inc.ReadEnum<PacketTypes>();
byte packetType = inc.ReadByte();
if (packetType == (byte)PacketTypes.ReliableMessage)
{
if (!reliableChannel.CheckMessage(inc)) continue;
packetType = (byte)inc.ReadEnum<PacketTypes>();
packetType = inc.ReadByte();
}
switch (packetType)
@@ -474,6 +482,35 @@ namespace Barotrauma.Networking
AddChatMessage(otherClient.name + " has joined the server", ChatMessageType.Server);
break;
case (byte)PacketTypes.RequestFile:
bool accepted = inc.ReadBoolean();
if (!accepted)
{
new GUIMessageBox("File transfer canceled", inc.ReadString());
if (fileStreamReceiver!=null)
{
fileStreamReceiver.DeleteFile();
fileStreamReceiver.Dispose();
fileStreamReceiver = null;
}
}
break;
case (byte)PacketTypes.FileStream:
if (fileStreamReceiver == null)
{
//todo: unexpected file
}
else
{
fileStreamReceiver.ReadMessage(inc);
}
break;
case (byte)PacketTypes.PlayerLeft:
byte leavingID = inc.ReadByte();
@@ -510,7 +547,7 @@ namespace Barotrauma.Networking
break;
case (byte)PacketTypes.Chatmessage:
ChatMessageType messageType = inc.ReadEnum<ChatMessageType>();
ChatMessageType messageType = (ChatMessageType)inc.ReadByte();
AddChatMessage(inc.ReadString(), messageType);
break;
@@ -678,6 +715,23 @@ namespace Barotrauma.Networking
{
base.Draw(spriteBatch);
if (fileStreamReceiver != null &&
(fileStreamReceiver.Status == FileTransferStatus.Receiving || fileStreamReceiver.Status == FileTransferStatus.NotStarted))
{
Vector2 pos = Screen.Selected == GameMain.NetLobbyScreen ?
new Vector2(GameMain.NetLobbyScreen.SubList.Rect.X, GameMain.NetLobbyScreen.SubList.Rect.Bottom+5) : new Vector2(GameMain.GraphicsWidth / 2 - 200, 10);
GUI.DrawString(spriteBatch, pos, "Downloading " + fileStreamReceiver.FileName, Color.White);
GUI.DrawString(spriteBatch, pos + Vector2.UnitX*300,
MathUtils.GetBytesReadable((long)fileStreamReceiver.Received) + " / " + MathUtils.GetBytesReadable((long)fileStreamReceiver.FileSize), Color.White);
GUI.DrawProgressBar(spriteBatch, new Vector2(pos.X, -pos.Y - 20), new Vector2(300, 15), fileStreamReceiver.Progress, Color.Green);
if (GUI.DrawButton(spriteBatch, new Rectangle((int)pos.X + 310, (int)pos.Y + 20, 100, 15), "Cancel", new Color(0.88f, 0.25f, 0.15f, 0.8f)))
{
CancelFileTransfer();
}
}
if (!GameMain.DebugDraw) return;
int width = 200, height = 300;
@@ -691,24 +745,78 @@ namespace Barotrauma.Networking
spriteBatch.DrawString(GUI.SmallFont, "Sent bytes: " + client.Statistics.SentBytes, new Vector2(x + 10, y + 75), Color.White);
spriteBatch.DrawString(GUI.SmallFont, "Sent packets: " + client.Statistics.SentPackets, new Vector2(x + 10, y + 90), Color.White);
}
public override void Disconnect()
{
NetOutgoingMessage msg = client.CreateMessage();
msg.WriteEnum(PacketTypes.PlayerLeft);
msg.Write((byte)PacketTypes.PlayerLeft);
client.SendMessage(msg, NetDeliveryMethod.ReliableUnordered);
client.Shutdown("");
GameMain.NetworkMember = null;
}
public void RequestFile(string file, FileTransferMessageType fileType)
{
if (fileStreamReceiver!=null)
{
CancelFileTransfer();
}
NetOutgoingMessage msg = client.CreateMessage();
msg.Write((byte)PacketTypes.RequestFile);
msg.Write((byte)fileType);
msg.Write(file);
client.SendMessage(msg, NetDeliveryMethod.ReliableUnordered);
fileStreamReceiver = new FileStreamReceiver(client, Path.Combine(Submarine.SavePath, "Downloaded"), fileType, OnFileReceived);
}
private void OnFileReceived(FileStreamReceiver receiver)
{
if (receiver.Status == FileTransferStatus.Error)
{
new GUIMessageBox("Error while receiving file from server", receiver.ErrorMessage, 400, 350);
receiver.DeleteFile();
}
else if (receiver.Status == FileTransferStatus.Finished)
{
new GUIMessageBox("Download finished", "File ''" + receiver.FileName + "'' was downloaded succesfully.");
switch (receiver.FileType)
{
case FileTransferMessageType.Submarine:
Submarine.Preload();
break;
}
}
fileStreamReceiver = null;
}
private void CancelFileTransfer()
{
fileStreamReceiver.DeleteFile();
fileStreamReceiver.Dispose();
fileStreamReceiver = null;
NetOutgoingMessage msg = client.CreateMessage();
msg.Write((byte)PacketTypes.RequestFile);
msg.Write((byte)FileTransferMessageType.Cancel);
client.SendMessage(msg, NetDeliveryMethod.ReliableUnordered);
}
public void Vote(VoteType voteType, object userData)
{
NetOutgoingMessage msg = client.CreateMessage();
msg.WriteEnum(PacketTypes.Vote);
msg.WriteEnum(voteType);
msg.Write((byte)PacketTypes.Vote);
msg.Write((byte)voteType);
switch (voteType)
{
@@ -729,7 +837,7 @@ namespace Barotrauma.Networking
public bool SpectateClicked(GUIButton button, object userData)
{
NetOutgoingMessage msg = client.CreateMessage();
msg.WriteEnum(PacketTypes.SpectateRequest);
msg.Write((byte)PacketTypes.SpectateRequest);
client.SendMessage(msg, NetDeliveryMethod.ReliableUnordered);
@@ -760,7 +868,7 @@ namespace Barotrauma.Networking
if (characterInfo == null) return;
NetOutgoingMessage msg = client.CreateMessage();
msg.WriteEnum(PacketTypes.CharacterInfo);
msg.Write((byte)PacketTypes.CharacterInfo);
msg.Write(characterInfo.Name);
msg.Write(characterInfo.Gender == Gender.Male);
@@ -837,8 +945,8 @@ namespace Barotrauma.Networking
(myCharacter == null || myCharacter.IsDead)) ? ChatMessageType.Dead : ChatMessageType.Default;
ReliableMessage msg = reliableChannel.CreateMessage();
msg.InnerMessage.WriteEnum(PacketTypes.Chatmessage);
msg.InnerMessage.WriteEnum(type);
msg.InnerMessage.Write((byte)PacketTypes.Chatmessage);
msg.InnerMessage.Write((byte)type);
msg.InnerMessage.Write(message);
reliableChannel.SendMessage(msg, client.ServerConnection);
@@ -848,41 +956,41 @@ namespace Barotrauma.Networking
/// sends some random data to the server (can be a networkevent or just something completely random)
/// use for debugging purposes
/// </summary>
public void SendRandomData()
{
NetOutgoingMessage msg = client.CreateMessage();
switch (Rand.Int(5))
{
case 0:
msg.WriteEnum(PacketTypes.NetworkEvent);
msg.WriteEnum(NetworkEventType.EntityUpdate);
msg.Write(Rand.Int(MapEntity.mapEntityList.Count));
break;
case 1:
msg.WriteEnum(PacketTypes.NetworkEvent);
msg.Write((byte)Enum.GetNames(typeof(NetworkEventType)).Length);
msg.Write(Rand.Int(MapEntity.mapEntityList.Count));
break;
case 2:
msg.WriteEnum(PacketTypes.NetworkEvent);
msg.WriteEnum(NetworkEventType.ComponentUpdate);
msg.Write((int)Item.ItemList[Rand.Int(Item.ItemList.Count)].ID);
msg.Write(Rand.Int(8));
break;
case 3:
msg.Write((byte)Enum.GetNames(typeof(PacketTypes)).Length);
break;
}
//public void SendRandomData()
//{
// NetOutgoingMessage msg = client.CreateMessage();
// switch (Rand.Int(5))
// {
// case 0:
// msg.WriteEnum(PacketTypes.NetworkEvent);
// msg.WriteEnum(NetworkEventType.EntityUpdate);
// msg.Write(Rand.Int(MapEntity.mapEntityList.Count));
// break;
// case 1:
// msg.WriteEnum(PacketTypes.NetworkEvent);
// msg.Write((byte)Enum.GetNames(typeof(NetworkEventType)).Length);
// msg.Write(Rand.Int(MapEntity.mapEntityList.Count));
// break;
// case 2:
// msg.WriteEnum(PacketTypes.NetworkEvent);
// msg.WriteEnum(NetworkEventType.ComponentUpdate);
// msg.Write((int)Item.ItemList[Rand.Int(Item.ItemList.Count)].ID);
// msg.Write(Rand.Int(8));
// break;
// case 3:
// msg.Write((byte)Enum.GetNames(typeof(PacketTypes)).Length);
// break;
// }
int bitCount = Rand.Int(100);
for (int i = 0; i<bitCount; i++)
{
msg.Write(Rand.Int(2)==0);
}
// int bitCount = Rand.Int(100);
// for (int i = 0; i<bitCount; i++)
// {
// msg.Write(Rand.Int(2)==0);
// }
client.SendMessage(msg, (Rand.Int(2)==0) ? NetDeliveryMethod.ReliableOrdered : NetDeliveryMethod.Unreliable);
}
// client.SendMessage(msg, (Rand.Int(2)==0) ? NetDeliveryMethod.ReliableOrdered : NetDeliveryMethod.Unreliable);
//}
}
}

View File

@@ -30,6 +30,7 @@ namespace Barotrauma.Networking
private DateTime sparseUpdateTimer;
private DateTime refreshMasterTimer;
private RestClient restClient;
private bool masterServerResponded;
private ServerLog log;
@@ -96,6 +97,8 @@ namespace Barotrauma.Networking
banList = new BanList();
LoadSettings();
//----------------------------------------
@@ -160,17 +163,21 @@ namespace Barotrauma.Networking
private void RegisterToMasterServer()
{
var client = new RestClient(NetConfig.MasterServerUrl);
if (restClient==null)
{
restClient = new RestClient(NetConfig.MasterServerUrl);
}
var request = new RestRequest("masterserver.php", Method.GET);
var request = new RestRequest("masterserver2.php", Method.GET);
request.AddParameter("action", "addserver");
request.AddParameter("servername", name);
request.AddParameter("serverport", Port);
request.AddParameter("playercount", PlayerCountToByte(ConnectedClients.Count, config.MaximumConnections));
request.AddParameter("currplayers", ConnectedClients.Count);
request.AddParameter("maxplayers", config.MaximumConnections);
request.AddParameter("password", string.IsNullOrWhiteSpace(password) ? 0 : 1);
// execute the request
RestResponse response = (RestResponse)client.Execute(request);
RestResponse response = (RestResponse)restClient.Execute(request);
if (response.StatusCode != System.Net.HttpStatusCode.OK)
{
@@ -190,12 +197,16 @@ namespace Barotrauma.Networking
private IEnumerable<object> RefreshMaster()
{
var client = new RestClient(NetConfig.MasterServerUrl);
if (restClient == null)
{
restClient = new RestClient(NetConfig.MasterServerUrl);
}
var request = new RestRequest("masterserver.php", Method.GET);
var request = new RestRequest("masterserver2.php", Method.GET);
request.AddParameter("action", "refreshserver");
request.AddParameter("gamestarted", gameStarted ? 1 : 0);
request.AddParameter("playercount", PlayerCountToByte(ConnectedClients.Count, config.MaximumConnections));
request.AddParameter("currplayers", ConnectedClients.Count);
request.AddParameter("maxplayers", config.MaximumConnections);
Log("Refreshing connection with master server...", Color.Cyan);
@@ -203,7 +214,7 @@ namespace Barotrauma.Networking
sw.Start();
masterServerResponded = false;
var restRequestHandle = client.ExecuteAsync(request, response => MasterServerCallBack(response));
var restRequestHandle = restClient.ExecuteAsync(request, response => MasterServerCallBack(response));
DateTime timeOut = DateTime.Now + new TimeSpan(0, 0, 15);
while (!masterServerResponded)
@@ -310,6 +321,8 @@ namespace Barotrauma.Networking
foreach (Client c in ConnectedClients)
{
if (c.FileStreamSender != null) UpdateFileTransfer(c, deltaTime);
c.ReliableChannel.Update(deltaTime);
}
@@ -420,7 +433,7 @@ namespace Barotrauma.Networking
// Notify the client that they have logged in
var outmsg = server.CreateMessage();
outmsg.WriteEnum(PacketTypes.LoggedIn);
outmsg.Write((byte)PacketTypes.LoggedIn);
outmsg.Write(sender.ID);
outmsg.Write(gameStarted);
outmsg.Write(gameStarted && sender.Character!=null);
@@ -445,7 +458,7 @@ namespace Barotrauma.Networking
//notify other clients about the new client
outmsg = server.CreateMessage();
outmsg.WriteEnum(PacketTypes.PlayerJoined);
outmsg.Write((byte)PacketTypes.PlayerJoined);
outmsg.Write(sender.name);
outmsg.Write(sender.ID);
@@ -474,12 +487,12 @@ namespace Barotrauma.Networking
Client dataSender = ConnectedClients.Find(c => c.Connection == inc.SenderConnection);
if (dataSender == null) return;
byte packetType = (byte)inc.ReadEnum<PacketTypes>();
byte packetType = inc.ReadByte();
if (packetType == (byte)PacketTypes.ReliableMessage)
{
if (!dataSender.ReliableChannel.CheckMessage(inc)) return;
packetType = (byte)inc.ReadEnum<PacketTypes>();
packetType = inc.ReadByte();
}
switch (packetType)
@@ -490,7 +503,7 @@ namespace Barotrauma.Networking
break;
case (byte)PacketTypes.Chatmessage:
ChatMessageType messageType = inc.ReadEnum<ChatMessageType>();
ChatMessageType messageType = (ChatMessageType)inc.ReadByte();
SendChatMessage(inc.ReadString(), messageType);
@@ -500,6 +513,48 @@ namespace Barotrauma.Networking
break;
case (byte)PacketTypes.CharacterInfo:
ReadCharacterData(inc);
break;
case (byte)PacketTypes.RequestFile:
if (!allowFileTransfers)
{
SendCancelTransferMessage(dataSender, "File transfers have been disabled by the server.");
break;
}
byte fileType = inc.ReadByte();
string fileName = fileType == (byte)FileTransferMessageType.Cancel ? "" : inc.ReadString();
switch (fileType)
{
case (byte)FileTransferMessageType.Submarine:
var requestedSubmarine = Submarine.SavedSubmarines.Find(s => s.Name == fileName);
if (requestedSubmarine==null)
{
//todo: ei voi ladata
}
else
{
if (dataSender.FileStreamSender != null) dataSender.FileStreamSender.CancelTransfer();
var fileStreamSender = FileStreamSender.Create(dataSender.Connection, requestedSubmarine.FilePath, FileTransferMessageType.Submarine);
if (fileStreamSender != null) dataSender.FileStreamSender = fileStreamSender;
}
break;
case (byte)FileTransferMessageType.Cancel:
if (dataSender.FileStreamSender != null)
{
dataSender.FileStreamSender.CancelTransfer();
}
break;
default:
DebugConsole.ThrowError("Unknown file type was requested ("+fileType+")");
break;
}
break;
case (byte)PacketTypes.ResendRequest:
@@ -511,11 +566,11 @@ namespace Barotrauma.Networking
case (byte)PacketTypes.Vote:
Voting.RegisterVote(inc, ConnectedClients);
if (Voting.AllowEndVoting && EndVoteMax > 0 &&
if (Voting.AllowEndVoting && EndVoteMax > 0 &&
((float)EndVoteCount / (float)EndVoteMax) >= EndVoteRequiredRatio)
{
Log("Ending round by votes ("+EndVoteCount+"/"+(EndVoteMax-EndVoteCount)+")", Color.Cyan);
EndButtonHit(null,null);
Log("Ending round by votes (" + EndVoteCount + "/" + (EndVoteMax - EndVoteCount) + ")", Color.Cyan);
EndButtonHit(null, null);
}
break;
case (byte)PacketTypes.RequestNetLobbyUpdate:
@@ -541,7 +596,7 @@ namespace Barotrauma.Networking
private void HandleConnectionApproval(NetIncomingMessage inc)
{
if (inc.ReadEnum<PacketTypes>() != PacketTypes.Login) return;
if ((PacketTypes)inc.ReadByte() != PacketTypes.Login) return;
DebugConsole.NewMessage("New player has joined the server", Color.White);
@@ -649,6 +704,8 @@ namespace Barotrauma.Networking
UpdateCrewFrame();
inc.SenderConnection.Approve();
refreshMasterTimer = DateTime.Now;
}
@@ -789,6 +846,14 @@ namespace Barotrauma.Networking
return false;
}
if (ConnectedClients.Any(c => c.FileStreamSender != null && c.FileStreamSender.FilePath == selectedSub.FilePath))
{
new GUIMessageBox("Couldn't start a round",
"Can't start a round while sending the selected submarine to clients. Cancel the transfers or wait for them to finish before starting.", 400, 400);
return false;
}
GameMain.ShowLoading(StartGame(selectedSub, selectedMode), false);
return true;
@@ -877,7 +942,6 @@ namespace Barotrauma.Networking
GameMain.GameScreen.Select();
AddChatMessage("Press TAB to chat. Use ''d;'' to talk to dead players and spectators, and ''player name;'' to only send the message to a specific player.", ChatMessageType.Server);
yield return CoroutineStatus.Success;
@@ -886,7 +950,7 @@ namespace Barotrauma.Networking
private NetOutgoingMessage CreateStartMessage(int seed, Submarine selectedSub, GameModePreset selectedMode)
{
NetOutgoingMessage msg = server.CreateMessage();
msg.WriteEnum(PacketTypes.StartGame);
msg.Write((byte)PacketTypes.StartGame);
msg.Write(seed);
@@ -910,7 +974,7 @@ namespace Barotrauma.Networking
if (myCharacter != null)
{
msg.Write(0);
msg.Write((byte)0);
WriteCharacterData(msg, myCharacter.Info.Name, myCharacter);
}
@@ -949,7 +1013,7 @@ namespace Barotrauma.Networking
if (ConnectedClients.Count > 0)
{
NetOutgoingMessage msg = server.CreateMessage();
msg.WriteEnum(PacketTypes.EndGame);
msg.Write((byte)PacketTypes.EndGame);
msg.Write(endMessage);
if (server.ConnectionsCount > 0)
@@ -989,7 +1053,9 @@ namespace Barotrauma.Networking
private void DisconnectClient(NetConnection senderConnection, string msg = "", string targetmsg = "")
{
Client client = ConnectedClients.Find(x => x.Connection == senderConnection);
if (client != null) DisconnectClient(client, msg, targetmsg);
if (client == null) return;
DisconnectClient(client, msg, targetmsg);
}
private void DisconnectClient(Client client, string msg = "", string targetmsg = "")
@@ -1007,14 +1073,14 @@ namespace Barotrauma.Networking
Log(msg, messageColor[(int)ChatMessageType.Server]);
NetOutgoingMessage outmsg = server.CreateMessage();
outmsg.WriteEnum(PacketTypes.KickedOut);
outmsg.Write((byte)PacketTypes.KickedOut);
outmsg.Write(targetmsg);
server.SendMessage(outmsg, client.Connection, NetDeliveryMethod.ReliableUnordered, 0);
ConnectedClients.Remove(client);
outmsg = server.CreateMessage();
outmsg.WriteEnum(PacketTypes.PlayerLeft);
outmsg.Write((byte)PacketTypes.PlayerLeft);
outmsg.Write(client.ID);
outmsg.Write(msg);
@@ -1025,9 +1091,17 @@ namespace Barotrauma.Networking
server.SendMessage(outmsg, server.Connections, NetDeliveryMethod.ReliableUnordered, 0);
}
if (client.FileStreamSender != null)
{
client.FileStreamSender.Dispose();
client.FileStreamSender = null;
}
AddChatMessage(msg, ChatMessageType.Server);
UpdateCrewFrame();
refreshMasterTimer = DateTime.Now;
}
private void UpdateCrewFrame()
@@ -1073,6 +1147,65 @@ namespace Barotrauma.Networking
}
}
private void UpdateFileTransfer(Client client, float deltaTime)
{
if (client.FileStreamSender == null) return;
var clientNameBox = GameMain.NetLobbyScreen.PlayerList.FindChild(client.name);
var clientInfo = clientNameBox.FindChild(client.FileStreamSender);
if (clientInfo == null)
{
clientNameBox.ClearChildren();
clientInfo = new GUIFrame(new Rectangle(0, 0, 180, 0), Color.Transparent, Alignment.TopRight, null, clientNameBox);
clientInfo.UserData = client.FileStreamSender;
new GUIProgressBar(new Rectangle(0, 4, 160, clientInfo.Rect.Height - 8), Color.Green, GUI.Style, 0.0f, Alignment.Left, clientInfo).IsHorizontal = true;
new GUITextBlock(new Rectangle(0, 2, 160, 0), "", GUI.Style, Alignment.TopLeft, Alignment.Left | Alignment.CenterY, clientInfo, true, GUI.SmallFont);
var cancelButton = new GUIButton(new Rectangle(20, 0, 14, 0), "X", Alignment.Right, GUI.Style, clientInfo);
cancelButton.OnClicked = (GUIButton button, object userdata) =>
{
(cancelButton.Parent.UserData as FileStreamSender).CancelTransfer();
return true;
};
}
else
{
var progressBar = clientInfo.GetChild<GUIProgressBar>();
progressBar.BarSize = client.FileStreamSender.Progress;
var progressText = clientInfo.GetChild<GUITextBlock>();
progressText.Text = client.FileStreamSender.FileName + " " +
MathUtils.GetBytesReadable(client.FileStreamSender.Sent) + " / " + MathUtils.GetBytesReadable(client.FileStreamSender.FileSize);
}
client.FileStreamSender.Update(deltaTime);
if (client.FileStreamSender.Status != FileTransferStatus.Sending &&
client.FileStreamSender.Status != FileTransferStatus.NotStarted)
{
if (client.FileStreamSender.Status == FileTransferStatus.Canceled)
{
SendCancelTransferMessage(client, "File transfer was canceled by the server.");
}
clientNameBox.RemoveChild(clientInfo);
client.FileStreamSender.Dispose();
client.FileStreamSender = null;
}
}
private void SendCancelTransferMessage(Client client, string message)
{
var outmsg = server.CreateMessage();
outmsg.Write((byte)PacketTypes.RequestFile);
outmsg.Write(false);
outmsg.Write(message);
server.SendMessage(outmsg, client.Connection, NetDeliveryMethod.ReliableUnordered);
}
public void NewTraitor(Character traitor, Character target)
{
Log(traitor.Name + " is the traitor and the target is " + target.Name, Color.Cyan);
@@ -1086,7 +1219,7 @@ namespace Barotrauma.Networking
}
NetOutgoingMessage msg = server.CreateMessage();
msg.WriteEnum(PacketTypes.Traitor);
msg.Write((byte)PacketTypes.Traitor);
msg.Write(target.Info.Name);
if (server.Connections.Count > 0)
{
@@ -1175,7 +1308,7 @@ namespace Barotrauma.Networking
try
{
NetOutgoingMessage msg = server.CreateMessage();
msg.WriteEnum(PacketTypes.VoteStatus);
msg.Write((byte)PacketTypes.VoteStatus);
Voting.WriteData(msg, ConnectedClients);
server.SendMessage(msg, server.Connections, NetDeliveryMethod.ReliableUnordered, 0);
@@ -1199,7 +1332,7 @@ namespace Barotrauma.Networking
if (server.Connections.Count == 0) return true;
NetOutgoingMessage msg = server.CreateMessage();
msg.WriteEnum(PacketTypes.UpdateNetLobby);
msg.Write((byte)PacketTypes.UpdateNetLobby);
GameMain.NetLobbyScreen.WriteData(msg);
server.SendMessage(msg, server.Connections, NetDeliveryMethod.ReliableUnordered, 0);
@@ -1275,8 +1408,8 @@ namespace Barotrauma.Networking
foreach (Client c in recipients)
{
ReliableMessage msg = c.ReliableChannel.CreateMessage();
msg.InnerMessage.WriteEnum(PacketTypes.Chatmessage);
msg.InnerMessage.WriteEnum(type);
msg.InnerMessage.Write((byte)PacketTypes.Chatmessage);
msg.InnerMessage.Write((byte)type);
msg.InnerMessage.Write(message);
c.ReliableChannel.SendMessage(msg, c.Connection);
@@ -1343,7 +1476,7 @@ namespace Barotrauma.Networking
if (items == null || !items.Any()) return;
NetOutgoingMessage message = server.CreateMessage();
message.WriteEnum(PacketTypes.NewItem);
message.Write((byte)PacketTypes.NewItem);
Item.Spawner.FillNetworkData(message, items, inventories);
@@ -1466,13 +1599,13 @@ namespace Barotrauma.Networking
switch (Rand.Int(5))
{
case 0:
msg.WriteEnum(PacketTypes.NetworkEvent);
msg.Write(Rand.Int(Enum.GetNames(typeof(NetworkEventType)).Length));
msg.Write(Rand.Int(MapEntity.mapEntityList.Count));
msg.Write((byte)PacketTypes.NetworkEvent);
msg.Write((byte)Rand.Int(Enum.GetNames(typeof(NetworkEventType)).Length));
msg.Write((ushort)Rand.Int(MapEntity.mapEntityList.Count));
break;
case 1:
msg.WriteEnum(PacketTypes.NetworkEvent);
msg.WriteEnum(NetworkEventType.ComponentUpdate);
msg.Write((byte)PacketTypes.NetworkEvent);
msg.Write((byte)NetworkEventType.ComponentUpdate);
msg.Write((int)Item.ItemList[Rand.Int(Item.ItemList.Count)].ID);
msg.Write(Rand.Int(8));
break;
@@ -1497,12 +1630,27 @@ namespace Barotrauma.Networking
{
banList.Save();
if (registeredToMaster && restClient != null)
{
var request = new RestRequest("masterserver2.php", Method.GET);
request.AddParameter("action", "removeserver");
restClient.Execute(request);
restClient = null;
}
if (saveServerLogs)
{
Log("Shutting down server...", Color.Cyan);
log.Save();
}
foreach (Client client in ConnectedClients)
{
if (client.FileStreamSender != null) client.FileStreamSender.Dispose();
}
server.Shutdown("The server has shut down");
}
}
@@ -1523,6 +1671,8 @@ namespace Barotrauma.Networking
public List<JobPrefab> jobPreferences;
public JobPrefab assignedJob;
public FileStreamSender FileStreamSender;
public bool Spectating;
public ReliableChannel ReliableChannel;

View File

@@ -3,6 +3,8 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace Barotrauma.Networking
{
@@ -18,6 +20,8 @@ namespace Barotrauma.Networking
partial class GameServer : NetworkMember
{
public const string SettingsFile = "serversettings.xml";
public bool ShowNetStats;
private TimeSpan refreshMasterInterval = new TimeSpan(0, 0, 30);
@@ -45,6 +49,8 @@ namespace Barotrauma.Networking
private bool saveServerLogs = true;
private bool allowFileTransfers = true;
public bool AutoRestart
{
get { return (ConnectedClients.Count == 0) ? false : autoRestart; }
@@ -89,15 +95,112 @@ namespace Barotrauma.Networking
public float EndVoteRequiredRatio = 0.5f;
private void SaveSettings()
{
XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;
settings.NewLineOnAttributes = true;
using (var writer = XmlWriter.Create(SettingsFile, settings))
{
writer.WriteStartElement("serversettings");
writer.WriteAttributeString("AllowSpectating", allowSpectating.ToString());
writer.WriteAttributeString("RandomizeSeed", randomizeSeed.ToString());
writer.WriteAttributeString("EndRoundAtLevelEnd", endRoundAtLevelEnd.ToString());
writer.WriteAttributeString("AllowFileTransfers", allowFileTransfers.ToString());
writer.WriteAttributeString("MaxFileTransferDuration", ((int)FileStreamSender.MaxTransferDuration.TotalSeconds).ToString());
writer.WriteAttributeString("SaveServerLogs", saveServerLogs.ToString());
writer.WriteAttributeString("LinesPerLogFile", log.LinesPerFile.ToString());
writer.WriteAttributeString("SubSelection", subSelectionMode.ToString());
writer.WriteAttributeString("ModeSelection", modeSelectionMode.ToString());
writer.Flush();
}
}
private void LoadSettings()
{
XDocument doc = null;
if (System.IO.File.Exists(SettingsFile))
{
doc = ToolBox.TryLoadXml(SettingsFile);
}
else
{
return;
}
if (doc == null)
{
doc = new XDocument(new XElement("serversettings"));
}
allowSpectating = ToolBox.GetAttributeBool(doc.Root, "AllowSpectating", true);
randomizeSeed = ToolBox.GetAttributeBool(doc.Root, "RandomizeSeed", true);
endRoundAtLevelEnd = ToolBox.GetAttributeBool(doc.Root, "EndRoundAtLevelEnd", true);
allowFileTransfers = ToolBox.GetAttributeBool(doc.Root, "AllowFileTransfers", true);
saveServerLogs = ToolBox.GetAttributeBool(doc.Root, "SaveServerLogs", true);
log.LinesPerFile = ToolBox.GetAttributeInt(doc.Root, "LinesPerLogFile", 800);
subSelectionMode = SelectionMode.Manual;
Enum.TryParse<SelectionMode>(ToolBox.GetAttributeString(doc.Root, "SubSelection", "Manual"), out subSelectionMode);
modeSelectionMode = SelectionMode.Manual;
Enum.TryParse<SelectionMode>(ToolBox.GetAttributeString(doc.Root, "ModeSelection", "Manual"), out modeSelectionMode);
FileStreamSender.MaxTransferDuration = new TimeSpan(0,0,ToolBox.GetAttributeInt(doc.Root, "MaxFileTransferDuration", 150));
}
private void CreateSettingsFrame()
{
settingsFrame = new GUIFrame(new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight), Color.Black * 0.5f);
GUIFrame innerFrame = new GUIFrame(new Rectangle(0, 0, 400, 400), null, Alignment.Center, GUI.Style, settingsFrame);
innerFrame.Padding = new Vector4(20.0f, 20.0f, 20.0f, 20.0f);
new GUITextBlock(new Rectangle(0, -15, 0, 20), "Server settings", GUI.Style, innerFrame, GUI.LargeFont);
new GUITextBlock(new Rectangle(0, -5, 0, 20), "Server settings", GUI.Style, innerFrame, GUI.LargeFont);
var randomizeLevelBox = new GUITickBox(new Rectangle(0, 30, 20, 20), "Randomize level seed between rounds", Alignment.Left, innerFrame);
int y = 40;
var endBox = new GUITickBox(new Rectangle(0, y, 20, 20), "End round when destination reached", Alignment.Left, innerFrame);
endBox.Selected = endRoundAtLevelEnd;
endBox.OnSelected = (GUITickBox) => { endRoundAtLevelEnd = GUITickBox.Selected; return true; };
y += 30;
var endVoteBox = new GUITickBox(new Rectangle(0, y, 20, 20), "End round by voting", Alignment.Left, innerFrame);
endVoteBox.Selected = Voting.AllowEndVoting;
endVoteBox.OnSelected = (GUITickBox) =>
{
Voting.AllowEndVoting = !Voting.AllowEndVoting;
GameMain.Server.UpdateVoteStatus();
return true;
};
var votesRequiredText = new GUITextBlock(new Rectangle(20, y+20, 20, 20), "Votes required: 50 %", GUI.Style, innerFrame, GUI.SmallFont);
var votesRequiredSlider = new GUIScrollBar(new Rectangle(150, y+22, 100, 10), GUI.Style, 0.1f, innerFrame);
votesRequiredSlider.UserData = votesRequiredText;
votesRequiredSlider.BarScroll = (EndVoteRequiredRatio - 0.5f) * 2.0f;
votesRequiredSlider.OnMoved = (GUIScrollBar scrollBar, float barScroll) =>
{
GUITextBlock voteText = scrollBar.UserData as GUITextBlock;
scrollBar.BarScroll = MathUtils.Round(barScroll, 0.2f);
EndVoteRequiredRatio = barScroll / 2.0f + 0.5f;
voteText.Text = "Votes required: " + (int)MathUtils.Round(EndVoteRequiredRatio * 100.0f, 10.0f) + " %";
return true;
};
votesRequiredSlider.OnMoved(votesRequiredSlider, votesRequiredSlider.BarScroll);
y += 40;
var randomizeLevelBox = new GUITickBox(new Rectangle(0, y, 20, 20), "Randomize level seed between rounds", Alignment.Left, innerFrame);
randomizeLevelBox.Selected = randomizeSeed;
randomizeLevelBox.OnSelected = (GUITickBox) =>
{
@@ -105,37 +208,23 @@ namespace Barotrauma.Networking
return true;
};
var endBox = new GUITickBox(new Rectangle(0, 60, 20, 20), "End round when destination reached", Alignment.Left, innerFrame);
endBox.Selected = endRoundAtLevelEnd;
endBox.OnSelected = (GUITickBox) => { endRoundAtLevelEnd = GUITickBox.Selected; return true; };
var endVoteBox = new GUITickBox(new Rectangle(0, 90, 20, 20), "End round by voting", Alignment.Left, innerFrame);
endVoteBox.Selected = Voting.AllowEndVoting;
endVoteBox.OnSelected = (GUITickBox) =>
y += 40;
var shareSubsBox = new GUITickBox(new Rectangle(0, y, 20, 20), "Share submarine files with players", Alignment.Left, innerFrame);
shareSubsBox.Selected = allowFileTransfers;
shareSubsBox.OnSelected = (GUITickBox) =>
{
Voting.AllowEndVoting = !Voting.AllowEndVoting;
GameMain.Server.UpdateVoteStatus();
return true;
};
var votesRequiredText = new GUITextBlock(new Rectangle(20, 110, 20, 20), "Votes required: 50 %", GUI.Style, innerFrame, GUI.SmallFont);
var votesRequiredSlider = new GUIScrollBar(new Rectangle(150,115, 100, 10), GUI.Style, 0.1f, innerFrame);
votesRequiredSlider.UserData = votesRequiredText;
votesRequiredSlider.BarScroll = (EndVoteRequiredRatio - 0.5f) * 2.0f;
votesRequiredSlider.OnMoved = (GUIScrollBar scrollBar, float barScroll) =>
{
GUITextBlock voteText = scrollBar.UserData as GUITextBlock;
scrollBar.BarScroll = MathUtils.Round(barScroll, 0.2f);
EndVoteRequiredRatio = barScroll/2.0f + 0.5f;
voteText.Text = "Votes required: " + (int)MathUtils.Round(EndVoteRequiredRatio * 100.0f, 10.0f) + " %";
allowFileTransfers = GUITickBox.Selected;
return true;
};
votesRequiredSlider.OnMoved(votesRequiredSlider, votesRequiredSlider.BarScroll);
new GUITextBlock(new Rectangle(0, 95+50, 100, 20), "Submarine selection:", GUI.Style, innerFrame);
var selectionFrame = new GUIFrame(new Rectangle(0, 120 + 50, 300, 20), null, innerFrame);
y += 40;
new GUITextBlock(new Rectangle(0, y, 100, 20), "Submarine selection:", GUI.Style, innerFrame);
var selectionFrame = new GUIFrame(new Rectangle(0, y+20, 300, 20), null, innerFrame);
for (int i = 0; i<3; i++)
{
var selectionTick = new GUITickBox(new Rectangle(i * 100, 0, 20, 20), ((SelectionMode)i).ToString(), Alignment.Left, selectionFrame);
@@ -144,8 +233,10 @@ namespace Barotrauma.Networking
selectionTick.UserData = (SelectionMode)i;
}
new GUITextBlock(new Rectangle(0, 145 + 50, 100, 20), "Mode selection:", GUI.Style, innerFrame);
selectionFrame = new GUIFrame(new Rectangle(0, 170 + 50, 300, 20), null, innerFrame);
y += 45;
new GUITextBlock(new Rectangle(0, y, 100, 20), "Mode selection:", GUI.Style, innerFrame);
selectionFrame = new GUIFrame(new Rectangle(0, y+20, 300, 20), null, innerFrame);
for (int i = 0; i<3; i++)
{
var selectionTick = new GUITickBox(new Rectangle(i*100, 0, 20, 20), ((SelectionMode)i).ToString(), Alignment.Left, selectionFrame);
@@ -154,7 +245,9 @@ namespace Barotrauma.Networking
selectionTick.UserData = (SelectionMode)i;
}
var allowSpecBox = new GUITickBox(new Rectangle(0, 210 + 50, 20, 20), "Allow spectating", Alignment.Left, innerFrame);
y += 60;
var allowSpecBox = new GUITickBox(new Rectangle(0, y, 20, 20), "Allow spectating", Alignment.Left, innerFrame);
allowSpecBox.Selected = allowSpectating;
allowSpecBox.OnSelected = (GUITickBox) =>
{
@@ -162,7 +255,9 @@ namespace Barotrauma.Networking
return true;
};
var saveLogsBox = new GUITickBox(new Rectangle(0, 240 + 50, 20, 20), "Save server logs", Alignment.Left, innerFrame);
y += 30;
var saveLogsBox = new GUITickBox(new Rectangle(0, y, 20, 20), "Save server logs", Alignment.Left, innerFrame);
saveLogsBox.Selected = saveServerLogs;
saveLogsBox.OnSelected = (GUITickBox) =>
{
@@ -225,6 +320,7 @@ namespace Barotrauma.Networking
else
{
settingsFrame = null;
SaveSettings();
}
return false;

View File

@@ -5,14 +5,14 @@ namespace Barotrauma.Networking
{
static class NetBufferExtensions
{
public static void WriteEnum(this NetBuffer buffer, Enum value)
{
buffer.WriteRangedInteger(0, Enum.GetValues(value.GetType()).Length - 1, Convert.ToInt32(value));
}
//public static void WriteEnum(this NetBuffer buffer, Enum value)
//{
// buffer.WriteRangedInteger(0, Enum.GetValues(value.GetType()).Length - 1, Convert.ToInt32(value));
//}
public static TEnum ReadEnum<TEnum>(this NetBuffer buffer)
{
return (TEnum)(object)buffer.ReadRangedInteger(0, Enum.GetValues(typeof(TEnum)).Length - 1);
}
//public static TEnum ReadEnum<TEnum>(this NetBuffer buffer)
//{
// return (TEnum)(object)buffer.ReadRangedInteger(0, Enum.GetValues(typeof(TEnum)).Length - 1);
//}
}
}

View File

@@ -132,7 +132,7 @@ namespace Barotrauma.Networking
public bool FillData(NetBuffer message)
{
message.WriteEnum(eventType);
message.Write((byte)eventType);
Entity e = Entity.FindEntityByID(id);
if (e == null) return false;
@@ -189,7 +189,7 @@ namespace Barotrauma.Networking
try
{
eventType = message.ReadEnum<NetworkEventType>();
eventType = (NetworkEventType)message.ReadByte();
id = message.ReadUInt16();
}
catch (Exception exception)

View File

@@ -7,7 +7,7 @@ using Lidgren.Network;
namespace Barotrauma.Networking
{
enum PacketTypes : int
enum PacketTypes : byte
{
Unknown,
@@ -32,6 +32,8 @@ namespace Barotrauma.Networking
Vote, VoteStatus,
ResendRequest, ReliableMessage, LatestMessageID,
RequestFile, FileStream,
SpectateRequest
}
@@ -163,14 +165,14 @@ namespace Barotrauma.Networking
if (msgBytes.Count == 0) return null;
NetOutgoingMessage message = netPeer.CreateMessage();
message.WriteEnum(PacketTypes.NetworkEvent);
message.Write((byte)PacketTypes.NetworkEvent);
message.Write((float)NetTime.Now);
message.Write((byte)msgBytes.Count);
foreach (byte[] msgData in msgBytes)
{
if (msgData.Length > 255) DebugConsole.ThrowError("too large networkevent (" + msgData.Length + " bytes)");
if (msgData.Length > 255) DebugConsole.ThrowError("Too large networkevent (" + msgData.Length + " bytes)");
message.Write((byte)msgData.Length);
message.Write(msgData);
@@ -295,25 +297,6 @@ namespace Barotrauma.Networking
}
public virtual void Disconnect() { }
protected byte PlayerCountToByte(int playerCount, int maxPlayers)
{
byte byteVal = (byte)playerCount;
byteVal |= (byte)((maxPlayers - 1) << 4);
return byteVal;
}
public static int ByteToPlayerCount(byte byteVal, out int maxPlayers)
{
maxPlayers = (byteVal >> 4)+1;
int playerCount = byteVal & (byte)((1 << 4) - 1);
return playerCount;
}
}
}

View File

@@ -94,7 +94,7 @@ namespace Barotrauma.Networking.ReliableMessages
var reliableMessage = new ReliableMessage(message, messageID);
message.WriteEnum(PacketTypes.ReliableMessage);
message.Write((byte)PacketTypes.ReliableMessage);
message.Write(messageID);
@@ -184,7 +184,7 @@ namespace Barotrauma.Networking.ReliableMessages
//Debug.WriteLine("Sending ack message: "+messageCount);
NetOutgoingMessage message = sender.CreateMessage();
message.WriteEnum(PacketTypes.LatestMessageID);
message.Write((byte)PacketTypes.LatestMessageID);
message.Write(messageCount);
@@ -244,7 +244,7 @@ namespace Barotrauma.Networking.ReliableMessages
Debug.WriteLine("rerequest "+missingMessage.ID+" (try #"+missingMessage.ResendRequestsSent+")");
NetOutgoingMessage resendRequest = receiver.CreateMessage();
resendRequest.WriteEnum(PacketTypes.ResendRequest);
resendRequest.Write((byte)PacketTypes.ResendRequest);
resendRequest.Write(missingMessage.ID);
@@ -443,6 +443,7 @@ namespace Barotrauma.Networking.ReliableMessages
public void SaveInnerMessage()
{
innerMessage.WritePadBits();
innerMessageBytes = innerMessage.PeekBytes(innerMessage.LengthBytes);
//innerMessage = null;
}

View File

@@ -9,7 +9,7 @@ namespace Barotrauma.Networking
{
class ServerLog
{
const int LinesPerFile = 300;
private int linesPerFile = 800;
public const string SavePath = "ServerLogs";
@@ -21,6 +21,12 @@ namespace Barotrauma.Networking
private Queue<ColoredText> lines;
public int LinesPerFile
{
get { return linesPerFile; }
set { linesPerFile = Math.Max(10, linesPerFile); }
}
public ServerLog(string serverName)
{
this.serverName = serverName;

View File

@@ -155,24 +155,28 @@ namespace Barotrauma
if (held) heldQueue = true;
}
public bool Dequeue
public bool DequeueHit()
{
get
{
bool value = hitQueue;
hitQueue = false;
return value;
}
bool value = hitQueue;
hitQueue = false;
return value;
}
public bool DequeueHeld
public bool DequeueHeld()
{
get
{
bool value = heldQueue;
heldQueue = false;
return value;
}
bool value = heldQueue;
heldQueue = false;
return value;
}
public bool GetHeldQueue
{
get { return heldQueue; }
}
public bool GetHitQueue
{
get { return hitQueue; }
}

View File

@@ -193,7 +193,7 @@ namespace Barotrauma
return editableProperties;
}
public static Dictionary<string, ObjectProperty> GetProperties(object obj)
public static Dictionary<string, ObjectProperty> GetProperties(IPropertyObject obj)
{
var properties = TypeDescriptor.GetProperties(obj.GetType()).Cast<PropertyDescriptor>();
@@ -207,7 +207,12 @@ namespace Barotrauma
return dictionary;
}
public static Dictionary<string, ObjectProperty> InitProperties(object obj, XElement element)
public static Dictionary<string, ObjectProperty> InitProperties(IPropertyObject obj)
{
return InitProperties(obj, null);
}
public static Dictionary<string, ObjectProperty> InitProperties(IPropertyObject obj, XElement element)
{
var properties = TypeDescriptor.GetProperties(obj.GetType()).Cast<PropertyDescriptor>();
@@ -226,16 +231,19 @@ namespace Barotrauma
}
}
//go through all the attributes in the xml element
//and set the value of the matching property if it is initializable
foreach (XAttribute attribute in element.Attributes())
if (element!=null)
{
ObjectProperty property = null;
if (!dictionary.TryGetValue(attribute.Name.ToString().ToLower(), out property)) continue;
if (!property.Attributes.OfType<HasDefaultValue>().Any()) continue;
property.TrySetValue(attribute.Value);
//go through all the attributes in the xml element
//and set the value of the matching property if it is initializable
foreach (XAttribute attribute in element.Attributes())
{
ObjectProperty property = null;
if (!dictionary.TryGetValue(attribute.Name.ToString().ToLower(), out property)) continue;
if (!property.Attributes.OfType<HasDefaultValue>().Any()) continue;
property.TrySetValue(attribute.Value);
}
}
return dictionary;
}

View File

@@ -2,6 +2,7 @@
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using System;
using System.IO;
using System.Linq;
namespace Barotrauma
@@ -291,7 +292,14 @@ namespace Barotrauma
return false;
}
Submarine.SaveCurrent(nameBox.Text + ".sub");
string savePath = nameBox.Text + ".sub";
if (Submarine.Loaded != null)
{
savePath = Path.Combine(Path.GetDirectoryName(Submarine.Loaded.FilePath), savePath);
}
Submarine.SaveCurrent(savePath);
Submarine.Loaded.CheckForErrors();
GUI.AddMessage("Submarine saved to " + Submarine.Loaded.FilePath, Color.Green, 3.0f);

View File

@@ -177,7 +177,7 @@ namespace Barotrauma
//{
// cam.TargetPos = Character.Controlled.WorldPosition;
//}
cam.UpdateTransform();
DrawMap(graphics, spriteBatch);
@@ -200,6 +200,8 @@ namespace Barotrauma
if (GameMain.GameSession != null) GameMain.GameSession.Draw(spriteBatch);
if (Character.Controlled == null && Submarine.Loaded != null) DrawSubmarineIndicator(spriteBatch, Submarine.Loaded);
GUI.Draw((float)deltaTime, spriteBatch, cam);
if (!PlayerInput.LeftButtonHeld()) Inventory.draggingItem = null;
@@ -348,5 +350,25 @@ namespace Barotrauma
GameMain.LightManager.DrawLOS(graphics, spriteBatch, cam);
}
private void DrawSubmarineIndicator(SpriteBatch spriteBatch, Submarine submarine)
{
Vector2 subDiff = submarine.WorldPosition - cam.Position;
if (Math.Abs(subDiff.X) > cam.WorldView.Width || Math.Abs(subDiff.Y) > cam.WorldView.Height)
{
Vector2 normalizedSubDiff = Vector2.Normalize(subDiff);
Vector2 iconPos =
cam.WorldToScreen(cam.Position) +
new Vector2(normalizedSubDiff.X * GameMain.GraphicsWidth * 0.4f, -normalizedSubDiff.Y * GameMain.GraphicsHeight * 0.4f);
GUI.SubmarineIcon.Draw(spriteBatch, iconPos, Color.LightBlue * 0.5f);
Vector2 arrowOffset = normalizedSubDiff * GUI.SubmarineIcon.size.X * 0.7f;
arrowOffset.Y = -arrowOffset.Y;
GUI.Arrow.Draw(spriteBatch, iconPos + arrowOffset, Color.LightBlue * 0.5f, MathUtils.VectorToAngle(arrowOffset) + MathHelper.PiOver2);
}
}
}
}

View File

@@ -37,6 +37,10 @@ namespace Barotrauma
public bool IsServer;
public string ServerName, ServerMessage;
const float NetworkUpdateInterval = 1.0f;
private float networkUpdateTimer;
private bool valueChanged;
private Sprite backgroundSprite;
private GUITextBox serverMessage;
@@ -51,6 +55,11 @@ namespace Barotrauma
get { return modeList; }
}
public GUIListBox PlayerList
{
get { return playerList; }
}
public GUIFrame InfoFrame
{
get { return infoFrame; }
@@ -183,24 +192,7 @@ namespace Barotrauma
voteText.UserData = "subvotes";
voteText.Visible = false;
if (Submarine.SavedSubmarines.Count > 0)
{
foreach (Submarine sub in Submarine.SavedSubmarines)
{
GUITextBlock textBlock = new GUITextBlock(
new Rectangle(0, 0, 0, 25),
sub.Name, GUI.Style,
Alignment.Left, Alignment.Left,
subList);
textBlock.Padding = new Vector4(10.0f, 0.0f, 0.0f, 0.0f);
textBlock.UserData = sub;
}
}
else
{
DebugConsole.ThrowError("No saved submarines found!");
return;
}
UpdateSubList();
columnX += columnWidth + 20;
@@ -209,8 +201,7 @@ namespace Barotrauma
new GUITextBlock(new Rectangle(columnX, 120, 0, 30), "Game mode: ", GUI.Style, infoFrame);
modeList = new GUIListBox(new Rectangle(columnX, 150, columnWidth, infoFrame.Rect.Height - 150 - 80), GUI.Style, infoFrame);
modeList.OnSelected = VotableClicked;
voteText = new GUITextBlock(new Rectangle(columnX, 120, columnWidth, 30), "Votes: ", GUI.Style, Alignment.TopLeft, Alignment.TopRight, infoFrame);
voteText.UserData = "modevotes";
voteText.Visible = false;
@@ -327,7 +318,7 @@ namespace Barotrauma
modeList.OnSelected = VotableClicked;
modeList.OnSelected = SelectMode;
subList.OnSelected = VotableClicked;
subList.OnSelected = SelectMap;
subList.OnSelected = SelectSub;
traitorProbabilityButtons[0].OnClicked = ToggleTraitorsEnabled;
traitorProbabilityButtons[1].OnClicked = ToggleTraitorsEnabled;
@@ -449,8 +440,6 @@ namespace Barotrauma
UpdateJobPreferences(jobList);
//UpdatePreviewPlayer(Game1.Client.CharacterInfo);
UpdatePreviewPlayer(characterInfo);
}
}
@@ -484,8 +473,8 @@ namespace Barotrauma
if (GameMain.Server == null) return false;
GameMain.Server.AutoRestart = tickBox.Selected;
GameMain.Server.UpdateNetLobby(tickBox);
valueChanged = true;
return true;
}
@@ -501,8 +490,8 @@ namespace Barotrauma
if (index > 2) index = 0;
SetTraitorsEnabled((YesNoMaybe)index);
if (GameMain.Server != null) GameMain.Server.UpdateNetLobby(null);
valueChanged = true;
return true;
}
@@ -515,20 +504,51 @@ namespace Barotrauma
}
private bool SelectMap(GUIComponent component, object obj)
private bool SelectSub(GUIComponent component, object obj)
{
if (GameMain.Server != null) GameMain.Server.UpdateNetLobby(obj);
valueChanged = true;
//Submarine sub = (Submarine)obj;
var hash = (obj as Submarine).MD5Hash;
//hash will be null if opening the sub file failed -> don't select the sub
if (string.IsNullOrWhiteSpace(hash.Hash))
{
(component as GUITextBlock).TextColor = Color.DarkRed * 0.8f;
component.CanBeFocused = false;
//submarine already loaded
//if (Submarine.Loaded != null && sub.FilePath == Submarine.Loaded.FilePath) return true;
//sub.Load();
return false;
}
return true;
}
public void UpdateSubList()
{
if (subList == null) return;
subList.ClearChildren();
if (Submarine.SavedSubmarines.Count > 0)
{
foreach (Submarine sub in Submarine.SavedSubmarines)
{
GUITextBlock textBlock = new GUITextBlock(
new Rectangle(0, 0, 0, 25),
sub.Name, GUI.Style,
Alignment.Left, Alignment.Left,
subList);
textBlock.Padding = new Vector4(10.0f, 0.0f, 0.0f, 0.0f);
textBlock.UserData = sub;
}
}
else
{
DebugConsole.ThrowError("No saved submarines found!");
return;
}
}
public bool VotableClicked(GUIComponent component, object userData)
{
if (GameMain.Client == null) return false;
@@ -558,7 +578,7 @@ namespace Barotrauma
{
if (GameMain.Server == null) return false;
ServerName = text;
GameMain.Server.UpdateNetLobby(null, null);
valueChanged = true;
return true;
}
@@ -567,7 +587,7 @@ namespace Barotrauma
{
if (GameMain.Server == null) return false;
ServerMessage = text;
GameMain.Server.UpdateNetLobby(null, null);
valueChanged = true;
return true;
}
@@ -575,7 +595,7 @@ namespace Barotrauma
public void AddPlayer(string name)
{
GUITextBlock textBlock = new GUITextBlock(
new Rectangle(0, 0, 0, 25), name,
new Rectangle(0, 0, playerList.Rect.Width-20, 25), name,
GUI.Style, Alignment.Left, Alignment.Left,
playerList);
@@ -614,7 +634,7 @@ namespace Barotrauma
var closeButton = new GUIButton(new Rectangle(0, 0, 100, 20), "Close", Alignment.BottomRight, GUI.Style, playerFrameInner);
closeButton.OnClicked = ClosePlayerFrame;
return true;
return false;
}
private bool ClosePlayerFrame(GUIButton button, object userData)
@@ -644,10 +664,7 @@ namespace Barotrauma
public void ClearPlayers()
{
for (int i = 1; i<playerList.CountChildren; i++)
{
playerList.RemoveChild(playerList.children[i]);
}
playerList.ClearChildren();
}
public override void Update(double deltaTime)
@@ -692,6 +709,18 @@ namespace Barotrauma
{
if (GameMain.Server.BanList.BanFrame != null) GameMain.Server.BanList.BanFrame.Update((float)deltaTime);
}
if (valueChanged && GameMain.Server != null)
{
networkUpdateTimer -= (float)deltaTime;
if (networkUpdateTimer <= 0.0f)
{
GameMain.Server.UpdateNetLobby(null);
valueChanged = false;
networkUpdateTimer = NetworkUpdateInterval;
}
}
//durationBar.BarScroll = Math.Max(durationBar.BarScroll, 1.0f / 60.0f);
}
@@ -803,7 +832,7 @@ namespace Barotrauma
GameModePreset modePreset = obj as GameModePreset;
if (modePreset == null) return false;
if (GameMain.Server != null) GameMain.Server.UpdateNetLobby(obj);
valueChanged = true;
return true;
}
@@ -818,8 +847,8 @@ namespace Barotrauma
//textBox.Text = LevelSeed;
//textBox.Selected = false;
if (GameMain.Server != null) GameMain.Server.UpdateNetLobby(null);
valueChanged = true;
return true;
}
@@ -901,29 +930,47 @@ namespace Barotrauma
public bool TrySelectSub(string subName, string md5Hash)
{
//already downloading the selected sub file
if (GameMain.Client.ActiveFileTransferName == subName+".sub") return false;
Submarine sub = Submarine.SavedSubmarines.Find(m => m.Name == subName);
if (sub == null)
if (sub == null || sub.MD5Hash.Hash != md5Hash)
{
new GUIMessageBox("Submarine not found!","The submarine ''" + subName + "'' has been selected by the server. Matching file not found in your map folder.");
return false;
}
else
{
if (sub.MD5Hash.Hash != md5Hash)
string errorMsg = "";
if (sub == null)
{
new GUIMessageBox("Submarine not found!",
"Your version of the map file ''" + sub.Name + "'' doesn't match the server's version!"
+"\nYour file: " + sub.Name + "(MD5 hash : " + sub.MD5Hash.Hash + ")"
+"\nServer's file: " + subName + "(MD5 hash : " + md5Hash + ")");
return false;
errorMsg = "Submarine ''" + subName + "'' was selected by the server. Matching file not found in your submarine folder. ";
}
else if (sub.MD5Hash.Hash == null)
{
errorMsg = "Couldn't load submarine ''" + subName + "''. The file may be corrupted. ";
}
else
{
subList.Select(sub, true);
//map.Load();
return true;
errorMsg = "Your version of the submarine file ''" + sub.Name + "'' doesn't match the server's version! "
+ "Your MD5 hash: " + sub.MD5Hash.Hash + " \n"
+ "Server's MD5 hash: " + md5Hash + ". ";
}
string downloadMsg = GameMain.Client.ActiveFileTransferName == "" ?
"Do you want to download the file from the server host?" :
"Do you want to download the file and cancel downloading ''" + GameMain.Client.ActiveFileTransferName + "''?";
var requestFileBox = new GUIMessageBox("Submarine not found!", errorMsg+downloadMsg, new string[] { "Yes", "No" }, 400, 300);
requestFileBox.Buttons[0].UserData = subName;
requestFileBox.Buttons[0].OnClicked += requestFileBox.Close;
requestFileBox.Buttons[0].OnClicked += (GUIButton button, object userdata) =>
{
GameMain.Client.RequestFile(userdata.ToString(), FileTransferMessageType.Submarine);
return true;
};
requestFileBox.Buttons[1].OnClicked += requestFileBox.Close;
return false;
}
subList.Select(sub, true);
return true;
}
public void WriteData(NetOutgoingMessage msg)
@@ -949,7 +996,7 @@ namespace Barotrauma
//msg.Write(AllowSubVoting);
//msg.Write(AllowModeVoting);
msg.Write(modeList.SelectedIndex);
msg.Write((byte)modeList.SelectedIndex);
//msg.Write(durationBar.BarScroll);
msg.Write(LevelSeed);
@@ -966,7 +1013,7 @@ namespace Barotrauma
public void ReadData(NetIncomingMessage msg)
{
string mapName="", md5Hash="";
string mapName = "", md5Hash = "";
int modeIndex = 0;
//float durationScroll = 0.0f;
@@ -991,7 +1038,7 @@ namespace Barotrauma
//AllowSubVoting = msg.ReadBoolean();
//AllowModeVoting = msg.ReadBoolean();
modeIndex = msg.ReadInt32();
modeIndex = msg.ReadByte();
//durationScroll = msg.ReadFloat();
@@ -1001,9 +1048,9 @@ namespace Barotrauma
restartTimer = msg.ReadFloat();
int playerCount = msg.ReadByte();
playerList.ClearChildren();
for (int i = 0; i<playerCount; i++)
for (int i = 0; i < playerCount; i++)
{
AddPlayer(msg.ReadString());
}

View File

@@ -128,7 +128,7 @@ namespace Barotrauma
voteText.UserData = "votes";
}
voteText.Text = votes.ToString();
voteText.Text = votes == 0 ? "" : votes.ToString();
}
}
@@ -233,6 +233,11 @@ namespace Barotrauma
AllowSubVoting = msg.ReadBoolean();
if (allowSubVoting)
{
foreach (Submarine sub in Submarine.SavedSubmarines)
{
SetVoteText(GameMain.NetLobbyScreen.SubList, sub, 0);
}
int votableCount = msg.ReadByte();
for (int i = 0; i < votableCount; i++)
{
@@ -252,7 +257,7 @@ namespace Barotrauma
int votes = msg.ReadByte();
string modeName = msg.ReadString();
GameModePreset mode = GameModePreset.list.Find(m => m.Name == modeName);
SetVoteText(GameMain.NetLobbyScreen.SubList, mode, votes);
SetVoteText(GameMain.NetLobbyScreen.ModeList, mode, votes);
}
}

View File

@@ -165,24 +165,27 @@ namespace Barotrauma
string port = arguments[1];
string serverName = arguments[2];
string gameStarted = (arguments.Length > 3) ? arguments[3] : "";
string playerCountStr = (arguments.Length > 4) ? arguments[4] : "";
string currPlayersStr = (arguments.Length > 4) ? arguments[4] : "";
string maxPlayersStr = (arguments.Length > 5) ? arguments[5] : "";
string hasPassWordStr = (arguments.Length > 5) ? arguments[5] : "";
var serverFrame = new GUIFrame(new Rectangle(0,0,0,20), (i%2 == 0) ? Color.Transparent : Color.White*0.2f, null, serverList);
serverFrame.UserData = IP+":"+port;
string hasPassWordStr = (arguments.Length > 6) ? arguments[6] : "";
var serverFrame = new GUIFrame(new Rectangle(0, 0, 0, 20), (i % 2 == 0) ? Color.Transparent : Color.White * 0.2f, null, serverList);
serverFrame.UserData = IP + ":" + port;
serverFrame.HoverColor = Color.Gold * 0.2f;
serverFrame.SelectedColor = Color.Gold * 0.5f;
var passwordBox = new GUITickBox(new Rectangle(columnX[0]/2, 0, 20, 20), "", Alignment.TopLeft, serverFrame);
var passwordBox = new GUITickBox(new Rectangle(columnX[0] / 2, 0, 20, 20), "", Alignment.TopLeft, serverFrame);
passwordBox.Selected = hasPassWordStr == "1";
passwordBox.Enabled = false;
passwordBox.UserData = "password";
var nameText = new GUITextBlock(new Rectangle(columnX[0], 0, 0, 0), serverName, GUI.Style, serverFrame);
int playerCount, maxPlayers;
playerCount = GameClient.ByteToPlayerCount((byte)int.Parse(playerCountStr), out maxPlayers);
int playerCount = 0, maxPlayers = 1;
int.TryParse(currPlayersStr, out playerCount);
int.TryParse(maxPlayersStr, out maxPlayers);
var playerCountText = new GUITextBlock(new Rectangle(columnX[1], 0, 0, 0), playerCount + "/" + maxPlayers, GUI.Style, serverFrame);
@@ -208,7 +211,7 @@ namespace Barotrauma
if (client == null) yield return CoroutineStatus.Success;
var request = new RestRequest("masterserver.php", Method.GET);
var request = new RestRequest("masterserver2.php", Method.GET);
request.AddParameter("gamename", "barotrauma"); // adds to POST or URL querystring based on Method
request.AddParameter("action", "listservers"); // adds to POST or URL querystring based on Method