Merge pull request #1424 from Howaner/Fixes

Fixes
master
Mattes D 2014-09-12 20:43:05 +02:00
commit db13405da2
21 changed files with 169 additions and 85 deletions

View File

@ -590,7 +590,7 @@ void cBlockInfo::Initialize(cBlockInfoArray & a_Info)
a_Info[E_BLOCK_LOG ].m_PlaceSound = "dig.wood";
a_Info[E_BLOCK_LEAVES ].m_PlaceSound = "dig.grass";
a_Info[E_BLOCK_SPONGE ].m_PlaceSound = "dig.grass";
a_Info[E_BLOCK_GLASS ].m_PlaceSound = "dig.glass";
a_Info[E_BLOCK_GLASS ].m_PlaceSound = "dig.stone";
a_Info[E_BLOCK_LAPIS_ORE ].m_PlaceSound = "dig.stone";
a_Info[E_BLOCK_LAPIS_BLOCK ].m_PlaceSound = "dig.stone";
a_Info[E_BLOCK_DISPENSER ].m_PlaceSound = "dig.stone";
@ -647,7 +647,7 @@ void cBlockInfo::Initialize(cBlockInfoArray & a_Info)
a_Info[E_BLOCK_REDSTONE_TORCH_ON ].m_PlaceSound = "dig.wood";
a_Info[E_BLOCK_STONE_BUTTON ].m_PlaceSound = "dig.stone";
a_Info[E_BLOCK_SNOW ].m_PlaceSound = "dig.snow";
a_Info[E_BLOCK_ICE ].m_PlaceSound = "dig.glass";
a_Info[E_BLOCK_ICE ].m_PlaceSound = "dig.stone";
a_Info[E_BLOCK_SNOW_BLOCK ].m_PlaceSound = "dig.snow";
a_Info[E_BLOCK_CACTUS ].m_PlaceSound = "dig.cloth";
a_Info[E_BLOCK_CLAY ].m_PlaceSound = "dig.gravel";
@ -657,20 +657,20 @@ void cBlockInfo::Initialize(cBlockInfoArray & a_Info)
a_Info[E_BLOCK_PUMPKIN ].m_PlaceSound = "dig.wood";
a_Info[E_BLOCK_NETHERRACK ].m_PlaceSound = "dig.stone";
a_Info[E_BLOCK_SOULSAND ].m_PlaceSound = "dig.sand";
a_Info[E_BLOCK_GLOWSTONE ].m_PlaceSound = "dig.glass";
a_Info[E_BLOCK_NETHER_PORTAL ].m_PlaceSound = "dig.glass";
a_Info[E_BLOCK_GLOWSTONE ].m_PlaceSound = "dig.stone";
a_Info[E_BLOCK_NETHER_PORTAL ].m_PlaceSound = "dig.stone";
a_Info[E_BLOCK_JACK_O_LANTERN ].m_PlaceSound = "dig.wood";
a_Info[E_BLOCK_CAKE ].m_PlaceSound = "dig.snow";
a_Info[E_BLOCK_REDSTONE_REPEATER_OFF ].m_PlaceSound = "dig.wood";
a_Info[E_BLOCK_REDSTONE_REPEATER_ON ].m_PlaceSound = "dig.wood";
a_Info[E_BLOCK_STAINED_GLASS ].m_PlaceSound = "dig.glass";
a_Info[E_BLOCK_STAINED_GLASS ].m_PlaceSound = "dig.stone";
a_Info[E_BLOCK_TRAPDOOR ].m_PlaceSound = "dig.wood";
a_Info[E_BLOCK_SILVERFISH_EGG ].m_PlaceSound = "dig.stone";
a_Info[E_BLOCK_STONE_BRICKS ].m_PlaceSound = "dig.stone";
a_Info[E_BLOCK_HUGE_BROWN_MUSHROOM ].m_PlaceSound = "dig.wood";
a_Info[E_BLOCK_HUGE_RED_MUSHROOM ].m_PlaceSound = "dig.wood";
a_Info[E_BLOCK_IRON_BARS ].m_PlaceSound = "dig.metal";
a_Info[E_BLOCK_GLASS_PANE ].m_PlaceSound = "dig.glass";
a_Info[E_BLOCK_GLASS_PANE ].m_PlaceSound = "dig.stone";
a_Info[E_BLOCK_MELON ].m_PlaceSound = "dig.wood";
a_Info[E_BLOCK_PUMPKIN_STEM ].m_PlaceSound = "dig.wood";
a_Info[E_BLOCK_MELON_STEM ].m_PlaceSound = "dig.wood";
@ -687,12 +687,12 @@ void cBlockInfo::Initialize(cBlockInfoArray & a_Info)
a_Info[E_BLOCK_ENCHANTMENT_TABLE ].m_PlaceSound = "dig.stone";
a_Info[E_BLOCK_BREWING_STAND ].m_PlaceSound = "dig.stone";
a_Info[E_BLOCK_CAULDRON ].m_PlaceSound = "dig.stone";
a_Info[E_BLOCK_END_PORTAL ].m_PlaceSound = "dig.glass";
a_Info[E_BLOCK_END_PORTAL_FRAME ].m_PlaceSound = "dig.glass";
a_Info[E_BLOCK_END_PORTAL ].m_PlaceSound = "dig.stone";
a_Info[E_BLOCK_END_PORTAL_FRAME ].m_PlaceSound = "dig.stone";
a_Info[E_BLOCK_END_STONE ].m_PlaceSound = "dig.stone";
a_Info[E_BLOCK_DRAGON_EGG ].m_PlaceSound = "dig.stone";
a_Info[E_BLOCK_REDSTONE_LAMP_OFF ].m_PlaceSound = "dig.glass";
a_Info[E_BLOCK_REDSTONE_LAMP_ON ].m_PlaceSound = "dig.glass";
a_Info[E_BLOCK_REDSTONE_LAMP_OFF ].m_PlaceSound = "dig.stone";
a_Info[E_BLOCK_REDSTONE_LAMP_ON ].m_PlaceSound = "dig.stone";
a_Info[E_BLOCK_DOUBLE_WOODEN_SLAB ].m_PlaceSound = "dig.wood";
a_Info[E_BLOCK_WOODEN_SLAB ].m_PlaceSound = "dig.wood";
a_Info[E_BLOCK_COCOA_POD ].m_PlaceSound = "dig.wood";
@ -712,7 +712,7 @@ void cBlockInfo::Initialize(cBlockInfoArray & a_Info)
a_Info[E_BLOCK_CARROTS ].m_PlaceSound = "dig.grass";
a_Info[E_BLOCK_POTATOES ].m_PlaceSound = "dig.grass";
a_Info[E_BLOCK_HEAD ].m_PlaceSound = "dig.stone";
a_Info[E_BLOCK_ANVIL ].m_PlaceSound = "dig.anvil";
a_Info[E_BLOCK_ANVIL ].m_PlaceSound = "random.anvil_land";
a_Info[E_BLOCK_TRAPPED_CHEST ].m_PlaceSound = "dig.wood";
a_Info[E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE ].m_PlaceSound = "dig.wood";
a_Info[E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE ].m_PlaceSound = "dig.wood";
@ -727,7 +727,7 @@ void cBlockInfo::Initialize(cBlockInfoArray & a_Info)
a_Info[E_BLOCK_ACTIVATOR_RAIL ].m_PlaceSound = "dig.metal";
a_Info[E_BLOCK_DROPPER ].m_PlaceSound = "dig.stone";
a_Info[E_BLOCK_STAINED_CLAY ].m_PlaceSound = "dig.stone";
a_Info[E_BLOCK_STAINED_GLASS_PANE ].m_PlaceSound = "dig.glass";
a_Info[E_BLOCK_STAINED_GLASS_PANE ].m_PlaceSound = "dig.stone";
a_Info[E_BLOCK_NEW_LEAVES ].m_PlaceSound = "dig.grass";
a_Info[E_BLOCK_NEW_LOG ].m_PlaceSound = "dig.wood";
a_Info[E_BLOCK_ACACIA_WOOD_STAIRS ].m_PlaceSound = "dig.wood";
@ -736,7 +736,7 @@ void cBlockInfo::Initialize(cBlockInfoArray & a_Info)
a_Info[E_BLOCK_CARPET ].m_PlaceSound = "dig.cloth";
a_Info[E_BLOCK_HARDENED_CLAY ].m_PlaceSound = "dig.stone";
a_Info[E_BLOCK_BLOCK_OF_COAL ].m_PlaceSound = "dig.stone";
a_Info[E_BLOCK_PACKED_ICE ].m_PlaceSound = "dig.glass";
a_Info[E_BLOCK_PACKED_ICE ].m_PlaceSound = "dig.stone";
a_Info[E_BLOCK_BIG_FLOWER ].m_PlaceSound = "dig.grass";
}

