Index: binary-improvements/7dtd-server-fixes/7dtd-server-fixes.csproj
===================================================================
--- binary-improvements/7dtd-server-fixes/7dtd-server-fixes.csproj	(revision 323)
+++ binary-improvements/7dtd-server-fixes/7dtd-server-fixes.csproj	(revision 324)
@@ -60,4 +60,12 @@
       <Private>False</Private>
     </Reference>
+    <Reference Include="UnityEngine.CoreModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
+      <HintPath>..\7dtd-binaries\UnityEngine.CoreModule.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="UnityEngine.ImageConversionModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
+      <HintPath>..\7dtd-binaries\UnityEngine.ImageConversionModule.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
   </ItemGroup>
   <ItemGroup>
Index: binary-improvements/7dtd-server-fixes/src/API.cs
===================================================================
--- binary-improvements/7dtd-server-fixes/src/API.cs	(revision 323)
+++ binary-improvements/7dtd-server-fixes/src/API.cs	(revision 324)
@@ -1,33 +1,40 @@
 using System;
+using System.Collections.Generic;
 
 namespace AllocsFixes
 {
-	public class API : ModApiAbstract {
+	public class API : IModApi {
 
-		public override void GameAwake () {
+		public void GameAwake () {
 			StateManager.Awake ();
 		}
 
-		public override void GameShutdown () {
+		public void GameShutdown () {
 			StateManager.Shutdown ();
 		}
 		
-		public override void SavePlayerData (ClientInfo _cInfo, PlayerDataFile _playerDataFile) {
+		public void SavePlayerData (ClientInfo _cInfo, PlayerDataFile _playerDataFile) {
 			PlayerDataStuff.GM_SavePlayerData (_cInfo, _playerDataFile);
 		}
 
-		public override void PlayerLogin (ClientInfo _cInfo, string _compatibilityVersion) {
-		}
-		
-		public override void PlayerSpawning (ClientInfo _cInfo, int _chunkViewDim, PlayerProfile _playerProfile) {
+		public void PlayerSpawning (ClientInfo _cInfo, int _chunkViewDim, PlayerProfile _playerProfile) {
 			AllocsLogFunctions.RequestToSpawnPlayer (_cInfo, _chunkViewDim, _playerProfile);
 		}
 		
-		public override void PlayerDisconnected (ClientInfo _cInfo, bool _bShutdown) {
+		public void PlayerDisconnected (ClientInfo _cInfo, bool _bShutdown) {
 			AllocsLogFunctions.PlayerDisconnected (_cInfo, _bShutdown);
 		}
 
-		public override bool ChatMessage (ClientInfo _cInfo, EnumGameMessages _type, string _msg, string _mainName, bool _localizeMain, string _secondaryName, bool _localizeSecondary) {
+		public bool ChatMessage (ClientInfo _cInfo, EChatType _type, int _senderId, string _msg, string _mainName, bool _localizeMain, List<int> _recipientEntityIds) {
 			return ChatHookExample.Hook (_cInfo, _type, _msg, _mainName);
+		}
+
+		public void InitMod () {
+			ModEvents.GameAwake.RegisterHandler (GameAwake);
+			ModEvents.GameShutdown.RegisterHandler (GameShutdown);
+			ModEvents.SavePlayerData.RegisterHandler (SavePlayerData);
+			ModEvents.PlayerSpawning.RegisterHandler (PlayerSpawning);
+			ModEvents.PlayerDisconnected.RegisterHandler (PlayerDisconnected);
+			ModEvents.ChatMessage.RegisterHandler (ChatMessage);
 		}
 	}
Index: binary-improvements/7dtd-server-fixes/src/ChatHookExample.cs
===================================================================
--- binary-improvements/7dtd-server-fixes/src/ChatHookExample.cs	(revision 323)
+++ binary-improvements/7dtd-server-fixes/src/ChatHookExample.cs	(revision 324)
@@ -6,11 +6,10 @@
 		private const string ANSWER = "     [ff0000]I[-] [ff7f00]W[-][ffff00]A[-][80ff00]S[-] [00ffff]H[-][0080ff]E[-][0000ff]R[-][8b00ff]E[-]";
 
-		public static bool Hook (ClientInfo _cInfo, EnumGameMessages _type, string _message, string _playerName) {
-			if (_type == EnumGameMessages.Chat && !string.IsNullOrEmpty (_message)) {
-				if (_message.ToLower () == "/alloc") {
+		public static bool Hook (ClientInfo _cInfo, EChatType _type, string _message, string _playerName) {
+			if (!string.IsNullOrEmpty (_message)) {
+				if (_message.EqualsCaseInsensitive ("/alloc")) {
 					if (_cInfo != null) {
 						Log.Out ("Sent chat hook reply to {0}", _cInfo.playerId);
-						_cInfo.SendPackage (new NetPackageGameMessage (EnumGameMessages.Chat, ANSWER, "", false, "", false));
-						GameManager.Instance.GameMessageServer (_cInfo, EnumGameMessages.Chat, string.Format("!{0}", _message), _playerName, false, "", false);
+						_cInfo.SendPackage (new NetPackageChat(EChatType.Whisper, -1, ANSWER, "", false, null));
 					} else {
 						Log.Error ("ChatHookExample: Argument _cInfo null on message: {0}", _message);
Index: binary-improvements/7dtd-server-fixes/src/FileCache/AbstractCache.cs
===================================================================
--- binary-improvements/7dtd-server-fixes/src/FileCache/AbstractCache.cs	(revision 323)
+++ binary-improvements/7dtd-server-fixes/src/FileCache/AbstractCache.cs	(revision 324)
@@ -1,17 +1,8 @@
-using System;
-using System.Collections.Generic;
+namespace AllocsFixes.FileCache {
+    public abstract class AbstractCache {
+        public AbstractCache () {
+        }
 
-namespace AllocsFixes.FileCache
-{
-	public abstract class AbstractCache
-	{
-
-		public AbstractCache ()
-		{
-		}
-
-		public abstract byte[] GetFileContent (string filename);
-
-	}
+        public abstract byte[] GetFileContent (string filename);
+    }
 }
-
Index: binary-improvements/7dtd-server-fixes/src/FileCache/MapTileCache.cs
===================================================================
--- binary-improvements/7dtd-server-fixes/src/FileCache/MapTileCache.cs	(revision 323)
+++ binary-improvements/7dtd-server-fixes/src/FileCache/MapTileCache.cs	(revision 324)
@@ -1,5 +1,5 @@
 using System;
-using System.Collections.Generic;
 using System.IO;
+using UnityEngine;
 
 namespace AllocsFixes.FileCache
@@ -21,6 +21,6 @@
 		public MapTileCache (int _tileSize)
 		{
-			UnityEngine.Texture2D tex = new UnityEngine.Texture2D (_tileSize, _tileSize);
-			UnityEngine.Color nullColor = new UnityEngine.Color (0, 0, 0, 0);
+			Texture2D tex = new Texture2D (_tileSize, _tileSize);
+			Color nullColor = new Color (0, 0, 0, 0);
 			for (int x = 0; x < _tileSize; x++) {
 				for (int y = 0; y < _tileSize; y++) {
Index: binary-improvements/7dtd-server-fixes/src/JSON/JSONNumber.cs
===================================================================
--- binary-improvements/7dtd-server-fixes/src/JSON/JSONNumber.cs	(revision 323)
+++ binary-improvements/7dtd-server-fixes/src/JSON/JSONNumber.cs	(revision 324)
@@ -86,5 +86,5 @@
 				} else {
 					double number;
-					if (!Utils.TryParseDouble(sbNum.ToString (), out number)) {
+					if (!StringParsers.TryParseDouble(sbNum.ToString (), out number)) {
 						throw new MalformedJSONException ("Mantissa is not a valid decimal (\"" + sbNum.ToString () + "\")");
 					}
Index: binary-improvements/7dtd-server-fixes/src/PersistentData/Inventory.cs
===================================================================
--- binary-improvements/7dtd-server-fixes/src/PersistentData/Inventory.cs	(revision 323)
+++ binary-improvements/7dtd-server-fixes/src/PersistentData/Inventory.cs	(revision 324)
@@ -1,86 +1,87 @@
 using System;
 using System.Collections.Generic;
-using System.Runtime.Serialization;
-using System.Threading;
 
-namespace AllocsFixes.PersistentData
-{
-	[Serializable]
-	public class Inventory {
-		public List<InvItem> bag;
-		public List<InvItem> belt;
-		public InvItem[] equipment;
+namespace AllocsFixes.PersistentData {
+    [Serializable]
+    public class Inventory {
+        public List<InvItem> bag;
+        public List<InvItem> belt;
+        public InvItem[] equipment;
 
-		public Inventory () {
-			bag = new List<InvItem> ();
-			belt = new List<InvItem> ();
-			equipment = null;
-		}
+        public Inventory () {
+            bag = new List<InvItem> ();
+            belt = new List<InvItem> ();
+            equipment = null;
+        }
 
-		public void Update (PlayerDataFile pdf) {
-			lock (this) {
-				//Log.Out ("Updating player inventory - player id: " + pdf.id);
-				ProcessInv (bag, pdf.bag, pdf.id);
-				ProcessInv (belt, pdf.inventory, pdf.id);
-				ProcessEqu (pdf.equipment, pdf.id);
-			}
-		}
+        public void Update (PlayerDataFile pdf) {
+            lock (this) {
+                //Log.Out ("Updating player inventory - player id: " + pdf.id);
+                ProcessInv (bag, pdf.bag, pdf.id);
+                ProcessInv (belt, pdf.inventory, pdf.id);
+                ProcessEqu (pdf.equipment, pdf.id);
+            }
+        }
 
-		private void ProcessInv (List<InvItem> target, ItemStack[] sourceFields, int id) {
-			target.Clear ();
-			for (int i = 0; i < sourceFields.Length; i++) {
-				InvItem item = CreateInvItem (sourceFields [i].itemValue, sourceFields [i].count, id);
-				if (item != null && sourceFields [i].itemValue.Parts != null) {
-					ProcessParts (sourceFields [i].itemValue.Parts, item, id);
-				}
-				target.Add (item);
-			}
-		}
+        private void ProcessInv (List<InvItem> target, ItemStack[] sourceFields, int id) {
+            target.Clear ();
+            for (int i = 0; i < sourceFields.Length; i++) {
+                InvItem item = CreateInvItem (sourceFields [i].itemValue, sourceFields [i].count, id);
+                if (item != null && sourceFields [i].itemValue.Modifications != null) {
+                    ProcessParts (sourceFields [i].itemValue.Modifications, item, id);
+                }
 
-		private void ProcessEqu (Equipment sourceEquipment, int _playerId) {
-			equipment = new InvItem[sourceEquipment.GetSlotCount ()];
-			for (int i = 0; i < sourceEquipment.GetSlotCount (); i++) {
-				equipment [i] = CreateInvItem (sourceEquipment.GetSlotItem (i), 1, _playerId);
-			}
-		}
+                target.Add (item);
+            }
+        }
 
-		private void ProcessParts (ItemValue[] _parts, InvItem _item, int _playerId) {
-			InvItem[] itemParts = new InvItem[_parts.Length];
-			for (int i = 0; i < _parts.Length; i++) {
-				InvItem partItem = CreateInvItem (_parts [i], 1, _playerId);
-				if (partItem != null && _parts [i].Parts != null) {
-					ProcessParts (_parts [i].Parts, partItem, _playerId);
-				}
-				itemParts [i] = partItem;
-			}
-			_item.parts = itemParts;
-		}
+        private void ProcessEqu (Equipment sourceEquipment, int _playerId) {
+            equipment = new InvItem[sourceEquipment.GetSlotCount ()];
+            for (int i = 0; i < sourceEquipment.GetSlotCount (); i++) {
+                equipment [i] = CreateInvItem (sourceEquipment.GetSlotItem (i), 1, _playerId);
+            }
+        }
 
-		private InvItem CreateInvItem (ItemValue _itemValue, int _count, int _playerId) {
-			if (_count > 0 && _itemValue != null && !_itemValue.Equals (ItemValue.None)) {
-				ItemClass itemClass = ItemClass.list [_itemValue.type];
-				int maxAllowed = itemClass.Stacknumber.Value;
-				string name = itemClass.GetItemName ();
+        private void ProcessParts (ItemValue[] _parts, InvItem _item, int _playerId) {
+            InvItem[] itemParts = new InvItem[_parts.Length];
+            for (int i = 0; i < _parts.Length; i++) {
+                InvItem partItem = CreateInvItem (_parts [i], 1, _playerId);
+                if (partItem != null && _parts [i].Modifications != null) {
+                    ProcessParts (_parts [i].Modifications, partItem, _playerId);
+                }
 
-				if (_count > maxAllowed) {
-					Log.Out ("Player with ID " + _playerId + " has stack for \"" + name + "\" greater than allowed (" + _count + " > " + maxAllowed + ")");
-				}
+                itemParts [i] = partItem;
+            }
 
-				InvItem item = null;
-				if (_itemValue.HasQuality) {
-					item = new InvItem (name, _count, _itemValue.Quality, _itemValue.MaxUseTimes, _itemValue.UseTimes);
-				} else {
-					item = new InvItem (name, _count, -1, _itemValue.MaxUseTimes, _itemValue.UseTimes);
-				}
+            _item.parts = itemParts;
+        }
 
-				item.icon = itemClass.GetIconName ();
+        private InvItem CreateInvItem (ItemValue _itemValue, int _count, int _playerId) {
+            if (_count > 0 && _itemValue != null && !_itemValue.Equals (ItemValue.None)) {
+                ItemClass itemClass = ItemClass.list [_itemValue.type];
+                int maxAllowed = itemClass.Stacknumber.Value;
+                string name = itemClass.GetItemName ();
 
-				item.iconcolor = AllocsUtils.ColorToHex (itemClass.GetIconTint ());
-                    
-				return item;
-			} else {
-				return null;
-			}
-		}
-	}
+                if (_count > maxAllowed) {
+                    Log.Out ("Player with ID " + _playerId + " has stack for \"" + name + "\" greater than allowed (" +
+                             _count + " > " + maxAllowed + ")");
+                }
+
+                InvItem item = null;
+                if (_itemValue.HasQuality) {
+                    item = new InvItem (name, _count, _itemValue.Quality, _itemValue.MaxUseTimes, _itemValue.UseTimes);
+                } else {
+                    item = new InvItem (name, _count, -1, _itemValue.MaxUseTimes, _itemValue.UseTimes);
+                }
+
+                item.icon = itemClass.GetIconName ();
+
+                item.iconcolor = AllocsUtils.ColorToHex (itemClass.GetIconTint ());
+
+                return item;
+            } else {
+                return null;
+            }
+        }
+    }
 }
Index: binary-improvements/7dtd-server-fixes/src/PersistentData/Player.cs
===================================================================
--- binary-improvements/7dtd-server-fixes/src/PersistentData/Player.cs	(revision 323)
+++ binary-improvements/7dtd-server-fixes/src/PersistentData/Player.cs	(revision 324)
@@ -3,224 +3,215 @@
 using UnityEngine;
 
-namespace AllocsFixes.PersistentData
-{
-	[Serializable]
-	public class Player
-	{
-		private readonly string steamId;
-		private int entityId;
-		private string name;
-		private string ip;
-		private long totalPlayTime;
-		[OptionalField]
-		private DateTime
-			lastOnline;
-		private Inventory inventory;
-		[OptionalField]
-		private int
-			lastPositionX, lastPositionY, lastPositionZ;
-		[OptionalField][Obsolete("experience no longer available, use level and expToNextLevel instead")]
-		private uint experience;
-		[OptionalField]
-		private bool chatMuted;
-		[OptionalField]
-		private int maxChatLength;
-		[OptionalField]
-		private string chatColor;
-		[OptionalField]
-		private bool chatName;
-		[OptionalField]
-		private uint expToNextLevel;
-		[OptionalField]
-		private int level;
-
-		[NonSerialized]
-		private ClientInfo
-			clientInfo;
-
-		public string SteamID {
-			get { return steamId; }
-		}
-
-		public int EntityID {
-			get { return entityId; }
-		}
-
-		public string Name {
-			get { return name == null ? string.Empty : name; }
-		}
-
-		public string IP {
-			get { return ip == null ? string.Empty : ip; }
-		}
-
-		public Inventory Inventory {
-			get {
-				if (inventory == null)
-					inventory = new Inventory ();
-				return inventory;
-			}
-		}
-
-		public bool IsOnline {
-			get { return clientInfo != null; }
-		}
-
-		public ClientInfo ClientInfo {
-			get { return clientInfo; }
-		}
-
-		public EntityPlayer Entity {
-			get {
-				if (IsOnline) {
-					return GameManager.Instance.World.Players.dict [clientInfo.entityId];
-				} else {
-					return null;
-				}
-			}
-		}
-
-		public long TotalPlayTime {
-			get {
-				if (IsOnline) {
-					return totalPlayTime + (long)(DateTime.Now - lastOnline).TotalSeconds;
-				} else {
-					return totalPlayTime;
-				}
-			}
-		}
-
-		public DateTime LastOnline {
-			get {
-				if (IsOnline)
-					return DateTime.Now;
-				else
-					return lastOnline;
-			}
-		}
-
-		public Vector3i LastPosition {
-			get {
-				if (IsOnline)
-					return new Vector3i (Entity.GetPosition ());
-				else
-					return new Vector3i (lastPositionX, lastPositionY, lastPositionZ);
-			}
-		}
-
-		public bool LandProtectionActive {
-			get {
-				return GameManager.Instance.World.IsLandProtectionValidForPlayer (GameManager.Instance.GetPersistentPlayerList ().GetPlayerData (SteamID));
-			}
-		}
-
-		public float LandProtectionMultiplier {
-			get {
-				return GameManager.Instance.World.GetLandProtectionHardnessModifierForPlayer (GameManager.Instance.GetPersistentPlayerList ().GetPlayerData (SteamID));
-			}
-		}
-
-
-		[Obsolete("Experience no longer available, use Level instead")]
-		public uint Experience {
-			get {
-				return 0;
-			}
-		}
-
-		public float Level {
-			get {
-				float expForNextLevel = (int)Math.Min ((Progression.BaseExpToLevel * Mathf.Pow (Progression.ExpMultiplier, level + 1)), int.MaxValue);
-				float fLevel = level + 1f - ((float)expToNextLevel / expForNextLevel);
-				return fLevel;
-			}
-		}
-
-		public bool IsChatMuted{
-			get {
-				return chatMuted;
-			}
-			set {
-				chatMuted = value;
-			}
-		}
-
-		public int MaxChatLength {
-			get {
-				if (maxChatLength == 0 ) {
-					maxChatLength = 255;
-				}
-				return maxChatLength;
-			}
-			set {
-				maxChatLength = value;
-			}
-		}
-
-		public string ChatColor {
-			get {
-				if (chatColor == null || chatColor == "") {
-					chatColor = "";
-				}
-				return chatColor;
-			}
-
-			set {
-				chatColor = value;
-			}
-		}
-
-		public bool ChatName {
-			get {
-				return chatName;
-			}
-
-			set {
-				chatName = value;
-			}
-		}
-
-		public void SetOffline ()
-		{
-			if (clientInfo != null) {
-				Log.Out ("Player set to offline: " + steamId);
-				lastOnline = DateTime.Now;
-				try {
-					Vector3i lastPos = new Vector3i (Entity.GetPosition ());
-					lastPositionX = lastPos.x;
-					lastPositionY = lastPos.y;
-					lastPositionZ = lastPos.z;
-					totalPlayTime += (long)(Time.timeSinceLevelLoad - Entity.CreationTimeSinceLevelLoad);
-				} catch (NullReferenceException) {
-					Log.Out ("Entity not available. Something seems to be wrong here...");
-				}
-				clientInfo = null;
-			}
-		}
-
-		public void SetOnline (ClientInfo ci)
-		{
-			Log.Out ("Player set to online: " + steamId);
-			clientInfo = ci;
-			entityId = ci.entityId;
-			name = ci.playerName;
-			ip = ci.ip;
-			lastOnline = DateTime.Now;
-		}
-
-		public void Update (PlayerDataFile _pdf) {
-			experience = 0;
-			expToNextLevel = _pdf.experience;
-			level = _pdf.level;
-			inventory.Update (_pdf);
-		}
-
-		public Player (string steamId)
-		{
-			this.steamId = steamId;
-			this.inventory = new Inventory ();
-		}
-
-
-	}
+namespace AllocsFixes.PersistentData {
+    [Serializable]
+    public class Player {
+        private readonly string steamId;
+        private int entityId;
+        private string name;
+        private string ip;
+        private long totalPlayTime;
+
+        [OptionalField] private DateTime
+            lastOnline;
+
+        private Inventory inventory;
+
+        [OptionalField] private int
+            lastPositionX, lastPositionY, lastPositionZ;
+
+        [OptionalField] [Obsolete ("experience no longer available, use level and expToNextLevel instead")]
+        private uint experience;
+
+        [OptionalField] private bool chatMuted;
+        [OptionalField] private int maxChatLength;
+        [OptionalField] private string chatColor;
+        [OptionalField] private bool chatName;
+        [OptionalField] private uint expToNextLevel;
+        [OptionalField] private int level;
+
+        [NonSerialized] private ClientInfo
+            clientInfo;
+
+        public string SteamID {
+            get { return steamId; }
+        }
+
+        public int EntityID {
+            get { return entityId; }
+        }
+
+        public string Name {
+            get { return name == null ? string.Empty : name; }
+        }
+
+        public string IP {
+            get { return ip == null ? string.Empty : ip; }
+        }
+
+        public Inventory Inventory {
+            get {
+                if (inventory == null)
+                    inventory = new Inventory ();
+                return inventory;
+            }
+        }
+
+        public bool IsOnline {
+            get { return clientInfo != null; }
+        }
+
+        public ClientInfo ClientInfo {
+            get { return clientInfo; }
+        }
+
+        public EntityPlayer Entity {
+            get {
+                if (IsOnline) {
+                    return GameManager.Instance.World.Players.dict [clientInfo.entityId];
+                } else {
+                    return null;
+                }
+            }
+        }
+
+        public long TotalPlayTime {
+            get {
+                if (IsOnline) {
+                    return totalPlayTime + (long) (DateTime.Now - lastOnline).TotalSeconds;
+                } else {
+                    return totalPlayTime;
+                }
+            }
+        }
+
+        public DateTime LastOnline {
+            get {
+                if (IsOnline)
+                    return DateTime.Now;
+                else
+                    return lastOnline;
+            }
+        }
+
+        public Vector3i LastPosition {
+            get {
+                if (IsOnline)
+                    return new Vector3i (Entity.GetPosition ());
+                else
+                    return new Vector3i (lastPositionX, lastPositionY, lastPositionZ);
+            }
+        }
+
+        public bool LandProtectionActive {
+            get {
+                return GameManager.Instance.World.IsLandProtectionValidForPlayer (GameManager.Instance
+                    .GetPersistentPlayerList ().GetPlayerData (SteamID));
+            }
+        }
+
+        public float LandProtectionMultiplier {
+            get {
+                return GameManager.Instance.World.GetLandProtectionHardnessModifierForPlayer (GameManager.Instance
+                    .GetPersistentPlayerList ().GetPlayerData (SteamID));
+            }
+        }
+
+
+        [Obsolete ("Experience no longer available, use Level instead")]
+        public uint Experience {
+            get { return 0; }
+        }
+
+        public float Level {
+            get {
+                float expForNextLevel =
+                    (int) Math.Min ((Progression.BaseExpToLevel * Mathf.Pow (Progression.ExpMultiplier, level + 1)),
+                        int.MaxValue);
+                float fLevel = level + 1f - ((float) expToNextLevel / expForNextLevel);
+                return fLevel;
+            }
+        }
+
+        public bool IsChatMuted {
+            get { return chatMuted; }
+            set { chatMuted = value; }
+        }
+
+        public int MaxChatLength {
+            get {
+                if (maxChatLength == 0) {
+                    maxChatLength = 255;
+                }
+
+                return maxChatLength;
+            }
+            set { maxChatLength = value; }
+        }
+
+        public string ChatColor {
+            get {
+                if (chatColor == null || chatColor == "") {
+                    chatColor = "";
+                }
+
+                return chatColor;
+            }
+
+            set { chatColor = value; }
+        }
+
+        public bool ChatName {
+            get { return chatName; }
+
+            set { chatName = value; }
+        }
+
+        public void SetOffline () {
+            if (clientInfo != null) {
+                Log.Out ("Player set to offline: " + steamId);
+                lastOnline = DateTime.Now;
+                try {
+                    Vector3i lastPos = new Vector3i (Entity.GetPosition ());
+                    lastPositionX = lastPos.x;
+                    lastPositionY = lastPos.y;
+                    lastPositionZ = lastPos.z;
+                    totalPlayTime += (long) (Time.timeSinceLevelLoad - Entity.CreationTimeSinceLevelLoad);
+                } catch (NullReferenceException) {
+                    Log.Out ("Entity not available. Something seems to be wrong here...");
+                }
+
+                clientInfo = null;
+            }
+        }
+
+        public void SetOnline (ClientInfo ci) {
+            Log.Out ("Player set to online: " + steamId);
+            clientInfo = ci;
+            entityId = ci.entityId;
+            name = ci.playerName;
+            ip = ci.ip;
+            lastOnline = DateTime.Now;
+        }
+
+        public void Update (PlayerDataFile _pdf) {
+            UpdateProgression (_pdf);
+            inventory.Update (_pdf);
+        }
+
+        private void UpdateProgression (PlayerDataFile _pdf) {
+            if (_pdf.progressionData.Length > 0) {
+                using (PooledBinaryReader pbr = MemoryPools.poolBinaryReader.AllocSync (false)) {
+                    pbr.SetBaseStream (_pdf.progressionData);
+                    Progression p = Progression.Read (pbr, null);
+                    expToNextLevel = (uint) p.ExpToNextLevel;
+                    level = p.Level;
+                }
+            }
+        }
+
+        public Player (string steamId) {
+            this.steamId = steamId;
+            this.inventory = new Inventory ();
+        }
+    }
 }
Index: binary-improvements/AllocsCommands/AllocsCommands.csproj
===================================================================
--- binary-improvements/AllocsCommands/AllocsCommands.csproj	(revision 323)
+++ binary-improvements/AllocsCommands/AllocsCommands.csproj	(revision 324)
@@ -1,3 +1,3 @@
-<?xml version="1.0" encoding="utf-8"?>
+﻿<?xml version="1.0" encoding="utf-8"?>
 <Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <PropertyGroup>
@@ -43,4 +43,8 @@
       <Private>False</Private>
     </Reference>
+    <Reference Include="UnityEngine.CoreModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
+      <HintPath>..\7dtd-binaries\UnityEngine.CoreModule.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
   </ItemGroup>
   <ItemGroup>
Index: binary-improvements/AllocsCommands/Commands/Give.cs
===================================================================
--- binary-improvements/AllocsCommands/Commands/Give.cs	(revision 323)
+++ binary-improvements/AllocsCommands/Commands/Give.cs	(revision 324)
@@ -53,35 +53,21 @@
 				}
 
+				int quality = Constants.cItemMaxQuality;
+
 				if (_params.Count == 4) {
-					if (!iv.HasQuality && iv.Attachments == null && iv.Parts == null) {
-						SdtdConsole.Instance.Output ("Item " + _params [1] + " does not support quality.");
-						return;
-					}
-
-					int quality = int.MinValue;
-					if (!int.TryParse (_params [3], out quality) || quality <= 0) {
+					if(!int.TryParse(_params [1], out quality) || quality <= 0) {
 						SdtdConsole.Instance.Output ("Quality is not an integer or not greater than zero.");
 						return;
 					}
+				}
+
+				if (ItemClass.list [iv.type].HasSubItems) {
+					for (int i = 0; i < iv.Modifications.Length; i++) {
+						ItemValue tmp = iv.Modifications[i];
+						tmp.Quality = quality;
+						iv.Modifications[i] = tmp;
+					}
+				} else if (ItemClass.list [iv.type].HasQuality) {
 					iv.Quality = quality;
-
-					// Specific code for weapons with parts and attachmetns
-					if (iv.Attachments != null && iv.Attachments.Length != 0) {
-						for (int i = 0; i < iv.Attachments.Length; i++) {
-							ItemValue att = iv.Attachments[i];
-							if (att != null && att.HasQuality) {
-								att.Quality = quality;
-							}
-						}
-					}
-
-					if (iv.Parts != null && iv.Parts.Length != 0) {
-						for (int i = 0; i < iv.Parts.Length; i++) {
-							ItemValue part = iv.Parts[i];
-							if (part != null && part.HasQuality) {
-								part.Quality = quality;
-							}
-						}
-					}
 				}
 
Index: binary-improvements/AllocsCommands/PrivateMessageConnections.cs
===================================================================
--- binary-improvements/AllocsCommands/PrivateMessageConnections.cs	(revision 323)
+++ binary-improvements/AllocsCommands/PrivateMessageConnections.cs	(revision 324)
@@ -18,5 +18,5 @@
 			if (senderOfLastPM.ContainsKey (_player.steamId)) {
 				CSteamID recSteamId = senderOfLastPM [_player.steamId];
-				ClientInfo recInfo = ConnectionManager.Instance.GetClientInfoForSteamId (recSteamId);
+				ClientInfo recInfo = ConnectionManager.Instance.Clients.ForSteamId (recSteamId);
 				return recInfo;
 			}
Index: binary-improvements/MapRendering/API.cs
===================================================================
--- binary-improvements/MapRendering/API.cs	(revision 323)
+++ binary-improvements/MapRendering/API.cs	(revision 324)
@@ -3,12 +3,12 @@
 namespace MapRendering
 {
-	public class API : ModApiAbstract {
-
-		public override void GameAwake () {
+	public class API : IModApi {
+		private void GameAwake () {
+			// ReSharper disable once ObjectCreationAsStatement
 			new AllocsFixes.NetConnections.Servers.Web.Web ();
 			AllocsFixes.NetConnections.Servers.Web.LogBuffer.Instance.GetType ();
 		}
 
-		public override void GameStartDone () {
+		private void GameStartDone () {
 			if (AllocsFixes.NetConnections.Servers.Web.Handlers.ItemIconHandler.Instance != null) {
 				AllocsFixes.NetConnections.Servers.Web.Handlers.ItemIconHandler.Instance.LoadIcons ();
@@ -16,12 +16,18 @@
 		}
 
-		public override void GameShutdown () {
+		private void GameShutdown () {
 			AllocsFixes.MapRendering.MapRendering.Shutdown ();
 		}
 
-		public override void CalcChunkColorsDone (Chunk _chunk) {
+		private void CalcChunkColorsDone (Chunk _chunk) {
 			AllocsFixes.MapRendering.MapRendering.RenderSingleChunk (_chunk);
 		}
 
+		public void InitMod () {
+			ModEvents.GameAwake.RegisterHandler (GameAwake);
+			ModEvents.GameStartDone.RegisterHandler (GameStartDone);
+			ModEvents.GameShutdown.RegisterHandler (GameShutdown);
+			ModEvents.CalcChunkColorsDone.RegisterHandler (CalcChunkColorsDone);
+		}
 	}
 }
Index: binary-improvements/MapRendering/Web/API/GetPlayerList.cs
===================================================================
--- binary-improvements/MapRendering/Web/API/GetPlayerList.cs	(revision 323)
+++ binary-improvements/MapRendering/Web/API/GetPlayerList.cs	(revision 324)
@@ -153,5 +153,5 @@
 			Match filterMatch = numberFilterMatcher.Match (_filterVal);
 			if (filterMatch.Success) {
-				double value = Utils.ParseDouble (filterMatch.Groups [2].Value);
+				double value = StringParsers.ParseDouble (filterMatch.Groups [2].Value);
 				NumberMatchType matchType;
 				double epsilon = value / 100000;
Index: binary-improvements/MapRendering/Web/API/GetPlayersOnline.cs
===================================================================
--- binary-improvements/MapRendering/Web/API/GetPlayersOnline.cs	(revision 323)
+++ binary-improvements/MapRendering/Web/API/GetPlayersOnline.cs	(revision 324)
@@ -15,5 +15,5 @@
 			World w = GameManager.Instance.World;
 			foreach (KeyValuePair<int, EntityPlayer> current in w.Players.dict) {
-				ClientInfo ci = ConnectionManager.Instance.GetClientInfoForEntityId (current.Key);
+				ClientInfo ci = ConnectionManager.Instance.Clients.ForEntityId (current.Key);
 				Player player = PersistentContainer.Instance.Players [ci.playerId, false];
 
@@ -32,5 +32,5 @@
 
 				// Deprecated!
-				p.Add ("experience", new JSONNumber (player != null ? player.Experience : 0));
+				p.Add ("experience", new JSONNumber (-1));
 
 				p.Add ("level", new JSONNumber (player != null ? player.Level : -1));
Index: binary-improvements/MapRendering/WebAndMapRendering.csproj
===================================================================
--- binary-improvements/MapRendering/WebAndMapRendering.csproj	(revision 323)
+++ binary-improvements/MapRendering/WebAndMapRendering.csproj	(revision 324)
@@ -44,4 +44,12 @@
     <Reference Include="System">
       <HintPath>..\7dtd-binaries\System.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="UnityEngine.CoreModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
+      <HintPath>..\7dtd-binaries\UnityEngine.CoreModule.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="UnityEngine.ImageConversionModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
+      <HintPath>..\7dtd-binaries\UnityEngine.ImageConversionModule.dll</HintPath>
       <Private>False</Private>
     </Reference>
