Browse Source

use framework logging and console

Kolja Strohm 2 months ago
parent
commit
56fbc7625e

+ 188 - 0
FactoryCraft/Animal.cpp

@@ -0,0 +1,188 @@
+#include "Animal.h"
+
+#include "AddEntityUpdate.h"
+#include "Game.h"
+#include "ItemEntity.h"
+#include "ItemStack.h"
+#include "TypeRegistry.h"
+
+Animal::Animal(
+    int typeId, Framework::Vec3<float> location, int dimensionId, int entityId)
+    : Entity(typeId, location, dimensionId, entityId)
+{}
+
+Animal::~Animal()
+{
+    if (ai)
+    {
+        ai->release();
+    }
+}
+
+void Animal::onDeath()
+{
+    if (!removed)
+    {
+        for (const SpawnConfig& config : spawns)
+        {
+            if ((double)rand() / RAND_MAX < config.chance)
+            {
+                int amount = config.min
+                           + (int)((config.max - config.min)
+                                   * ((double)rand() / RAND_MAX));
+                if (amount > 0)
+                {
+                    ItemStack* spawnedItems
+                        = Game::INSTANCE->zItemType(config.typeId)
+                              ->createItemStack(amount);
+                    if (spawnedItems)
+                    {
+                        ItemEntity* itemEntity
+                            = (ItemEntity*)Game::INSTANCE
+                                  ->zEntityType(EntityTypeEnum::ITEM)
+                                  ->createEntity(location
+                                                     + Framework::Vec3<float>(
+                                                         0.5f, 0.5f, 0.5f),
+                                      getDimensionId(),
+                                      Game::INSTANCE->getNextEntityId());
+                        itemEntity->unsaveAddItem(
+                            spawnedItems, NO_DIRECTION, 0);
+                        spawnedItems->release();
+                        Game::INSTANCE->requestWorldUpdate(
+                            new AddEntityUpdate(itemEntity, getDimensionId()));
+                    }
+                }
+            }
+        }
+    }
+    Entity::onDeath();
+}
+
+void Animal::setSpawns(const Framework::Array<SpawnConfig>& spawnConfig)
+{
+    spawns = spawnConfig;
+}
+
+void Animal::setAI(AnimalAI* ai)
+{
+    if (this->ai)
+    {
+        this->ai->release();
+    }
+    this->ai = ai;
+}
+
+bool Animal::interact(Item* zItem, Entity* zActor)
+{
+    return false;
+}
+
+void Animal::takeDamage(Entity* zSource, float damage)
+{
+    if (damage > 0)
+    {
+        ai->onDamage(zSource, damage);
+    }
+    Entity::takeDamage(zSource, damage);
+}
+
+void Animal::tick(const Dimension* zDimension)
+{
+    Entity::tick(zDimension);
+}
+
+AnimalEntityType::AnimalEntityType(Framework::Text name, ModelInfo* model)
+    : EntityType(name, model)
+{}
+
+AnimalEntityType::~AnimalEntityType()
+{
+    if (ai)
+    {
+        ai->release();
+    }
+}
+
+void AnimalEntityType::loadSuperEntity(
+    Entity* zEntity, Framework::StreamReader* zReader) const
+{
+    EntityType::loadSuperEntity(zEntity, zReader);
+}
+
+void AnimalEntityType::saveSuperEntity(
+    Entity* zEntity, Framework::StreamWriter* zWriter) const
+{
+    EntityType::saveSuperEntity(zEntity, zWriter);
+}
+
+Entity* AnimalEntityType::createEntity(
+    Framework::Vec3<float> position, int dimensionId, int entityId) const
+{
+    Animal* result = new Animal(getId(), position, dimensionId, entityId);
+    result->setAI(Game::INSTANCE->zTypeRegistry()->fromJson<AnimalAI>(ai));
+    result->setSpawns(spawns);
+    return result;
+}
+
+AnimalEntityTypeFactory::AnimalEntityTypeFactory()
+    : SubTypeFactory()
+{}
+
+AnimalEntityType* AnimalEntityTypeFactory::createValue(
+    Framework::JSON::JSONObject* zJson) const
+{
+    Framework::Text name = zJson->zValue("typeName")->asString()->getString();
+    AnimalEntityType* result = new AnimalEntityType(name,
+        Game::INSTANCE->zTypeRegistry()->fromJson<ModelInfo>(
+            zJson->zValue("model")));
+    return result;
+}
+
+void AnimalEntityTypeFactory::fromJson(
+    AnimalEntityType* zResult, Framework::JSON::JSONObject* zJson) const
+{
+    Framework::JSON::JSONArray* spawnsJson = zJson->zValue("spawns")->asArray();
+    for (int i = 0; i < spawnsJson->getLength(); i++)
+    {
+        Framework::JSON::JSONObject* spawnJson
+            = spawnsJson->zValue(i)->asObject();
+        zResult->spawns.add(SpawnConfig{
+            (int)spawnJson->zValue("min")->asNumber()->getNumber(),
+            (int)spawnJson->zValue("max")->asNumber()->getNumber(),
+            (float)spawnJson->zValue("chance")->asNumber()->getNumber(),
+            spawnJson->zValue("itemType")->asString()->getString(),
+            0,
+        });
+    }
+    zResult->ai = zJson->getValue("ai")->asObject();
+}
+
+void AnimalEntityTypeFactory::toJson(
+    AnimalEntityType* zObject, Framework::JSON::JSONObject* zResult) const
+{
+    Framework::JSON::JSONArray* spawnsJson = new Framework::JSON::JSONArray();
+    for (int i = 0; i < zObject->spawns.getEintragAnzahl(); i++)
+    {
+        SpawnConfig spawn = zObject->spawns.get(i);
+        Framework::JSON::JSONObject* spawnJson
+            = new Framework::JSON::JSONObject();
+        spawnJson->addValue("min", new Framework::JSON::JSONNumber(spawn.min));
+        spawnJson->addValue("max", new Framework::JSON::JSONNumber(spawn.max));
+        spawnJson->addValue(
+            "chance", new Framework::JSON::JSONNumber(spawn.chance));
+        spawnJson->addValue(
+            "itemType", new Framework::JSON::JSONString(spawn.itemTypeName));
+        spawnsJson->addValue(spawnJson);
+    }
+    zResult->addValue("spawns", spawnsJson);
+    zResult->addValue(
+        "typeName", new Framework::JSON::JSONString(zObject->getName()));
+    zResult->addValue(
+        "model", Game::INSTANCE->zTypeRegistry()->toJson(zObject->zModel()));
+    zResult->addValue("ai", zObject->ai->clone());
+}
+
+Framework::Text AnimalEntityTypeFactory::getTypeToken() const
+{
+    return "animal";
+}

+ 67 - 0
FactoryCraft/Animal.h

@@ -0,0 +1,67 @@
+#pragma once
+
+#include "AnimalAI.h"
+#include "BasicBlocks.h"
+#include "Entity.h"
+#include "EntityType.h"
+
+class Animal : public Entity
+{
+private:
+    Framework::Array<SpawnConfig> spawns;
+    AnimalAI* ai;
+
+protected:
+    void onDeath() override;
+
+public:
+    Animal(int typeId,
+        Framework::Vec3<float> location,
+        int dimensionId,
+        int entityId);
+    ~Animal();
+    void setSpawns(const Framework::Array<SpawnConfig>& spawnConfig);
+    void setAI(AnimalAI* ai);
+    bool interact(Item* zItem, Entity* zActor) override;
+    void takeDamage(Entity* zSource, float damage) override;
+    void tick(const Dimension* zDimension) override;
+};
+
+class AnimalEntityTypeFactory;
+
+class AnimalEntityType : public EntityType
+{
+private:
+    Framework::JSON::JSONObject* ai;
+    Framework::Array<SpawnConfig> spawns;
+
+protected:
+    virtual void loadSuperEntity(
+        Entity* zEntity, Framework::StreamReader* zReader) const;
+    virtual void saveSuperEntity(
+        Entity* zEntity, Framework::StreamWriter* zWriter) const;
+
+public:
+    AnimalEntityType(Framework::Text name, ModelInfo* model);
+    ~AnimalEntityType();
+
+    Entity* createEntity(Framework::Vec3<float> position,
+        int dimensionId,
+        int entityId) const override;
+
+    friend AnimalEntityTypeFactory;
+};
+
+class AnimalEntityTypeFactory
+    : public SubTypeFactory<EntityType, AnimalEntityType>
+{
+public:
+    AnimalEntityTypeFactory();
+    AnimalEntityType* createValue(
+        Framework::JSON::JSONObject* zJson) const override;
+    void fromJson(AnimalEntityType* zResult,
+        Framework::JSON::JSONObject* zJson) const override;
+    void toJson(AnimalEntityType* zObject,
+        Framework::JSON::JSONObject* zResult) const override;
+    Framework::Text getTypeToken() const override;
+};

+ 47 - 0
FactoryCraft/AnimalAI.cpp

@@ -0,0 +1,47 @@
+#include "AnimalAI.h"
+
+#include "Entity.h"
+
+AnimalAI::AnimalAI(Animal* zAnimal)
+    : ReferenceCounter(),
+      zAnimal(zAnimal),
+      ticksToNextAction(0),
+      viewDistance(0)
+{}
+
+void AnimalAI::onTick()
+{
+    ticksToNextAction--;
+    if (ticksToNextAction <= 0)
+    {
+        ticksToNextAction = desideAction();
+    }
+}
+
+void AnimalAI::save(Framework::StreamWriter* zWriter) const {}
+
+void AnimalAI::load(Framework::StreamReader* zReader) {}
+
+void AnimalAI::onEntityEntersView(Entity* zEntity)
+{
+    for (int id : viewableEntities)
+    {
+        if (id == zEntity->getId())
+        {
+            return;
+        }
+    }
+    viewableEntities.add(zEntity->getId());
+}
+
+void AnimalAI::onEntityLeavesView(Entity* zEntity)
+{
+    for (auto iterator = viewableEntities.begin(); iterator; iterator++)
+    {
+        if (*iterator == zEntity->getId())
+        {
+            iterator.remove();
+            return;
+        }
+    }
+}

+ 30 - 0
FactoryCraft/AnimalAI.h

@@ -0,0 +1,30 @@
+#pragma once
+
+#include <Array.h>
+#include <Reader.h>
+#include <Writer.h>
+
+class Animal;
+class Entity;
+
+class AnimalAI : public Framework::ReferenceCounter
+{
+private:
+    Animal* zAnimal;
+    int ticksToNextAction;
+    Framework::Array<int> viewableEntities;
+    int viewDistance;
+
+public:
+    AnimalAI(Animal* zAnimal);
+
+    void onTick();
+
+    virtual void save(Framework::StreamWriter* zWriter) const;
+    virtual void load(Framework::StreamReader* zReader);
+
+    virtual void onDamage(Entity* zAttacker, float damage) = 0;
+    virtual void onEntityEntersView(Entity* zEntity);
+    virtual void onEntityLeavesView(Entity* zEntity);
+    virtual int desideAction() = 0;
+};