View File

@ -15,7 +15,7 @@ void cBlockBedHandler::OnPlacedByPlayer(
if (a_BlockMeta < 8)
{
Vector3i Direction = MetaDataToDirection(a_BlockMeta);
a_ChunkInterface.SetBlock(a_WorldInterface, a_BlockX + Direction.x, a_BlockY, a_BlockZ + Direction.z, E_BLOCK_BED, a_BlockMeta | 0x8);
a_ChunkInterface.SetBlock(a_BlockX + Direction.x, a_BlockY, a_BlockZ + Direction.z, E_BLOCK_BED, a_BlockMeta | 0x8);
}
}

View File

@ -102,7 +102,7 @@ void cBlockDoorHandler::OnPlacedByPlayer(
{
a_TopBlockMeta = 9;
}
a_ChunkInterface.SetBlock(a_WorldInterface, a_BlockX, a_BlockY + 1, a_BlockZ, m_BlockType, a_TopBlockMeta);
a_ChunkInterface.SetBlock(a_BlockX, a_BlockY + 1, a_BlockZ, m_BlockType, a_TopBlockMeta);
}

View File

@ -28,49 +28,12 @@ public:
virtual void OnUpdate(cChunkInterface & cChunkInterface, cWorldInterface & a_WorldInterface, cBlockPluginInterface & a_PluginInterface, cChunk & a_Chunk, int a_RelX, int a_RelY, int a_RelZ) override
{
bool Found = false;
EMCSBiome Biome = a_Chunk.GetBiomeAt(a_RelX, a_RelZ);
if (a_Chunk.GetWorld()->IsWeatherWet() && !IsBiomeNoDownfall(Biome))
{
// Rain hydrates farmland, too, except in Desert biomes.
Found = true;
}
else
{
// Search for water in a close proximity:
// Ref.: http://www.minecraftwiki.net/wiki/Farmland#Hydrated_Farmland_Tiles
// TODO: Rewrite this to use the chunk and its neighbors directly
cBlockArea Area;
int BlockX = a_RelX + a_Chunk.GetPosX() * cChunkDef::Width;
int BlockZ = a_RelZ + a_Chunk.GetPosZ() * cChunkDef::Width;
if (!Area.Read(a_Chunk.GetWorld(), BlockX - 4, BlockX + 4, a_RelY, a_RelY + 1, BlockZ - 4, BlockZ + 4))
{
// Too close to the world edge, cannot check surroundings; don't tick at all
return;
}
size_t NumBlocks = Area.GetBlockCount();
BLOCKTYPE * BlockTypes = Area.GetBlockTypes();
for (size_t i = 0; i < NumBlocks; i++)
{
if (IsBlockWater(BlockTypes[i]))
{
Found = true;
break;
}
} // for i - BlockTypes[]
}
NIBBLETYPE BlockMeta = a_Chunk.GetMeta(a_RelX, a_RelY, a_RelZ);
if (Found)
if (IsWaterInNear(a_Chunk, a_RelX, a_RelY, a_RelZ))
{
// Water was found, hydrate the block until hydration reaches 7:
if (BlockMeta < 7)
{
a_Chunk.FastSetBlock(a_RelX, a_RelY, a_RelZ, m_BlockType, ++BlockMeta);
}
// Water was found, set block meta to 7
a_Chunk.FastSetBlock(a_RelX, a_RelY, a_RelZ, m_BlockType, 7);
return;
}
@ -80,9 +43,10 @@ public:
a_Chunk.FastSetBlock(a_RelX, a_RelY, a_RelZ, E_BLOCK_FARMLAND, --BlockMeta);
return;
}
// Farmland too dry. If nothing is growing on top, turn back to dirt:
switch (a_Chunk.GetBlock(a_RelX, a_RelY + 1, a_RelZ))
BLOCKTYPE UpperBlock = (a_RelY >= cChunkDef::Height) ? E_BLOCK_AIR : a_Chunk.GetBlock(a_RelX, a_RelY + 1, a_RelZ);
switch (UpperBlock)
{
case E_BLOCK_CROPS:
case E_BLOCK_POTATOES:
@ -95,16 +59,63 @@ public:
}
default:
{
a_Chunk.FastSetBlock(a_RelX, a_RelY, a_RelZ, E_BLOCK_DIRT, 0);
a_Chunk.SetBlock(a_RelX, a_RelY, a_RelZ, E_BLOCK_DIRT, 0);
break;
}
}
}
virtual void OnNeighborChanged(cChunkInterface & a_ChunkInterface, int a_BlockX, int a_BlockY, int a_BlockZ) override
{
if (a_BlockY >= cChunkDef::Height)
{
return;
}
BLOCKTYPE UpperBlock = a_ChunkInterface.GetBlock(a_BlockX, a_BlockY + 1, a_BlockZ);
if (cBlockInfo::FullyOccupiesVoxel(UpperBlock))
{
a_ChunkInterface.SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_DIRT, 0);
}
}
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
{
a_Pickups.Add(E_BLOCK_DIRT, 1, 0); // Reset meta
}
bool IsWaterInNear(cChunk & a_Chunk, int a_RelX, int a_RelY, int a_RelZ)
{
if (a_Chunk.GetWorld()->IsWeatherWetAt(a_RelX, a_RelZ))
{
// Rain hydrates farmland, too, except in Desert biomes.
return true;
}
// Search for water in a close proximity:
// Ref.: http://www.minecraftwiki.net/wiki/Farmland#Hydrated_Farmland_Tiles
// TODO: Rewrite this to use the chunk and its neighbors directly
cBlockArea Area;
int BlockX = a_RelX + a_Chunk.GetPosX() * cChunkDef::Width;
int BlockZ = a_RelZ + a_Chunk.GetPosZ() * cChunkDef::Width;
if (!Area.Read(a_Chunk.GetWorld(), BlockX - 4, BlockX + 4, a_RelY, a_RelY + 1, BlockZ - 4, BlockZ + 4))
{
// Too close to the world edge, cannot check surroundings
return false;
}
size_t NumBlocks = Area.GetBlockCount();
BLOCKTYPE * BlockTypes = Area.GetBlockTypes();
for (size_t i = 0; i < NumBlocks; i++)
{
if (IsBlockWater(BlockTypes[i]))
{
return true;
}
} // for i - BlockTypes[]
return false;
}
} ;

