• There is NO official Otland's Discord server and NO official Otland's server list. The Otland's Staff does not manage any Discord server or server list. Moderators or administrator of any Discord server or server lists have NO connection to the Otland's Staff. Do not get scammed!

Lua Function doSaveHouse(houseId)

Powers

New Member
Joined
May 10, 2010
Messages
19
Reaction score
0
reworked the script for my needs may be useful to someone :) test on 0.3.4 tfs

(only useHouseDataStorage = "no" / false ;work only save house to MySQL )

luascript.h:
Code:
static int32_t luaDoSaveHouse(lua_State* L);


luascript.cpp:
Code:
	//doSaveHouse({list})
	lua_register(m_luaState, "doSaveHouse", LuaScriptInterface::luaDoSaveHouse);


Code:
int32_t LuaScriptInterface::luaDoSaveHouse(lua_State* L)
{
	//doSaveHouse(houseID)
	
	if(g_config.getBool(ConfigManager::HOUSE_STORAGE))
    {
        std::stringstream s;
		s << "config: useHouseDataStorage must be = no/false";
		reportErrorFunc(s.str());
		lua_pushboolean(L, false);                                              
    }
	
	House* house = Houses::getInstance().getHouse(popNumber(L));
	if(!house)
	{
        reportErrorFunc(getErrorDesc(LUA_ERROR_HOUSE_NOT_FOUND));
		lua_pushboolean(L, false);
		return 1;
	}

	Database* db = Database::getInstance();
	DBTransaction trans(db);
	
	if(!trans.begin())
    	{
    		lua_pushboolean(L, false);
    		return 1;
    	}

    if(!IOMapSerialize::getInstance()->saveHouse(db, house))
		{
			std::stringstream s;
			s << "Unable to save house information, ID: " << house->getHouseId();
			reportErrorFunc(s.str());
		}

	if(!IOMapSerialize::getInstance()->saveHouseItems(db, house))
		{
			std::stringstream s;
			s << "Unable to save house items, ID: " << house->getHouseId();
			reportErrorFunc(s.str());
		}

	lua_pushboolean(L, trans.commit());
	return 1;
}


iomapserialize.cpp:
Code:
[B]UNDER:
bool IOMapSerialize::saveHouse(Database* db, House* house)[/B]

bool IOMapSerialize::saveHouseItems(Database* db, House* house)
{
	if(g_config.getBool(ConfigManager::HOUSE_STORAGE))
			return false;
			
	DBTransaction trans(db);
	if(!trans.begin())
		return false;

	DBQuery query;
	query << "DELETE FROM `tile_items` WHERE `tile_id` IN (SELECT `id` FROM `tiles` WHERE `house_id` = "
		<< house->getHouseId() << " AND `world_id` = " << g_config.getNumber(ConfigManager::WORLD_ID)
		<< ") AND `world_id` = " << g_config.getNumber(ConfigManager::WORLD_ID);
	if(!db->executeQuery(query.str()))
		return false;

	query.str("");
	query << "DELETE FROM `tiles` WHERE `house_id` = " << house->getHouseId()
		<< " AND `world_id` = " << g_config.getNumber(ConfigManager::WORLD_ID);
	if(!db->executeQuery(query.str()))
		return false;

	query.str("");
	query << "SELECT `id` FROM `tiles` WHERE `world_id` = " << g_config.getNumber(ConfigManager::WORLD_ID) << " ORDER BY `id` DESC LIMIT 1;";

	DBResult* result;
	if(!(result = db->storeQuery(query.str())))
		uint32_t tileId = 0;

	uint32_t tileId = result->getDataInt("id")+1;
	result->free();
	
 return saveHouseRelational(db, house, tileId);
}



bool IOMapSerialize::saveHouseRelational(Database* db, House* house, uint32_t& tileId)
{
		for(HouseTileList::iterator tit = house->getHouseTileBegin(); tit != house->getHouseTileEnd(); ++tit)
			saveItems(db, tileId, house->getHouseId(), (*tit));

	return true;
}

iomapserialize.h :
Code:
[B]UNDER: 
bool saveMapRelational(Map* map);[/B]

bool saveHouseRelational(Database* db, House* house, uint32_t& tileId);


example use: (in talkaction)