+ 3 - 1
FactoryCraft/BlockInfoCommand.cpp

@@ -1,5 +1,7 @@
 #include "BlockInfoCommand.h"
 
+#include <Logging.h>
+
 #include "Block.h"
 #include "BlockType.h"
 #include "Chat.h"
@@ -145,6 +147,6 @@ void BlockInfoCommand::execute(
     }
     else
     {
-        std::cout << result;
+        Framework::Logging::info() << result;
     }
 }

+ 9 - 7
FactoryCraft/Chat.cpp

@@ -1,6 +1,7 @@
 #include "Chat.h"
 
 #include <Datei.h>
+#include <Logging.h>
 
 #include "Game.h"
 #include "Player.h"
@@ -19,11 +20,12 @@ Chat::Chat()
     if (messageData.existiert()
         && messageData.open(Framework::Datei::Style::lesen))
     {
-        std::cout << "loading chat history from "
-                  << messageData.zPfad()->getText() << std::endl
-                  << "Delete that file to reset the chat history or use the "
-                     "'/resetChat [channel] [timestamp]' command."
-                  << std::endl; // TODO: implement /resetChat command
+        Framework::Logging::info()
+            << "loading chat history from " << messageData.zPfad()->getText()
+            << "\nDelete that file to reset the chat history or use the "
+               "'/resetChat [channel] [timestamp]' command."; // TODO: implement
+                                                              // /resetChat
+                                                              // command
         while (!messageData.istEnde())
         {
             ChatMessage* message = new ChatMessage(&messageData);
@@ -230,7 +232,7 @@ void Chat::chatApi(Framework::StreamReader* zRequest,
 void Chat::broadcastMessage(Framework::Text message, Framework::Text channel)
 {
     addMessage(new ChatMessage(message, channel, ""));
-    std::cout << "Chat [" << channel << "] " << message << "\n";
+    Framework::Logging::info() << "Chat [" << channel << "] " << message;
 }
 
 void Chat::sendMessageTo(
@@ -238,7 +240,7 @@ void Chat::sendMessageTo(
 {
     if (!zTarget)
     {
-        std::cout << message << "\n";
+        Framework::Logging::info() << message;
         return;
     }
     Player* p = dynamic_cast<Player*>(zTarget);

+ 8 - 4
FactoryCraft/Chunk.cpp

@@ -2,6 +2,7 @@
 
 #include <AsynchronCall.h>
 #include <InMemoryBuffer.h>
+#include <Logging.h>
 
 #include "Constants.h"
 #include "Dimension.h"
@@ -343,7 +344,8 @@ void Chunk::addObserver(Entity* zEntity, DoLaterHandler& laterHandler)
         sendLightToClient(&buffer);
         NetworkMessage* msg = new NetworkMessage();
         msg->addressDimension(Game::INSTANCE->zDimension(dimensionId));
-        std::cout << "chunk size: " << buffer.getSize() << "b\n";
+        Framework::Logging::debug()
+            << "chunk size: " << buffer.getSize() << "b";
         char* message = new char[buffer.getSize()];
         buffer.lese(message, (int)buffer.getSize());
         msg->setMessage(message, (int)buffer.getSize());
@@ -540,7 +542,8 @@ void Chunk::putBlockAt(Framework::Vec3<int> location, Block* block)
     Block* old = blocks[index];
     if (old && old->isTickSource())
     { // remove from tick sorces
-        for (Framework::Iterator<Block*> obj = tickSources.begin(); obj; obj++)
+        for (Framework::ArrayIterator<Block*> obj = tickSources.begin(); obj;
+             obj++)
         {
             if (obj.val() == old)
             {
@@ -986,8 +989,9 @@ void Chunk::removeUnusedBlocks()
         if (Game::INSTANCE->zBlockType(blockIds[i])->doesNeedClientInstance())
             count++;
     }
-    std::cout << "chunk " << location.x << ", " << location.y
-              << " was generated with " << count << " blocks.\n";
+    Framework::Logging::debug()
+        << "chunk " << location.x << ", " << location.y
+        << " was generated with " << count << " blocks.";
 }
 
 int Chunk::getDimensionId() const

+ 13 - 10
FactoryCraft/Dimension.cpp

@@ -1,5 +1,7 @@
 #include "Dimension.h"
 
+#include <Logging.h>
+
 #include "ChunkMap.h"
 #include "Constants.h"
 #include "Datei.h"
@@ -282,14 +284,15 @@ void Dimension::thread()
         {
             messer.messungEnde();
             time += messer.getSekunden();
-            std::cout << "100000 light updates needed " << time << " seconds\n";
+            Logging::debug()
+                << "100000 light updates needed " << time << " seconds";
             time = 0;
             index = 0;
             messer.messungStart();
         }
     }
-    std::cout << Text("Dimension ") + this->getDimensionId()
-                     + " update Thread exited.\n";
+    Logging::info() << Text("Dimension ") + this->getDimensionId()
+                           + " update Thread exited.";
 }
 
 void Dimension::getAddrOf(Punkt cPos, char* addr) const
@@ -481,7 +484,7 @@ void Dimension::setChunk(Chunk* chunk, Punkt center)
     {
         cs.lock();
         int index = 0;
-        for (Iterator<RequestQueue> iterator = waitingRequests.begin();
+        for (ArrayIterator<RequestQueue> iterator = waitingRequests.begin();
              iterator;)
         {
             Entity* zE = Game::INSTANCE->zEntity(iterator.val().sourceId);
@@ -613,7 +616,7 @@ bool Dimension::reviveChunk(int x, int y)
     }
     removedChunksCs.lock();
     int index = 0;
-    for (Iterator<Chunk*> i = removedChunks.begin(); i; i++)
+    for (ArrayIterator<Chunk*> i = removedChunks.begin(); i; i++)
     {
         if (i->getCenter().x == x && i->getCenter().y == y)
         {
@@ -646,7 +649,7 @@ void Dimension::removeOldChunks()
     }
     chunkCs.unlock();
     structurCs.lock();
-    Iterator<MultiblockStructure*> i = structures.begin();
+    ArrayIterator<MultiblockStructure*> i = structures.begin();
     while (i)
     {
         if (i->isEmpty())
@@ -732,8 +735,8 @@ void Dimension::updateLightAtChunkBorders(Punkt chunkCenter)
 {
     if (lightUpdateQueue.getEintragAnzahl() > 300000)
     {
-        std::cout
-            << "warning: light calculation queue is over 300000 blocks long\n";
+        Logging::warning()
+            << "light calculation queue is over 300000 blocks long";
     }
     for (int i = WORLD_HEIGHT - 1; i >= 0; i--)
     {
@@ -866,8 +869,8 @@ MultiblockStructure* Dimension::zStructureById(__int64 id)
         structurCs.unlock();
         return str;
     }
-    std::cout << "WARNING: did not find Structure information file '" << path
-              << "'.\n";
+    Logging::warning() << "did not find Structure information file '" << path
+                       << "'.";
     structurCs.unlock();
     return 0;
 }

+ 14 - 10
FactoryCraft/DimensionGenerator.cpp

@@ -1,6 +1,7 @@
 #include "DimensionGenerator.h"
 
 #include <iostream>
+#include <Logging.h>
 #include <Zeit.h>
 
 #include "Constants.h"
@@ -273,7 +274,8 @@ BiomedCavedDimensionGenerator::getGeneratedStructoresForArea(
 Chunk* BiomedCavedDimensionGenerator::generateChunk(int centerX, int centerY)
 {
     zMemory()->lock();
-    std::cout << "generating chunk " << centerX << ", " << centerY << "\n";
+    Framework::Logging::debug()
+        << "generating chunk " << centerX << ", " << centerY;
     double structureTime = 0;
     double structureTime2 = 0;
     double structureTime3 = 0;
@@ -385,15 +387,17 @@ Chunk* BiomedCavedDimensionGenerator::generateChunk(int centerX, int centerY)
     caveGen->release();
     structures->release();
     zmGlobal.messungEnde();
-    std::cout << "structureGenerationTime: " << structureTime << "\n";
-    std::cout << "structure.isBlockAffected: " << structureTime2 << "\n";
-    std::cout << "structure.generateBlockAt: " << structureTime3 << "\n";
-    std::cout << "caveGenerationTime: " << caveTime << "\n";
-    std::cout << "caveEvaluationTime: " << caveTime2 << "\n";
-    std::cout << "blockGenTime: " << blockGenTime << "\n";
-    std::cout << "biomTime: " << biomTime << "\n";
-    std::cout << "layerTime: " << layerTime << "\n";
-    std::cout << "totalTime: " << zmGlobal.getSekunden() << "\n";
+    Framework::Logging::trace() << "structureGenerationTime: " << structureTime;
+    Framework::Logging::trace()
+        << "structure.isBlockAffected: " << structureTime2;
+    Framework::Logging::trace()
+        << "structure.generateBlockAt: " << structureTime3;
+    Framework::Logging::trace() << "caveGenerationTime: " << caveTime;
+    Framework::Logging::trace() << "caveEvaluationTime: " << caveTime2;
+    Framework::Logging::trace() << "blockGenTime: " << blockGenTime;
+    Framework::Logging::trace() << "biomTime: " << biomTime;
+    Framework::Logging::trace() << "layerTime: " << layerTime;
+    Framework::Logging::debug() << "totalTime: " << zmGlobal.getSekunden();
     zMemory()->unlock();
     return chunk;
 }

+ 4 - 2
FactoryCraft/DimensionMap.cpp

@@ -1,6 +1,7 @@
 #include "DimensionMap.h"
 
 #include <Datei.h>
+#include <Logging.h>
 
 #include "Chat.h"
 #include "ChunkMap.h"
@@ -194,8 +195,9 @@ void DimensionMap::saveMap(char* addr, int addrLen)
                 "Could not save map data. The map has to be recalulated at "
                 "each chunk loading.",
                 Chat::CHANNEL_WARNING);
-            std::cout << "WARNING: could not open file '" << filePath.getText()
-                      << "' for writing.";
+            Framework::Logging::warning()
+                << "could not open file '" << filePath.getText()
+                << "' for writing.";
         }
     }
     cs.unlock();

+ 9 - 3
FactoryCraft/Entity.cpp

@@ -722,6 +722,11 @@ void Entity::setPosition(Framework::Vec3<float> pos)
     location = pos;
 }
 
+void Entity::takeDamage(Entity* zSource, float damage)
+{
+    // TODO: implement this
+}
+
 void Entity::setHP(float hp)
 {
     currentHP = MIN(MAX(hp, 0), maxHP);
@@ -734,7 +739,7 @@ void Entity::setHP(float hp)
     notifyStatusBarObservers(msg);
     if (currentHP == 0)
     {
-         onDeath();
+        onDeath();
     }
 }
 
@@ -774,8 +779,9 @@ void Entity::setThirst(float thirst)
     notifyStatusBarObservers(msg);
 }
 
-void Entity::setGravityMultiplier(float multiplier) {
-	gravityMultiplier = multiplier;
+void Entity::setGravityMultiplier(float multiplier)
+{
+    gravityMultiplier = multiplier;
 }
 
 float Entity::getMaxHP() const

+ 2 - 1
FactoryCraft/Entity.h

@@ -9,8 +9,8 @@
 #include "Effect.h"
 #include "Inventory.h"
 #include "ItemSkill.h"
-#include "NetworkMessage.h"
 #include "ModelInfo.h"
+#include "NetworkMessage.h"
 
 class EntityType;
 class Dimension;
@@ -110,6 +110,7 @@ public:
     virtual void onFall(float collisionSpeed);
     void setChatSecurityLevel(int level);
     void setPosition(Framework::Vec3<float> pos);
+    virtual void takeDamage(Entity* zSource, float damage);
     void setHP(float hp);
     void setStamina(float stamina);
     void setHunger(float hunger);

+ 4 - 0
FactoryCraft/FactoryCraft.vcxproj

@@ -96,6 +96,8 @@
     <RemoteTargetPath>$(RemoteProjectDir)/$(TargetName)$(TargetExt)</RemoteTargetPath>
   </PropertyGroup>
   <ItemGroup>
+    <ClInclude Include="Animal.h" />
+    <ClInclude Include="AnimalyAI.h" />
     <ClInclude Include="ArrayUtils.h" />
     <ClInclude Include="BlockFilter.h" />
     <ClInclude Include="BlockInfoCommand.h" />
@@ -199,6 +201,8 @@
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="AddEntityUpdate.cpp" />
+    <ClCompile Include="Animal.cpp" />
+    <ClCompile Include="AnimalAI.cpp" />
     <ClCompile Include="Area.cpp" />
     <ClCompile Include="ArrayUtils.cpp" />
     <ClCompile Include="BasicBlocks.cpp" />

+ 15 - 0
FactoryCraft/FactoryCraft.vcxproj.filters

@@ -103,6 +103,9 @@
     <Filter Include="server\utils">
       <UniqueIdentifier>{843e5bdf-f68d-4178-93be-426e72b12699}</UniqueIdentifier>
     </Filter>
+    <Filter Include="entities\animals">
+      <UniqueIdentifier>{8c0ab651-350d-42ad-92e8-45899c87420a}</UniqueIdentifier>
+    </Filter>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="Chunk.h">
@@ -405,6 +408,12 @@
     <ClInclude Include="PlaceableProof.h">
       <Filter>world</Filter>
     </ClInclude>
+    <ClInclude Include="Animal.h">
+      <Filter>entities\animals</Filter>
+    </ClInclude>
+    <ClInclude Include="AnimalyAI.h">
+      <Filter>entities\animals</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="Server.cpp">
@@ -695,5 +704,11 @@
     <ClCompile Include="PlaceableProof.cpp">
       <Filter>world</Filter>
     </ClCompile>
+    <ClCompile Include="AnimalAI.cpp">
+      <Filter>entities\animals</Filter>
+    </ClCompile>
+    <ClCompile Include="Animal.cpp">
+      <Filter>entities\animals</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>

+ 5 - 3
FactoryCraft/FluidBlock.cpp

@@ -1,5 +1,7 @@
 #include "FluidBlock.h"
 
+#include <Logging.h>
+
 #include "Dimension.h"
 #include "FluidContainer.h"
 #include "Game.h"
@@ -127,9 +129,9 @@ void FluidBlock::doFlow()
                         }
                         else
                         {
-                            std::cout
-                                << "ERROR: created flow fuild block is not an "
-                                   "instance of FluidBlock\n";
+                            Framework::Logging::error()
+                                << "created flow fuild block is not an "
+                                   "instance of FluidBlock";
                             belowBlock->release();
                         }
                     }

+ 20 - 14
FactoryCraft/FluidContainer.cpp

@@ -1,5 +1,6 @@
 #include "FluidContainer.h"
 
+#include <Logging.h>
 #include <TextFeld.h>
 
 #include "Dimension.h"
@@ -563,8 +564,8 @@ void FluidContainerItemType::loadSuperItem(
     }
     else
     {
-        std::cout << "ERROR: FluidContainerItemType::loadSuperItem: "
-                     "zItem is not a FluidContainerItem\n";
+        Framework::Logging::error() << "FluidContainerItemType::loadSuperItem: "
+                                       "zItem is not a FluidContainerItem";
     }
 }
 
@@ -581,8 +582,8 @@ void FluidContainerItemType::saveSuperItem(
     }
     else
     {
-        std::cout << "ERROR: FluidContainerItemType::saveSuperItem: "
-                     "zItem is not a FluidContainerItem\n";
+        Framework::Logging::error() << "FluidContainerItemType::saveSuperItem: "
+                                       "zItem is not a FluidContainerItem";
     }
 }
 
@@ -609,8 +610,9 @@ void FluidContainerItemType::setItemAttribute(
     FluidContainerItem* item = dynamic_cast<FluidContainerItem*>(zItem);
     if (!item)
     {
-        std::cout << "ERROR: FluidContainerItemType::setItemAttribute: "
-                     "zItem is not a FluidContainerItem\n";
+        Framework::Logging::error()
+            << "FluidContainerItemType::setItemAttribute: "
+               "zItem is not a FluidContainerItem";
         return;
     }
     if (name.istGleich("fluidType"))
@@ -624,14 +626,16 @@ void FluidContainerItemType::setItemAttribute(
             }
             else
             {
-                std::cout << "ERROR: FluidContainerItemType::setItemAttribute: "
-                             "'fluidType' is not a valid type name\n";
+                Framework::Logging::error()
+                    << "FluidContainerItemType::setItemAttribute: "
+                       "'fluidType' is not a valid type name";
             }
         }
         else
         {
-            std::cout << "ERROR: FluidContainerItemType::setItemAttribute: "
-                         "'fluidType' is not a string or string\n";
+            Framework::Logging::error()
+                << "FluidContainerItemType::setItemAttribute: "
+                   "'fluidType' is not a string or string";
         }
     }
     else if (name.istGleich("fluidAmount"))
@@ -642,8 +646,9 @@ void FluidContainerItemType::setItemAttribute(
         }
         else
         {
-            std::cout << "ERROR: FluidContainerItemType::setItemAttribute: "
-                         "'fluidAmount' is not a number\n";
+            Framework::Logging::error()
+                << "FluidContainerItemType::setItemAttribute: "
+                   "'fluidAmount' is not a number";
         }
     }
     else
