////////////////////////////////////////////////////////////////////// // This file is part of Remere's Map Editor ////////////////////////////////////////////////////////////////////// // Remere's Map Editor is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Remere's Map Editor is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . ////////////////////////////////////////////////////////////////////// #include "main.h" #include "lua_api_map.h" #include "../map.h" #include "../basemap.h" #include "../tile.h" #include "../position.h" #include "../gui.h" #include "../editor.h" namespace LuaAPI { // Custom iterator for Map tiles to use in Lua for-loops class LuaMapTileIterator { public: explicit LuaMapTileIterator(Map* map) : map(map) { if (map) { iter = map->begin(); endIter = map->end(); } } std::tuple next(sol::this_state ts) { sol::state_view lua(ts); if (!map) { return std::make_tuple(sol::lua_nil, sol::lua_nil); } // Find next valid tile while (iter != endIter) { TileLocation* loc = *iter; ++iter; if (loc && loc->get()) { Tile* tile = loc->get(); return std::make_tuple( sol::make_object(lua, tile), sol::make_object(lua, tile) ); } } return std::make_tuple(sol::lua_nil, sol::lua_nil); } private: Map* map; MapIterator iter; MapIterator endIter; bool started = false; }; // Iterator for Spawns class LuaMapSpawnIterator { public: explicit LuaMapSpawnIterator(Map* map) : map(map) { if (map) { iter = map->spawnsMonster.begin(); endIter = map->spawnsMonster.end(); } } Tile* next() { if (!map) { return nullptr; } if (iter != endIter) { Position pos = *iter; ++iter; return map->getTile(pos); } return nullptr; } private: Map* map; SpawnNpcPositionList::const_iterator iter; SpawnNpcPositionList::const_iterator endIter; }; void registerMap(sol::state &lua) { // Register the iterator type lua.new_usertype("MapTileIterator", sol::no_constructor, "next", &LuaMapTileIterator::next); // Register Spawn iterator lua.new_usertype("MapSpawnIterator", sol::no_constructor, "next", &LuaMapSpawnIterator::next); // Register Map usertype lua.new_usertype( "Map", // No public constructor - maps are obtained from app.map sol::no_constructor, // Properties (read-only) "name", sol::property(&Map::getName), "filename", sol::property(&Map::getFilename), "description", sol::property(&Map::getMapDescription), "width", sol::property(&Map::getWidth), "height", sol::property(&Map::getHeight), "houseFilename", sol::property(&Map::getHouseFilename), "spawnFilename", sol::property(&Map::getSpawnFilename), "hasFile", sol::property(&Map::hasFile), "hasChanged", sol::property(&Map::hasChanged), "tileCount", sol::property([](Map* map) -> uint64_t { return map ? map->getTileCount() : 0; }), // Get tile methods "getTile", sol::overload([](Map* map, int x, int y, int z) -> Tile* { return map ? map->getTile(x, y, z) : nullptr; }, [](Map* map, const Position &pos) -> Tile* { return map ? map->getTile(pos) : nullptr; }), // Get or create tile (for adding content to empty positions) "getOrCreateTile", [](Map* map, sol::variadic_args va) -> Tile* { if (!map){ return nullptr; } Position pos; if (va.size() == 1 && va[0].is()) { pos = va[0].as(); } else if (va.size() == 3) { pos.x = va[0].as(); pos.y = va[1].as(); pos.z = va[2].as(); } else { throw sol::error("getOrCreateTile expects (x, y, z) or (Position)"); } TileLocation* loc = map->createTileL(pos); Tile* tile = loc->get(); if (!tile) { tile = map->allocator(loc); map->setTile(pos, tile); } return tile; }, // Tiles iterator - allows: for tile in map.tiles do ... end "tiles", sol::property([](Map* map, sol::this_state ts) { sol::state_view lua(ts); // Return an iterator function auto iterator = std::make_shared(map); // Return the iterator function that Lua will call repeatedly return sol::make_object(lua, [iterator](sol::this_state ts) { return iterator->next(ts); }); }), // Spawns iterator - allows: for tile in map.spawns do ... end "spawns", sol::property([](Map* map, sol::this_state ts) { sol::state_view lua(ts); auto iterator = std::make_shared(map); return sol::make_object(lua, [iterator]() -> Tile* { return iterator->next(); }); }), // String representation sol::meta_function::to_string, [](Map* map) { if (!map){ return std::string("Map(invalid)"); } return "Map(\"" + map->getName() + "\", " + std::to_string(map->getWidth()) + "x" + std::to_string(map->getHeight()) + ")"; } ); } } // namespace LuaAPI