1
0

Merge pull request #890 from daniel0916/Enchanting

Enchanting
This commit is contained in:
Mattes D 2014-04-20 13:34:38 +02:00
commit f99bdfb457
18 changed files with 1509 additions and 9 deletions

View File

@ -0,0 +1,37 @@
#pragma once
#include "BlockHandler.h"
#include "../UI/Window.h"
#include "../Entities/Player.h"
class cBlockEnchantmentTableHandler :
public cBlockHandler
{
public:
cBlockEnchantmentTableHandler(BLOCKTYPE a_BlockType)
: cBlockHandler(a_BlockType)
{
}
virtual void OnUse(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) override
{
cWindow * Window = new cEnchantingWindow(a_BlockX, a_BlockY, a_BlockZ);
a_Player->OpenWindow(Window);
}
virtual bool IsUseable(void) override
{
return true;
}
};

View File

@ -25,6 +25,7 @@
#include "BlockDirt.h"
#include "BlockDoor.h"
#include "BlockDropSpenser.h"
#include "BlockEnchantmentTable.h"
#include "BlockEnderchest.h"
#include "BlockEntity.h"
#include "BlockFarmland.h"
@ -119,6 +120,7 @@ cBlockHandler * cBlockHandler::CreateBlockHandler(BLOCKTYPE a_BlockType)
case E_BLOCK_DOUBLE_WOODEN_SLAB: return new cBlockDoubleSlabHandler (a_BlockType);
case E_BLOCK_DROPPER: return new cBlockDropSpenserHandler (a_BlockType);
case E_BLOCK_EMERALD_ORE: return new cBlockOreHandler (a_BlockType);
case E_BLOCK_ENCHANTMENT_TABLE: return new cBlockEnchantmentTableHandler(a_BlockType);
case E_BLOCK_ENDER_CHEST: return new cBlockEnderchestHandler (a_BlockType);
case E_BLOCK_FARMLAND: return new cBlockFarmlandHandler ( );
case E_BLOCK_FENCE_GATE: return new cBlockFenceGateHandler (a_BlockType);

View File

@ -2729,4 +2729,27 @@ void cClientHandle::SocketClosed(void)
void cClientHandle::HandleEnchantItem(Byte & WindowID, Byte & Enchantment)
{
cEnchantingWindow * Window = (cEnchantingWindow*)m_Player->GetWindow();
cItem Item = *Window->m_SlotArea->GetSlot(0, *m_Player);
int BaseEnchantmentLevel = Window->GetPropertyValue(Enchantment);
if (Item.EnchantByXPLevels(BaseEnchantmentLevel))
{
if (m_Player->IsGameModeCreative() || m_Player->DeltaExperience(-m_Player->XpForLevel(BaseEnchantmentLevel)) >= 0)
{
Window->m_SlotArea->SetSlot(0, *m_Player, Item);
Window->SendSlot(*m_Player, Window->m_SlotArea, 0);
Window->BroadcastWholeWindow();
Window->SetProperty(0, 0, *m_Player);
Window->SetProperty(1, 0, *m_Player);
Window->SetProperty(2, 0, *m_Player);
}
}
}

View File

@ -18,6 +18,8 @@
#include "ByteBuffer.h"
#include "Scoreboard.h"
#include "Map.h"
#include "Enchantments.h"
#include "UI/SlotArea.h"
@ -244,6 +246,9 @@ public:
/** Called when the player moves into a different world; queues sreaming the new chunks */
void MoveToWorld(cWorld & a_World, bool a_SendRespawnPacket);
/** Called when the player will enchant a Item */
void HandleEnchantItem(Byte & WindowID, Byte & Enchantment);
private:
/** Handles the block placing packet when it is a real block placement (not block-using, item-using or eating) */

View File

