Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add function for loading/unloading OTBM files per offset #436

Merged
merged 7 commits into from
Jan 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/game/game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -322,9 +322,9 @@ bool Game::loadCustomMap(const std::string& filename)
return map.loadMapCustom(g_configManager().getString(DATA_DIRECTORY) + "/world/custom/" + filename + ".otbm", true, true, true);
}

void Game::loadMap(const std::string& path)
void Game::loadMap(const std::string& path, const Position& pos, bool unload)
{
map.loadMap(path);
map.loadMap(path, false, false, false, false, pos, unload);
}

Cylinder* Game::internalGetCylinder(Player* player, const Position& pos) const
Expand Down
2 changes: 1 addition & 1 deletion src/game/game.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ class Game
* \returns true if the custom map was loaded successfully
*/
bool loadCustomMap(const std::string& filename);
void loadMap(const std::string& path);
void loadMap(const std::string& path, const Position& pos = Position(), bool unload = false);

void getMapDimensions(uint32_t& width, uint32_t& height) const {
width = map.width;
Expand Down
94 changes: 62 additions & 32 deletions src/io/iomap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

#include "io/iomap.h"
#include "game/movement/teleport.h"
#include "game/game.h"

/*
OTBM_ROOTV1
Expand Down Expand Up @@ -55,7 +56,7 @@ Tile* IOMap::createTile(Item*& ground, Item* item, uint16_t x, uint16_t y, uint8
return tile;
}

bool IOMap::loadMap(Map* map, const std::string& fileName)
bool IOMap::loadMap(Map* map, const std::string& fileName, const Position& pos, bool unload)
{
int64_t start = OTSYS_TIME();
OTB::Loader loader{fileName, OTB::Identifier{{'O', 'T', 'B', 'M'}}};
Expand Down Expand Up @@ -108,7 +109,7 @@ bool IOMap::loadMap(Map* map, const std::string& fileName)

for (auto& mapDataNode : mapNode.children) {
if (mapDataNode.type == OTBM_TILE_AREA) {
if (!parseTileArea(loader, mapDataNode, *map)) {
if (!parseTileArea(loader, mapDataNode, *map, pos, unload)) {
return false;
}
} else if (mapDataNode.type == OTBM_TOWNS) {
Expand Down Expand Up @@ -188,7 +189,7 @@ bool IOMap::parseMapDataAttributes(OTB::Loader& loader, const OTB::Node& mapNode
return true;
}

bool IOMap::parseTileArea(OTB::Loader& loader, const OTB::Node& tileAreaNode, Map& map)
bool IOMap::parseTileArea(OTB::Loader& loader, const OTB::Node& tileAreaNode, Map& map, const Position& pos, bool unload)
{
PropStream propStream;
if (!loader.getProps(tileAreaNode, propStream)) {
Expand All @@ -204,7 +205,7 @@ bool IOMap::parseTileArea(OTB::Loader& loader, const OTB::Node& tileAreaNode, Ma

uint16_t base_x = area_coord.x;
uint16_t base_y = area_coord.y;
uint16_t z = area_coord.z;
uint16_t base_z = area_coord.z;

static std::map<uint64_t, uint64_t> teleportMap;

Expand All @@ -225,8 +226,31 @@ bool IOMap::parseTileArea(OTB::Loader& loader, const OTB::Node& tileAreaNode, Ma
return false;
}

uint16_t x = base_x + tile_coord.x;
uint16_t y = base_y + tile_coord.y;
uint16_t x = base_x + tile_coord.x + pos.x;
uint16_t y = base_y + tile_coord.y + pos.y;
uint8_t z = static_cast<uint8_t>(base_z + pos.z);

if (unload) {
Tile* tile = map.getTile(Position(x, y, z));

if (const TileItemVector* items = tile->getItemList();
items) {
TileItemVector item_list = *items;
if (!item_list.size() == 0) {
for (Item* item : item_list) {
if (item) {
g_game().internalRemoveItem(item);
}
}
}
}

if (Item* ground = tile->getGround();
ground) {
g_game().internalRemoveItem(ground);
}
continue;
}

bool isHouseTile = false;
House* house = nullptr;
Expand All @@ -243,42 +267,48 @@ bool IOMap::parseTileArea(OTB::Loader& loader, const OTB::Node& tileAreaNode, Ma
return false;
}

house = map.houses.addHouse(houseId);
if (!house) {
std::ostringstream ss;
ss << "[x:" << x << ", y:" << y << ", z:" << z << "] Could not create house id: " << houseId;
setLastErrorString(ss.str());
return false;
}
if (!unload) {
house = map.houses.addHouse(houseId);
if (!house) {
std::ostringstream ss;
ss << "[x:" << x << ", y:" << y << ", z:" << z << "] Could not create house id: " << houseId;
setLastErrorString(ss.str());
return false;
}

tile = new HouseTile(x, y, z, house);
house->addTile(static_cast<HouseTile*>(tile));
isHouseTile = true;
tile = new HouseTile(x, y, z, house);
house->addTile(static_cast<HouseTile*>(tile));
isHouseTile = true;
}
}

uint8_t attribute;
//read tile attributes
while (propStream.read<uint8_t>(attribute)) {
switch (attribute) {
case OTBM_ATTR_TILE_FLAGS: {
uint32_t flags;
if (!propStream.read<uint32_t>(flags)) {
std::ostringstream ss;
ss << "[x:" << x << ", y:" << y << ", z:" << z << "] Failed to read tile flags.";
setLastErrorString(ss.str());
return false;
}
if (!unload) {
uint32_t flags;
if (!propStream.read<uint32_t>(flags)) {
std::ostringstream ss;
ss << "[x:" << x << ", y:" << y << ", z:" << z << "] Failed to read tile flags.";
setLastErrorString(ss.str());
return false;
}

if ((flags & OTBM_TILEFLAG_PROTECTIONZONE) != 0) {
tileflags |= TILESTATE_PROTECTIONZONE;
} else if ((flags & OTBM_TILEFLAG_NOPVPZONE) != 0) {
tileflags |= TILESTATE_NOPVPZONE;
} else if ((flags & OTBM_TILEFLAG_PVPZONE) != 0) {
tileflags |= TILESTATE_PVPZONE;
}
if ((flags & OTBM_TILEFLAG_PROTECTIONZONE) != 0) {
tileflags |= TILESTATE_PROTECTIONZONE;
}
else if ((flags & OTBM_TILEFLAG_NOPVPZONE) != 0) {
tileflags |= TILESTATE_NOPVPZONE;
}
else if ((flags & OTBM_TILEFLAG_PVPZONE) != 0) {
tileflags |= TILESTATE_PVPZONE;
}

if ((flags & OTBM_TILEFLAG_NOLOGOUT) != 0) {
tileflags |= TILESTATE_NOLOGOUT;
if ((flags & OTBM_TILEFLAG_NOLOGOUT) != 0) {
tileflags |= TILESTATE_NOLOGOUT;
}
}
break;
}
Expand Down
4 changes: 2 additions & 2 deletions src/io/iomap.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ class IOMap
static Tile* createTile(Item*& ground, Item* item, uint16_t x, uint16_t y, uint8_t z);

public:
bool loadMap(Map* map, const std::string& identifier);
bool loadMap(Map* map, const std::string& identifier, const Position& pos = Position(), bool unload = false);

/**
* Load main map monsters
Expand Down Expand Up @@ -157,7 +157,7 @@ class IOMap
bool parseMapDataAttributes(OTB::Loader& loader, const OTB::Node& mapNode, Map& map, const std::string& fileName);
bool parseWaypoints(OTB::Loader& loader, const OTB::Node& waypointsNode, Map& map);
bool parseTowns(OTB::Loader& loader, const OTB::Node& townsNode, Map& map);
bool parseTileArea(OTB::Loader& loader, const OTB::Node& tileAreaNode, Map& map);
bool parseTileArea(OTB::Loader& loader, const OTB::Node& tileAreaNode, Map& map, const Position& pos, bool unload);
std::string errorString;
};

Expand Down
9 changes: 9 additions & 0 deletions src/lua/functions/core/game/game_functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,15 @@ int GameFunctions::luaGameLoadMap(lua_State* L) {
return 0;
}

int GameFunctions::luaGameloadMapChunk(lua_State* L) {
// Game.loadMapChunk(path, position, remove)
const std::string& path = getString(L, 1);
const Position& position = getPosition(L, 2);
bool unload = getBoolean(L, 3);
g_dispatcher().addTask(createTask([path, position, unload]() {g_game().loadMap(path, position, unload); }));
return 0;
}

int GameFunctions::luaGameGetMonsterCount(lua_State* L) {
// Game.getMonsterCount()
lua_pushnumber(L, g_game().getMonstersOnline());
Expand Down
2 changes: 2 additions & 0 deletions src/lua/functions/core/game/game_functions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class GameFunctions final : LuaScriptInterface {

registerMethod(L, "Game", "getPlayers", GameFunctions::luaGameGetPlayers);
registerMethod(L, "Game", "loadMap", GameFunctions::luaGameLoadMap);
registerMethod(L, "Game", "loadMapChunk", GameFunctions::luaGameloadMapChunk);

registerMethod(L, "Game", "getMonsterCount", GameFunctions::luaGameGetMonsterCount);
registerMethod(L, "Game", "getPlayerCount", GameFunctions::luaGameGetPlayerCount);
Expand Down Expand Up @@ -85,6 +86,7 @@ class GameFunctions final : LuaScriptInterface {

static int luaGameGetPlayers(lua_State* L);
static int luaGameLoadMap(lua_State* L);
static int luaGameloadMapChunk(lua_State* L);

static int luaGameGetMonsterCount(lua_State* L);
static int luaGameGetPlayerCount(lua_State* L);
Expand Down
9 changes: 5 additions & 4 deletions src/map/map.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@
#include "game/game.h"
#include "creatures/monsters/monster.h"

bool Map::load(const std::string& identifier) {
bool Map::load(const std::string& identifier, const Position& pos, bool unload) {
try {
IOMap loader;
if (!loader.loadMap(this, identifier)) {
if (!loader.loadMap(this, identifier, pos, unload)) {
SPDLOG_ERROR("[Map::load] - {}", loader.getLastErrorString());
return false;
}
Expand All @@ -33,7 +33,8 @@ bool Map::load(const std::string& identifier) {

bool Map::loadMap(const std::string& identifier,
bool mainMap /*= false*/,bool loadHouses /*= false*/,
bool loadMonsters /*= false*/, bool loadNpcs /*= false*/)
bool loadMonsters /*= false*/, bool loadNpcs /*= false*/,
const Position& pos /*= Position()*/, bool unload /*= false*/)
{
// Only download map if is loading the main map and it is not already downloaded
if (mainMap && g_configManager().getBoolean(TOGGLE_DOWNLOAD_MAP) && !std::filesystem::exists(identifier)) {
Expand All @@ -56,7 +57,7 @@ bool Map::loadMap(const std::string& identifier,
}

// Load the map
this->load(identifier);
this->load(identifier, pos, unload);

// Only create items from lua functions if is loading main map
// It needs to be after the load map to ensure the map already exists before creating the items
Expand Down
4 changes: 2 additions & 2 deletions src/map/map.h
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ class Map
* Load a map.
* \returns true if the map was loaded successfully
*/
bool load(const std::string& identifier);
bool load(const std::string& identifier, const Position& pos = Position(), bool unload = false);
/**
* Load the main map
* \param identifier Is the main map name (name of file .otbm)
Expand All @@ -184,7 +184,7 @@ class Map
* \param loadNpcs if true, the main map npcs is loaded
* \returns true if the main map was loaded successfully
*/
bool loadMap(const std::string& identifier, bool mainMap = false, bool loadHouses = false, bool loadMonsters = false, bool loadNpcs = false);
bool loadMap(const std::string& identifier, bool mainMap = false, bool loadHouses = false, bool loadMonsters = false, bool loadNpcs = false, const Position& pos = Position(), bool unload = false);
/**
* Load the custom map
* \param identifier Is the map custom folder
Expand Down