1
0

Merge branch 'master' into 1.8-Protocol

Conflicts:
	src/Items/ItemHoe.h
This commit is contained in:
Howaner 2014-09-13 01:21:43 +02:00
commit 69afc4dbba
24 changed files with 186 additions and 105 deletions

View File

@ -1885,13 +1885,13 @@ cPluginManager.AddHook(cPluginManager.HOOK_CHAT, OnChatMessage);
},
BindCommand =
{
{ Params = "Command, Permission, Callback, HelpString", Return = "[bool]", Notes = "(STATIC) Binds an in-game command with the specified callback function, permission and help string. By common convention, providing an empty string for HelpString will hide the command from the /help display. Returns true if successful, logs to console and returns no value on error." },
{ Params = "Command, Permission, Callback, HelpString", Return = "[bool]", Notes = "Binds an in-game command with the specified callback function, permission and help string. By common convention, providing an empty string for HelpString will hide the command from the /help display. Returns true if successful, logs to console and returns no value on error." },
{ Params = "Command, Permission, Callback, HelpString", Return = "[bool]", Notes = "(STATIC) Binds an in-game command with the specified callback function, permission and help string. By common convention, providing an empty string for HelpString will hide the command from the /help display. Returns true if successful, logs to console and returns no value on error. The callback uses the following signature: <pre class=\"prettyprint lang-lua\">function(Split, {{cPlayer|Player}})</pre> The Split parameter contains an array-table of the words that the player has sent, Player is the {{cPlayer}} object representing the player who sent the command. If the callback returns true, the command is assumed to have executed successfully; in all other cases the server sends a warning to the player that the command is unknown (this is so that subcommands can be implemented)." },
{ Params = "Command, Permission, Callback, HelpString", Return = "[bool]", Notes = "Binds an in-game command with the specified callback function, permission and help string. By common convention, providing an empty string for HelpString will hide the command from the /help display. Returns true if successful, logs to console and returns no value on error. The callback uses the following signature: <pre class=\"prettyprint lang-lua\">function(Split, {{cPlayer|Player}})</pre> The Split parameter contains an array-table of the words that the player has sent, Player is the {{cPlayer}} object representing the player who sent the command. If the callback returns true, the command is assumed to have executed successfully; in all other cases the server sends a warning to the player that the command is unknown (this is so that subcommands can be implemented)." },
},
BindConsoleCommand =
{
{ Params = "Command, Callback, HelpString", Return = "[bool]", Notes = "(STATIC) Binds a console command with the specified callback function and help string. By common convention, providing an empty string for HelpString will hide the command from the \"help\" console command. Returns true if successful, logs to console and returns no value on error." },
{ Params = "Command, Callback, HelpString", Return = "[bool]", Notes = "Binds a console command with the specified callback function and help string. By common convention, providing an empty string for HelpString will hide the command from the \"help\" console command. Returns true if successful, logs to console and returns no value on error." },
{ Params = "Command, Callback, HelpString", Return = "[bool]", Notes = "(STATIC) Binds a console command with the specified callback function and help string. By common convention, providing an empty string for HelpString will hide the command from the \"help\" console command. Returns true if successful, logs to console and returns no value on error. The callback uses the following signature: <pre class=\"prettyprint lang-lua\">function(Split)</pre> The Split parameter contains an array-table of the words that the admin has typed. If the callback returns true, the command is assumed to have executed successfully; in all other cases the server issues a warning to the console that the command is unknown (this is so that subcommands can be implemented)." },
{ Params = "Command, Callback, HelpString", Return = "[bool]", Notes = "Binds a console command with the specified callback function and help string. By common convention, providing an empty string for HelpString will hide the command from the \"help\" console command. Returns true if successful, logs to console and returns no value on error. The callback uses the following signature: <pre class=\"prettyprint lang-lua\">function(Split)</pre> The Split parameter contains an array-table of the words that the admin has typed. If the callback returns true, the command is assumed to have executed successfully; in all other cases the server issues a warning to the console that the command is unknown (this is so that subcommands can be implemented)." },
},
CallPlugin = { Params = "PluginName, FunctionName, [FunctionArgs...]", Return = "[FunctionRets]", Notes = "(STATIC) Calls the specified function in the specified plugin, passing all the given arguments to it. If it succeeds, it returns all the values returned by that function. If it fails, returns no value at all. Note that only strings, numbers, bools, nils and classes can be used for parameters and return values; tables and functions cannot be copied across plugins." },
DisablePlugin = { Params = "PluginName", Return = "bool", Notes = "Disables a plugin specified by its name. Returns true if the plugin was disabled, false if it wasn't found or wasn't active." },

@ -1 +1 @@
Subproject commit 203c2fb68bbf871eaf4ca98756a113d74d620dea
Subproject commit 27b9d111818af3b05bcf4153bb6e380fe1dd6816

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

@ -1139,6 +1139,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());
@ -1466,8 +1472,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

@ -941,19 +941,21 @@ void cEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk)
}
NextSpeed.y += fallspeed;
}
// Friction
if (NextSpeed.SqrLength() > 0.0004f)
else
{
NextSpeed.x *= 0.7f / (1 + a_Dt);
if (fabs(NextSpeed.x) < 0.05)
// Friction on ground
if (NextSpeed.SqrLength() > 0.0004f)
{
NextSpeed.x = 0;
}
NextSpeed.z *= 0.7f / (1 + a_Dt);
if (fabs(NextSpeed.z) < 0.05)
{
NextSpeed.z = 0;
NextSpeed.x *= 0.7f / (1 + a_Dt);
if (fabs(NextSpeed.x) < 0.05)
{
NextSpeed.x = 0;
}
NextSpeed.z *= 0.7f / (1 + a_Dt);
if (fabs(NextSpeed.z) < 0.05)
{
NextSpeed.z = 0;
}
}
}

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

@ -18,17 +18,19 @@ 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
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)
if ((a_Dir == BLOCK_FACE_NONE) || (a_BlockY >= cChunkDef::Height))
{
return false;
}
BLOCKTYPE Block = a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ);
if (IsBlockTypeOfDirt(Block))
BLOCKTYPE UpperBlock = a_World->GetBlock(a_BlockX, a_BlockY + 1, a_BlockZ);
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;
}
@ -45,4 +47,3 @@ public:

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

@ -1040,9 +1040,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);