@@ -658,8 +663,9 @@ void FluidContainerItemType::addItemAttributes(
     FluidContainerItem* item = dynamic_cast<FluidContainerItem*>(zItem);
     if (!item)
     {
-        std::cout << "ERROR: FluidContainerItemType::addItemAttributes: "
-                     "zItem is not a FluidContainerItem\n";
+        Framework::Logging::error()
+            << "FluidContainerItemType::addItemAttributes: "
+               "zItem is not a FluidContainerItem";
         return;
     }
     ItemType::addItemAttributes(zItem, zItemObjet);

+ 64 - 49
FactoryCraft/Game.cpp

@@ -1,5 +1,7 @@
 #include "Game.h"
 
+#include <Logging.h>
+
 #include "AddEntityUpdate.h"
 #include "AsynchronCall.h"
 #include "Chat.h"
@@ -25,6 +27,9 @@
 
 using namespace Framework;
 
+Framework::ConsoleHandler* Game::consoleHandler = 0;
+Framework::InputLine* Game::consoleInput = 0;
+
 GameClient::GameClient(Player* zPlayer, FCKlient* client)
     : Thread(),
       zPlayer(zPlayer),
@@ -158,7 +163,7 @@ void GameClient::reply()
     other.unlock();
     if (first)
     {
-        foreground.lock(); 
+        foreground.lock();
         int id = zPlayer->getId();
         client->zForegroundWriter()->schreibe(
             (char*)&Message::POSITION_UPDATE, 1);
@@ -231,8 +236,9 @@ void GameClient::sendResponse(NetworkMessage* response)
         if (foregroundQueue.getEintragAnzahl() > 100)
         {
             queueCs.unlock();
-            std::cout << "WARNING: Game paused because nework connection to "
-                      << zPlayer->getName() << " is to slow.\n";
+            Framework::Logging::warning()
+                << "Game paused because nework connection to "
+                << zPlayer->getName() << " is to slow.";
             ZeitMesser m;
             m.messungStart();
             while (foregroundQueue.getEintragAnzahl() > 0)
@@ -241,8 +247,8 @@ void GameClient::sendResponse(NetworkMessage* response)
                 emptyForegroundQueueSync.wait(100);
             }
             m.messungEnde();
-            std::cout << "WARNING: Game resumed after " << m.getSekunden()
-                      << " seconds.\n";
+            Framework::Logging::warning()
+                << "Game resumed after " << m.getSekunden() << " seconds.";
             queueCs.lock();
         }
         foregroundQueue.add(response);
@@ -411,7 +417,7 @@ void Game::initialize()
 {
     // TODO load mods libraries
     // load block types
-    std::cout << "Loading block types\n";
+    Framework::Logging::info() << "Loading block types";
     Framework::Array<BlockType*> blockTypeArray;
     Framework::JSON::Validator::JSONValidator* validator
         = Framework::JSON::Validator::JSONValidator::buildForArray()
@@ -428,7 +434,7 @@ void Game::initialize()
             for (Framework::JSON::Validator::JSONValidationResult* result :
                 validationResults)
             {
-                result->printInvalidInfo();
+                Framework::Logging::error() << result->getInvalidInfo();
             }
             if (validParts)
             {
@@ -445,8 +451,8 @@ void Game::initialize()
             }
         });
     validator->release();
-    std::cout << "Loaded " << blockTypeArray.getEintragAnzahl()
-              << " block types from data/blocks\n";
+    Framework::Logging::info() << "Loaded " << blockTypeArray.getEintragAnzahl()
+                               << " block types from data/blocks";
     blockTypes = new BlockType*[2 + blockTypeArray.getEintragAnzahl()];
     blockTypes[0]
         = new NoBlockBlockType(&NoBlock::INSTANCE, "__not_yet_generated");
