diff --git a/Barotrauma/BarotraumaClient/Source/Characters/Animation/Ragdoll.cs b/Barotrauma/BarotraumaClient/Source/Characters/Animation/Ragdoll.cs
index bcf133b30..fa30d8a82 100644
--- a/Barotrauma/BarotraumaClient/Source/Characters/Animation/Ragdoll.cs
+++ b/Barotrauma/BarotraumaClient/Source/Characters/Animation/Ragdoll.cs
@@ -108,6 +108,61 @@ namespace Barotrauma
}
}
+ //unconscious/dead characters can't correct their position using AnimController movement
+ // -> we need to correct it manually
+ if (!character.AllowInput)
+ {
+ float mainLimbDistSqrd = Vector2.DistanceSquared(MainLimb.PullJointWorldAnchorA, Collider.SimPosition);
+ float mainLimbErrorTolerance = 0.1f;
+ //if the main limb is roughly at the correct position and the collider isn't moving (much at least),
+ //don't attempt to correct the position.
+ if (mainLimbDistSqrd > mainLimbErrorTolerance || Collider.LinearVelocity.LengthSquared() > 0.05f)
+ {
+ MainLimb.PullJointWorldAnchorB = Collider.SimPosition;
+ MainLimb.PullJointEnabled = true;
+ }
+ character.SelectedConstruction = character.MemState[0].SelectedItem;
+ }
+
+ if (character.MemState[0].Animation == AnimController.Animation.CPR)
+ {
+ character.AnimController.Anim = AnimController.Animation.CPR;
+ }
+ else if (character.AnimController.Anim == AnimController.Animation.CPR)
+ {
+ character.AnimController.Anim = AnimController.Animation.None;
+ }
+
+ Vector2 newVelocity = Collider.LinearVelocity;
+ Vector2 newPosition = Collider.SimPosition;
+ float newRotation = Collider.Rotation;
+ float newAngularVelocity = Collider.AngularVelocity;
+ Collider.CorrectPosition(character.MemState, out newPosition, out newVelocity, out newRotation, out newAngularVelocity);
+
+ newVelocity = newVelocity.ClampLength(100.0f);
+ if (!MathUtils.IsValid(newVelocity)) { newVelocity = Vector2.Zero; }
+ overrideTargetMovement = newVelocity.LengthSquared() > 0.01f ? newVelocity : Vector2.Zero;
+
+ Collider.LinearVelocity = newVelocity;
+ Collider.AngularVelocity = newAngularVelocity;
+
+ float distSqrd = Vector2.DistanceSquared(newPosition, Collider.SimPosition);
+ float errorTolerance = character.AllowInput ? 0.01f : 0.2f;
+ if (distSqrd > errorTolerance)
+ {
+ if (distSqrd > 10.0f || !character.AllowInput)
+ {
+ Collider.TargetRotation = newRotation;
+ SetPosition(newPosition, lerp: distSqrd < 5.0f, ignorePlatforms: false);
+ }
+ else
+ {
+ Collider.TargetRotation = newRotation;
+ Collider.TargetPosition = newPosition;
+ Collider.MoveToTargetPosition(true);
+ }
+ }
+
//unconscious/dead characters can't correct their position using AnimController movement
// -> we need to correct it manually
if (!character.AllowInput)
@@ -151,32 +206,34 @@ namespace Barotrauma
}
}
-
- if (character.MemLocalState.Count > 120) character.MemLocalState.RemoveRange(0, character.MemLocalState.Count - 120);
- character.MemState.Clear();
+ character.MemLocalState.Clear();
}
- }
-
- partial void ImpactProjSpecific(float impact, Body body)
- {
- float volume = MathHelper.Clamp(impact - 3.0f, 0.5f, 1.0f);
-
- if (body.UserData is Limb limb && character.Stun <= 0f)
+ else
{
- if (impact > 3.0f) { PlayImpactSound(limb); }
- }
- else if (body.UserData is Limb || body == Collider.FarseerBody)
- {
- if (!character.IsRemotePlayer && impact > ImpactTolerance)
+ //remove states with a timestamp (there may still timestamp-based states
+ //in the list if the controlled character switches from timestamp-based interpolation to ID-based)
+ character.MemState.RemoveAll(m => m.Timestamp > 0.0f);
+
+ for (int i = 0; i < character.MemLocalState.Count; i++)
{
- SoundPlayer.PlayDamageSound("LimbBlunt", strongestImpact, Collider);
+ if (character.Submarine == null)
+ {
+ //transform in-sub coordinates to outside coordinates
+ if (character.MemLocalState[i].Position.Y > lowestSubPos)
+ {
+ character.MemLocalState[i].TransformInToOutside();
+ }
+ }
+ else if (currentHull?.Submarine != null)
+ {
+ //transform outside coordinates to in-sub coordinates
+ if (character.MemLocalState[i].Position.Y < lowestSubPos)
+ {
+ character.MemLocalState[i].TransformOutToInside(currentHull.Submarine);
+ }
+ }
+
}
- }
- if (Character.Controlled == character)
- {
- GameMain.GameScreen.Cam.Shake = Math.Min(Math.Max(strongestImpact, GameMain.GameScreen.Cam.Shake), 3.0f);
- }
- }
if (character.MemState.Count < 1) return;
diff --git a/Barotrauma/BarotraumaClient/Source/Networking/SteamManager.cs b/Barotrauma/BarotraumaClient/Source/Networking/SteamManager.cs
index 9a729b108..94131a5b3 100644
--- a/Barotrauma/BarotraumaClient/Source/Networking/SteamManager.cs
+++ b/Barotrauma/BarotraumaClient/Source/Networking/SteamManager.cs
@@ -601,7 +601,7 @@ namespace Barotrauma.Steam
{
// TODO: If you create a new mod via the workshop interface and enable it, it will show the error msg, but still allows you to enable the content.
- if (File.Exists(newContentPackagePath))
+ if (File.Exists(newContentPackagePath) && !CheckFileEquality(newContentPackagePath, metaDataFilePath))
{
errorMsg = TextManager.Get("WorkshopErrorOverwriteOnEnable")
.Replace("[itemname]", item.Title)
@@ -613,7 +613,7 @@ namespace Barotrauma.Steam
foreach (ContentFile contentFile in contentPackage.Files)
{
string sourceFile = Path.Combine(item.Directory.FullName, contentFile.Path);
- if (File.Exists(sourceFile) && File.Exists(contentFile.Path))
+ if (File.Exists(sourceFile) && File.Exists(contentFile.Path) && !CheckFileEquality(sourceFile, contentFile.Path))
{
errorMsg = TextManager.Get("WorkshopErrorOverwriteOnEnable")
.Replace("[itemname]", item.Title)
@@ -685,6 +685,22 @@ namespace Barotrauma.Steam
return true;
}
+ private static bool CheckFileEquality(string filePath1, string filePath2)
+ {
+ if (filePath1 == filePath2)
+ {
+ return true;
+ }
+
+ using (FileStream fs1 = File.OpenRead(filePath1))
+ using (FileStream fs2 = File.OpenRead(filePath2))
+ {
+ Md5Hash hash1 = new Md5Hash(fs1);
+ Md5Hash hash2 = new Md5Hash(fs2);
+ return hash1.Hash == hash2.Hash;
+ }
+ }
+
///
/// Disables a workshop item by removing the files from the game folder.
///
diff --git a/Barotrauma/BarotraumaServer/Source/GameMain.cs b/Barotrauma/BarotraumaServer/Source/GameMain.cs
index ebf4486e2..ec81b52c3 100644
--- a/Barotrauma/BarotraumaServer/Source/GameMain.cs
+++ b/Barotrauma/BarotraumaServer/Source/GameMain.cs
@@ -162,6 +162,23 @@ namespace Barotrauma
}
}
+ ///
+ /// Returns the file paths of all files of the given type in the content packages.
+ ///
+ ///
+ /// If true, also returns files in content packages that are installed but not currently selected.
+ public IEnumerable GetFilesOfType(ContentType type, bool searchAllContentPackages = false)
+ {
+ if (searchAllContentPackages)
+ {
+ return ContentPackage.GetFilesOfType(ContentPackage.List, type);
+ }
+ else
+ {
+ return ContentPackage.GetFilesOfType(SelectedPackages, type);
+ }
+ }
+
///
/// Returns the file paths of all files of the given type in the currently selected content packages.
///
diff --git a/Barotrauma/BarotraumaShared/Source/Map/Md5Hash.cs b/Barotrauma/BarotraumaShared/Source/Map/Md5Hash.cs
index 47b1d3a26..e1e2c8776 100644
--- a/Barotrauma/BarotraumaShared/Source/Map/Md5Hash.cs
+++ b/Barotrauma/BarotraumaShared/Source/Map/Md5Hash.cs
@@ -8,44 +8,28 @@ namespace Barotrauma
{
public class Md5Hash
{
- private string hash;
- private string shortHash;
+ public string Hash { get; private set; }
- public string Hash
- {
- get
- {
- return hash;
- }
- }
-
- public string ShortHash
- {
- get
- {
- return shortHash;
- }
- }
+ public string ShortHash { get; private set; }
public Md5Hash(string md5Hash)
{
- this.hash = md5Hash;
-
- shortHash = GetShortHash(md5Hash);
+ this.Hash = md5Hash;
+ ShortHash = GetShortHash(md5Hash);
}
public Md5Hash(byte[] bytes)
{
- hash = CalculateHash(bytes);
+ Hash = CalculateHash(bytes);
- shortHash = GetShortHash(hash);
+ ShortHash = GetShortHash(Hash);
}
public Md5Hash(FileStream fileStream)
{
- hash = CalculateHash(fileStream);
+ Hash = CalculateHash(fileStream);
- shortHash = GetShortHash(hash);
+ ShortHash = GetShortHash(Hash);
}
public Md5Hash(XDocument doc)
@@ -56,14 +40,14 @@ namespace Barotrauma
byte[] inputBytes = Encoding.ASCII.GetBytes(docString);
- hash = CalculateHash(inputBytes);
+ Hash = CalculateHash(inputBytes);
- shortHash = GetShortHash(hash);
+ ShortHash = GetShortHash(Hash);
}
public override string ToString()
{
- return hash;
+ return Hash;
}
private string CalculateHash(FileStream stream)