the game where you go into mines and start crafting! but for consoles (forked directly from smartcmd's github)
at main 494 lines 12 kB view raw
1#include "stdafx.h" 2#include "com.mojang.nbt.h" 3#include "BrewingStandTileEntity.h" 4#include "SharedConstants.h" 5#include "net.minecraft.h" 6#include "net.minecraft.world.level.h" 7#include "net.minecraft.world.item.h" 8#include "net.minecraft.world.item.alchemy.h" 9 10int slotsForUp [] = { BrewingStandTileEntity::INGREDIENT_SLOT }; 11int slotsForOtherFaces [] = { 0, 1, 2 }; 12 13intArray BrewingStandTileEntity::SLOTS_FOR_UP = intArray(slotsForUp, 1); 14intArray BrewingStandTileEntity::SLOTS_FOR_OTHER_FACES = intArray(slotsForOtherFaces, 3); 15 16BrewingStandTileEntity::BrewingStandTileEntity() 17{ 18 brewTime = 0; 19 items = ItemInstanceArray(4); 20 name = L""; 21} 22 23BrewingStandTileEntity::~BrewingStandTileEntity() 24{ 25 delete [] items.data; 26} 27 28wstring BrewingStandTileEntity::getName() 29{ 30 return hasCustomName() ? name : app.GetString(IDS_TILE_BREWINGSTAND); 31} 32 33wstring BrewingStandTileEntity::getCustomName() 34{ 35 return hasCustomName() ? name : L""; 36} 37 38bool BrewingStandTileEntity::hasCustomName() 39{ 40 return !name.empty(); 41} 42 43void BrewingStandTileEntity::setCustomName(const wstring &name) 44{ 45 this->name = name; 46} 47 48unsigned int BrewingStandTileEntity::getContainerSize() 49{ 50 return items.length; 51} 52 53void BrewingStandTileEntity::tick() 54{ 55 if (brewTime > 0) 56 { 57 brewTime--; 58 59 if (brewTime == 0) 60 { 61 // apply ingredients to all potions 62 doBrew(); 63 setChanged(); 64 } 65 else if (!isBrewable()) 66 { 67 brewTime = 0; 68 setChanged(); 69 } 70 else if (ingredientId != items[INGREDIENT_SLOT]->id) 71 { 72 brewTime = 0; 73 setChanged(); 74 } 75 } 76 else if (isBrewable()) 77 { 78 brewTime = SharedConstants::TICKS_PER_SECOND * PotionBrewing::BREWING_TIME_SECONDS; 79 ingredientId = items[INGREDIENT_SLOT]->id; 80 } 81 82 int newCount = getPotionBits(); 83 if (newCount != lastPotionCount) 84 { 85 lastPotionCount = newCount; 86 level->setData(x, y, z, newCount, Tile::UPDATE_CLIENTS); 87 } 88 89 TileEntity::tick(); 90} 91 92int BrewingStandTileEntity::getBrewTime() 93{ 94 return brewTime; 95} 96 97bool BrewingStandTileEntity::isBrewable() 98{ 99 if (items[INGREDIENT_SLOT] == NULL || items[INGREDIENT_SLOT]->count <= 0) 100 { 101 return false; 102 } 103 shared_ptr<ItemInstance> ingredient = items[INGREDIENT_SLOT]; 104 if (PotionBrewing::SIMPLIFIED_BREWING) 105 { 106 if (!Item::items[ingredient->id]->hasPotionBrewingFormula()) 107 { 108 return false; 109 } 110 111 bool oneResult = false; 112 for (int dest = 0; dest < 3; dest++) 113 { 114 if (items[dest] != NULL && items[dest]->id == Item::potion_Id) 115 { 116 int currentBrew = items[dest]->getAuxValue(); 117 int newBrew = NORMALISE_POTION_AUXVAL( applyIngredient(currentBrew, ingredient) ); 118 119 if (!PotionItem::isThrowable(currentBrew) && PotionItem::isThrowable(newBrew)) 120 { 121 oneResult = true; 122 break; 123 } 124 125 vector<MobEffectInstance *> *currentEffects = Item::potion->getMobEffects(currentBrew); 126 vector<MobEffectInstance *> *newEffects = Item::potion->getMobEffects(newBrew); 127 128 // 4J - this code replaces an expression "currentEffects.equals(newEffects)" in the java. 129 // TODO - find out whether actually checking pointers to MobEffectInstance classes for equality 130 // is of any use 131 bool equals = false; 132 if( ( currentEffects != NULL ) && ( newEffects != NULL ) ) 133 { 134 if( currentEffects->size() == newEffects->size() ) 135 { 136 if( std::equal(currentEffects->begin(), currentEffects->end(), newEffects->begin() ) ) 137 { 138 equals = true; 139 } 140 } 141 } 142 143 if ((currentBrew > 0 && currentEffects == newEffects) || 144 (currentEffects != NULL && (equals || newEffects == NULL))) 145 { 146 } 147 else if (currentBrew != newBrew) 148 { 149 oneResult = true; 150 break; 151 } 152 } 153 } 154 return oneResult; 155 156 } 157 else 158 { 159 if (!Item::items[ingredient->id]->hasPotionBrewingFormula() && ingredient->id != Item::bucket_water_Id && ingredient->id != Item::netherwart_seeds_Id) 160 { 161 return false; 162 } 163 bool isWater = ingredient->id == Item::bucket_water_Id; 164 165 // at least one destination potion must have a result 166 bool oneResult = false; 167 for (int dest = 0; dest < 3; dest++) 168 { 169 if (items[dest] != NULL && items[dest]->id == Item::potion_Id) 170 { 171 int currentBrew = items[dest]->getAuxValue(); 172 int newBrew = NORMALISE_POTION_AUXVAL( applyIngredient(currentBrew, ingredient) ); 173 if (currentBrew != newBrew) 174 { 175 oneResult = true; 176 break; 177 } 178 } 179 else if (isWater && items[dest] != NULL && items[dest]->id == Item::glassBottle_Id) 180 { 181 oneResult = true; 182 break; 183 } 184 } 185 return oneResult; 186 } 187} 188 189void BrewingStandTileEntity::doBrew() 190{ 191 if (!isBrewable()) 192 { 193 return; 194 } 195 196 shared_ptr<ItemInstance> ingredient = items[INGREDIENT_SLOT]; 197 198 if (PotionBrewing::SIMPLIFIED_BREWING) 199 { 200 for (int dest = 0; dest < 3; dest++) 201 { 202 if (items[dest] != NULL && items[dest]->id == Item::potion_Id) 203 { 204 int currentBrew = items[dest]->getAuxValue(); 205 int newBrew = NORMALISE_POTION_AUXVAL( applyIngredient(currentBrew, ingredient) ); 206 207 vector<MobEffectInstance *> *currentEffects = Item::potion->getMobEffects(currentBrew); 208 vector<MobEffectInstance *> *newEffects = Item::potion->getMobEffects(newBrew); 209 210 // 4J - this code replaces an expression "currentEffects.equals(newEffects)" in the java. 211 // TODO - find out whether actually checking pointers to MobEffectInstance classes for equality 212 // is of any use 213 bool equals = false; 214 if( ( currentEffects != NULL ) && ( newEffects != NULL ) ) 215 { 216 if( currentEffects->size() == newEffects->size() ) 217 { 218 if( std::equal(currentEffects->begin(), currentEffects->end(), newEffects->begin() ) ) 219 { 220 equals = true; 221 } 222 } 223 } 224 225 if ((currentBrew > 0 && currentEffects == newEffects) || 226 (currentEffects != NULL && (equals || newEffects == NULL))) 227 { 228 if (!PotionItem::isThrowable(currentBrew) && PotionItem::isThrowable(newBrew)) 229 { 230 items[dest]->setAuxValue(newBrew); 231 } 232 233 } 234 else if (currentBrew != newBrew) 235 { 236 items[dest]->setAuxValue(newBrew); 237 } 238 239 } 240 } 241 242 } 243 else 244 { 245 bool isWater = ingredient->id == Item::bucket_water_Id; 246 247 for (int dest = 0; dest < 3; dest++) 248 { 249 if (items[dest] != NULL && items[dest]->id == Item::potion_Id) 250 { 251 int currentBrew = items[dest]->getAuxValue(); 252 int newBrew = NORMALISE_POTION_AUXVAL( applyIngredient(currentBrew, ingredient) ); 253 items[dest]->setAuxValue(newBrew); 254 } 255 else if (isWater && items[dest] != NULL && items[dest]->id == Item::glassBottle_Id) 256 { 257 items[dest] = shared_ptr<ItemInstance>(new ItemInstance(Item::potion)); 258 } 259 } 260 } 261 262 if (Item::items[ingredient->id]->hasCraftingRemainingItem()) 263 { 264 items[INGREDIENT_SLOT] = shared_ptr<ItemInstance>(new ItemInstance(Item::items[ingredient->id]->getCraftingRemainingItem())); 265 } 266 else 267 { 268 items[INGREDIENT_SLOT]->count--; 269 if (items[INGREDIENT_SLOT]->count <= 0) 270 { 271 items[INGREDIENT_SLOT] = nullptr; 272 } 273 } 274} 275 276int BrewingStandTileEntity::applyIngredient(int currentBrew, shared_ptr<ItemInstance> ingredient) 277{ 278 if (ingredient == NULL) 279 { 280 return currentBrew; 281 } 282 if (!PotionBrewing::SIMPLIFIED_BREWING) 283 { 284#if !(_SIMPLIFIED_BREWING) 285 // 4J Stu - SIMPLIFIED_BREWING is on, so we never use this 286 if (ingredient->id == Item::bucket_water_Id) 287 { 288 return PotionBrewing::applyBrew(currentBrew, PotionBrewing::MOD_WATER); 289 } 290 if (ingredient->id == Item::netherwart_seeds_Id) 291 { 292 return PotionBrewing::stirr(currentBrew); 293 } 294#endif 295 } 296 if (Item::items[ingredient->id]->hasPotionBrewingFormula()) 297 { 298 return PotionBrewing::applyBrew(currentBrew, Item::items[ingredient->id]->getPotionBrewingFormula()); 299 } 300 return currentBrew; 301} 302 303void BrewingStandTileEntity::load(CompoundTag *base) 304{ 305 TileEntity::load(base); 306 307 ListTag<CompoundTag> *inventoryList = (ListTag<CompoundTag> *) base->getList(L"Items"); 308 delete [] items.data; 309 items = ItemInstanceArray(getContainerSize()); 310 for (int i = 0; i < inventoryList->size(); i++) 311 { 312 CompoundTag *tag = inventoryList->get(i); 313 int slot = tag->getByte(L"Slot"); 314 if (slot >= 0 && slot < items.length) items[slot] = ItemInstance::fromTag(tag); 315 } 316 317 brewTime = base->getShort(L"BrewTime"); 318 if (base->contains(L"CustomName")) name = base->getString(L"CustomName"); 319} 320 321void BrewingStandTileEntity::save(CompoundTag *base) 322{ 323 TileEntity::save(base); 324 325 base->putShort(L"BrewTime", (short) (brewTime)); 326 ListTag<CompoundTag> *listTag = new ListTag<CompoundTag>(); 327 328 for (int i = 0; i < items.length; i++) 329 { 330 if (items[i] != NULL) 331 { 332 CompoundTag *tag = new CompoundTag(); 333 tag->putByte(L"Slot", (byte) i); 334 items[i]->save(tag); 335 listTag->add(tag); 336 } 337 } 338 base->put(L"Items", listTag); 339 if (hasCustomName()) base->putString(L"CustomName", name); 340} 341 342shared_ptr<ItemInstance> BrewingStandTileEntity::getItem(unsigned int slot) 343{ 344 if (slot >= 0 && slot < items.length) 345 { 346 return items[slot]; 347 } 348 return nullptr; 349} 350 351shared_ptr<ItemInstance> BrewingStandTileEntity::removeItem(unsigned int slot, int count) 352{ 353 // 4J Stu - Changed the implementation of this function to be the same as ChestTileEntity to enable the "Pickup Half" 354 // option on the ingredients slot 355 // Fix for #65373 - TU8: Content: UI: Command "Take Half" in the Brewing Stand interface doesn't work as intended. 356 357 if (slot >= 0 && slot < items.length && items[slot] != NULL) 358 { 359 if (items[slot]->count <= count) 360 { 361 shared_ptr<ItemInstance> item = items[slot]; 362 items[slot] = nullptr; 363 this->setChanged(); 364 // 4J Stu - Fix for duplication glitch 365 if(item->count <= 0) return nullptr; 366 return item; 367 } 368 else 369 { 370 shared_ptr<ItemInstance> i = items[slot]->remove(count); 371 if (items[slot]->count == 0) items[slot] = nullptr; 372 this->setChanged(); 373 // 4J Stu - Fix for duplication glitch 374 if(i->count <= 0) return nullptr; 375 return i; 376 } 377 } 378 return nullptr; 379} 380 381shared_ptr<ItemInstance> BrewingStandTileEntity::removeItemNoUpdate(int slot) 382{ 383 if (slot >= 0 && slot < items.length) 384 { 385 shared_ptr<ItemInstance> item = items[slot]; 386 items[slot] = nullptr; 387 return item; 388 } 389 return nullptr; 390} 391 392void BrewingStandTileEntity::setItem(unsigned int slot, shared_ptr<ItemInstance> item) 393{ 394 if (slot >= 0 && slot < items.length) 395 { 396 items[slot] = item; 397 } 398} 399 400int BrewingStandTileEntity::getMaxStackSize() const 401{ 402 // this value is not used for the potion slots 403 return 64; 404} 405 406bool BrewingStandTileEntity::stillValid(shared_ptr<Player> player) 407{ 408 if (level->getTileEntity(x, y, z) != shared_from_this()) return false; 409 if (player->distanceToSqr(x + 0.5, y + 0.5, z + 0.5) > 8 * 8) return false; 410 return true; 411} 412 413void BrewingStandTileEntity::startOpen() 414{ 415} 416 417void BrewingStandTileEntity::stopOpen() 418{ 419} 420 421bool BrewingStandTileEntity::canPlaceItem(int slot, shared_ptr<ItemInstance> item) 422{ 423 if (slot == INGREDIENT_SLOT) 424 { 425 if (PotionBrewing::SIMPLIFIED_BREWING) 426 { 427 return Item::items[item->id]->hasPotionBrewingFormula(); 428 } 429 else 430 { 431 return Item::items[item->id]->hasPotionBrewingFormula() || item->id == Item::netherwart_seeds_Id || item->id == Item::bucket_water_Id; 432 } 433 } 434 435 return item->id == Item::potion_Id || item->id == Item::glassBottle_Id; 436} 437 438void BrewingStandTileEntity::setBrewTime(int value) 439{ 440 brewTime = value; 441} 442 443int BrewingStandTileEntity::getPotionBits() 444{ 445 int newCount = 0; 446 for (int potion = 0; potion < 3; potion++) 447 { 448 if (items[potion] != NULL) 449 { 450 newCount |= (1 << potion); 451 } 452 } 453 return newCount; 454} 455 456intArray BrewingStandTileEntity::getSlotsForFace(int face) 457{ 458 if (face == Facing::UP) 459 { 460 return SLOTS_FOR_UP; 461 } 462 463 return SLOTS_FOR_OTHER_FACES; 464} 465 466bool BrewingStandTileEntity::canPlaceItemThroughFace(int slot, shared_ptr<ItemInstance> item, int face) 467{ 468 return canPlaceItem(slot, item); 469} 470 471bool BrewingStandTileEntity::canTakeItemThroughFace(int slot, shared_ptr<ItemInstance> item, int face) 472{ 473 return true; 474} 475 476// 4J Added 477shared_ptr<TileEntity> BrewingStandTileEntity::clone() 478{ 479 shared_ptr<BrewingStandTileEntity> result = shared_ptr<BrewingStandTileEntity>( new BrewingStandTileEntity() ); 480 TileEntity::clone(result); 481 482 result->brewTime = brewTime; 483 result->lastPotionCount = lastPotionCount; 484 result->ingredientId = ingredientId; 485 486 for (unsigned int i = 0; i < items.length; i++) 487 { 488 if (items.data[i] != NULL) 489 { 490 result->items.data[i] = ItemInstance::clone(items.data[i]); 491 } 492 } 493 return result; 494}