block asset loading
 
-       block type loader can determine which textures are needed in the array
-       it should compose a map while loading, assigning an ID to each
-       individual texture and after all types are loaded, load the appropriate
-       textures into the array
-
-       also, parameterization of chunk generator should be less static/dangerous
+       parameterization of chunk generator should be less static/dangerous
 
 networking
 
 
 class BlockTypeRegistry;
 class Sound;
 class Texture;
+class TextureIndex;
 
 class Assets {
 
 public:
        explicit Assets(const std::string &base);
 
-       void LoadBlockTypes(const std::string &set_name, BlockTypeRegistry &) const;
+       void LoadBlockTypes(const std::string &set_name, BlockTypeRegistry &, TextureIndex &) const;
        Font LoadFont(const std::string &name, int size) const;
        Sound LoadSound(const std::string &name) const;
        Texture LoadTexture(const std::string &name) const;
        void LoadTexture(const std::string &name, ArrayTexture &, int layer) const;
+       void LoadTextures(const TextureIndex &, ArrayTexture &) const;
 
 private:
        std::string fonts;
 
--- /dev/null
+#ifndef BLANK_APP_TEXTUREINDEX_HPP_
+#define BLANK_APP_TEXTUREINDEX_HPP_
+
+#include <map>
+#include <string>
+
+
+namespace blank {
+
+class TextureIndex {
+
+       using MapType = std::map<std::string, int>;
+
+public:
+       TextureIndex();
+
+       int GetID(const std::string &);
+
+       std::size_t Size() const noexcept { return id_map.size(); }
+       const MapType &Entries() const noexcept { return id_map; }
+
+private:
+       MapType id_map;
+
+};
+
+};
+
+#endif
 
 #include "FrameCounter.hpp"
 #include "State.hpp"
 #include "StateControl.hpp"
+#include "TextureIndex.hpp"
 
 #include "init.hpp"
 #include "../audio/Sound.hpp"
 
 }
 
-void Assets::LoadBlockTypes(const std::string &set_name, BlockTypeRegistry ®) const {
+void Assets::LoadBlockTypes(const std::string &set_name, BlockTypeRegistry ®, TextureIndex &tex_index) const {
        string full = data + set_name + ".types";
        std::ifstream file(full);
        if (!file) {
                        if (name == "visible") {
                                type.visible = in.GetBool();
                        } else if (name == "texture") {
-                               // TODO: load textures as requested
                                in.ReadString(tex_name);
-                               if (tex_name == "rock-1") {
-                                       type.texture = 1;
-                               } else if (tex_name == "rock-2") {
-                                       type.texture = 2;
-                               } else if (tex_name == "rock-3") {
-                                       type.texture = 3;
-                               } else if (tex_name == "debug") {
-                                       type.texture = 0;
-                               } else {
-                                       throw runtime_error("unknown texture: " + tex_name);
-                               }
+                               type.texture = tex_index.GetID(tex_name);
                        } else if (name == "color") {
                                in.ReadVec(type.color);
                        } else if (name == "label") {
        SDL_FreeSurface(srf);
 }
 
+void Assets::LoadTextures(const TextureIndex &index, ArrayTexture &tex) const {
+       // TODO: where the hell should that size come from?
+       tex.Reserve(16, 16, index.Size(), Format());
+       for (const auto &entry : index.Entries()) {
+               LoadTexture(entry.first, tex, entry.second);
+       }
+}
+
+
+TextureIndex::TextureIndex()
+: id_map() {
+
+}
+
+int TextureIndex::GetID(const string &name) {
+       auto entry = id_map.find(name);
+       if (entry == id_map.end()) {
+               auto result = id_map.emplace(name, Size());
+               return result.first->second;
+       } else {
+               return entry->second;
+       }
+}
+
 
 void FrameCounter::EnterFrame() noexcept {
        last_enter = SDL_GetTicks();
 
 
 #include "WorldCollision.hpp"
 #include "../app/Assets.hpp"
+#include "../app/TextureIndex.hpp"
 #include "../graphics/Format.hpp"
 #include "../graphics/Viewport.hpp"
 
 , entities()
 , light_direction(config.light_direction)
 , fog_density(config.fog_density) {
+       TextureIndex tex_index;
+       assets.LoadBlockTypes("default", block_type, tex_index);
+
        block_tex.Bind();
-       block_tex.Reserve(16, 16, 4, Format());
-       assets.LoadTexture("debug", block_tex, 0);
-       assets.LoadTexture("rock-1", block_tex, 1);
-       assets.LoadTexture("rock-2", block_tex, 2);
-       assets.LoadTexture("rock-3", block_tex, 3);
+       assets.LoadTextures(tex_index, block_tex);
        block_tex.FilterNearest();
 
-       assets.LoadBlockTypes("default", block_type);
-
        generate.Space(0);
        generate.Light(13);
        generate.Solids({ 1, 4, 7, 10 });