tibia-rme/source/kmap_writer.cpp

324 lines
7.1 KiB
C++
Raw Permalink Normal View History

//////////////////////////////////////////////////////////////////////
// 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<http://www.gnu.org/licenses/>.
//////////////////////////////////////////////////////////////////////
#include "main.h"
#include "kmap_writer.hpp"
#include "map.h"
void KmapWriter::build(Map & map)
{
2022-08-19 15:10:50 -03:00
builder.Finish(Kmap::CreateMap(builder, buildHeader(map), buildMapData(map)));
save(map.getPath() + ".kmap");
}
void KmapWriter::save(std::string mapPath)
{
std::ofstream ofs(mapPath, std::ofstream::binary);
ofs.write((char*) getBuffer(), getSize());
ofs.close();
wxMessageBox(mapPath);
}
uint8_t *KmapWriter::getBuffer()
{
return builder.GetBufferPointer();
}
flatbuffers::uoffset_t KmapWriter::getSize()
{
return builder.GetSize();
}
2022-08-19 15:10:50 -03:00
FBOffset<Kmap::MapHeader> KmapWriter::buildHeader(Map & map)
{
return Kmap::CreateMapHeader(
builder,
map.getWidth(),
map.getHeight(),
map.getVersion().otbm,
2022-08-19 15:10:50 -03:00
buildString(getFullFileName(map.getSpawnFilename())),
buildString(getFullFileName(map.getSpawnNpcFilename())),
buildString(getFullFileName(map.getHouseFilename())),
buildString("Saved with Remere's Map Editor " + __RME_VERSION__ + "\n" + map.getMapDescription())
);
}
2022-08-19 15:10:50 -03:00
FBOffset<Kmap::MapData> KmapWriter::buildMapData(Map & map)
{
2022-08-19 15:10:50 -03:00
return Kmap::CreateMapData(builder, buildAreas(map), buildTowns(map), buildWaypoints(map));
}
2022-08-19 15:10:50 -03:00
FBVectorOffset<FBOffset<Kmap::Area>> KmapWriter::buildAreas(Map &map)
{
2022-08-19 15:10:50 -03:00
StdOffsetVector<Kmap::Area> areasOffset;
StdOffsetVector<Kmap::Tile> tilesOffset;
2022-08-19 15:10:50 -03:00
Position* areaPos = nullptr;
MapIterator mapIterator = map.begin();
while (mapIterator != map.end())
{
Tile *tile = (*mapIterator)->get();
if (tile == nullptr || tile->size() == 0)
{
++mapIterator;
continue;
}
2022-08-22 14:33:31 -03:00
Position pos = tile->getPosition();
if (isNewArea(pos, areaPos))
{
2022-08-19 15:13:28 -03:00
if (auto areaOffset = buildArea(pos, areaPos, tilesOffset);
!areaOffset.IsNull())
{
areasOffset.push_back(areaOffset);
}
areaPos->x = pos.x;
areaPos->y = pos.y;
areaPos->z = pos.z;
tilesOffset.clear();
}
2022-08-22 14:33:31 -03:00
if (areaPos == nullptr) {
areaPos = &pos;
}
2022-08-19 15:10:50 -03:00
auto offset = buildTile(*tile);
if (!offset.IsNull())
{
tilesOffset.push_back(offset);
}
++mapIterator;
}
return builder.CreateVector(areasOffset);
}
2022-08-19 15:10:50 -03:00
FBOffset<Kmap::Area> KmapWriter::buildArea(const Position pos, Position *areaPos, StdOffsetVector<Kmap::Tile> tilesOffset)
{
2022-08-19 15:13:28 -03:00
if (tilesOffset.empty())
{
return 0;
}
2022-08-19 15:10:50 -03:00
StdOffsetVector<Kmap::Tile> finalizedOffset;
tilesOffset.swap(finalizedOffset);
2022-08-19 15:10:50 -03:00
auto areaOffset = Kmap::CreateArea(
builder,
2022-08-19 15:10:50 -03:00
builder.CreateVector(finalizedOffset),
Kmap::CreatePosition(builder, areaPos->x &0xFF00, areaPos->y &0xFF00, areaPos->z)
);
2022-08-19 15:10:50 -03:00
return areaOffset;
}
bool KmapWriter::isNewArea(const Position &pos, Position *areaPos)
{
2022-08-19 15:13:28 -03:00
if (areaPos == nullptr)
{
return false;
}
return pos.x < areaPos->x ||
2022-08-19 15:13:28 -03:00
pos.x >= areaPos->x + 256 ||
pos.y < areaPos->y ||
pos.y >= areaPos->y + 256 ||
pos.z != areaPos->z;
}
2022-08-19 15:10:50 -03:00
FBOffset<Kmap::Tile> KmapWriter::buildTile(Tile &tile)
{
2022-08-19 15:10:50 -03:00
Item *ground = tile.ground;
bool hasGround = false;
if (ground && !ground->isMetaItem())
{
hasGround = true;
2022-08-19 15:10:50 -03:00
for(Item* item : tile.items)
{
if (!ground->hasBorderEquivalent())
{
break;
}
if (item->getGroundEquivalent() == ground->getID())
{
hasGround = false;
break;
}
}
}
return Kmap::CreateTile(
builder,
2022-08-19 15:10:50 -03:00
buildItems(tile.items),
hasGround ? buildItem(*ground) : 0,
tile.getX() &0xFF,
tile.getY() &0xFF,
tile.getMapFlags(),
tile.getHouseID()
);
}
2022-08-19 15:10:50 -03:00
FBVectorOffset<FBOffset<Kmap::Item>> KmapWriter::buildItems(std::vector<Item*> &items)
{
2022-08-19 15:13:28 -03:00
if (items.empty())
2022-08-19 15:10:50 -03:00
{
return 0;
}
StdOffsetVector<Kmap::Item> itemsOffset;
for (Item *item: items)
{
2022-08-19 15:10:50 -03:00
if (item == nullptr)
{
continue;
}
2022-08-19 15:13:28 -03:00
if (auto itemOffset = buildItem(*item);
2022-08-19 15:10:50 -03:00
!itemOffset.IsNull())
{
itemsOffset.push_back(itemOffset);
}
}
2022-08-19 15:13:28 -03:00
if (itemsOffset.empty())
{
return 0;
}
return builder.CreateVector(itemsOffset);
}
2022-08-19 15:13:28 -03:00
FBOffset<Kmap::Item> KmapWriter::buildItem(Item &item)
{
2022-08-19 15:10:50 -03:00
if (item.isMetaItem())
{
return 0;
}
2022-08-19 15:13:28 -03:00
FBOffset<Kmap::ItemAttributes> itemAttributesOffset = 0;
if (!item.getText().empty() || !item.getDescription().empty() || item.getSubtype() > 0)
{
itemAttributesOffset = CreateItemAttributes(
builder,
item.getSubtype(),
buildString(item.getText()),
buildString(item.getDescription()),
buildActionAttributes(item)
);
}
2022-08-19 15:10:50 -03:00
return Kmap::CreateItem(
builder,
2022-08-19 15:10:50 -03:00
item.getID(),
buildItemsDetails(item),
itemAttributesOffset
);
}
2022-08-19 15:10:50 -03:00
FBOffset<Kmap::Action> KmapWriter::buildActionAttributes(Item &item)
{
2022-08-19 15:10:50 -03:00
if (item.getActionID() == 0 && item.getUniqueID() == 0)
{
2022-08-19 15:10:50 -03:00
return 0;
}
2022-08-19 15:10:50 -03:00
return Kmap::CreateAction(builder, item.getActionID(), item.getUniqueID());
}
2022-08-19 15:10:50 -03:00
FBOffset<Kmap::ItemDetails> KmapWriter::buildItemsDetails(Item &item)
{
Container *container = dynamic_cast<Container*>(&item);
Depot *depot = dynamic_cast<Depot*>(&item);
Door *door = dynamic_cast<Door*>(&item);
Teleport *teleport = dynamic_cast<Teleport*>(&item);
2022-08-19 15:13:28 -03:00
if (container == nullptr && depot == nullptr && door == nullptr && teleport == nullptr)
{
return 0;
}
2022-08-19 15:10:50 -03:00
return Kmap::CreateItemDetails(
builder,
container ? buildItems(container->getVector()) : 0,
depot ? depot->getDepotID() : 0,
door ? door->getDoorID() : 0,
teleport ? buildPosition(teleport->getDestination()) : 0
);
2022-08-19 15:10:50 -03:00
}
2022-08-19 15:10:50 -03:00
FBVectorOffset<FBOffset<Kmap::Town>> KmapWriter::buildTowns(Map & map)
{
StdOffsetVector<Kmap::Town> townsOffset;
2022-08-19 15:10:50 -03:00
for (const auto &[townId, town]: map.towns)
{
townsOffset.push_back(
Kmap::CreateTown(
builder,
townId,
buildString(town->getName()),
buildPosition(town->getTemplePosition())
)
);
}
return builder.CreateVector(townsOffset);
}
2022-08-19 15:10:50 -03:00
FBVectorOffset<FBOffset<Kmap::Waypoint>> KmapWriter::buildWaypoints(Map & map)
{
2022-08-19 15:10:50 -03:00
StdOffsetVector<Kmap::Waypoint> waypointsOffSet;
for (const auto &[waypointId, waypoint]: map.waypoints)
{
2022-08-19 15:10:50 -03:00
waypointsOffSet.push_back(
Kmap::CreateWaypoint(
builder,
buildString(waypoint->name),
buildPosition(waypoint->pos)
)
);
}
return builder.CreateVector(waypointsOffSet);
}
2022-08-19 15:10:50 -03:00
FBOffset<flatbuffers::String> KmapWriter::buildString(std::string string)
{
return string.empty() ? builder.CreateString(string) : 0;
}
FBOffset<Kmap::Position> KmapWriter::buildPosition(const Position &pos)
{
return Kmap::CreatePosition(builder, pos.x, pos.y, pos.z);
}
std::string KmapWriter::getFullFileName(std::string fileName)
{
FileName tmpName;
tmpName.Assign(wxstr(fileName));
return nstr(tmpName.GetFullName());
}