diff --git a/Subsurface/Characters/AI/EnemyAIController.cs b/Subsurface/Characters/AI/EnemyAIController.cs index e80f694f3..3e18ecebf 100644 --- a/Subsurface/Characters/AI/EnemyAIController.cs +++ b/Subsurface/Characters/AI/EnemyAIController.cs @@ -380,27 +380,30 @@ namespace Subsurface Body closestBody = Map.CheckVisibility(rayStart, rayEnd); Structure closestStructure = (closestBody == null) ? null : closestBody.UserData as Structure; - if (targetCharacter != null) - { - //if target is a character that isn't visible, ignore - if (closestStructure != null) continue; + //if (targetCharacter != null) + //{ + // //if target is a character that isn't visible, ignore + // if (closestStructure != null) continue; - //prefer targets with low health - valueModifier = valueModifier / targetCharacter.Health; - } - else - { + // //prefer targets with low health + // valueModifier = valueModifier / targetCharacter.Health; + //} + //else + //{ if (targetDamageable != null) { - valueModifier = valueModifier / targetDamageable.Health; - + valueModifier = valueModifier / targetDamageable.Health; } else if (closestStructure!=null) { valueModifier = valueModifier / (closestStructure as IDamageable).Health; } + else + { + valueModifier = valueModifier / 1000.0f; + } - } + //} diff --git a/Subsurface/Characters/LimbAttack.cs b/Subsurface/Characters/Attack.cs similarity index 77% rename from Subsurface/Characters/LimbAttack.cs rename to Subsurface/Characters/Attack.cs index 3aa4f2968..650f17a03 100644 --- a/Subsurface/Characters/LimbAttack.cs +++ b/Subsurface/Characters/Attack.cs @@ -8,12 +8,26 @@ using System.Xml.Linq; namespace Subsurface { - public enum DamageType { None, Blunt, Slash }; + public enum DamageType { None, Blunt, Slash }; + + struct AttackResult + { + public readonly float damage; + public readonly float bleeding; + + public readonly bool hitArmor; + + public AttackResult(float damage, float bleeding, bool hitArmor=false) + { + this.damage = damage; + this.bleeding = bleeding; + + this.hitArmor = hitArmor; + } + } class Attack { - - public enum Type { None, PinchCW, PinchCCW @@ -67,7 +81,7 @@ namespace Subsurface priority = ToolBox.GetAttributeFloat(element, "priority", 1.0f); } - public void DoDamage(IDamageable target, Vector2 position, float deltaTime, bool playSound=true) + public AttackResult DoDamage(IDamageable target, Vector2 position, float deltaTime, bool playSound=true) { float damageAmount = 0.0f; //DamageSoundType damageSoundType = DamageSoundType.None; @@ -89,7 +103,14 @@ namespace Subsurface if (duration > 0.0f) damageAmount *= deltaTime; float bleedingAmount = (duration == 0.0f) ? bleedingDamage : bleedingDamage * deltaTime; - if (damageAmount>0.0f) target.AddDamage(position, damageType, damageAmount, bleedingAmount, stun, playSound); + if (damageAmount > 0.0f) + { + return target.AddDamage(position, damageType, damageAmount, bleedingAmount, stun, playSound); + } + else + { + return new AttackResult(0.0f, 0.0f); + } } } } diff --git a/Subsurface/Characters/Character.cs b/Subsurface/Characters/Character.cs index cbabf9a79..7130bbc6c 100644 --- a/Subsurface/Characters/Character.cs +++ b/Subsurface/Characters/Character.cs @@ -654,7 +654,7 @@ namespace Subsurface } } - public void AddDamage(Vector2 position, DamageType damageType, float amount, float bleedingAmount, float stun, bool playSound = false) + public AttackResult AddDamage(Vector2 position, DamageType damageType, float amount, float bleedingAmount, float stun, bool playSound = false) { animController.StunTimer = Math.Max(animController.StunTimer, stun); @@ -675,7 +675,7 @@ namespace Subsurface closestLimb.body.ApplyForce(pull*Math.Min(amount*100.0f, 100.0f)); - closestLimb.AddDamage(position, damageType, amount, bleedingAmount, playSound); + return closestLimb.AddDamage(position, damageType, amount, bleedingAmount, playSound); } diff --git a/Subsurface/Characters/HumanoidAnimController.cs b/Subsurface/Characters/HumanoidAnimController.cs index 7cf77748b..e2fe94c63 100644 --- a/Subsurface/Characters/HumanoidAnimController.cs +++ b/Subsurface/Characters/HumanoidAnimController.cs @@ -33,7 +33,7 @@ namespace Subsurface { case Physics.CollisionStairs: Structure structure = fixture.Body.UserData as Structure; - if (stairs == null) + if (stairs == null && (!inWater || TargetMovement.Y>0.0f)) { if (LowestLimb.SimPosition.Y=100.0f) //{ // bloodAmount *= 2; @@ -311,6 +317,8 @@ namespace Subsurface { Game1.particleManager.CreateParticle("waterblood", SimPosition, Vector2.Zero); } + + return new AttackResult(amount, bleedingAmount, hitArmor); } public void Update(float deltaTime) diff --git a/Subsurface/Characters/Ragdoll.cs b/Subsurface/Characters/Ragdoll.cs index 98f28e7d2..aabff7ca5 100644 --- a/Subsurface/Characters/Ragdoll.cs +++ b/Subsurface/Characters/Ragdoll.cs @@ -442,7 +442,7 @@ namespace Subsurface inWater = false; headInWater = false; - if (ConvertUnits.ToSimUnits(currentHull.Surface)-floorY> HeadPosition) + if (ConvertUnits.ToSimUnits(currentHull.Surface)-floorY> HeadPosition*0.95f) inWater = true; } diff --git a/Subsurface/Content/Characters/Crawler/crawler.xml b/Subsurface/Content/Characters/Crawler/crawler.xml index 6123d043a..f51510ed6 100644 --- a/Subsurface/Content/Characters/Crawler/crawler.xml +++ b/Subsurface/Content/Characters/Crawler/crawler.xml @@ -10,17 +10,17 @@ flip="true"> - + - + - + @@ -70,7 +70,7 @@ - diff --git a/Subsurface/Content/Sounds/Damage/HitArmor1.ogg b/Subsurface/Content/Sounds/Damage/HitArmor1.ogg new file mode 100644 index 000000000..a085ff2e5 Binary files /dev/null and b/Subsurface/Content/Sounds/Damage/HitArmor1.ogg differ diff --git a/Subsurface/Content/Sounds/Damage/HitArmor2.ogg b/Subsurface/Content/Sounds/Damage/HitArmor2.ogg new file mode 100644 index 000000000..6c5e91e5c Binary files /dev/null and b/Subsurface/Content/Sounds/Damage/HitArmor2.ogg differ diff --git a/Subsurface/Content/Sounds/Damage/HitArmor3.ogg b/Subsurface/Content/Sounds/Damage/HitArmor3.ogg new file mode 100644 index 000000000..89e13d422 Binary files /dev/null and b/Subsurface/Content/Sounds/Damage/HitArmor3.ogg differ diff --git a/Subsurface/Content/Sounds/sounds.xml b/Subsurface/Content/Sounds/sounds.xml index 34fa04a62..c9c2fa3b6 100644 --- a/Subsurface/Content/Sounds/sounds.xml +++ b/Subsurface/Content/Sounds/sounds.xml @@ -20,5 +20,9 @@ + + + + \ No newline at end of file diff --git a/Subsurface/DebugConsole.cs b/Subsurface/DebugConsole.cs index f49882672..a4c2e7dd0 100644 --- a/Subsurface/DebugConsole.cs +++ b/Subsurface/DebugConsole.cs @@ -209,11 +209,11 @@ namespace Subsurface Game1.lobbyScreen.Select(); break; case "savemap": - Map.Save("Content/SavedMaps/", commands[1]); + Map.Loaded.SaveAs("Content/SavedMaps/" + commands[1]); NewMessage("map saved", Color.Green); break; case "loadmap": - Map.Load("Content/SavedMaps/", commands[1]); + Map.Load("Content/SavedMaps/" + commands[1]); break; case "debugdraw": Hull.DebugDraw = !Hull.DebugDraw; diff --git a/Subsurface/Game1.cs b/Subsurface/Game1.cs index 1d94139f3..40837c7a5 100644 --- a/Subsurface/Game1.cs +++ b/Subsurface/Game1.cs @@ -145,6 +145,7 @@ namespace Subsurface AmbientSoundManager.Init("Content/Sounds/Sounds.xml"); + Map.PreloadMaps("Content/SavedMaps"); gameScreen = new GameScreen(graphics.GraphicsDevice); mainMenuScreen = new MainMenuScreen(this); lobbyScreen = new LobbyScreen(); @@ -152,6 +153,7 @@ namespace Subsurface editMapScreen = new EditMapScreen(); editCharacterScreen = new EditCharacterScreen(); + mainMenuScreen.Select(); } diff --git a/Subsurface/GameSession/GameSession.cs b/Subsurface/GameSession/GameSession.cs index 122b53868..47b8fd635 100644 --- a/Subsurface/GameSession/GameSession.cs +++ b/Subsurface/GameSession/GameSession.cs @@ -116,7 +116,7 @@ namespace Subsurface { if (saveFile == null) return false; - Map.Save(Path.GetDirectoryName(saveFile) + "/", Path.GetFileName(saveFile)); + Map.Loaded.SaveAs(Path.GetDirectoryName(saveFile) + "/"+ Path.GetFileName(saveFile)); crewManager.EndShift(); diff --git a/Subsurface/Items/Components/Container.cs b/Subsurface/Items/Components/Container.cs index 8536adae7..3e4e74a9e 100644 --- a/Subsurface/Items/Components/Container.cs +++ b/Subsurface/Items/Components/Container.cs @@ -242,6 +242,8 @@ namespace Subsurface.Items.Components public override void OnMapLoaded() { + if (itemIds == null) return; + for (int i = 0; i < itemIds.Length; i++) { Item item = MapEntity.FindEntityByID(itemIds[i]) as Item; diff --git a/Subsurface/Items/Components/Projectile.cs b/Subsurface/Items/Components/Projectile.cs index be4299b2b..8857103a7 100644 --- a/Subsurface/Items/Components/Projectile.cs +++ b/Subsurface/Items/Components/Projectile.cs @@ -157,37 +157,18 @@ namespace Subsurface.Items.Components //float damage = f1.Body.LinearVelocity.Length(); + AttackResult attackResult = new AttackResult(0.0f, 0.0f); if (attack!=null) { Limb limb; Structure structure; if ((limb = (f2.Body.UserData as Limb)) != null) { - attack.DoDamage(limb.character, item.SimPosition, 0.0f); - //limb.Damage += damage; - //limb.Bleeding += bleedingDamage; - - //if (bleedingDamage>0.0f) - //{ - // for (int i = 0; i < 5; i++ ) - // { - // Game1.particleManager.CreateParticle(limb.SimPosition, - // ToolBox.VectorToAngle(-f1.Body.LinearVelocity*0.5f) + ToolBox.RandomFloat(-0.5f, 0.5f), - // ToolBox.RandomFloat(1.0f, 3.0f), "blood"); - // } - - // Game1.particleManager.CreateParticle(limb.SimPosition, - // 0.0f, - // Vector2.Zero, "waterblood"); - //} - - //AmbientSoundManager.PlayDamageSound(DamageType.LimbBlunt, damage, limb.body.FarseerBody); + attackResult = attack.DoDamage(limb.character, item.SimPosition, 1.0f); } else if ((structure = (f2.Body.UserData as Structure)) != null) { - attack.DoDamage(structure, item.SimPosition, 0.0f); - - //AmbientSoundManager.PlayDamageSound(DamageType.StructureBlunt, damage, f2.Body); + attackResult = attack.DoDamage(structure, item.SimPosition, 1.0f); } } @@ -200,7 +181,11 @@ namespace Subsurface.Items.Components ignoredBodies.Clear(); - if (doesStick) + if (attackResult.hitArmor) + { + item.body.LinearVelocity *= 0.5f; + } + else if (doesStick) { Vector2 normal = contact.Manifold.LocalNormal; Vector2 dir = new Vector2( diff --git a/Subsurface/Items/Components/Signal/Connection.cs b/Subsurface/Items/Components/Signal/Connection.cs index 355ac550e..fe8330e78 100644 --- a/Subsurface/Items/Components/Signal/Connection.cs +++ b/Subsurface/Items/Components/Signal/Connection.cs @@ -398,6 +398,13 @@ namespace Subsurface.Items.Components { XElement newElement = new XElement(isOutput ? "output" : "input", new XAttribute("name", name)); + Array.Sort(wires, delegate(Wire wire1, Wire wire2) + { + if (wire1 == null) return 1; + if (wire2 == null) return -1; + return wire1.Item.ID.CompareTo(wire2.Item.ID); + }); + for (int i = 0; i < MaxLinked; i++ ) { if (wires[i] == null) continue; @@ -406,7 +413,7 @@ namespace Subsurface.Items.Components //int connectionIndex = recipient.item.Connections.FindIndex(x => x == recipient); newElement.Add(new XElement("link", - new XAttribute("w", (wires[i] == null) ? "-1" : wires[i].Item.ID.ToString()))); + new XAttribute("w", wires[i].Item.ID.ToString()))); } parentElement.Add(newElement); diff --git a/Subsurface/Items/Item.cs b/Subsurface/Items/Item.cs index c87ccf2ec..b7285b9c5 100644 --- a/Subsurface/Items/Item.cs +++ b/Subsurface/Items/Item.cs @@ -370,9 +370,11 @@ namespace Subsurface } - public void AddDamage(Vector2 position, DamageType damageType, float amount, float bleedingAmount, float stun, bool playSound = true) + public AttackResult AddDamage(Vector2 position, DamageType damageType, float amount, float bleedingAmount, float stun, bool playSound = true) { Condition -= amount; + + return new AttackResult(amount, 0.0f, false); } diff --git a/Subsurface/Map/IDamageable.cs b/Subsurface/Map/IDamageable.cs index b737175f5..29af336d4 100644 --- a/Subsurface/Map/IDamageable.cs +++ b/Subsurface/Map/IDamageable.cs @@ -14,6 +14,6 @@ namespace Subsurface get; } - void AddDamage(Vector2 position, DamageType damageType, float amount, float bleedingAmount, float stun, bool playSound=true); + AttackResult AddDamage(Vector2 position, DamageType damageType, float amount, float bleedingAmount, float stun, bool playSound=true); } } diff --git a/Subsurface/Map/Map.cs b/Subsurface/Map/Map.cs index b471e873e..ccd5a536b 100644 --- a/Subsurface/Map/Map.cs +++ b/Subsurface/Map/Map.cs @@ -17,18 +17,36 @@ namespace Subsurface None = 0, Left = 1, Right = 2 } - static class Map + class Map { - static string MapFolder = "Content/SavedMaps"; + static string MapFolder; + MapHash mapHash; - public static Vector2 gridSize = new Vector2(16.0f, 16.0f); + public static List SavedMaps = new List(); + + private static Map loaded; + + //public static Map Loaded + //{ + // get { return loaded; } + // set { loaded = value; } + //} + + + public static readonly Vector2 gridSize = new Vector2(16.0f, 16.0f); private static Vector2 lastPickedPosition; private static float lastPickedFraction; - private static Rectangle borders; + private Rectangle borders; - private static string filePath; + private string filePath; + private string name; + + public string Name + { + get { return name; } + } public static Vector2 LastPickedPosition { @@ -40,12 +58,31 @@ namespace Subsurface get { return lastPickedFraction; } } - public static Rectangle Borders + public MapHash MapHash { - get { return borders; } + get + { + XDocument doc = OpenDoc(filePath); + mapHash = new MapHash(doc); + + return mapHash; + } } - public static string FilePath + public static Map Loaded + { + get { return loaded; } + } + + public static Rectangle Borders + { + get + { + return (loaded==null) ? Rectangle.Empty : loaded.borders; + } + } + + public string FilePath { get { return filePath; } } @@ -223,38 +260,51 @@ namespace Subsurface return true; } - public static void Save(string filePath, string fileName) + + public void Save() { - if (fileName==null) - { - DebugConsole.ThrowError("No save file selected"); - return; - } + SaveAs(filePath); + } + + public void SaveAs(string filePath) + { + //if (filePath=="") + //{ + // DebugConsole.ThrowError("No save file selected"); + // return; + //} XDocument doc = new XDocument( - new XElement((XName)fileName)); + new XElement((XName)name)); foreach (MapEntity e in MapEntity.mapEntityList) { e.Save(doc); } + mapHash = new MapHash(doc); + doc.Root.Add(new XAttribute("md5hash", mapHash.MD5Hash)); + try { string docString = doc.ToString(); - ToolBox.CompressStringToFile(filePath+fileName+".gz", doc.ToString()); + ToolBox.CompressStringToFile(filePath+".gz", doc.ToString()); } catch { - DebugConsole.ThrowError("Saving map ''" + filePath + fileName + "'' failed!"); + DebugConsole.ThrowError("Saving map ''" + filePath + "'' failed!"); } - //doc.Save(filePath + fileName); + doc.Save(filePath); } - public static string[] GetMapFilePaths() + public static void PreloadMaps(string mapFolder) { - string[] mapFilePaths; + MapFolder = mapFolder; + + //string[] mapFilePaths; + Unload(); + SavedMaps.Clear(); if (!Directory.Exists(MapFolder)) { @@ -266,10 +316,12 @@ namespace Subsurface { DebugConsole.ThrowError("Directory ''Content/SavedMaps'' not found and creating the directory failed."); - return null; + return; } } + string[] mapFilePaths; + try { mapFilePaths = Directory.GetFiles(MapFolder); @@ -277,21 +329,42 @@ namespace Subsurface catch (Exception e) { DebugConsole.ThrowError("Couldn't open directory ''Content/SavedMaps''!", e); - return null; + return; } - return mapFilePaths; + foreach (string mapPath in mapFilePaths) + { + //Map savedMap = new Map(mapPath); + SavedMaps.Add(new Map(mapPath)); + } } - public static void Load(string filePath, string fileName) + public Map(string filePath, string mapHash="") { - Load(filePath + fileName); + this.filePath = filePath; + this.name = Path.GetFileNameWithoutExtension(filePath); + + if (mapHash != "") + { + this.mapHash = new MapHash(mapHash); + } + else + { + //XDocument doc = OpenDoc(filePath); + + //string md5Hash = ToolBox.GetAttributeString(doc.Root, "md5hash", ""); + //if (md5Hash == "" || md5Hash.Length < 16) + //{ + // DebugConsole.ThrowError("Couldn't find a valid MD5 hash in the map file"); + //} + + //this.mapHash = new MapHash(md5Hash); + } + } - public static void Load(string file) + private XDocument OpenDoc(string file) { - Clear(); - filePath = file; XDocument doc = null; string extension = ""; @@ -302,16 +375,16 @@ namespace Subsurface catch { DebugConsole.ThrowError("Couldn't load map ''" + file + "! (Unrecognized file extension)"); - return; + return null; } - if (extension==".gz") + if (extension == ".gz") { Stream stream = ToolBox.DecompressFiletoStream(file); if (stream == null) { DebugConsole.ThrowError("Loading map ''" + file + "'' failed!"); - return; + return null; } try @@ -325,19 +398,37 @@ namespace Subsurface catch { DebugConsole.ThrowError("Loading map ''" + file + "'' failed!"); - return; + return null; } } - else if (extension ==".xml") + else if (extension == ".xml") { - doc = XDocument.Load(file); + try + { + doc = XDocument.Load(file); + } + + catch + { + DebugConsole.ThrowError("Loading map ''" + file + "'' failed!"); + return null; + } } else { - DebugConsole.ThrowError("Couldn't load map ''"+file+"! (Unrecognized file extension)"); - return; + DebugConsole.ThrowError("Couldn't load map ''" + file + "! (Unrecognized file extension)"); + return null; } - + + return doc; + } + + public void Load() + { + //string file = filePath; + + XDocument doc = OpenDoc(filePath); + if (doc == null) return; foreach (XElement element in doc.Root.Elements()) { @@ -350,13 +441,13 @@ namespace Subsurface t = Type.GetType("Subsurface." + typeName + ", Subsurface", true, true); if (t == null) { - DebugConsole.ThrowError("Error in " + file + "! Could not find a entity of the type ''" + typeName + "''."); + DebugConsole.ThrowError("Error in " + filePath + "! Could not find a entity of the type ''" + typeName + "''."); continue; } } catch (Exception e) { - DebugConsole.ThrowError("Error in " + file + "! Could not find a entity of the type ''" + typeName + "''.", e); + DebugConsole.ThrowError("Error in " + filePath + "! Could not find a entity of the type ''" + typeName + "''.", e); continue; } @@ -390,13 +481,29 @@ namespace Subsurface ic.OnMapLoaded(); } } + + loaded = this; } - - - public static void Clear() + public static void Load(string file) { - Map.filePath = ""; + Unload(); + + Map map = new Map(file); + map.Load(); + + } + + public static void Unload() + { + if (loaded==null)return; + loaded.Clear(); + loaded = null; + } + + private void Clear() + { + filePath = ""; if (Game1.gameScreen.Cam != null) Game1.gameScreen.Cam.TargetPos = Vector2.Zero; diff --git a/Subsurface/Map/MapHash.cs b/Subsurface/Map/MapHash.cs new file mode 100644 index 000000000..e82fa2a03 --- /dev/null +++ b/Subsurface/Map/MapHash.cs @@ -0,0 +1,65 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Cryptography; +using System.Text; +using System.Text.RegularExpressions; +using System.Xml.Linq; + +namespace Subsurface +{ + class MapHash + { + private string md5Hash; + private string shortHash; + + public string MD5Hash + { + get + { + return md5Hash; + } + } + + public string ShortHash + { + get + { + return shortHash; + } + } + + public MapHash(string md5Hash) + { + this.md5Hash = md5Hash; + + shortHash = GetShortHash(md5Hash); + } + + public MapHash(XDocument doc) + { + string docString = Regex.Replace(doc.ToString(), @"\s+", ""); + // step 1, calculate MD5 hash from input + + MD5 md5 = MD5.Create(); + byte[] inputBytes = Encoding.ASCII.GetBytes(docString); + byte[] hash = md5.ComputeHash(inputBytes); + + // step 2, convert byte array to hex string + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < hash.Length; i++) + { + sb.Append(hash[i].ToString("X2")); + } + + md5Hash = sb.ToString(); + + shortHash = GetShortHash(md5Hash); + } + + private string GetShortHash(string fullHash) + { + return fullHash; + } + } +} diff --git a/Subsurface/Map/Structure.cs b/Subsurface/Map/Structure.cs index 7547fa831..d80521510 100644 --- a/Subsurface/Map/Structure.cs +++ b/Subsurface/Map/Structure.cs @@ -378,12 +378,12 @@ namespace Subsurface sections[sectionIndex].rect.Y - sections[sectionIndex].rect.Height / 2.0f); } - public void AddDamage(Vector2 position, DamageType damageType, float amount, float bleedingAmount, float stun, bool playSound = false) + public AttackResult AddDamage(Vector2 position, DamageType damageType, float amount, float bleedingAmount, float stun, bool playSound = false) { - if (!prefab.HasBody || prefab.IsPlatform) return; + if (!prefab.HasBody || prefab.IsPlatform) return new AttackResult(0.0f, 0.0f); int i = FindSectionIndex(ConvertUnits.ToDisplayUnits(position)); - if (i == -1) return; + if (i == -1) return new AttackResult(0.0f, 0.0f); Game1.particleManager.CreateParticle("dustcloud", ConvertUnits.ToSimUnits(SectionPosition(i)), 0.0f, 0.0f); @@ -394,6 +394,8 @@ namespace Subsurface } AddDamage(i, amount); + + return new AttackResult(amount, 0.0f); } private void SetDamage(int sectionIndex, float damage) diff --git a/Subsurface/Networking/GameClient.cs b/Subsurface/Networking/GameClient.cs index e3c6d7e38..4d7af6dca 100644 --- a/Subsurface/Networking/GameClient.cs +++ b/Subsurface/Networking/GameClient.cs @@ -225,8 +225,15 @@ namespace Subsurface.Networking int seed = inc.ReadInt32(); Game1.random = new Random(seed); - string mapFile = inc.ReadString(); - Map.Load(mapFile); + string mapName = inc.ReadString(); + string mapHash = inc.ReadString(); + + Game1.netLobbyScreen.TrySelectMap(mapName, mapHash); + + + //Map.Load(mapFile); + + double durationMinutes = inc.ReadDouble(); @@ -316,7 +323,7 @@ namespace Subsurface.Networking public void EndGame(string endMessage) { - Map.Clear(); + Map.Unload(); Game1.netLobbyScreen.Select(); diff --git a/Subsurface/Networking/GameServer.cs b/Subsurface/Networking/GameServer.cs index 7bd5ded11..a4b782e35 100644 --- a/Subsurface/Networking/GameServer.cs +++ b/Subsurface/Networking/GameServer.cs @@ -271,7 +271,9 @@ namespace Subsurface.Networking int seed = DateTime.Now.Millisecond; Game1.random = new Random(seed); - Map.Load(Game1.netLobbyScreen.SelectedMap); + Map selectedMap = Game1.netLobbyScreen.SelectedMap as Map; + + selectedMap.Load(); Game1.gameSession = new GameSession("", false, Game1.netLobbyScreen.GameDuration, Game1.netLobbyScreen.SelectedMode); Game1.gameSession.StartShift(1); @@ -305,7 +307,9 @@ namespace Subsurface.Networking msg.Write(seed); - msg.Write(Game1.netLobbyScreen.SelectedMap); + msg.Write(Game1.netLobbyScreen.SelectedMap.Name); + msg.Write(Game1.netLobbyScreen.SelectedMap.MapHash.MD5Hash); + msg.Write(Game1.netLobbyScreen.GameDuration.TotalMinutes); WriteCharacterData(msg, client.name, client.character); @@ -336,7 +340,7 @@ namespace Subsurface.Networking public void EndGame(string endMessage) { - Map.Clear(); + Map.Unload(); gameStarted = false; diff --git a/Subsurface/Screens/LobbyScreen.cs b/Subsurface/Screens/LobbyScreen.cs index c91b3f346..5477bbc9f 100644 --- a/Subsurface/Screens/LobbyScreen.cs +++ b/Subsurface/Screens/LobbyScreen.cs @@ -96,7 +96,7 @@ namespace Subsurface { base.Select(); - Map.Clear(); + Map.Unload(); UpdateCharacterLists(); @@ -213,7 +213,7 @@ namespace Subsurface private bool StartShift(GUIButton button, object selection) { - Map.Load("", Game1.gameSession.SaveFile); + Map.Load(Game1.gameSession.SaveFile); Game1.gameSession.StartShift(); diff --git a/Subsurface/Screens/MainMenu.cs b/Subsurface/Screens/MainMenu.cs index 26fa90f87..54a58cb1a 100644 --- a/Subsurface/Screens/MainMenu.cs +++ b/Subsurface/Screens/MainMenu.cs @@ -56,23 +56,23 @@ namespace Subsurface new GUITextBlock(new Rectangle(0, 30, 0, 30), "Selected map:", Color.Transparent, Color.Black, Alignment.Left, menuTabs[(int)Tabs.NewGame]); mapList = new GUIListBox(new Rectangle(0, 60, 200, 400), Color.White, menuTabs[1]); - string[] mapFilePaths = Map.GetMapFilePaths(); - if (mapFilePaths!=null) - { - foreach (string s in mapFilePaths) + //string[] mapFilePaths = Map.GetMapFilePaths(); + //if (mapFilePaths!=null) + //{ + foreach (Map map in Map.SavedMaps) { GUITextBlock textBlock = new GUITextBlock( new Rectangle(0, 0, 0, 25), - Path.GetFileNameWithoutExtension(s), + map.Name, GUI.style, Alignment.Left, Alignment.Left, mapList); textBlock.Padding = new Vector4(10.0f, 0.0f, 0.0f, 0.0f); - textBlock.UserData = s; + textBlock.UserData = map; } - if (mapFilePaths.Length > 0) mapList.Select(mapFilePaths[0]); - } + if (Map.SavedMaps.Count > 0) mapList.Select(Map.SavedMaps[0]); + //} button = new GUIButton(new Rectangle(0, 0, 100, 30), "Start", GUI.style, Alignment.Right | Alignment.Bottom, menuTabs[(int)Tabs.NewGame]); button.OnClicked = StartGame; @@ -146,9 +146,12 @@ namespace Subsurface private bool StartGame(GUIButton button, object obj) { - if (mapList.SelectedData == null) return false; - Game1.gameSession = new GameSession(mapList.SelectedData.ToString(), true, TimeSpan.Zero); + Map selectedMap = mapList.SelectedData as Map; + if (selectedMap == null) return false; + + + Game1.gameSession = new GameSession(selectedMap.FilePath, true, TimeSpan.Zero); Game1.lobbyScreen.Select(); diff --git a/Subsurface/Screens/NetLobbyScreen.cs b/Subsurface/Screens/NetLobbyScreen.cs index 3f3df070c..bdd1a4727 100644 --- a/Subsurface/Screens/NetLobbyScreen.cs +++ b/Subsurface/Screens/NetLobbyScreen.cs @@ -31,9 +31,9 @@ namespace Subsurface public bool isServer; - public string SelectedMap + public Map SelectedMap { - get { return mapList.SelectedData.ToString(); } + get { return mapList.SelectedData as Map; } } @@ -136,20 +136,19 @@ namespace Subsurface mapList.OnSelected = SelectMap; mapList.Enabled = (Game1.server!=null); - string[] mapFilePaths = Map.GetMapFilePaths(); - if (mapFilePaths != null) + if (Map.SavedMaps.Count>0) { - foreach (string s in mapFilePaths) + foreach (Map map in Map.SavedMaps) { GUITextBlock textBlock = new GUITextBlock( new Rectangle(0, 0, 0, 25), - Path.GetFileNameWithoutExtension(s), + map.Name, GUI.style, Alignment.Left, Alignment.Left, mapList); textBlock.Padding = new Vector4(10.0f, 0.0f, 0.0f, 0.0f); - textBlock.UserData = s; + textBlock.UserData = map; } } else @@ -194,7 +193,7 @@ namespace Subsurface modeList.OnSelected = Game1.server.UpdateNetLobby; durationBar.OnMoved = Game1.server.UpdateNetLobby; - if (mapFilePaths.Length > 0) mapList.Select(mapFilePaths[oldMapIndex]); + if (mapList.CountChildren > 0) mapList.Select(Map.SavedMaps[0]); if (GameMode.list.Count > 0) modeList.Select(GameMode.list[0]); } else @@ -245,8 +244,12 @@ namespace Subsurface { if (Game1.server != null) Game1.server.UpdateNetLobby(obj); - if ((string)obj == Map.FilePath) return true; - Map.Load((string)obj); + Map map = (Map)obj; + + //map already loaded + if (Map.Loaded!=null && map.FilePath == Map.Loaded.FilePath) return true; + + map.Load(); return true; } @@ -462,15 +465,60 @@ namespace Subsurface public void WriteData(NetOutgoingMessage msg) { - msg.Write(mapList.SelectedIndex); - msg.Write(modeList.SelectedIndex); + Map selectedMap = mapList.SelectedData as Map; + if (selectedMap==null) + { + msg.Write(" "); + msg.Write(" "); + } + else + { + msg.Write(selectedMap.Name); + msg.Write(selectedMap.MapHash.MD5Hash); + } + + msg.Write(modeList.SelectedIndex); msg.Write(durationBar.BarScroll); } + public bool TrySelectMap(string mapName, string md5Hash) + { + + Map map = Map.SavedMaps.Find(m => m.Name == mapName); + if (map==null) + { + DebugConsole.ThrowError("The map ''" + mapName + "'' has been selected by the server."); + DebugConsole.ThrowError("Matching map not found in your map folder."); + return false; + } + else + { + if (map.MapHash.MD5Hash!=md5Hash) + { + DebugConsole.ThrowError("Your version of the map file ''"+map.Name+"'' doesn't match the server's version!"); + DebugConsole.ThrowError("Your file: "+map.Name+"(MD5 hash : "+map.MapHash.MD5Hash+")"); + DebugConsole.ThrowError("Server's file: " + mapName + "(MD5 hash : " + md5Hash + ")"); + return false; + } + else + { + mapList.Select(map); + map.Load(); + return true; + } + } + } + public void ReadData(NetIncomingMessage msg) { - mapList.Select(msg.ReadInt32()); + string mapName = msg.ReadString(); + string md5Hash = msg.ReadString(); + + TrySelectMap(mapName, md5Hash); + + + //mapList.Select(msg.ReadInt32()); modeList.Select(msg.ReadInt32()); durationBar.BarScroll = msg.ReadFloat(); diff --git a/Subsurface/Sounds/AmbientSoundManager.cs b/Subsurface/Sounds/AmbientSoundManager.cs index 3bb42e95d..272686287 100644 --- a/Subsurface/Sounds/AmbientSoundManager.cs +++ b/Subsurface/Sounds/AmbientSoundManager.cs @@ -9,7 +9,11 @@ using Subsurface.Sounds; namespace Subsurface { - public enum DamageSoundType { None, StructureBlunt, StructureSlash, LimbBlunt, LimbSlash, Implode } + public enum DamageSoundType { + None, + StructureBlunt, StructureSlash, + LimbBlunt, LimbSlash, LimbArmor, + Implode } public struct DamageSound {