View File

@ -126,11 +126,11 @@ public:
{
if (Dir == 1)
{
a_ChunkInterface.SetBlock(a_WorldInterface, Width, Height, Z, E_BLOCK_NETHER_PORTAL, Dir);
a_ChunkInterface.SetBlock(Width, Height, Z, E_BLOCK_NETHER_PORTAL, Dir);
}
else
{
a_ChunkInterface.SetBlock(a_WorldInterface, X, Height, Width, E_BLOCK_NETHER_PORTAL, Dir);
a_ChunkInterface.SetBlock(X, Height, Width, E_BLOCK_NETHER_PORTAL, Dir);
}
}
}

View File

@ -18,13 +18,15 @@ public:
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
{
a_Pickups.Add(E_BLOCK_GRAVEL, 1, 0);
cFastRandom Random;
if (Random.NextInt(30) == 0)
{
a_Pickups.Add(E_ITEM_FLINT, 1, 0);
}
else
{
a_Pickups.Add(E_BLOCK_GRAVEL, 1, 0);
}
}
} ;

View File

@ -47,6 +47,7 @@
#include "BlockLilypad.h"
#include "BlockLever.h"
#include "BlockMelon.h"
#include "BlockMobSpawner.h"
#include "BlockMushroom.h"
#include "BlockMycelium.h"
#include "BlockNetherWart.h"
@ -244,6 +245,7 @@ cBlockHandler * cBlockHandler::CreateBlockHandler(BLOCKTYPE a_BlockType)
case E_BLOCK_LOG: return new cBlockSidewaysHandler (a_BlockType);
case E_BLOCK_MELON: return new cBlockMelonHandler (a_BlockType);
case E_BLOCK_MELON_STEM: return new cBlockStemsHandler (a_BlockType);
case E_BLOCK_MOB_SPAWNER: return new cBlockMobSpawnerHandler (a_BlockType);
case E_BLOCK_MYCELIUM: return new cBlockMyceliumHandler (a_BlockType);
case E_BLOCK_NETHER_BRICK_STAIRS: return new cBlockStairsHandler (a_BlockType);
case E_BLOCK_NETHER_PORTAL: return new cBlockPortalHandler (a_BlockType);

