2022-08-19 01:42:50 -03:00
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
|
// 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)));
|
2022-08-19 01:42:50 -03:00
|
|
|
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)
|
2022-08-19 01:42:50 -03:00
|
|
|
{
|
|
|
|
|
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 01:42:50 -03:00
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2022-08-19 15:10:50 -03:00
|
|
|
FBOffset<Kmap::MapData> KmapWriter::buildMapData(Map & map)
|
2022-08-19 01:42:50 -03:00
|
|
|
{
|
2022-08-19 15:10:50 -03:00
|
|
|
return Kmap::CreateMapData(builder, buildAreas(map), buildTowns(map), buildWaypoints(map));
|
2022-08-19 01:42:50 -03:00
|
|
|
}
|
|
|
|
|
|
2022-08-19 15:10:50 -03:00
|
|
|
FBVectorOffset<FBOffset<Kmap::Area>> KmapWriter::buildAreas(Map &map)
|
2022-08-19 01:42:50 -03:00
|
|
|
{
|
2022-08-19 15:10:50 -03:00
|
|
|
StdOffsetVector<Kmap::Area> areasOffset;
|
|
|
|
|
StdOffsetVector<Kmap::Tile> tilesOffset;
|
2022-08-19 01:42:50 -03:00
|
|
|
|
2022-08-19 15:10:50 -03:00
|
|
|
Position* areaPos = nullptr;
|
2022-08-19 01:42:50 -03:00
|
|
|
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();
|
2022-08-19 01:42:50 -03:00
|
|
|
|
|
|
|
|
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;
|
2022-08-19 01:42:50 -03:00
|
|
|
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);
|
2022-08-19 01:42:50 -03:00
|
|
|
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 01:42:50 -03:00
|
|
|
{
|
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 01:42:50 -03:00
|
|
|
|
2022-08-19 15:10:50 -03:00
|
|
|
auto areaOffset = Kmap::CreateArea(
|
2022-08-19 01:42:50 -03:00
|
|
|
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 01:42:50 -03:00
|
|
|
);
|
2022-08-19 15:10:50 -03:00
|
|
|
|
|
|
|
|
return areaOffset;
|
2022-08-19 01:42:50 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool KmapWriter::isNewArea(const Position &pos, Position *areaPos)
|
|
|
|
|
{
|
2022-08-19 15:13:28 -03:00
|
|
|
if (areaPos == nullptr)
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2022-08-19 01:42:50 -03:00
|
|
|
|
|
|
|
|
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 01:42:50 -03:00
|
|
|
}
|
|
|
|
|
|
2022-08-19 15:10:50 -03:00
|
|
|
FBOffset<Kmap::Tile> KmapWriter::buildTile(Tile &tile)
|
2022-08-19 01:42:50 -03:00
|
|
|
{
|
2022-08-19 15:10:50 -03:00
|
|
|
Item *ground = tile.ground;
|
|
|
|
|
bool hasGround = false;
|
|
|
|
|
if (ground && !ground->isMetaItem())
|
|
|
|
|
{
|
|
|
|
|
hasGround = true;
|
2022-08-19 01:42:50 -03:00
|
|
|
|
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(
|
2022-08-19 01:42:50 -03:00
|
|
|
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 01:42:50 -03:00
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2022-08-19 15:10:50 -03:00
|
|
|
FBVectorOffset<FBOffset<Kmap::Item>> KmapWriter::buildItems(std::vector<Item*> &items)
|
2022-08-19 01:42:50 -03:00
|
|
|
{
|
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 01:42:50 -03:00
|
|
|
{
|
2022-08-19 15:10:50 -03:00
|
|
|
if (item == nullptr)
|
2022-08-19 01:42:50 -03:00
|
|
|
{
|
|
|
|
|
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 01:42:50 -03:00
|
|
|
}
|
|
|
|
|
|
2022-08-19 15:13:28 -03:00
|
|
|
if (itemsOffset.empty())
|
|
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2022-08-19 01:42:50 -03:00
|
|
|
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())
|
2022-08-19 01:42:50 -03:00
|
|
|
{
|
|
|
|
|
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 01:42:50 -03:00
|
|
|
|
2022-08-19 15:10:50 -03:00
|
|
|
return Kmap::CreateItem(
|
2022-08-19 01:42:50 -03:00
|
|
|
builder,
|
2022-08-19 15:10:50 -03:00
|
|
|
item.getID(),
|
|
|
|
|
buildItemsDetails(item),
|
|
|
|
|
itemAttributesOffset
|
2022-08-19 01:42:50 -03:00
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2022-08-19 15:10:50 -03:00
|
|
|
FBOffset<Kmap::Action> KmapWriter::buildActionAttributes(Item &item)
|
2022-08-19 01:42:50 -03:00
|
|
|
{
|
2022-08-19 15:10:50 -03:00
|
|
|
if (item.getActionID() == 0 && item.getUniqueID() == 0)
|
2022-08-19 01:42:50 -03:00
|
|
|
{
|
2022-08-19 15:10:50 -03:00
|
|
|
return 0;
|
|
|
|
|
}
|
2022-08-19 01:42:50 -03:00
|
|
|
|
2022-08-19 15:10:50 -03:00
|
|
|
return Kmap::CreateAction(builder, item.getActionID(), item.getUniqueID());
|
|
|
|
|
}
|
2022-08-19 01:42:50 -03:00
|
|
|
|
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 01:42:50 -03:00
|
|
|
|
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 01:42:50 -03:00
|
|
|
);
|
2022-08-19 15:10:50 -03:00
|
|
|
}
|
2022-08-19 01:42: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 01:42:50 -03:00
|
|
|
|
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())
|
|
|
|
|
)
|
|
|
|
|
);
|
2022-08-19 01:42:50 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return builder.CreateVector(townsOffset);
|
|
|
|
|
}
|
|
|
|
|
|
2022-08-19 15:10:50 -03:00
|
|
|
FBVectorOffset<FBOffset<Kmap::Waypoint>> KmapWriter::buildWaypoints(Map & map)
|
2022-08-19 01:42:50 -03:00
|
|
|
{
|
2022-08-19 15:10:50 -03:00
|
|
|
StdOffsetVector<Kmap::Waypoint> waypointsOffSet;
|
|
|
|
|
|
2022-08-19 01:42:50 -03:00
|
|
|
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)
|
|
|
|
|
)
|
|
|
|
|
);
|
2022-08-19 01:42:50 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
2022-08-19 01:42:50 -03:00
|
|
|
std::string KmapWriter::getFullFileName(std::string fileName)
|
|
|
|
|
{
|
|
|
|
|
FileName tmpName;
|
|
|
|
|
tmpName.Assign(wxstr(fileName));
|
|
|
|
|
return nstr(tmpName.GetFullName());
|
|
|
|
|
}
|