本文整理汇总了C++中PropStream::GET_STRUCT方法的典型用法代码示例。如果您正苦于以下问题:C++ PropStream::GET_STRUCT方法的具体用法?C++ PropStream::GET_STRUCT怎么用?C++ PropStream::GET_STRUCT使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类PropStream
的用法示例。
在下文中一共展示了PropStream::GET_STRUCT方法的10个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: readAttr
Attr_ReadValue Teleport::readAttr(AttrTypes_t attr, PropStream& propStream)
{
if(attr != ATTR_TELE_DEST)
return Item::readAttr(attr, propStream);
TeleportDest* dest;
if(!propStream.GET_STRUCT(dest))
return ATTR_READ_ERROR;
setDestination(Position(dest->_x, dest->_y, dest->_z));
return ATTR_READ_CONTINUE;
}
示例2: readAttr
Attr_ReadValue Teleport::readAttr(AttrTypes_t attr, PropStream& propStream)
{
if (ATTR_TELE_DEST == attr) {
TeleportDest* tele_dest;
if (!propStream.GET_STRUCT(tele_dest)) {
return ATTR_READ_ERROR;
}
setDestPos(Position(tele_dest->_x, tele_dest->_y, tele_dest->_z));
return ATTR_READ_CONTINUE;
} else {
return Item::readAttr(attr, propStream);
}
}
示例3: loadMap
bool IOMap::loadMap(Map* map, const std::string& identifier)
{
FileLoader f;
if(!f.openFile(identifier.c_str(), false, true))
{
std::stringstream ss;
ss << "Could not open the file " << identifier << ".";
setLastErrorString(ss.str());
return false;
}
uint32_t type = 0;
NODE root = f.getChildNode((NODE)NULL, type);
PropStream propStream;
if(!f.getProps(root, propStream))
{
setLastErrorString("Could not read root property.");
return false;
}
OTBM_root_header* rootHeader;
if(!propStream.GET_STRUCT(rootHeader))
{
setLastErrorString("Could not read header.");
return false;
}
uint32_t headerVersion = rootHeader->version;
if(headerVersion <= 0)
{
//In otbm version 1 the count variable after splashes/fluidcontainers and stackables
//are saved as attributes instead, this solves alot of problems with items
//that is changed (stackable/charges/fluidcontainer/splash) during an update.
setLastErrorString("This map needs to be upgraded by using the latest map editor version to be able to load correctly.");
return false;
}
if(headerVersion > 2)
{
setLastErrorString("Unknown OTBM version detected.");
return false;
}
uint32_t headerMajorItems = rootHeader->majorVersionItems;
if(headerMajorItems < 3)
{
setLastErrorString("This map needs to be upgraded by using the latest map editor version to be able to load correctly.");
return false;
}
if(headerMajorItems > (uint32_t)Items::dwMajorVersion)
{
setLastErrorString("The map was saved with a different items.otb version, an upgraded items.otb is required.");
return false;
}
uint32_t headerMinorItems = rootHeader->minorVersionItems;
if(headerMinorItems < CLIENT_VERSION_810)
{
setLastErrorString("This map needs an updated items.otb.");
return false;
}
if(headerMinorItems > (uint32_t)Items::dwMinorVersion)
setLastErrorString("This map needs an updated items.otb.");
std::cout << "> Map size: " << rootHeader->width << "x" << rootHeader->height << "." << std::endl;
map->mapWidth = rootHeader->width;
map->mapHeight = rootHeader->height;
NODE nodeMap = f.getChildNode(root, type);
if(type != OTBM_MAP_DATA)
{
setLastErrorString("Could not read data node.");
return false;
}
if(!f.getProps(nodeMap, propStream))
{
setLastErrorString("Could not read map data attributes.");
return false;
}
std::string tmp;
uint8_t attribute;
while(propStream.GET_UCHAR(attribute))
{
switch(attribute)
{
case OTBM_ATTR_DESCRIPTION:
{
if(!propStream.GET_STRING(tmp))
{
setLastErrorString("Invalid description tag.");
return false;
}
map->descriptions.push_back(tmp);
break;
//.........这里部分代码省略.........
示例4: loadMap
bool IOMap::loadMap(Map* map, const std::string& identifier)
{
int64_t start = OTSYS_TIME();
FileLoader f;
if (!f.openFile(identifier.c_str(), "OTBM", false, true)) {
std::ostringstream ss;
ss << "Could not open the file " << identifier << '.';
setLastErrorString(ss.str());
return false;
}
uint32_t type;
PropStream propStream;
NODE root = f.getChildNode((NODE)nullptr, type);
if (!f.getProps(root, propStream)) {
setLastErrorString("Could not read root property.");
return false;
}
OTBM_root_header* root_header;
if (!propStream.GET_STRUCT(root_header)) {
setLastErrorString("Could not read header.");
return false;
}
uint32_t headerVersion = root_header->version;
if (headerVersion <= 0) {
//In otbm version 1 the count variable after splashes/fluidcontainers and stackables
//are saved as attributes instead, this solves alot of problems with items
//that is changed (stackable/charges/fluidcontainer/splash) during an update.
setLastErrorString("This map need to be upgraded by using the latest map editor version to be able to load correctly.");
return false;
}
if (headerVersion > 2) {
setLastErrorString("Unknown OTBM version detected.");
return false;
}
if (root_header->majorVersionItems < 3) {
setLastErrorString("This map need to be upgraded by using the latest map editor version to be able to load correctly.");
return false;
}
if (root_header->majorVersionItems > (uint32_t)Items::dwMajorVersion) {
setLastErrorString("The map was saved with a different items.otb version, an upgraded items.otb is required.");
return false;
}
if (root_header->minorVersionItems < CLIENT_VERSION_810) {
setLastErrorString("This map needs to be updated.");
return false;
}
if (root_header->minorVersionItems > (uint32_t)Items::dwMinorVersion) {
std::cout << "[Warning - IOMap::loadMap] This map needs an updated items.otb." << std::endl;
}
std::cout << "> Map size: " << root_header->width << "x" << root_header->height << '.' << std::endl;
map->mapWidth = root_header->width;
map->mapHeight = root_header->height;
NODE nodeMap = f.getChildNode(root, type);
if (type != OTBM_MAP_DATA) {
setLastErrorString("Could not read data node.");
return false;
}
if (!f.getProps(nodeMap, propStream)) {
setLastErrorString("Could not read map data attributes.");
return false;
}
unsigned char attribute;
std::string mapDescription;
std::string tmp;
while (propStream.GET_UCHAR(attribute)) {
switch (attribute) {
case OTBM_ATTR_DESCRIPTION:
if (!propStream.GET_STRING(mapDescription)) {
setLastErrorString("Invalid description tag.");
return false;
}
break;
case OTBM_ATTR_EXT_SPAWN_FILE:
if (!propStream.GET_STRING(tmp)) {
setLastErrorString("Invalid spawn tag.");
return false;
//.........这里部分代码省略.........
示例5: loadFromOtb
int Items::loadFromOtb(std::string file)
{
ItemLoader f;
if(!f.openFile(file.c_str(), false, true)){
return f.getError();
}
unsigned long type,len;
const unsigned char* data;
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;
datasize_t datalen = 0;
if(!props.GET_VALUE(attr)){
return ERROR_INVALID_FORMAT;
}
if(attr == ROOT_ATTR_VERSION){
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::dwMinorVersion = vi->dwMinorVersion;
Items::dwBuildNumber = vi->dwBuildNumber;
}
}
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) {
data = f.getProps(node, len);
if(data == NULL && f.getError() != ERROR_NONE)
return f.getError();
flags_t flags;
if(data != NULL) {
const unsigned char* p = &data[0];
ItemType* iType = new ItemType();
bool loadedFlags = false;
while(p < data + len) {
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:
{
if(!loadedFlags) {
//read 4 byte flags
memcpy((void*)&flags, p, sizeof(flags_t)); p+= sizeof(flags_t);
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);
if(type == ITEM_GROUP_WRITEABLE) {
iType->RWInfo |= CAN_BE_WRITTEN;
//.........这里部分代码省略.........
示例6: loadFromOtb
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: {
//.........这里部分代码省略.........
示例7: readAttr
//.........这里部分代码省略.........
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;
}
示例8: loadFromOtb
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);
//.........这里部分代码省略.........
示例9: readAttr
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)){
//.........这里部分代码省略.........
示例10: loadMap
bool IOMapOTBM::loadMap(Map* map, const std::string& identifier)
{
int64_t start = OTSYS_TIME();
FileLoader f;
if(!f.openFile(identifier.c_str(), false, true)){
std::stringstream ss;
ss << "Could not open the file " << identifier << ".";
setLastErrorString(ss.str());
return false;
}
unsigned long type;
PropStream propStream;
NODE root = f.getChildNode((NODE)NULL, type);
if(!f.getProps(root, propStream)){
setLastErrorString("Could not read root property.");
return false;
}
OTBM_root_header* root_header;
if(!propStream.GET_STRUCT(root_header)){
setLastErrorString("Could not read header.");
return false;
}
if(root_header->version > 2){
setLastErrorString("Unknown OTBM version detected, please update your server.");;
return false;
}
if(root_header->majorVersionItems > (unsigned long)Items::dwMajorVersion){
setLastErrorString("The map was saved with a different items.otb version, an upgraded items.otb is required.");
return false;
}
// Prevent load maps saved with items.otb previous to
// version 800, because of the change to stackable of
// itemid 3965
if(root_header->minorVersionItems < CLIENT_VERSION_760){
setLastErrorString("This map needs to be updated.");
return false;
}
if(root_header->minorVersionItems > (unsigned long)Items::dwMinorVersion){
std::cout << "Warning: [OTBM loader] This map needs an updated items OTB file." <<std::endl;
}
std::cout << "Map size: " << root_header->width << "x" << root_header->height << std::endl;
map->mapWidth = root_header->width;
map->mapHeight = root_header->height;
NODE nodeMap = f.getChildNode(root, type);
if(type != OTBM_MAP_DATA){
setLastErrorString("Could not read data node.");
return false;
}
if(!f.getProps(nodeMap, propStream)){
setLastErrorString("Could not read map data attributes.");
return false;
}
unsigned char attribute;
std::string mapDescription;
std::string tmp;
while(propStream.GET_UCHAR(attribute)){
switch(attribute){
case OTBM_ATTR_DESCRIPTION:
if(!propStream.GET_STRING(mapDescription)){
setLastErrorString("Invalid description tag.");
return false;
}
std::cout << "Map description: " << mapDescription << std::endl;
break;
case OTBM_ATTR_EXT_SPAWN_FILE:
if(!propStream.GET_STRING(tmp)){
setLastErrorString("Invalid spawn tag.");
return false;
}
map->spawnfile = identifier.substr(0, identifier.rfind('/') + 1);
map->spawnfile += tmp;
break;
case OTBM_ATTR_EXT_HOUSE_FILE:
if(!propStream.GET_STRING(tmp)){
setLastErrorString("Invalid house tag.");
return false;
}
map->housefile = identifier.substr(0, identifier.rfind('/') + 1);
map->housefile += tmp;
break;
default:
//.........这里部分代码省略.........