@ -5,6 +5,7 @@
#include "Globals.h"
#include "Enchantments.h"
#include "WorldStorage/FastNBT.h"
#include "FastRandom.h"
@ -218,8 +219,782 @@ bool cEnchantments::operator !=(const cEnchantments & a_Other) const
void cEnchantments::AddItemEnchantmentWeights(cWeightedEnchantments & a_Enchantments, short a_ItemType, int a_EnchantmentLevel)
{
if (ItemCategory::IsSword(a_ItemType))
{
// Sharpness
if ((a_EnchantmentLevel >= 34) && (a_EnchantmentLevel <= 54))
{
AddEnchantmentWeightToVector(a_Enchantments, 10, enchSharpness, 4);
}
else if ((a_EnchantmentLevel >= 23) && (a_EnchantmentLevel <= 43))
{
AddEnchantmentWeightToVector(a_Enchantments, 10, enchSharpness, 3);
}
else if ((a_EnchantmentLevel >= 12) && (a_EnchantmentLevel <= 32))
{
AddEnchantmentWeightToVector(a_Enchantments, 10, enchSharpness, 2);
}
else if ((a_EnchantmentLevel >= 1) && (a_EnchantmentLevel <= 21))
{
AddEnchantmentWeightToVector(a_Enchantments, 10, enchSharpness, 1);
}
// Smite
if ((a_EnchantmentLevel >= 29) && (a_EnchantmentLevel <= 49))
{
AddEnchantmentWeightToVector(a_Enchantments, 5, enchSmite, 4);
}
else if ((a_EnchantmentLevel >= 21) && (a_EnchantmentLevel <= 41))
{
AddEnchantmentWeightToVector(a_Enchantments, 5, enchSmite, 3);
}
else if ((a_EnchantmentLevel >= 13) && (a_EnchantmentLevel <= 33))
{
AddEnchantmentWeightToVector(a_Enchantments, 5, enchSmite, 2);
}
else if ((a_EnchantmentLevel >= 5) && (a_EnchantmentLevel <= 25))
{
AddEnchantmentWeightToVector(a_Enchantments, 5, enchSmite, 1);
}
// Bane of Arthropods
if ((a_EnchantmentLevel >= 29) && (a_EnchantmentLevel <= 49))
{
AddEnchantmentWeightToVector(a_Enchantments, 5, enchBaneOfArthropods, 4);
}
else if ((a_EnchantmentLevel >= 21) && (a_EnchantmentLevel <= 41))
{
AddEnchantmentWeightToVector(a_Enchantments, 5, enchBaneOfArthropods, 3);
}
else if ((a_EnchantmentLevel >= 13) && (a_EnchantmentLevel <= 33))
{
AddEnchantmentWeightToVector(a_Enchantments, 5, enchBaneOfArthropods, 2);
}
else if ((a_EnchantmentLevel >= 5) && (a_EnchantmentLevel <= 25))
{
AddEnchantmentWeightToVector(a_Enchantments, 5, enchBaneOfArthropods, 1);
}
// Knockback
if ((a_EnchantmentLevel >= 25) && (a_EnchantmentLevel <= 75))
{
AddEnchantmentWeightToVector(a_Enchantments, 5, enchKnockback, 2);
}
else if ((a_EnchantmentLevel >= 5) && (a_EnchantmentLevel <= 55))
{
AddEnchantmentWeightToVector(a_Enchantments, 5, enchKnockback, 1);
}
// Fire Aspect
if ((a_EnchantmentLevel >= 30) && (a_EnchantmentLevel <= 80))
{
AddEnchantmentWeightToVector(a_Enchantments, 2, enchFireAspect, 2);
}
else if ((a_EnchantmentLevel >= 10) && (a_EnchantmentLevel <= 60))
{
AddEnchantmentWeightToVector(a_Enchantments, 2, enchFireAspect, 1);
}
// Looting
if ((a_EnchantmentLevel >= 33) && (a_EnchantmentLevel <= 83))
{
AddEnchantmentWeightToVector(a_Enchantments, 2, enchLooting, 3);
}
else if ((a_EnchantmentLevel >= 24) && (a_EnchantmentLevel <= 74))
{
AddEnchantmentWeightToVector(a_Enchantments, 2, enchLooting, 2);
}
else if ((a_EnchantmentLevel >= 15) && (a_EnchantmentLevel <= 65))
{
AddEnchantmentWeightToVector(a_Enchantments, 2, enchLooting, 1);
}
}
else if (ItemCategory::IsTool(a_ItemType))
{
// Efficiency
if ((a_EnchantmentLevel >= 31) && (a_EnchantmentLevel <= 81))
{
AddEnchantmentWeightToVector(a_Enchantments, 10, enchEfficiency, 4);
}
else if ((a_EnchantmentLevel >= 21) && (a_EnchantmentLevel <= 71))
{
AddEnchantmentWeightToVector(a_Enchantments, 10, enchEfficiency, 3);
}
else if ((a_EnchantmentLevel >= 11) && (a_EnchantmentLevel <= 61))
{
AddEnchantmentWeightToVector(a_Enchantments, 10, enchEfficiency, 2);
}
else if ((a_EnchantmentLevel >= 1) && (a_EnchantmentLevel <= 51))
{
AddEnchantmentWeightToVector(a_Enchantments, 10, enchEfficiency, 1);
}
// Silk Touch
if ((a_EnchantmentLevel >= 15) && (a_EnchantmentLevel <= 65))
{
AddEnchantmentWeightToVector(a_Enchantments, 1, enchSilkTouch, 1);
}
// Fortune
if ((a_EnchantmentLevel >= 33) && (a_EnchantmentLevel <= 83))
{
AddEnchantmentWeightToVector(a_Enchantments, 2, enchFortune, 3);
}
else if ((a_EnchantmentLevel >= 24) && (a_EnchantmentLevel <= 74))
{
AddEnchantmentWeightToVector(a_Enchantments, 2, enchFortune, 2);
}
else if ((a_EnchantmentLevel >= 15) && (a_EnchantmentLevel <= 65))
{
AddEnchantmentWeightToVector(a_Enchantments, 2, enchFortune, 1);
}
}
else if (ItemCategory::IsArmor(a_ItemType))
{
// Protection
if ((a_EnchantmentLevel >= 34) && (a_EnchantmentLevel <= 54))
{
AddEnchantmentWeightToVector(a_Enchantments, 10, enchProtection, 4);
}
else if ((a_EnchantmentLevel >= 23) && (a_EnchantmentLevel <= 43))
{
AddEnchantmentWeightToVector(a_Enchantments, 10, enchProtection, 3);
}
else if ((a_EnchantmentLevel >= 12) && (a_EnchantmentLevel <= 32))
{
AddEnchantmentWeightToVector(a_Enchantments, 10, enchProtection, 2);
}
else if ((a_EnchantmentLevel >= 1) && (a_EnchantmentLevel <= 21))
{
AddEnchantmentWeightToVector(a_Enchantments, 10, enchProtection, 1);
}
// Fire Protection
if ((a_EnchantmentLevel >= 34) && (a_EnchantmentLevel <= 46))
{
AddEnchantmentWeightToVector(a_Enchantments, 5, enchFireProtection, 4);
}
else if ((a_EnchantmentLevel >= 26) && (a_EnchantmentLevel <= 38))
{
AddEnchantmentWeightToVector(a_Enchantments, 5, enchFireProtection, 3);
}
else if ((a_EnchantmentLevel >= 18) && (a_EnchantmentLevel <= 30))
{
AddEnchantmentWeightToVector(a_Enchantments, 5, enchFireProtection, 2);
}
else if ((a_EnchantmentLevel >= 10) && (a_EnchantmentLevel <= 22))
{
AddEnchantmentWeightToVector(a_Enchantments, 5, enchFireProtection, 1);
}
// Blast Protection
if ((a_EnchantmentLevel >= 29) && (a_EnchantmentLevel <= 41))
{
AddEnchantmentWeightToVector(a_Enchantments, 2, enchBlastProtection, 4);
}
else if ((a_EnchantmentLevel >= 21) && (a_EnchantmentLevel <= 33))
{
AddEnchantmentWeightToVector(a_Enchantments, 2, enchBlastProtection, 3);
}
else if ((a_EnchantmentLevel >= 13) && (a_EnchantmentLevel <= 25))
{
AddEnchantmentWeightToVector(a_Enchantments, 2, enchBlastProtection, 2);
}
else if ((a_EnchantmentLevel >= 5) && (a_EnchantmentLevel <= 17))
{
AddEnchantmentWeightToVector(a_Enchantments, 2, enchBlastProtection, 1);
}
// Projectile Protection
if ((a_EnchantmentLevel >= 21) && (a_EnchantmentLevel <= 36))
{
AddEnchantmentWeightToVector(a_Enchantments, 5, enchProjectileProtection, 4);
}
else if ((a_EnchantmentLevel >= 15) && (a_EnchantmentLevel <= 30))
{
AddEnchantmentWeightToVector(a_Enchantments, 5, enchProjectileProtection, 3);
}
else if ((a_EnchantmentLevel >= 9) && (a_EnchantmentLevel <= 24))
{
AddEnchantmentWeightToVector(a_Enchantments, 5, enchProjectileProtection, 2);
}
else if ((a_EnchantmentLevel >= 3) && (a_EnchantmentLevel <= 18))
{
AddEnchantmentWeightToVector(a_Enchantments, 5, enchProjectileProtection, 1);
}
// Thorns
if ((a_EnchantmentLevel >= 50) && (a_EnchantmentLevel <= 100))
{
AddEnchantmentWeightToVector(a_Enchantments, 1, enchThorns, 3);
}
else if ((a_EnchantmentLevel >= 30) && (a_EnchantmentLevel <= 80))
{
AddEnchantmentWeightToVector(a_Enchantments, 1, enchThorns, 2);
}
else if ((a_EnchantmentLevel >= 10) && (a_EnchantmentLevel <= 60))
{
AddEnchantmentWeightToVector(a_Enchantments, 1, enchThorns, 1);
}
if (ItemCategory::IsHelmet(a_ItemType))
{
// Respiration
if ((a_EnchantmentLevel >= 30) && (a_EnchantmentLevel <= 60))
{
AddEnchantmentWeightToVector(a_Enchantments, 2, enchRespiration, 3);
}
else if ((a_EnchantmentLevel >= 20) && (a_EnchantmentLevel <= 50))
{
AddEnchantmentWeightToVector(a_Enchantments, 2, enchRespiration, 2);
}
else if ((a_EnchantmentLevel >= 10) && (a_EnchantmentLevel <= 40))
{
AddEnchantmentWeightToVector(a_Enchantments, 2, enchRespiration, 1);
}
// Aqua Affinity
if ((a_EnchantmentLevel >= 1) && (a_EnchantmentLevel <= 41))
{
AddEnchantmentWeightToVector(a_Enchantments, 2, enchAquaAffinity, 1);
}
}
else if (ItemCategory::IsBoots(a_ItemType))
{
// Feather Fall
if ((a_EnchantmentLevel >= 23) && (a_EnchantmentLevel <= 33))
{
AddEnchantmentWeightToVector(a_Enchantments, 5, enchFeatherFalling, 4);
}
else if ((a_EnchantmentLevel >= 17) && (a_EnchantmentLevel <= 27))
{
AddEnchantmentWeightToVector(a_Enchantments, 5, enchFeatherFalling, 3);
}
else if ((a_EnchantmentLevel >= 11) && (a_EnchantmentLevel <= 21))
{
AddEnchantmentWeightToVector(a_Enchantments, 5, enchFeatherFalling, 2);
}
else if ((a_EnchantmentLevel >= 5) && (a_EnchantmentLevel <= 15))
{
AddEnchantmentWeightToVector(a_Enchantments, 5, enchFeatherFalling, 1);
}
}
}
else if (a_ItemType == E_ITEM_BOW)
{
// Power
if ((a_EnchantmentLevel >= 31) && (a_EnchantmentLevel <= 46))
{
AddEnchantmentWeightToVector(a_Enchantments, 10, enchPower, 4);
}
else if ((a_EnchantmentLevel >= 21) && (a_EnchantmentLevel <= 36))
{
AddEnchantmentWeightToVector(a_Enchantments, 10, enchPower, 3);
}
else if ((a_EnchantmentLevel >= 11) && (a_EnchantmentLevel <= 26))
{
AddEnchantmentWeightToVector(a_Enchantments, 10, enchPower, 2);
}
else if ((a_EnchantmentLevel >= 1) && (a_EnchantmentLevel <= 16))
{
AddEnchantmentWeightToVector(a_Enchantments, 10, enchPower, 1);
}
// Punch
if ((a_EnchantmentLevel >= 32) && (a_EnchantmentLevel <= 57))
{
AddEnchantmentWeightToVector(a_Enchantments, 2, enchPunch, 2);
}
else if ((a_EnchantmentLevel >= 12) && (a_EnchantmentLevel <= 37))
{
AddEnchantmentWeightToVector(a_Enchantments, 2, enchPunch, 1);
}
// Flame and Infinity
if ((a_EnchantmentLevel >= 20) && (a_EnchantmentLevel <= 50))
{
AddEnchantmentWeightToVector(a_Enchantments, 2, enchFlame, 1);
AddEnchantmentWeightToVector(a_Enchantments, 1, enchInfinity, 1);
}
}
else if (a_ItemType == E_ITEM_FISHING_ROD)
{
// Luck of the Sea and Lure
if ((a_EnchantmentLevel >= 33) && (a_EnchantmentLevel <= 83))
{
AddEnchantmentWeightToVector(a_Enchantments, 1, enchLuckOfTheSea, 3);
AddEnchantmentWeightToVector(a_Enchantments, 1, enchLure, 3);
}
else if ((a_EnchantmentLevel >= 24) && (a_EnchantmentLevel <= 74))
{
AddEnchantmentWeightToVector(a_Enchantments, 1, enchLuckOfTheSea, 2);
AddEnchantmentWeightToVector(a_Enchantments, 1, enchLure, 2);
}
else if ((a_EnchantmentLevel >= 15) && (a_EnchantmentLevel <= 65))
{
AddEnchantmentWeightToVector(a_Enchantments, 1, enchLuckOfTheSea, 1);
AddEnchantmentWeightToVector(a_Enchantments, 1, enchLure, 1);
}
}
else if (a_ItemType == E_ITEM_BOOK)
{
// All Enchantments
// Sharpness
if ((a_EnchantmentLevel >= 34) && (a_EnchantmentLevel <= 54))
{
AddEnchantmentWeightToVector(a_Enchantments, 10, enchSharpness, 4);
}
else if ((a_EnchantmentLevel >= 23) && (a_EnchantmentLevel <= 43))
{
AddEnchantmentWeightToVector(a_Enchantments, 10, enchSharpness, 3);
}
else if ((a_EnchantmentLevel >= 12) && (a_EnchantmentLevel <= 32))
{
AddEnchantmentWeightToVector(a_Enchantments, 10, enchSharpness, 2);
}
else if ((a_EnchantmentLevel >= 1) && (a_EnchantmentLevel <= 21))
{
AddEnchantmentWeightToVector(a_Enchantments, 10, enchSharpness, 1);
}
// Smite
if ((a_EnchantmentLevel >= 29) && (a_EnchantmentLevel <= 49))
{
AddEnchantmentWeightToVector(a_Enchantments, 5, enchSmite, 4);
}
else if ((a_EnchantmentLevel >= 21) && (a_EnchantmentLevel <= 41))
{
AddEnchantmentWeightToVector(a_Enchantments, 5, enchSmite, 3);
}
else if ((a_EnchantmentLevel >= 13) && (a_EnchantmentLevel <= 33))
{
AddEnchantmentWeightToVector(a_Enchantments, 5, enchSmite, 2);
}
else if ((a_EnchantmentLevel >= 5) && (a_EnchantmentLevel <= 25))
{
AddEnchantmentWeightToVector(a_Enchantments, 5, enchSmite, 1);
}
// Bane of Arthropods
if ((a_EnchantmentLevel >= 29) && (a_EnchantmentLevel <= 49))
{
AddEnchantmentWeightToVector(a_Enchantments, 5, enchBaneOfArthropods, 4);
}
else if ((a_EnchantmentLevel >= 21) && (a_EnchantmentLevel <= 41))
{
AddEnchantmentWeightToVector(a_Enchantments, 5, enchBaneOfArthropods, 3);
}
else if ((a_EnchantmentLevel >= 13) && (a_EnchantmentLevel <= 33))
{
AddEnchantmentWeightToVector(a_Enchantments, 5, enchBaneOfArthropods, 2);
}
else if ((a_EnchantmentLevel >= 5) && (a_EnchantmentLevel <= 25))
{
AddEnchantmentWeightToVector(a_Enchantments, 5, enchBaneOfArthropods, 1);
}
// Knockback
if ((a_EnchantmentLevel >= 25) && (a_EnchantmentLevel <= 75))
{
AddEnchantmentWeightToVector(a_Enchantments, 5, enchKnockback, 2);
}
else if ((a_EnchantmentLevel >= 5) && (a_EnchantmentLevel <= 55))
{
AddEnchantmentWeightToVector(a_Enchantments, 5, enchKnockback, 1);
}
// Fire Aspect
if ((a_EnchantmentLevel >= 30) && (a_EnchantmentLevel <= 80))
{
AddEnchantmentWeightToVector(a_Enchantments, 2, enchFireAspect, 2);
}
else if ((a_EnchantmentLevel >= 10) && (a_EnchantmentLevel <= 60))
{
AddEnchantmentWeightToVector(a_Enchantments, 2, enchFireAspect, 1);
}
// Looting
if ((a_EnchantmentLevel >= 33) && (a_EnchantmentLevel <= 83))
{
AddEnchantmentWeightToVector(a_Enchantments, 2, enchLooting, 3);
}
else if ((a_EnchantmentLevel >= 24) && (a_EnchantmentLevel <= 74))
{
AddEnchantmentWeightToVector(a_Enchantments, 2, enchLooting, 2);
}
else if ((a_EnchantmentLevel >= 15) && (a_EnchantmentLevel <= 65))
{
AddEnchantmentWeightToVector(a_Enchantments, 2, enchLooting, 1);
}
// Efficiency
if ((a_EnchantmentLevel >= 31) && (a_EnchantmentLevel <= 81))
{
AddEnchantmentWeightToVector(a_Enchantments, 10, enchEfficiency, 4);
}
else if ((a_EnchantmentLevel >= 21) && (a_EnchantmentLevel <= 71))
{
AddEnchantmentWeightToVector(a_Enchantments, 10, enchEfficiency, 3);
}
else if ((a_EnchantmentLevel >= 11) && (a_EnchantmentLevel <= 61))
{
AddEnchantmentWeightToVector(a_Enchantments, 10, enchEfficiency, 2);
}
else if ((a_EnchantmentLevel >= 1) && (a_EnchantmentLevel <= 51))
{
AddEnchantmentWeightToVector(a_Enchantments, 10, enchEfficiency, 1);
}
// Silk Touch
if ((a_EnchantmentLevel >= 15) && (a_EnchantmentLevel <= 65))
{
AddEnchantmentWeightToVector(a_Enchantments, 1, enchSilkTouch, 1);
}
// Fortune
if ((a_EnchantmentLevel >= 33) && (a_EnchantmentLevel <= 83))
{
AddEnchantmentWeightToVector(a_Enchantments, 2, enchFortune, 3);
}
else if ((a_EnchantmentLevel >= 24) && (a_EnchantmentLevel <= 74))
{
AddEnchantmentWeightToVector(a_Enchantments, 2, enchFortune, 2);
}
else if ((a_EnchantmentLevel >= 15) && (a_EnchantmentLevel <= 65))
{
AddEnchantmentWeightToVector(a_Enchantments, 2, enchFortune, 1);
}
// Protection
if ((a_EnchantmentLevel >= 34) && (a_EnchantmentLevel <= 54))
{
AddEnchantmentWeightToVector(a_Enchantments, 10, enchProtection, 4);
}
else if ((a_EnchantmentLevel >= 23) && (a_EnchantmentLevel <= 43))
{
AddEnchantmentWeightToVector(a_Enchantments, 10, enchProtection, 3);
}
else if ((a_EnchantmentLevel >= 12) && (a_EnchantmentLevel <= 32))
{
AddEnchantmentWeightToVector(a_Enchantments, 10, enchProtection, 2);
}
else if ((a_EnchantmentLevel >= 1) && (a_EnchantmentLevel <= 21))
{
AddEnchantmentWeightToVector(a_Enchantments, 10, enchProtection, 1);
}
// Fire Protection
if ((a_EnchantmentLevel >= 34) && (a_EnchantmentLevel <= 46))
{
AddEnchantmentWeightToVector(a_Enchantments, 5, enchFireProtection, 4);
}
else if ((a_EnchantmentLevel >= 26) && (a_EnchantmentLevel <= 38))
{
AddEnchantmentWeightToVector(a_Enchantments, 5, enchFireProtection, 3);
}
else if ((a_EnchantmentLevel >= 18) && (a_EnchantmentLevel <= 30))
{
AddEnchantmentWeightToVector(a_Enchantments, 5, enchFireProtection, 2);
}
else if ((a_EnchantmentLevel >= 10) && (a_EnchantmentLevel <= 22))
{
AddEnchantmentWeightToVector(a_Enchantments, 5, enchFireProtection, 1);
}
// Blast Protection
if ((a_EnchantmentLevel >= 29) && (a_EnchantmentLevel <= 41))
{
AddEnchantmentWeightToVector(a_Enchantments, 2, enchBlastProtection, 4);
}
else if ((a_EnchantmentLevel >= 21) && (a_EnchantmentLevel <= 33))
{
AddEnchantmentWeightToVector(a_Enchantments, 2, enchBlastProtection, 3);
}
else if ((a_EnchantmentLevel >= 13) && (a_EnchantmentLevel <= 25))
{
AddEnchantmentWeightToVector(a_Enchantments, 2, enchBlastProtection, 2);
}
else if ((a_EnchantmentLevel >= 5) && (a_EnchantmentLevel <= 17))
{
AddEnchantmentWeightToVector(a_Enchantments, 2, enchBlastProtection, 1);
}
// Projectile Protection
if ((a_EnchantmentLevel >= 21) && (a_EnchantmentLevel <= 36))
{
AddEnchantmentWeightToVector(a_Enchantments, 5, enchProjectileProtection, 4);
}
else if ((a_EnchantmentLevel >= 15) && (a_EnchantmentLevel <= 30))
{
AddEnchantmentWeightToVector(a_Enchantments, 5, enchProjectileProtection, 3);
}
else if ((a_EnchantmentLevel >= 9) && (a_EnchantmentLevel <= 24))
{
AddEnchantmentWeightToVector(a_Enchantments, 5, enchProjectileProtection, 2);
}
else if ((a_EnchantmentLevel >= 3) && (a_EnchantmentLevel <= 18))
{
AddEnchantmentWeightToVector(a_Enchantments, 5, enchProjectileProtection, 1);
}
// Thorns
if ((a_EnchantmentLevel >= 50) && (a_EnchantmentLevel <= 100))
{
AddEnchantmentWeightToVector(a_Enchantments, 1, enchThorns, 3);
}
else if ((a_EnchantmentLevel >= 30) && (a_EnchantmentLevel <= 80))
{
AddEnchantmentWeightToVector(a_Enchantments, 1, enchThorns, 2);
}
else if ((a_EnchantmentLevel >= 10) && (a_EnchantmentLevel <= 60))
{
AddEnchantmentWeightToVector(a_Enchantments, 1, enchThorns, 1);
}
// Respiration
if ((a_EnchantmentLevel >= 30) && (a_EnchantmentLevel <= 60))
{
AddEnchantmentWeightToVector(a_Enchantments, 2, enchRespiration, 3);
}
else if ((a_EnchantmentLevel >= 20) && (a_EnchantmentLevel <= 50))
{
AddEnchantmentWeightToVector(a_Enchantments, 2, enchRespiration, 2);
}
else if ((a_EnchantmentLevel >= 10) && (a_EnchantmentLevel <= 40))
{
AddEnchantmentWeightToVector(a_Enchantments, 2, enchRespiration, 1);
}
// Aqua Affinity
if ((a_EnchantmentLevel >= 1) && (a_EnchantmentLevel <= 41))
{
AddEnchantmentWeightToVector(a_Enchantments, 2, enchAquaAffinity, 1);
}
// Feather Fall
if ((a_EnchantmentLevel >= 23) && (a_EnchantmentLevel <= 33))
{
AddEnchantmentWeightToVector(a_Enchantments, 5, enchFeatherFalling, 4);
}
else if ((a_EnchantmentLevel >= 17) && (a_EnchantmentLevel <= 27))
{
AddEnchantmentWeightToVector(a_Enchantments, 5, enchFeatherFalling, 3);
}
else if ((a_EnchantmentLevel >= 11) && (a_EnchantmentLevel <= 21))
{
AddEnchantmentWeightToVector(a_Enchantments, 5, enchFeatherFalling, 2);
}
else if ((a_EnchantmentLevel >= 5) && (a_EnchantmentLevel <= 15))
{
AddEnchantmentWeightToVector(a_Enchantments, 5, enchFeatherFalling, 1);
}
// Power
if ((a_EnchantmentLevel >= 31) && (a_EnchantmentLevel <= 46))
{
AddEnchantmentWeightToVector(a_Enchantments, 10, enchPower, 4);
}
else if ((a_EnchantmentLevel >= 21) && (a_EnchantmentLevel <= 36))
{
AddEnchantmentWeightToVector(a_Enchantments, 10, enchPower, 3);
}
else if ((a_EnchantmentLevel >= 11) && (a_EnchantmentLevel <= 26))
{
AddEnchantmentWeightToVector(a_Enchantments, 10, enchPower, 2);
}
else if ((a_EnchantmentLevel >= 1) && (a_EnchantmentLevel <= 16))
{
AddEnchantmentWeightToVector(a_Enchantments, 10, enchPower, 1);
}
// Punch
if ((a_EnchantmentLevel >= 32) && (a_EnchantmentLevel <= 57))
{
AddEnchantmentWeightToVector(a_Enchantments, 2, enchPunch, 2);
}
else if ((a_EnchantmentLevel >= 12) && (a_EnchantmentLevel <= 37))
{
AddEnchantmentWeightToVector(a_Enchantments, 2, enchPunch, 1);
}
// Flame and Infinity
if ((a_EnchantmentLevel >= 20) && (a_EnchantmentLevel <= 50))
{
AddEnchantmentWeightToVector(a_Enchantments, 2, enchFlame, 1);
AddEnchantmentWeightToVector(a_Enchantments, 1, enchInfinity, 1);
}
// Luck of the Sea and Lure
if ((a_EnchantmentLevel >= 33) && (a_EnchantmentLevel <= 83))
{
AddEnchantmentWeightToVector(a_Enchantments, 1, enchLuckOfTheSea, 3);
AddEnchantmentWeightToVector(a_Enchantments, 1, enchLure, 3);
}
else if ((a_EnchantmentLevel >= 24) && (a_EnchantmentLevel <= 74))
{
AddEnchantmentWeightToVector(a_Enchantments, 1, enchLuckOfTheSea, 2);
AddEnchantmentWeightToVector(a_Enchantments, 1, enchLure, 2);
}
else if ((a_EnchantmentLevel >= 15) && (a_EnchantmentLevel <= 65))
{
AddEnchantmentWeightToVector(a_Enchantments, 1, enchLuckOfTheSea, 1);
AddEnchantmentWeightToVector(a_Enchantments, 1, enchLure, 1);
}
}
// Unbreaking
if ((a_EnchantmentLevel >= 21) && (a_EnchantmentLevel <= 71))
{
AddEnchantmentWeightToVector(a_Enchantments, 5, enchUnbreaking, 3);
}
else if ((a_EnchantmentLevel >= 13) && (a_EnchantmentLevel <= 63))
{
AddEnchantmentWeightToVector(a_Enchantments, 5, enchUnbreaking, 2);
}
else if ((a_EnchantmentLevel >= 5) && (a_EnchantmentLevel <= 55))
{
AddEnchantmentWeightToVector(a_Enchantments, 5, enchUnbreaking, 1);
}
}
void cEnchantments::AddEnchantmentWeightToVector(cWeightedEnchantments & a_Enchantments, int a_Weight, int a_EnchantmentID, int a_EnchantmentLevel)
{
cWeightedEnchantment weightedenchantment;
weightedenchantment.m_Weight = a_Weight;
cEnchantments enchantment;
enchantment.SetLevel(a_EnchantmentID, a_EnchantmentLevel);
weightedenchantment.m_Enchantments = enchantment;
a_Enchantments.push_back(weightedenchantment);
}
void cEnchantments::RemoveEnchantmentWeightFromVector(cWeightedEnchantments & a_Enchantments, int a_EnchantmentID)
{
for (cWeightedEnchantments::iterator it = a_Enchantments.begin(); it != a_Enchantments.end(); ++it)
{
if ((*it).m_Enchantments.GetLevel(a_EnchantmentID) > 0)
{
a_Enchantments.erase(it);
break;
}
}
}
void cEnchantments::RemoveEnchantmentWeightFromVector(cWeightedEnchantments & a_Enchantments, const cEnchantments & a_Enchantment)
{
for (cWeightedEnchantments::iterator it = a_Enchantments.begin(); it != a_Enchantments.end(); ++it)
{
if ((*it).m_Enchantments == a_Enchantment)
{
a_Enchantments.erase(it);
break;
}
}
}
void cEnchantments::CheckEnchantmentConflictsFromVector(cWeightedEnchantments & a_Enchantments, cEnchantments a_FirstEnchantment)
{
if (a_FirstEnchantment.GetLevel(cEnchantments::enchProtection) > 0)
{
RemoveEnchantmentWeightFromVector(a_Enchantments, cEnchantments::enchFireProtection);
RemoveEnchantmentWeightFromVector(a_Enchantments, cEnchantments::enchBlastProtection);
RemoveEnchantmentWeightFromVector(a_Enchantments, cEnchantments::enchProjectileProtection);
}
else if (a_FirstEnchantment.GetLevel(cEnchantments::enchFireProtection) > 0)
{
RemoveEnchantmentWeightFromVector(a_Enchantments, cEnchantments::enchProtection);
RemoveEnchantmentWeightFromVector(a_Enchantments, cEnchantments::enchBlastProtection);
RemoveEnchantmentWeightFromVector(a_Enchantments, cEnchantments::enchProjectileProtection);
}
else if (a_FirstEnchantment.GetLevel(cEnchantments::enchBlastProtection) > 0)
{
RemoveEnchantmentWeightFromVector(a_Enchantments, cEnchantments::enchProtection);
RemoveEnchantmentWeightFromVector(a_Enchantments, cEnchantments::enchFireProtection);
RemoveEnchantmentWeightFromVector(a_Enchantments, cEnchantments::enchProjectileProtection);
}
else if (a_FirstEnchantment.GetLevel(cEnchantments::enchProjectileProtection) > 0)
{
RemoveEnchantmentWeightFromVector(a_Enchantments, cEnchantments::enchProtection);
RemoveEnchantmentWeightFromVector(a_Enchantments, cEnchantments::enchFireProtection);
RemoveEnchantmentWeightFromVector(a_Enchantments, cEnchantments::enchBlastProtection);
}
else if (a_FirstEnchantment.GetLevel(cEnchantments::enchSharpness) > 0)
{
RemoveEnchantmentWeightFromVector(a_Enchantments, cEnchantments::enchSmite);
RemoveEnchantmentWeightFromVector(a_Enchantments, cEnchantments::enchBaneOfArthropods);
}
else if (a_FirstEnchantment.GetLevel(cEnchantments::enchSmite) > 0)
{
RemoveEnchantmentWeightFromVector(a_Enchantments, cEnchantments::enchSharpness);
RemoveEnchantmentWeightFromVector(a_Enchantments, cEnchantments::enchBaneOfArthropods);
}
else if (a_FirstEnchantment.GetLevel(cEnchantments::enchBaneOfArthropods) > 0)
{
RemoveEnchantmentWeightFromVector(a_Enchantments, cEnchantments::enchSharpness);
RemoveEnchantmentWeightFromVector(a_Enchantments, cEnchantments::enchSmite);
}
else if (a_FirstEnchantment.GetLevel(cEnchantments::enchSilkTouch) > 0)
{
RemoveEnchantmentWeightFromVector(a_Enchantments, cEnchantments::enchFortune);
}
else if (a_FirstEnchantment.GetLevel(cEnchantments::enchFortune) > 0)
{
RemoveEnchantmentWeightFromVector(a_Enchantments, cEnchantments::enchSilkTouch);
}
}
cEnchantments cEnchantments::GetRandomEnchantmentFromVector(cWeightedEnchantments & a_Enchantments)
{
cFastRandom Random;
int AllWeights = 0;
for (cWeightedEnchantments::iterator it = a_Enchantments.begin(); it != a_Enchantments.end(); ++it)
{
AllWeights += (*it).m_Weight;
}
int RandomNumber = Random.GenerateRandomInteger(0, AllWeights - 1);
for (cWeightedEnchantments::iterator it = a_Enchantments.begin(); it != a_Enchantments.end(); ++it)
{
RandomNumber -= (*it).m_Weight;
if (RandomNumber < 0)
{
return (*it).m_Enchantments;
}
}
return cEnchantments();
}