View File

@ -146,9 +146,9 @@ public:
a_ChunkInterface.FastSetBlock(a_BlockX, a_BlockY - 2, a_BlockZ, E_BLOCK_AIR, 0);
// Block entities
a_ChunkInterface.SetBlock(a_WorldInterface, a_BlockX + 1, a_BlockY, a_BlockZ, E_BLOCK_AIR, 0);
a_ChunkInterface.SetBlock(a_WorldInterface, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_AIR, 0);
a_ChunkInterface.SetBlock(a_WorldInterface, a_BlockX - 1, a_BlockY, a_BlockZ, E_BLOCK_AIR, 0);
a_ChunkInterface.SetBlock(a_BlockX + 1, a_BlockY, a_BlockZ, E_BLOCK_AIR, 0);
a_ChunkInterface.SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_AIR, 0);
a_ChunkInterface.SetBlock(a_BlockX - 1, a_BlockY, a_BlockZ, E_BLOCK_AIR, 0);
// Spawn the wither:
a_WorldInterface.SpawnMob(a_BlockX + 0.5, a_BlockY - 2, a_BlockZ + 0.5, cMonster::mtWither);
@ -176,9 +176,9 @@ public:
a_ChunkInterface.FastSetBlock(a_BlockX, a_BlockY - 2, a_BlockZ, E_BLOCK_AIR, 0);
// Block entities
a_ChunkInterface.SetBlock(a_WorldInterface, a_BlockX, a_BlockY, a_BlockZ + 1, E_BLOCK_AIR, 0);
a_ChunkInterface.SetBlock(a_WorldInterface, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_AIR, 0);
a_ChunkInterface.SetBlock(a_WorldInterface, a_BlockX, a_BlockY, a_BlockZ - 1, E_BLOCK_AIR, 0);
a_ChunkInterface.SetBlock(a_BlockX, a_BlockY, a_BlockZ + 1, E_BLOCK_AIR, 0);
a_ChunkInterface.SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_AIR, 0);
a_ChunkInterface.SetBlock(a_BlockX, a_BlockY, a_BlockZ - 1, E_BLOCK_AIR, 0);
// Spawn the wither:
a_WorldInterface.SpawnMob(a_BlockX + 0.5, a_BlockY - 2, a_BlockZ + 0.5, cMonster::mtWither);

