internal void UpdateInfo(Eleon.Modding.PlayerInfo pInfo)
        {
            var newFaction   = _gameServerConnection.GetFaction(pInfo.factionId);
            var newplayField = _gameServerConnection.GetPlayfield(pInfo.playfield);

            lock (this)
            {
                System.Diagnostics.Debug.Assert(EntityId == pInfo.entityId);
                this.SteamId        = pInfo.steamId;
                this.FactionGroupId = pInfo.factionGroup;
                this.Origin         = pInfo.origin;
                this.Position       = new WorldPosition {
                    playfield = newplayField, position = pInfo.pos.ToVector3()
                };
                this.MemberOfFaction      = newFaction;
                this.BpResourcesInFactory = pInfo.bpResourcesInFactory;
                _permission = pInfo.permission;
            }
        }
 internal Player(GameServerConnection gameServerConnection, Eleon.Modding.PlayerInfo pInfo)
     : base(gameServerConnection, pInfo.entityId, EntityType.Player, pInfo.playerName)
 {
     UpdateInfo(pInfo);
 }
        public void FromPlayerInfo(Eleon.Modding.PlayerInfo playerinfo)
        {
            clientId       = playerinfo.clientId;
            entityId       = playerinfo.entityId;
            steamId        = playerinfo.steamId;
            steamOwnerId   = playerinfo.steamOwnerId;
            playerName     = playerinfo.playerName;
            playfield      = playerinfo.playfield;
            startPlayfield = playerinfo.startPlayfield;
            pos            = new PVector3();
            pos.x          = playerinfo.pos.x;
            pos.y          = playerinfo.pos.y;
            pos.z          = playerinfo.pos.z;
            OnPropertyChanged("pos");
            rot   = new PVector3();
            rot.x = playerinfo.rot.x;
            rot.y = playerinfo.rot.y;
            rot.z = playerinfo.rot.z;
            OnPropertyChanged("rot");
            factionGroup = playerinfo.factionGroup;
            factionId    = playerinfo.factionId;
            factionRole  = playerinfo.factionRole;
            origin       = playerinfo.origin;
            health       = playerinfo.health;
            healthMax    = playerinfo.healthMax;
            oxygen       = playerinfo.oxygen;
            oxygenMax    = playerinfo.oxygenMax;
            stamina      = playerinfo.stamina;
            staminaMax   = playerinfo.staminaMax;
            kills        = playerinfo.kills;
            died         = playerinfo.died;
            credits      = playerinfo.credits;

            if (playerinfo.toolbar != null)
            {
                toolbar = new List <ItemStack>();
                ItemStack iSt;
                foreach (Eleon.Modding.ItemStack itemStack in playerinfo.toolbar)
                {
                    iSt = new ItemStack();
                    iSt.FromItemStack(itemStack);
                    toolbar.Add(iSt);
                }
            }

            if (playerinfo.bag != null)
            {
                bag = new List <ItemStack>();
                ItemStack iSt;
                foreach (Eleon.Modding.ItemStack itemStack in playerinfo.bag)
                {
                    iSt = new ItemStack();
                    iSt.FromItemStack(itemStack);
                    bag.Add(iSt);
                }
            }

            exp                  = playerinfo.exp;
            upgrade              = playerinfo.upgrade;
            bpRemainingTime      = playerinfo.bpRemainingTime;
            bpResourcesInFactory = playerinfo.bpResourcesInFactory;
            bpInFactory          = playerinfo.bpInFactory;
            producedPrefabs      = playerinfo.producedPrefabs;
            ping                 = playerinfo.ping;
        }
        //This function receives all data from the game
        public void onGameEvent(ModProtocol.Package p)
        {
            try
            {
                if (System.Windows.Application.Current == null)
                {
                    return;
                }
                if (p.data == null)
                {
                    output(string.Format("Empty Package id rec: {0}", p.cmd), p.cmd);
                    return;
                }

                if (mainWindowDataContext != null && mainWindowDataContext.EnableOutput_DataRecieved)
                {
                    output(string.Format("Package received, id: {0}, type: {1}", p.cmd, Enum.GetName(cmdType, p.cmd)));
                    output("received  event: c=" + p.cmd + " sNr=" + p.seqNr + " d=" + p.data + " client=" + client);
                }

                switch (p.cmd)
                {
                case Eleon.Modding.CmdId.Event_Player_Connected:
                {
                    int entityId = ((Eleon.Modding.Id)p.data).id;

                    addEvent(string.Format("Player with id {0} connected", entityId));

                    lock (playerIds)
                    {
                        playerIds.Add(entityId);
                    }
                    System.Windows.Application.Current.Dispatcher.Invoke((Action)(() => mainWindowDataContext.onlinePlayer.Add(entityId)));
                }
                break;

                case Eleon.Modding.CmdId.Event_Player_Disconnected:
                {
                    int entityId = ((Eleon.Modding.Id)p.data).id;

                    addEvent(string.Format("Player with id {0} disconnected", entityId));

                    lock (playerIds)
                    {
                        playerIds.Remove(entityId);
                    }
                    System.Windows.Application.Current.Dispatcher.Invoke((Action)(() => mainWindowDataContext.onlinePlayer.Remove(entityId)));
                }
                break;

                case Eleon.Modding.CmdId.Event_Player_List:
                {
                    if (p.data != null)
                    {          // empyt list is null?!
                        lock (playerIds)
                        {
                            playerIds = ((Eleon.Modding.IdList)p.data).list;
                        }
                        System.Windows.Application.Current.Dispatcher.Invoke((Action)(() => mainWindowDataContext.onlinePlayer.Clear()));
                        for (int i = 0; i < playerIds.Count; i++)
                        {
                            System.Windows.Application.Current.Dispatcher.Invoke((Action)(() => mainWindowDataContext.onlinePlayer.Add(playerIds[i])));
                            output(string.Format("{0} Player with id {1}", i + 1, playerIds[i]), p.cmd);
                        }
                    }
                    else
                    {
                        output("No players connected", p.cmd);
                    }
                }
                break;

                case Eleon.Modding.CmdId.Event_Player_Info:
                {
                    Eleon.Modding.PlayerInfo pInfo = (Eleon.Modding.PlayerInfo)p.data;
                    if (pInfo == null)
                    {
                        break;
                    }
                    output(string.Format("Player info (seqnr {0}): cid={1} eid={2} name={3} playfield={4} fac={5}", p.seqNr, pInfo.clientId, pInfo.entityId, pInfo.playerName, pInfo.playfield, pInfo.factionId), p.cmd);

                    System.Windows.Application.Current.Dispatcher.Invoke((Action)(() =>
                        {
                            mainWindowDataContext.playerInfos.Clear();
                            PlayerInfo plI = new PlayerInfo();
                            plI.FromPlayerInfo(pInfo);
                            mainWindowDataContext.playerInfos.Add(plI);
                        }));
                }
                break;

                case Eleon.Modding.CmdId.Event_Player_Inventory:
                {
                    Eleon.Modding.Inventory inv = (Eleon.Modding.Inventory)p.data;
                    if (inv == null)
                    {
                        break;
                    }
                    output(string.Format("Inventory received from player {0}", inv.playerId), p.cmd);
                    if (inv.toolbelt != null)
                    {
                        output("Toolbelt:", p.cmd);
                        for (int i = 0; inv.toolbelt != null && i < inv.toolbelt.Length; i++)
                        {
                            output("  " + inv.toolbelt[i].slotIdx + ". " + inv.toolbelt[i].id + " " + inv.toolbelt[i].count + " " + inv.toolbelt[i].ammo, p.cmd);
                        }
                    }
                    if (inv.bag != null)
                    {
                        output("Bag:", p.cmd);
                        for (int i = 0; inv.bag != null && i < inv.bag.Length; i++)
                        {
                            output("  " + inv.bag[i].slotIdx + ". " + inv.bag[i].id + " " + inv.bag[i].count + " " + inv.bag[i].ammo, p.cmd);
                        }
                    }
                }
                break;

                case Eleon.Modding.CmdId.Event_Entity_PosAndRot:
                {
                    Eleon.Modding.IdPositionRotation idPos = (Eleon.Modding.IdPositionRotation)p.data;
                    if (idPos == null)
                    {
                        break;
                    }
                    output(string.Format("Player with id {0} position {1}, {2}, {3} rotation {4}, {5}, {6}", idPos.id, idPos.pos.x, idPos.pos.y, idPos.pos.z, idPos.rot.x, idPos.rot.y, idPos.rot.z), p.cmd);
                }
                break;

                case Eleon.Modding.CmdId.Event_Player_Credits:
                {
                    Eleon.Modding.IdCredits idCredits = (Eleon.Modding.IdCredits)p.data;
                    if (idCredits == null)
                    {
                        break;
                    }
                    output(string.Format("Credits player with id {0}: {1}", idCredits.id, idCredits.credits), p.cmd);
                }
                break;

                case Eleon.Modding.CmdId.Event_Ok:
                {
                    output(string.Format("Event Ok seqnr {0}", p.seqNr), p.cmd);
                }
                break;

                case Eleon.Modding.CmdId.Event_Error:
                {
                    Eleon.Modding.CmdId     cmdId = (Eleon.Modding.CmdId)p.seqNr;
                    Eleon.Modding.ErrorInfo eInfo = (Eleon.Modding.ErrorInfo)p.data;

                    if (eInfo == null)
                    {
                        output(string.Format("Event Error seqnr {0}: TMD: p.data of Event_Error was not set", p.seqNr), p.cmd);
                    }
                    else
                    {
                        output(string.Format("Event Error {0} seqnr {1}", eInfo.errorType, cmdId), p.cmd);
                    }
                }
                break;

                case Eleon.Modding.CmdId.Event_Player_ChangedPlayfield:
                {
                    Eleon.Modding.IdPlayfield obj = (Eleon.Modding.IdPlayfield)p.data;

                    addEvent(string.Format("Player with id {0} changes to playfield {1}", obj.id, obj.playfield));
                }
                break;

                case Eleon.Modding.CmdId.Event_Playfield_Stats:
                {
                    Eleon.Modding.PlayfieldStats obj = (Eleon.Modding.PlayfieldStats)p.data;
                    if (obj == null)
                    {
                        break;
                    }
                    addStats(string.Format("Playfield stats for Akua: fps={0} heap={1} procid={2}", obj.fps, obj.mem, obj.processId));
                }
                break;

                case Eleon.Modding.CmdId.Event_Playfield_Loaded:
                {
                    Eleon.Modding.PlayfieldLoad obj = (Eleon.Modding.PlayfieldLoad)p.data;
                    if (obj == null)
                    {
                        break;
                    }

                    addEvent(string.Format("Playfield {0} loaded pid={1}", obj.playfield, obj.processId));

                    lock (playfields)
                    {
                        playfields.Add(obj.playfield);
                        System.Windows.Application.Current.Dispatcher.Invoke((Action)(() => mainWindowDataContext.onlinePlayfields.Add(obj.playfield)));
                    }
                }
                break;

                case Eleon.Modding.CmdId.Event_Playfield_Unloaded:
                {
                    Eleon.Modding.PlayfieldLoad obj = (Eleon.Modding.PlayfieldLoad)p.data;
                    if (obj == null)
                    {
                        break;
                    }

                    addEvent(string.Format("Playfield {0} unloaded pid={1}", obj.playfield, obj.processId));

                    lock (playfields)
                    {
                        playfields.Remove(obj.playfield);
                        System.Windows.Application.Current.Dispatcher.Invoke((Action)(() => mainWindowDataContext.onlinePlayfields.Remove(obj.playfield)));
                    }
                }
                break;

                case Eleon.Modding.CmdId.Event_Dedi_Stats:
                {
                    Eleon.Modding.DediStats obj = (Eleon.Modding.DediStats)p.data;
                    if (obj == null)
                    {
                        break;
                    }
                    addStats(string.Format("Dedi stats: {0}fps", obj.fps));
                }
                break;

                case Eleon.Modding.CmdId.Event_GlobalStructure_List:
                {
                    Eleon.Modding.GlobalStructureList obj = (Eleon.Modding.GlobalStructureList)p.data;
                    if (obj == null || obj.globalStructures == null)
                    {
                        break;
                    }
                    output(string.Format("Global structures. Count: {0}", obj.globalStructures != null ? obj.globalStructures.Count : 0), p.cmd);

                    if (obj.globalStructures != null)
                    {
                        System.Windows.Application.Current.Dispatcher.Invoke((Action)(() => mainWindowDataContext.structures.Clear()));

                        foreach (KeyValuePair <string, List <Eleon.Modding.GlobalStructureInfo> > kvp in obj.globalStructures)
                        {
                            output(string.Format("Playfield {0}", kvp.Key), p.cmd);

                            foreach (Eleon.Modding.GlobalStructureInfo g in kvp.Value)
                            {
                                StructureInfo stI = new StructureInfo();
                                stI.FromStructureInfo(g, kvp.Key);

                                output(string.Format("  id={0} name={1} type={2} #blocks={3} #devices={4} playfield={5} pos={6}/{7}/{8}", g.id, g.name, g.type, g.cntBlocks, g.cntDevices, kvp.Key, g.pos.x, g.pos.y, g.pos.z), p.cmd);

                                System.Windows.Application.Current.Dispatcher.Invoke((Action)(() => mainWindowDataContext.structures.Add(stI)));
                            }
                        }
                    }
                }
                break;

                case Eleon.Modding.CmdId.Event_Playfield_List:
                {
                    Eleon.Modding.PlayfieldList obj = (Eleon.Modding.PlayfieldList)p.data;
                    if (obj == null || obj.playfields == null)
                    {
                        break;
                    }
                    output(string.Format("Playfield list. Count: {0}", obj.playfields != null ? obj.playfields.Count : 0), p.cmd);
                    System.Windows.Application.Current.Dispatcher.Invoke((Action)(() => mainWindowDataContext.onlinePlayfields.Clear()));

                    lock (playfields)
                    {
                        playfields.Clear();
                        foreach (string s in obj.playfields)
                        {
                            System.Windows.Application.Current.Dispatcher.Invoke((Action)(() => mainWindowDataContext.onlinePlayfields.Add(s)));
                            output(string.Format("  {0}", s), p.cmd);
                            playfields.Add(s);
                        }
                    }
                }
                break;

                case Eleon.Modding.CmdId.Event_Faction_Changed:
                {
                    Eleon.Modding.FactionChangeInfo obj = (Eleon.Modding.FactionChangeInfo)p.data;
                    if (obj == null)
                    {
                        break;
                    }

                    addEvent(string.Format("Faction changed entity: {0} faction id: {1} faction {2}", obj.id, obj.factionId, obj.factionGroup));
                }
                break;

                case Eleon.Modding.CmdId.Event_Statistics:
                {
                    Eleon.Modding.StatisticsParam obj = (Eleon.Modding.StatisticsParam)p.data;
                    if (obj == null)
                    {
                        break;
                    }

                    addEvent(string.Format("Event_Statistics: {0} {1} {2} {3} {4}", obj.type, obj.int1, obj.int2, obj.int3, obj.int4));

                    //CoreRemoved,    int1: Structure id, int2: destryoing entity id, int3: (optional) controlling entity id
                    //CoreAdded,      int1: Structure id, int2: destryoing entity id, int3: (optional) controlling entity id
                    //PlayerDied,     // int1: player entity id, int2: death type (Unknown = 0,Projectile = 1,Explosion = 2,Food = 3,Oxygen = 4,Disease = 5,Drowning = 6,Fall = 7,Suicide = 8), int3: (optional) other entity involved, int4: (optional) other entity CV/SV/HV id
                    //StructOnOff,    int1: structure id, int2: changing entity id, int3: 0 = off, 1 = on
                    //StructDestroyed,// int1: structure id, int2: type (0=wipe, 1=decay)
                }
                break;

                case Eleon.Modding.CmdId.Request_ConsoleCommand:
                {
                    Eleon.Modding.PString obj = (Eleon.Modding.PString)p.data;
                    if (obj == null)
                    {
                        break;
                    }

                    output(string.Format("Request_ConsoleCommand: {0}", obj.pstr), p.cmd);
                }
                break;

                case Eleon.Modding.CmdId.Event_ChatMessage:
                {
                    Eleon.Modding.ChatInfo obj = (Eleon.Modding.ChatInfo)p.data;
                    if (obj == null)
                    {
                        break;
                    }

                    string typeName;
                    switch (obj.type)
                    {
                    case 7:
                        typeName = "to faction";
                        break;

                    case 8:
                        typeName = "to player";
                        break;

                    case 9:
                        typeName = "to server";
                        break;

                    default:
                        typeName = "";
                        break;
                    }

                    output(string.Format("Chat: Player: {0}, Recepient: {1}, Recepient Faction: {2}, {3}, Message: '{4}'", obj.playerId, obj.recipientEntityId, obj.recipientFactionId, typeName, obj.msg), p.cmd);
                }
                break;

                case Eleon.Modding.CmdId.Event_Player_DisconnectedWaiting:
                {
                    Eleon.Modding.Id obj = (Eleon.Modding.Id)p.data;
                    if (obj == null)
                    {
                        break;
                    }

                    addEvent(string.Format("Event_Player_DisconnectedWaiting: Player: {0}", obj.id));
                }
                break;

                case Eleon.Modding.CmdId.Event_AlliancesAll:
                {
                    Eleon.Modding.AlliancesTable obj = (Eleon.Modding.AlliancesTable)p.data;
                    if (obj == null)
                    {
                        break;
                    }

                    int facId1;
                    int facId2;

                    //Only differences to default alliances are listed (everyone in same Origin is by default allied)
                    foreach (int factionHash in obj.alliances)
                    {
                        facId1 = (factionHash >> 16) & 0xffff;
                        facId2 = factionHash & 0xffff;

                        output(string.Format("Alliance difference between faction {0} and faction {1}", facId1, facId2), p.cmd);
                    }
                }
                break;

                case Eleon.Modding.CmdId.Event_Get_Factions:
                {
                    Eleon.Modding.FactionInfoList obj = (Eleon.Modding.FactionInfoList)p.data;
                    if (obj == null || obj.factions == null)
                    {
                        break;
                    }
                    output(string.Format("Faction list. Count: {0}", obj.factions != null ? obj.factions.Count : 0), p.cmd);
                    foreach (Eleon.Modding.FactionInfo fI in obj.factions)
                    {
                        output(string.Format("Id: {0}, Abrev: {1}, Name: {2}, Origin: {3}", fI.factionId, fI.abbrev, fI.name, fI.origin), p.cmd);
                    }
                }
                break;

                case Eleon.Modding.CmdId.Event_Structure_BlockStatistics:
                {
                    Eleon.Modding.IdStructureBlockInfo obj = (Eleon.Modding.IdStructureBlockInfo)p.data;
                    if (obj == null || obj.blockStatistics == null)
                    {
                        break;
                    }

                    foreach (KeyValuePair <int, int> blockstat in obj.blockStatistics)
                    {
                        output(string.Format("Item {0}: Amount: {1}", blockstat.Key, blockstat.Value), p.cmd);
                    }
                    output(string.Format("Block statistic for {0}", obj.id), p.cmd);
                }
                break;

                case Eleon.Modding.CmdId.Event_BannedPlayers:
                {
                    Eleon.Modding.BannedPlayerData obj = (Eleon.Modding.BannedPlayerData)p.data;
                    if (obj == null || obj.BannedPlayers == null)
                    {
                        break;
                    }
                    output(string.Format("Banned list. Count: {0}", obj.BannedPlayers != null ? obj.BannedPlayers.Count : 0), p.cmd);
                    foreach (Eleon.Modding.BannedPlayerData.BanEntry ba in obj.BannedPlayers)
                    {
                        output(string.Format("Id: {0}, Date: {1}", ba.steam64Id, DateTime.FromBinary(ba.dateTime)), p.cmd);
                    }
                }
                break;

                case Eleon.Modding.CmdId.Event_TraderNPCItemSold:
                {
                    Eleon.Modding.TraderNPCItemSoldInfo obj = (Eleon.Modding.TraderNPCItemSoldInfo)p.data;
                    if (obj == null)
                    {
                        break;
                    }
                    output(string.Format("Trader NPC item sold info: TraderType: {0}, TraderId: {1}, PlayerId: {2}, StructureId: {3}, Item: {4}, Amount: {5}, Price: {6}", obj.traderType, obj.traderEntityId, obj.playerEntityId, obj.structEntityId, obj.boughtItemId, obj.boughtItemCount, obj.boughtItemPrice), p.cmd);
                }
                break;

                case Eleon.Modding.CmdId.Event_Player_GetAndRemoveInventory:
                {
                    Eleon.Modding.Inventory inv = (Eleon.Modding.Inventory)p.data;
                    if (inv == null)
                    {
                        break;
                    }
                    output(string.Format("Got and removed Inventory from player {0}", inv.playerId), p.cmd);
                    if (inv.toolbelt != null)
                    {
                        output("Toolbelt:", p.cmd);
                        for (int i = 0; inv.toolbelt != null && i < inv.toolbelt.Length; i++)
                        {
                            output("  " + inv.toolbelt[i].slotIdx + ". " + inv.toolbelt[i].id + " " + inv.toolbelt[i].count + " " + inv.toolbelt[i].ammo, p.cmd);
                        }
                    }
                    if (inv.bag != null)
                    {
                        output("Bag:", p.cmd);
                        for (int i = 0; inv.bag != null && i < inv.bag.Length; i++)
                        {
                            output("  " + inv.bag[i].slotIdx + ". " + inv.bag[i].id + " " + inv.bag[i].count + " " + inv.bag[i].ammo, p.cmd);
                        }
                    }
                }
                break;

                case Eleon.Modding.CmdId.Event_Playfield_Entity_List:
                {
                    Eleon.Modding.PlayfieldEntityList obj = (Eleon.Modding.PlayfieldEntityList)p.data;
                    if (obj == null || obj.entities == null)
                    {
                        break;
                    }
                    output(string.Format("Entities. Count: {0}", obj.entities != null ? obj.entities.Count : 0), p.cmd);

                    if (obj.entities != null)
                    {
                        output(string.Format("Playfield {0}", obj.playfield), p.cmd);

                        foreach (Eleon.Modding.EntityInfo g in obj.entities)
                        {
                            EntityInfo stI = new EntityInfo();
                            stI.FromEntityInfo(g, obj.playfield);

                            output(string.Format("  id={0} type={1} playfield={2} pos={3}/{4}/{5}", g.id, g.type, obj.playfield, g.pos.x, g.pos.y, g.pos.z), p.cmd);

                            System.Windows.Application.Current.Dispatcher.Invoke((Action)(() => mainWindowDataContext.entities.Add(stI)));
                        }
                    }
                }
                break;

                case Eleon.Modding.CmdId.Event_ConsoleCommand:
                {
                    Eleon.Modding.ConsoleCommandInfo obj = (Eleon.Modding.ConsoleCommandInfo)p.data;
                    if (obj == null)
                    {
                        break;
                    }
                    output(string.Format("Player {0}; Console command: {1} Allowed: {2}", obj.playerEntityId, obj.command, obj.allowed), p.cmd);
                }
                break;

                case Eleon.Modding.CmdId.Event_NewEntityId:
                {
                    output(string.Format("New ID: {0}", ((Eleon.Modding.Id)p.data).id), p.cmd);
                    break;
                }

                case Eleon.Modding.CmdId.Event_PdaStateChange:
                {
                    Eleon.Modding.PdaStateInfo data = (Eleon.Modding.PdaStateInfo)p.data;
                    addEvent(string.Format("PdaStateChange for {0}. Change: {1}", data.Name, data.StateChange));
                }
                break;

                case Eleon.Modding.CmdId.Event_GameEvent:
                {
                    Eleon.Modding.GameEventData data = (Eleon.Modding.GameEventData)p.data;

                    string inventory = "";
                    for (int i = 0; data.ItemStacks != null && i < data.ItemStacks.Length; i++)
                    {
                        inventory = inventory + ";  " + data.ItemStacks[i].slotIdx + ". " + data.ItemStacks[i].id + " " + data.ItemStacks[i].count + " " + data.ItemStacks[i].ammo;
                    }

                    addEvent(string.Format("Event_GameEvent EventType:{0} Name:{1} Type:{2} Amount:{3} PlayerId:{4} Flag:{5} Inventory:{6}", data.EventType, data.Name, data.Type, data.Amount, data.PlayerId, data.Flag, inventory));
                }
                break;

                default:
                    output(string.Format("(1) Unknown package cmd {0}", p.cmd), p.cmd);
                    break;
                }
            }
            catch (Exception ex)
            {
                output(string.Format("Error: {0}", ex.Message), p.cmd);
            }
        }
        private static void Client_GameEventReceived(ModProtocol.Package p)
        {
            try
            {
                if (p.data == null)
                {
                    Output("Empty Package id rec: {0}", p.cmd);
                    return;
                }

                switch (p.cmd)
                {
                case Eleon.Modding.CmdId.Event_Player_Connected:
                {
                    int entityId = ((Eleon.Modding.Id)p.data).id;

                    Output("Player with id {0} connected", entityId);

                    SendRequest(Eleon.Modding.CmdId.Request_Player_Info, Eleon.Modding.CmdId.Request_Player_Info, new Eleon.Modding.Id(entityId));
                }
                break;

                case Eleon.Modding.CmdId.Event_Player_List:
                {
                    if (p.data != null)
                    {
                        var playerIds = ((Eleon.Modding.IdList)p.data).list;

                        for (int i = 0; i < playerIds.Count; i++)
                        {
                            SendRequest(Eleon.Modding.CmdId.Request_Player_Info, Eleon.Modding.CmdId.Request_Player_Info, new Eleon.Modding.Id(playerIds[i]));
                            Output("{0} Player with id {1}", i + 1, playerIds[i]);
                        }
                    }
                    else
                    {
                        Output("No players connected");
                    }
                }
                break;

                case Eleon.Modding.CmdId.Event_Player_Info:
                {
                    Eleon.Modding.PlayerInfo pInfo = (Eleon.Modding.PlayerInfo)p.data;
                    if (pInfo == null)
                    {
                        break;
                    }
                    lock (playerInfoById)
                    {
                        playerInfoById[pInfo.entityId] = pInfo;
                    }
                    Output("Player info (seqnr {0}): cid={1} eid={2} name={3} playfield={4} fac={5}", p.seqNr, pInfo.clientId, pInfo.entityId, pInfo.playerName, pInfo.playfield, pInfo.factionId);
                }
                break;

                case Eleon.Modding.CmdId.Event_ChatMessage:
                {
                    Eleon.Modding.ChatInfo obj = (Eleon.Modding.ChatInfo)p.data;
                    if (obj == null)
                    {
                        break;
                    }

                    string typeName;
                    switch (obj.type)
                    {
                    case 5:             //?
                    case 7:
                        typeName = "to faction";
                        break;

                    case 8:
                        typeName = "to player";
                        break;

                    case 9:
                        typeName = "to server";
                        break;

                    default:
                        typeName = "";
                        break;
                    }

                    Output("Chat: Player: {0}, Recepient: {1}, Recepient Faction: {2}, {3}, Message: '{4}'", obj.playerId, obj.recipientEntityId, obj.recipientFactionId, typeName, obj.msg);

                    if (obj.type != 8 && obj.type != 7 && obj.msg == "!MODS")
                    {
                        ChatMessage(k_versionString);
                    }

                    if (obj.msg == config.TeleportCommand || obj.msg == string.Format("s! {0}", config.TeleportCommand))
                    {
                        lock (playerInfoById)
                        {
                            Config.Configuration.FactionHomeWorldData homeworldData = null;

                            if (config.FactionHomeWorlds.ContainsKey(playerInfoById[obj.playerId].factionId))
                            {
                                homeworldData = config.FactionHomeWorlds[playerInfoById[obj.playerId].factionId];
                            }
                            else if (config.FactionHomeWorlds.ContainsKey(-1))
                            {
                                // everyone else goes to the default
                                homeworldData = config.FactionHomeWorlds[-1];
                            }

                            if (homeworldData != null)
                            {
                                if ((homeworldData.FromPlayfield == null) || homeworldData.FromPlayfield == playerInfoById[obj.playerId].playfield)
                                {
                                    var location = homeworldData.GetNextLocation();
                                    SendRequest(
                                        Eleon.Modding.CmdId.Request_Player_ChangePlayerfield,
                                        Eleon.Modding.CmdId.Request_Player_ChangePlayerfield
                                        , new Eleon.Modding.IdPlayfieldPositionRotation(obj.playerId, homeworldData.ToPlayfield, location.Position, location.Rotation));
                                }
                                else
                                {
                                    // TODO: send failure message to player
                                }
                            }
                            else
                            {
                                // TODO: send failure message to player
                            }
                        }
                    }
                }
                break;

                default:
                    Output("(1) Unknown package cmd {0}", p.cmd);
                    break;
                }
            }
            catch (Exception ex)
            {
                Output("Error: {0}", ex.Message);
            }
        }