@@ -460,7 +466,7 @@ void Game::initialize()
     {
         blockTypes[i]->setTypeId(i);
     }
-    std::cout << "Loading item types\n";
+    Framework::Logging::info() << "Loading item types";
     Framework::Array<ItemType*> itemTypeArray;
     validator
         = Framework::JSON::Validator::JSONValidator::buildForArray()
@@ -477,7 +483,7 @@ void Game::initialize()
             for (Framework::JSON::Validator::JSONValidationResult* result :
                 validationResults)
             {
-                result->printInvalidInfo();
+                Framework::Logging::error() << result->getInvalidInfo();
             }
             if (validParts)
             {
@@ -494,8 +500,8 @@ void Game::initialize()
             }
         });
     validator->release();
-    std::cout << "Loaded " << itemTypeArray.getEintragAnzahl()
-              << " item types from data/items\n";
+    Framework::Logging::info() << "Loaded " << itemTypeArray.getEintragAnzahl()
+                               << " item types from data/items";
     itemTypes
         = new ItemType*[blockTypeCount + itemTypeArray.getEintragAnzahl()];
     itemTypes[0] = new PlayerHandItemType();
@@ -516,7 +522,7 @@ void Game::initialize()
     {
         itemTypes[i]->setTypeId(i);
     }
-    std::cout << "Loading entity types\n";
+    Framework::Logging::info() << "Loading entity types";
     Framework::Array<EntityType*> entityTypeArray;
     /* validator
         = Framework::JSON::Validator::JSONValidator::buildForArray()
@@ -550,8 +556,9 @@ void Game::initialize()
             }
         });
     validator->release();*/
-    std::cout << "Loaded " << entityTypeArray.getEintragAnzahl()
-              << " entity types from data/entities\n";
+    Framework::Logging::info()
+        << "Loaded " << entityTypeArray.getEintragAnzahl()
+        << " entity types from data/entities";
     entityTypes = new EntityType*[2 + entityTypeArray.getEintragAnzahl()];
     entityTypes[0] = new PlayerEntityType();
     entityTypes[1] = new ItemEntityType();
@@ -573,8 +580,9 @@ void Game::initialize()
         {
             if (blockTypes[i] && !blockTypes[i]->initialize(this))
             {
-                std::cout << "ERROR: Could not initialize Block Type '"
-                          << blockTypes[i]->getName() << "'.\n";
+                Framework::Logging::error()
+                    << "Could not initialize Block Type '"
+                    << blockTypes[i]->getName() << "'.";
                 blockTypes[i]->release();
                 blockTypes[i] = 0;
                 allInitialized = false;
@@ -589,8 +597,9 @@ void Game::initialize()
         {
             if (itemTypes[i] && !itemTypes[i]->initialize(this))
             {
-                std::cout << "ERROR: Could not initialize Item Type '"
-                          << itemTypes[i]->getName() << "'.\n";
+                Framework::Logging::error()
+                    << "Could not initialize Item Type '"
+                    << itemTypes[i]->getName() << "'.";
                 itemTypes[i]->release();
                 itemTypes[i] = 0;
                 allInitialized = false;
@@ -605,8 +614,9 @@ void Game::initialize()
         {
             if (entityTypes[i] && !entityTypes[i]->initialize(this))
             {
-                std::cout << "ERROR: Could not initialize Entity Type '"
-                          << entityTypes[i]->getName() << "'.\n";
+                Framework::Logging::error()
+                    << "Could not initialize Entity Type '"
+                    << entityTypes[i]->getName() << "'.";
                 entityTypes[i]->release();
                 entityTypes[i] = 0;
                 allInitialized = false;
@@ -752,9 +762,10 @@ void Game::thread()
                     addDimension(dim);
                 else
                 {
-                    std::cout << "ERROR: could not create dimension "
-                              << update->getAffectedDimension()
-                              << ". No Factory was provided.\n";
+                    Framework::Logging::error()
+                        << "could not create dimension "
+                        << update->getAffectedDimension()
+                        << ". No Factory was provided.";
                 }
             }
             if (zDimension(update->getAffectedDimension()))
@@ -796,19 +807,19 @@ void Game::thread()
             totalTickTime = 0;
             tickCounter = 0;
             totalTime = 0;
-            std::cout << std::flush; // update info in console
         }
         else if (sec > 1)
         {
-            std::cout << "WARNING: tick needed " << sec
-                      << " seconds. The game will run sower then normal.\n";
-            std::cout << "waiting: " << waitTotal << "\nremoveOldClients: "
-                      << removeOldClients.getSekunden()
-                      << "\ntickEntities:" << tickEntities.getSekunden()
-                      << "\nworldUpdates: " << worldUpdates.getSekunden()
-                      << "\nclientReply: " << clientReply.getSekunden()
-                      << "\nremoveOldChunks:" << removeOldChunks.getSekunden()
-                      << "\n";
+            Framework::Logging::warning()
+                << "tick needed " << sec
+                << " seconds. The game will run sower then normal.\n";
+            Framework::Logging::trace()
+                << "waiting: " << waitTotal
+                << "\nremoveOldClients: " << removeOldClients.getSekunden()
+                << "\ntickEntities:" << tickEntities.getSekunden()
+                << "\nworldUpdates: " << worldUpdates.getSekunden()
+                << "\nclientReply: " << clientReply.getSekunden()
+                << "\nremoveOldChunks:" << removeOldChunks.getSekunden();
         }
     }
     save();
@@ -817,7 +828,7 @@ void Game::thread()
     ticker->exitAndWait();
     for (Dimension* dim : *dimensions)
         dim->requestStopAndWait();
-    std::cout << "Game thread exited\n";
+    Framework::Logging::info() << "Game thread exited";
 }
 
 void Game::api(Framework::InMemoryBuffer* zRequest, GameClient* zOrigin)
@@ -836,9 +847,10 @@ void Game::api(Framework::InMemoryBuffer* zRequest, GameClient* zOrigin)
                     zOrigin->zEntity()->getDimensionId());
                 if (!dim)
                 {
-                    std::cout << "ERROR: could not create dimension "
-                              << zOrigin->zEntity()->getDimensionId()
-                              << ". No Factory was provided.\n";
+                    Framework::Logging::error()
+                        << "could not create dimension "
+                        << zOrigin->zEntity()->getDimensionId()
+                        << ". No Factory was provided.";
                     return;
                 }
                 addDimension(dim);
@@ -923,8 +935,8 @@ void Game::api(Framework::InMemoryBuffer* zRequest, GameClient* zOrigin)
             break;
         }
     default:
-        std::cout << "received unknown api request in game with type "
-                  << (int)type << "\n";
+        Framework::Logging::warning()
+            << "received unknown api request in game with type " << (int)type;
     }
     if (!response->isEmpty())
     {
@@ -986,8 +998,9 @@ bool Game::checkPlayer(Framework::Text name, Framework::Text secret)
         return 1;
     else
     {
-        std::cout << "player " << name.getText()
-                  << " tryed to connect with an invalid secret.\n";
+        Framework::Logging::warning()
+            << "player " << name.getText()
+            << " tryed to connect with an invalid secret.";
         return 0;
     }
 }
@@ -1036,9 +1049,9 @@ GameClient* Game::addPlayer(FCKlient* client, Framework::Text name)
         Dimension* dim = generator->createDimension(player->getDimensionId());
         if (!dim)
         {
-            std::cout << "ERROR: could not create dimension "
-                      << (int)player->getDimensionId()
-                      << ". No Factory was provided.\n";
+            Framework::Logging::error() << "could not create dimension "
+                                        << (int)player->getDimensionId()
+                                        << ". No Factory was provided.";
             return 0;
         }
         NetworkMessage* msg = new NetworkMessage();
@@ -1218,7 +1231,7 @@ void Game::save() const
     for (auto dim : *dimensions)
         dim->save(path);
     chat->save();
-    std::cout << "Game was saved\n";
+    Framework::Logging::info() << "Game was saved";
 }
 
 void Game::requestStop()
@@ -1394,7 +1407,8 @@ int Game::getBlockTypeId(const char* name) const
             return i;
         }
     }
-    std::cout << "WARNING: no block type with name '" << name << "' found.\n";
+    Framework::Logging::warning()
+        << "no block type with name '" << name << "' found.";
     return -1;
 }
 
@@ -1408,7 +1422,8 @@ int Game::getItemTypeId(const char* name) const
             return i;
         }
     }
-    std::cout << "WARNING: no item type with name '" << name << "' found.\n";
+    Framework::Logging::warning()
+        << "no item type with name '" << name << "' found.";
     return -1;
 }
 

+ 5 - 0
FactoryCraft/Game.h

@@ -1,5 +1,6 @@
 #pragma once
 
+#include <Console.h>
 #include <Critical.h>
 #include <Either.h>
 #include <InMemoryBuffer.h>
@@ -81,6 +82,10 @@ public:
 
 class Game : public virtual Framework::Thread
 {
+public:
+    static Framework::ConsoleHandler* consoleHandler;
+    static Framework::InputLine* consoleInput;
+
 private:
     Framework::Text name;
     TypeRegistry* typeRegistry;

+ 4 - 4
FactoryCraft/Inventory.cpp

@@ -698,12 +698,12 @@ int Inventory::numberOfAddableItems(
     return count;
 }
 
-Framework::Iterator<ItemSlot*> Inventory::begin()
+Framework::ArrayIterator<ItemSlot*> Inventory::begin()
 {
     return pullSlotsOrder->begin();
 }
 
-Framework::Iterator<ItemSlot*> Inventory::end()
+Framework::ArrayIterator<ItemSlot*> Inventory::end()
 {
     return pullSlotsOrder->end();
 }
@@ -846,8 +846,8 @@ Framework::Vec3<float> Inventory::getLocation() const
 
 bool Inventory::unsafeMove(Inventory* zSource,
     Inventory* zTarget,
-    Iterator<ItemSlot*>& sourceSlot,
-    Iterator<ItemSlot*>& targetSlot,
+    ArrayIterator<ItemSlot*>& sourceSlot,
+    ArrayIterator<ItemSlot*>& targetSlot,
     Direction outDir,
     Direction inDir,
     int& count)

+ 5 - 5
FactoryCraft/Inventory.h

@@ -115,10 +115,10 @@ public:
     ItemStack* takeItemsOut(ItemSlot* zSlot, int count, Direction dir);
     virtual void addItems(ItemSlot* zSlot, ItemStack* zItems, Direction dir);
     InventoryInteraction interactWith(Inventory* zInventory, Direction dir);
-    void unsaveAddItem(ItemStack* zStack, Direction dir, ItemFilter *zFilter);
+    void unsaveAddItem(ItemStack* zStack, Direction dir, ItemFilter* zFilter);
     int numberOfAddableItems(const ItemStack* zStack, Direction dir) const;
-    Framework::Iterator<ItemSlot*> begin();
-    Framework::Iterator<ItemSlot*> end();
+    Framework::ArrayIterator<ItemSlot*> begin();
+    Framework::ArrayIterator<ItemSlot*> end();
     void inventoryApi(Framework::StreamReader* zRequest,
         NetworkMessage* zResponse,
         Entity* zSource);
@@ -139,8 +139,8 @@ public:
 private:
     static bool unsafeMove(Inventory* zSource,
         Inventory* zTarget,
-        Framework::Iterator<ItemSlot*>& sourceSlot,
-        Framework::Iterator<ItemSlot*>& targetSlot,
+        Framework::ArrayIterator<ItemSlot*>& sourceSlot,
+        Framework::ArrayIterator<ItemSlot*>& targetSlot,
         Direction outDir,
         Direction inDir,
         int& count);

+ 4 - 2
FactoryCraft/ItemType.cpp

@@ -2,6 +2,7 @@
 #include "ItemType.h"
 
 #include <InMemoryBuffer.h>
+#include <Logging.h>
 
 #include "Game.h"
 #include "ItemSkill.h"
@@ -133,8 +134,9 @@ void ItemType::setItemAttribute(
     }
     if (!ok)
     {
-        std::cout << "Invalid Item Attribute '" << name << "' for item type '"
-                  << getName() << "'\n";
+        Framework::Logging::warning()
+            << "Invalid Item Attribute '" << name << "' for item type '"
+            << getName() << "'\n";
     }
 }
 