View File

@ -0,0 +1,40 @@
#pragma once
#include "BlockHandler.h"
#include "../World.h"
#include "../Items/ItemHandler.h"
class cBlockMobSpawnerHandler :
public cBlockHandler
{
public:
cBlockMobSpawnerHandler(BLOCKTYPE a_BlockType)
: cBlockHandler(a_BlockType)
{
}
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
{
// No pickups
}
virtual void OnDestroyedByPlayer(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ) override
{
cItemHandler * Handler = a_Player->GetEquippedItem().GetHandler();
if (a_Player->IsGameModeCreative() || !Handler->CanHarvestBlock(E_BLOCK_MOB_SPAWNER))
{
return;
}
cFastRandom Random;
int Reward = 15 + Random.NextInt(15) + Random.NextInt(15);
a_WorldInterface.SpawnExperienceOrb((double)a_BlockX, (double)a_BlockY + 1, (double)a_BlockZ, Reward);
}
} ;

View File

@ -52,7 +52,7 @@ void cBlockPistonHandler::OnDestroyed(cChunkInterface & a_ChunkInterface, cWorld
if (a_ChunkInterface.GetBlock(newX, newY, newZ) == E_BLOCK_PISTON_EXTENSION)
{
a_ChunkInterface.SetBlock(a_WorldInterface, newX, newY, newZ, E_BLOCK_AIR, 0);
a_ChunkInterface.SetBlock(newX, newY, newZ, E_BLOCK_AIR, 0);
}
}

View File

