(49d6e0ff6) Fixed an ID mismatch problem that occasionally caused clients to get kicked out in the multiplayer campaign. Closes #1603, closes #1562

This commit is contained in:
Joonas Rikkonen
2019-06-13 11:46:03 +03:00
parent cdb2476d51
commit 40aac0de8f
3 changed files with 84 additions and 6 deletions

View File

@@ -894,6 +894,75 @@ namespace Barotrauma
return configFile;
}
private static IEnumerable<string> characterConfigFiles;
private static IEnumerable<string> CharacterConfigFiles
{
#if SERVER
if (GameMain.Server != null && IsRemotePlayer)
{
if (characterConfigFiles == null)
{
case InputType.Left:
return !(dequeuedInput.HasFlag(InputNetFlags.Left)) && (prevDequeuedInput.HasFlag(InputNetFlags.Left));
case InputType.Right:
return !(dequeuedInput.HasFlag(InputNetFlags.Right)) && (prevDequeuedInput.HasFlag(InputNetFlags.Right));
case InputType.Up:
return !(dequeuedInput.HasFlag(InputNetFlags.Up)) && (prevDequeuedInput.HasFlag(InputNetFlags.Up));
case InputType.Down:
return !(dequeuedInput.HasFlag(InputNetFlags.Down)) && (prevDequeuedInput.HasFlag(InputNetFlags.Down));
case InputType.Run:
return !(dequeuedInput.HasFlag(InputNetFlags.Run)) && (prevDequeuedInput.HasFlag(InputNetFlags.Run));
case InputType.Crouch:
return !(dequeuedInput.HasFlag(InputNetFlags.Crouch)) && (prevDequeuedInput.HasFlag(InputNetFlags.Crouch));
case InputType.Select:
return dequeuedInput.HasFlag(InputNetFlags.Select); //TODO: clean up the way this input is registered
case InputType.Deselect:
return dequeuedInput.HasFlag(InputNetFlags.Deselect);
case InputType.Health:
return dequeuedInput.HasFlag(InputNetFlags.Health);
case InputType.Grab:
return dequeuedInput.HasFlag(InputNetFlags.Grab);
case InputType.Use:
return !(dequeuedInput.HasFlag(InputNetFlags.Use)) && (prevDequeuedInput.HasFlag(InputNetFlags.Use));
case InputType.Shoot:
return !(dequeuedInput.HasFlag(InputNetFlags.Shoot)) && (prevDequeuedInput.HasFlag(InputNetFlags.Shoot));
case InputType.Ragdoll:
return !(dequeuedInput.HasFlag(InputNetFlags.Ragdoll)) && (prevDequeuedInput.HasFlag(InputNetFlags.Ragdoll));
default:
return false;
}
return characterConfigFiles;
}
}
/// <summary>
/// Searches for a character config file from all currently selected content packages,
/// or from a specific package if the contentPackage parameter is given.
/// </summary>
public static string GetConfigFile(string speciesName, ContentPackage contentPackage = null)
{
string configFile = null;
if (contentPackage == null)
{
configFile = GameMain.Instance.GetFilesOfType(ContentType.Character)
.FirstOrDefault(c => Path.GetFileName(c).ToLowerInvariant() == $"{speciesName.ToLowerInvariant()}.xml");
}
else
{
configFile = contentPackage.GetFilesOfType(ContentType.Character)?
.FirstOrDefault(c => Path.GetFileName(c).ToLowerInvariant() == $"{speciesName.ToLowerInvariant()}.xml");
}
#endif
if (configFile == null)
{
DebugConsole.ThrowError($"Couldn't find a config file for {speciesName} from the selected content packages!");
DebugConsole.ThrowError($"(The config file must end with \"{speciesName}.xml\")");
return string.Empty;
}
return configFile;
}
private static IEnumerable<string> characterConfigFiles;
private static IEnumerable<string> CharacterConfigFiles
{

View File

@@ -9,6 +9,7 @@ namespace Barotrauma
class Entity : ISpatialEntity
{
public const ushort NullEntityID = 0;
public const ushort EntitySpawnerID = ushort.MaxValue;
private static Dictionary<ushort, Entity> dictionary = new Dictionary<ushort, Entity>();
public static List<Entity> GetEntityList()
@@ -43,12 +44,19 @@ namespace Barotrauma
}
set
{
if (this is EntitySpawner) { return; }
if (value == NullEntityID)
{
DebugConsole.ThrowError("Cannot set the ID of an entity to " + NullEntityID +
"! The value is reserved for entity events referring to a non-existent (e.g. removed) entity.\n" + Environment.StackTrace);
return;
}
if (value == EntitySpawnerID)
{
DebugConsole.ThrowError("Cannot set the ID of an entity to " + EntitySpawnerID +
"! The value is reserved for EntitySpawner.\n" + Environment.StackTrace);
return;
}
if (dictionary.TryGetValue(id, out Entity thisEntity) && thisEntity == this)
{
@@ -107,15 +115,17 @@ namespace Barotrauma
this.Submarine = submarine;
//give a unique ID
id = FindFreeID(submarine == null ? (ushort)1 : submarine.IdOffset);
id = this is EntitySpawner ?
EntitySpawnerID :
FindFreeID(submarine == null ? (ushort)1 : submarine.IdOffset);
dictionary.Add(id, this);
}
public static ushort FindFreeID(ushort idOffset = 0)
{
//ushort.MaxValue - 1 because 0 is a reserved value
if (dictionary.Count >= ushort.MaxValue - 1)
//ushort.MaxValue - 2 because 0 and ushort.MaxValue are reserved values
if (dictionary.Count >= ushort.MaxValue - 2)
{
throw new Exception("Maximum amount of entities (" + (ushort.MaxValue - 1) + ") reached!");
}

View File

@@ -382,7 +382,6 @@ namespace Barotrauma
DockedTo = new List<Submarine>();
ID = ushort.MaxValue;
FreeID();
}
@@ -1405,7 +1404,7 @@ namespace Barotrauma
}
ID = (ushort)(ushort.MaxValue - Submarine.loaded.IndexOf(this));
ID = (ushort)(ushort.MaxValue - 1 - Submarine.loaded.IndexOf(this));
}
public static Submarine Load(XElement element, bool unloadPrevious)