+ 55 - 5
FactoryCraft/JsonUtils.cpp

@@ -1,10 +1,13 @@
 #include "JsonUtils.h"
 
+#include <Console.h>
 #include <Datei.h>
 
-void loadAllJsonsFromDirectory(Framework::Text path,
-    std::function<void(Framework::JSON::JSONValue* zValue, Framework::Text path)> action)
+#include "Game.h"
+
+int countAllJsonsInDirectory(Framework::Text path)
 {
+    int count = 0;
     if (path.hatAt(path.getLength() - 1, "/")
         || path.hatAt(path.getLength() - 1, "\\"))
     {
@@ -13,11 +16,39 @@ void loadAllJsonsFromDirectory(Framework::Text path,
     Framework::Datei dir(path);
     if (dir.istOrdner())
     {
-        Framework::RCArray<Framework::Text> *list = dir.getDateiListe();
+        Framework::RCArray<Framework::Text>* list = dir.getDateiListe();
         for (Framework::Text* name : *list)
         {
             Framework::Text nextPath = path + "/" + *name;
-            loadAllJsonsFromDirectory(nextPath, action);
+            count += countAllJsonsInDirectory(nextPath);
+        }
+        list->release();
+    }
+    else if (path.hatAt(path.getLength() - 5, ".json") && dir.existiert())
+    {
+        count++;
+    }
+    return count;
+}
+
+void internalLoadAllJsonsFromDirectory(Framework::Text path,
+    std::function<void(
+        Framework::JSON::JSONValue* zValue, Framework::Text path)> action,
+    Framework::ConsoleProgressBar* progress)
+{
+    if (path.hatAt(path.getLength() - 1, "/")
+        || path.hatAt(path.getLength() - 1, "\\"))
+    {
+        path.remove(path.getLength() - 1, path.getLength());
+    }
+    Framework::Datei dir(path);
+    if (dir.istOrdner())
+    {
+        Framework::RCArray<Framework::Text>* list = dir.getDateiListe();
+        for (Framework::Text* name : *list)
+        {
+            Framework::Text nextPath = path + "/" + *name;
+            internalLoadAllJsonsFromDirectory(nextPath, action, progress);
         }
         list->release();
     }
@@ -30,5 +61,24 @@ void loadAllJsonsFromDirectory(Framework::Text path,
             action(value, path);
             value->release();
         }
-	}
+        progress->setProgress(progress->getProgress() + 1);
+        progress->triggerUpdate();
+    }
+}
+
+void loadAllJsonsFromDirectory(Framework::Text path,
+    std::function<void(
+        Framework::JSON::JSONValue* zValue, Framework::Text path)> action)
+{
+    Framework::ConsoleProgressBar* progressBar
+        = new Framework::ConsoleProgressBar();
+    Game::consoleHandler->addContent(
+        progressBar, Framework::ConsoleContentPosition::Top);
+    progressBar->triggerUpdate();
+    progressBar->setMaxProgress(countAllJsonsInDirectory(path));
+    progressBar->triggerUpdate();
+    internalLoadAllJsonsFromDirectory(path, action, progressBar);
+    progressBar->setMaxWidth(0);
+    progressBar->triggerUpdate();
+    Game::consoleHandler->removeContent(progressBar);
 }

+ 3 - 1
FactoryCraft/NetworkMessage.cpp

@@ -1,5 +1,7 @@
 #include "NetworkMessage.h"
 
+#include <Logging.h>
+
 #include "ChatMessage.h"
 #include "ChatObserver.h"
 #include "Chunk.h"
@@ -249,7 +251,7 @@ void NetworkMessage::writeTo(Framework::StreamWriter* zWriter) const
     }
     else
     {
-        std::cout << "ERROR: invalid message was queued\n";
+        Framework::Logging::error() << "invalid message was queued";
     }
 }
 

+ 13 - 9
FactoryCraft/Quest.cpp

@@ -2,6 +2,7 @@
 
 #include <Datei.h>
 #include <Fenster.h>
+#include <Logging.h>
 #include <TextFeld.h>
 
 #include "Game.h"