@ -37,9 +37,9 @@ public:
/** Sets the block at the specified coords to the specified value.
Full processing, incl. updating neighbors, is performed.
*/
void SetBlock(cWorldInterface & a_WorldInterface, int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
void SetBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
{
m_ChunkMap->SetBlock(a_WorldInterface, a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta);
m_ChunkMap->SetBlock(a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta);
}
void SetBlockMeta(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_MetaData)

View File

@ -35,6 +35,9 @@ public:
/** Spawns a mob of the specified type. Returns the mob's EntityID if recognized and spawned, <0 otherwise */
virtual int SpawnMob(double a_PosX, double a_PosY, double a_PosZ, cMonster::eType a_MonsterType) = 0;
/** Spawns an experience orb at the given location with the given reward. It returns the UniqueID of the spawned experience orb. */
virtual int SpawnExperienceOrb(double a_X, double a_Y, double a_Z, int a_Reward) = 0;
/** Calls the callback for the block entity at the specified coords; returns false if there's no block entity at those coords, true if found */
virtual bool DoWithBlockEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBlockEntityCallback & a_Callback) = 0;

View File

@ -1287,12 +1287,12 @@ void cChunkMap::SetBlockMeta(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYP
void cChunkMap::SetBlock(cWorldInterface & a_WorldInterface, int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, bool a_SendToClients)
void cChunkMap::SetBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, bool a_SendToClients)
{
cChunkInterface ChunkInterface(this);
if (a_BlockType == E_BLOCK_AIR)
{
BlockHandler(GetBlock(a_BlockX, a_BlockY, a_BlockZ))->OnDestroyed(ChunkInterface, a_WorldInterface, a_BlockX, a_BlockY, a_BlockZ);
BlockHandler(GetBlock(a_BlockX, a_BlockY, a_BlockZ))->OnDestroyed(ChunkInterface, *m_World, a_BlockX, a_BlockY, a_BlockZ);
}
int ChunkX, ChunkZ, X = a_BlockX, Y = a_BlockY, Z = a_BlockZ;
@ -1305,7 +1305,7 @@ void cChunkMap::SetBlock(cWorldInterface & a_WorldInterface, int a_BlockX, int a
Chunk->SetBlock(X, Y, Z, a_BlockType, a_BlockMeta, a_SendToClients);
m_World->GetSimulatorManager()->WakeUp(a_BlockX, a_BlockY, a_BlockZ, Chunk);
}
BlockHandler(a_BlockType)->OnPlaced(ChunkInterface, a_WorldInterface, a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta);
BlockHandler(a_BlockType)->OnPlaced(ChunkInterface, *m_World, a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta);
}

View File

@ -151,8 +151,8 @@ public:
NIBBLETYPE GetBlockSkyLight (int a_BlockX, int a_BlockY, int a_BlockZ);
NIBBLETYPE GetBlockBlockLight(int a_BlockX, int a_BlockY, int a_BlockZ);
void SetBlockMeta (int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_BlockMeta);
void SetBlock (cWorldInterface & a_WorldInterface, int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, bool a_SendToClients = true);
void QueueSetBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Int64 a_Tick, BLOCKTYPE a_PreviousBlockType = E_BLOCK_AIR);
void SetBlock (int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, bool a_SendToClients = true);
void QueueSetBlock (int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Int64 a_Tick, BLOCKTYPE a_PreviousBlockType = E_BLOCK_AIR);
bool GetBlockTypeMeta (int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta);
bool GetBlockInfo (int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_Meta, NIBBLETYPE & a_SkyLight, NIBBLETYPE & a_BlockLight);

View File