View File

@ -8,6 +8,7 @@
#pragma once
#include "Defines.h"
#include "WorldStorage/EnchantmentSerializer.h"
@ -18,6 +19,11 @@ class cFastNBTWriter;
class cParsedNBT;
// fwd:
struct cWeightedEnchantment;
typedef std::vector<cWeightedEnchantment> cWeightedEnchantments;
@ -28,6 +34,8 @@ mapping each enchantment's id onto its level. ID may be either a number or the e
Level value of 0 means no such enchantment, and it will not be stored in the m_Enchantments.
Serialization will never put zero-level enchantments into the stringspec and will always use numeric IDs.
*/
// tolua_begin
class cEnchantments
{
@ -61,7 +69,7 @@ public:
enchLuckOfTheSea = 61,
enchLure = 62,
} ;
/// Creates an empty enchantments container
cEnchantments(void);
@ -91,9 +99,27 @@ public:
/// Returns true if a_Other contains exactly the same enchantments and levels
bool operator ==(const cEnchantments & a_Other) const;
// tolua_end
/** Add enchantment weights from item to the vector */
static void AddItemEnchantmentWeights(cWeightedEnchantments & a_Enchantments, short a_ItemType, int a_EnchantmentLevel);
/** Add a enchantment with weight to the vector */
static void AddEnchantmentWeightToVector(cWeightedEnchantments & a_Enchantments, int a_Weight, int a_EnchantmentID, int a_EnchantmentLevel);
/** Remove the entire enchantment (with weight) from the vector */
static void RemoveEnchantmentWeightFromVector(cWeightedEnchantments & a_Enchantments, int a_EnchantmentID);
/** Remove the entire enchantment (with weight) from the vector */
static void RemoveEnchantmentWeightFromVector(cWeightedEnchantments & a_Enchantments, const cEnchantments & a_Enchantment);
/** Check enchantment conflicts from enchantments from the vector */
static void CheckEnchantmentConflictsFromVector(cWeightedEnchantments & a_Enchantments, cEnchantments a_FirstEnchantment);
/** Gets random enchantment from Vector and returns it */
static cEnchantments GetRandomEnchantmentFromVector(cWeightedEnchantments & a_Enchantments);
/// Returns true if a_Other doesn't contain exactly the same enchantments and levels
bool operator !=(const cEnchantments & a_Other) const;
@ -102,7 +128,7 @@ public:
/// Reads the enchantments from the specified NBT list tag (ench or StoredEnchantments)
friend void EnchantmentSerializer::ParseFromNBT(cEnchantments& a_Enchantments, const cParsedNBT & a_NBT, int a_EnchListTagIdx);
protected:
/// Maps enchantment ID -> enchantment level
typedef std::map<int, int> cMap;
@ -114,3 +140,12 @@ protected:
// Define the cWeightedEnchantment struct for the Enchanting System to store the EnchantmentWeights:
struct cWeightedEnchantment
{
int m_Weight;
cEnchantments m_Enchantments;
};

