the game where you go into mines and start crafting! but for consoles (forked directly from smartcmd's github)
at main 612 lines 19 kB view raw
1#include "stdafx.h" 2#include "com.mojang.nbt.h" 3#include "net.minecraft.world.entity.player.h" 4#include "net.minecraft.world.item.h" 5#include "MapItemSavedData.h" 6#include "..\Minecraft.Client\PlayerList.h" 7#include "..\Minecraft.Client\MinecraftServer.h" 8#include "..\Minecraft.Client\ServerPlayer.h" 9#include "net.minecraft.world.level.h" 10#include "net.minecraft.world.level.storage.h" 11#include "..\Minecraft.Client\PlayerConnection.h" 12 13const int MapItemSavedData::END_PORTAL_DECORATION_KEY = -1; 14 15// 4J added entityId param 16MapItemSavedData::MapDecoration::MapDecoration(char img, char x, char y, char rot, int entityId, bool visible) 17{ 18 this->img = img; 19 this->x = x; 20 this->y = y; 21 this->rot = rot; 22 this->entityId = entityId; 23 this->visible = visible; 24} 25 26MapItemSavedData::HoldingPlayer::HoldingPlayer(shared_ptr<Player> player, const MapItemSavedData *parent) : parent( parent ), player( player ) 27{ 28 // inited outside of ctor 29 rowsDirtyMin = intArray(MapItem::IMAGE_WIDTH); 30 rowsDirtyMax = intArray(MapItem::IMAGE_WIDTH); 31 32 tick = 0; 33 sendPosTick = 0; 34 step = 0; 35 hasSentInitial = false; 36 37 // java ctor 38 //this->player = player; 39 for (unsigned int i = 0; i < rowsDirtyMin.length; i++) 40 { 41 rowsDirtyMin[i] = 0; 42 rowsDirtyMax[i] = MapItem::IMAGE_HEIGHT - 1; 43 } 44} 45 46MapItemSavedData::HoldingPlayer::~HoldingPlayer() 47{ 48 delete rowsDirtyMin.data; 49 delete rowsDirtyMax.data; 50 delete lastSentDecorations.data; 51} 52 53charArray MapItemSavedData::HoldingPlayer::nextUpdatePacket(shared_ptr<ItemInstance> itemInstance) 54{ 55 if (!hasSentInitial) 56 { 57 charArray data(2); 58 data[0] = HEADER_METADATA; 59 data[1] = parent->scale; 60 61 hasSentInitial = true; 62 return data; 63 } 64 if (--sendPosTick < 0) 65 { 66 sendPosTick = 4; 67 68 unsigned int playerDecorationsSize = (int)parent->decorations.size(); 69 unsigned int nonPlayerDecorationsSize = (int)parent->nonPlayerDecorations.size(); 70 charArray data = charArray( (playerDecorationsSize + nonPlayerDecorationsSize ) * DEC_PACKET_BYTES + 1); 71 data[0] = 1; 72 for (unsigned int i = 0; i < parent->decorations.size(); i++) 73 { 74 MapDecoration *md = parent->decorations.at(i); 75#ifdef _LARGE_WORLDS 76 data[i * DEC_PACKET_BYTES + 1] = (char) (md->img); 77 data[i * DEC_PACKET_BYTES + 8] = (char) (md->rot & 0xF); 78#else 79 data[i * DEC_PACKET_BYTES + 1] = (char) ((md->img << 4) | (md->rot & 0xF)); 80#endif 81 data[i * DEC_PACKET_BYTES + 2] = md->x; 82 data[i * DEC_PACKET_BYTES + 3] = md->y; 83 data[i * DEC_PACKET_BYTES + 4] = md->entityId & 0xFF; 84 data[i * DEC_PACKET_BYTES + 5] = (md->entityId>>8) & 0xFF; 85 data[i * DEC_PACKET_BYTES + 6] = (md->entityId>>16) & 0xFF; 86 data[i * DEC_PACKET_BYTES + 7] = (md->entityId>>24) & 0x7F; 87 data[i * DEC_PACKET_BYTES + 7] |= md->visible ? 0x80 : 0x0; 88 } 89 unsigned int dataIndex = playerDecorationsSize; 90 for(AUTO_VAR(it, parent->nonPlayerDecorations.begin()); it != parent->nonPlayerDecorations.end(); ++it) 91 { 92 MapDecoration *md = it->second; 93#ifdef _LARGE_WORLDS 94 data[dataIndex * DEC_PACKET_BYTES + 1] = (char) (md->img); 95 data[dataIndex * DEC_PACKET_BYTES + 8] = (char) (md->rot & 0xF); 96#else 97 data[dataIndex * DEC_PACKET_BYTES + 1] = (char) ((md->img << 4) | (md->rot & 0xF)); 98#endif 99 data[dataIndex * DEC_PACKET_BYTES + 2] = md->x; 100 data[dataIndex * DEC_PACKET_BYTES + 3] = md->y; 101 data[dataIndex * DEC_PACKET_BYTES + 4] = md->entityId & 0xFF; 102 data[dataIndex * DEC_PACKET_BYTES + 5] = (md->entityId>>8) & 0xFF; 103 data[dataIndex * DEC_PACKET_BYTES + 6] = (md->entityId>>16) & 0xFF; 104 data[dataIndex * DEC_PACKET_BYTES + 7] = (md->entityId>>24) & 0x7F; 105 data[dataIndex * DEC_PACKET_BYTES + 7] |= md->visible ? 0x80 : 0x0; 106 107 ++dataIndex; 108 } 109 bool thesame = !itemInstance->isFramed(); 110 if (lastSentDecorations.data == NULL || lastSentDecorations.length != data.length) 111 { 112 thesame = false; 113 } 114 else 115 { 116 for (unsigned int i = 0; i < data.length; i++) 117 { 118 if ( data[i] != lastSentDecorations[i]) 119 { 120 thesame = false; 121 break; 122 } 123 } 124 } 125 126 if (!thesame) 127 { 128 if( lastSentDecorations.data != NULL ) 129 { 130 delete[] lastSentDecorations.data; 131 } 132 // Make a copy of data, as the calling function presumes it can destroy the returned data 133 lastSentDecorations = charArray(data.length); 134 memcpy(lastSentDecorations.data, data.data, data.length); 135 return data; 136 } 137 delete data.data; 138 } 139 shared_ptr<ServerPlayer> servPlayer = dynamic_pointer_cast<ServerPlayer>(player); 140 for (int d = 0; d < 10; d++) 141 { 142 int column = (tick++ * 11) % (MapItem::IMAGE_WIDTH); 143 144 if (rowsDirtyMin[column] >= 0) 145 { 146 int len = rowsDirtyMax[column] - rowsDirtyMin[column] + 1; 147 int min = rowsDirtyMin[column]; 148 149 charArray data = charArray(len + 3); 150 data[0] = HEADER_COLOURS; 151 data[1] = (char) column; 152 data[2] = (char) min; 153 for (unsigned int y = 0; y < data.length - 3; y++) 154 { 155 data[y + 3] = parent->colors[(y + min) * MapItem::IMAGE_WIDTH + column]; 156 } 157 rowsDirtyMax[column] = -1; 158 rowsDirtyMin[column] = -1; 159 return data; 160 } 161 } 162 return charArray(); 163} 164 165 166MapItemSavedData::MapItemSavedData(const wstring& id) : SavedData( id ) 167{ 168 x = z = 0; 169 dimension = 0; 170 scale = 0; 171 colors = byteArray( MapItem::IMAGE_WIDTH * MapItem::IMAGE_HEIGHT ); 172} 173 174MapItemSavedData::~MapItemSavedData() 175{ 176 delete colors.data; 177 for( unsigned int i = 0; i < decorations.size(); i++ ) 178 { 179 delete decorations[i]; 180 } 181} 182 183void MapItemSavedData::load(CompoundTag *tag) 184{ 185 dimension = tag->getByte(L"dimension"); 186 x = tag->getInt(L"xCenter"); 187 z = tag->getInt(L"zCenter"); 188 scale = tag->getByte(L"scale"); 189 if (scale < 0) scale = 0; 190 if (scale > MAX_SCALE) scale = MAX_SCALE; 191 192 int width = tag->getShort(L"width"); 193 int height = tag->getShort(L"height"); 194 if (width == MapItem::IMAGE_WIDTH && height == MapItem::IMAGE_HEIGHT) 195 { 196 colors = tag->getByteArray(L"colors"); 197 } 198 else 199 { 200 byteArray newColors = tag->getByteArray(L"colors"); 201 //4J 202 if(colors.data != NULL) 203 { 204 delete[] colors.data; 205 } 206 //End4J 207 colors = byteArray(MapItem::IMAGE_WIDTH * MapItem::IMAGE_HEIGHT); 208 int xo = (MapItem::IMAGE_WIDTH - width) / 2; 209 int yo = (MapItem::IMAGE_HEIGHT - height) / 2; 210 for (int y = 0; y < height; y++) 211 { 212 int yt = y + yo; 213 if (yt < 0 && yt >= MapItem::IMAGE_HEIGHT) continue; 214 for (int x = 0; x < width; x++) 215 { 216 int xt = x + xo; 217 if (xt < 0 && xt >= MapItem::IMAGE_WIDTH) continue; 218 colors[xt + yt * MapItem::IMAGE_WIDTH] = newColors[x + y * width]; 219 } 220 } 221 } 222} 223 224void MapItemSavedData::save(CompoundTag *tag) 225{ 226 tag->putByte(L"dimension", dimension); 227 tag->putInt(L"xCenter", x); 228 tag->putInt(L"zCenter", z); 229 tag->putByte(L"scale", scale); 230 tag->putShort(L"width", (short) MapItem::IMAGE_WIDTH); 231 tag->putShort(L"height", (short) MapItem::IMAGE_HEIGHT); 232 tag->putByteArray(L"colors", colors); 233} 234 235void MapItemSavedData::tickCarriedBy(shared_ptr<Player> player, shared_ptr<ItemInstance> item) 236{ 237 if (carriedByPlayers.find(player) == carriedByPlayers.end()) 238 { 239 shared_ptr<HoldingPlayer> hp = shared_ptr<HoldingPlayer>( new HoldingPlayer(player, this ) ); 240 carriedByPlayers.insert( playerHoldingPlayerMapType::value_type(player, hp) ); 241 carriedBy.push_back(hp); 242 } 243 244 for( unsigned int i = 0; i < decorations.size(); i++ ) 245 { 246 delete decorations[i]; 247 } 248 decorations.clear(); 249 250 // 4J Stu - Put this block back in if you want to display entity positions on a map (see below) 251#if 0 252 nonPlayerDecorations.clear(); 253#endif 254 bool addedPlayers = false; 255 for (AUTO_VAR(it, carriedBy.begin()); it != carriedBy.end(); ) 256 { 257 shared_ptr<HoldingPlayer> hp = *it; 258 259 // 4J Stu - Players in the same dimension as an item frame with a map need to be sent this data, so don't remove them 260 if (hp->player->removed ) //|| (!hp->player->inventory->contains(item) && !item->isFramed() )) 261 { 262 AUTO_VAR(it2, carriedByPlayers.find( (shared_ptr<Player> ) hp->player )); 263 if( it2 != carriedByPlayers.end() ) 264 { 265 carriedByPlayers.erase( it2 ); 266 } 267 it = carriedBy.erase( std::find(carriedBy.begin(), carriedBy.end(), hp) ); 268 } 269 else 270 { 271 ++it; 272 273 Level *playerLevel = hp->player->level; 274 if(!playerLevel->isClientSide && hp->player->dimension == 0 && (playerLevel->getLevelData()->getHasStrongholdEndPortal() || playerLevel->getLevelData()->getHasStronghold() ) ) 275 { 276 bool atLeastOnePlayerInTheEnd = false; 277 PlayerList *players = MinecraftServer::getInstance()->getPlayerList(); 278 for(AUTO_VAR(it3, players->players.begin()); it3 != players->players.end(); ++it3) 279 { 280 shared_ptr<ServerPlayer> serverPlayer = *it3; 281 if(serverPlayer->dimension == 1) 282 { 283 atLeastOnePlayerInTheEnd = true; 284 break; 285 } 286 } 287 288 AUTO_VAR(currentPortalDecoration, nonPlayerDecorations.find( END_PORTAL_DECORATION_KEY )); 289 if( currentPortalDecoration == nonPlayerDecorations.end() && atLeastOnePlayerInTheEnd) 290 { 291 float origX = 0.0f; 292 float origZ = 0.0f; 293 294 if(playerLevel->getLevelData()->getHasStrongholdEndPortal()) 295 { 296 origX = playerLevel->getLevelData()->getXStrongholdEndPortal(); 297 origZ = playerLevel->getLevelData()->getZStrongholdEndPortal(); 298 } 299 else 300 { 301 origX = playerLevel->getLevelData()->getXStronghold()<<4; 302 origZ = playerLevel->getLevelData()->getZStronghold()<<4; 303 } 304 305 float xd = (float) ( origX - x ) / (1 << scale); 306 float yd = (float) ( origZ - z ) / (1 << scale); 307 char x = (char) (xd * 2 + 0.5); 308 char y = (char) (yd * 2 + 0.5); 309 int size = MAP_SIZE - 1; 310#ifdef _LARGE_WORLDS 311 if (xd < -size || yd < -size || xd > size || yd > size) 312 { 313 314 if (xd <= -size) x = (byte) (size * 2 + 2.5); 315 if (yd <= -size) y = (byte) (size * 2 + 2.5); 316 if (xd >= size) x = (byte) (size * 2 + 1); 317 if (yd >= size) y = (byte) (size * 2 + 1); 318 } 319#endif 320 //decorations.push_back(new MapDecoration(4, x, y, 0)); 321 nonPlayerDecorations.insert( unordered_map<int, MapDecoration *>::value_type( END_PORTAL_DECORATION_KEY, new MapDecoration(4, x, y, 0, END_PORTAL_DECORATION_KEY, true) ) ); 322 } 323 else if ( currentPortalDecoration != nonPlayerDecorations.end() && !atLeastOnePlayerInTheEnd ) 324 { 325 delete currentPortalDecoration->second; 326 nonPlayerDecorations.erase( currentPortalDecoration ); 327 } 328 } 329 330 if (item->isFramed()) 331 { 332 //addDecoration(1, player.level, "frame-" + item.getFrame().entityId, item.getFrame().xTile, item.getFrame().zTile, item.getFrame().dir * 90); 333 334 if( nonPlayerDecorations.find( item->getFrame()->entityId ) == nonPlayerDecorations.end() ) 335 { 336 float xd = (float) ( item->getFrame()->xTile - x ) / (1 << scale); 337 float yd = (float) ( item->getFrame()->zTile - z ) / (1 << scale); 338 char x = (char) (xd * 2 + 0.5); 339 char y = (char) (yd * 2 + 0.5); 340 int size = MAP_SIZE - 1; 341 char rot = (char) ( (item->getFrame()->dir * 90) * 16 / 360); 342 if (dimension < 0) 343 { 344 int s = (int) (playerLevel->getLevelData()->getDayTime() / 10); 345 rot = (char) ((s * s * 34187121 + s * 121) >> 15 & 15); 346 } 347#ifdef _LARGE_WORLDS 348 if (xd < -size || yd < -size || xd > size || yd > size) 349 { 350 351 if (xd <= -size) x = (byte) (size * 2 + 2.5); 352 if (yd <= -size) y = (byte) (size * 2 + 2.5); 353 if (xd >= size) x = (byte) (size * 2 + 1); 354 if (yd >= size) y = (byte) (size * 2 + 1); 355 } 356#endif 357 //decorations.push_back(new MapDecoration(7, x, y, 0)); 358 nonPlayerDecorations.insert( unordered_map<int, MapDecoration *>::value_type( item->getFrame()->entityId, new MapDecoration(12, x, y, rot, item->getFrame()->entityId, true) ) ); 359 } 360 } 361 362 // 4J Stu - Put this block back in if you want to display entity positions on a map (see above as well) 363#if 0 364 for(AUTO_VAR(it,playerLevel->entities.begin()); it != playerLevel->entities.end(); ++it) 365 { 366 shared_ptr<Entity> ent = *it; 367 368 if((ent->GetType() & eTYPE_ENEMY) == 0) continue; 369 370 float xd = (float) ( ent->x - x ) / (1 << scale); 371 float yd = (float) ( ent->z - z ) / (1 << scale); 372 char x = (char) (xd * 2 + 0.5); 373 char y = (char) (yd * 2 + 0.5); 374 int size = MAP_SIZE - 1; 375 char rot = 0; 376 if (dimension < 0) 377 { 378 int s = step / 10; 379 rot = (char) ((s * s * 34187121 + s * 121) >> 15 & 15); 380 } 381#ifdef _LARGE_WORLDS 382 if (xd < -size || yd < -size || xd > size || yd > size) 383 { 384 385 if (xd <= -size) x = (byte) (size * 2 + 2.5); 386 if (yd <= -size) y = (byte) (size * 2 + 2.5); 387 if (xd >= size) x = (byte) (size * 2 + 1); 388 if (yd >= size) y = (byte) (size * 2 + 1); 389 } 390#endif 391 //decorations.push_back(new MapDecoration(7, x, y, 0)); 392 nonPlayerDecorations.insert( unordered_map<int, MapDecoration *>::value_type( ent->entityId, new MapDecoration(4, x, y, rot, ent->entityId, true) ) ); 393 } 394#endif 395 396 // 4J-PB - display all the players in the map 397 // For the xbox, x and z are 0 398 if (hp->player->dimension == this->dimension && !addedPlayers) 399 { 400 addedPlayers = true; 401 402 PlayerList *players = MinecraftServer::getInstance()->getPlayerList(); 403 for(AUTO_VAR(it3, players->players.begin()); it3 != players->players.end(); ++it3) 404 { 405 shared_ptr<ServerPlayer> decorationPlayer = *it3; 406 if(decorationPlayer!=NULL && decorationPlayer->dimension == this->dimension) 407 { 408 float xd = (float) (decorationPlayer->x - x) / (1 << scale); 409 float yd = (float) (decorationPlayer->z - z) / (1 << scale); 410 char x = (char) (xd * 2); 411 char y = (char) (yd * 2); 412 int size = MAP_SIZE; // - 1; 413 char rot; 414 char imgIndex; 415 416#ifdef _LARGE_WORLDS 417 if (xd > -size && yd > -size && xd <= size && yd <= size) 418 419#endif 420 { 421 rot = (char) (decorationPlayer->yRot * 16 / 360 + 0.5); 422 if (dimension < 0) 423 { 424 int s = (int) (playerLevel->getLevelData()->getDayTime() / 10); 425 rot = (char) ((s * s * 34187121 + s * 121) >> 15 & 15); 426 } 427 428 // 4J Stu - As we have added new icons for players on a new row below 429 // other icons used in Java we need to move our index to the next row 430 imgIndex = (int)decorationPlayer->getPlayerIndex(); 431 if(imgIndex>3) imgIndex += 4; 432 } 433#ifdef _LARGE_WORLDS 434 else //if (abs(xd) < MAP_SIZE * 5 && abs(yd) < MAP_SIZE * 5) 435 { 436 // 4J Stu - As we have added new icons for players on a new row below 437 // other icons used in Java we need to move our index to the next row 438 imgIndex = (int)decorationPlayer->getPlayerIndex(); 439 if(imgIndex>3) imgIndex += 4; 440 imgIndex += 16; // Add 16 to indicate that it's on the next texture 441 442 rot = 0; 443 size--; // Added to match the old adjusted size 444 if (xd <= -size) x = (byte) (size * 2 + 2.5); 445 if (yd <= -size) y = (byte) (size * 2 + 2.5); 446 if (xd >= size) x = (byte) (size * 2 + 1); 447 if (yd >= size) y = (byte) (size * 2 + 1); 448 } 449#endif 450 451 MemSect(45); 452 decorations.push_back(new MapDecoration(imgIndex, x, y, rot, decorationPlayer->entityId, (decorationPlayer == hp->player || decorationPlayer->canShowOnMaps()) )); 453 MemSect(0); 454 } 455 } 456 } 457 458// float xd = (float) (hp->player->x - x) / (1 << scale); 459// float yd = (float) (hp->player->z - z) / (1 << scale); 460// int ww = 64; 461// int hh = 64; 462// if (xd >= -ww && yd >= -hh && xd <= ww && yd <= hh) 463// { 464// char img = 0; 465// char x = (char) (xd * 2 + 0.5); 466// char y = (char) (yd * 2 + 0.5); 467// char rot = (char) (player->yRot * 16 / 360 + 0.5); 468// if (dimension < 0) 469// { 470// int s = step / 10; 471// rot = (char) ((s * s * 34187121 + s * 121) >> 15 & 15); 472// } 473// if (hp->player->dimension == this->dimension) 474// { 475// decorations.push_back(new MapDecoration(img, x, y, rot)); 476// } 477// } 478 } 479 } 480} 481 482charArray MapItemSavedData::getUpdatePacket(shared_ptr<ItemInstance> itemInstance, Level *level, shared_ptr<Player> player) 483{ 484 AUTO_VAR(it, carriedByPlayers.find(player)); 485 if (it == carriedByPlayers.end() ) return charArray(); 486 487 shared_ptr<HoldingPlayer> hp = it->second; 488 return hp->nextUpdatePacket(itemInstance); 489} 490 491void MapItemSavedData::setDirty(int x, int y0, int y1) 492{ 493 SavedData::setDirty(); 494 495 AUTO_VAR(itEnd, carriedBy.end()); 496 for (AUTO_VAR(it, carriedBy.begin()); it != itEnd; it++) 497 { 498 shared_ptr<HoldingPlayer> hp = *it; //carriedBy.at(i); 499 if (hp->rowsDirtyMin[x] < 0 || hp->rowsDirtyMin[x] > y0) hp->rowsDirtyMin[x] = y0; 500 if (hp->rowsDirtyMax[x] < 0 || hp->rowsDirtyMax[x] < y1) hp->rowsDirtyMax[x] = y1; 501 } 502} 503 504void MapItemSavedData::handleComplexItemData(charArray &data) 505{ 506 if (data[0] == HEADER_COLOURS) 507 { 508 int xx = data[1] & 0xff; 509 int yy = data[2] & 0xff; 510 for (unsigned int y = 0; y < data.length - 3; y++) 511 { 512 colors[(y + yy) * MapItem::IMAGE_WIDTH + xx] = data[y + 3]; 513 } 514 setDirty(); 515 516 } 517 else if (data[0] == HEADER_DECORATIONS) 518 { 519 for( unsigned int i = 0; i < decorations.size(); i++ ) 520 { 521 delete decorations[i]; 522 } 523 decorations.clear(); 524 for (unsigned int i = 0; i < (data.length - 1) / DEC_PACKET_BYTES; i++) 525 { 526#ifdef _LARGE_WORLDS 527 char img = data[i * DEC_PACKET_BYTES + 1]; 528 char rot = data[i * DEC_PACKET_BYTES + 8]; 529#else 530 // 4J-PB - this gives the wrong result 531 char img = (char) ( (((int)data[i * DEC_PACKET_BYTES + 1])&0xF0) >> 4); 532 char rot = (char) (data[i * DEC_PACKET_BYTES + 1] & 0xF); 533#endif 534 char x = data[i * DEC_PACKET_BYTES + 2]; 535 char y = data[i * DEC_PACKET_BYTES + 3]; 536 int entityId = (((int)data[i * DEC_PACKET_BYTES + 4])&0xFF) | ( (((int)data[i * DEC_PACKET_BYTES + 5])&0xFF)<<8) | ((((int)data[i * DEC_PACKET_BYTES + 6])&0xFF)<<16) | ((((int)data[i * DEC_PACKET_BYTES + 7])&0x7F)<<24); 537 bool visible = (data[i * DEC_PACKET_BYTES + 7] & 0x80) != 0; 538 decorations.push_back(new MapDecoration(img, x, y, rot, entityId, visible)); 539 } 540 } 541 else if (data[0] == HEADER_METADATA) 542 { 543 scale = data[1]; 544 } 545} 546 547shared_ptr<MapItemSavedData::HoldingPlayer> MapItemSavedData::getHoldingPlayer(shared_ptr<Player> player) 548{ 549 shared_ptr<HoldingPlayer> hp = nullptr; 550 AUTO_VAR(it,carriedByPlayers.find(player)); 551 552 if (it == carriedByPlayers.end()) 553 { 554 hp = shared_ptr<HoldingPlayer>( new HoldingPlayer(player, this) ); 555 carriedByPlayers[player] = hp; 556 carriedBy.push_back(hp); 557 } 558 else 559 { 560 hp = it->second; 561 } 562 563 return hp; 564} 565 566// 4J Added 567// We only have one map per player per dimension, so if they pickup someone elses map we merge their map data with ours 568// so that we can see everything that they discovered but still only have one map data ourself 569void MapItemSavedData::mergeInMapData(shared_ptr<MapItemSavedData> dataToAdd) 570{ 571 int w = MapItem::IMAGE_WIDTH; 572 int h = MapItem::IMAGE_HEIGHT; 573 574 for (int x = 0; x < w; x++) 575 { 576 int yd0 = 255; 577 int yd1 = 0; 578 579 for (int z = 0; z < h; z++) 580 { 581 byte oldColor = colors[x + z * w]; 582 byte newColor = dataToAdd->colors[x + z * w]; 583 if (oldColor == 0 && oldColor != newColor) 584 { 585 if (yd0 > z) yd0 = z; 586 if (yd1 < z) yd1 = z; 587 colors[x + z * w] = newColor; 588 } 589 } 590 if (yd0 <= yd1) 591 { 592 setDirty(x, yd0, yd1); 593 } 594 } 595} 596 597void MapItemSavedData::removeItemFrameDecoration(shared_ptr<ItemInstance> item) 598{ 599 if ( !item ) 600 return; 601 602 std::shared_ptr<ItemFrame> frame = item->getFrame(); 603 if ( !frame ) 604 return; 605 606 auto frameDecoration = nonPlayerDecorations.find(frame->entityId); 607 if ( frameDecoration != nonPlayerDecorations.end() ) 608 { 609 delete frameDecoration->second; 610 nonPlayerDecorations.erase( frameDecoration ); 611 } 612}