static public void HandlePacket(BinaryReader reader, int whoAmI)
        {
            Message msg = (Message)reader.ReadByte();
            Dictionary <DataTag, object> tags = new Dictionary <DataTag, object>();

            foreach (DataTag tag in dataTags[msg])
            {
                tags.Add(tag, tag.read(reader));
            }
            switch (msg)
            {
            case Message.SyncLevel:
                RPGPlayer p = Main.player[(int)tags[DataTag.playerId]].GetModPlayer <RPGPlayer>();
                if (p.baseName == "")
                {
                    p.baseName = Main.player[(int)tags[DataTag.playerId]].name;
                }


                if ((int)tags[DataTag.playerId] != Main.myPlayer)
                {
                    if (Main.netMode != NetmodeID.SinglePlayer)
                    {
                        p.SyncLevel((int)tags[DataTag.amount]);
                    }
                    Main.player[(int)tags[DataTag.playerId]].name = p.baseName + " The Lvl." + p.GetLevel() + " " + (string)tags[DataTag.buffer];
                }

                break;

            case Message.AddXP:
                Main.LocalPlayer.GetModPlayer <RPGPlayer>().AddXp((int)tags[DataTag.amount], (int)tags[DataTag.level]);
                break;

            case Message.SyncNPCSpawn:
                if (Main.netMode == NetmodeID.MultiplayerClient)
                {
                    NPC npc = Main.npc[(int)tags[DataTag.npcId]];

                    if (npc.GetGlobalNPC <ARPGGlobalNPC>() == null)
                    {
                        AnotherRpgMod.Instance.Logger.Info(npc.GivenName);
                    }

                    //npc.SetDefaults(npc.type);
                    if (npc.GetGlobalNPC <ARPGGlobalNPC>().StatsCreated == true)
                    {
                        return;
                    }
                    int     tier  = (int)tags[DataTag.tier];
                    int     level = (int)tags[DataTag.level];
                    NPCRank rank  = (NPCRank)tags[DataTag.rank];

                    NPCModifier modifiers = (NPCModifier)tags[DataTag.modifiers];
                    if (npc == null || npc.GetGlobalNPC <ARPGGlobalNPC>() == null)
                    {
                        return;
                    }
                    AnotherRpgMod.Instance.Logger.Info(npc.GivenOrTypeName + "\nTier : " + tier + "   Level : " + level + "   rank : " + rank + "   Modifier  : " + modifiers + " \n Buffer : " + (string)tags[DataTag.buffer]);

                    Dictionary <string, string> bufferStack = Unparse((string)tags[DataTag.buffer]);

                    WorldManager.BossDefeated = (int)tags[DataTag.WorldTier];

                    npc.GetGlobalNPC <ARPGGlobalNPC>().StatsCreated = true;
                    npc.GetGlobalNPC <ARPGGlobalNPC>().modifier     = modifiers;
                    npc.GetGlobalNPC <ARPGGlobalNPC>().SetLevelTier(level, tier, (byte)rank);
                    npc.GetGlobalNPC <ARPGGlobalNPC>().specialBuffer = bufferStack;

                    npc.GetGlobalNPC <ARPGGlobalNPC>().SetStats(npc);

                    npc.GivenName = NPCUtils.GetNpcNameChange(npc, tier, level, rank);



                    //AnotherRpgMod.Instance.Logger.Info("NPC created with id : " + npc.whoAmI);
                    //AnotherRpgMod.Instance.Logger.Info( "Client Side : \n" + npc.GetGivenOrTypeNetName() + "\nLvl." + (npc.GetGlobalNPC<ARPGGlobalNPC>().getLevel + npc.GetGlobalNPC<ARPGGlobalNPC>().getTier) + "\nHealth : " + npc.life + " / " + npc.lifeMax + "\nDamage : " + npc.damage + "\nDef : " + npc.defense + "\nTier : " + npc.GetGlobalNPC<ARPGGlobalNPC>().getRank + "\n\n");
                }
                break;

            case Message.SyncNPCUpdate:
                if (Main.netMode == NetmodeID.MultiplayerClient)
                {
                    NPC npcu = Main.npc[(int)tags[DataTag.npcId]];

                    if (npcu.lifeMax != (int)tags[DataTag.maxLife] || npcu.life != (int)tags[DataTag.life])
                    {
                        AnotherRpgMod.Instance.Logger.Warn("DESYNC ERROR SPOTTED FOR : ");
                        AnotherRpgMod.Instance.Logger.Warn(npcu.GivenOrTypeName + "\n" + (int)tags[DataTag.life] + " / " + (int)tags[DataTag.maxLife] + "\n" + npcu.life + " / " + npcu.lifeMax);
                    }
                    Main.npc[(int)tags[DataTag.npcId]].lifeMax = (int)tags[DataTag.maxLife];
                    Main.npc[(int)tags[DataTag.npcId]].life    = (int)tags[DataTag.life];
                }
                break;

            case Message.Log:
                if (Main.netMode == NetmodeID.MultiplayerClient)
                {
                    //ErrorLogger.Log("LOG FROM SERVER");
                    AnotherRpgMod.Instance.Logger.Info((string)tags[DataTag.buffer]);
                }

                break;

            case Message.AskNpc:
                if (Main.netMode == NetmodeID.Server)
                {
                    NPC npc = Main.npc[(int)tags[DataTag.npcId]];
                    if (npc.GetGlobalNPC <ARPGGlobalNPC>() == null)
                    {
                        return;
                    }
                    int tier  = npc.GetGlobalNPC <ARPGGlobalNPC>().getTier;
                    int level = npc.GetGlobalNPC <ARPGGlobalNPC>().getLevel;
                    int rank  = npc.GetGlobalNPC <ARPGGlobalNPC>().getRank;
                    Mod mod   = AnotherRpgMod.Instance;
                    //MPDebug.Log(mod, "Server Side : \n" + npc.GetGivenOrTypeNetName() + " ID : " + npc.whoAmI + "\nLvl." + (npc.GetGlobalNPC<ARPGGlobalNPC>().getLevel + npc.GetGlobalNPC<ARPGGlobalNPC>().getTier) + "\nHealth : " + npc.life + " / " + npc.lifeMax + "\nDamage : " + npc.damage + "\nDef : " + npc.defense + "\nTier : " + npc.GetGlobalNPC<ARPGGlobalNPC>().getRank + "\n");

                    SendNpcSpawn(mod, npc, tier, level, npc.GetGlobalNPC <ARPGGlobalNPC>());
                }
                break;
            }
        }