View File

@ -172,3 +172,13 @@ float cFastRandom::NextFloat(float a_Range, int a_Salt)
int cFastRandom::GenerateRandomInteger(int a_Begin, int a_End)
{
cFastRandom Random;
return Random.NextInt(a_End - a_Begin + 1) + a_Begin;
}

View File

@ -43,6 +43,9 @@ public:
/// Returns a random float in the range [0 .. a_Range]; a_Range must be less than 1M; a_Salt is additional source of randomness
float NextFloat(float a_Range, int a_Salt);
/** Returns a random int in the range [a_Begin .. a_End] */
int GenerateRandomInteger(int a_Begin, int a_End);
protected:
int m_Seed;

View File

@ -5,6 +5,8 @@
#include "json/json.h"
#include "Items/ItemHandler.h"
#include "FastRandom.h"
@ -209,6 +211,157 @@ bool cItem::IsEnchantable(short item)
int cItem::GetEnchantability()
{
int Enchantability = 0;
switch (m_ItemType)
{
case E_ITEM_WOODEN_SWORD: Enchantability = 15; break;
case E_ITEM_WOODEN_PICKAXE: Enchantability = 15; break;
case E_ITEM_WOODEN_SHOVEL: Enchantability = 15; break;
case E_ITEM_WOODEN_AXE: Enchantability = 15; break;
case E_ITEM_WOODEN_HOE: Enchantability = 15; break;
case E_ITEM_LEATHER_CAP: Enchantability = 15; break;
case E_ITEM_LEATHER_TUNIC: Enchantability = 15; break;
case E_ITEM_LEATHER_PANTS: Enchantability = 15; break;
case E_ITEM_LEATHER_BOOTS: Enchantability = 15; break;
case E_ITEM_STONE_SWORD: Enchantability = 5; break;
case E_ITEM_STONE_PICKAXE: Enchantability = 5; break;
case E_ITEM_STONE_SHOVEL: Enchantability = 5; break;
case E_ITEM_STONE_AXE: Enchantability = 5; break;
case E_ITEM_STONE_HOE: Enchantability = 5; break;
case E_ITEM_IRON_HELMET: Enchantability = 9; break;
case E_ITEM_IRON_CHESTPLATE: Enchantability = 9; break;
case E_ITEM_IRON_LEGGINGS: Enchantability = 9; break;
case E_ITEM_IRON_BOOTS: Enchantability = 9; break;
case E_ITEM_IRON_SWORD: Enchantability = 14; break;
case E_ITEM_IRON_PICKAXE: Enchantability = 14; break;
case E_ITEM_IRON_SHOVEL: Enchantability = 14; break;
case E_ITEM_IRON_AXE: Enchantability = 14; break;
case E_ITEM_IRON_HOE: Enchantability = 14; break;
case E_ITEM_CHAIN_HELMET: Enchantability = 12; break;
case E_ITEM_CHAIN_CHESTPLATE: Enchantability = 12; break;
case E_ITEM_CHAIN_LEGGINGS: Enchantability = 12; break;
case E_ITEM_CHAIN_BOOTS: Enchantability = 12; break;
case E_ITEM_DIAMOND_HELMET: Enchantability = 10; break;
case E_ITEM_DIAMOND_CHESTPLATE: Enchantability = 10; break;
case E_ITEM_DIAMOND_LEGGINGS: Enchantability = 10; break;
case E_ITEM_DIAMOND_BOOTS: Enchantability = 10; break;
case E_ITEM_DIAMOND_SWORD: Enchantability = 10; break;
case E_ITEM_DIAMOND_PICKAXE: Enchantability = 10; break;
case E_ITEM_DIAMOND_SHOVEL: Enchantability = 10; break;
case E_ITEM_DIAMOND_AXE: Enchantability = 10; break;
case E_ITEM_DIAMOND_HOE: Enchantability = 10; break;
case E_ITEM_GOLD_HELMET: Enchantability = 25; break;
case E_ITEM_GOLD_CHESTPLATE: Enchantability = 25; break;
case E_ITEM_GOLD_LEGGINGS: Enchantability = 25; break;
case E_ITEM_GOLD_BOOTS: Enchantability = 25; break;
case E_ITEM_GOLD_SWORD: Enchantability = 22; break;
case E_ITEM_GOLD_PICKAXE: Enchantability = 22; break;
case E_ITEM_GOLD_SHOVEL: Enchantability = 22; break;
case E_ITEM_GOLD_AXE: Enchantability = 22; break;
case E_ITEM_GOLD_HOE: Enchantability = 22; break;
case E_ITEM_FISHING_ROD: Enchantability = 1; break;
case E_ITEM_BOW: Enchantability = 1; break;
case E_ITEM_BOOK: Enchantability = 1; break;
}
return Enchantability;
}
bool cItem::EnchantByXPLevels(int a_NumXPLevels)
{
if (!cItem::IsEnchantable(m_ItemType) && (m_ItemType != E_ITEM_BOOK))
{
return false;
}
int Enchantability = GetEnchantability();
cFastRandom Random;
int ModifiedEnchantmentLevel = a_NumXPLevels + (int)Random.NextFloat((float)Enchantability / 4) + (int)Random.NextFloat((float)Enchantability / 4) + 1;
float RandomBonus = 1.0F + (Random.NextFloat(1) + Random.NextFloat(1) - 1.0F) * 0.15F;
int FinalEnchantmentLevel = (int)(ModifiedEnchantmentLevel * RandomBonus + 0.5F);
cWeightedEnchantments enchantments;
cEnchantments::AddItemEnchantmentWeights(enchantments, m_ItemType, FinalEnchantmentLevel);
if (m_ItemType == E_ITEM_BOOK)
{
m_ItemType = E_ITEM_ENCHANTED_BOOK;
}
cEnchantments Enchantment1 = cEnchantments::GetRandomEnchantmentFromVector(enchantments);
m_Enchantments.AddFromString(Enchantment1.ToString());
cEnchantments::RemoveEnchantmentWeightFromVector(enchantments, Enchantment1);
// Checking for conflicting enchantments
cEnchantments::CheckEnchantmentConflictsFromVector(enchantments, Enchantment1);
float NewEnchantmentLevel = (float)a_NumXPLevels;
// Next Enchantment (Second)
NewEnchantmentLevel = NewEnchantmentLevel / 2;
float SecondEnchantmentChance = (NewEnchantmentLevel + 1) / 50 * 100;
if ((Random.NextFloat(100) > SecondEnchantmentChance) || (enchantments.size() == 0))
{
return false;
}
cEnchantments Enchantment2 = cEnchantments::GetRandomEnchantmentFromVector(enchantments);
m_Enchantments.AddFromString(Enchantment2.ToString());
cEnchantments::RemoveEnchantmentWeightFromVector(enchantments, Enchantment2);
// Checking for conflicting enchantments
cEnchantments::CheckEnchantmentConflictsFromVector(enchantments, Enchantment2);
// Next Enchantment (Third)
NewEnchantmentLevel = NewEnchantmentLevel / 2;
float ThirdEnchantmentChance = (NewEnchantmentLevel + 1) / 50 * 100;
if ((Random.NextFloat(100) > ThirdEnchantmentChance) || (enchantments.size() == 0))
{
return false;
}
cEnchantments Enchantment3 = cEnchantments::GetRandomEnchantmentFromVector(enchantments);
m_Enchantments.AddFromString(Enchantment3.ToString());
cEnchantments::RemoveEnchantmentWeightFromVector(enchantments, Enchantment3);
// Checking for conflicting enchantments
cEnchantments::CheckEnchantmentConflictsFromVector(enchantments, Enchantment3);
// Next Enchantment (Fourth)
NewEnchantmentLevel = NewEnchantmentLevel / 2;
float FourthEnchantmentChance = (NewEnchantmentLevel + 1) / 50 * 100;
if ((Random.NextFloat(100) > FourthEnchantmentChance) || (enchantments.size() == 0))
{
return false;
}
cEnchantments Enchantment4 = cEnchantments::GetRandomEnchantmentFromVector(enchantments);
m_Enchantments.AddFromString(Enchantment4.ToString());
return true;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// cItems:

View File

@ -175,6 +175,13 @@ public:
/** Returns true if the specified item type is enchantable (as per 1.2.5 protocol requirements) */
static bool IsEnchantable(short a_ItemType); // tolua_export
/** Returns the enchantability of the item. When the item hasn't a enchantability, it will returns 0 */
int GetEnchantability(); // tolua_export
/** Enchants the item using the specified number of XP levels.
Returns true if item enchanted, false if not. */
bool EnchantByXPLevels(int a_NumXPLevels); // tolua_export
// tolua_begin
short m_ItemType;

View File

@ -96,6 +96,7 @@ enum
PACKET_INVENTORY_WHOLE = 0x68,
PACKET_WINDOW_PROPERTY = 0x69,
PACKET_CREATIVE_INVENTORY_ACTION = 0x6B,
PACKET_ENCHANT_ITEM = 0x6C,
PACKET_UPDATE_SIGN = 0x82,
PACKET_ITEM_DATA = 0x83,
PACKET_PLAYER_LIST_ITEM = 0xC9,
@ -1278,6 +1279,7 @@ int cProtocol125::ParsePacket(unsigned char a_PacketType)
case PACKET_SLOT_SELECTED: return ParseSlotSelected();
case PACKET_UPDATE_SIGN: return ParseUpdateSign();
case PACKET_USE_ENTITY: return ParseUseEntity();
case PACKET_ENCHANT_ITEM: return ParseEnchantItem();
case PACKET_WINDOW_CLICK: return ParseWindowClick();
case PACKET_WINDOW_CLOSE: return ParseWindowClose();
}
@ -1639,6 +1641,20 @@ int cProtocol125::ParseUseEntity(void)
int cProtocol125::ParseEnchantItem(void)
{
HANDLE_PACKET_READ(ReadByte, Byte, WindowID);
HANDLE_PACKET_READ(ReadByte, Byte, Enchantment);
m_Client->HandleEnchantItem(WindowID, Enchantment);
return PARSE_OK;
}
int cProtocol125::ParseWindowClick(void)
{
HANDLE_PACKET_READ(ReadChar, char, WindowID);

View File

@ -143,6 +143,7 @@ protected:
virtual int ParseSlotSelected (void);
virtual int ParseUpdateSign (void);
virtual int ParseUseEntity (void);
virtual int ParseEnchantItem (void);
virtual int ParseWindowClick (void);
virtual int ParseWindowClose (void);

View File

@ -1580,6 +1580,7 @@ bool cProtocol172::HandlePacket(cByteBuffer & a_ByteBuffer, UInt32 a_PacketType)
case 0x0e: HandlePacketWindowClick (a_ByteBuffer); return true;
case 0x0f: // Confirm transaction - not used in MCS
case 0x10: HandlePacketCreativeInventoryAction(a_ByteBuffer); return true;
case 0x11: HandlePacketEnchantItem (a_ByteBuffer); return true;
case 0x12: HandlePacketUpdateSign (a_ByteBuffer); return true;
case 0x13: HandlePacketPlayerAbilities (a_ByteBuffer); return true;
case 0x14: HandlePacketTabComplete (a_ByteBuffer); return true;
@ -2044,6 +2045,18 @@ void cProtocol172::HandlePacketUseEntity(cByteBuffer & a_ByteBuffer)
void cProtocol172::HandlePacketEnchantItem(cByteBuffer & a_ByteBuffer)
{
HANDLE_READ(a_ByteBuffer, ReadByte, Byte, WindowID);
HANDLE_READ(a_ByteBuffer, ReadByte, Byte, Enchantment);
m_Client->HandleEnchantItem(WindowID, Enchantment);
}
void cProtocol172::HandlePacketWindowClick(cByteBuffer & a_ByteBuffer)
{
HANDLE_READ(a_ByteBuffer, ReadChar, char, WindowID);

View File

@ -280,6 +280,7 @@ protected:
void HandlePacketTabComplete (cByteBuffer & a_ByteBuffer);
void HandlePacketUpdateSign (cByteBuffer & a_ByteBuffer);
void HandlePacketUseEntity (cByteBuffer & a_ByteBuffer);
void HandlePacketEnchantItem (cByteBuffer & a_ByteBuffer);
void HandlePacketWindowClick (cByteBuffer & a_ByteBuffer);
void HandlePacketWindowClose (cByteBuffer & a_ByteBuffer);

View File

@ -13,6 +13,8 @@
#include "Window.h"
#include "../CraftingRecipes.h"
#include "../Root.h"
#include "../FastRandom.h"
#include "../BlockArea.h"
@ -145,6 +147,7 @@ void cSlotArea::Clicked(cPlayer & a_Player, int a_SlotNum, eClickAction a_ClickA
FreeSlots = 0;
}
int Filling = (FreeSlots > DraggingItem.m_ItemCount) ? DraggingItem.m_ItemCount : FreeSlots;
Slot.m_ItemCount += (char)Filling;
DraggingItem.m_ItemCount -= (char)Filling;
if (DraggingItem.m_ItemCount <= 0)
@ -167,7 +170,6 @@ void cSlotArea::Clicked(cPlayer & a_Player, int a_SlotNum, eClickAction a_ClickA
{
m_ParentWindow.BroadcastWholeWindow();
}
}
@ -592,6 +594,307 @@ cCraftingRecipe & cSlotAreaCrafting::GetRecipeForPlayer(cPlayer & a_Player)
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// cSlotAreaEnchanting:
cSlotAreaEnchanting::cSlotAreaEnchanting(cEnchantingWindow & a_ParentWindow) :
cSlotAreaTemporary(1, a_ParentWindow)
{
a_ParentWindow.m_SlotArea = this;
}
void cSlotAreaEnchanting::Clicked(cPlayer & a_Player, int a_SlotNum, eClickAction a_ClickAction, const cItem & a_ClickedItem)
{
ASSERT((a_SlotNum >= 0) && (a_SlotNum < GetNumSlots()));
bool bAsync = false;
if (GetSlot(a_SlotNum, a_Player) == NULL)
{
LOGWARNING("GetSlot(%d) returned NULL! Ignoring click", a_SlotNum);
return;
}
switch (a_ClickAction)
{
case caShiftLeftClick:
case caShiftRightClick:
{
ShiftClicked(a_Player, a_SlotNum, a_ClickedItem);
return;
}
case caDblClick:
{
DblClicked(a_Player, a_SlotNum);
return;
}
default:
{
break;
}
}
cItem Slot(*GetSlot(a_SlotNum, a_Player));
if (!Slot.IsSameType(a_ClickedItem))
{
LOGWARNING("*** Window lost sync at item %d in SlotArea with %d items ***", a_SlotNum, m_NumSlots);
LOGWARNING("My item: %s", ItemToFullString(Slot).c_str());
LOGWARNING("Their item: %s", ItemToFullString(a_ClickedItem).c_str());
bAsync = true;
}
cItem & DraggingItem = a_Player.GetDraggingItem();
switch (a_ClickAction)
{
case caRightClick:
{
// Right-clicked
if (DraggingItem.IsEmpty())
{
DraggingItem = Slot.CopyOne();
Slot.Empty();
break;
}
if (Slot.IsEmpty())
{
Slot = DraggingItem.CopyOne();
DraggingItem.m_ItemCount -= 1;
if (DraggingItem.m_ItemCount <= 0)
{
DraggingItem.Empty();
}
}
else if ((!DraggingItem.IsEqual(Slot)) && (DraggingItem.m_ItemCount == 1))
{
// Swap contents
cItem tmp(DraggingItem);
DraggingItem = Slot;
Slot = tmp;
}
break;
}
case caLeftClick:
{
// Left-clicked
if (DraggingItem.IsEmpty())
{
DraggingItem = Slot.CopyOne();
Slot.Empty();
break;
}
if (DraggingItem.IsEqual(Slot))
{
// Do nothing
break;
}
if (!Slot.IsEmpty())
{
if (DraggingItem.m_ItemCount == 1)
{
// Swap contents
cItem tmp(DraggingItem);
DraggingItem = Slot;
Slot = tmp;
}
}
else
{
Slot = DraggingItem.CopyOne();
DraggingItem.m_ItemCount -= 1;
if (DraggingItem.m_ItemCount <= 0)
{
DraggingItem.Empty();
}
}
break;
}
default:
{
LOGWARNING("SlotArea: Unhandled click action: %d (%s)", a_ClickAction, ClickActionToString(a_ClickAction));
m_ParentWindow.BroadcastWholeWindow();
return;
}
} // switch (a_ClickAction
SetSlot(a_SlotNum, a_Player, Slot);
if (bAsync)
{
m_ParentWindow.BroadcastWholeWindow();
}
UpdateResult(a_Player);
}
void cSlotAreaEnchanting::DblClicked(cPlayer & a_Player, int a_SlotNum)
{
cItem & Dragging = a_Player.GetDraggingItem();
if ((!Dragging.IsEmpty()) || (a_SlotNum != 0))
{
return;
}
cItem Item = *GetSlot(0, a_Player);
if (!m_ParentWindow.CollectItemsToHand(Item, *this, a_Player, false))
{
m_ParentWindow.CollectItemsToHand(Item, *this, a_Player, true);
}
}
void cSlotAreaEnchanting::DistributeStack(cItem & a_ItemStack, cPlayer & a_Player, bool a_Apply, bool a_KeepEmptySlots)
{
const cItem * Slot = GetSlot(0, a_Player);
if (!Slot->IsEmpty())
{
return;
}
if (a_Apply)
{
SetSlot(0, a_Player, a_ItemStack.CopyOne());
}
a_ItemStack.m_ItemCount -= 1;
if (a_ItemStack.m_ItemCount <= 0)
{
a_ItemStack.Empty();
}
UpdateResult(a_Player);
}
void cSlotAreaEnchanting::OnPlayerRemoved(cPlayer & a_Player)
{
// Toss the item in the enchanting slot
TossItems(a_Player, 0, 1);
super::OnPlayerRemoved(a_Player);
}
void cSlotAreaEnchanting::UpdateResult(cPlayer & a_Player)
{
cItem Item = *GetSlot(0, a_Player);
if (Item.IsEmpty() || !Item.m_Enchantments.IsEmpty())
{
m_ParentWindow.SetProperty(0, 0, a_Player);
m_ParentWindow.SetProperty(1, 0, a_Player);
m_ParentWindow.SetProperty(2, 0, a_Player);
}
else if (cItem::IsEnchantable(Item.m_ItemType) || Item.m_ItemType == E_ITEM_BOOK)
{
int Bookshelves = std::min(GetBookshelvesCount(a_Player.GetWorld()), 15);
cFastRandom Random;
int base = (Random.GenerateRandomInteger(1, 8) + floor(Bookshelves / 2) + Random.GenerateRandomInteger(0, Bookshelves));
int topSlot = std::max(base / 3, 1);
int middleSlot = (base * 2) / 3 + 1;
int bottomSlot = std::max(base, Bookshelves * 2);
m_ParentWindow.SetProperty(0, topSlot, a_Player);
m_ParentWindow.SetProperty(1, middleSlot, a_Player);
m_ParentWindow.SetProperty(2, bottomSlot, a_Player);
}
else
{
m_ParentWindow.SetProperty(0, 0, a_Player);
m_ParentWindow.SetProperty(1, 0, a_Player);
m_ParentWindow.SetProperty(2, 0, a_Player);
}
}
int cSlotAreaEnchanting::GetBookshelvesCount(cWorld * a_World)
{
int PosX, PosY, PosZ;
((cEnchantingWindow*)&m_ParentWindow)->GetBlockPos(PosX, PosY, PosZ);
int Bookshelves = 0;
cBlockArea Area;
Area.Read(a_World, PosX - 2, PosX + 2, PosY, PosY + 1, PosZ - 2, PosZ + 2);
static const struct
{
int m_BookX, m_BookY, m_BookZ; // Coords to check for bookcases
int m_AirX, m_AirY, m_AirZ; // Coords to check for air; if not air, the bookcase won't be counted
} CheckCoords[] =
{
{ 0, 0, 0, 1, 0, 1 }, // Bookcase at {0, 0, 0}, air at {1, 0, 1}
{ 0, 0, 1, 1, 0, 1 }, // Bookcase at {0, 0, 1}, air at {1, 0, 1}
{ 0, 0, 2, 1, 0, 2 }, // Bookcase at {0, 0, 2}, air at {1, 0, 2}
{ 0, 0, 3, 1, 0, 3 }, // Bookcase at {0, 0, 3}, air at {1, 0, 3}
{ 0, 0, 4, 1, 0, 3 }, // Bookcase at {0, 0, 4}, air at {1, 0, 3}
{ 1, 0, 4, 1, 0, 3 }, // Bookcase at {1, 0, 4}, air at {1, 0, 3}
{ 2, 0, 4, 2, 0, 3 }, // Bookcase at {2, 0, 4}, air at {2, 0, 3}
{ 3, 0, 4, 3, 0, 3 }, // Bookcase at {3, 0, 4}, air at {3, 0, 3}
{ 4, 0, 4, 3, 0, 3 }, // Bookcase at {4, 0, 4}, air at {3, 0, 3}
{ 4, 0, 3, 3, 0, 3 }, // Bookcase at {4, 0, 3}, air at {3, 0, 3}
{ 4, 0, 2, 3, 0, 2 }, // Bookcase at {4, 0, 2}, air at {3, 0, 2}
{ 4, 0, 1, 3, 0, 1 }, // Bookcase at {4, 0, 1}, air at {3, 0, 1}
{ 4, 0, 0, 3, 0, 1 }, // Bookcase at {4, 0, 0}, air at {3, 0, 1}
{ 3, 0, 0, 3, 0, 1 }, // Bookcase at {3, 0, 0}, air at {3, 0, 1}
{ 2, 0, 0, 2, 0, 1 }, // Bookcase at {2, 0, 0}, air at {2, 0, 1}
{ 1, 0, 0, 1, 0, 1 }, // Bookcase at {1, 0, 0}, air at {1, 0, 1}
{ 0, 1, 0, 1, 1, 1 }, // Bookcase at {0, 1, 0}, air at {1, 1, 1}
{ 0, 1, 1, 1, 1, 1 }, // Bookcase at {0, 1, 1}, air at {1, 1, 1}
{ 0, 1, 2, 1, 1, 2 }, // Bookcase at {0, 1, 2}, air at {1, 1, 2}
{ 0, 1, 3, 1, 1, 3 }, // Bookcase at {0, 1, 3}, air at {1, 1, 3}
{ 0, 1, 4, 1, 1, 3 }, // Bookcase at {0, 1, 4}, air at {1, 1, 3}
{ 1, 1, 4, 1, 1, 3 }, // Bookcase at {1, 1, 4}, air at {1, 1, 3}
{ 2, 1, 4, 2, 1, 3 }, // Bookcase at {2, 1, 4}, air at {2, 1, 3}
{ 3, 1, 4, 3, 1, 3 }, // Bookcase at {3, 1, 4}, air at {3, 1, 3}
{ 4, 1, 4, 3, 1, 3 }, // Bookcase at {4, 1, 4}, air at {3, 1, 3}
{ 4, 1, 3, 3, 1, 3 }, // Bookcase at {4, 1, 3}, air at {3, 1, 3}
{ 4, 1, 2, 3, 1, 2 }, // Bookcase at {4, 1, 2}, air at {3, 1, 2}
{ 4, 1, 1, 3, 1, 1 }, // Bookcase at {4, 1, 1}, air at {3, 1, 1}
{ 4, 1, 0, 3, 1, 1 }, // Bookcase at {4, 1, 0}, air at {3, 1, 1}
{ 3, 1, 0, 3, 1, 1 }, // Bookcase at {3, 1, 0}, air at {3, 1, 1}
{ 2, 1, 0, 2, 1, 1 }, // Bookcase at {2, 1, 0}, air at {2, 1, 1}
{ 1, 1, 0, 1, 1, 1 }, // Bookcase at {1, 1, 0}, air at {1, 1, 1}
};
for (size_t i = 0; i < ARRAYCOUNT(CheckCoords); i++)
{
if (
(Area.GetRelBlockType(CheckCoords[i].m_AirX, CheckCoords[i].m_AirY, CheckCoords[i].m_AirZ) == E_BLOCK_AIR) && // There's air in the checkspot
(Area.GetRelBlockType(CheckCoords[i].m_BookX, CheckCoords[i].m_BookY, CheckCoords[i].m_BookZ) == E_BLOCK_BOOKCASE) // There's bookcase in the wanted place
)
{
Bookshelves++;
}
} // for i - CheckCoords
return Bookshelves;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// cSlotAreaEnderChest:

View File

@ -19,6 +19,8 @@ class cDropSpenserEntity;
class cEnderChestEntity;
class cFurnaceEntity;
class cCraftingRecipe;
class cEnchantingWindow;
class cWorld;
@ -66,7 +68,7 @@ public:
/// If a_CollectFullStacks is false, slots with full stacks are skipped while collecting.
/// Returns true if full stack has been collected in a_Dragging, false if there's space remaining to fill.
virtual bool CollectItemsToHand(cItem & a_Dragging, cPlayer & a_Player, bool a_CollectFullStacks);
protected:
int m_NumSlots;
cWindow & m_ParentWindow;
@ -252,6 +254,34 @@ protected:
class cSlotAreaEnchanting :
public cSlotAreaTemporary
{
typedef cSlotAreaTemporary super;
public:
cSlotAreaEnchanting(cEnchantingWindow & a_ParentWindow);
// cSlotArea overrides:
virtual void Clicked(cPlayer & a_Player, int a_SlotNum, eClickAction a_ClickAction, const cItem & a_ClickedItem) override;
virtual void DblClicked(cPlayer & a_Player, int a_SlotNum) override;
virtual void DistributeStack(cItem & a_ItemStack, cPlayer & a_Player, bool a_ShouldApply, bool a_KeepEmptySlots) override;
// cSlotAreaTemporary overrides:
virtual void OnPlayerRemoved(cPlayer & a_Player) override;
/* Get the count of bookshelves who stand in the near of the enchanting table */
int GetBookshelvesCount(cWorld * a_World);
protected:
/** Handles a click in the item slot. */
void UpdateResult(cPlayer & a_Player);
};
class cSlotAreaChest :
public cSlotArea
{

View File

@ -804,6 +804,66 @@ cCraftingWindow::cCraftingWindow(int a_BlockX, int a_BlockY, int a_BlockZ) :
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// cEnchantingWindow:
cEnchantingWindow::cEnchantingWindow(int a_BlockX, int a_BlockY, int a_BlockZ) :
cWindow(wtEnchantment, "Enchant"),
m_BlockX(a_BlockX),
m_BlockY(a_BlockY),
m_BlockZ(a_BlockZ)
{
m_SlotAreas.push_back(new cSlotAreaEnchanting(*this));
m_SlotAreas.push_back(new cSlotAreaInventory(*this));
m_SlotAreas.push_back(new cSlotAreaHotBar(*this));
}
void cEnchantingWindow::SetProperty(int a_Property, int a_Value)
{
m_PropertyValue[a_Property] = a_Value;
super::SetProperty(a_Property, a_Value);
}
void cEnchantingWindow::SetProperty(int a_Property, int a_Value, cPlayer & a_Player)
{
m_PropertyValue[a_Property] = a_Value;
super::SetProperty(a_Property, a_Value, a_Player);
}
int cEnchantingWindow::GetPropertyValue(int a_Property)
{
return m_PropertyValue[a_Property];
}
void cEnchantingWindow::GetBlockPos(int & a_PosX, int & a_PosY, int & a_PosZ)
{
a_PosX = m_BlockX;
a_PosY = m_BlockY;
a_PosZ = m_BlockZ;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// cChestWindow:

View File

@ -136,11 +136,11 @@ public:
void SetWindowTitle(const AString & a_WindowTitle ) { m_WindowTitle = a_WindowTitle; }
/// Sends the UpdateWindowProperty (0x69) packet to all clients of the window
void SetProperty(int a_Property, int a_Value);
virtual void SetProperty(int a_Property, int a_Value);
/// Sends the UpdateWindowPropert(0x69) packet to the specified player
void SetProperty(int a_Property, int a_Value, cPlayer & a_Player);
virtual void SetProperty(int a_Property, int a_Value, cPlayer & a_Player);
// tolua_end
void OwnerDestroyed(void);
@ -165,7 +165,7 @@ public:
/// Used by cSlotAreas to send individual slots to clients, a_RelativeSlotNum is the slot number relative to a_SlotArea
void SendSlot(cPlayer & a_Player, cSlotArea * a_SlotArea, int a_RelativeSlotNum);
protected:
cSlotAreas m_SlotAreas;
@ -231,6 +231,32 @@ public:
class cEnchantingWindow :
public cWindow
{
typedef cWindow super;
public:
cEnchantingWindow(int a_BlockX, int a_BlockY, int a_BlockZ);
virtual void SetProperty(int a_Property, int a_Value, cPlayer & a_Player) override;
virtual void SetProperty(int a_Property, int a_Value) override;
/** Return the Value of a Property */
int GetPropertyValue(int a_Property);
/** Set the Position Values to the Position of the Enchantment Table */
void GetBlockPos(int & a_PosX, int & a_PosY, int & a_PosZ);
cSlotArea * m_SlotArea;
protected:
int m_PropertyValue[3];
int m_BlockX, m_BlockY, m_BlockZ;
};
class cFurnaceWindow :
public cWindow
{