First, Happy new year to all!
Well, this is hard to explain in a couple of words, basically I made a system that allows the players change their house tiles, the problem it's when the server restarts, the tiles obviously back to normal, then i guess if there is a way to make the house also saves the floor in the database.
So, i'll post some things that I found that could be usefull to slove this problem...
All the sources are at the end!
In IOMapSerialize.cpp
Sources:
src.rar
Edit----
I did it myself with lua
Thanks whitevo for the idea
This in startup.lua
Well, this is hard to explain in a couple of words, basically I made a system that allows the players change their house tiles, the problem it's when the server restarts, the tiles obviously back to normal, then i guess if there is a way to make the house also saves the floor in the database.
So, i'll post some things that I found that could be usefull to slove this problem...
All the sources are at the end!
In IOMapSerialize.cpp
The most important first and yes, it saves non-movable items
Code:
void IOMapSerialize::saveTile(PropWriteStream& stream, const Tile* tile)
{
const TileItemVector* tileItems = tile->getItemList();
if (!tileItems) {
return;
}
std::forward_list<Item*> items;
uint16_t count = 0;
for (Item* item : *tileItems) {
const ItemType& it = Item::items[item->getID()];
//Note that these are NEGATED, ie. these are the items that will be saved.
if (!(!item->isMoveable() || it.moveable || item->getDoor() || (item->getContainer() && !item->getContainer()->empty()) || it.canWriteText || item->getBed()) {
continue;
}
items.push_front(item);
++count;
}
if (!items.empty()) {
const Position& tilePosition = tile->getPosition();
stream.write<uint16_t>(tilePosition.x);
stream.write<uint16_t>(tilePosition.y);
stream.write<uint8_t>(tilePosition.z);
stream.write<uint32_t>(count);
for (const Item* item : items) {
saveItem(stream, item);
}
}
}
Code:
void IOMapSerialize::loadHouseItems(Map* map)
{
int64_t start = OTSYS_TIME();
DBResult_ptr result = Database::getInstance()->storeQuery("SELECT `data` FROM `tile_store`");
if (!result) {
return;
}
do {
unsigned long attrSize;
const char* attr = result->getStream("data", attrSize);
PropStream propStream;
propStream.init(attr, attrSize);
uint16_t x, y;
uint8_t z;
if (!propStream.read<uint16_t>(x) || !propStream.read<uint16_t>(y) || !propStream.read<uint8_t>(z)) {
continue;
}
Tile* tile = map->getTile(x, y, z);
if (!tile) {
continue;
}
uint32_t item_count;
if (!propStream.read<uint32_t>(item_count)) {
continue;
}
while (item_count--) {
loadItem(propStream, tile);
}
} while (result->next());
std::cout << "> Loaded house items in: " << (OTSYS_TIME() - start) / (1000.) << " s" << std::endl;
}
Code:
bool IOMapSerialize::saveHouseItems()
{
int64_t start = OTSYS_TIME();
Database* db = Database::getInstance();
std::ostringstream query;
//Start the transaction
DBTransaction transaction;
if (!transaction.begin()) {
return false;
}
//clear old tile data
if (!db->executeQuery("DELETE FROM `tile_store`")) {
return false;
}
DBInsert stmt("INSERT INTO `tile_store` (`house_id`, `data`) VALUES ");
PropWriteStream stream;
for (const auto& it : g_game.map.houses.getHouses()) {
//save house items
House* house = it.second;
for (HouseTile* tile : house->getTiles()) {
saveTile(stream, tile);
size_t attributesSize;
const char* attributes = stream.getStream(attributesSize);
if (attributesSize > 0) {
query << house->getId() << ',' << db->escapeBlob(attributes, attributesSize);
if (!stmt.addRow(query)) {
return false;
}
stream.clear();
}
}
}
if (!stmt.execute()) {
return false;
}
//End the transaction
bool success = transaction.commit();
std::cout << "> Saved house items in: " <<
(OTSYS_TIME() - start) / (1000.) << " s" << std::endl;
return success;
}
Sources:
src.rar
Edit----
I did it myself with lua
Thanks whitevo for the idea
Code:
function onSay(player, words, param)
local minimo ={x=100,y=100}
local maximo ={x=200,y=200}
db.query("TRUNCATE TABLE `tile_ground_store`")
for i=minimo.x,maximo.x do
for j=minimo.y,maximo.y do
local piso = Tile({x=i,y=j,z=7})
if piso then
local ground = piso:getGround()
local groundid = ground.itemid
if groundid == 405 then
db.asyncQuery("INSERT INTO `tile_ground_store` (`groundid`, `posx`, `posy`, `posz`) VALUES (" .. groundid .. "," .. i .. "," .. j .. ",7);")
end
end
end
end
end
This in startup.lua
Code:
--Load wooden floor
local resultfloor = db.storeQuery("SELECT * FROM `tile_ground_store`")
repeat
local posx = result.getDataInt(resultfloor , "posx")
local posy = result.getDataInt(resultfloor , "posy")
doCreateItem(405, 1, {x=posx,y=posy,z=7})
until not result.next(resultfloor)
Last edited: