Attr_ReadValue Teleport::readAttr(AttrTypes_t attr, PropStream& propStream) { if (ATTR_TELE_DEST == attr) { if (!propStream.GET_USHORT(destPos.x) || !propStream.GET_USHORT(destPos.y) || !propStream.GET_UCHAR(destPos.z)) { return ATTR_READ_ERROR; } return ATTR_READ_CONTINUE; } else { return Item::readAttr(attr, propStream); } }
bool IOMapSerialize::loadMap(Map* map) { int64_t start = OTSYS_TIME(); Database* db = Database::getInstance(); std::ostringstream query; DBResult* result = db->storeQuery("SELECT `id` FROM `houses`"); if (!result) { return true; } do { query.str(""); query << "SELECT `data` FROM `tile_store` WHERE `house_id` = " << result->getDataInt("id"); DBResult* tileResult = db->storeQuery(query.str()); if (!tileResult) { continue; } do { unsigned long attrSize = 0; const char* attr = tileResult->getDataStream("data", attrSize); PropStream propStream; propStream.init(attr, attrSize); uint16_t x = 0, y = 0; uint8_t z = 0; propStream.GET_USHORT(x); propStream.GET_USHORT(y); propStream.GET_UCHAR(z); if (x == 0 || y == 0) { continue; } Tile* tile = map->getTile(x, y, z); if (!tile) { continue; } uint32_t item_count = 0; propStream.GET_ULONG(item_count); while (item_count--) { loadItem(propStream, tile); } } while (tileResult->next()); db->freeResult(tileResult); } while (result->next()); db->freeResult(result); std::cout << "> Loaded house items in: " << (OTSYS_TIME() - start) / (1000.) << " s" << std::endl; return true; }
void IOMapSerialize::loadMap(Map* map) { int64_t start = OTSYS_TIME(); Database* db = Database::getInstance(); DBResult* result = db->storeQuery("SELECT `data` FROM `tile_store`"); if (!result) { return; } do { unsigned long attrSize; const char* attr = result->getDataStream("data", attrSize); PropStream propStream; propStream.init(attr, attrSize); uint16_t x, y; uint8_t z; if (!propStream.GET_USHORT(x) || !propStream.GET_USHORT(y) || !propStream.GET_UCHAR(z)) { continue; } Tile* tile = map->getTile(x, y, z); if (!tile) { continue; } uint32_t item_count; if (!propStream.GET_ULONG(item_count)) { continue; } while (item_count--) { loadItem(propStream, tile); } } while (result->next()); db->freeResult(result); std::cout << "> Loaded house items in: " << (OTSYS_TIME() - start) / (1000.) << " s" << std::endl; }
Attr_ReadValue Depot::readAttr(AttrTypes_t attr, PropStream& propStream) { if(attr != ATTR_DEPOT_ID) return Item::readAttr(attr, propStream); uint16_t depotId; if(!propStream.GET_USHORT(depotId)) return ATTR_READ_ERROR; setAttribute("depotid", depotId); return ATTR_READ_CONTINUE; }
Attr_ReadValue Depot::readAttr(AttrTypes_t attr, PropStream& propStream) { if(ATTR_DEPOT_ID == attr){ uint16_t _depotId; if(!propStream.GET_USHORT(_depotId)){ return ATTR_READ_ERROR; } setDepotId(_depotId); return ATTR_READ_CONTINUE; } else return Item::readAttr(attr, propStream); }
bool Depot::readAttr(AttrTypes_t attr, PropStream& propStream) { if(ATTR_DEPOT_ID == attr){ uint16_t _depotId; if(!propStream.GET_USHORT(_depotId)){ return false; } setDepotId(_depotId); return true; } else return Item::readAttr(attr, propStream); }
bool ItemAttributes::unserializeAttributeMap(PropStream& stream) { uint16_t n; if(stream.GET_USHORT(n)){ createAttributes(); std::string key; ItemAttribute attrib; while(n--){ if(!stream.GET_STRING(key)) return false; if(!attrib.unserialize(stream)) return false; (*attributes)[key] = attrib; } } return true; }
int32_t Items::loadFromOtb(const std::string& file) { FileLoader f; if (!f.openFile(file.c_str(), "OTBI")) { return f.getError(); } uint32_t type; NODE node = f.getChildNode(NO_NODE, type); PropStream props; if (f.getProps(node, props)) { //4 byte flags //attributes //0x01 = version data uint32_t flags; if (!props.GET_ULONG(flags)) { return ERROR_INVALID_FORMAT; } uint8_t attr; if (!props.GET_VALUE(attr)) { return ERROR_INVALID_FORMAT; } if (attr == ROOT_ATTR_VERSION) { uint16_t datalen; if (!props.GET_VALUE(datalen)) { return ERROR_INVALID_FORMAT; } if (datalen != sizeof(VERSIONINFO)) { return ERROR_INVALID_FORMAT; } VERSIONINFO* vi; if (!props.GET_STRUCT(vi)) { return ERROR_INVALID_FORMAT; } Items::dwMajorVersion = vi->dwMajorVersion; //items otb format file version Items::dwMinorVersion = vi->dwMinorVersion; //client version Items::dwBuildNumber = vi->dwBuildNumber; //revision } } if (Items::dwMajorVersion == 0xFFFFFFFF) { std::cout << "[Warning - Items::loadFromOtb] items.otb using generic client version." << std::endl; } else if (Items::dwMajorVersion != 3) { std::cout << "Old version detected, a newer version of items.otb is required." << std::endl; return ERROR_INVALID_FORMAT; } else if (Items::dwMinorVersion < CLIENT_VERSION_1035) { std::cout << "A newer version of items.otb is required." << std::endl; return ERROR_INVALID_FORMAT; } node = f.getChildNode(node, type); while (node != NO_NODE) { PropStream stream; if (!f.getProps(node, stream)) { return f.getError(); } uint32_t flags; if (!stream.GET_VALUE(flags)) { return ERROR_INVALID_FORMAT; } uint16_t serverId = 0; uint16_t clientId = 0; uint16_t speed = 0; uint16_t lightLevel = 0; uint16_t lightColor = 0; uint16_t wareId = 0; uint8_t alwaysOnTopOrder = 0; uint8_t attrib; while (stream.GET_VALUE(attrib)) { uint16_t datalen; if (!stream.GET_VALUE(datalen)) { return ERROR_INVALID_FORMAT; } switch (attrib) { case ITEM_ATTR_SERVERID: { if (datalen != sizeof(uint16_t)) { return ERROR_INVALID_FORMAT; } if (!stream.GET_USHORT(serverId)) { return ERROR_INVALID_FORMAT; } if (serverId > 30000 && serverId < 30100) { serverId -= 30000; } break; } case ITEM_ATTR_CLIENTID: { if (datalen != sizeof(uint16_t)) { return ERROR_INVALID_FORMAT; } if (!stream.GET_USHORT(clientId)) { return ERROR_INVALID_FORMAT; } break; } case ITEM_ATTR_SPEED: { if (datalen != sizeof(uint16_t)) { return ERROR_INVALID_FORMAT; } if (!stream.GET_USHORT(speed)) { return ERROR_INVALID_FORMAT; } break; } case ITEM_ATTR_LIGHT2: { if (datalen != sizeof(lightBlock2)) { return ERROR_INVALID_FORMAT; } lightBlock2* lb2; if (!stream.GET_STRUCT(lb2)) { return ERROR_INVALID_FORMAT; } lightLevel = lb2->lightLevel; lightColor = lb2->lightColor; break; } case ITEM_ATTR_TOPORDER: { if (datalen != sizeof(uint8_t)) { return ERROR_INVALID_FORMAT; } if (!stream.GET_UCHAR(alwaysOnTopOrder)) { return ERROR_INVALID_FORMAT; } break; } case ITEM_ATTR_WAREID: { if (datalen != sizeof(uint16_t)) { return ERROR_INVALID_FORMAT; } if (!stream.GET_USHORT(wareId)) { return ERROR_INVALID_FORMAT; } break; } default: { //skip unknown attributes if (!stream.SKIP_N(datalen)) { return ERROR_INVALID_FORMAT; } break; } } } if (reverseItemMap.find(clientId) == reverseItemMap.end()) { reverseItemMap[clientId] = serverId; } // store the found item if (serverId >= items.size()) { items.resize(serverId + 1); } ItemType& iType = items[serverId]; iType.group = (itemgroup_t)type; switch (type) { case ITEM_GROUP_CONTAINER: iType.type = ITEM_TYPE_CONTAINER; break; case ITEM_GROUP_DOOR: //not used iType.type = ITEM_TYPE_DOOR; break; case ITEM_GROUP_MAGICFIELD: //not used iType.type = ITEM_TYPE_MAGICFIELD; break; case ITEM_GROUP_TELEPORT: //not used iType.type = ITEM_TYPE_TELEPORT; break; case ITEM_GROUP_NONE: case ITEM_GROUP_GROUND: case ITEM_GROUP_SPLASH: case ITEM_GROUP_FLUID: case ITEM_GROUP_CHARGES: case ITEM_GROUP_DEPRECATED: break; default: return ERROR_INVALID_FORMAT; } iType.blockSolid = hasBitSet(FLAG_BLOCK_SOLID, flags); iType.blockProjectile = hasBitSet(FLAG_BLOCK_PROJECTILE, flags); iType.blockPathFind = hasBitSet(FLAG_BLOCK_PATHFIND, flags); iType.hasHeight = hasBitSet(FLAG_HAS_HEIGHT, flags); iType.useable = hasBitSet(FLAG_USEABLE, flags); iType.pickupable = hasBitSet(FLAG_PICKUPABLE, flags); iType.moveable = hasBitSet(FLAG_MOVEABLE, flags); iType.stackable = hasBitSet(FLAG_STACKABLE, flags); iType.alwaysOnTop = hasBitSet(FLAG_ALWAYSONTOP, flags); iType.isVertical = hasBitSet(FLAG_VERTICAL, flags); iType.isHorizontal = hasBitSet(FLAG_HORIZONTAL, flags); iType.isHangable = hasBitSet(FLAG_HANGABLE, flags); iType.allowDistRead = hasBitSet(FLAG_ALLOWDISTREAD, flags); iType.rotable = hasBitSet(FLAG_ROTABLE, flags); iType.canReadText = hasBitSet(FLAG_READABLE, flags); iType.lookThrough = hasBitSet(FLAG_LOOKTHROUGH, flags); iType.isAnimation = hasBitSet(FLAG_ANIMATION, flags); // iType.walkStack = !hasBitSet(FLAG_FULLTILE, flags); iType.id = serverId; iType.clientId = clientId; iType.speed = speed; iType.lightLevel = lightLevel; iType.lightColor = lightColor; iType.wareId = wareId; iType.alwaysOnTopOrder = alwaysOnTopOrder; node = f.getNextNode(node, type); } items.shrink_to_fit(); return ERROR_NONE; }
bool IOMapSerialize::loadItem(PropStream& propStream, Cylinder* parent, bool depotTransfer/* = false*/) { Tile* tile = NULL; if(!parent->getItem()) tile = parent->getTile(); uint16_t id = 0; propStream.GET_USHORT(id); Item* item = NULL; const ItemType& iType = Item::items[id]; if(iType.moveable || iType.forceSerialize || (!depotTransfer && !tile)) { if(!(item = Item::CreateItem(id))) return true; if(!item->unserializeAttr(propStream)) { std::cout << "[Warning - IOMapSerialize::loadItem] Unserialization error [0] for item type " << id << std::endl; delete item; return false; } if(Container* container = item->getContainer()) { if(!loadContainer(propStream, container)) { delete item; return false; } } if(parent) { parent->__internalAddThing(item); item->__startDecaying(); } else delete item; return true; } if(tile) { //Stationary items Item* findItem = NULL; for(uint32_t i = 0; i < tile->getThingCount(); ++i) { if(!(findItem = tile->__getThing(i)->getItem())) continue; if(findItem->getID() == id) { item = findItem; break; } if(iType.isDoor() && findItem->getDoor()) { item = findItem; break; } if(iType.isBed() && findItem->getBed()) { item = findItem; break; } } } if(item) { if(item->unserializeAttr(propStream)) { Container* container = item->getContainer(); if(container && !loadContainer(propStream, container)) return false; item = g_game.transformItem(item, id); } else std::cout << "[Warning - IOMapSerialize::loadItem] Unserialization error [1] for item type " << id << std::endl; return true; } //The map changed since the last save, just read the attributes if(!(item = Item::CreateItem(id))) return true; item->unserializeAttr(propStream); if(Container* container = item->getContainer()) { if(!loadContainer(propStream, container)) { delete item; return false; } if(depotTransfer) { for(ItemList::const_iterator it = container->getItems(); it != container->getEnd(); ++it) parent->__addThing(NULL, (*it)); container->itemlist.clear(); } } delete item; return true; }
bool IOMapSerialize::loadMapBinary(Map* map) { Database* db = Database::getInstance(); DBResult* result; DBQuery query; query << "SELECT `house_id`, `data` FROM `house_data` WHERE `world_id` = " << g_config.getNumber(ConfigManager::WORLD_ID); if(!(result = db->storeQuery(query.str()))) return false; House* house = NULL; do { int32_t houseId = result->getDataInt("house_id"); house = Houses::getInstance()->getHouse(houseId); uint64_t attrSize = 0; const char* attr = result->getDataStream("data", attrSize); PropStream propStream; propStream.init(attr, attrSize); while(propStream.size()) { uint16_t x = 0, y = 0; uint8_t z = 0; propStream.GET_USHORT(x); propStream.GET_USHORT(y); propStream.GET_UCHAR(z); uint32_t itemCount = 0; propStream.GET_ULONG(itemCount); Position pos(x, y, (int16_t)z); if(house && house->hasPendingTransfer()) { if(Player* player = g_game.getPlayerByGuidEx(house->getOwner())) { Depot* depot = player->getDepot(player->getTown(), true); while(itemCount--) loadItem(propStream, depot, true); if(player->isVirtual()) { IOLoginData::getInstance()->savePlayer(player); delete player; } } } else if(Tile* tile = map->getTile(pos)) { while(itemCount--) loadItem(propStream, tile, false); } else { std::cout << "[Error - IOMapSerialize::loadMapBinary] Unserialization of invalid tile" << " at position " << pos << std::endl; break; } } } while(result->next()); result->free(); return true; }
bool IOMapSerialize::loadItem(PropStream& propStream, Cylinder* parent) { uint16_t id; if (!propStream.GET_USHORT(id)) { return false; } Tile* tile = nullptr; if (parent->getParent() == nullptr) { tile = parent->getTile(); } const ItemType& iType = Item::items[id]; if (iType.moveable || !tile) { //create a new item Item* item = Item::CreateItem(id); if (item) { if (item->unserializeAttr(propStream)) { Container* container = item->getContainer(); if (container && !loadContainer(propStream, container)) { delete item; return false; } parent->__internalAddThing(item); item->__startDecaying(); } else { std::cout << "WARNING: Unserialization error in IOMapSerialize::loadItem()" << id << std::endl; delete item; return false; } } } else { // Stationary items like doors/beds/blackboards/bookcases Item* item = nullptr; if (const TileItemVector* items = tile->getItemList()) { for (Item* findItem : *items) { if (findItem->getID() == id) { item = findItem; break; } else if (iType.isDoor() && findItem->getDoor()) { item = findItem; break; } else if (iType.isBed() && findItem->getBed()) { item = findItem; break; } } } if (item) { if (item->unserializeAttr(propStream)) { Container* container = item->getContainer(); if (container && !loadContainer(propStream, container)) { return false; } item = g_game.transformItem(item, id); } else { std::cout << "WARNING: Unserialization error in IOMapSerialize::loadItem()" << id << std::endl; } } else { //The map changed since the last save, just read the attributes Item* dummy = Item::CreateItem(id); if (dummy) { dummy->unserializeAttr(propStream); Container* container = dummy->getContainer(); if (container && !loadContainer(propStream, container)) { delete dummy; return false; } delete dummy; } } } return true; }
Attr_ReadValue Item::readAttr(AttrTypes_t attr, PropStream& propStream) { switch (attr) { case ATTR_COUNT: { uint8_t _count = 0; if (!propStream.GET_UCHAR(_count)) { return ATTR_READ_ERROR; } setSubType(_count); break; } case ATTR_ACTION_ID: { uint16_t _actionid = 0; if (!propStream.GET_USHORT(_actionid)) { return ATTR_READ_ERROR; } setActionId(_actionid); break; } case ATTR_UNIQUE_ID: { uint16_t _uniqueid; if (!propStream.GET_USHORT(_uniqueid)) { return ATTR_READ_ERROR; } setUniqueId(_uniqueid); break; } case ATTR_TEXT: { std::string _text; if (!propStream.GET_STRING(_text)) { return ATTR_READ_ERROR; } setText(_text); break; } case ATTR_WRITTENDATE: { uint32_t _writtenDate; if (!propStream.GET_ULONG(_writtenDate)) { return ATTR_READ_ERROR; } setDate(_writtenDate); break; } case ATTR_WRITTENBY: { std::string _writer; if (!propStream.GET_STRING(_writer)) { return ATTR_READ_ERROR; } setWriter(_writer); break; } case ATTR_DESC: { std::string _text; if (!propStream.GET_STRING(_text)) { return ATTR_READ_ERROR; } setSpecialDescription(_text); break; } case ATTR_RUNE_CHARGES: { uint8_t _charges = 1; if (!propStream.GET_UCHAR(_charges)) { return ATTR_READ_ERROR; } setSubType(_charges); break; } case ATTR_CHARGES: { uint16_t _charges = 1; if (!propStream.GET_USHORT(_charges)) { return ATTR_READ_ERROR; } setSubType(_charges); break; } case ATTR_DURATION: { uint32_t duration = 0; if (!propStream.GET_ULONG(duration)) { return ATTR_READ_ERROR; } if (((int32_t)duration) < 0) { duration = 0; } setDuration(duration); break; } case ATTR_DECAYING_STATE: { uint8_t state = 0; if (!propStream.GET_UCHAR(state)) { return ATTR_READ_ERROR; } if (state != DECAYING_FALSE) { setDecaying(DECAYING_PENDING); } break; } //these should be handled through derived classes //If these are called then something has changed in the items.xml since the map was saved //just read the values //Depot class case ATTR_DEPOT_ID: { uint16_t _depotId; if (!propStream.GET_USHORT(_depotId)) { return ATTR_READ_ERROR; } return ATTR_READ_CONTINUE; } //Door class case ATTR_HOUSEDOORID: { uint8_t _doorId; if (!propStream.GET_UCHAR(_doorId)) { return ATTR_READ_ERROR; } return ATTR_READ_CONTINUE; } //Bed class case ATTR_SLEEPERGUID: { uint32_t _guid; if (!propStream.GET_ULONG(_guid)) { return ATTR_READ_ERROR; } return ATTR_READ_CONTINUE; } case ATTR_SLEEPSTART: { uint32_t sleep_start; if (!propStream.GET_ULONG(sleep_start)) { return ATTR_READ_ERROR; } return ATTR_READ_CONTINUE; } //Teleport class case ATTR_TELE_DEST: { TeleportDest* tele_dest; if (!propStream.GET_STRUCT(tele_dest)) { return ATTR_READ_ERROR; } return ATTR_READ_CONTINUE; } //Container class case ATTR_CONTAINER_ITEMS: { uint32_t count; if (!propStream.GET_ULONG(count)) { return ATTR_READ_ERROR; } return ATTR_READ_ERROR; } default: return ATTR_READ_ERROR; } return ATTR_READ_CONTINUE; }
int Items::loadFromOtb(std::string file) { ItemLoader f; if(!f.openFile(file.c_str(), false, true)){ return f.getError(); } unsigned long type; NODE node = f.getChildNode(NO_NODE, type); PropStream props; if(f.getProps(node,props)){ //4 byte flags //attributes //0x01 = version data unsigned long flags; if(!props.GET_ULONG(flags)){ return ERROR_INVALID_FORMAT; } attribute_t attr; if(!props.GET_VALUE(attr)){ return ERROR_INVALID_FORMAT; } if(attr == ROOT_ATTR_VERSION){ datasize_t datalen = 0; if(!props.GET_VALUE(datalen)){ return ERROR_INVALID_FORMAT; } if(datalen != sizeof(VERSIONINFO)){ return ERROR_INVALID_FORMAT; } VERSIONINFO *vi; if(!props.GET_STRUCT(vi)){ return ERROR_INVALID_FORMAT; } Items::dwMajorVersion = vi->dwMajorVersion; //items otb format file version Items::dwMinorVersion = vi->dwMinorVersion; //client version Items::dwBuildNumber = vi->dwBuildNumber; //revision } } if(Items::dwMajorVersion != 1){ std::cout << "Not supported items.otb version." << std::endl; return ERROR_INVALID_FORMAT; } if(Items::dwMinorVersion != CLIENT_VERSION_760){ std::cout << "Not supported items.otb client version." << std::endl; return ERROR_INVALID_FORMAT; } node = f.getChildNode(node, type); while(node != NO_NODE){ PropStream props; if(!f.getProps(node,props)){ return f.getError(); } flags_t flags; ItemType* iType = new ItemType(); iType->group = (itemgroup_t)type; switch(type){ case ITEM_GROUP_NONE: case ITEM_GROUP_GROUND: case ITEM_GROUP_CONTAINER: case ITEM_GROUP_WEAPON: case ITEM_GROUP_AMMUNITION: case ITEM_GROUP_ARMOR: case ITEM_GROUP_RUNE: case ITEM_GROUP_TELEPORT: case ITEM_GROUP_MAGICFIELD: case ITEM_GROUP_WRITEABLE: case ITEM_GROUP_KEY: case ITEM_GROUP_SPLASH: case ITEM_GROUP_FLUID: case ITEM_GROUP_DOOR: break; default: return ERROR_INVALID_FORMAT; break; } //read 4 byte flags if(!props.GET_VALUE(flags)){ return ERROR_INVALID_FORMAT; } iType->blockSolid = ((flags & FLAG_BLOCK_SOLID) == FLAG_BLOCK_SOLID); iType->blockProjectile = ((flags & FLAG_BLOCK_PROJECTILE) == FLAG_BLOCK_PROJECTILE); iType->blockPathFind = ((flags & FLAG_BLOCK_PATHFIND) == FLAG_BLOCK_PATHFIND); iType->hasHeight = ((flags & FLAG_HAS_HEIGHT) == FLAG_HAS_HEIGHT); iType->useable = ((flags & FLAG_USEABLE) == FLAG_USEABLE); iType->pickupable = ((flags & FLAG_PICKUPABLE) == FLAG_PICKUPABLE); iType->moveable = ((flags & FLAG_MOVEABLE) == FLAG_MOVEABLE); iType->stackable = ((flags & FLAG_STACKABLE) == FLAG_STACKABLE); iType->floorChangeDown = ((flags & FLAG_FLOORCHANGEDOWN) == FLAG_FLOORCHANGEDOWN); iType->floorChangeNorth = ((flags & FLAG_FLOORCHANGENORTH) == FLAG_FLOORCHANGENORTH); iType->floorChangeEast = ((flags & FLAG_FLOORCHANGEEAST) == FLAG_FLOORCHANGEEAST); iType->floorChangeSouth = ((flags & FLAG_FLOORCHANGESOUTH) == FLAG_FLOORCHANGESOUTH); iType->floorChangeWest = ((flags & FLAG_FLOORCHANGEWEST) == FLAG_FLOORCHANGEWEST); iType->alwaysOnTop = ((flags & FLAG_ALWAYSONTOP) == FLAG_ALWAYSONTOP); iType->canDecay = !((flags & FLAG_CANNOTDECAY) == FLAG_CANNOTDECAY); iType->isVertical = ((flags & FLAG_VERTICAL) == FLAG_VERTICAL); iType->isHorizontal = ((flags & FLAG_HORIZONTAL) == FLAG_HORIZONTAL); iType->isHangable = ((flags & FLAG_HANGABLE) == FLAG_HANGABLE); iType->allowDistRead = ((flags & FLAG_ALLOWDISTREAD) == FLAG_ALLOWDISTREAD); if(type == ITEM_GROUP_WRITEABLE) { iType->RWInfo |= CAN_BE_WRITTEN; } if((flags & FLAG_READABLE) == FLAG_READABLE) iType->RWInfo |= CAN_BE_READ; iType->rotable = ((flags & FLAG_ROTABLE) == FLAG_ROTABLE); attribute_t attrib; datasize_t datalen = 0; while(props.GET_VALUE(attrib)){ //size of data if(!props.GET_VALUE(datalen)){ delete iType; return ERROR_INVALID_FORMAT; } switch(attrib){ case ITEM_ATTR_SERVERID: { if(datalen != sizeof(unsigned short)) return ERROR_INVALID_FORMAT; unsigned short serverid; if(!props.GET_USHORT(serverid)) return ERROR_INVALID_FORMAT; if(serverid > 20000 && serverid < 20100) serverid = serverid - 20000; iType->id = serverid; break; } case ITEM_ATTR_CLIENTID: { if(datalen != sizeof(unsigned short)) return ERROR_INVALID_FORMAT; if(!props.GET_USHORT(iType->clientId)) return ERROR_INVALID_FORMAT; break; } case ITEM_ATTR_NAME: { char name[128]; if(datalen >= sizeof(name)) return ERROR_INVALID_FORMAT; if(!props.GET_NSTRING(datalen, iType->name)) return ERROR_INVALID_FORMAT; break; } case ITEM_ATTR_DESCR: { char descr[128]; if(datalen >= sizeof(descr)) return ERROR_INVALID_FORMAT; if(!props.GET_NSTRING(datalen, iType->description)) return ERROR_INVALID_FORMAT; break; } case ITEM_ATTR_SPEED: { if(datalen != sizeof(unsigned short)) return ERROR_INVALID_FORMAT; if(!props.GET_USHORT(iType->speed)) return ERROR_INVALID_FORMAT; break; } case ITEM_ATTR_SLOT: { if(datalen != sizeof(unsigned short)) return ERROR_INVALID_FORMAT; unsigned short otb_slot; if(!props.GET_USHORT(otb_slot)) return ERROR_INVALID_FORMAT; switch(otb_slot){ case OTB_SLOT_DEFAULT: case OTB_SLOT_WEAPON: case OTB_SLOT_HAND: //default break; case OTB_SLOT_HEAD: iType->slot_position = SLOTP_HEAD; break; case OTB_SLOT_BODY: iType->slot_position = SLOTP_ARMOR; break; case OTB_SLOT_LEGS: iType->slot_position = SLOTP_LEGS; break; case OTB_SLOT_BACKPACK: iType->slot_position = SLOTP_BACKPACK; break; case OTB_SLOT_2HAND: iType->slot_position = SLOTP_TWO_HAND; break; case OTB_SLOT_FEET: iType->slot_position = SLOTP_FEET; break; case OTB_SLOT_AMULET: iType->slot_position = SLOTP_NECKLACE; break; case OTB_SLOT_RING: iType->slot_position = SLOTP_RING; break; } iType->slot_position = iType->slot_position | SLOTP_LEFT | SLOTP_RIGHT | SLOTP_AMMO; break; } case ITEM_ATTR_MAXITEMS: { if(datalen != sizeof(unsigned short)) return ERROR_INVALID_FORMAT; if(!props.GET_USHORT(iType->maxItems)) return ERROR_INVALID_FORMAT; break; } case ITEM_ATTR_WEIGHT: { if(datalen != sizeof(double)) return ERROR_INVALID_FORMAT; if(!props.GET_VALUE(iType->weight)) return ERROR_INVALID_FORMAT; break; } case ITEM_ATTR_MAGLEVEL: { if(datalen != sizeof(unsigned short)) return ERROR_INVALID_FORMAT; unsigned short maglev; if(!props.GET_USHORT(maglev)) return ERROR_INVALID_FORMAT; iType->runeMagLevel = maglev; break; } case ITEM_ATTR_MAGFIELDTYPE: { if(datalen != sizeof(unsigned char)) return ERROR_INVALID_FORMAT; unsigned char fieldtype; if(!props.GET_UCHAR(fieldtype)) return ERROR_INVALID_FORMAT; iType->magicfieldtype = fieldtype; break; } case ITEM_ATTR_ROTATETO: { if(datalen != sizeof(unsigned short)) return ERROR_INVALID_FORMAT; unsigned short rotate; if(!props.GET_USHORT(rotate)) return ERROR_INVALID_FORMAT; iType->rotateTo = rotate; break; } case ITEM_ATTR_DECAY2: { if(datalen != sizeof(decayBlock2)) return ERROR_INVALID_FORMAT; decayBlock2* db2; if(!props.GET_STRUCT(db2)) return ERROR_INVALID_FORMAT; iType->decayTime = db2->decayTime; iType->decayTo = db2->decayTo; break; } case ITEM_ATTR_WEAPON2: { if(datalen != sizeof(weaponBlock2)) return ERROR_INVALID_FORMAT; weaponBlock2* wb2; if(!props.GET_STRUCT(wb2)) return ERROR_INVALID_FORMAT; iType->weaponType = (WeaponType_t)wb2->weaponType; iType->shootType = translateOTBShootType((ShootTypeOtb_t)wb2->shootType); iType->amuType = (Ammo_t)wb2->amuType; iType->attack = wb2->attack; iType->defence = wb2->defence; break; } case ITEM_ATTR_AMU2: { if(datalen != sizeof(amuBlock2)) return ERROR_INVALID_FORMAT; amuBlock2* ab2; if(!props.GET_STRUCT(ab2)) return ERROR_INVALID_FORMAT; iType->weaponType = WEAPON_AMMO; iType->shootType = translateOTBShootType((ShootTypeOtb_t)ab2->shootType); iType->amuType = (Ammo_t)ab2->amuType; iType->attack = ab2->attack; break; } case ITEM_ATTR_ARMOR2: { if(datalen != sizeof(armorBlock2)) return ERROR_INVALID_FORMAT; armorBlock2* ab2; if(!props.GET_STRUCT(ab2)) return ERROR_INVALID_FORMAT; iType->armor = ab2->armor; iType->weight = ab2->weight; //ignore this value //iType->slot_position = (slots_t)ab2.slot_position; break; } case ITEM_ATTR_WRITEABLE3: { if(datalen != sizeof(writeableBlock3)) return ERROR_INVALID_FORMAT; writeableBlock3* wb3; if(!props.GET_STRUCT(wb3)) return ERROR_INVALID_FORMAT; iType->readOnlyId = wb3->readOnlyId; iType->maxTextLen = wb3->maxTextLen; break; } case ITEM_ATTR_LIGHT2: { if(datalen != sizeof(lightBlock2)) return ERROR_INVALID_FORMAT; lightBlock2* lb2; if(!props.GET_STRUCT(lb2)) return ERROR_INVALID_FORMAT; iType->lightLevel = lb2->lightLevel; iType->lightColor = lb2->lightColor; break; } case ITEM_ATTR_TOPORDER: { if(datalen != sizeof(unsigned char)) return ERROR_INVALID_FORMAT; if(!props.GET_UCHAR(iType->alwaysOnTopOrder)) return ERROR_INVALID_FORMAT; break; } default: //skip unknown attributes if(!props.SKIP_N(datalen)) return ERROR_INVALID_FORMAT; break; } } //get rune mag level from spells.xml if(iType->group == ITEM_GROUP_RUNE){ /* std::map<unsigned short, Spell*>::iterator it = spells.getAllRuneSpells()->find(iType->id); if(it != spells.getAllRuneSpells()->end()){ iType->runeMagLevel = it->second->getMagLv(); } else{ iType->runeMagLevel = 0; } */ } // store the found item items[iType->id] = iType; //revItems[iType->clientId] = iType->id; node = f.getNextNode(node, type); } return ERROR_NONE; }
bool Item::readAttr(AttrTypes_t attr, PropStream& propStream) { switch(attr){ case ATTR_COUNT: { unsigned char _count = 0; if(!propStream.GET_UCHAR(_count)){ return false; } setItemCountOrSubtype(_count); break; } case ATTR_ACTION_ID: { unsigned short _actionid = 0; if(!propStream.GET_USHORT(_actionid)){ return false; } setActionId(_actionid); break; } case ATTR_UNIQUE_ID: { unsigned short _uniqueid; if(!propStream.GET_USHORT(_uniqueid)){ return false; } setUniqueId(_uniqueid); break; } case ATTR_TEXT: { std::string _text; if(!propStream.GET_STRING(_text)){ return false; } setText(_text); break; } case ATTR_DESC: { std::string _text; if(!propStream.GET_STRING(_text)){ return false; } setSpecialDescription(_text); break; } case ATTR_RUNE_CHARGES: { unsigned char _charges = 1; if(!propStream.GET_UCHAR(_charges)){ return false; } setItemCountOrSubtype(_charges); break; } //these should be handled through derived classes //If these are called then something has changed in the items.otb since the map was saved //just read the values //Depot class case ATTR_DEPOT_ID: { unsigned short _depotId; if(!propStream.GET_USHORT(_depotId)){ return false; } return true; } //Door class case ATTR_HOUSEDOORID: { unsigned char _doorId; if(!propStream.GET_UCHAR(_doorId)){ return false; } return true; } //Teleport class case ATTR_TELE_DEST: { TeleportDest* tele_dest; if(!propStream.GET_STRUCT(tele_dest)){ return false; } return true; } default: return false; break; } return true; }