Merge branch 'master' into unreachable
This commit is contained in:
commit
90ab055eab
@ -1,29 +0,0 @@
|
||||
|
||||
-- @EnableMobDebug.lua
|
||||
|
||||
-- Enables the MobDebug debugger, used by ZeroBrane Studio, for a plugin
|
||||
-- Needs to be named with a @ at the start so that it's loaded as the first file of the plugin
|
||||
|
||||
--[[
|
||||
Usage:
|
||||
Copy this file to your plugin's folder when you want to debug that plugin
|
||||
You should neither check this file into the plugin's version control system,
|
||||
nor distribute it in the final release.
|
||||
--]]
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
-- Try to load the debugger, be silent about failures:
|
||||
local IsSuccess, MobDebug = pcall(require, "mobdebug")
|
||||
if (IsSuccess) then
|
||||
MobDebug.start()
|
||||
|
||||
-- The debugger will automatically put a breakpoint on this line, use this opportunity to set more breakpoints in your code
|
||||
LOG(cPluginManager:GetCurrentPlugin():GetName() .. ": MobDebug enabled")
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
49
MCServer/Plugins/DumpInfo/Init.lua
Normal file
49
MCServer/Plugins/DumpInfo/Init.lua
Normal file
@ -0,0 +1,49 @@
|
||||
function Initialize(a_Plugin)
|
||||
a_Plugin:SetName("DumpInfo")
|
||||
a_Plugin:SetVersion(1)
|
||||
|
||||
-- Check if the infodump file exists.
|
||||
if (not cFile:Exists("Plugins/InfoDump.lua")) then
|
||||
LOGWARN("[DumpInfo] InfoDump.lua was not found.")
|
||||
return false
|
||||
end
|
||||
|
||||
-- Add the webtab.
|
||||
a_Plugin:AddWebTab("DumpPlugin", HandleDumpPluginRequest)
|
||||
return true
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
function HandleDumpPluginRequest(a_Request)
|
||||
local Content = ""
|
||||
|
||||
-- Check if it already was requested to dump a plugin.
|
||||
if (a_Request.PostParams["DumpInfo"] ~= nil) then
|
||||
local F = loadfile("Plugins/InfoDump.lua")
|
||||
F("Plugins/" .. a_Request.PostParams["DumpInfo"])
|
||||
end
|
||||
|
||||
Content = Content .. [[
|
||||
<table>
|
||||
<th colspan="2">DumpInfo</th>]]
|
||||
|
||||
-- Loop through each plugin that is found.
|
||||
for PluginName, k in pairs(cPluginManager:Get():GetAllPlugins()) do
|
||||
|
||||
-- Check if there is a file called 'Info.lua' or 'info.lua'
|
||||
if (cFile:Exists("Plugins/" .. PluginName .. "/Info.lua")) then
|
||||
Content = Content .. "<tr>"
|
||||
Content = Content .. "<td>" .. PluginName .. "</td>"
|
||||
Content = Content .. "<td> <form method='POST'> <input type='hidden' value='" .. PluginName .. "' name='DumpInfo'> <input type='submit' value='DumpInfo'> </form>"
|
||||
Content = Content .. "</td>"
|
||||
end
|
||||
end
|
||||
|
||||
Content = Content .. [[
|
||||
</table>]]
|
||||
|
||||
return Content
|
||||
end
|
@ -59,13 +59,13 @@ local function MultiCommandHandler(a_Split, a_Player, a_CmdString, a_CmdInfo, a_
|
||||
return true;
|
||||
end
|
||||
|
||||
-- Check if the handler is valid:
|
||||
-- If the handler is not valid, check the next sublevel:
|
||||
if (Subcommand.Handler == nil) then
|
||||
if (Subcommand.Subcommands == nil) then
|
||||
LOG("Cannot find handler for command " .. a_CmdString .. " " .. Verb);
|
||||
return false;
|
||||
end
|
||||
ListSubcommands(a_Player, Subcommand.Subcommands, a_CmdString .. " " .. Verb);
|
||||
MultiCommandHandler(a_Split, a_Player, a_CmdString .. " " .. Verb, Subcommand, a_Level + 1);
|
||||
return true;
|
||||
end
|
||||
|
||||
|
@ -138,6 +138,12 @@ void cDispenserEntity::DropSpenseFromSlot(cChunk & a_Chunk, int a_SlotNum)
|
||||
break;
|
||||
}
|
||||
|
||||
case E_ITEM_FIRE_CHARGE:
|
||||
{
|
||||
// TODO: Spawn fireball entity
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
DropFromSlot(a_Chunk, a_SlotNum);
|
||||
|
@ -219,7 +219,7 @@ bool cHopperEntity::MovePickupsIn(cChunk & a_Chunk, Int64 a_CurrentTick)
|
||||
|
||||
Vector3f EntityPos = a_Entity->GetPosition();
|
||||
Vector3f BlockPos(m_Pos.x + 0.5f, (float)m_Pos.y + 1, m_Pos.z + 0.5f); // One block above hopper, and search from center outwards
|
||||
float Distance = (EntityPos - BlockPos).Length();
|
||||
double Distance = (EntityPos - BlockPos).Length();
|
||||
|
||||
if (Distance < 0.5)
|
||||
{
|
||||
|
@ -93,6 +93,7 @@ void cBlockInfo::Initialize(void)
|
||||
ms_Info[E_BLOCK_IRON_BARS ].m_SpreadLightFalloff = 1;
|
||||
ms_Info[E_BLOCK_IRON_DOOR ].m_SpreadLightFalloff = 1;
|
||||
ms_Info[E_BLOCK_LEAVES ].m_SpreadLightFalloff = 1;
|
||||
ms_Info[E_BLOCK_NEW_LEAVES ].m_SpreadLightFalloff = 1;
|
||||
ms_Info[E_BLOCK_SIGN_POST ].m_SpreadLightFalloff = 1;
|
||||
ms_Info[E_BLOCK_TORCH ].m_SpreadLightFalloff = 1;
|
||||
ms_Info[E_BLOCK_VINES ].m_SpreadLightFalloff = 1;
|
||||
|
63
src/Blocks/BlockAnvil.h
Normal file
63
src/Blocks/BlockAnvil.h
Normal file
@ -0,0 +1,63 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "BlockHandler.h"
|
||||
#include "../World.h"
|
||||
#include "../Entities/Player.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class cBlockAnvilHandler :
|
||||
public cBlockHandler
|
||||
{
|
||||
public:
|
||||
cBlockAnvilHandler(BLOCKTYPE a_BlockType)
|
||||
: cBlockHandler(a_BlockType)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
|
||||
{
|
||||
a_Pickups.push_back(cItem(E_BLOCK_ANVIL, 1, a_BlockMeta >> 2));
|
||||
}
|
||||
|
||||
virtual bool GetPlacementBlockTypeMeta(
|
||||
cChunkInterface & a_ChunkInterface, cPlayer * a_Player,
|
||||
int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
|
||||
int a_CursorX, int a_CursorY, int a_CursorZ,
|
||||
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
|
||||
) override
|
||||
{
|
||||
a_BlockType = m_BlockType;
|
||||
|
||||
int Direction = (int)floor(a_Player->GetYaw() * 4.0 / 360.0 + 0.5) & 0x3;
|
||||
int RawMeta = a_BlockMeta >> 2;
|
||||
|
||||
Direction++;
|
||||
Direction %= 4;
|
||||
switch (Direction)
|
||||
{
|
||||
case 0: a_BlockMeta = 0x2 | RawMeta << 2; break;
|
||||
case 1: a_BlockMeta = 0x3 | RawMeta << 2; break;
|
||||
case 2: a_BlockMeta = 0x0 | RawMeta << 2; break;
|
||||
case 3: a_BlockMeta = 0x1 | RawMeta << 2; break;
|
||||
default:
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool IsUseable() override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
|
@ -51,6 +51,49 @@ void cBlockBedHandler::OnDestroyed(cChunkInterface & a_ChunkInterface, cWorldInt
|
||||
|
||||
|
||||
|
||||
class cTimeFastForwardTester :
|
||||
public cPlayerListCallback
|
||||
{
|
||||
virtual bool Item(cPlayer * a_Player) override
|
||||
{
|
||||
if (!a_Player->IsInBed())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class cPlayerBedStateUnsetter :
|
||||
public cPlayerListCallback
|
||||
{
|
||||
public:
|
||||
cPlayerBedStateUnsetter(Vector3i a_Position, cWorldInterface & a_WorldInterface) :
|
||||
m_Position(a_Position), m_WorldInterface(a_WorldInterface)
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool Item(cPlayer * a_Player) override
|
||||
{
|
||||
a_Player->SetIsInBed(false);
|
||||
m_WorldInterface.GetBroadcastManager().BroadcastEntityAnimation(*a_Player, 2);
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
Vector3i m_Position;
|
||||
cWorldInterface & m_WorldInterface;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cBlockBedHandler::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)
|
||||
{
|
||||
if (a_WorldInterface.GetDimension() != dimOverworld)
|
||||
@ -69,6 +112,8 @@ void cBlockBedHandler::OnUse(cChunkInterface & a_ChunkInterface, cWorldInterface
|
||||
}
|
||||
else
|
||||
{
|
||||
Vector3i PillowDirection(0, 0, 0);
|
||||
|
||||
if (Meta & 0x8)
|
||||
{
|
||||
// Is pillow
|
||||
@ -77,16 +122,30 @@ void cBlockBedHandler::OnUse(cChunkInterface & a_ChunkInterface, cWorldInterface
|
||||
else
|
||||
{
|
||||
// Is foot end
|
||||
Vector3i Direction = MetaDataToDirection( Meta & 0x7 );
|
||||
if (a_ChunkInterface.GetBlock(a_BlockX + Direction.x, a_BlockY, a_BlockZ + Direction.z) == E_BLOCK_BED) // Must always use pillow location for sleeping
|
||||
VERIFY((Meta & 0x4) != 0x4); // Occupied flag should never be set, else our compilator (intended) is broken
|
||||
|
||||
PillowDirection = MetaDataToDirection(Meta & 0x7);
|
||||
if (a_ChunkInterface.GetBlock(a_BlockX + PillowDirection.x, a_BlockY, a_BlockZ + PillowDirection.z) == E_BLOCK_BED) // Must always use pillow location for sleeping
|
||||
{
|
||||
a_WorldInterface.GetBroadcastManager().BroadcastUseBed(*a_Player, a_BlockX + Direction.x, a_BlockY, a_BlockZ + Direction.z);
|
||||
a_WorldInterface.GetBroadcastManager().BroadcastUseBed(*a_Player, a_BlockX + PillowDirection.x, a_BlockY, a_BlockZ + PillowDirection.z);
|
||||
}
|
||||
}
|
||||
a_ChunkInterface.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, (Meta | (1 << 2)));
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
a_ChunkInterface.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, Meta | 0x4); // Where 0x4 = occupied bit
|
||||
a_Player->SetIsInBed(true);
|
||||
|
||||
cTimeFastForwardTester Tester;
|
||||
if (a_WorldInterface.ForEachPlayer(Tester))
|
||||
{
|
||||
cPlayerBedStateUnsetter Unsetter(Vector3i(a_BlockX + PillowDirection.x, a_BlockY, a_BlockZ + PillowDirection.z), a_WorldInterface);
|
||||
a_WorldInterface.ForEachPlayer(Unsetter);
|
||||
a_WorldInterface.SetTimeOfDay(0);
|
||||
a_ChunkInterface.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, Meta & 0xB); // Where 0xB = 1011, and zero is to make sure 'occupied' bit is always unset
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
a_Player->SendMessageFailure("You can only sleep at night");
|
||||
}
|
||||
}
|
||||
|
55
src/Blocks/BlockCake.h
Normal file
55
src/Blocks/BlockCake.h
Normal file
@ -0,0 +1,55 @@
|
||||
#pragma once
|
||||
|
||||
#include "BlockHandler.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class cBlockCakeHandler :
|
||||
public cBlockHandler
|
||||
{
|
||||
public:
|
||||
cBlockCakeHandler(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
|
||||
{
|
||||
NIBBLETYPE Meta = a_ChunkInterface.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ);
|
||||
|
||||
if (!a_Player->Feed(2, 0.1))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (Meta >= 5)
|
||||
{
|
||||
a_ChunkInterface.FastSetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_AIR, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
a_ChunkInterface.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, Meta + 1);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
|
||||
{
|
||||
// Give nothing
|
||||
}
|
||||
|
||||
virtual bool IsUseable(void) override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual const char * GetStepSound(void) override
|
||||
{
|
||||
return "step.cloth";
|
||||
}
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
|
@ -6,10 +6,12 @@
|
||||
#include "../Root.h"
|
||||
#include "../Bindings/PluginManager.h"
|
||||
#include "../Chunk.h"
|
||||
#include "BlockAnvil.h"
|
||||
#include "BlockBed.h"
|
||||
#include "BlockBrewingStand.h"
|
||||
#include "BlockButton.h"
|
||||
#include "BlockCactus.h"
|
||||
#include "BlockCake.h"
|
||||
#include "BlockCarpet.h"
|
||||
#include "BlockCauldron.h"
|
||||
#include "BlockChest.h"
|
||||
@ -85,12 +87,14 @@ cBlockHandler * cBlockHandler::CreateBlockHandler(BLOCKTYPE a_BlockType)
|
||||
// Block handlers, alphabetically sorted:
|
||||
case E_BLOCK_ACACIA_WOOD_STAIRS: return new cBlockStairsHandler (a_BlockType);
|
||||
case E_BLOCK_ACTIVATOR_RAIL: return new cBlockRailHandler (a_BlockType);
|
||||
case E_BLOCK_ANVIL: return new cBlockAnvilHandler (a_BlockType);
|
||||
case E_BLOCK_BED: return new cBlockBedHandler (a_BlockType);
|
||||
case E_BLOCK_BIRCH_WOOD_STAIRS: return new cBlockStairsHandler (a_BlockType);
|
||||
case E_BLOCK_BREWING_STAND: return new cBlockBrewingStandHandler (a_BlockType);
|
||||
case E_BLOCK_BRICK_STAIRS: return new cBlockStairsHandler (a_BlockType);
|
||||
case E_BLOCK_BROWN_MUSHROOM: return new cBlockMushroomHandler (a_BlockType);
|
||||
case E_BLOCK_CACTUS: return new cBlockCactusHandler (a_BlockType);
|
||||
case E_BLOCK_CAKE: return new cBlockCakeHandler (a_BlockType);
|
||||
case E_BLOCK_CARROTS: return new cBlockCropsHandler (a_BlockType);
|
||||
case E_BLOCK_CARPET: return new cBlockCarpetHandler (a_BlockType);
|
||||
case E_BLOCK_CAULDRON: return new cBlockCauldronHandler (a_BlockType);
|
||||
|
@ -16,6 +16,7 @@
|
||||
{ \
|
||||
case E_BLOCK_LEAVES: a_Area.SetBlockType(x, y, z, (BLOCKTYPE)(E_BLOCK_SPONGE + i + 1)); break; \
|
||||
case E_BLOCK_LOG: return true; \
|
||||
case E_BLOCK_NEW_LOG: return true; \
|
||||
}
|
||||
|
||||
bool HasNearLog(cBlockArea &a_Area, int a_BlockX, int a_BlockY, int a_BlockZ);
|
||||
|
@ -39,6 +39,7 @@ public:
|
||||
case E_BLOCK_CACTUS:
|
||||
case E_BLOCK_ICE:
|
||||
case E_BLOCK_LEAVES:
|
||||
case E_BLOCK_NEW_LEAVES:
|
||||
case E_BLOCK_AIR:
|
||||
{
|
||||
return false;
|
||||
|
@ -73,7 +73,7 @@ public:
|
||||
/// Returns true if the specified block type is good for vines to attach to
|
||||
static bool IsBlockAttachable(BLOCKTYPE a_BlockType)
|
||||
{
|
||||
return (a_BlockType == E_BLOCK_LEAVES) || cBlockInfo::IsSolid(a_BlockType);
|
||||
return (a_BlockType == E_BLOCK_LEAVES) || (a_BlockType == E_BLOCK_NEW_LEAVES) || cBlockInfo::IsSolid(a_BlockType);
|
||||
}
|
||||
|
||||
|
||||
|
@ -5,6 +5,7 @@ class cBroadcastInterface
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void BroadcastUseBed(const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ ) = 0;
|
||||
virtual void BroadcastSoundEffect (const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch, const cClientHandle * a_Exclude = NULL) = 0;
|
||||
virtual void BroadcastUseBed (const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ ) = 0;
|
||||
virtual void BroadcastSoundEffect(const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch, const cClientHandle * a_Exclude = NULL) = 0;
|
||||
virtual void BroadcastEntityAnimation(const cEntity & a_Entity, char a_Animation, const cClientHandle * a_Exclude = NULL) = 0;
|
||||
};
|
||||
|
@ -27,7 +27,13 @@ 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;
|
||||
|
||||
|
||||
/** Sends the block on those coords to the player */
|
||||
virtual void SendBlockTo(int a_BlockX, int a_BlockY, int a_BlockZ, cPlayer * a_Player) = 0;
|
||||
|
||||
/** Calls the callback for each player in the list; returns true if all players processed, false if the callback aborted by returning true */
|
||||
virtual bool ForEachPlayer(cItemCallback<cPlayer> & a_Callback) = 0;
|
||||
|
||||
virtual void SetTimeOfDay(Int64 a_TimeOfDay) = 0;
|
||||
|
||||
};
|
||||
|
@ -58,6 +58,9 @@ if (NOT MSVC)
|
||||
Entities/Player.h
|
||||
Entities/ProjectileEntity.h
|
||||
Entities/TNTEntity.h
|
||||
Entities/ExpOrb.h
|
||||
Entities/HangingEntity.h
|
||||
Entities/ItemFrame.h
|
||||
Generating/ChunkDesc.h
|
||||
Group.h
|
||||
Inventory.h
|
||||
|
106
src/ChunkMap.cpp
106
src/ChunkMap.cpp
@ -1383,6 +1383,13 @@ void cChunkMap::ReplaceTreeBlocks(const sSetBlockVector & a_Blocks)
|
||||
}
|
||||
break;
|
||||
}
|
||||
case E_BLOCK_NEW_LEAVES:
|
||||
{
|
||||
if (itr->BlockType == E_BLOCK_NEW_LOG)
|
||||
{
|
||||
Chunk->SetBlock(itr->x, itr->y, itr->z, itr->BlockType, itr->BlockMeta);
|
||||
}
|
||||
}
|
||||
}
|
||||
} // for itr - a_Blocks[]
|
||||
}
|
||||
@ -1784,57 +1791,58 @@ void cChunkMap::DoExplosionAt(double a_ExplosionSize, double a_BlockX, double a_
|
||||
BLOCKTYPE Block = area.GetBlockType(bx + x, by + y, bz + z);
|
||||
switch (Block)
|
||||
{
|
||||
case E_BLOCK_TNT:
|
||||
{
|
||||
// Activate the TNT, with a random fuse between 10 to 30 game ticks
|
||||
double FuseTime = (double)(10 + m_World->GetTickRandomNumber(20)) / 20;
|
||||
m_World->SpawnPrimedTNT(a_BlockX + x + 0.5, a_BlockY + y + 0.5, a_BlockZ + z + 0.5, FuseTime);
|
||||
area.SetBlockType(bx + x, by + y, bz + z, E_BLOCK_AIR);
|
||||
a_BlocksAffected.push_back(Vector3i(bx + x, by + y, bz + z));
|
||||
break;
|
||||
}
|
||||
case E_BLOCK_OBSIDIAN:
|
||||
case E_BLOCK_BEDROCK:
|
||||
case E_BLOCK_WATER:
|
||||
case E_BLOCK_LAVA:
|
||||
{
|
||||
// These blocks are not affected by explosions
|
||||
break;
|
||||
}
|
||||
|
||||
case E_BLOCK_STATIONARY_WATER:
|
||||
{
|
||||
// Turn into simulated water:
|
||||
area.SetBlockType(bx + x, by + y, bz + z, E_BLOCK_WATER);
|
||||
break;
|
||||
}
|
||||
|
||||
case E_BLOCK_STATIONARY_LAVA:
|
||||
{
|
||||
// Turn into simulated lava:
|
||||
area.SetBlockType(bx + x, by + y, bz + z, E_BLOCK_LAVA);
|
||||
break;
|
||||
}
|
||||
|
||||
case E_BLOCK_AIR:
|
||||
{
|
||||
// No pickups for air
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
if (m_World->GetTickRandomNumber(100) <= 25) // 25% chance of pickups
|
||||
case E_BLOCK_TNT:
|
||||
{
|
||||
cItems Drops;
|
||||
cBlockHandler * Handler = BlockHandler(Block);
|
||||
|
||||
Handler->ConvertToPickups(Drops, area.GetBlockMeta(bx + x, by + y, bz + z)); // Stone becomes cobblestone, coal ore becomes coal, etc.
|
||||
m_World->SpawnItemPickups(Drops, bx + x, by + y, bz + z);
|
||||
// Activate the TNT, with a random fuse between 10 to 30 game ticks
|
||||
int FuseTime = 10 + m_World->GetTickRandomNumber(20);
|
||||
m_World->SpawnPrimedTNT(a_BlockX + x + 0.5, a_BlockY + y + 0.5, a_BlockZ + z + 0.5, FuseTime);
|
||||
area.SetBlockType(bx + x, by + y, bz + z, E_BLOCK_AIR);
|
||||
a_BlocksAffected.push_back(Vector3i(bx + x, by + y, bz + z));
|
||||
break;
|
||||
}
|
||||
|
||||
case E_BLOCK_OBSIDIAN:
|
||||
case E_BLOCK_BEDROCK:
|
||||
case E_BLOCK_WATER:
|
||||
case E_BLOCK_LAVA:
|
||||
{
|
||||
// These blocks are not affected by explosions
|
||||
break;
|
||||
}
|
||||
|
||||
case E_BLOCK_STATIONARY_WATER:
|
||||
{
|
||||
// Turn into simulated water:
|
||||
area.SetBlockType(bx + x, by + y, bz + z, E_BLOCK_WATER);
|
||||
break;
|
||||
}
|
||||
|
||||
case E_BLOCK_STATIONARY_LAVA:
|
||||
{
|
||||
// Turn into simulated lava:
|
||||
area.SetBlockType(bx + x, by + y, bz + z, E_BLOCK_LAVA);
|
||||
break;
|
||||
}
|
||||
|
||||
case E_BLOCK_AIR:
|
||||
{
|
||||
// No pickups for air
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
if (m_World->GetTickRandomNumber(100) <= 25) // 25% chance of pickups
|
||||
{
|
||||
cItems Drops;
|
||||
cBlockHandler * Handler = BlockHandler(Block);
|
||||
|
||||
Handler->ConvertToPickups(Drops, area.GetBlockMeta(bx + x, by + y, bz + z)); // Stone becomes cobblestone, coal ore becomes coal, etc.
|
||||
m_World->SpawnItemPickups(Drops, bx + x, by + y, bz + z);
|
||||
}
|
||||
area.SetBlockType(bx + x, by + y, bz + z, E_BLOCK_AIR);
|
||||
a_BlocksAffected.push_back(Vector3i(bx + x, by + y, bz + z));
|
||||
}
|
||||
area.SetBlockType(bx + x, by + y, bz + z, E_BLOCK_AIR);
|
||||
a_BlocksAffected.push_back(Vector3i(bx + x, by + y, bz + z));
|
||||
}
|
||||
} // switch (BlockType)
|
||||
} // for z
|
||||
} // for y
|
||||
|
@ -529,16 +529,22 @@ enum eMessageType
|
||||
// http://forum.mc-server.org/showthread.php?tid=1212
|
||||
// MessageType...
|
||||
|
||||
mtCustom, // Send raw data without any processing
|
||||
mtFailure, // Something could not be done (i.e. command not executed due to insufficient privilege)
|
||||
mtInformation, // Informational message (i.e. command usage)
|
||||
mtSuccess, // Something executed successfully
|
||||
mtWarning, // Something concerning (i.e. reload) is about to happen
|
||||
mtFatal, // Something catastrophic occured (i.e. plugin crash)
|
||||
mtDeath, // Denotes death of player
|
||||
mtPrivateMessage, // Player to player messaging identifier
|
||||
mtJoin, // A player has joined the server
|
||||
mtLeave, // A player has left the server
|
||||
mtCustom, // Send raw data without any processing
|
||||
mtFailure, // Something could not be done (i.e. command not executed due to insufficient privilege)
|
||||
mtInformation, // Informational message (i.e. command usage)
|
||||
mtSuccess, // Something executed successfully
|
||||
mtWarning, // Something concerning (i.e. reload) is about to happen
|
||||
mtFatal, // Something catastrophic occured (i.e. plugin crash)
|
||||
mtDeath, // Denotes death of player
|
||||
mtPrivateMessage, // Player to player messaging identifier
|
||||
mtJoin, // A player has joined the server
|
||||
mtLeave, // A player has left the server
|
||||
|
||||
// Common aliases:
|
||||
mtFail = mtFailure,
|
||||
mtError = mtFailure,
|
||||
mtInfo = mtInformation,
|
||||
mtPM = mtPrivateMessage,
|
||||
};
|
||||
|
||||
|
||||
|
@ -5,20 +5,26 @@
|
||||
#include "../ClientHandle.h"
|
||||
|
||||
|
||||
cExpOrb::cExpOrb(double a_X, double a_Y, double a_Z, int a_Reward) :
|
||||
cEntity(etExpOrb, a_X, a_Y, a_Z, 0.98, 0.98),
|
||||
m_Reward(a_Reward)
|
||||
cExpOrb::cExpOrb(double a_X, double a_Y, double a_Z, int a_Reward)
|
||||
: cEntity(etExpOrb, a_X, a_Y, a_Z, 0.98, 0.98)
|
||||
, m_Reward(a_Reward)
|
||||
, m_Timer(0.f)
|
||||
{
|
||||
SetMaxHealth(5);
|
||||
SetHealth(5);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
cExpOrb::cExpOrb(const Vector3d & a_Pos, int a_Reward) :
|
||||
cEntity(etExpOrb, a_Pos.x, a_Pos.y, a_Pos.z, 0.98, 0.98),
|
||||
m_Reward(a_Reward)
|
||||
cExpOrb::cExpOrb(const Vector3d & a_Pos, int a_Reward)
|
||||
: cEntity(etExpOrb, a_Pos.x, a_Pos.y, a_Pos.z, 0.98, 0.98)
|
||||
, m_Reward(a_Reward)
|
||||
, m_Timer(0.f)
|
||||
{
|
||||
SetMaxHealth(5);
|
||||
SetHealth(5);
|
||||
}
|
||||
|
||||
|
||||
@ -52,7 +58,7 @@ void cExpOrb::Tick(float a_Dt, cChunk & a_Chunk)
|
||||
LOGD("Player %s picked up an ExpOrb. His reward is %i", a_ClosestPlayer->GetName().c_str(), m_Reward);
|
||||
a_ClosestPlayer->DeltaExperience(m_Reward);
|
||||
|
||||
m_World->BroadcastSoundEffect("random.orb", (int)GetPosX() * 8, (int)GetPosY() * 8, (int)GetPosZ() * 8, 0.5f, (float)(0.75 + ((float)((GetUniqueID() * 23) % 32)) / 64));
|
||||
m_World->BroadcastSoundEffect("random.orb", (int)(GetPosX() * 8), (int)(GetPosY() * 8), (int)(GetPosZ() * 8), 0.5f, (float)(0.75 + ((float)((GetUniqueID() * 23) % 32)) / 64));
|
||||
|
||||
Destroy();
|
||||
}
|
||||
@ -64,4 +70,10 @@ void cExpOrb::Tick(float a_Dt, cChunk & a_Chunk)
|
||||
BroadcastMovementUpdate();
|
||||
}
|
||||
HandlePhysics(a_Dt, a_Chunk);
|
||||
|
||||
m_Timer += a_Dt;
|
||||
if (m_Timer >= 1000 * 60 * 5) // 5 minutes
|
||||
{
|
||||
Destroy(true);
|
||||
}
|
||||
}
|
||||
|
@ -7,14 +7,17 @@
|
||||
|
||||
|
||||
|
||||
// tolua_begin
|
||||
class cExpOrb :
|
||||
public cEntity
|
||||
{
|
||||
typedef cExpOrb super;
|
||||
|
||||
public:
|
||||
// tolua_end
|
||||
|
||||
CLASS_PROTODEF(cExpOrb);
|
||||
|
||||
|
||||
cExpOrb(double a_X, double a_Y, double a_Z, int a_Reward);
|
||||
cExpOrb(const Vector3d & a_Pos, int a_Reward);
|
||||
|
||||
@ -22,9 +25,21 @@ public:
|
||||
virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
|
||||
virtual void SpawnOn(cClientHandle & a_Client) override;
|
||||
|
||||
// cExpOrb functions
|
||||
int GetReward(void) const { return m_Reward; }
|
||||
/** Returns the number of ticks that this entity has existed */
|
||||
int GetAge(void) const { return (int)(m_Timer / 50); } // tolua_export
|
||||
|
||||
/** Set the number of ticks that this entity has existed */
|
||||
void SetAge(int a_Age) { m_Timer = (float)(a_Age * 50); } // tolua_export
|
||||
|
||||
/** Get the exp amount */
|
||||
int GetReward(void) const { return m_Reward; } // tolua_export
|
||||
|
||||
/** Set the exp amount */
|
||||
void SetReward(int a_Reward) { m_Reward = a_Reward; } // tolua_export
|
||||
|
||||
protected:
|
||||
int m_Reward;
|
||||
} ;
|
||||
|
||||
/** The number of ticks that the entity has existed / timer between collect and destroy; in msec */
|
||||
float m_Timer;
|
||||
} ; // tolua_export
|
53
src/Entities/HangingEntity.cpp
Normal file
53
src/Entities/HangingEntity.cpp
Normal file
@ -0,0 +1,53 @@
|
||||
|
||||
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
|
||||
|
||||
#include "HangingEntity.h"
|
||||
#include "ClientHandle.h"
|
||||
#include "Player.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
cHangingEntity::cHangingEntity(eEntityType a_EntityType, eBlockFace a_BlockFace, double a_X, double a_Y, double a_Z)
|
||||
: cEntity(a_EntityType, a_X, a_Y, a_Z, 0.8, 0.8)
|
||||
, m_BlockFace(a_BlockFace)
|
||||
{
|
||||
SetMaxHealth(1);
|
||||
SetHealth(1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cHangingEntity::SpawnOn(cClientHandle & a_ClientHandle)
|
||||
{
|
||||
int Dir = 0;
|
||||
|
||||
// The client uses different values for item frame directions and block faces. Our constants are for the block faces, so we convert them here to item frame faces
|
||||
switch (m_BlockFace)
|
||||
{
|
||||
case BLOCK_FACE_ZP: break; // Initialised to zero
|
||||
case BLOCK_FACE_ZM: Dir = 2; break;
|
||||
case BLOCK_FACE_XM: Dir = 1; break;
|
||||
case BLOCK_FACE_XP: Dir = 3; break;
|
||||
default: ASSERT(!"Unhandled block face when trying to spawn item frame!"); return;
|
||||
}
|
||||
|
||||
if ((Dir == 0) || (Dir == 2)) // Probably a client bug, but two directions are flipped and contrary to the norm, so we do -180
|
||||
{
|
||||
SetYaw((Dir * 90) - 180);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetYaw(Dir * 90);
|
||||
}
|
||||
|
||||
a_ClientHandle.SendSpawnObject(*this, 71, Dir, (Byte)GetYaw(), (Byte)GetPitch());
|
||||
a_ClientHandle.SendEntityMetadata(*this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
49
src/Entities/HangingEntity.h
Normal file
49
src/Entities/HangingEntity.h
Normal file
@ -0,0 +1,49 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Entity.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// tolua_begin
|
||||
class cHangingEntity :
|
||||
public cEntity
|
||||
{
|
||||
// tolua_end
|
||||
typedef cEntity super;
|
||||
|
||||
public:
|
||||
|
||||
CLASS_PROTODEF(cHangingEntity);
|
||||
|
||||
cHangingEntity(eEntityType a_EntityType, eBlockFace a_BlockFace, double a_X, double a_Y, double a_Z);
|
||||
|
||||
/** Returns the orientation from the hanging entity */
|
||||
eBlockFace GetDirection() const { return m_BlockFace; } // tolua_export
|
||||
|
||||
/** Set the orientation from the hanging entity */
|
||||
void SetDirection(eBlockFace a_BlockFace) { m_BlockFace = a_BlockFace; } // tolua_export
|
||||
|
||||
/** Returns the X coord. */
|
||||
int GetTileX() const { return POSX_TOINT; } // tolua_export
|
||||
|
||||
/** Returns the Y coord. */
|
||||
int GetTileY() const { return POSY_TOINT; } // tolua_export
|
||||
|
||||
/** Returns the Z coord. */
|
||||
int GetTileZ() const { return POSZ_TOINT; } // tolua_export
|
||||
|
||||
private:
|
||||
|
||||
virtual void SpawnOn(cClientHandle & a_ClientHandle) override;
|
||||
virtual void Tick(float a_Dt, cChunk & a_Chunk) override {};
|
||||
|
||||
eBlockFace m_BlockFace;
|
||||
|
||||
}; // tolua_export
|
||||
|
||||
|
||||
|
||||
|
@ -10,43 +10,10 @@
|
||||
|
||||
|
||||
cItemFrame::cItemFrame(eBlockFace a_BlockFace, double a_X, double a_Y, double a_Z)
|
||||
: cEntity(etItemFrame, a_X, a_Y, a_Z, 0.8, 0.8),
|
||||
m_BlockFace(a_BlockFace),
|
||||
m_Item(E_BLOCK_AIR),
|
||||
m_Rotation(0)
|
||||
: cHangingEntity(etItemFrame, a_BlockFace, a_X, a_Y, a_Z)
|
||||
, m_Item(E_BLOCK_AIR)
|
||||
, m_Rotation(0)
|
||||
{
|
||||
SetMaxHealth(1);
|
||||
SetHealth(1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cItemFrame::SpawnOn(cClientHandle & a_ClientHandle)
|
||||
{
|
||||
int Dir = 0;
|
||||
|
||||
// The client uses different values for item frame directions and block faces. Our constants are for the block faces, so we convert them here to item frame faces
|
||||
switch (m_BlockFace)
|
||||
{
|
||||
case BLOCK_FACE_ZP: break; // Initialised to zero
|
||||
case BLOCK_FACE_ZM: Dir = 2; break;
|
||||
case BLOCK_FACE_XM: Dir = 1; break;
|
||||
case BLOCK_FACE_XP: Dir = 3; break;
|
||||
default: ASSERT(!"Unhandled block face when trying to spawn item frame!"); return;
|
||||
}
|
||||
|
||||
if ((Dir == 0) || (Dir == 2)) // Probably a client bug, but two directions are flipped and contrary to the norm, so we do -180
|
||||
{
|
||||
SetYaw((Dir * 90) - 180);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetYaw(Dir * 90);
|
||||
}
|
||||
|
||||
a_ClientHandle.SendSpawnObject(*this, 71, Dir, (Byte)GetYaw(), (Byte)GetPitch());
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Entity.h"
|
||||
#include "HangingEntity.h"
|
||||
|
||||
|
||||
|
||||
@ -9,10 +9,10 @@
|
||||
|
||||
// tolua_begin
|
||||
class cItemFrame :
|
||||
public cEntity
|
||||
public cHangingEntity
|
||||
{
|
||||
// tolua_end
|
||||
typedef cEntity super;
|
||||
typedef cHangingEntity super;
|
||||
|
||||
public:
|
||||
|
||||
@ -20,18 +20,24 @@ public:
|
||||
|
||||
cItemFrame(eBlockFace a_BlockFace, double a_X, double a_Y, double a_Z);
|
||||
|
||||
const cItem & GetItem(void) { return m_Item; }
|
||||
Byte GetRotation(void) const { return m_Rotation; }
|
||||
/** Returns the item in the frame */
|
||||
const cItem & GetItem(void) { return m_Item; } // tolua_export
|
||||
|
||||
/** Set the item in the frame */
|
||||
void SetItem(cItem & a_Item) { m_Item = a_Item; }; // tolua_export
|
||||
|
||||
/** Returns the rotation from the item in the frame */
|
||||
Byte GetRotation(void) const { return m_Rotation; } // tolua_export
|
||||
|
||||
/** Set the rotation from the item in the frame */
|
||||
void SetRotation(Byte a_Rotation) { m_Rotation = a_Rotation; } // tolua_export
|
||||
|
||||
private:
|
||||
|
||||
virtual void SpawnOn(cClientHandle & a_ClientHandle) override;
|
||||
virtual void OnRightClicked(cPlayer & a_Player) override;
|
||||
virtual void Tick(float a_Dt, cChunk & a_Chunk) override {};
|
||||
virtual void KilledBy(cEntity * a_Killer) override;
|
||||
virtual void GetDrops(cItems & a_Items, cEntity * a_Killer) override;
|
||||
|
||||
eBlockFace m_BlockFace;
|
||||
cItem m_Item;
|
||||
Byte m_Rotation;
|
||||
|
||||
|
@ -82,7 +82,7 @@ cPickup::cPickup(double a_PosX, double a_PosY, double a_PosZ, const cItem & a_It
|
||||
|
||||
void cPickup::SpawnOn(cClientHandle & a_Client)
|
||||
{
|
||||
a_Client.SendPickupSpawn(*this);
|
||||
a_Client.SendPickupSpawn(*this);
|
||||
}
|
||||
|
||||
|
||||
|
@ -26,31 +26,34 @@ public:
|
||||
CLASS_PROTODEF(cPickup);
|
||||
|
||||
cPickup(double a_PosX, double a_PosY, double a_PosZ, const cItem & a_Item, bool IsPlayerCreated, float a_SpeedX = 0.f, float a_SpeedY = 0.f, float a_SpeedZ = 0.f);
|
||||
|
||||
|
||||
cItem & GetItem(void) {return m_Item; } // tolua_export
|
||||
const cItem & GetItem(void) const {return m_Item; }
|
||||
|
||||
virtual void SpawnOn(cClientHandle & a_ClientHandle) override;
|
||||
|
||||
|
||||
bool CollectedBy(cPlayer * a_Dest); // tolua_export
|
||||
|
||||
virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
|
||||
|
||||
/// Returns the number of ticks that this entity has existed
|
||||
int GetAge(void) const { return (int)(m_Timer / 50); } // tolua_export
|
||||
|
||||
/// Returns true if the pickup has already been collected
|
||||
|
||||
/** Returns the number of ticks that this entity has existed */
|
||||
int GetAge(void) const { return (int)(m_Timer / 50); } // tolua_export
|
||||
|
||||
/** Set the number of ticks that this entity has existed */
|
||||
void SetAge(int a_Age) { m_Timer = (float)(a_Age * 50); } // tolua_export
|
||||
|
||||
/** Returns true if the pickup has already been collected */
|
||||
bool IsCollected(void) const { return m_bCollected; } // tolua_export
|
||||
|
||||
/// Returns true if created by player (i.e. vomiting), used for determining picking-up delay time
|
||||
/** Returns true if created by player (i.e. vomiting), used for determining picking-up delay time */
|
||||
bool IsPlayerCreated(void) const { return m_bIsPlayerCreated; } // tolua_export
|
||||
|
||||
|
||||
private:
|
||||
Vector3d m_ResultingSpeed; //Can be used to modify the resulting speed for the current tick ;)
|
||||
|
||||
Vector3d m_WaterSpeed;
|
||||
|
||||
/// The number of ticks that the entity has existed / timer between collect and destroy; in msec
|
||||
/** The number of ticks that the entity has existed / timer between collect and destroy; in msec */
|
||||
float m_Timer;
|
||||
|
||||
cItem m_Item;
|
||||
|
@ -270,6 +270,9 @@ public:
|
||||
/// Returns true if the player is currently flying.
|
||||
bool IsFlying(void) const { return m_IsFlying; }
|
||||
|
||||
/** Returns if a player is sleeping in a bed */
|
||||
bool IsInBed(void) const { return m_bIsInBed; }
|
||||
|
||||
/// returns true if the player has thrown out a floater.
|
||||
bool IsFishing(void) const { return m_IsFishing; }
|
||||
|
||||
@ -278,6 +281,9 @@ public:
|
||||
int GetFloaterID(void) const { return m_FloaterID; }
|
||||
|
||||
// tolua_end
|
||||
|
||||
/** Sets a player's in-bed state; we can't be sure plugins will keep this value updated, so no exporting */
|
||||
void SetIsInBed(bool a_Flag) { m_bIsInBed = a_Flag; }
|
||||
|
||||
/// Starts eating the currently equipped item. Resets the eating timer and sends the proper animation packet
|
||||
void StartEating(void);
|
||||
@ -371,8 +377,8 @@ protected:
|
||||
GroupList m_ResolvedGroups;
|
||||
GroupList m_Groups;
|
||||
|
||||
std::string m_PlayerName;
|
||||
std::string m_LoadedWorldName;
|
||||
AString m_PlayerName;
|
||||
AString m_LoadedWorldName;
|
||||
|
||||
/// Xp Level stuff
|
||||
enum
|
||||
@ -456,7 +462,7 @@ protected:
|
||||
|
||||
int m_FloaterID;
|
||||
|
||||
cTeam* m_Team;
|
||||
cTeam * m_Team;
|
||||
|
||||
|
||||
|
||||
@ -479,6 +485,11 @@ protected:
|
||||
|
||||
/// Adds food exhaustion based on the difference between Pos and LastPos, sprinting status and swimming (in water block)
|
||||
void ApplyFoodExhaustionFromMovement();
|
||||
|
||||
/** Flag representing whether the player is currently in a bed
|
||||
Set by a right click on unoccupied bed, unset by a time fast forward or teleport */
|
||||
bool m_bIsInBed;
|
||||
|
||||
} ; // tolua_export
|
||||
|
||||
|
||||
|
41
src/Items/ItemCake.h
Normal file
41
src/Items/ItemCake.h
Normal file
@ -0,0 +1,41 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ItemHandler.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class cItemCakeHandler :
|
||||
public cItemHandler
|
||||
{
|
||||
public:
|
||||
cItemCakeHandler(int a_ItemType) :
|
||||
cItemHandler(a_ItemType)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
virtual bool IsPlaceable(void) override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
virtual bool GetPlacementBlockTypeMeta(
|
||||
cWorld * a_World, cPlayer * a_Player,
|
||||
int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
|
||||
int a_CursorX, int a_CursorY, int a_CursorZ,
|
||||
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
|
||||
) override
|
||||
{
|
||||
a_BlockType = E_BLOCK_CAKE;
|
||||
a_BlockMeta = 0;
|
||||
return true;
|
||||
}
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "ItemBow.h"
|
||||
#include "ItemBrewingStand.h"
|
||||
#include "ItemBucket.h"
|
||||
#include "ItemCake.h"
|
||||
#include "ItemCauldron.h"
|
||||
#include "ItemCloth.h"
|
||||
#include "ItemComparator.h"
|
||||
@ -94,6 +95,7 @@ cItemHandler *cItemHandler::CreateItemHandler(int a_ItemType)
|
||||
|
||||
// Single item per handler, alphabetically sorted:
|
||||
case E_BLOCK_LEAVES: return new cItemLeavesHandler(a_ItemType);
|
||||
case E_BLOCK_NEW_LEAVES: return new cItemLeavesHandler(a_ItemType);
|
||||
case E_BLOCK_SAPLING: return new cItemSaplingHandler(a_ItemType);
|
||||
case E_BLOCK_WOOL: return new cItemClothHandler(a_ItemType);
|
||||
case E_ITEM_BED: return new cItemBedHandler(a_ItemType);
|
||||
@ -101,12 +103,14 @@ cItemHandler *cItemHandler::CreateItemHandler(int a_ItemType)
|
||||
case E_ITEM_BOTTLE_O_ENCHANTING: return new cItemBottleOEnchantingHandler();
|
||||
case E_ITEM_BOW: return new cItemBowHandler;
|
||||
case E_ITEM_BREWING_STAND: return new cItemBrewingStandHandler(a_ItemType);
|
||||
case E_ITEM_CAKE: return new cItemCakeHandler(a_ItemType);
|
||||
case E_ITEM_CAULDRON: return new cItemCauldronHandler(a_ItemType);
|
||||
case E_ITEM_COMPARATOR: return new cItemComparatorHandler(a_ItemType);
|
||||
case E_ITEM_DYE: return new cItemDyeHandler(a_ItemType);
|
||||
case E_ITEM_EGG: return new cItemEggHandler();
|
||||
case E_ITEM_EMPTY_MAP: return new cItemEmptyMapHandler();
|
||||
case E_ITEM_ENDER_PEARL: return new cItemEnderPearlHandler();
|
||||
case E_ITEM_FIRE_CHARGE: return new cItemLighterHandler(a_ItemType);
|
||||
case E_ITEM_FIREWORK_ROCKET: return new cItemFireworkHandler();
|
||||
case E_ITEM_FISHING_ROD: return new cItemFishingRodHandler(a_ItemType);
|
||||
case E_ITEM_FLINT_AND_STEEL: return new cItemLighterHandler(a_ItemType);
|
||||
@ -337,6 +341,7 @@ char cItemHandler::GetMaxStackSize(void)
|
||||
case E_ITEM_BREWING_STAND: return 64;
|
||||
case E_ITEM_BUCKET: return 16;
|
||||
case E_ITEM_CARROT: return 64;
|
||||
case E_ITEM_CAKE: return 1;
|
||||
case E_ITEM_CAULDRON: return 64;
|
||||
case E_ITEM_CLAY: return 64;
|
||||
case E_ITEM_CLAY_BRICK: return 64;
|
||||
|
@ -34,7 +34,11 @@ public:
|
||||
if (Block == E_BLOCK_AIR)
|
||||
{
|
||||
cItemFrame * ItemFrame = new cItemFrame(a_Dir, a_BlockX, a_BlockY, a_BlockZ);
|
||||
ItemFrame->Initialize(a_World);
|
||||
if (!ItemFrame->Initialize(a_World))
|
||||
{
|
||||
delete ItemFrame;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!a_Player->IsGameModeCreative())
|
||||
{
|
||||
|
@ -26,7 +26,26 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
a_Player->UseEquippedItem();
|
||||
if (!a_Player->IsGameModeCreative())
|
||||
{
|
||||
switch (m_ItemType)
|
||||
{
|
||||
case E_ITEM_FLINT_AND_STEEL:
|
||||
{
|
||||
a_Player->UseEquippedItem();
|
||||
break;
|
||||
}
|
||||
case E_ITEM_FIRE_CHARGE:
|
||||
{
|
||||
a_Player->GetInventory().RemoveOneEquippedItem();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
ASSERT(!"Unknown Lighter Item!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch (a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ))
|
||||
{
|
||||
@ -49,6 +68,7 @@ public:
|
||||
if (a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ) == E_BLOCK_AIR)
|
||||
{
|
||||
a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_FIRE, 0);
|
||||
a_World->BroadcastSoundEffect("fire.ignite", a_BlockX * 8, a_BlockY * 8, a_BlockZ * 8, 1.0F, 1.04F);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -28,10 +28,10 @@ public:
|
||||
virtual bool OnDiggingBlock(cWorld * a_World, cPlayer * a_Player, const cItem & a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_Dir) override
|
||||
{
|
||||
BLOCKTYPE Block = a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ);
|
||||
if (Block == E_BLOCK_LEAVES)
|
||||
if ((Block == E_BLOCK_LEAVES) || (Block == E_BLOCK_NEW_LEAVES))
|
||||
{
|
||||
cItems Drops;
|
||||
Drops.push_back(cItem(E_BLOCK_LEAVES, 1, a_World->GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ) & 0x03));
|
||||
Drops.push_back(cItem(Block, 1, a_World->GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ) & 0x03));
|
||||
a_World->SpawnItemPickups(Drops, a_BlockX, a_BlockY, a_BlockZ);
|
||||
|
||||
a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_AIR, 0);
|
||||
@ -49,6 +49,7 @@ public:
|
||||
case E_BLOCK_COBWEB:
|
||||
case E_BLOCK_VINES:
|
||||
case E_BLOCK_LEAVES:
|
||||
case E_BLOCK_NEW_LEAVES:
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
@ -169,7 +169,7 @@ bool cMobSpawner::CanSpawnHere(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_R
|
||||
(TargetBlock == E_BLOCK_AIR) &&
|
||||
(BlockAbove == E_BLOCK_AIR) &&
|
||||
(
|
||||
(BlockBelow == E_BLOCK_GRASS) || (BlockBelow == E_BLOCK_LEAVES)
|
||||
(BlockBelow == E_BLOCK_GRASS) || (BlockBelow == E_BLOCK_LEAVES) || (BlockBelow == E_BLOCK_NEW_LEAVES)
|
||||
) &&
|
||||
(a_RelY >= 62) &&
|
||||
(m_Random.NextInt(3, a_Biome) != 0)
|
||||
|
@ -82,11 +82,11 @@ cMonster::cMonster(const AString & a_ConfigName, eType a_MobType, const AString
|
||||
, m_AttackRange(2)
|
||||
, m_AttackInterval(0)
|
||||
, m_SightDistance(25)
|
||||
, m_DropChanceWeapon(0.085)
|
||||
, m_DropChanceHelmet(0.085)
|
||||
, m_DropChanceChestplate(0.085)
|
||||
, m_DropChanceLeggings(0.085)
|
||||
, m_DropChanceBoots(0.085)
|
||||
, m_DropChanceWeapon(0.085f)
|
||||
, m_DropChanceHelmet(0.085f)
|
||||
, m_DropChanceChestplate(0.085f)
|
||||
, m_DropChanceLeggings(0.085f)
|
||||
, m_DropChanceBoots(0.085f)
|
||||
, m_CanPickUpLoot(true)
|
||||
, m_BurnsInDaylight(false)
|
||||
{
|
||||
|
@ -1062,7 +1062,7 @@ void cIncrementalRedstoneSimulator::HandlePressurePlate(int a_BlockX, int a_Bloc
|
||||
{
|
||||
Vector3f EntityPos = a_Entity->GetPosition();
|
||||
Vector3f BlockPos(m_X + 0.5f, (float)m_Y, m_Z + 0.5f);
|
||||
float Distance = (EntityPos - BlockPos).Length();
|
||||
double Distance = (EntityPos - BlockPos).Length();
|
||||
|
||||
if (Distance <= 0.7)
|
||||
{
|
||||
|
73
src/World.h
73
src/World.h
@ -125,15 +125,16 @@ public:
|
||||
// tolua_begin
|
||||
|
||||
int GetTicksUntilWeatherChange(void) const { return m_WeatherInterval; }
|
||||
virtual Int64 GetWorldAge(void) const { return m_WorldAge; }
|
||||
virtual Int64 GetTimeOfDay(void) const { return m_TimeOfDay; }
|
||||
|
||||
virtual Int64 GetWorldAge (void) const { return m_WorldAge; } // override, cannot specify due to tolua
|
||||
virtual Int64 GetTimeOfDay(void) const { return m_TimeOfDay; } // override, cannot specify due to tolua
|
||||
|
||||
void SetTicksUntilWeatherChange(int a_WeatherInterval)
|
||||
{
|
||||
m_WeatherInterval = a_WeatherInterval;
|
||||
}
|
||||
|
||||
void SetTimeOfDay(Int64 a_TimeOfDay)
|
||||
virtual void SetTimeOfDay(Int64 a_TimeOfDay) // override, cannot specify due to tolua
|
||||
{
|
||||
m_TimeOfDay = a_TimeOfDay;
|
||||
m_TimeOfDaySecs = (double)a_TimeOfDay / 20.0;
|
||||
@ -191,35 +192,35 @@ public:
|
||||
void BroadcastChat (const cCompositeChat & a_Message, const cClientHandle * a_Exclude = NULL);
|
||||
// tolua_end
|
||||
|
||||
void BroadcastChunkData (int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer, const cClientHandle * a_Exclude = NULL);
|
||||
void BroadcastCollectPickup (const cPickup & a_Pickup, const cPlayer & a_Player, const cClientHandle * a_Exclude = NULL);
|
||||
void BroadcastDestroyEntity (const cEntity & a_Entity, const cClientHandle * a_Exclude = NULL);
|
||||
void BroadcastEntityEffect (const cEntity & a_Entity, int a_EffectID, int a_Amplifier, short a_Duration, const cClientHandle * a_Exclude = NULL);
|
||||
void BroadcastEntityEquipment (const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item, const cClientHandle * a_Exclude = NULL);
|
||||
void BroadcastEntityHeadLook (const cEntity & a_Entity, const cClientHandle * a_Exclude = NULL);
|
||||
void BroadcastEntityLook (const cEntity & a_Entity, const cClientHandle * a_Exclude = NULL);
|
||||
void BroadcastEntityMetadata (const cEntity & a_Entity, const cClientHandle * a_Exclude = NULL);
|
||||
void BroadcastEntityRelMove (const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ, const cClientHandle * a_Exclude = NULL);
|
||||
void BroadcastEntityRelMoveLook (const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ, const cClientHandle * a_Exclude = NULL);
|
||||
void BroadcastEntityStatus (const cEntity & a_Entity, char a_Status, const cClientHandle * a_Exclude = NULL);
|
||||
void BroadcastEntityVelocity (const cEntity & a_Entity, const cClientHandle * a_Exclude = NULL);
|
||||
void BroadcastEntityAnimation (const cEntity & a_Entity, char a_Animation, const cClientHandle * a_Exclude = NULL);
|
||||
void BroadcastParticleEffect (const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmmount, cClientHandle * a_Exclude = NULL); // tolua_export
|
||||
void BroadcastPlayerListItem (const cPlayer & a_Player, bool a_IsOnline, const cClientHandle * a_Exclude = NULL);
|
||||
void BroadcastRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID, const cClientHandle * a_Exclude = NULL);
|
||||
void BroadcastScoreboardObjective(const AString & a_Name, const AString & a_DisplayName, Byte a_Mode);
|
||||
void BroadcastScoreUpdate (const AString & a_Objective, const AString & a_Player, cObjective::Score a_Score, Byte a_Mode);
|
||||
void BroadcastDisplayObjective (const AString & a_Objective, cScoreboard::eDisplaySlot a_Display);
|
||||
void BroadcastSoundEffect (const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch, const cClientHandle * a_Exclude = NULL); // tolua_export a_Src coords are Block * 8
|
||||
void BroadcastSoundParticleEffect(int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data, const cClientHandle * a_Exclude = NULL); // tolua_export
|
||||
void BroadcastSpawnEntity (cEntity & a_Entity, const cClientHandle * a_Exclude = NULL);
|
||||
void BroadcastTeleportEntity (const cEntity & a_Entity, const cClientHandle * a_Exclude = NULL);
|
||||
void BroadcastThunderbolt (int a_BlockX, int a_BlockY, int a_BlockZ, const cClientHandle * a_Exclude = NULL);
|
||||
void BroadcastTimeUpdate (const cClientHandle * a_Exclude = NULL);
|
||||
virtual void BroadcastUseBed (const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ );
|
||||
void BroadcastWeather (eWeather a_Weather, const cClientHandle * a_Exclude = NULL);
|
||||
void BroadcastChunkData (int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer, const cClientHandle * a_Exclude = NULL);
|
||||
void BroadcastCollectPickup (const cPickup & a_Pickup, const cPlayer & a_Player, const cClientHandle * a_Exclude = NULL);
|
||||
void BroadcastDestroyEntity (const cEntity & a_Entity, const cClientHandle * a_Exclude = NULL);
|
||||
void BroadcastEntityEffect (const cEntity & a_Entity, int a_EffectID, int a_Amplifier, short a_Duration, const cClientHandle * a_Exclude = NULL);
|
||||
void BroadcastEntityEquipment (const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item, const cClientHandle * a_Exclude = NULL);
|
||||
void BroadcastEntityHeadLook (const cEntity & a_Entity, const cClientHandle * a_Exclude = NULL);
|
||||
void BroadcastEntityLook (const cEntity & a_Entity, const cClientHandle * a_Exclude = NULL);
|
||||
void BroadcastEntityMetadata (const cEntity & a_Entity, const cClientHandle * a_Exclude = NULL);
|
||||
void BroadcastEntityRelMove (const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ, const cClientHandle * a_Exclude = NULL);
|
||||
void BroadcastEntityRelMoveLook (const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ, const cClientHandle * a_Exclude = NULL);
|
||||
void BroadcastEntityStatus (const cEntity & a_Entity, char a_Status, const cClientHandle * a_Exclude = NULL);
|
||||
void BroadcastEntityVelocity (const cEntity & a_Entity, const cClientHandle * a_Exclude = NULL);
|
||||
virtual void BroadcastEntityAnimation(const cEntity & a_Entity, char a_Animation, const cClientHandle * a_Exclude = NULL) override;
|
||||
void BroadcastParticleEffect (const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmmount, cClientHandle * a_Exclude = NULL); // tolua_export
|
||||
void BroadcastPlayerListItem (const cPlayer & a_Player, bool a_IsOnline, const cClientHandle * a_Exclude = NULL);
|
||||
void BroadcastRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID, const cClientHandle * a_Exclude = NULL);
|
||||
void BroadcastScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode);
|
||||
void BroadcastScoreUpdate (const AString & a_Objective, const AString & a_Player, cObjective::Score a_Score, Byte a_Mode);
|
||||
void BroadcastDisplayObjective (const AString & a_Objective, cScoreboard::eDisplaySlot a_Display);
|
||||
void BroadcastSoundEffect (const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch, const cClientHandle * a_Exclude = NULL); // tolua_export a_Src coords are Block * 8
|
||||
void BroadcastSoundParticleEffect (int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data, const cClientHandle * a_Exclude = NULL); // tolua_export
|
||||
void BroadcastSpawnEntity (cEntity & a_Entity, const cClientHandle * a_Exclude = NULL);
|
||||
void BroadcastTeleportEntity (const cEntity & a_Entity, const cClientHandle * a_Exclude = NULL);
|
||||
void BroadcastThunderbolt (int a_BlockX, int a_BlockY, int a_BlockZ, const cClientHandle * a_Exclude = NULL);
|
||||
void BroadcastTimeUpdate (const cClientHandle * a_Exclude = NULL);
|
||||
virtual void BroadcastUseBed (const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ) override;
|
||||
void BroadcastWeather (eWeather a_Weather, const cClientHandle * a_Exclude = NULL);
|
||||
|
||||
virtual cBroadcastInterface & GetBroadcastManager()
|
||||
virtual cBroadcastInterface & GetBroadcastManager(void) override
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
@ -273,7 +274,7 @@ public:
|
||||
void RemovePlayer( cPlayer* a_Player );
|
||||
|
||||
/** Calls the callback for each player in the list; returns true if all players processed, false if the callback aborted by returning true */
|
||||
bool ForEachPlayer(cPlayerListCallback & a_Callback); // >> EXPORTED IN MANUALBINDINGS <<
|
||||
virtual bool ForEachPlayer(cPlayerListCallback & a_Callback) override; // >> EXPORTED IN MANUALBINDINGS <<
|
||||
|
||||
/** Calls the callback for the player of the given name; returns true if the player was found and the callback called, false if player not found. Callback return ignored */
|
||||
bool DoWithPlayer(const AString & a_PlayerName, cPlayerListCallback & a_Callback); // >> EXPORTED IN MANUALBINDINGS <<
|
||||
@ -365,7 +366,7 @@ public:
|
||||
bool IsChunkLighted(int a_ChunkX, int a_ChunkZ);
|
||||
|
||||
/** Calls the callback for each chunk in the coords specified (all cords are inclusive). Returns true if all chunks have been processed successfully */
|
||||
virtual bool ForEachChunkInRect(int a_MinChunkX, int a_MaxChunkX, int a_MinChunkZ, int a_MaxChunkZ, cChunkDataCallback & a_Callback);
|
||||
virtual bool ForEachChunkInRect(int a_MinChunkX, int a_MaxChunkX, int a_MinChunkZ, int a_MaxChunkZ, cChunkDataCallback & a_Callback) override;
|
||||
|
||||
// tolua_begin
|
||||
|
||||
@ -456,7 +457,7 @@ public:
|
||||
|
||||
// tolua_begin
|
||||
bool DigBlock (int a_X, int a_Y, int a_Z);
|
||||
virtual void SendBlockTo(int a_X, int a_Y, int a_Z, cPlayer * a_Player);
|
||||
virtual void SendBlockTo(int a_X, int a_Y, int a_Z, cPlayer * a_Player); // override, cannot specify due to tolua
|
||||
|
||||
double GetSpawnX(void) const { return m_SpawnX; }
|
||||
double GetSpawnY(void) const { return m_SpawnY; }
|
||||
@ -507,7 +508,7 @@ public:
|
||||
| esWitherBirth | TBD |
|
||||
| esPlugin | void * |
|
||||
*/
|
||||
virtual void DoExplosionAt(double a_ExplosionSize, double a_BlockX, double a_BlockY, double a_BlockZ, bool a_CanCauseFire, eExplosionSource a_Source, void * a_SourceData); // tolua_export
|
||||
virtual void DoExplosionAt(double a_ExplosionSize, double a_BlockX, double a_BlockY, double a_BlockZ, bool a_CanCauseFire, eExplosionSource a_Source, void * a_SourceData); // tolua_export // override, cannot specify due to tolua
|
||||
|
||||
/** 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 */
|
||||
bool DoWithBlockEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBlockEntityCallback & a_Callback); // Exported in ManualBindings.cpp
|
||||
@ -703,7 +704,7 @@ public:
|
||||
bool IsBlockDirectlyWatered(int a_BlockX, int a_BlockY, int a_BlockZ); // tolua_export
|
||||
|
||||
/** 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); // tolua_export
|
||||
virtual int SpawnMob(double a_PosX, double a_PosY, double a_PosZ, cMonster::eType a_MonsterType); // tolua_export // override, cannot specify due to tolua
|
||||
int SpawnMobFinalize(cMonster* a_Monster);
|
||||
|
||||
/** Creates a projectile of the specified type. Returns the projectile's EntityID if successful, <0 otherwise */
|
||||
|
@ -29,6 +29,9 @@
|
||||
#include "../Entities/Pickup.h"
|
||||
#include "../Entities/ProjectileEntity.h"
|
||||
#include "../Entities/TNTEntity.h"
|
||||
#include "../Entities/ExpOrb.h"
|
||||
#include "../Entities/HangingEntity.h"
|
||||
#include "../Entities/ItemFrame.h"
|
||||
|
||||
#include "../Mobs/Monster.h"
|
||||
#include "../Mobs/Bat.h"
|
||||
@ -526,8 +529,8 @@ void cNBTChunkSerializer::AddPickupEntity(cPickup * a_Pickup)
|
||||
m_Writer.BeginCompound("");
|
||||
AddBasicEntity(a_Pickup, "Item");
|
||||
AddItem(a_Pickup->GetItem(), -1, "Item");
|
||||
m_Writer.AddShort("Health", a_Pickup->GetHealth());
|
||||
m_Writer.AddShort("Age", a_Pickup->GetAge());
|
||||
m_Writer.AddShort("Health", (Int16)(unsigned char)a_Pickup->GetHealth());
|
||||
m_Writer.AddShort("Age", (Int16)a_Pickup->GetAge());
|
||||
m_Writer.EndCompound();
|
||||
}
|
||||
|
||||
@ -592,6 +595,25 @@ void cNBTChunkSerializer::AddProjectileEntity(cProjectileEntity * a_Projectile)
|
||||
|
||||
|
||||
|
||||
void cNBTChunkSerializer::AddHangingEntity(cHangingEntity * a_Hanging)
|
||||
{
|
||||
m_Writer.AddByte("Direction", (unsigned char)a_Hanging->GetDirection());
|
||||
m_Writer.AddInt("TileX", a_Hanging->GetTileX());
|
||||
m_Writer.AddInt("TileY", a_Hanging->GetTileY());
|
||||
m_Writer.AddInt("TileZ", a_Hanging->GetTileZ());
|
||||
switch (a_Hanging->GetDirection())
|
||||
{
|
||||
case 0: m_Writer.AddByte("Dir", (unsigned char)2); break;
|
||||
case 1: m_Writer.AddByte("Dir", (unsigned char)1); break;
|
||||
case 2: m_Writer.AddByte("Dir", (unsigned char)0); break;
|
||||
case 3: m_Writer.AddByte("Dir", (unsigned char)3); break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cNBTChunkSerializer::AddTNTEntity(cTNTEntity * a_TNT)
|
||||
{
|
||||
m_Writer.BeginCompound("");
|
||||
@ -604,6 +626,35 @@ void cNBTChunkSerializer::AddTNTEntity(cTNTEntity * a_TNT)
|
||||
|
||||
|
||||
|
||||
void cNBTChunkSerializer::AddExpOrbEntity(cExpOrb * a_ExpOrb)
|
||||
{
|
||||
m_Writer.BeginCompound("");
|
||||
AddBasicEntity(a_ExpOrb, "XPOrb");
|
||||
m_Writer.AddShort("Health", (Int16)(unsigned char)a_ExpOrb->GetHealth());
|
||||
m_Writer.AddShort("Age", (Int16)a_ExpOrb->GetAge());
|
||||
m_Writer.AddShort("Value", (Int16)a_ExpOrb->GetReward());
|
||||
m_Writer.EndCompound();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cNBTChunkSerializer::AddItemFrameEntity(cItemFrame * a_ItemFrame)
|
||||
{
|
||||
m_Writer.BeginCompound("");
|
||||
AddBasicEntity(a_ItemFrame, "ItemFrame");
|
||||
AddHangingEntity(a_ItemFrame);
|
||||
AddItem(a_ItemFrame->GetItem(), -1, "Item");
|
||||
m_Writer.AddByte("ItemRotation", (unsigned char)a_ItemFrame->GetRotation());
|
||||
m_Writer.AddFloat("ItemDropChance", 1.0F);
|
||||
m_Writer.EndCompound();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cNBTChunkSerializer::AddMinecartChestContents(cMinecartWithChest * a_Minecart)
|
||||
{
|
||||
m_Writer.BeginList("Items", TAG_Compound);
|
||||
@ -684,8 +735,8 @@ void cNBTChunkSerializer::Entity(cEntity * a_Entity)
|
||||
case cEntity::etPickup: AddPickupEntity ((cPickup *) a_Entity); break;
|
||||
case cEntity::etProjectile: AddProjectileEntity ((cProjectileEntity *)a_Entity); break;
|
||||
case cEntity::etTNT: AddTNTEntity ((cTNTEntity *) a_Entity); break;
|
||||
case cEntity::etExpOrb: /* TODO */ break;
|
||||
case cEntity::etItemFrame: /* TODO */ break;
|
||||
case cEntity::etExpOrb: AddExpOrbEntity ((cExpOrb *) a_Entity); break;
|
||||
case cEntity::etItemFrame: AddItemFrameEntity ((cItemFrame *) a_Entity); break;
|
||||
case cEntity::etPainting: /* TODO */ break;
|
||||
case cEntity::etPlayer: return; // Players aren't saved into the world
|
||||
default:
|
||||
|
@ -42,6 +42,9 @@ class cPickup;
|
||||
class cItemGrid;
|
||||
class cProjectileEntity;
|
||||
class cTNTEntity;
|
||||
class cExpOrb;
|
||||
class cHangingEntity;
|
||||
class cItemFrame;
|
||||
|
||||
|
||||
|
||||
@ -108,7 +111,10 @@ protected:
|
||||
void AddMonsterEntity (cMonster * a_Monster);
|
||||
void AddPickupEntity (cPickup * a_Pickup);
|
||||
void AddProjectileEntity (cProjectileEntity * a_Projectile);
|
||||
void AddHangingEntity (cHangingEntity * a_Hanging);
|
||||
void AddTNTEntity (cTNTEntity * a_TNT);
|
||||
void AddExpOrbEntity (cExpOrb * a_ExpOrb);
|
||||
void AddItemFrameEntity (cItemFrame * a_ItemFrame);
|
||||
|
||||
void AddMinecartChestContents(cMinecartWithChest * a_Minecart);
|
||||
|
||||
|
@ -37,6 +37,9 @@
|
||||
#include "../Entities/Pickup.h"
|
||||
#include "../Entities/ProjectileEntity.h"
|
||||
#include "../Entities/TNTEntity.h"
|
||||
#include "../Entities/ExpOrb.h"
|
||||
#include "../Entities/HangingEntity.h"
|
||||
#include "../Entities/ItemFrame.h"
|
||||
|
||||
|
||||
|
||||
@ -366,6 +369,7 @@ bool cWSSAnvil::LoadChunkFromNBT(const cChunkCoords & a_Chunk, const cParsedNBT
|
||||
{
|
||||
case E_BLOCK_AIR:
|
||||
case E_BLOCK_LEAVES:
|
||||
case E_BLOCK_NEW_LEAVES:
|
||||
{
|
||||
// nothing needed
|
||||
break;
|
||||
@ -1098,6 +1102,18 @@ void cWSSAnvil::LoadEntityFromNBT(cEntityList & a_Entities, const cParsedNBT & a
|
||||
{
|
||||
LoadPickupFromNBT(a_Entities, a_NBT, a_EntityTagIdx);
|
||||
}
|
||||
else if (strncmp(a_IDTag, "PrimedTnt", a_IDTagLength) == 0)
|
||||
{
|
||||
LoadTNTFromNBT(a_Entities, a_NBT, a_EntityTagIdx);
|
||||
}
|
||||
else if (strncmp(a_IDTag, "XPOrb", a_IDTagLength) == 0)
|
||||
{
|
||||
LoadExpOrbFromNBT(a_Entities, a_NBT, a_EntityTagIdx);
|
||||
}
|
||||
else if (strncmp(a_IDTag, "ItemFrame", a_IDTagLength) == 0)
|
||||
{
|
||||
LoadItemFrameFromNBT(a_Entities, a_NBT, a_EntityTagIdx);
|
||||
}
|
||||
else if (strncmp(a_IDTag, "Arrow", a_IDTagLength) == 0)
|
||||
{
|
||||
LoadArrowFromNBT(a_Entities, a_NBT, a_EntityTagIdx);
|
||||
@ -1238,10 +1254,6 @@ void cWSSAnvil::LoadEntityFromNBT(cEntityList & a_Entities, const cParsedNBT & a
|
||||
{
|
||||
LoadPigZombieFromNBT(a_Entities, a_NBT, a_EntityTagIdx);
|
||||
}
|
||||
else if (strncmp(a_IDTag, "PrimedTnt", a_IDTagLength) == 0)
|
||||
{
|
||||
LoadTNTFromNBT(a_Entities, a_NBT, a_EntityTagIdx);
|
||||
}
|
||||
// TODO: other entities
|
||||
}
|
||||
|
||||
@ -1384,6 +1396,7 @@ void cWSSAnvil::LoadMinecartHFromNBT(cEntityList & a_Entities, const cParsedNBT
|
||||
|
||||
void cWSSAnvil::LoadPickupFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx)
|
||||
{
|
||||
// Load item:
|
||||
int ItemTag = a_NBT.FindChildByName(a_TagIdx, "Item");
|
||||
if ((ItemTag < 0) || (a_NBT.GetType(ItemTag) != TAG_Compound))
|
||||
{
|
||||
@ -1394,11 +1407,27 @@ void cWSSAnvil::LoadPickupFromNBT(cEntityList & a_Entities, const cParsedNBT & a
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
std::auto_ptr<cPickup> Pickup(new cPickup(0, 0, 0, Item, false)); // Pickup delay doesn't matter, just say false
|
||||
if (!LoadEntityBaseFromNBT(*Pickup.get(), a_NBT, a_TagIdx))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Load health:
|
||||
int Health = a_NBT.FindChildByName(a_TagIdx, "Health");
|
||||
if (Health > 0)
|
||||
{
|
||||
Pickup->SetHealth((int) (a_NBT.GetShort(Health) & 0xFF));
|
||||
}
|
||||
|
||||
// Load age:
|
||||
int Age = a_NBT.FindChildByName(a_TagIdx, "Age");
|
||||
if (Age > 0)
|
||||
{
|
||||
Pickup->SetAge(a_NBT.GetShort(Age));
|
||||
}
|
||||
|
||||
a_Entities.push_back(Pickup.release());
|
||||
}
|
||||
|
||||
@ -1406,6 +1435,148 @@ void cWSSAnvil::LoadPickupFromNBT(cEntityList & a_Entities, const cParsedNBT & a
|
||||
|
||||
|
||||
|
||||
void cWSSAnvil::LoadTNTFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx)
|
||||
{
|
||||
std::auto_ptr<cTNTEntity> TNT(new cTNTEntity(0.0, 0.0, 0.0, 0));
|
||||
if (!LoadEntityBaseFromNBT(*TNT.get(), a_NBT, a_TagIdx))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Load Fuse Ticks:
|
||||
int FuseTicks = a_NBT.FindChildByName(a_TagIdx, "Fuse");
|
||||
if (FuseTicks > 0)
|
||||
{
|
||||
TNT->SetFuseTicks((int) a_NBT.GetByte(FuseTicks));
|
||||
}
|
||||
|
||||
a_Entities.push_back(TNT.release());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cWSSAnvil::LoadExpOrbFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx)
|
||||
{
|
||||
std::auto_ptr<cExpOrb> ExpOrb(new cExpOrb(0.0, 0.0, 0.0, 0));
|
||||
if (!LoadEntityBaseFromNBT(*ExpOrb.get(), a_NBT, a_TagIdx))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Load Health:
|
||||
int Health = a_NBT.FindChildByName(a_TagIdx, "Health");
|
||||
if (Health > 0)
|
||||
{
|
||||
ExpOrb->SetHealth((int) (a_NBT.GetShort(Health) & 0xFF));
|
||||
}
|
||||
|
||||
// Load Age:
|
||||
int Age = a_NBT.FindChildByName(a_TagIdx, "Age");
|
||||
if (Age > 0)
|
||||
{
|
||||
ExpOrb->SetAge(a_NBT.GetShort(Age));
|
||||
}
|
||||
|
||||
// Load Reward (Value):
|
||||
int Reward = a_NBT.FindChildByName(a_TagIdx, "Value");
|
||||
if (Reward > 0)
|
||||
{
|
||||
ExpOrb->SetReward(a_NBT.GetShort(Reward));
|
||||
}
|
||||
|
||||
a_Entities.push_back(ExpOrb.release());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cWSSAnvil::LoadHangingFromNBT(cHangingEntity & a_Hanging, const cParsedNBT & a_NBT, int a_TagIdx)
|
||||
{
|
||||
int Direction = a_NBT.FindChildByName(a_TagIdx, "Direction");
|
||||
if (Direction > 0)
|
||||
{
|
||||
Direction = (int)a_NBT.GetByte(Direction);
|
||||
if ((Direction < 0) || (Direction > 5))
|
||||
{
|
||||
a_Hanging.SetDirection(BLOCK_FACE_NORTH);
|
||||
}
|
||||
else
|
||||
{
|
||||
a_Hanging.SetDirection(static_cast<eBlockFace>(Direction));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Direction = a_NBT.FindChildByName(a_TagIdx, "Dir");
|
||||
if (Direction > 0)
|
||||
{
|
||||
switch ((int)a_NBT.GetByte(Direction))
|
||||
{
|
||||
case 0: a_Hanging.SetDirection(BLOCK_FACE_NORTH); break;
|
||||
case 1: a_Hanging.SetDirection(BLOCK_FACE_TOP); break;
|
||||
case 2: a_Hanging.SetDirection(BLOCK_FACE_BOTTOM); break;
|
||||
case 3: a_Hanging.SetDirection(BLOCK_FACE_SOUTH); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int TileX = a_NBT.FindChildByName(a_TagIdx, "TileX");
|
||||
int TileY = a_NBT.FindChildByName(a_TagIdx, "TileY");
|
||||
int TileZ = a_NBT.FindChildByName(a_TagIdx, "TileZ");
|
||||
if ((TileX > 0) && (TileY > 0) && (TileZ > 0))
|
||||
{
|
||||
a_Hanging.SetPosition(
|
||||
(double)a_NBT.GetInt(TileX),
|
||||
(double)a_NBT.GetInt(TileY),
|
||||
(double)a_NBT.GetInt(TileZ)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cWSSAnvil::LoadItemFrameFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx)
|
||||
{
|
||||
// Load item:
|
||||
int ItemTag = a_NBT.FindChildByName(a_TagIdx, "Item");
|
||||
if ((ItemTag < 0) || (a_NBT.GetType(ItemTag) != TAG_Compound))
|
||||
{
|
||||
return;
|
||||
}
|
||||
cItem Item;
|
||||
if (!LoadItemFromNBT(Item, a_NBT, ItemTag))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
std::auto_ptr<cItemFrame> ItemFrame(new cItemFrame(BLOCK_FACE_NONE, 0.0, 0.0, 0.0));
|
||||
if (!LoadEntityBaseFromNBT(*ItemFrame.get(), a_NBT, a_TagIdx))
|
||||
{
|
||||
return;
|
||||
}
|
||||
ItemFrame->SetItem(Item);
|
||||
|
||||
LoadHangingFromNBT(*ItemFrame.get(), a_NBT, a_TagIdx);
|
||||
|
||||
// Load Rotation:
|
||||
int Rotation = a_NBT.FindChildByName(a_TagIdx, "ItemRotation");
|
||||
if (Rotation > 0)
|
||||
{
|
||||
ItemFrame->SetRotation((Byte)a_NBT.GetByte(Rotation));
|
||||
}
|
||||
|
||||
a_Entities.push_back(ItemFrame.release());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cWSSAnvil::LoadArrowFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx)
|
||||
{
|
||||
std::auto_ptr<cArrowEntity> Arrow(new cArrowEntity(NULL, 0, 0, 0, Vector3d(0, 0, 0)));
|
||||
@ -2178,28 +2349,6 @@ void cWSSAnvil::LoadPigZombieFromNBT(cEntityList & a_Entities, const cParsedNBT
|
||||
|
||||
|
||||
|
||||
void cWSSAnvil::LoadTNTFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx)
|
||||
{
|
||||
std::auto_ptr<cTNTEntity> TNT(new cTNTEntity(0.0, 0.0, 0.0, 0));
|
||||
if (!LoadEntityBaseFromNBT(*TNT.get(), a_NBT, a_TagIdx))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Load Fuse Ticks:
|
||||
int FuseTicks = a_NBT.FindChildByName(a_TagIdx, "Fuse");
|
||||
if (FuseTicks > 0)
|
||||
{
|
||||
TNT->SetFuseTicks((int) a_NBT.GetByte(FuseTicks));
|
||||
}
|
||||
|
||||
a_Entities.push_back(TNT.release());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cWSSAnvil::LoadEntityBaseFromNBT(cEntity & a_Entity, const cParsedNBT & a_NBT, int a_TagIdx)
|
||||
{
|
||||
double Pos[3];
|
||||
|
@ -20,6 +20,7 @@
|
||||
class cItemGrid;
|
||||
|
||||
class cProjectileEntity;
|
||||
class cHangingEntity;
|
||||
|
||||
|
||||
|
||||
@ -149,6 +150,10 @@ protected:
|
||||
void LoadBoatFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx);
|
||||
void LoadFallingBlockFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx);
|
||||
void LoadPickupFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx);
|
||||
void LoadTNTFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx);
|
||||
void LoadExpOrbFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx);
|
||||
void LoadHangingFromNBT (cHangingEntity & a_Hanging,const cParsedNBT & a_NBT, int a_TagIdx);
|
||||
void LoadItemFrameFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx);
|
||||
|
||||
void LoadMinecartRFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx);
|
||||
void LoadMinecartCFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx);
|
||||
@ -192,7 +197,6 @@ protected:
|
||||
void LoadWolfFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx);
|
||||
void LoadZombieFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx);
|
||||
void LoadPigZombieFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx);
|
||||
void LoadTNTFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx);
|
||||
|
||||
/// Loads entity common data from the NBT compound; returns true if successful
|
||||
bool LoadEntityBaseFromNBT(cEntity & a_Entity, const cParsedNBT & a_NBT, int a_TagIdx);
|
||||
|
Loading…
Reference in New Issue
Block a user