@@ -701,14 +702,16 @@ void QuestManager::loadQuests()
     Framework::Text questDir = worldDir + "/quests";
     if (!Framework::DateiExistiert(questDir))
     {
-        std::cout << "no quest data found in world save, using default data\n";
+        Framework::Logging::info()
+            << "no quest data found in world save, using default data";
         questDir = "data/quests";
     }
     Framework::JSON::JSONValue* value
         = Framework::JSON::loadJSONFromFile(questDir + "/quests.json");
     if (!value || value->getType() == Framework::JSON::JSONType::NULL_)
     {
-        std::cout << "No valid quests.json found in " << questDir << "\n";
+        Framework::Logging::warning()
+            << "No valid quests.json found in " << questDir;
         if (value)
         {
             value->release();
@@ -716,7 +719,7 @@ void QuestManager::loadQuests()
     }
     else
     {
-        std::cout << "loading quests ...\n";
+        Framework::Logging::info() << "loading quests ...";
         Framework::JSON::Validator::JSONValidator* validator
             = Framework::JSON::Validator::JSONValidator::buildForArray()
                   ->addAcceptedTypeInArray(
@@ -731,7 +734,7 @@ void QuestManager::loadQuests()
         for (Framework::JSON::Validator::JSONValidationResult* invalidPart :
             validationResult)
         {
-            invalidPart->printInvalidInfo();
+            Framework::Logging::error() << invalidPart->getInvalidInfo();
         }
         value->release();
         for (Framework::JSON::JSONValue* validPart : *valid)
@@ -753,7 +756,7 @@ void QuestManager::loadQuests()
     }
     else
     {
-        std::cout << "loading quest parties ...\n";
+        Framework::Logging::info() << "loading quest parties ...";
         Framework::JSON::Validator::JSONValidator* validator
             = Framework::JSON::Validator::JSONValidator::buildForArray()
                   ->addAcceptedTypeInArray(Game::INSTANCE->zTypeRegistry()
@@ -767,7 +770,7 @@ void QuestManager::loadQuests()
         for (Framework::JSON::Validator::JSONValidationResult* invalidPart :
             validationResult)
         {
-            invalidPart->printInvalidInfo();
+            Framework::Logging::error() << invalidPart->getInvalidInfo();
         }
         value->release();
         for (Framework::JSON::JSONValue* validPart : *valid)
@@ -778,9 +781,10 @@ void QuestManager::loadQuests()
         valid->release();
         validator->release();
     }
-    std::cout << "Loaded " << questCollections.getEintragAnzahl()
-              << " Quest Collections and " << parties.getEintragAnzahl()
-              << " Quest Parties\n";
+    Framework::Logging::info()
+        << "Loaded " << questCollections.getEintragAnzahl()
+        << " Quest Collections and " << parties.getEintragAnzahl()
+        << " Quest Parties";
 }
 
 void QuestManager::saveQuests()

+ 5 - 3
FactoryCraft/Recipie.cpp

@@ -1,5 +1,7 @@
 #include "Recipie.h"
 
+#include <Logging.h>
+
 #include "CraftingStorage.h"
 #include "Game.h"
 #include "Item.h"
@@ -554,9 +556,9 @@ void ShapedRecipieFactory::fromJson(
         int y = (int)input->asObject()->zValue("y")->asNumber()->getNumber();
         if (x >= width || y >= height)
         {
-            std::cout << "Invalid input position in shaped recipie with width="
-                      << width << ", height=" << height << "\n"
-                      << (x >= width ? x : y) << "\n";
+            Framework::Logging::warning()
+                << "Invalid input position in shaped recipie with width="
+                << width << ", height=" << height << ", x=" << x << ", y=" << y;
             return;
         }
         zResult->setInput(y * width + x,

+ 5 - 3
FactoryCraft/RecipieLoader.cpp

@@ -2,6 +2,7 @@
 
 #include <Datei.h>
 #include <iostream>
+#include <Logging.h>
 #include <stdexcept>
 
 #include "Game.h"
@@ -25,7 +26,8 @@ void RecipieLoader::loadRecipies(const char* path)
 {
     loadAllJsonsFromDirectory(
         path, [this](JSONValue* zJson, Framework::Text path) {
-            std::cout << "loading recipies from '" << path << "'" << std::endl;
+            Framework::Logging::info()
+                << "loading recipies from '" << path << "'";
             JSONValidator* validator
                 = Framework::JSON::Validator::JSONValidator::buildForArray()
                       ->addAcceptedTypeInArray(Game::INSTANCE->zTypeRegistry()
@@ -36,7 +38,7 @@ void RecipieLoader::loadRecipies(const char* path)
             JSONValue* valid = validator->getValidParts(zJson, &invalidParts);
             for (JSONValidationResult* invalidPart : invalidParts)
             {
-                invalidPart->printInvalidInfo();
+                Framework::Logging::error() << invalidPart->getInvalidInfo();
             }
             int count = 0;
             if (valid)
@@ -60,7 +62,7 @@ void RecipieLoader::loadRecipies(const char* path)
                     }
                 }
             }
-            std::cout << count << " recipies were loaded.\n";
+            Framework::Logging::info() << count << " recipies were loaded.";
         });
 }
 

+ 18 - 12
FactoryCraft/Server.cpp

@@ -6,6 +6,7 @@
 #include <iostream>
 #include <JSON.h>
 #include <Klient.h>
+#include <Logging.h>
 
 #include "PlayerRegister.h"
 
@@ -22,26 +23,30 @@ FactoryCraftServer::FactoryCraftServer(InitDatei* zIni)
     sslServer = new SSLServer();
     sslServer->setPrivateKeyPassword(zIni->zWert("SSLPasswort")->getText());
     sslServer->setCertificateFile(zIni->zWert("SSLCert")->getText());
-    std::cout << "using cert file " << zIni->zWert("SSLCert")->getText()
-              << "\n";
+    Framework::Logging::info()
+        << "using cert file " << zIni->zWert("SSLCert")->getText();
     sslServer->setPrivateKeyFile(zIni->zWert("SSLKey")->getText());
-    std::cout << "using private key " << zIni->zWert("SSLKey")->getText()
-              << "\n";
+    Framework::Logging::info()
+        << "using private key " << zIni->zWert("SSLKey")->getText();
     server = new Server();
-    std::cout << "Server Port: " << ini->zWert("Port")->getText() << "\n";
+    Framework::Logging::info()
+        << "Server Port: " << ini->zWert("Port")->getText();
     if (!server->verbinde(
             (unsigned short)TextZuInt(ini->zWert("Port")->getText(), 10), 10))
     {
-        std::cout << "Der Server konnte nicht gestartet werden.\n";
+        Framework::Logging::error()
+            << "Der Server konnte nicht gestartet werden.";
         exit(1);
     }
-    std::cout << "SSL Server Port: " << ini->zWert("SSLPort")->getText()
-              << "\n";
+
+    Framework::Logging::info()
+        << "SSL Server Port: " << ini->zWert("SSLPort")->getText();
     if (!sslServer->verbinde(
             (unsigned short)TextZuInt(ini->zWert("SSLPort")->getText(), 10),
             10))
     {
-        std::cout << "Der SSL Server konnte nicht gestartet werden.\n";
+        Framework::Logging::error()
+            << "Der SSL Server konnte nicht gestartet werden.";
         exit(2);
     }
     Game::initialize(
@@ -84,7 +89,8 @@ FactoryCraftServer::FactoryCraftServer(InitDatei* zIni)
             if (!found)
             {
                 klient->sende("\0", 1);
-                std::cout << "client failed to pass through authorisation\n";
+                Framework::Logging::error()
+                    << "client failed to pass through authorisation";
                 klient->release();
             }
         }
@@ -204,7 +210,7 @@ FCKlient::~FCKlient()
 // nicht constant
 void FCKlient::setForegroundClient(SKlient* foreground)
 {
-    std::cout << "foreground client connected\n";
+    Framework::Logging::trace() << "foreground client connected";
     this->foreground = foreground;
     foregroundReader = new NetworkReader(foreground);
     foregroundWriter = new NetworkWriter(foreground);
@@ -239,7 +245,7 @@ void FCKlient::setForegroundClient(SKlient* foreground)
 
 void FCKlient::setBackgroundClient(SKlient* background)
 {
-    std::cout << "background client connected\n";
+    Framework::Logging::trace() << "background client connected";
     this->background = background;
     backgroundReader = new NetworkReader(background);
     backgroundWriter = new NetworkWriter(background);

+ 116 - 157
FactoryCraft/Start.cpp

@@ -12,6 +12,8 @@
 #    include <main.h>
 #endif
 #include <AsynchronCall.h>
+#include <Console.h>
+#include <Logging.h>
 #include <Text.h>
 #include <Zeit.h>
 
@@ -25,13 +27,13 @@ FactoryCraftServer* mserver = 0;
 LONG WINAPI exceptionHandler(struct _EXCEPTION_POINTERS* apExceptionInfo)
 {
     Sleep(10000);
-    std::cout << "ERROR: Creating dump";
-    std::cout.flush();
+    Logging::error() << "Creating dump";
     createMinidump(apExceptionInfo);
     if (mserver)
     {
-        std::cout << "The server terminated unexpectedly. Trying to save game "
-                     "progress.\n";
+        Logging::error()
+            << "The server terminated unexpectedly. Trying to save game "
+               "progress.";
         mserver->close();
     }
     return EXCEPTION_CONTINUE_SEARCH;
@@ -41,13 +43,13 @@ LONG WINAPI exceptionHandler(struct _EXCEPTION_POINTERS* apExceptionInfo)
 void onError(int i)
 {
     Sleep(10000);
-    std::cout << "ERROR: Creating dump";
-    std::cout.flush();
+    Logging::error() << "Creating dump";
     createMinidump(0);
     if (mserver)
     {
-        std::cout << "The server terminated unexpectedly. Trying to save game "
-                     "progress.\n";
+        Logging::error()
+            << "The server terminated unexpectedly. Trying to save game "
+               "progress.";
         mserver->close();
     }
 }
@@ -55,119 +57,45 @@ void onError(int i)
 void onExit()
 {
     Sleep(10000);
-    std::cout << "Programm exited";
-    std::cout.flush();
+    Logging::info() << "Programm exited";
     onError(0);
 }
 
-
 bool exited = false;
 
-class DuplicatingStreamBuf : public std::stringbuf
+class StatusBar : public StickyConsoleContent
 {
-private:
-    std::ostream& console;
-    std::ostream& file;
-    bool hasFile = 0;
-    int infoLength;
-    Critical cs;
-
 public:
-    DuplicatingStreamBuf(std::ostream& console, std::ostream& file)
-        : std::stringbuf(),
-          console(console),
-          file(file),
-          hasFile(1),
-          infoLength(0)
-    {}
-
-    DuplicatingStreamBuf(std::ostream& console)
-        : std::stringbuf(),
-          console(console),
-          file(console),
-          hasFile(0),
-          infoLength(0)
+    StatusBar()
+        : StickyConsoleContent()
     {}
 
-#ifdef WIN32
-    void __CLR_OR_THIS_CALL _Lock() override
-    {
-        cs.lock();
-    }
-
-    void __CLR_OR_THIS_CALL _Unlock() override
+    int print() const override
     {
-        cs.unlock();
-    }
-#endif
-
-    int sync() override
-    {
-        cs.lock();
-        std::string value = str();
-        if (value.length() == 0 && !Game::INSTANCE)
-        {
-            cs.unlock();
-            return 0;
-        }
-        str("");
-        if (infoLength > 0)
-        {
-            console << /* store cursor position */ "\033[s"
-                    << /* move cursor a line up*/ "\033[1A"
-                    << /* clear the line */ "\x1b[2K"
-                    << /* return to beginning of line */ "\r";
-        }
-        int newLines = Text(value.c_str()).anzahlVon('\n');
-        if (value.length() > 0)
-        {
-            console << value;
-            if (value.c_str()[value.length() - 1] != '\n')
-            {
-                console << "\n";
-                newLines++;
-            }
-        }
         if (!exited && Game::INSTANCE)
         {
+            std::cout << "\r\33[0K"; // erase current line
             int tps = Game::INSTANCE->getTicksPerSecond();
-            Framework::Text infoLine = "";
-            infoLine.append()
-                << "Players: " << Game::INSTANCE->getPlayerCount()
-                << "\tChunks: " << Game::INSTANCE->getChunkCount() << "\ttps: ";
+            std::cout << "Players: " << Game::INSTANCE->getPlayerCount()
+                      << "\tChunks: " << Game::INSTANCE->getChunkCount()
+                      << "\ttps: ";
             if (tps < 15)
             { // red
-                infoLine += "\033[1;31m";
+                std::cout << "\033[1;31m";
             }
             else if (tps < 20)
             { // yellow
-                infoLine += "\033[1;33m";
+                std::cout << "\033[1;33m";
             }
             else
             { // green
-                infoLine += "\033[1;32m";
+                std::cout << "\033[1;32m";
             }
-            infoLine.append() << tps << /* reset color */ "\033[0m"
-                              << "\tAverage Tick Time: "
-                              << Game::INSTANCE->getAverageTickTime() << "\n";
-            if (infoLength > 0)
-            {
-                infoLine.append()
-                    << /* restore cursor position */ "\033[u"
-                    << /* set cursor down by amount of new lines */
-                    (newLines > 0 ? (Text("\033[") + newLines + "B").getText()
-                                  : "");
-                // << "\x1b[0K";
-            }
-            infoLength = infoLine.getLength();
-            console << infoLine << std::flush;
-        }
-        else
-        {
-            infoLength = 0;
+            std::cout << tps << /* reset color */ "\033[0m"
+                      << "\tAverage Tick Time: "
+                      << Game::INSTANCE->getAverageTickTime();
+            return 1;
         }
-        if (hasFile) file << value << std::flush;
-        cs.unlock();
         return 0;
     }
 };
@@ -179,6 +107,8 @@ int main()
 #endif
     Framework::initFramework();
 
+    Game::consoleHandler = new ConsoleHandler();
+
 #ifndef _WINDOWS
     struct rlimit core_limits;
     core_limits.rlim_cur = core_limits.rlim_max = RLIM_INFINITY;
@@ -189,35 +119,90 @@ int main()
     Text* pfad = new Text("log/");
     pfad->append(z->getZeit("y-m-d_h-i-s.log"));
     z->release();
-    DateiPfadErstellen(pfad->getText());
-    std::ofstream file;
-    std::streambuf* sbuf = std::cout.rdbuf();
-    // #ifndef _DEBUG
-    file.open(pfad->getText());
-    std::ostream newCout(sbuf);
-    DuplicatingStreamBuf duplicator(newCout, file);
-    std::cout.rdbuf(&duplicator);
-    /* #else
-        std::ostream newCout(sbuf);
-        DuplicatingStreamBuf duplicator(newCout);
-        std::cout.rdbuf(&duplicator);
-    #endif */
-    pfad->release();
-
-    std::cout << "Starting...\n";
-    std::cout << "Loading config file fcInit.ini ...\n";
+    Datei* logFile = new Datei(pfad);
+    Logging::LoggingChannel* fileLogger
+        = new Logging::FileLoggingChannel(logFile);
+    fileLogger->setFormat(Logging::LoggingFormatBuilder()
+                              .datetime("h:i:s")
+                              .level(false)
+                              .text(": ")
+                              .build());
+    Logging::zLoggingHandler()->addChannel(fileLogger);
+    Logging::zLoggingHandler()->removeLoggingChannel(
+        Logging::LogLevel::Error, fileLogger);
+    Logging::zLoggingHandler()->removeLoggingChannel(
+        Logging::LogLevel::Warning, fileLogger);
+    Logging::LoggingChannel* errorFileLogger = new Logging::FileLoggingChannel(
+        dynamic_cast<Datei*>(logFile->getThis()));
+    errorFileLogger->setFormat(Logging::LoggingFormatBuilder()
+                                   .datetime("h:i:s")
+                                   .level()
+                                   .fileName()
+                                   .functionName()
+                                   .text("(")
+                                   .fileLine(false)
+                                   .text("): ")
+                                   .build());
+    Framework::Logging::zLoggingHandler()->addChannel(
+        Logging::LogLevel::Warning,
+        dynamic_cast<Logging::LoggingChannel*>(errorFileLogger->getThis()));
+    Framework::Logging::zLoggingHandler()->addChannel(
+        Logging::LogLevel::Error, errorFileLogger);
+    Logging::LoggingChannel* consoleLogger
+        = new Logging::ConsoleHandlerLoggingChannel(
+            dynamic_cast<ConsoleHandler*>(Game::consoleHandler->getThis()));
+    consoleLogger->setFormat(
+        Logging::LoggingFormatBuilder()
+            .color(Logging::LogLevel::Debug, Color::LIGHT_BLUE)
+            .color(Logging::LogLevel::Trace, Color::LIGHT_CYAN)
+            .datetime("h:i:s")
+            .level(false)
+            .text(": ")
+            .build());
+    Framework::Logging::zLoggingHandler()->addChannel(consoleLogger);
+    Framework::Logging::zLoggingHandler()->removeLoggingChannel(
+        Logging::LogLevel::Error, consoleLogger);
+    Framework::Logging::zLoggingHandler()->removeLoggingChannel(
+        Logging::LogLevel::Warning, consoleLogger);
+    Logging::LoggingChannel* errorConsoleLogger
+        = new Logging::ConsoleHandlerLoggingChannel(
+            dynamic_cast<ConsoleHandler*>(Game::consoleHandler->getThis()));
+    errorConsoleLogger->setFormat(
+        Logging::LoggingFormatBuilder()
+            .color(Logging::LogLevel::Warning, Color::LIGHT_YELLOW)
+            .color(Logging::LogLevel::Error, Color::LIGHT_RED)
+            .datetime("h:i:s")
+            .level()
+            .fileName()
+            .functionName()
+            .text("(")
+            .fileLine(false)
+            .text("): ")
+            .build());
+    Framework::Logging::zLoggingHandler()->addChannel(
+        Logging::LogLevel::Warning,
+        dynamic_cast<Logging::LoggingChannel*>(errorConsoleLogger->getThis()));
+    Framework::Logging::zLoggingHandler()->addChannel(
+        Logging::LogLevel::Error, errorConsoleLogger);
+
+    Game::consoleInput = new InputLine();
+    Game::consoleHandler->addContent(
+        Game::consoleInput, ConsoleContentPosition::Bottom);
+    Game::consoleHandler->addContent(
+        new StatusBar(), ConsoleContentPosition::Bottom);
+
+    Logging::info() << "Starting ...";
+    Logging::info() << "Loading config file fcInit.ini ...";
 
     InitDatei* dat = new InitDatei("fcInit.ini");
     if (!dat->laden())
     {
-        std::cout << "error: Datei konnte nicht gelesen werden. Das Programm "
-                     "wird geschlossen.\n";
+        Logging::error() << "Datei konnte nicht gelesen werden. Das Programm "
+                            "wird geschlossen.";
         dat->release();
-        // #ifndef _DEBUG
-        file.close();
-        // #endif
-        std::cout.rdbuf(sbuf);
-        exit(1);
+        Game::consoleHandler->release();
+        Framework::releaseFramework();
+        return 1;
     }
     const char* wichtig[]
         = {"SSLPort", "SSLCert", "SSLKey", "SSLPasswort", "Port"};
@@ -225,12 +210,13 @@ int main()
     {
         if (!dat->wertExistiert(w))
         {
-            std::cout << "error: The value '" << w
-                      << "' was not specified. The Server can not start.\n";
+            Logging::error()
+                << "The value '" << w
+                << "' was not specified. The Server can not start.";
             dat->release();
-            file.close();
-            std::cout.rdbuf(sbuf);
-            exit(1);
+            Game::consoleHandler->release();
+            Framework::releaseFramework();
+            return 1;
         }
     }
 
@@ -243,31 +229,7 @@ int main()
     signal(SIGFPE, onError);
     signal(SIGINT, onError);
 
-    new Framework::AsynchronCall("Commander", []() {
-        while (mserver)
-        {
-            std::string line;
-            std::getline(std::cin, line);
-            if (!mserver) return;
-            std::cout << std::flush << "\033[1A"
-                      << "\x1b[2K"
-                      << "\x1b[0G" << line << "\n\033[1A\033[s" << std::flush;
-            if (Text(line.c_str()) == Text("exit"))
-            {
-                std::cout << "The server will be terminated and the game "
-                             "progress will be saved.\n";
-                mserver->close();
-                return;
-            }
-            else if (Game::INSTANCE)
-            {
-                Game::INSTANCE->zChat()->zCommandExecutor()->execute(
-                    line.c_str(), 0);
-            }
-        }
-    });
-
-    std::cout << "The Server is now running.\n";
+    Logging::info() << "The Server is now running.";
     mserver->run();
     exited = 1;
     mserver->release();
@@ -281,11 +243,8 @@ int main()
         Game::INSTANCE = 0;
     }
     dat->release();
-    std::cout << "The server was shut down successfully.\n" << std::flush;
-    // #ifndef _DEBUG
-    file.close();
-    // #endif
-    std::cout.rdbuf(sbuf);
+    Logging::info() << "The server was shut down successfully.";
+    Game::consoleHandler->release();
     Framework::releaseFramework();
     return 0;
 }

+ 1 - 1
FactoryCraft/TickOrganizer.cpp

@@ -44,7 +44,7 @@ void TickOrganizer::addTickSource(Tickable* zObj)
 void TickOrganizer::removeTickSource(Tickable* zObj)
 {
     sourceCs.lock();
-    for (Framework::Iterator<Tickable*> obj = tickSources.begin(); obj; obj++)
+    for (Framework::ArrayIterator<Tickable*> obj = tickSources.begin(); obj; obj++)
     {
         if (obj.val() == zObj)
         {

+ 4 - 2
FactoryCraft/TickWorker.cpp

@@ -1,5 +1,7 @@
 #include "TickWorker.h"
 
+#include <Logging.h>
+
 #ifndef _WINDOWS
 #    include <sys/syscall.h>
 #    include <unistd.h>
@@ -35,8 +37,8 @@ void TickWorker::thread()
 #else
     tid = (pid_t)syscall(SYS_gettid);
 #endif
-    Framework::Text txt = Framework::Text("exiting tick worker ") + tid + "\n";
-    std::cout << txt.getText();
+    Framework::Text txt = Framework::Text("exiting tick worker ") + tid;
+    Framework::Logging::info() << txt.getText();
 }
 
 bool TickWorker::isWaiting() const

+ 20 - 2
FactoryCraft/TypeRegistry.h

@@ -3,6 +3,7 @@
 #include <Array.h>
 #include <cstdlib>
 #include <JSON.h>
+#include <Logging.h>
 #include <Trie.h>
 #include <typeinfo>
 
@@ -193,7 +194,11 @@ public:
     JSONObjectValidationBuilder* addToValidator(
         JSONObjectValidationBuilder* builder) const override
     {
-        throw "Can not add polymorph json validator to an object "
+        Framework::Logging::error()
+            << "Can not add polymorph json validator to an object "
+               "validation builder";
+        throw "Can not add polymorph json "
+              "validator to an object "
               "validation builder";
     }
 
@@ -373,6 +378,9 @@ public:
                 typeFactoryRef->zFactory<T>());
         if (!polymorphFactory)
         {
+            Framework::Logging::error()
+                << Framework::Text("Type not registered as Polymorphic type: ")
+                       + typeId;
             throw Framework::Text("Type not registered as Polymorphic type: ")
                 + typeId;
         }
@@ -386,6 +394,8 @@ public:
             = parsableTypes.z(typeId, typeId.getLength());
         if (typeFactoryRef)
         {
+            Framework::Logging::error()
+                << Framework::Text("Type already registered: ") + typeId;
             throw Framework::Text("Type already registered: ") + typeId;
         }
         typeFactoryRef = new TypeFatoryRef(
@@ -414,6 +424,8 @@ public:
             = parsableTypes.z(typeId, typeId.getLength());
         if (!typeFactoryRef)
         {
+            Framework::Logging::error()
+                << Framework::Text("Type not registered: ") + typeId;
             throw Framework::Text("Type not registered: ") + typeId;
         }
         T* result = (T*)(typeFactoryRef->createValue(zJson->asObject()));
@@ -428,6 +440,8 @@ public:
             = parsableTypes.z(typeId, typeId.getLength());
         if (!typeFactoryRef)
         {
+            Framework::Logging::error()
+                << Framework::Text("Type not registered: ") + typeId;
             throw Framework::Text("Type not registered: ") + typeId;
         }
         Framework::JSON::JSONObject* result = new Framework::JSON::JSONObject();
@@ -443,6 +457,8 @@ public:
             = parsableTypes.z(typeId, typeId.getLength());
         if (!typeFactoryRef)
         {
+            Framework::Logging::error()
+                << Framework::Text("Type not registered: ") + typeId;
             throw Framework::Text("Type not registered: ") + typeId;
         }
         return typeFactoryRef->getValidator();
@@ -456,6 +472,8 @@ public:
             = parsableTypes.z(typeId, typeId.getLength());
         if (!typeFactoryRef)
         {
+            Framework::Logging::error()
+                << Framework::Text("Type not registered: ") + typeId;
             throw Framework::Text("Type not registered: ") + typeId;
         }
         return typeFactoryRef->addToValidator(builder);
@@ -473,7 +491,7 @@ public:
         for (Framework::JSON::Validator::JSONValidationResult* invalidPart :
             invalidParts)
         {
-            invalidPart->printInvalidInfo();
+            Framework::Logging::error() << invalidPart->getInvalidInfo();
         }
         return result;
     }

+ 16 - 14
FactoryCraft/WorldGenerator.cpp

@@ -2,6 +2,7 @@
 
 #include <Betriebssystem.h>
 #include <functional>
+#include <Logging.h>
 
 #include "Dimension.h"
 #include "Game.h"
@@ -18,8 +19,9 @@ WorldGenerator::WorldGenerator(int seed)
       seed(seed)
 {
     setName("World Generator");
-    std::cout << "loading world generator configs. Changes at the config files "
-                 "may lead to a sudden change in landscape.\n";
+    Framework::Logging::info()
+        << "loading world generator configs. Changes at the config files "
+           "may lead to a sudden change in landscape.";
     JSONValidator* configValidator
         = JSONValidator::buildForArray()
               ->removeInvalidEntries()
@@ -29,14 +31,14 @@ WorldGenerator::WorldGenerator(int seed)
     loadAllJsonsFromDirectory("data/generator",
         [this, configValidator, seed](
             Framework::JSON::JSONValue* zValue, Framework::Text path) {
-            std::cout << "loading dimension configs from '" << path << "'"
-                      << std::endl;
+            Framework::Logging::info()
+                << "loading dimension configs from '" << path << "'";
             Framework::RCArray<JSONValidationResult> invalidParts;
             JSONValue* valid
                 = configValidator->getValidParts(zValue, &invalidParts);
             for (JSONValidationResult* invalidPart : invalidParts)
             {
-                invalidPart->printInvalidInfo();
+                Framework::Logging::error() << invalidPart->getInvalidInfo();
             }
             if (valid)
             {
@@ -65,8 +67,8 @@ Dimension* WorldGenerator::createDimension(int dimensionId)
         if (generator->getDimensionId() == dimensionId)
             return generator->createDimension();
     }
-    std::cout << "ERROR: no dimension generator found for dimension "
-              << dimensionId << "\n";
+    Framework::Logging::error()
+        << "no dimension generator found for dimension " << dimensionId;
     return 0;
 }
 
@@ -116,13 +118,13 @@ void WorldGenerator::thread()
                     zm.messungStart();
                     generatedChunk->initializeLightning();
                     zm.messungEnde();
-                    std::cout << "light calculation: " << zm.getSekunden()
-                              << "\n";
+                    Framework::Logging::trace()
+                        << "light calculation: " << zm.getSekunden();
                     zm.messungStart();
                     generatedChunk->removeUnusedBlocks();
                     zm.messungEnde();
-                    std::cout << "unused block removal: " << zm.getSekunden()
-                              << "\n";
+                    Framework::Logging::trace()
+                        << "unused block removal: " << zm.getSekunden();
                     zm.messungStart();
                     Dimension* dim
                         = Game::INSTANCE->zDimension(next.dimensionId);
@@ -133,13 +135,13 @@ void WorldGenerator::thread()
                     }
                     dim->setChunk(generatedChunk, Punkt(x, y));
                     zm.messungEnde();
-                    std::cout << "adding chunk to map: " << zm.getSekunden()
-                              << "\n";
+                    Framework::Logging::trace()
+                        << "adding chunk to map: " << zm.getSekunden();
                 }
             }
         }
     }
-    std::cout << "World Generator thread exited\n";
+    Framework::Logging::info() << "World Generator thread exited";
 }
 
 void WorldGenerator::requestGeneration(Area request)

