the game where you go into mines and start crafting! but for consoles (forked directly from smartcmd's github)
at main 416 lines 11 kB view raw
1#include "stdafx.h" 2#include "com.mojang.nbt.h" 3#include "net.minecraft.world.h" 4#include "net.minecraft.world.level.h" 5#include "TileEntity.h" 6#include "net.minecraft.world.entity.item.h" 7#include "net.minecraft.world.entity.player.h" 8#include "net.minecraft.world.item.h" 9#include "net.minecraft.world.inventory.h" 10#include "net.minecraft.world.level.tile.h" 11#include "net.minecraft.world.phys.h" 12#include "ChestTileEntity.h" 13#include "ContainerOpenPacket.h" 14#include "SoundTypes.h" 15 16int ChestTileEntity::getContainerType() 17{ 18 if (isBonusChest) return ContainerOpenPacket::BONUS_CHEST; 19 else return ContainerOpenPacket::CONTAINER; 20} 21 22void ChestTileEntity::_init(bool isBonusChest) 23{ 24 items = new ItemInstanceArray(9 * 4); 25 26 hasCheckedNeighbors = false; 27 this->isBonusChest = isBonusChest; 28 29 openness = 0.0f; 30 oOpenness = 0.0f; 31 openCount = 0; 32 tickInterval = 0; 33 34 type = -1; 35 name = L""; 36} 37 38ChestTileEntity::ChestTileEntity(bool isBonusChest/* = false*/) : TileEntity() 39{ 40 _init(isBonusChest); 41} 42 43ChestTileEntity::ChestTileEntity(int type, bool isBonusChest/* = false*/) : TileEntity() 44{ 45 _init(isBonusChest); 46 47 this->type = type; 48} 49 50ChestTileEntity::~ChestTileEntity() 51{ 52 delete[] items->data; 53 delete items; 54} 55 56unsigned int ChestTileEntity::getContainerSize() 57{ 58 return 9 * 3; 59} 60 61shared_ptr<ItemInstance> ChestTileEntity::getItem(unsigned int slot) 62{ 63 return items->data[slot]; 64} 65 66shared_ptr<ItemInstance> ChestTileEntity::removeItem(unsigned int slot, int count) 67{ 68 if (items->data[slot] != NULL) 69 { 70 if (items->data[slot]->count <= count) 71 { 72 shared_ptr<ItemInstance> item = items->data[slot]; 73 items->data[slot] = nullptr; 74 setChanged(); 75 // 4J Stu - Fix for duplication glitch 76 if(item->count <= 0) return nullptr; 77 return item; 78 } 79 else 80 { 81 shared_ptr<ItemInstance> i = items->data[slot]->remove(count); 82 if (items->data[slot]->count == 0) items->data[slot] = nullptr; 83 setChanged(); 84 // 4J Stu - Fix for duplication glitch 85 if(i->count <= 0) return nullptr; 86 return i; 87 } 88 } 89 return nullptr; 90} 91 92shared_ptr<ItemInstance> ChestTileEntity::removeItemNoUpdate(int slot) 93{ 94 if (items->data[slot] != NULL) 95 { 96 shared_ptr<ItemInstance> item = items->data[slot]; 97 items->data[slot] = nullptr; 98 return item; 99 } 100 return nullptr; 101} 102 103void ChestTileEntity::setItem(unsigned int slot, shared_ptr<ItemInstance> item) 104{ 105 items->data[slot] = item; 106 if (item != NULL && item->count > getMaxStackSize()) item->count = getMaxStackSize(); 107 this->setChanged(); 108} 109 110wstring ChestTileEntity::getName() 111{ 112 return hasCustomName() ? name : app.GetString(IDS_TILE_CHEST); 113} 114 115wstring ChestTileEntity::getCustomName() 116{ 117 return hasCustomName() ? name : L""; 118} 119 120bool ChestTileEntity::hasCustomName() 121{ 122 return !name.empty(); 123} 124 125void ChestTileEntity::setCustomName(const wstring &name) 126{ 127 this->name = name; 128} 129 130void ChestTileEntity::load(CompoundTag *base) 131{ 132 TileEntity::load(base); 133 ListTag<CompoundTag> *inventoryList = (ListTag<CompoundTag> *) base->getList(L"Items"); 134 if( items ) 135 { 136 delete [] items->data; 137 delete items; 138 } 139 items = new ItemInstanceArray(getContainerSize()); 140 if (base->contains(L"CustomName")) name = base->getString(L"CustomName"); 141 for (int i = 0; i < inventoryList->size(); i++) 142 { 143 CompoundTag *tag = inventoryList->get(i); 144 unsigned int slot = tag->getByte(L"Slot") & 0xff; 145 if (slot >= 0 && slot < items->length) (*items)[slot] = ItemInstance::fromTag(tag); 146 } 147 isBonusChest = base->getBoolean(L"bonus"); 148} 149 150void ChestTileEntity::save(CompoundTag *base) 151{ 152 TileEntity::save(base); 153 ListTag<CompoundTag> *listTag = new ListTag<CompoundTag>; 154 155 for (unsigned int i = 0; i < items->length; i++) 156 { 157 if (items->data[i] != NULL) 158 { 159 CompoundTag *tag = new CompoundTag(); 160 tag->putByte(L"Slot", (byte) i); 161 items->data[i]->save(tag); 162 listTag->add(tag); 163 } 164 } 165 base->put(L"Items", listTag); 166 if (hasCustomName()) base->putString(L"CustomName", name); 167 base->putBoolean(L"bonus", isBonusChest); 168} 169 170int ChestTileEntity::getMaxStackSize() const 171{ 172 return Container::LARGE_MAX_STACK_SIZE; 173} 174 175bool ChestTileEntity::stillValid(shared_ptr<Player> player) 176{ 177 if (level->getTileEntity(x, y, z) != shared_from_this() ) return false; 178 if (player->distanceToSqr(x + 0.5, y + 0.5, z + 0.5) > 8 * 8) return false; 179 return true; 180} 181 182void ChestTileEntity::setChanged() 183{ 184 TileEntity::setChanged(); 185} 186 187void ChestTileEntity::clearCache() 188{ 189 TileEntity::clearCache(); 190 hasCheckedNeighbors = false; 191} 192 193void ChestTileEntity::heyImYourNeighbor(shared_ptr<ChestTileEntity> neighbor, int from) 194{ 195 if (neighbor->isRemoved()) 196 { 197 hasCheckedNeighbors = false; 198 } 199 else if (hasCheckedNeighbors) 200 { 201 switch (from) 202 { 203 case Direction::NORTH: 204 if (n.lock() != neighbor) hasCheckedNeighbors = false; 205 break; 206 case Direction::SOUTH: 207 if (s.lock() != neighbor) hasCheckedNeighbors = false; 208 break; 209 case Direction::EAST: 210 if (e.lock() != neighbor) hasCheckedNeighbors = false; 211 break; 212 case Direction::WEST: 213 if (w.lock() != neighbor) hasCheckedNeighbors = false; 214 break; 215 } 216 } 217} 218 219void ChestTileEntity::checkNeighbors() 220{ 221 if (hasCheckedNeighbors) return; 222 223 hasCheckedNeighbors = true; 224 n = weak_ptr<ChestTileEntity>(); 225 e = weak_ptr<ChestTileEntity>(); 226 w = weak_ptr<ChestTileEntity>(); 227 s = weak_ptr<ChestTileEntity>(); 228 229 if (isSameChest(x - 1, y, z)) 230 { 231 w = dynamic_pointer_cast<ChestTileEntity>(level->getTileEntity(x - 1, y, z)); 232 } 233 if (isSameChest(x + 1, y, z)) 234 { 235 e = dynamic_pointer_cast<ChestTileEntity>(level->getTileEntity(x + 1, y, z)); 236 } 237 if (isSameChest(x, y, z - 1)) 238 { 239 n = dynamic_pointer_cast<ChestTileEntity>(level->getTileEntity(x, y, z - 1)); 240 } 241 if (isSameChest(x, y, z + 1)) 242 { 243 s = dynamic_pointer_cast<ChestTileEntity>(level->getTileEntity(x, y, z + 1)); 244 } 245 246 shared_ptr<ChestTileEntity> cteThis = dynamic_pointer_cast<ChestTileEntity>(shared_from_this()); 247 if (n.lock() != NULL) n.lock()->heyImYourNeighbor(cteThis, Direction::SOUTH); 248 if (s.lock() != NULL) s.lock()->heyImYourNeighbor(cteThis, Direction::NORTH); 249 if (e.lock() != NULL) e.lock()->heyImYourNeighbor(cteThis, Direction::WEST); 250 if (w.lock() != NULL) w.lock()->heyImYourNeighbor(cteThis, Direction::EAST); 251} 252 253bool ChestTileEntity::isSameChest(int x, int y, int z) 254{ 255 Tile *tile = Tile::tiles[level->getTile(x, y, z)]; 256 if (tile == NULL || !(dynamic_cast<ChestTile *>(tile) != NULL)) return false; 257 return ((ChestTile *) tile)->type == getType(); 258} 259 260void ChestTileEntity::tick() 261{ 262 TileEntity::tick(); 263 checkNeighbors(); 264 265 ++tickInterval; 266 if (!level->isClientSide && openCount != 0 && (tickInterval + x + y + z) % (SharedConstants::TICKS_PER_SECOND * 10) == 0) 267 { 268 // level.tileEvent(x, y, z, Tile.chest.id, ChestTile.EVENT_SET_OPEN_COUNT, openCount); 269 270 openCount = 0; 271 272 float range = 5; 273 vector<shared_ptr<Entity> > *players = level->getEntitiesOfClass(typeid(Player), AABB::newTemp(x - range, y - range, z - range, x + 1 + range, y + 1 + range, z + 1 + range)); 274 for (AUTO_VAR(it,players->begin()); it != players->end(); ++it) 275 { 276 shared_ptr<Player> player = dynamic_pointer_cast<Player>(*it); 277 278 ContainerMenu *containerMenu = dynamic_cast<ContainerMenu*>(player->containerMenu); 279 if (containerMenu != NULL) 280 { 281 shared_ptr<Container> container = containerMenu->getContainer(); 282 shared_ptr<Container> thisContainer = dynamic_pointer_cast<Container>(shared_from_this()); 283 shared_ptr<CompoundContainer> compoundContainer = dynamic_pointer_cast<CompoundContainer>( container ); 284 if ( (container == thisContainer) || (compoundContainer != NULL && compoundContainer->contains(thisContainer)) ) 285 { 286 openCount++; 287 } 288 } 289 } 290 delete players; 291 } 292 293 oOpenness = openness; 294 295 float speed = 0.10f; 296 if (openCount > 0 && openness == 0) 297 { 298 if (n.lock() == NULL && w.lock() == NULL) 299 { 300 double xc = x + 0.5; 301 double zc = z + 0.5; 302 if (s.lock() != NULL) zc += 0.5; 303 if (e.lock() != NULL) xc += 0.5; 304 305 // 4J-PB - Seems the chest open volume is much louder than other sounds from user reports. We'll tone it down a bit 306 level->playSound(xc, y + 0.5, zc, eSoundType_RANDOM_CHEST_OPEN, 0.2f, level->random->nextFloat() * 0.1f + 0.9f); 307 } 308 } 309 if ((openCount == 0 && openness > 0) || (openCount > 0 && openness < 1)) 310 { 311 float oldOpen = openness; 312 if (openCount > 0) openness += speed; 313 else openness -= speed; 314 if (openness > 1) 315 { 316 openness = 1; 317 } 318 float lim = 0.5f; 319 if (openness < lim && oldOpen >= lim) 320 { 321 // Fix for #64546 - Customer Encountered: TU7: Chests placed by the Player are closing too fast. 322 //openness = 0; 323 if (n.lock() == NULL && w.lock() == NULL) 324 { 325 double xc = x + 0.5; 326 double zc = z + 0.5; 327 if (s.lock() != NULL) zc += 0.5; 328 if (e.lock() != NULL) xc += 0.5; 329 330 // 4J-PB - Seems the chest open volume is much louder than other sounds from user reports. We'll tone it down a bit 331 level->playSound(xc, y + 0.5, zc, eSoundType_RANDOM_CHEST_CLOSE, 0.2f, level->random->nextFloat() * 0.1f + 0.9f); 332 } 333 } 334 if (openness < 0) 335 { 336 openness = 0; 337 } 338 } 339 340} 341 342bool ChestTileEntity::triggerEvent(int b0, int b1) 343{ 344 if (b0 == ChestTile::EVENT_SET_OPEN_COUNT) 345 { 346 openCount = b1; 347 return true; 348 } 349 return TileEntity::triggerEvent(b0, b1); 350} 351 352void ChestTileEntity::startOpen() 353{ 354 if (openCount < 0) 355 { 356 openCount = 0; 357 } 358 openCount++; 359 level->tileEvent(x, y, z, getTile()->id, ChestTile::EVENT_SET_OPEN_COUNT, openCount); 360 level->updateNeighborsAt(x, y, z, getTile()->id); 361 level->updateNeighborsAt(x, y - 1, z, getTile()->id); 362} 363 364void ChestTileEntity::stopOpen() 365{ 366 if (getTile() == NULL || !( dynamic_cast<ChestTile *>( getTile() ) != NULL)) return; 367 openCount--; 368 level->tileEvent(x, y, z, getTile()->id, ChestTile::EVENT_SET_OPEN_COUNT, openCount); 369 level->updateNeighborsAt(x, y, z, getTile()->id); 370 level->updateNeighborsAt(x, y - 1, z, getTile()->id); 371} 372 373bool ChestTileEntity::canPlaceItem(int slot, shared_ptr<ItemInstance> item) 374{ 375 return true; 376} 377 378void ChestTileEntity::setRemoved() 379{ 380 TileEntity::setRemoved(); 381 clearCache(); 382 checkNeighbors(); 383} 384 385int ChestTileEntity::getType() 386{ 387 if (type == -1) 388 { 389 if (level != NULL && dynamic_cast<ChestTile *>( getTile() ) != NULL) 390 { 391 type = ((ChestTile *) getTile())->type; 392 } 393 else 394 { 395 return ChestTile::TYPE_BASIC; 396 } 397 } 398 399 return type; 400} 401 402// 4J Added 403shared_ptr<TileEntity> ChestTileEntity::clone() 404{ 405 shared_ptr<ChestTileEntity> result = shared_ptr<ChestTileEntity>( new ChestTileEntity() ); 406 TileEntity::clone(result); 407 408 for (unsigned int i = 0; i < items->length; i++) 409 { 410 if (items->data[i] != NULL) 411 { 412 result->items->data[i] = ItemInstance::clone(items->data[i]); 413 } 414 } 415 return result; 416}