- converting NetworkEvent sending time to local time before doing any comparisons

- using mersenne twister for random number generation due to differences in Mono and .NET implementations of the Random library
- password prompt for password-protected private servers
- fixed deconstructor, fabricator and railgun connection panels closing immediately after opening
- fixed editor saving newly created subs to the root folder instead of the Submarines folder
- keeping items in the same inventory slots between clients instead of just syncing which items are in the inventory
- fixed crashing when swapping items between different limbslots
This commit is contained in:
Regalis
2016-03-03 21:11:54 +02:00
parent 35c36d283a
commit 40714c1102
21 changed files with 225 additions and 59 deletions
+1
View File
@@ -142,6 +142,7 @@
<Compile Include="Source\Networking\GameServerSettings.cs" />
<Compile Include="Source\Screens\NetLobbyVoting.cs" />
<Compile Include="Source\Screens\ServerListScreen.cs" />
<Compile Include="Source\Utils\MTRandom.cs" />
<Compile Include="Source\Utils\Rand.cs" />
<Compile Include="Source\Events\PropertyTask.cs" />
<Compile Include="Source\Events\RepairTask.cs" />
@@ -49,7 +49,7 @@
<fabricableitem name="Incendium Fuel Rod" requireditems="Steel Bar, Incendium Bar"/>
</Fabricator>
<ConnectionPanel canbeselected = "true">
<ConnectionPanel selectkey="Action" canbeselected = "true">
<requireditem name="Screwdriver" type="Equipped"/>
<output name="power_in"/>
</ConnectionPanel>
@@ -73,7 +73,7 @@
<GuiFrame rect="0,0,300,200" alignment="Center" color="0.0,0.0,0.0,0.6"/>
</Deconstructor>
<ConnectionPanel canbeselected = "true">
<ConnectionPanel selectkey="Action" canbeselected = "true">
<requireditem name="Screwdriver" type="Equipped"/>
<output name="power_in"/>
</ConnectionPanel>
+2 -2
View File
@@ -17,7 +17,7 @@
</StatusEffect>
</Turret>
<ConnectionPanel canbeselected = "true" msg="Rewire [Screwdriver]">
<ConnectionPanel selectkey="Action" canbeselected = "true" msg="Rewire [Screwdriver]">
<requireditem name="Screwdriver,Wire" type="Equipped"/>
<input name="power_in"/>
<input name="position_in"/>
@@ -40,7 +40,7 @@
<limbposition limb="RightHand" position="43,-85"/>
</Controller>
<ConnectionPanel canbeselected = "true" msg="Rewire [Screwdriver]">
<ConnectionPanel selectkey="Action" canbeselected = "true" msg="Rewire [Screwdriver]">
<requireditem name="Screwdriver,Wire" type="Equipped"/>
<input name="power_in"/>
<output name="position_out"/>
@@ -47,7 +47,7 @@ namespace Barotrauma
{
if (!character.SelectedItems.Contains(weapon))
{
character.Inventory.TryPutItem(weapon, 3, false);
character.Inventory.TryPutItem(weapon, 3, true, false);
weapon.Equip(character);
}
character.CursorPosition = enemy.Position;
@@ -88,7 +88,7 @@ namespace Barotrauma
if (targetSlot>-1 && character.Inventory.IsInLimbSlot(targetItem, LimbSlot.Any))
{
character.Inventory.TryPutItem(targetItem, targetSlot, false);
character.Inventory.TryPutItem(targetItem, targetSlot, true, false);
}
}
@@ -875,15 +875,17 @@ namespace Barotrauma
Vector2 itemPos = aim ? aimPos : holdPos;
bool usingController = character.SelectedConstruction != null && character.SelectedConstruction.GetComponent<Controller>() != null;
float itemAngle;
if (Anim != Animation.Climbing && stunTimer <= 0.0f && aim && itemPos != Vector2.Zero)
if (Anim != Animation.Climbing && !usingController && stunTimer <= 0.0f && aim && itemPos != Vector2.Zero)
{
Vector2 mousePos = ConvertUnits.ToSimUnits(character.CursorPosition);
Vector2 diff = (mousePos - torso.SimPosition) * Dir;
holdAngle = MathUtils.VectorToAngle(new Vector2(diff.X, diff.Y * Dir)) - torso.body.Rotation * Dir;
//holdAngle = MathHelper.Clamp(MathUtils.WrapAnglePi(holdAngle), -1.3f, 1.0f);
itemAngle = (torso.body.Rotation + holdAngle * Dir);
@@ -909,7 +911,7 @@ namespace Barotrauma
Vector2 shoulderPos = limbJoints[2].WorldAnchorA;
Vector2 transformedHoldPos = shoulderPos;
if (itemPos == Vector2.Zero || Anim == Animation.Climbing || (leftHand.Disabled && rightHand.Disabled))
if (itemPos == Vector2.Zero || Anim == Animation.Climbing || usingController)
{
if (character.SelectedItems[1] == item)
{
+1 -1
View File
@@ -487,7 +487,7 @@ namespace Barotrauma
if (item == null) continue;
item.Pick(this, true, true, true);
inventory.TryPutItem(item, i, false);
inventory.TryPutItem(item, i, false, false);
}
}
}
@@ -96,6 +96,8 @@ namespace Barotrauma
}
}
if (Screen.Selected == GameMain.EditMapScreen) return;
if (character.Oxygen < 50.0f && !character.IsDead)
{
Vector2 offset = Rand.Vector(noiseOverlay.size.X);
+10 -7
View File
@@ -149,7 +149,7 @@ namespace Barotrauma
return placed;
}
public override bool TryPutItem(Item item, int index, bool createNetworkEvent)
public override bool TryPutItem(Item item, int index, bool allowSwapping, bool createNetworkEvent)
{
//there's already an item in the slot
if (Items[index] != null)
@@ -173,7 +173,7 @@ namespace Barotrauma
combined = true;
}
//if moving the item between slots in the same inventory
else if (item.ParentInventory == this)
else if (item.ParentInventory == this && allowSwapping)
{
int currentIndex = Array.IndexOf(Items, item);
@@ -182,16 +182,19 @@ namespace Barotrauma
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))
if (TryPutItem(existingItem, currentIndex, false, false) &&
TryPutItem(item, index, false, false))
{
new Networking.NetworkEvent(Networking.NetworkEventType.InventoryUpdate, Owner.ID, true, true);
}
else
{
Items[currentIndex] = null;
Items[index] = null;
//swapping the items failed -> move them back to where they were
TryPutItem(item, currentIndex, false);
TryPutItem(existingItem, index, false);
TryPutItem(item, currentIndex, false, false);
TryPutItem(existingItem, index, false, false);
}
}
@@ -416,7 +419,7 @@ namespace Barotrauma
if (Items[i] != item && Items[i] != null) Items[i].Drop(character, false);
if (TryPutItem(item, i, false))
if (TryPutItem(item, i, false, false))
{
if (droppedItems.Contains(item))
{
@@ -241,7 +241,7 @@ namespace Barotrauma.Items.Components
Item item = MapEntity.FindEntityByID(itemIds[i]) as Item;
if (item == null) continue;
Inventory.TryPutItem(item, i, false);
Inventory.TryPutItem(item, i, false, false);
}
itemIds = null;
+14 -26
View File
@@ -104,7 +104,7 @@ namespace Barotrauma
return true;
}
public virtual bool TryPutItem(Item item, int i, bool createNetworkEvent = true)
public virtual bool TryPutItem(Item item, int i, bool allowSwapping, bool createNetworkEvent)
{
if (Owner == null) return false;
if (CanBePut(item,i))
@@ -274,7 +274,7 @@ namespace Barotrauma
}
//selectedSlot = slotIndex;
TryPutItem(draggingItem, slotIndex);
TryPutItem(draggingItem, slotIndex, true, true);
draggingItem = null;
}
@@ -351,11 +351,9 @@ namespace Barotrauma
public virtual bool FillNetworkData(NetworkEventType type, NetBuffer message, object data)
{
var foundItems = Array.FindAll(Items, i => i != null);
message.Write((byte)foundItems.Count());
foreach (Item item in foundItems)
for (int i = 0; i < capacity; i++)
{
message.Write((ushort)item.ID);
message.Write((ushort)(Items[i]==null ? 0 : Items[i].ID));
}
return true;
@@ -368,31 +366,21 @@ namespace Barotrauma
List<ushort> newItemIDs = new List<ushort>();
List<Item> droppedItems = new List<Item>();
List<Item> prevItems = new List<Item>(Items);
byte count = message.ReadByte();
for (int i = 0; i<count; i++)
{
newItemIDs.Add(message.ReadUInt16());
}
for (int i = 0; i < capacity; i++)
{
if (Items[i] == null) continue;
if (!newItemIDs.Contains(Items[i].ID))
ushort itemId = message.ReadUInt16();
if (itemId==0)
{
droppedItems.Add(Items[i]);
Items[i].Drop(null, false);
continue;
if (Items[i] != null) Items[i].Drop();
}
}
foreach (ushort itemId in newItemIDs)
{
Item item = Entity.FindEntityByID(itemId) as Item;
if (item == null) continue;
else
{
var item = Entity.FindEntityByID(itemId) as Item;
if (item == null) continue;
TryPutItem(item, item.AllowedSlots, false);
if (droppedItems.Contains(item)) droppedItems.Remove(item);
TryPutItem(item, i, true, false);
}
}
lastUpdate = sendingTime;
+2 -2
View File
@@ -44,9 +44,9 @@ namespace Barotrauma
return (item!=null && Items[i]==null && container.CanBeContained(item));
}
public override bool TryPutItem(Item item, int i, bool createNetworkEvent)
public override bool TryPutItem(Item item, int i, bool allowSwapping, bool createNetworkEvent)
{
bool wasPut = base.TryPutItem(item, i, createNetworkEvent);
bool wasPut = base.TryPutItem(item, i, allowSwapping, createNetworkEvent);
if (wasPut)
{
+9 -1
View File
@@ -289,7 +289,15 @@ namespace Barotrauma.Networking
{
string denyMessage = inc.ReadString();
new GUIMessageBox("Couldn't connect to server", denyMessage);
if (denyMessage == "Password required!" || denyMessage == "Wrong password!")
{
GameMain.ServerListScreen.JoinServer(serverIP, true);
}
else
{
new GUIMessageBox("Couldn't connect to server", denyMessage);
}
connectCanceled = true;
}
+11 -6
View File
@@ -167,7 +167,7 @@ namespace Barotrauma.Networking
{
restClient = new RestClient(NetConfig.MasterServerUrl);
}
var request = new RestRequest("masterserver2.php", Method.GET);
request.AddParameter("action", "addserver");
request.AddParameter("servername", name);
@@ -631,12 +631,17 @@ namespace Barotrauma.Networking
return;
}
#if !DEBUG
if (userPassword != password)
#if DEBUG
if (!string.IsNullOrWhiteSpace(password) && string.IsNullOrWhiteSpace(userPassword))
{
inc.SenderConnection.Deny("Password required!");
DebugConsole.NewMessage(name + " couldn't join the server (no password)", Color.Red);
return;
}
else if (userPassword != password)
{
inc.SenderConnection.Deny("Wrong password!");
DebugConsole.NewMessage(name +" couldn't join the server (wrong password)", Color.Red);
DebugConsole.NewMessage(name + " couldn't join the server (wrong password)", Color.Red);
return;
}
else if (version != GameMain.Version.ToString())
@@ -657,7 +662,7 @@ namespace Barotrauma.Networking
DebugConsole.NewMessage(name + " couldn't join the server (wrong content package hash)", Color.Red);
return;
}
else if (ConnectedClients.Find(c => c.name.ToLower() == name.ToLower() && c.ID!=userID) != null)
else if (ConnectedClients.Find(c => c.name.ToLower() == name.ToLower() && c.ID != userID) != null)
{
inc.SenderConnection.Deny("The name ''" + name + "'' is already in use. Please choose another name.");
DebugConsole.NewMessage(name + " couldn't join the server (name already in use)", Color.Red);
@@ -160,6 +160,8 @@ namespace Barotrauma.Networking
{
float sendingTime = message.ReadFloat();
sendingTime = (float)message.SenderConnection.GetLocalTime(sendingTime);
byte msgCount = message.ReadByte();
long currPos = message.PositionInBytes;
@@ -298,6 +298,10 @@ namespace Barotrauma
{
savePath = Path.Combine(Path.GetDirectoryName(Submarine.Loaded.FilePath), savePath);
}
else
{
savePath = Path.Combine(Submarine.SavePath, savePath);
}
Submarine.SaveCurrent(savePath);
Submarine.Loaded.CheckForErrors();
@@ -293,17 +293,22 @@ namespace Barotrauma
return false;
}
CoroutineManager.StartCoroutine(JoinServer(ip));
CoroutineManager.StartCoroutine(ConnectToServer(ip, serverList.Selected != null && (serverList.Selected.GetChild("password") as GUITickBox).Selected));
return true;
}
private IEnumerable<object> JoinServer(string ip)
public void JoinServer(string ip, bool hasPassword)
{
CoroutineManager.StartCoroutine(ConnectToServer(ip, hasPassword));
}
private IEnumerable<object> ConnectToServer(string ip, bool hasPassword)
{
string selectedPassword = "";
if (serverList.Selected!=null && (serverList.Selected.GetChild("password") as GUITickBox).Selected)
if (hasPassword)
{
var msgBox = new GUIMessageBox("Password required:", "", new string[] { "OK", "Cancel" });
var passwordBox = new GUITextBox(new Rectangle(0,40,150,25), Alignment.TopLeft, GUI.Style, msgBox.children[0]);
+139
View File
@@ -0,0 +1,139 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Barotrauma
{
/// <summary>
/// Mersenne Twister based random
/// </summary>
public sealed class MTRandom : Random
{
private const int N = 624;
private const int M = 397;
private const uint MATRIX_A = 0x9908b0dfU;
private const uint UPPER_MASK = 0x80000000U;
private const uint LOWER_MASK = 0x7fffffffU;
private const uint TEMPER1 = 0x9d2c5680U;
private const uint TEMPER2 = 0xefc60000U;
private const int TEMPER3 = 11;
private const int TEMPER4 = 7;
private const int TEMPER5 = 15;
private const int TEMPER6 = 18;
private UInt32[] mt;
private int mti;
private UInt32[] mag01;
private const double c_realUnitInt = 1.0 / ((double)int.MaxValue + 1.0);
/// <summary>
/// Constructor with randomized seed
/// </summary>
public MTRandom()
{
Initialize((uint)Environment.TickCount);
}
/// <summary>
/// Constructor with provided 32 bit seed
/// </summary>
[CLSCompliant(false)]
public MTRandom(int seed)
{
Initialize((uint)Math.Abs(seed));
}
/// <summary>
/// (Re)initialize this instance with provided 32 bit seed
/// </summary>
[CLSCompliant(false)]
private void Initialize(uint seed)
{
mt = new UInt32[N];
mti = N + 1;
mag01 = new UInt32[] { 0x0U, MATRIX_A };
mt[0] = seed;
for (int i = 1; i < N; i++)
mt[i] = (UInt32)(1812433253 * (mt[i - 1] ^ (mt[i - 1] >> 30)) + i);
}
/// <summary>
/// Generates a random value from UInt32.MinValue to UInt32.MaxValue, inclusively
/// </summary>
[CLSCompliant(false)]
private uint NextUInt32()
{
UInt32 y;
if (mti >= N)
{
GenRandAll();
mti = 0;
}
y = mt[mti++];
y ^= (y >> TEMPER3);
y ^= (y << TEMPER4) & TEMPER1;
y ^= (y << TEMPER5) & TEMPER2;
y ^= (y >> TEMPER6);
return y;
}
/// <summary>
/// Generates a random value that is greater or equal than 0 and less than Int32.MaxValue
/// </summary>
public override int Next()
{
var retval = (int)(0x7FFFFFFF & NextUInt32());
if (retval == 0x7FFFFFFF)
return NextInt32();
return retval;
}
/// <summary>
/// Returns a random value is greater or equal than 0 and less than maxValue
/// </summary>
public override int Next(int maxValue)
{
return (int)(NextDouble() * maxValue);
}
/// <summary>
/// Generates a random value greater or equal than 0 and less or equal than Int32.MaxValue (inclusively)
/// </summary>
public int NextInt32()
{
return (int)(0x7FFFFFFF & NextUInt32());
}
/// <summary>
/// Returns random value larger or equal to 0.0 and less than 1.0
/// </summary>
public override double NextDouble()
{
return c_realUnitInt * NextInt32();
}
private void GenRandAll()
{
int kk = 1;
UInt32 y;
UInt32 p;
y = mt[0] & UPPER_MASK;
do
{
p = mt[kk];
mt[kk - 1] = mt[kk + (M - 1)] ^ ((y | (p & LOWER_MASK)) >> 1) ^ mag01[p & 1];
y = p & UPPER_MASK;
} while (++kk < N - M + 1);
do
{
p = mt[kk];
mt[kk - 1] = mt[kk + (M - N - 1)] ^ ((y | (p & LOWER_MASK)) >> 1) ^ mag01[p & 1];
y = p & UPPER_MASK;
} while (++kk < N);
p = mt[0];
mt[N - 1] = mt[M - 1] ^ ((y | (p & LOWER_MASK)) >> 1) ^ mag01[p & 1];
}
}
}
+4 -3
View File
@@ -1,4 +1,5 @@
using Microsoft.Xna.Framework;
using Lidgren.Network;
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -9,11 +10,11 @@ namespace Barotrauma
static class Rand
{
private static Random localRandom = new Random();
private static Random syncedRandom = new Random();
private static Random syncedRandom = new MTRandom();
public static void SetSyncedSeed(int seed)
{
syncedRandom = new Random(seed);
syncedRandom = new MTRandom(seed);
}
public static float Range(float minimum, float maximum, bool local = true)
+6
View File
@@ -2,6 +2,12 @@
v0.3.4.0
---------------------------------------------------------------------------------------------------------
Multiplayer:
---------------------------------------------------------------------------------------------------------
v0.3.4.0
---------------------------------------------------------------------------------------------------------
Multiplayer:
- missing submarine files can be downloaded from the server host
- player syncing bugfixes (aiming is visible to other players, smoother movement in water)
Binary file not shown.