@ -1134,6 +1134,12 @@ void cClientHandle::HandleBlockDigFinished(int a_BlockX, int a_BlockY, int a_Blo
FinishDigAnimation();
if (!m_Player->IsGameModeCreative() && (a_OldBlock == E_BLOCK_BEDROCK))
{
Kick("You can't break a bedrock!");
return;
}
cWorld * World = m_Player->GetWorld();
cItemHandler * ItemHandler = cItemHandler::GetItemHandler(m_Player->GetEquippedItem());
@ -1447,8 +1453,20 @@ void cClientHandle::HandlePlaceBlock(int a_BlockX, int a_BlockY, int a_BlockZ, e
cChunkInterface ChunkInterface(World->GetChunkMap());
NewBlock->OnPlacedByPlayer(ChunkInterface, *World, m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, BlockType, BlockMeta);
// Step sound with 0.8f pitch is used as block placement sound
World->BroadcastSoundEffect(cBlockInfo::GetPlaceSound(BlockType), (double)a_BlockX, (double)a_BlockY, (double)a_BlockZ, 1.0f, 0.8f);
AString PlaceSound = cBlockInfo::GetPlaceSound(BlockType);
float Volume = 1.0f, Pitch = 0.8f;
if (PlaceSound == "dig.metal")
{
Pitch = 1.2f;
PlaceSound = "dig.stone";
}
else if (PlaceSound == "random.anvil_land")
{
Volume = 0.65f;
}
World->BroadcastSoundEffect(PlaceSound, a_BlockX + 0.5, a_BlockY + 0.5, a_BlockZ + 0.5, Volume, Pitch);
cRoot::Get()->GetPluginManager()->CallHookPlayerPlacedBlock(*m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, BlockType, BlockMeta);
}

View File

@ -582,6 +582,7 @@ bool cItemHandler::CanHarvestBlock(BLOCKTYPE a_BlockType)
case E_BLOCK_SNOW:
case E_BLOCK_VINES:
case E_BLOCK_PACKED_ICE:
case E_BLOCK_MOB_SPAWNER:
{
return false;
}

View File

@ -20,11 +20,17 @@ public:
virtual bool OnItemUse(cWorld *a_World, cPlayer *a_Player, const cItem & a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_Dir) override
{
if ((a_Dir == BLOCK_FACE_NONE) || (a_BlockY >= cChunkDef::Height))
{
return false;
}
BLOCKTYPE Block = a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ);
BLOCKTYPE UpperBlock = a_World->GetBlock(a_BlockX, a_BlockY + 1, a_BlockZ);
if ((Block == E_BLOCK_DIRT) || (Block == E_BLOCK_GRASS))
if (((Block == E_BLOCK_DIRT) || (Block == E_BLOCK_GRASS)) && (UpperBlock == E_BLOCK_AIR))
{
a_World->FastSetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_FARMLAND, 0);
a_World->BroadcastSoundEffect("dig.gravel", a_BlockX + 0.5, a_BlockY + 0.5, a_BlockZ + 0.5, 1.0f, 0.8f);
a_Player->UseEquippedItem();
return true;
}

View File

@ -81,6 +81,7 @@ public:
case E_BLOCK_STONE_BRICK_STAIRS:
case E_BLOCK_NETHER_BRICK_STAIRS:
case E_BLOCK_CAULDRON:
case E_BLOCK_MOB_SPAWNER:
{
return PickaxeLevel() >= 1;
}

View File

@ -1033,9 +1033,9 @@ void cProtocol172::SendExperienceOrb(const cExpOrb & a_ExpOrb)
cPacketizer Pkt(*this, 0x11);
Pkt.WriteVarInt(a_ExpOrb.GetUniqueID());
Pkt.WriteInt((int) a_ExpOrb.GetPosX());
Pkt.WriteInt((int) a_ExpOrb.GetPosY());
Pkt.WriteInt((int) a_ExpOrb.GetPosZ());
Pkt.WriteFPInt(a_ExpOrb.GetPosX());
Pkt.WriteFPInt(a_ExpOrb.GetPosY());
Pkt.WriteFPInt(a_ExpOrb.GetPosZ());
Pkt.WriteShort(a_ExpOrb.GetReward());
}

View File

@ -1727,7 +1727,7 @@ bool cWorld::SetAreaBiome(const cCuboid & a_Area, EMCSBiome a_Biome)
void cWorld::SetBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, bool a_SendToClients)
{
m_ChunkMap->SetBlock(*this, a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta, a_SendToClients);
m_ChunkMap->SetBlock(a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta, a_SendToClients);
}

View File

@ -469,7 +469,7 @@ public:
int SpawnMinecart(double a_X, double a_Y, double a_Z, int a_MinecartType, const cItem & a_Content = cItem(), int a_BlockHeight = 1);
/** Spawns an experience orb at the given location with the given reward. It returns the UniqueID of the spawned experience orb. */
int SpawnExperienceOrb(double a_X, double a_Y, double a_Z, int a_Reward);
virtual int SpawnExperienceOrb(double a_X, double a_Y, double a_Z, int a_Reward) override;
/** Spawns a new primed TNT entity at the specified block coords and specified fuse duration. Initial velocity is given based on the relative coefficient provided */
void SpawnPrimedTNT(double a_X, double a_Y, double a_Z, int a_FuseTimeInSec = 80, double a_InitialVelocityCoeff = 1);