Lua:
function onSay(cid, words, param, channel)


	if exhaustion.check(cid, 25958) then
		doPlayerSendCancel(cid, 'You are Exhausted (save house)')
		return true
	end

	
	local playerHouseId = getHouseByPlayerGUID(getPlayerGUID(cid))
	
	if playerHouseId ~= nil then
	
		if doSaveHouse(playerHouseId) then
			doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_BLUE, 'House '.. getHouseName(playerHouseId) ..' saved succesfull!')
			exhaustion.set(cid, 25958, 300)
		else
			doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_RED, 'House '.. getHouseName(playerHouseId) ..' saved failed!')
		end
	
	else
		doPlayerSendCancel(cid, 'You do not rent any flat.')
	
	end
	

	return true
end


//command can be used for example if a player arrange the items in the house, and if the crash is what you saved.
 
Last edited:
Hmm, partially coped my code from 0.4. But I wonder how the heck you got 0.4 code without being a donator? :)

yes code from 0.4 + small fixes for errors appearing in INSERT to db. i have 2 account ?
 
idk, just asking. Yeh, there was a small bug as I didn't check out where the tileId is being changed. So basically thank you for kind of pointing a bug.
 
Doesn't work at 0.4 (btw, i had premium)



iomapserialize.cpp:257: error: no 'bool IOMapSerialize::saveHouseItems(Database*, House*)' member function declared in class 'IOMapSerialize'
make[1]: *** [iomapserialize.o] Error 1
make[1]: Leaving directory `/home/ots2/silnik'
make: *** [all] Error 2
root@vm157:/home/ots2/silnik# make
make all-am
make[1]: Entering directory `/home/ots2/silnik'
make[1]: Warning: File `iomapserialize.h' has modification time 19 s in the future


I know i refreshed the topic, but this is very important for me.
 
I get this error on 0.2

SfgS-o.png
 
Here is a full code I've found, It will include dosavehouse and another fixes.


In /trunk/game.h after
[cpp]
bool isRunning() const {return services && services->isRunning();}
int32_t getLightHour() const {return lightHour;}
void startDecay(Item* item);
[/cpp]

add
[cpp]
#ifdef __GROUND_CACHE__

std::map<Item*, int32_t> grounds;
#endif

[/cpp]

In /trunk/protocolgame.h replace
[cpp]
void sendVIP(uint32_t guid, const std::string& name, bool isOnline);
[/cpp]

with
[cpp]
void sendVIP(uint32_t guid, const std::string& name, bool online);
[/cpp]

In /trunk/luascript.h after
[cpp]
static int32_t luaDoSaveServer(lua_State* L);
[/cpp]

add
[cpp]
static int32_t luaDoSaveHouse(lua_State* L);
[/cpp]

In /trunk/iomapserialize.cpp replace
[cpp]
if(result->getDataInt("clear"))
[/cpp]

with
[cpp]
if(result->getDataInt("clear") == 1)
[/cpp]

After
[cpp]
return false;
}
[/cpp]

Add
[cpp]
const Door* door;
[/cpp]

Replace
[cpp]
const Door* door = (*it);
if(!door)
[/cpp]

With
[cpp]
if(!(door = *it) || doorIds.find(door->getDoorId()) != doorIds.end()
|| listText.empty() || !door->getAccessList(listText))
[/cpp]

Replace
[cpp]
if(door->getAccessList(listText) && !listText.empty() && doorIds.find(door->getDoorId()) == doorIds.end())
{
query.str("");
doorIds.insert(door->getDoorId());
query << house->getId() << ", " << g_config.getNumber(ConfigManager::WORLD_ID) << ", "
<< door->getDoorId() << ", " << db->escapeString(listText);
if(!queryInsert.addRow(query.str()))
return false;
}
[/cpp]

With
[cpp]
query.str("");
doorIds.insert(door->getDoorId());
query << house->getId() << ", " << g_config.getNumber(ConfigManager::WORLD_ID) << ", "
<< door->getDoorId() << ", " << db->escapeString(listText);
if(!queryInsert.addRow(query.str()))
return false;
[/cpp]

Before function bool IOMapSerialize::loadMapRelational(Map* map) add
[cpp]
bool IOMapSerialize::saveHouseItems(Database* db, House* house)
{
std::string config = asLowerCaseString(g_config.getString(ConfigManager::HOUSE_STORAGE));
if(config == "binary-tilebased")
{
DBQuery query;
query << "DELETE FROM `tile_store` WHERE `house_id` = " << house->getId()
<< " AND `world_id` = " << g_config.getNumber(ConfigManager::WORLD_ID);
if(!db->query(query.str()))
return false;

DBInsert stmt(db);
stmt.setQuery("INSERT INTO `tile_store` (`house_id`, `world_id`, `data`) VALUES ");
return saveHouseBinaryTileBased(db, stmt, house) && stmt.execute();
}
else if(config == "binary")
{
DBQuery query;
query << "DELETE FROM `house_data` WHERE `house_id` = "<< house->getId()
<< " AND `world_id` = " << g_config.getNumber(ConfigManager::WORLD_ID);
if(!db->query(query.str()))
return false;

DBInsert stmt(db);
stmt.setQuery("INSERT INTO `house_data` (`house_id`, `world_id`, `data`) VALUES ");
return saveHouseBinary(db, stmt, house) && stmt.execute();
}

DBQuery query;
query << "DELETE FROM `tile_items` WHERE `tile_id` IN (SELECT `id` FROM `tiles` WHERE `house_id` = "
<< house->getId() << " AND `world_id` = " << g_config.getNumber(ConfigManager::WORLD_ID)
<< ") AND `world_id` = " << g_config.getNumber(ConfigManager::WORLD_ID);
if(!db->query(query.str()))
return false;

query.str("");
query << "DELETE FROM `tiles` WHERE `house_id` = " << house->getId()
<< " AND `world_id` = " << g_config.getNumber(ConfigManager::WORLD_ID);
if(!db->query(query.str()))
return false;

query.str("");
query << "SELECT `id` FROM `tiles` WHERE `world_id` = " << g_config.getNumber(ConfigManager::WORLD_ID) << " ORDER BY `id` DESC LIMIT 1;";

DBResult* result;
if(!(result = db->storeQuery(query.str())))
return false;

uint32_t tileId = result->getDataInt("id");
result->free();
return saveHouseRelational(db, house, tileId);
}
[/cpp]

Replace
[cpp]
loadItems(db, itemsResult, depot, true);
[/cpp]

With
[cpp]
loadItems(itemsResult, depot, true);
[/cpp]

Replace
[cpp]
loadItems(db, itemsResult, tile, false);
[/cpp]

With
[cpp]
loadItems(itemsResult, tile, false);
[/cpp]

Replace
[cpp]
loadItems(db, itemsResult, depot, true);
[/cpp]

With
[cpp]
loadItems(itemsResult, depot, true);
[/cpp]

Replace
[cpp]
loadItems(db, itemsResult, (*it), false);
[/cpp]

With
[cpp]
loadItems(itemsResult, (*it), false);
[/cpp]

Replace
[cpp]
{
//save house items
for(HouseTileList::iterator tit = it->second->getHouseTileBegin(); tit != it->second->getHouseTileEnd(); ++tit)
saveItems(db, tileId, it->second->getId(), (*tit));
}
[/cpp]

With
[cpp]
saveHouseRelational(db, it->second, tileId);
[/cpp]

Replace
[cpp]
{
//save house items
PropWriteStream stream;
for(HouseTileList::iterator tit = it->second->getHouseTileBegin(); tit != it->second->getHouseTileEnd(); ++tit)
{
if(!saveTile(stream, *tit))
return false;
}
[/cpp]

With
[cpp]
saveHouseBinary(db, stmt, it->second);
[/cpp]

Remove it
[cpp]
uint32_t attributesSize = 0;
const char* attributes = stream.getStream(attributesSize);
query.str("");

query << it->second->getId() << ", " << g_config.getNumber(ConfigManager::WORLD_ID)
<< ", " << db->escapeBlob(attributes, attributesSize);
if(!stmt.addRow(query))
return false;
}
[/cpp]

Replace
[cpp]
{
//save house items
House* house = it->second;
for(HouseTileList::iterator tit = house->getHouseTileBegin(); tit != house->getHouseTileEnd(); ++tit)
{
PropWriteStream stream;
saveTile(stream, *tit);
[/cpp]

With
[cpp]
saveHouseBinaryTileBased(db, stmt, it->second);
[/cpp]

Remove
[cpp]
uint32_t attributesSize = 0;
const char* attributes = stream.getStream(attributesSize);

query.str("");
if(attributesSize > 0)
{
query << it->second->getId() << ", " << g_config.getNumber(ConfigManager::WORLD_ID)
<< ", " << db->escapeBlob(attributes, attributesSize);

if(!stmt.addRow(query))
return false;
}
}
}
[/cpp]

Replace
[cpp]
bool IOMapSerialize::loadItems(Database*, DBResult* result, Cylinder* parent, bool depotTransfer/* = false*/)
[/cpp]

With
[cpp]
bool IOMapSerialize::saveHouseRelational(Database* db, House* house, uint32_t& tileId)
[/cpp]

and after { add
[cpp]
for(HouseTileList::iterator tit = house->getHouseTileBegin(); tit != house->getHouseTileEnd(); ++tit)
saveItems(db, tileId, house->getId(), (*tit));

return true;
}

bool IOMapSerialize::saveHouseBinary(Database* db, DBInsert& stmt, House* house)
{
PropWriteStream stream;
for(HouseTileList::iterator tit = house->getHouseTileBegin(); tit != house->getHouseTileEnd(); ++tit)
{
if(!saveTile(stream, *tit))
continue;
}

uint32_t attributesSize = 0;
const char* attributes = stream.getStream(attributesSize);
if(!attributesSize)
return true;

DBQuery query;
query << house->getId() << ", " << g_config.getNumber(ConfigManager::WORLD_ID)
<< ", " << db->escapeBlob(attributes, attributesSize);
return stmt.addRow(query);
}

bool IOMapSerialize::saveHouseBinaryTileBased(Database* db, DBInsert& stmt, House* house)
{
for(HouseTileList::iterator tit = house->getHouseTileBegin(); tit != house->getHouseTileEnd(); ++tit)
{
PropWriteStream stream;
if(!saveTile(stream, *tit))
continue;

uint32_t attributesSize = 0;
const char* attributes = stream.getStream(attributesSize);
if(!attributesSize)
continue;

DBQuery query;
query << house->getId() << ", " << g_config.getNumber(ConfigManager::WORLD_ID)
<< ", " << db->escapeBlob(attributes, attributesSize);
if(!stmt.addRow(query))
return false;
}

return true;
}

bool IOMapSerialize::loadItems(DBResult* result, Cylinder* parent, bool depotTransfer/* = false*/)
{
[/cpp]

In /trunk/luascript.cpp after
[cpp]
//doSaveServer([flags = 13])
lua_register(m_luaState, "doSaveServer", LuaInterface::luaDoSaveServer);
[/cpp]

add
[cpp]
//doSaveHouse({list})
lua_register(m_luaState, "doSaveHouse", LuaInterface::luaDoSaveHouse);
[/cpp]

After
[cpp]
return 1;
}
[/cpp]

add
[cpp]
int32_t LuaInterface::luaDoSaveHouse(lua_State* L)
{
//doSaveHouse({list})
IntegerVec list;
if(lua_istable(L, -1))
{
lua_pushnil(L);
while(lua_next(L, -2))
list.push_back(popNumber(L));

lua_pop(L, 2);
}
else
list.push_back(popNumber(L));

House* house;
std::vector<House*> houses;
for(IntegerVec::const_iterator it = list.begin(); it != list.end(); ++it)
{
if(!(house = Houses::getInstance()->getHouse(*it)))
{
std::stringstream s;
s << "House not found, ID: " << house->getId();
errorEx(s.str());

lua_pushboolean(L, false);
return 1;
}

houses.push_back(house);
}

Database* db = Database::getInstance();
DBTransaction trans(db);
if(!trans.begin())
{
lua_pushboolean(L, false);
return 1;
}

std::string config = asLowerCaseString(g_config.getString(ConfigManager::HOUSE_STORAGE));
if(config != "binary-tilebased" && config != "binary")
{
for(std::vector<House*>::iterator it = houses.begin(); it != houses.end(); ++it)
{
if(IOMapSerialize::getInstance()->saveHouse(db, *it))
continue;

std::stringstream s;
s << "Unable to save house information, ID: " << (*it)->getId();
errorEx(s.str());

lua_pushboolean(L, false);
return 1;
}

if(!trans.commit())
{
lua_pushboolean(L, false);
return 1;
}

for(std::vector<House*>::iterator it = houses.begin(); it != houses.end(); ++it)
{
if(IOMapSerialize::getInstance()->saveHouseItems(db, *it))
continue;

std::stringstream s;
s << "Unable to save house items, ID: " << (*it)->getId();
errorEx(s.str());

lua_pushboolean(L, false);
return 1;
}

lua_pushboolean(L, true);
return 1;
}

for(std::vector<House*>::iterator it = houses.begin(); it != houses.end(); ++it)
{
if(!IOMapSerialize::getInstance()->saveHouse(db, *it))
{
std::stringstream s;
s << "Unable to save house information, ID: " << (*it)->getId();
errorEx(s.str());
}

if(!IOMapSerialize::getInstance()->saveHouseItems(db, *it))
{
std::stringstream s;
s << "Unable to save house items, ID: " << (*it)->getId();
errorEx(s.str());
}
}

lua_pushboolean(L, trans.commit());
return 1;
}
[/cpp]

In /trunk/iomapserialize.h after
[cpp]
bool saveHouse(Database* db, House* house);
[/cpp]

add
[cpp]
bool saveHouseItems(Database* db, House* house);
[/cpp]

after
[cpp]
bool saveMapRelational(Map* map);
[/cpp]

add
[cpp]
bool saveHouseRelational(Database* db, House* house, uint32_t& tileId);
[/cpp]

after
[cpp]
bool saveMapBinary(Map* map);
[/cpp]

add
[cpp]
bool saveHouseBinary(Database* db, DBInsert& stmt, House* house);
[/cpp]

after
[cpp]
bool saveMapBinaryTileBased(Map* map);
[/cpp]

add
[cpp]
bool saveHouseBinaryTileBased(Database* db, DBInsert& stmt, House* house);
[/cpp]

replace
[cpp]
bool loadItems(Database* db, DBResult* result, Cylinder* parent, bool depotTransfer);
[/cpp]

with
[cpp]
bool loadItems(DBResult* result, Cylinder* parent, bool depotTransfer);
[/cpp]

before
[cpp]
bool loadContainer(PropStream& propStream, Container* container);
[/cpp]

add
[cpp]
bool loadItem(PropStream& propStream, Cylinder* parent, bool depotTransfer);
[/cpp]

and remove
[cpp]
bool loadItem(PropStream& propStream, Cylinder* parent, bool depotTransfer);
[/cpp]

In /trunk/player.cpp after
[cpp]
bool Player::addVIP(uint32_t _guid, std::string& name, bool isOnline, bool internal/* = false*/)
[/cpp]

add
[cpp]
bool Player::addVIP(uint32_t _guid, const std::string& name, bool online, bool loading/* = false*/)
[/cpp]

replace
[cpp]
if(!internal)
[/cpp]

with
[cpp]
if(!loading)
[/cpp]

Replace
[cpp]
if(VIPList.size() > (size_t)(group ? group->getMaxVips(isPremium()) : g_config.getNumber(ConfigManager::VIPLIST_DEFAULT_LIMIT)))
[/cpp]

with
[cpp]
if(!loading && VIPList.size() > (size_t)(group ? group->getMaxVips(isPremium()) : g_config.getNumber(ConfigManager::VIPLIST_DEFAULT_LIMIT)))
[/cpp]

Replace
[cpp]
if(!internal)
sendTextMessage(MSG_STATUS_SMALL, "You cannot add more buddies.");
[/cpp]

with
[cpp]
sendTextMessage(MSG_STATUS_SMALL, "You cannot add more buddies.");
[/cpp]

Replace
[cpp]
if(!internal)
[/cpp]

with
[cpp]
if(!loading)
[/cpp]

replace
[cpp]
if(client && !internal)
client->sendVIP(_guid, name, isOnline);
[/cpp]

with
[cpp]
if(!loading && client)
client->sendVIP(_guid, name, online);
[/cpp]

In /trunk/protocolgame.cpp replace
[cpp]
void ProtocolGame::sendVIP(uint32_t guid, const std::string& name, bool isOnline)
[/cpp]

with
[cpp]
void ProtocolGame::sendVIP(uint32_t guid, const std::string& name, bool online)
[/cpp]

replace
[cpp]
msg->put<char>(isOnline ? 1 : 0);
[/cpp]

with
[cpp]
msg->put<char>(online ? 1 : 0);
[/cpp]

In /trunk/iomap.cpp replace
[cpp]
g_grounds[it->second.first] = it->second.second;
[/cpp]

with
[cpp]
g_game.grounds[it->second.first] = it->second.second;
[/cpp]

In /trunk/player.h replace
[cpp]
bool addVIP(uint32_t guid, std::string& name, bool isOnline, bool internal = false);
[/cpp]

with
[cpp]
bool addVIP(uint32_t guid, const std::string& name, bool online, bool loading = false);
[/cpp]

In /trunk/iomanager.cpp remove
[cpp]
std::string dummy;
[/cpp]

replace
[cpp]
player->addVIP(vid, dummy, false, true);
[/cpp]

with
[cpp]
player->addVIP(vid, "", false, true);
[/cpp]

replace
[cpp]
<< "`pd`.`date` >= " << (time(NULL) - (7 * 86400));
[/cpp]

with
[cpp]
<< "`pd`.`date` >= " << (time(NULL) - (7 * 86400)); // TODO: configurable
[/cpp]
 
Sorry but this will not work on 0.2 :/ since many things are missing :/
 
Back
Top