+ 6 - 5
FactoryCraft/WorldLoader.cpp

@@ -1,6 +1,7 @@
 #include "WorldLoader.h"
 
 #include <Datei.h>
+#include <Logging.h>
 #include <Punkt.h>
 #include <Text.h>
 
@@ -30,8 +31,7 @@ WorldLoader::WorldLoader()
             if (entities.open(Framework::Datei::Style::lesen))
             {
                 Dimension* dim
-                    = Game::INSTANCE->zGenerator()->createDimension(
-                        (int)*name);
+                    = Game::INSTANCE->zGenerator()->createDimension((int)*name);
                 if (dim)
                 {
                     while (!entities.istEnde())
@@ -46,8 +46,9 @@ WorldLoader::WorldLoader()
                 }
                 else
                 {
-                    std::cout << "ERROR: could not create dimension " << *name
-                              << ". No Factory was provided.\n";
+                    Framework::Logging::error()
+                        << "could not create dimension " << *name
+                        << ". No Factory was provided.";
                 }
             }
         }
@@ -123,7 +124,7 @@ void WorldLoader::thread()
             }
         }
     }
-    std::cout << "World Loader thread exited\n";
+    Framework::Logging::info() << "World Loader thread exited";
 }
 
 void WorldLoader::requestLoading(Area request)

+ 8 - 6
NoiseTest/NoiseTest.cpp

@@ -7,13 +7,13 @@
 #include <RenderThread.h>
 #include <string.h>
 
+#include "FactorizeNoise.h"
 #include "FastNoiseLite.h"
 #include "FastNoiseWrapper.h"
+#include "MultiplyNoise.h"
+#include "NoiseCombiner.h"
 #include "RandNoise.h"
 #include "ShapedNoise.h"
-#include "NoiseCombiner.h"
-#include "FactorizeNoise.h"
-#include "MultiplyNoise.h"
 
 using namespace Framework;
 
@@ -46,7 +46,9 @@ void updateView()
 {
     Vec3<int> minP
         = position
-        - (Vec3<int>)Vec3<float>((float)img->getBreite() / 2.f, (float)img->getHeight() / 2.f, 0.f) / zoom;
+        - (Vec3<int>)Vec3<float>(
+              (float)img->getBreite() / 2.f, (float)img->getHeight() / 2.f, 0.f)
+              / zoom;
     Vec3<int> maxP
         = position
         + (Vec3<int>)Vec3<float>(
@@ -144,8 +146,8 @@ int main()
     FastNoiseWrapper* wrapper2 = new FastNoiseWrapper(n, 2);
     wrapper2->setMultiplier(0.4f);
     Noise* mountainRegion
-        = new RescaleNoise(new NegatedNoise(new RescaleNoise(wrapper2, 3.5)), 1.5);
-    noise = new FastNoiseLite(3);
+        = new RescaleNoise(new NegatedNoise(new
+   RescaleNoise(wrapper2, 3.5)), 1.5); noise = new FastNoiseLite(3);
     noise->SetNoiseType(FastNoiseLite::NoiseType::NoiseType_Perlin);
     noise->SetFrequency(0.25f);
     wrapper2 = new FastNoiseWrapper(noise, 0);

+ 6 - 2
Windows Version/Windows Version.vcxproj

@@ -115,7 +115,7 @@
       <SDLCheck>true</SDLCheck>
       <PreprocessorDefinitions>_DEBUG;_CONSOLE;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <ConformanceMode>true</ConformanceMode>
-      <LanguageStandard>stdcpp17</LanguageStandard>
+      <LanguageStandard>stdcpp20</LanguageStandard>
     </ClCompile>
     <Link>
       <SubSystem>Console</SubSystem>
@@ -139,7 +139,7 @@ copy ..\..\..\..\..\Allgemein\Framework\x64\debug\Framework.dll Framework.dll</C
       <SDLCheck>true</SDLCheck>
       <PreprocessorDefinitions>NDEBUG;_CONSOLE;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <ConformanceMode>true</ConformanceMode>
-      <LanguageStandard>stdcpp17</LanguageStandard>
+      <LanguageStandard>stdcpp20</LanguageStandard>
     </ClCompile>
     <Link>
       <SubSystem>Console</SubSystem>
@@ -158,6 +158,8 @@ copy ..\..\..\..\..\Allgemein\Framework\x64\release\Framework.dll Framework.dll<
   </ItemDefinitionGroup>
   <ItemGroup>
     <ClCompile Include="..\FactoryCraft\AddEntityUpdate.cpp" />
+    <ClCompile Include="..\FactoryCraft\Animal.cpp" />
+    <ClCompile Include="..\FactoryCraft\AnimalAI.cpp" />
     <ClCompile Include="..\FactoryCraft\Area.cpp" />
     <ClCompile Include="..\FactoryCraft\ArrayUtils.cpp" />
     <ClCompile Include="..\FactoryCraft\BasicBlocks.cpp" />
@@ -255,6 +257,8 @@ copy ..\..\..\..\..\Allgemein\Framework\x64\release\Framework.dll Framework.dll<
     <ClCompile Include="..\FactoryCraft\WormCaveGenerator.cpp" />
   </ItemGroup>
   <ItemGroup>
+    <ClInclude Include="..\FactoryCraft\Animal.h" />
+    <ClInclude Include="..\FactoryCraft\AnimalAI.h" />
     <ClInclude Include="..\FactoryCraft\ArrayUtils.h" />
     <ClInclude Include="..\FactoryCraft\BlockFilter.h" />
     <ClInclude Include="..\FactoryCraft\BlockInfoCommand.h" />

+ 21 - 6
Windows Version/Windows Version.vcxproj.filters

@@ -103,6 +103,9 @@
     <Filter Include="server\utils">
       <UniqueIdentifier>{05682bc5-0ac5-4ac3-bc89-bc7fb952f350}</UniqueIdentifier>
     </Filter>
+    <Filter Include="entities\animals">
+      <UniqueIdentifier>{1c04d738-2f59-40e4-9660-14aaf6bf68aa}</UniqueIdentifier>
+    </Filter>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="..\FactoryCraft\Server.cpp">
@@ -171,9 +174,6 @@
     <ClCompile Include="..\FactoryCraft\Area.cpp">
       <Filter>world</Filter>
     </ClCompile>
-    <ClCompile Include="..\FactoryCraft\Entity.cpp">
-      <Filter>entities</Filter>
-    </ClCompile>
     <ClCompile Include="..\FactoryCraft\EntityType.cpp">
       <Filter>entities</Filter>
     </ClCompile>
@@ -393,6 +393,15 @@
     <ClCompile Include="..\FactoryCraft\JsonUtils.cpp">
       <Filter>server\config</Filter>
     </ClCompile>
+    <ClCompile Include="..\FactoryCraft\Entity.cpp">
+      <Filter>entities</Filter>
+    </ClCompile>
+    <ClCompile Include="..\FactoryCraft\AnimalAI.cpp">
+      <Filter>entities\animals</Filter>
+    </ClCompile>
+    <ClCompile Include="..\FactoryCraft\Animal.cpp">
+      <Filter>entities\animals</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="..\FactoryCraft\Chunk.h">
@@ -437,9 +446,6 @@
     <ClInclude Include="..\FactoryCraft\ItemSkill.h">
       <Filter>inventory</Filter>
     </ClInclude>
-    <ClInclude Include="..\FactoryCraft\Entity.h">
-      <Filter>entities</Filter>
-    </ClInclude>
     <ClInclude Include="..\FactoryCraft\BasicBlocks.h">
       <Filter>world\blocks</Filter>
     </ClInclude>
@@ -695,5 +701,14 @@
     <ClInclude Include="..\FactoryCraft\JsonUtils.h">
       <Filter>server\config</Filter>
     </ClInclude>
+    <ClInclude Include="..\FactoryCraft\Entity.h">
+      <Filter>entities</Filter>
+    </ClInclude>
+    <ClInclude Include="..\FactoryCraft\Animal.h">
+      <Filter>entities\animals</Filter>
+    </ClInclude>
+    <ClInclude Include="..\FactoryCraft\AnimalAI.h">
+      <Filter>entities\animals</Filter>
+    </ClInclude>
   </ItemGroup>
 </Project>