the game where you go into mines and start crafting! but for consoles (forked directly from smartcmd's github)
at main 505 lines 12 kB view raw
1#include "stdafx.h" 2#include "net.minecraft.h" 3#include "net.minecraft.world.entity.h" 4#include "net.minecraft.world.entity.item.h" 5#include "net.minecraft.world.entity.player.h" 6#include "net.minecraft.world.level.h" 7#include "net.minecraft.world.level.tile.h" 8#include "net.minecraft.world.level.tile.entity.h" 9#include "net.minecraft.world.phys.h" 10#include "net.minecraft.world.h" 11#include "HopperTileEntity.h" 12 13HopperTileEntity::HopperTileEntity() 14{ 15 items = ItemInstanceArray(5); 16 name = L""; 17 cooldownTime = -1; 18} 19 20HopperTileEntity::~HopperTileEntity() 21{ 22 delete [] items.data; 23} 24 25void HopperTileEntity::load(CompoundTag *base) 26{ 27 TileEntity::load(base); 28 29 ListTag<CompoundTag> *inventoryList = (ListTag<CompoundTag> *) base->getList(L"Items"); 30 delete[] items.data; 31 items = ItemInstanceArray(getContainerSize()); 32 if (base->contains(L"CustomName")) name = base->getString(L"CustomName"); 33 cooldownTime = base->getInt(L"TransferCooldown"); 34 for (int i = 0; i < inventoryList->size(); i++) 35 { 36 CompoundTag *tag = inventoryList->get(i); 37 int slot = tag->getByte(L"Slot"); 38 if (slot >= 0 && slot < items.length) items[slot] = ItemInstance::fromTag(tag); 39 } 40} 41 42void HopperTileEntity::save(CompoundTag *base) 43{ 44 TileEntity::save(base); 45 ListTag<CompoundTag> *listTag = new ListTag<CompoundTag>(); 46 47 for (int i = 0; i < items.length; i++) 48 { 49 if (items[i] != NULL) 50 { 51 CompoundTag *tag = new CompoundTag(); 52 tag->putByte(L"Slot", (byte) i); 53 items[i]->save(tag); 54 listTag->add(tag); 55 } 56 } 57 base->put(L"Items", listTag); 58 base->putInt(L"TransferCooldown", cooldownTime); 59 if (hasCustomName()) base->putString(L"CustomName", name); 60} 61 62void HopperTileEntity::setChanged() 63{ 64 TileEntity::setChanged(); 65} 66 67unsigned int HopperTileEntity::getContainerSize() 68{ 69 return items.length; 70} 71 72shared_ptr<ItemInstance> HopperTileEntity::getItem(unsigned int slot) 73{ 74 return items[slot]; 75} 76 77shared_ptr<ItemInstance> HopperTileEntity::removeItem(unsigned int slot, int count) 78{ 79 if (items[slot] != NULL) 80 { 81 if (items[slot]->count <= count) 82 { 83 shared_ptr<ItemInstance> item = items[slot]; 84 items[slot] = nullptr; 85 return item; 86 } 87 else 88 { 89 shared_ptr<ItemInstance> i = items[slot]->remove(count); 90 if (items[slot]->count == 0) items[slot] = nullptr; 91 return i; 92 } 93 } 94 return nullptr; 95} 96 97shared_ptr<ItemInstance> HopperTileEntity::removeItemNoUpdate(int slot) 98{ 99 if (items[slot] != NULL) 100 { 101 shared_ptr<ItemInstance> item = items[slot]; 102 items[slot] = nullptr; 103 return item; 104 } 105 return nullptr; 106} 107 108void HopperTileEntity::setItem(unsigned int slot, shared_ptr<ItemInstance> item) 109{ 110 items[slot] = item; 111 if (item != NULL && item->count > getMaxStackSize()) item->count = getMaxStackSize(); 112} 113 114wstring HopperTileEntity::getName() 115{ 116 return hasCustomName() ? name : app.GetString(IDS_CONTAINER_HOPPER); 117} 118 119wstring HopperTileEntity::getCustomName() 120{ 121 return hasCustomName() ? name : L""; 122} 123 124bool HopperTileEntity::hasCustomName() 125{ 126 return !name.empty(); 127} 128 129void HopperTileEntity::setCustomName(const wstring &name) 130{ 131 this->name = name; 132} 133 134int HopperTileEntity::getMaxStackSize() const 135{ 136 return Container::LARGE_MAX_STACK_SIZE; 137} 138 139bool HopperTileEntity::stillValid(shared_ptr<Player> player) 140{ 141 if (level->getTileEntity(x, y, z) != shared_from_this()) return false; 142 if (player->distanceToSqr(x + 0.5, y + 0.5, z + 0.5) > 8 * 8) return false; 143 return true; 144} 145 146void HopperTileEntity::startOpen() 147{ 148} 149 150void HopperTileEntity::stopOpen() 151{ 152} 153 154bool HopperTileEntity::canPlaceItem(int slot, shared_ptr<ItemInstance> item) 155{ 156 return true; 157} 158 159void HopperTileEntity::tick() 160{ 161 if (level == NULL || level->isClientSide) return; 162 163 cooldownTime--; 164 165 if (!isOnCooldown()) 166 { 167 setCooldown(0); 168 tryMoveItems(); 169 } 170} 171 172bool HopperTileEntity::tryMoveItems() 173{ 174 if (level == NULL || level->isClientSide) return false; 175 176 if (!isOnCooldown() && HopperTile::isTurnedOn(getData())) 177 { 178 bool changed = ejectItems(); 179 changed = suckInItems(this) || changed; 180 181 if (changed) 182 { 183 setCooldown(MOVE_ITEM_SPEED); 184 setChanged(); 185 return true; 186 } 187 } 188 189 return false; 190} 191 192bool HopperTileEntity::ejectItems() 193{ 194 shared_ptr<Container> container = getAttachedContainer(); 195 if (container == NULL) 196 { 197 return false; 198 } 199 200 for (int slot = 0; slot < getContainerSize(); slot++) 201 { 202 if (getItem(slot) == NULL) continue; 203 204 shared_ptr<ItemInstance> original = getItem(slot)->copy(); 205 shared_ptr<ItemInstance> result = addItem(container.get(), removeItem(slot, 1), Facing::OPPOSITE_FACING[HopperTile::getAttachedFace(getData())]); 206 207 if (result == NULL || result->count == 0) 208 { 209 container->setChanged(); 210 return true; 211 } 212 else 213 { 214 setItem(slot, original); 215 } 216 } 217 218 return false; 219} 220 221bool HopperTileEntity::suckInItems(Hopper *hopper) 222{ 223 shared_ptr<Container> container = getSourceContainer(hopper); 224 225 if (container != NULL) 226 { 227 int face = Facing::DOWN; 228 229 shared_ptr<WorldlyContainer> worldly = dynamic_pointer_cast<WorldlyContainer>(container); 230 if ( (worldly != NULL) && (face > -1) ) 231 { 232 intArray slots = worldly->getSlotsForFace(face); 233 234 for (int i = 0; i < slots.length; i++) 235 { 236 if (tryTakeInItemFromSlot(hopper, container.get(), slots[i], face)) return true; 237 } 238 } 239 else 240 { 241 int size = container->getContainerSize(); 242 for (int i = 0; i < size; i++) 243 { 244 if (tryTakeInItemFromSlot(hopper, container.get(), i, face)) return true; 245 } 246 } 247 } 248 else 249 { 250 shared_ptr<ItemEntity> above = getItemAt(hopper->getLevel(), hopper->getLevelX(), hopper->getLevelY() + 1, hopper->getLevelZ()); 251 252 if (above != NULL) 253 { 254 return addItem(hopper, above); 255 } 256 } 257 258 return false; 259} 260 261bool HopperTileEntity::tryTakeInItemFromSlot(Hopper *hopper, Container *container, int slot, int face) 262{ 263 shared_ptr<ItemInstance> item = container->getItem(slot); 264 265 if (item != NULL && canTakeItemFromContainer(container, item, slot, face)) 266 { 267 shared_ptr<ItemInstance> original = item->copy(); 268 shared_ptr<ItemInstance> result = addItem(hopper, container->removeItem(slot, 1), -1); 269 270 if (result == NULL || result->count == 0) 271 { 272 container->setChanged(); 273 return true; 274 } 275 else 276 { 277 container->setItem(slot, original); 278 } 279 } 280 281 return false; 282} 283 284bool HopperTileEntity::addItem(Container *container, shared_ptr<ItemEntity> item) 285{ 286 bool changed = false; 287 if (item == NULL) return false; 288 289 shared_ptr<ItemInstance> copy = item->getItem()->copy(); 290 shared_ptr<ItemInstance> result = addItem(container, copy, -1); 291 292 if (result == NULL || result->count == 0) 293 { 294 changed = true; 295 296 item->remove(); 297 } 298 else 299 { 300 item->setItem(result); 301 } 302 303 return changed; 304} 305 306shared_ptr<ItemInstance> HopperTileEntity::addItem(Container *container, shared_ptr<ItemInstance> item, int face) 307{ 308 if (dynamic_cast<WorldlyContainer *>( container ) != NULL && face > -1) 309 { 310 WorldlyContainer *worldly = (WorldlyContainer *) container; 311 intArray slots = worldly->getSlotsForFace(face); 312 313 for (int i = 0; i < slots.length && item != NULL && item->count > 0; i++) 314 { 315 item = tryMoveInItem(container, item, slots[i], face); 316 } 317 } 318 else 319 { 320 int size = container->getContainerSize(); 321 for (int i = 0; i < size && item != NULL && item->count > 0; i++) 322 { 323 item = tryMoveInItem(container, item, i, face); 324 } 325 } 326 327 if (item != NULL && item->count == 0) 328 { 329 item = nullptr; 330 } 331 332 return item; 333} 334 335bool HopperTileEntity::canPlaceItemInContainer(Container *container, shared_ptr<ItemInstance> item, int slot, int face) 336{ 337 if (!container->canPlaceItem(slot, item)) return false; 338 if ( dynamic_cast<WorldlyContainer *>( container ) != NULL && !dynamic_cast<WorldlyContainer *>( container )->canPlaceItemThroughFace(slot, item, face)) return false; 339 return true; 340} 341 342bool HopperTileEntity::canTakeItemFromContainer(Container *container, shared_ptr<ItemInstance> item, int slot, int face) 343{ 344 if (dynamic_cast<WorldlyContainer *>( container ) != NULL && !dynamic_cast<WorldlyContainer *>( container )->canTakeItemThroughFace(slot, item, face)) return false; 345 return true; 346} 347 348shared_ptr<ItemInstance> HopperTileEntity::tryMoveInItem(Container *container, shared_ptr<ItemInstance> item, int slot, int face) 349{ 350 shared_ptr<ItemInstance> current = container->getItem(slot); 351 352 if (canPlaceItemInContainer(container, item, slot, face)) 353 { 354 bool success = false; 355 if (current == NULL) 356 { 357 container->setItem(slot, item); 358 item = nullptr; 359 success = true; 360 } 361 else if (canMergeItems(current, item)) 362 { 363 int space = item->getMaxStackSize() - current->count; 364 int count = min(item->count, space); 365 366 item->count -= count; 367 current->count += count; 368 success = count > 0; 369 } 370 if (success) 371 { 372 HopperTileEntity *hopper = dynamic_cast<HopperTileEntity *>(container); 373 if (hopper != NULL) 374 { 375 hopper->setCooldown(MOVE_ITEM_SPEED); 376 container->setChanged(); 377 } 378 container->setChanged(); 379 } 380 } 381 return item; 382} 383 384shared_ptr<Container> HopperTileEntity::getAttachedContainer() 385{ 386 int face = HopperTile::getAttachedFace(getData()); 387 return getContainerAt(getLevel(), x + Facing::STEP_X[face], y + Facing::STEP_Y[face], z + Facing::STEP_Z[face]); 388} 389 390shared_ptr<Container> HopperTileEntity::getSourceContainer(Hopper *hopper) 391{ 392 return getContainerAt(hopper->getLevel(), hopper->getLevelX(), hopper->getLevelY() + 1, hopper->getLevelZ()); 393} 394 395shared_ptr<ItemEntity> HopperTileEntity::getItemAt(Level *level, double xt, double yt, double zt) 396{ 397 vector<shared_ptr<Entity> > *entities = level->getEntitiesOfClass(typeid(ItemEntity), AABB::newTemp(xt, yt, zt, xt + 1, yt + 1, zt + 1), EntitySelector::ENTITY_STILL_ALIVE); 398 399 if (entities->size() > 0) 400 { 401 shared_ptr<ItemEntity> out = dynamic_pointer_cast<ItemEntity>( entities->at(0) ); 402 delete entities; 403 return out; 404 } 405 else 406 { 407 delete entities; 408 return nullptr; 409 } 410} 411 412shared_ptr<Container> HopperTileEntity::getContainerAt(Level *level, double x, double y, double z) 413{ 414 shared_ptr<Container> result = nullptr; 415 416 int xt = Mth::floor(x); 417 int yt = Mth::floor(y); 418 int zt = Mth::floor(z); 419 420 shared_ptr<TileEntity> entity = level->getTileEntity(xt, yt, zt); 421 422 result = dynamic_pointer_cast<Container>(entity); 423 if (result != NULL) 424 { 425 if ( dynamic_pointer_cast<ChestTileEntity>(result) != NULL ) 426 { 427 int id = level->getTile(xt, yt, zt); 428 Tile *tile = Tile::tiles[id]; 429 430 if ( dynamic_cast<ChestTile *>( tile ) != NULL ) 431 { 432 result = ((ChestTile *) tile)->getContainer(level, xt, yt, zt); 433 } 434 } 435 } 436 437 if (result == NULL) 438 { 439 vector<shared_ptr<Entity> > *entities = level->getEntities(nullptr, AABB::newTemp(x, y, z, x + 1, y + 1, z + 1), EntitySelector::CONTAINER_ENTITY_SELECTOR); 440 441 if ( (entities != NULL) && (entities->size() > 0) ) 442 { 443 result = dynamic_pointer_cast<Container>( entities->at( level->random->nextInt(entities->size()) ) ); 444 } 445 } 446 447 return result; 448} 449 450bool HopperTileEntity::canMergeItems(shared_ptr<ItemInstance> a, shared_ptr<ItemInstance> b) 451{ 452 if (a->id != b->id) return false; 453 if (a->getAuxValue() != b->getAuxValue()) return false; 454 if (a->count > a->getMaxStackSize()) return false; 455 if (!ItemInstance::tagMatches(a, b)) return false; 456 return true; 457} 458 459Level *HopperTileEntity::getLevel() 460{ 461 return TileEntity::getLevel(); 462} 463 464double HopperTileEntity::getLevelX() 465{ 466 return x; 467} 468 469double HopperTileEntity::getLevelY() 470{ 471 return y; 472} 473 474double HopperTileEntity::getLevelZ() 475{ 476 return z; 477} 478 479void HopperTileEntity::setCooldown(int time) 480{ 481 cooldownTime = time; 482} 483 484bool HopperTileEntity::isOnCooldown() 485{ 486 return cooldownTime > 0; 487} 488 489// 4J Added 490shared_ptr<TileEntity> HopperTileEntity::clone() 491{ 492 shared_ptr<HopperTileEntity> result = shared_ptr<HopperTileEntity>( new HopperTileEntity() ); 493 TileEntity::clone(result); 494 495 result->name = name; 496 result->cooldownTime = cooldownTime; 497 for (unsigned int i = 0; i < items.length; i++) 498 { 499 if (items[i] != NULL) 500 { 501 result->items[i] = ItemInstance::clone(items[i]); 502 } 503 } 504 return result; 505}