void LogicSystem::setupCharacter(ScriptValuePtr scriptEntity)
{
//    #ifdef CLIENT
//        assert(0); // until we figure this out
//    #endif

    int uniqueId = scriptEntity->getPropertyInt("uniqueId");

    Logging::log(Logging::DEBUG, "setupCharacter: %d\r\n", uniqueId);
    INDENT_LOG(Logging::DEBUG);

    fpsent* fpsEntity;

    int clientNumber = scriptEntity->getPropertyInt("clientNumber");
    Logging::log(Logging::DEBUG, "(a) clientNumber: %d\r\n", clientNumber);

    #ifdef CLIENT
        Logging::log(Logging::DEBUG, "client numbers: %d, %d\r\n", ClientSystem::playerNumber, clientNumber);

        if (uniqueId == ClientSystem::uniqueId)
        {
            scriptEntity->setProperty("clientNumber", ClientSystem::playerNumber);
        }
    #endif

    Logging::log(Logging::DEBUG, "(b) clientNumber: %d\r\n", clientNumber);

    assert(clientNumber >= 0);

    #ifdef CLIENT
    // If this is the player. There should already have been created an fpsent for this client,
    // which we can fetch with the valid client #
    Logging::log(Logging::DEBUG, "UIDS: in ClientSystem %d, and given to us%d\r\n", ClientSystem::uniqueId, uniqueId);

    if (uniqueId == ClientSystem::uniqueId)
    {
        Logging::log(Logging::DEBUG, "This is the player, use existing clientnumber for fpsent (should use player1?) \r\n");

        fpsEntity = dynamic_cast<fpsent*>( FPSClientInterface::getPlayerByNumber(clientNumber) );

        // Wipe clean the uniqueId set for the fpsent, so we can re-use it.
        fpsEntity->uniqueId = -77;
    }
    else
    #endif
    {
        Logging::log(Logging::DEBUG, "This is a remote client or NPC, do a newClient for the fpsent\r\n");

        // This is another client, perhaps NPC. Connect this new client using newClient
        fpsEntity =  dynamic_cast<fpsent*>( FPSClientInterface::newClient(clientNumber) );
    }

    // Register with the C++ system.

    LogicSystem::setUniqueId(fpsEntity, uniqueId);
    LogicSystem::registerLogicEntity(fpsEntity);
}
void LogicSystem::dismantleCharacter(ScriptValuePtr scriptEntity)
{
    int clientNumber = scriptEntity->getPropertyInt("clientNumber");
    #ifdef CLIENT
    if (clientNumber == ClientSystem::playerNumber)
        Logging::log(Logging::DEBUG, "Not dismantling own client\r\n", clientNumber);
    else
    #endif
    {
        Logging::log(Logging::DEBUG, "Dismantling other client %d\r\n", clientNumber);

#ifdef SERVER
        fpsent* fpsEntity = dynamic_cast<fpsent*>( FPSClientInterface::getPlayerByNumber(clientNumber) );
        bool isNPC = fpsEntity->serverControlled;
#endif

        FPSClientInterface::clientDisconnected(clientNumber);

#ifdef SERVER
        if (isNPC)
            NPC::remove(clientNumber); // The server connections of NPCs are removed when they are dismantled -
                                       // they must be re-created manually in the new scenario, unlike players
#endif
    }
}
void LogicSystem::setupExtent(ScriptValuePtr scriptEntity, int type, float x, float y, float z, int attr1, int attr2, int attr3, int attr4)
{
    int uniqueId = scriptEntity->getPropertyInt("uniqueId");

    Logging::log(Logging::DEBUG, "setupExtent: %d,  %d : %f,%f,%f : %d,%d,%d,%d\r\n", uniqueId, type, x, y, z, attr1, attr2, attr3, attr4);
    INDENT_LOG(Logging::DEBUG);

    vector<extentity *> &ents = entities::getents();

    extentity &e = *(entities::newentity());
    ents.add(&e);

    e.type  = type;
    e.o     = vec(x,y,z);
    e.attr1 = attr1;
    e.attr2 = attr2;
    e.attr3 = attr3;
    e.attr4 = attr4;

    e.inoctanode = false; // This is not set by the constructor in sauer, but by those calling ::newentity(), so we also do that here

    // If this is a new ent for this map - i.e., we are not currently loading the map - then we must
    // do some inserting into the octaworld.
//    if (!WorldSystem::loadingWorld) // XXX Try both ways
    {
        extern void addentity(extentity* entity);
        addentity(&e);
    }

    LogicSystem::setUniqueId(&e, uniqueId);
    LogicSystem::registerLogicEntity(&e);
}
void LogicSystem::setupNonSauer(ScriptValuePtr scriptEntity)
{
    int uniqueId = scriptEntity->getPropertyInt("uniqueId");

    Logging::log(Logging::DEBUG, "setupNonSauer: %d\r\n", uniqueId);
    INDENT_LOG(Logging::DEBUG);

    LogicSystem::registerLogicEntityNonSauer(uniqueId);
}
void readClasses()
{
    if (classes.size() != 0)
        return;

    ScriptValuePtr entityClasses = ScriptEngineManager::getGlobal()->call("listEntityClasses");
    int numClasses = entityClasses->getPropertyInt("length");

    for (int i = 0; i < numClasses; i++)
        classes.push_back( entityClasses->getPropertyString(Utility::toString(i)) );

    sort( classes.begin(), classes.end() );
}
void LogicSystem::dismantleExtent(ScriptValuePtr scriptEntity)
{
    int uniqueId = scriptEntity->getPropertyInt("uniqueId");

    Logging::log(Logging::DEBUG, "Dismantle extent: %d\r\n", uniqueId);

    extentity* extent = getLogicEntity(uniqueId)->staticEntity;

    removeentity(extent);
    extent->type = ET_EMPTY;

//    entities::deleteentity(extent); extent = NULL; // For symmetry with the newentity() this should be here, but sauer does it
                                                     // in clearents() in the next load_world.
}
void luaPopulateEntityList(CEGUI::Window* entityListWindow)
{
    CEGUI::Tree* theTree = (CEGUI::Tree*)entityListWindow->getChildRecursive("Editing/EntityList/Tree");
//    theTree->initialise();
    theTree->resetList();

    // Create classes, top-level
    readClasses();

    stringTreeItemMap classTreeItems;

    for (unsigned int i = 0; i < classes.size(); i++)
    {
        std::string name = classes[i];

        CEGUI::TreeItem* item = new CEGUI::TreeItem( name );
        item->setAutoDeleted(true);
        item->setTextColours(CEGUI::colour(0.0, 0.0, 0.0));
        theTree->addItem(item);

        classTreeItems.insert( stringTreeItemMap::value_type(name, item) );
    }

    // Insert entities at second level
    for(LogicSystem::LogicEntityMap::iterator iter = LogicSystem::logicEntities.begin();
        iter != LogicSystem::logicEntities.end();
        iter++)
    {
        int uniqueId = iter->first;
        ScriptValuePtr scriptEntity = iter->second.get()->scriptEntity;
        std::string className = scriptEntity->getPropertyString("_class");

        CEGUI::TreeItem* item = new CEGUI::TreeItem( Utility::toString(uniqueId) );
        item->setAutoDeleted(true);
        item->setTextColours(CEGUI::colour(0.0, 0.0, 0.0));
        classTreeItems[className]->addItem(item);
    }

    // Prune classes with 0 entities
    for (unsigned int i = 0; i < classes.size(); i++)
    {
        CEGUI::TreeItem *item = classTreeItems[classes[i]];
        if (item->getItemCount() == 0)
        {
            theTree->removeItem(item);
            // Note: No need to remove from classTreeItems
        }
    }

    // Create tags

    CEGUI::TreeItem* tagsItem = new CEGUI::TreeItem( "__tags__" );
    tagsItem->setAutoDeleted(true);
    tagsItem->setTextColours(CEGUI::colour(0.0, 0.333, 0.0));
    theTree->addItem(tagsItem);

    stringTreeItemMap tagTreeItems;

    for(LogicSystem::LogicEntityMap::iterator iter = LogicSystem::logicEntities.begin();
        iter != LogicSystem::logicEntities.end();
        iter++)
    {
        int uniqueId = iter->first;
        ScriptValuePtr scriptEntity = iter->second.get()->scriptEntity;
        ScriptValuePtr tags = scriptEntity->getProperty("tags");
        int numTags = tags->getPropertyInt("length");

        // Add item under each of its tags, creating the tag category if necessary
        for (int i = 0; i < numTags; i++)
        {
            std::string currTag = tags->getPropertyString( Utility::toString(i) );

            // Add the tag category if needed
            if (tagTreeItems.find(currTag) == tagTreeItems.end())
            {
                CEGUI::TreeItem* item = new CEGUI::TreeItem( currTag );
                item->setAutoDeleted(true);
                item->setTextColours(CEGUI::colour(0.0, 0.0, 0.0));
                tagsItem->addItem(item);

                tagTreeItems.insert( stringTreeItemMap::value_type(currTag, item) );
            }

            // Add the entity to the tag
            CEGUI::TreeItem* item = new CEGUI::TreeItem( Utility::toString(uniqueId) );
            item->setAutoDeleted(true);
            item->setTextColours(CEGUI::colour(0.0, 0.0, 0.0));
            tagTreeItems[currTag]->addItem(item);
        }
    }
}
// Sets up a GUI for editing an entity's state data
void prepare_entity_gui()
{
    GuiControl::EditedEntity::stateData.clear();
    GuiControl::EditedEntity::sortedKeys.clear();

    GuiControl::EditedEntity::currEntity = TargetingControl::targetLogicEntity;
    if (GuiControl::EditedEntity::currEntity->isNone())
    {
        Logging::log(Logging::DEBUG, "No entity to show the GUI for\r\n");
        return;
    }

    int uniqueId = GuiControl::EditedEntity::currEntity->getUniqueId();
    ScriptValuePtr stateData = ScriptEngineManager::runScript(
        "getEntity(" + Utility::toString(uniqueId) + ").createStateDataDict()"
    );

    ScriptValuePtr keys = ScriptEngineManager::getGlobal()->call("keys", stateData);

    num_entity_gui_fields = keys->getPropertyInt("length");

    // Save the stateData, to see what changed and what didn't
    for (int i = 0; i < num_entity_gui_fields; i++)
    {
        std::string key = keys->getPropertyString( Utility::toString(i) );
        std::string guiName = ScriptEngineManager::getGlobal()->call(
            "__getVariableGuiName",
            ScriptValueArgs().append(uniqueId).append(key)
        )->getString();

        std::string value = stateData->getPropertyString(key);

        GuiControl::EditedEntity::stateData.insert(
            GuiControl::EditedEntity::StateDataMap::value_type(
                key,
                std::pair<std::string, std::string>(
                    guiName,
                    value
                )
            )
        );

//        std::string a = python::extract<std::string>( keys[i] );
//        std::string b = python::extract<std::string>( pythonStateData[keys[i]] );

        GuiControl::EditedEntity::sortedKeys.push_back( key );
    }

    sort( GuiControl::EditedEntity::sortedKeys.begin(), GuiControl::EditedEntity::sortedKeys.end() ); // So order is always the same

    for (int i = 0; i < num_entity_gui_fields; i++)
    {
        std::string key = GuiControl::EditedEntity::sortedKeys[i];
        std::string guiName = GuiControl::EditedEntity::stateData[key].first;
        std::string value = GuiControl::EditedEntity::stateData[key].second;

        std::string fieldName = "entity_gui_field_" + Utility::toString(i);
        std::string labelName = "entity_gui_label_" + Utility::toString(i);

        setsvar((char*)fieldName.c_str(), (char*)value.c_str());
        setsvar((char*)labelName.c_str(), (char*)guiName.c_str());
    }

    // Title
    std::string title = GuiControl::EditedEntity::currEntity->scriptEntity->getPropertyString("_class");
    title = Utility::toString(uniqueId) + ": " + title;

    setsvar((char*)"entity_gui_title", (char*)title.c_str());

    // Create the gui
    std::string command =
    "newgui entity [\n"
    "    guitext $entity_gui_title\n"
    "    guibar\n";

    for (int i = 0; i < num_entity_gui_fields; i++)
    {
        std::string sI = Utility::toString(i);
        std::string key = GuiControl::EditedEntity::sortedKeys[i];
        std::string value = GuiControl::EditedEntity::stateData[key].second;

        if (value.size() > 50)
        {
            Logging::log(Logging::WARNING, "Not showing field '%s' as it is overly large for the GUI\r\n", key.c_str());
            continue; // Do not even try to show overly-large items
        }

        command +=
    "    guilist [\n"
    "        guitext (get_entity_gui_label " + sI + ")\n"
    "        new_entity_gui_field_" + sI + " = (get_entity_gui_value " + sI + ")\n"
    "        guifield new_entity_gui_field_" + sI + " " + Utility::toString((int)value.size()+25) + " [set_entity_gui_value " + sI + " $new_entity_gui_field_" + sI + "] 0\n"
    "    ]\n";

        if ((i+1) % 10 == 0)
        {
            command +=
    "   guitab " + Utility::toString(i) + "\n";
        }
    }

    command +=
    "]";

//    printf("Command: %s\r\n", command.c_str());
    execute(command.c_str());
}