the game where you go into mines and start crafting! but for consoles (forked directly from smartcmd's github)
at main 422 lines 13 kB view raw
1#include "stdafx.h" 2#include "net.minecraft.world.item.h" 3#include "net.minecraft.world.item.alchemy.h" 4#include "net.minecraft.world.effect.h" 5#include "net.minecraft.world.level.h" 6#include "net.minecraft.world.entity.ai.attributes.h" 7#include "net.minecraft.world.entity.player.h" 8#include "net.minecraft.world.entity.projectile.h" 9#include "net.minecraft.world.h" 10#include "MobEffectInstance.h" 11#include "StringHelpers.h" 12#include "SharedConstants.h" 13#include "PotionItem.h" 14#include "SoundTypes.h" 15 16const wstring PotionItem::DEFAULT_ICON = L"potion"; 17const wstring PotionItem::THROWABLE_ICON = L"potion_splash"; 18const wstring PotionItem::CONTENTS_ICON = L"potion_contents"; 19 20// 4J Added 21vector<pair<int, int> > PotionItem::s_uniquePotionValues; 22 23PotionItem::PotionItem(int id) : Item(id) 24{ 25 setMaxStackSize(1); 26 setStackedByData(true); 27 setMaxDamage(0); 28 29 iconThrowable = NULL; 30 iconDrinkable = NULL; 31 iconOverlay = NULL; 32} 33 34vector<MobEffectInstance *> *PotionItem::getMobEffects(shared_ptr<ItemInstance> potion) 35{ 36 if (!potion->hasTag() || !potion->getTag()->contains(L"CustomPotionEffects")) 37 { 38 vector<MobEffectInstance *> *effects = NULL; 39 AUTO_VAR(it, cachedMobEffects.find(potion->getAuxValue())); 40 if(it != cachedMobEffects.end()) effects = it->second; 41 if (effects == NULL) 42 { 43 effects = PotionBrewing::getEffects(potion->getAuxValue(), false); 44 cachedMobEffects[potion->getAuxValue()] = effects; 45 } 46 47 // Result should be a new (unmanaged) vector, so create a new one 48 return effects == NULL ? NULL : new vector<MobEffectInstance *>(*effects); 49 } 50 else 51 { 52 vector<MobEffectInstance *> *effects = new vector<MobEffectInstance *>(); 53 ListTag<CompoundTag> *customList = (ListTag<CompoundTag> *) potion->getTag()->getList(L"CustomPotionEffects"); 54 55 for (int i = 0; i < customList->size(); i++) 56 { 57 CompoundTag *tag = customList->get(i); 58 effects->push_back(MobEffectInstance::load(tag)); 59 } 60 61 return effects; 62 } 63} 64 65vector<MobEffectInstance *> *PotionItem::getMobEffects(int auxValue) 66{ 67 vector<MobEffectInstance *> *effects = NULL; 68 AUTO_VAR(it, cachedMobEffects.find(auxValue)); 69 if(it != cachedMobEffects.end()) effects = it->second; 70 if (effects == NULL) 71 { 72 effects = PotionBrewing::getEffects(auxValue, false); 73 if(effects != NULL) cachedMobEffects.insert( std::pair<int, vector<MobEffectInstance *> *>(auxValue, effects) ); 74 } 75 return effects; 76} 77 78shared_ptr<ItemInstance> PotionItem::useTimeDepleted(shared_ptr<ItemInstance> instance, Level *level, shared_ptr<Player> player) 79{ 80 if (!player->abilities.instabuild) instance->count--; 81 82 if (!level->isClientSide) 83 { 84 vector<MobEffectInstance *> *effects = getMobEffects(instance); 85 if (effects != NULL) 86 { 87 //for (MobEffectInstance effect : effects) 88 for(AUTO_VAR(it, effects->begin()); it != effects->end(); ++it) 89 { 90 player->addEffect(new MobEffectInstance(*it)); 91 } 92 } 93 } 94 if (!player->abilities.instabuild) 95 { 96 if (instance->count <= 0) 97 { 98 return shared_ptr<ItemInstance>( new ItemInstance(Item::glassBottle) ); 99 } 100 else 101 { 102 player->inventory->add( shared_ptr<ItemInstance>( new ItemInstance(Item::glassBottle) ) ); 103 } 104 } 105 106 return instance; 107} 108 109int PotionItem::getUseDuration(shared_ptr<ItemInstance> itemInstance) 110{ 111 return DRINK_DURATION; 112} 113 114UseAnim PotionItem::getUseAnimation(shared_ptr<ItemInstance> itemInstance) 115{ 116 return UseAnim_drink; 117} 118 119bool PotionItem::TestUse(shared_ptr<ItemInstance> itemInstance, Level *level, shared_ptr<Player> player) 120{ 121 return true; 122} 123 124shared_ptr<ItemInstance> PotionItem::use(shared_ptr<ItemInstance> instance, Level *level, shared_ptr<Player> player) 125{ 126 if (isThrowable(instance->getAuxValue())) 127 { 128 if (!player->abilities.instabuild) instance->count--; 129 level->playEntitySound(player, eSoundType_RANDOM_BOW, 0.5f, 0.4f / (random->nextFloat() * 0.4f + 0.8f)); 130 if (!level->isClientSide) level->addEntity(shared_ptr<ThrownPotion>( new ThrownPotion(level, player, instance->getAuxValue()) )); 131 return instance; 132 } 133 player->startUsingItem(instance, getUseDuration(instance)); 134 return instance; 135} 136 137bool PotionItem::useOn(shared_ptr<ItemInstance> itemInstance, shared_ptr<Player> player, Level *level, int x, int y, int z, int face, float clickX, float clickY, float clickZ, bool bTestUseOnOnly) 138{ 139 return false; 140} 141 142Icon *PotionItem::getIcon(int auxValue) 143{ 144 if (isThrowable(auxValue)) 145 { 146 return iconThrowable; 147 } 148 return iconDrinkable; 149} 150 151Icon *PotionItem::getLayerIcon(int auxValue, int spriteLayer) 152{ 153 if (spriteLayer == 0) 154 { 155 return iconOverlay; 156 } 157 return Item::getLayerIcon(auxValue, spriteLayer); 158} 159 160bool PotionItem::isThrowable(int auxValue) 161{ 162 return ((auxValue & PotionBrewing::THROWABLE_MASK) != 0); 163} 164 165int PotionItem::getColor(int data) 166{ 167 return PotionBrewing::getColorValue(data, false); 168} 169 170int PotionItem::getColor(shared_ptr<ItemInstance> item, int spriteLayer) 171{ 172 if (spriteLayer > 0) 173 { 174 return 0xffffff; 175 } 176 return PotionBrewing::getColorValue(item->getAuxValue(), false); 177} 178 179bool PotionItem::hasMultipleSpriteLayers() 180{ 181 return true; 182} 183 184bool PotionItem::hasInstantenousEffects(int itemAuxValue) 185{ 186 vector<MobEffectInstance *> *mobEffects = getMobEffects(itemAuxValue); 187 if (mobEffects == NULL || mobEffects->empty()) 188 { 189 return false; 190 } 191 //for (MobEffectInstance effect : mobEffects) { 192 for(AUTO_VAR(it, mobEffects->begin()); it != mobEffects->end(); ++it) 193 { 194 MobEffectInstance *effect = *it; 195 if (MobEffect::effects[effect->getId()]->isInstantenous()) 196 { 197 return true; 198 } 199 } 200 return false; 201} 202 203wstring PotionItem::getHoverName(shared_ptr<ItemInstance> itemInstance) 204{ 205 if (itemInstance->getAuxValue() == 0) 206 { 207 return app.GetString(IDS_ITEM_WATER_BOTTLE); // I18n.get("item.emptyPotion.name").trim(); 208 } 209 210 wstring elementName = Item::getHoverName(itemInstance); 211 if (isThrowable(itemInstance->getAuxValue())) 212 { 213 //elementName = I18n.get("potion.prefix.grenade").trim() + " " + elementName; 214 elementName = replaceAll(elementName,L"{*splash*}",app.GetString(IDS_POTION_PREFIX_GRENADE)); 215 } 216 else 217 { 218 elementName = replaceAll(elementName,L"{*splash*}",L""); 219 } 220 221 vector<MobEffectInstance *> *effects = ((PotionItem *) Item::potion)->getMobEffects(itemInstance); 222 if (effects != NULL && !effects->empty()) 223 { 224 //String postfixString = effects.get(0).getDescriptionId(); 225 //postfixString += ".postfix"; 226 //return elementName + " " + I18n.get(postfixString).trim(); 227 228 elementName = replaceAll(elementName,L"{*prefix*}",L""); 229 elementName = replaceAll(elementName,L"{*postfix*}",app.GetString(effects->at(0)->getPostfixDescriptionId())); 230 } 231 else 232 { 233 //String appearanceName = PotionBrewing.getAppearanceName(itemInstance.getAuxValue()); 234 //return I18n.get(appearanceName).trim() + " " + elementName; 235 236 elementName = replaceAll(elementName,L"{*prefix*}",app.GetString( PotionBrewing::getAppearanceName(itemInstance->getAuxValue()))); 237 elementName = replaceAll(elementName,L"{*postfix*}",L""); 238 } 239 return elementName; 240} 241 242void PotionItem::appendHoverText(shared_ptr<ItemInstance> itemInstance, shared_ptr<Player> player, vector<HtmlString> *lines, bool advanced) 243{ 244 if (itemInstance->getAuxValue() == 0) 245 { 246 return; 247 } 248 vector<MobEffectInstance *> *effects = ((PotionItem *) Item::potion)->getMobEffects(itemInstance); 249 attrAttrModMap modifiers; 250 if (effects != NULL && !effects->empty()) 251 { 252 //for (MobEffectInstance effect : effects) 253 for(AUTO_VAR(it, effects->begin()); it != effects->end(); ++it) 254 { 255 MobEffectInstance *effect = *it; 256 wstring effectString = app.GetString( effect->getDescriptionId() ); 257 258 MobEffect *mobEffect = MobEffect::effects[effect->getId()]; 259 unordered_map<Attribute*, AttributeModifier*> *effectModifiers = mobEffect->getAttributeModifiers(); 260 261 if (effectModifiers != NULL && effectModifiers->size() > 0) 262 { 263 for(AUTO_VAR(it, effectModifiers->begin()); it != effectModifiers->end(); ++it) 264 { 265 // 4J - anonymous modifiers added here are destroyed shortly? 266 AttributeModifier *original = it->second; 267 AttributeModifier *modifier = new AttributeModifier(mobEffect->getAttributeModifierValue(effect->getAmplifier(), original), original->getOperation()); 268 modifiers.insert( std::pair<eATTRIBUTE_ID, AttributeModifier*>( it->first->getId(), modifier) ); 269 } 270 } 271 272 // Don't want to delete this (that's a pointer to mobEffects internal vector of modifiers) 273 // delete effectModifiers; 274 275 if (effect->getAmplifier() > 0) 276 { 277 wstring potencyString = L""; 278 switch(effect->getAmplifier()) 279 { 280 case 1: 281 potencyString = L" "; 282 potencyString += app.GetString( IDS_POTION_POTENCY_1 ); 283 break; 284 case 2: 285 potencyString = L" "; 286 potencyString += app.GetString( IDS_POTION_POTENCY_2 ); 287 break; 288 case 3: 289 potencyString = L" "; 290 potencyString += app.GetString( IDS_POTION_POTENCY_3 ); 291 break; 292 default: 293 potencyString = app.GetString( IDS_POTION_POTENCY_0 ); 294 break; 295 } 296 effectString += potencyString; // + I18n.get("potion.potency." + effect.getAmplifier()).trim(); 297 } 298 if (effect->getDuration() > SharedConstants::TICKS_PER_SECOND) 299 { 300 effectString += L" (" + MobEffect::formatDuration(effect) + L")"; 301 } 302 303 eMinecraftColour color = eMinecraftColour_NOT_SET; 304 305 if (mobEffect->isHarmful()) 306 { 307 color = eHTMLColor_c; 308 } 309 else 310 { 311 color = eHTMLColor_7; 312 } 313 314 lines->push_back(HtmlString(effectString, color)); 315 } 316 } 317 else 318 { 319 wstring effectString = app.GetString(IDS_POTION_EMPTY); //I18n.get("potion.empty").trim(); 320 321 lines->push_back(HtmlString(effectString, eHTMLColor_7)); //"�7" 322 } 323 324 if (!modifiers.empty()) 325 { 326 // Add new line 327 lines->push_back(HtmlString(L"")); 328 lines->push_back(HtmlString(app.GetString(IDS_POTION_EFFECTS_WHENDRANK), eHTMLColor_5)); 329 330 // Add modifier descriptions 331 for (AUTO_VAR(it, modifiers.begin()); it != modifiers.end(); ++it) 332 { 333 // 4J: Moved modifier string building to AttributeModifier 334 lines->push_back(it->second->getHoverText(it->first)); 335 } 336 } 337} 338 339bool PotionItem::isFoil(shared_ptr<ItemInstance> itemInstance) 340{ 341 vector<MobEffectInstance *> *mobEffects = getMobEffects(itemInstance); 342 return mobEffects != NULL && !mobEffects->empty(); 343} 344 345unsigned int PotionItem::getUseDescriptionId(shared_ptr<ItemInstance> instance) 346{ 347 int brew = instance->getAuxValue(); 348 if(brew == 0) return IDS_POTION_DESC_WATER_BOTTLE; 349 else if( MACRO_POTION_IS_REGENERATION(brew)) return IDS_POTION_DESC_REGENERATION; 350 else if( MACRO_POTION_IS_SPEED(brew) ) return IDS_POTION_DESC_MOVESPEED; 351 else if( MACRO_POTION_IS_FIRE_RESISTANCE(brew)) return IDS_POTION_DESC_FIRERESISTANCE; 352 else if( MACRO_POTION_IS_INSTANTHEALTH(brew)) return IDS_POTION_DESC_HEAL; 353 else if( MACRO_POTION_IS_NIGHTVISION(brew)) return IDS_POTION_DESC_NIGHTVISION; 354 else if( MACRO_POTION_IS_INVISIBILITY(brew)) return IDS_POTION_DESC_INVISIBILITY; 355 else if( MACRO_POTION_IS_WEAKNESS(brew)) return IDS_POTION_DESC_WEAKNESS; 356 else if( MACRO_POTION_IS_STRENGTH(brew)) return IDS_POTION_DESC_DAMAGEBOOST; 357 else if( MACRO_POTION_IS_SLOWNESS(brew)) return IDS_POTION_DESC_MOVESLOWDOWN; 358 else if( MACRO_POTION_IS_POISON(brew)) return IDS_POTION_DESC_POISON; 359 else if( MACRO_POTION_IS_INSTANTDAMAGE(brew)) return IDS_POTION_DESC_HARM; 360 return IDS_POTION_DESC_EMPTY; 361} 362 363void PotionItem::registerIcons(IconRegister *iconRegister) 364{ 365 iconDrinkable = iconRegister->registerIcon(DEFAULT_ICON); 366 iconThrowable = iconRegister->registerIcon(THROWABLE_ICON); 367 iconOverlay = iconRegister->registerIcon(CONTENTS_ICON); 368} 369 370Icon *PotionItem::getTexture(const wstring &name) 371{ 372 if (name.compare(DEFAULT_ICON) == 0) return Item::potion->iconDrinkable; 373 if (name.compare(THROWABLE_ICON) == 0) return Item::potion->iconThrowable; 374 if (name.compare(CONTENTS_ICON) == 0) return Item::potion->iconOverlay; 375 return NULL; 376} 377 378 379// 4J Stu - Based loosely on a function that gets added in java much later on (1.3) 380vector<pair<int, int> > *PotionItem::getUniquePotionValues() 381{ 382 if (s_uniquePotionValues.empty()) 383 { 384 for (int brew = 0; brew <= PotionBrewing::BREW_MASK; ++brew) 385 { 386 vector<MobEffectInstance *> *effects = PotionBrewing::getEffects(brew, false); 387 388 if (effects != NULL) 389 { 390 if(!effects->empty()) 391 { 392 // 4J Stu - Based on implementation of Java List.hashCode() at http://docs.oracle.com/javase/6/docs/api/java/util/List.html#hashCode() 393 // and adding deleting to clear up as we go 394 int effectsHashCode = 1; 395 for(AUTO_VAR(it, effects->begin()); it != effects->end(); ++it) 396 { 397 MobEffectInstance *mei = *it; 398 effectsHashCode = 31*effectsHashCode + (mei==NULL ? 0 : mei->hashCode()); 399 delete (*it); 400 } 401 402 bool toAdd = true; 403 for(AUTO_VAR(it, s_uniquePotionValues.begin()); it != s_uniquePotionValues.end(); ++it) 404 { 405 // Some potions hash the same (identical effects) but are throwable so account for that 406 if(it->first == effectsHashCode && !(!isThrowable(it->second) && isThrowable(brew)) ) 407 { 408 toAdd = false; 409 break; 410 } 411 } 412 if( toAdd ) 413 { 414 s_uniquePotionValues.push_back(pair<int,int>(effectsHashCode, brew) ); 415 } 416 } 417 delete effects; 418 } 419 } 420 } 421 return &s_uniquePotionValues; 422}