1
0

Merge branch 'master' of https://github.com/mc-server/MCServer into portals

This commit is contained in:
Tiger Wang 2014-06-24 21:15:48 +01:00
commit bd5df3d3b9
20 changed files with 297 additions and 102 deletions

View File

@ -1,6 +1,6 @@
Many people have contributed to MCServer, and this list attempts to broadcast at least some of them. Many people have contributed to MCServer, and this list attempts to broadcast at least some of them.
BasedDoge - Donated AlchemistVillage prefabs BasedDoge (Donated AlchemistVillage prefabs)
bearbin (Alexander Harkness) bearbin (Alexander Harkness)
derouinw derouinw
Diusrex Diusrex
@ -27,6 +27,6 @@ tonibm19
UltraCoderRU UltraCoderRU
worktycho worktycho
xoft xoft
Yeeeeezus - Donated AlchemistVillage prefabs Yeeeeezus (Donated AlchemistVillage prefabs)
Please add yourself to this list if you contribute to MCServer. Please add yourself to this list if you contribute to MCServer.

View File

@ -523,13 +523,16 @@ end
Functions = Functions =
{ {
GenerateOfflineUUID = { Params = "Username", Return = "string", Notes = "(STATIC) Generates an UUID based on the player name provided. This is used for the offline (non-auth) mode, when there's no UUID source. Each username generates a unique and constant UUID, so that when the player reconnects with the same name, their UUID is the same. Returns a 36-char UUID (with dashes)." },
GetLocale = { Params = "", Return = "Locale", Notes = "Returns the locale string that the client sends as part of the protocol handshake. Can be used to provide localized strings." }, GetLocale = { Params = "", Return = "Locale", Notes = "Returns the locale string that the client sends as part of the protocol handshake. Can be used to provide localized strings." },
GetPing = { Params = "", Return = "number", Notes = "Returns the ping time, in ms" }, GetPing = { Params = "", Return = "number", Notes = "Returns the ping time, in ms" },
GetPlayer = { Params = "", Return = "{{cPlayer|cPlayer}}", Notes = "Returns the player object connected to this client. Note that this may be nil, for example if the player object is not yet spawned." }, GetPlayer = { Params = "", Return = "{{cPlayer|cPlayer}}", Notes = "Returns the player object connected to this client. Note that this may be nil, for example if the player object is not yet spawned." },
GetUniqueID = { Params = "", Return = "number", Notes = "Returns the UniqueID of the client used to identify the client in the server" }, GetUniqueID = { Params = "", Return = "number", Notes = "Returns the UniqueID of the client used to identify the client in the server" },
GetUUID = { Params = "", Return = "string", Notes = "Returns the authentication-based UUID of the client. This UUID should be used to identify the player when persisting any player-related data." },
GetUsername = { Params = "", Return = "string", Notes = "Returns the username that the client has provided" }, GetUsername = { Params = "", Return = "string", Notes = "Returns the username that the client has provided" },
GetViewDistance = { Params = "", Return = "number", Notes = "Returns the viewdistance (number of chunks loaded for the player in each direction)" }, GetViewDistance = { Params = "", Return = "number", Notes = "Returns the viewdistance (number of chunks loaded for the player in each direction)" },
HasPluginChannel = { Params = "ChannelName", Return = "bool", Notes = "Returns true if the client has registered to receive messages on the specified plugin channel." }, HasPluginChannel = { Params = "ChannelName", Return = "bool", Notes = "Returns true if the client has registered to receive messages on the specified plugin channel." },
IsUUIDOnline = { Params = "UUID", Return = "bool", Notes = "(STATIC) Returns true if the UUID is generated by online auth, false if it is an offline-generated UUID. We use Version-3 UUIDs for offline UUIDs, online UUIDs are Version-4, thus we can tell them apart. Accepts both 32-char and 36-char UUIDs (with and without dashes). If the string given is not a valid UUID, returns false."},
Kick = { Params = "Reason", Return = "", Notes = "Kicks the user with the specified reason" }, Kick = { Params = "Reason", Return = "", Notes = "Kicks the user with the specified reason" },
SendPluginMessage = { Params = "Channel, Message", Return = "", Notes = "Sends the plugin message on the specified channel." }, SendPluginMessage = { Params = "Channel, Message", Return = "", Notes = "Sends the plugin message on the specified channel." },
SetLocale = { Params = "Locale", Return = "", Notes = "Sets the locale that MCServer keeps on record. Initially the locale is initialized in protocol handshake, this function allows plugins to override the stored value (but only server-side and only until the user disconnects)." }, SetLocale = { Params = "Locale", Return = "", Notes = "Sets the locale that MCServer keeps on record. Initially the locale is initialized in protocol handshake, this function allows plugins to override the stored value (but only server-side and only until the user disconnects)." },

View File

@ -346,7 +346,7 @@ end
function OnUsingBlazeRod(Player, BlockX, BlockY, BlockZ, BlockFace, CursorX, CursorY, CursorZ) function OnUsingBlazeRod(Player, BlockX, BlockY, BlockZ, BlockFace, CursorX, CursorY, CursorZ)
-- Magic rod of query: show block types and metas for both neighbors of the pointed face -- Magic rod of query: show block types and metas for both neighbors of the pointed face
local Type, Meta, Valid = Player:GetWorld():GetBlockTypeMeta(BlockX, BlockY, BlockZ, Type, Meta); local Valid, Type, Meta = Player:GetWorld():GetBlockTypeMeta(BlockX, BlockY, BlockZ);
if (Type == E_BLOCK_AIR) then if (Type == E_BLOCK_AIR) then
Player:SendMessage(cChatColor.LightGray .. "Block {" .. BlockX .. ", " .. BlockY .. ", " .. BlockZ .. "}: air:" .. Meta); Player:SendMessage(cChatColor.LightGray .. "Block {" .. BlockX .. ", " .. BlockY .. ", " .. BlockZ .. "}: air:" .. Meta);
@ -356,7 +356,7 @@ function OnUsingBlazeRod(Player, BlockX, BlockY, BlockZ, BlockFace, CursorX, Cur
end end
local X, Y, Z = AddFaceDirection(BlockX, BlockY, BlockZ, BlockFace); local X, Y, Z = AddFaceDirection(BlockX, BlockY, BlockZ, BlockFace);
Valid, Type, Meta = Player:GetWorld():GetBlockTypeMeta(X, Y, Z, Type, Meta); Valid, Type, Meta = Player:GetWorld():GetBlockTypeMeta(X, Y, Z);
if (Type == E_BLOCK_AIR) then if (Type == E_BLOCK_AIR) then
Player:SendMessage(cChatColor.LightGray .. "Block {" .. X .. ", " .. Y .. ", " .. Z .. "}: air:" .. Meta); Player:SendMessage(cChatColor.LightGray .. "Block {" .. X .. ", " .. Y .. ", " .. Z .. "}: air:" .. Meta);
else else

View File

@ -122,6 +122,13 @@ void cChestEntity::UsedBy(cPlayer * a_Player)
void cChestEntity::OpenNewWindow(void) void cChestEntity::OpenNewWindow(void)
{ {
// TODO: cats are an obstruction
if ((GetPosY() + 1 < cChunkDef::Height) && cBlockInfo::IsSolid(GetWorld()->GetBlock(GetPosX(), GetPosY() + 1, GetPosZ())))
{
// Obstruction, don't open
return;
}
// Callback for opening together with neighbor chest: // Callback for opening together with neighbor chest:
class cOpenDouble : class cOpenDouble :
public cChestCallback public cChestCallback
@ -135,6 +142,12 @@ void cChestEntity::OpenNewWindow(void)
virtual bool Item(cChestEntity * a_Chest) override virtual bool Item(cChestEntity * a_Chest) override
{ {
if ((a_Chest->GetPosY() + 1 < cChunkDef::Height) && cBlockInfo::IsSolid(a_Chest->GetWorld()->GetBlock(a_Chest->GetPosX(), a_Chest->GetPosY() + 1, a_Chest->GetPosZ())))
{
// Obstruction, don't open
return false;
}
// The primary chest should eb the one with lesser X or Z coord: // The primary chest should eb the one with lesser X or Z coord:
cChestEntity * Primary = a_Chest; cChestEntity * Primary = a_Chest;
cChestEntity * Secondary = m_ThisChest; cChestEntity * Secondary = m_ThisChest;

View File

@ -294,23 +294,24 @@ bool cHopperEntity::MoveItemsOut(cChunk & a_Chunk, Int64 a_CurrentTick)
return false; return false;
} }
int bx, by, bz; // Get the coords of the block where to output items:
int OutX, OutY, OutZ;
NIBBLETYPE Meta = a_Chunk.GetMeta(m_RelX, m_PosY, m_RelZ); NIBBLETYPE Meta = a_Chunk.GetMeta(m_RelX, m_PosY, m_RelZ);
if (!GetOutputBlockPos(Meta, bx, by, bz)) if (!GetOutputBlockPos(Meta, OutX, OutY, OutZ))
{ {
// Not attached to another container // Not attached to another container
return false; return false;
} }
if (by < 0) if (OutY < 0)
{ {
// Cannot output below the zero-th block level // Cannot output below the zero-th block level
return false; return false;
} }
// Convert coords to relative: // Convert coords to relative:
int rx = bx - a_Chunk.GetPosX() * cChunkDef::Width; int OutRelX = OutX - a_Chunk.GetPosX() * cChunkDef::Width;
int rz = bz - a_Chunk.GetPosZ() * cChunkDef::Width; int OutRelZ = OutZ - a_Chunk.GetPosZ() * cChunkDef::Width;
cChunk * DestChunk = a_Chunk.GetRelNeighborChunkAdjustCoords(rx, rz); cChunk * DestChunk = a_Chunk.GetRelNeighborChunkAdjustCoords(OutRelX, OutRelZ);
if (DestChunk == NULL) if (DestChunk == NULL)
{ {
// The destination chunk has been unloaded, don't tick // The destination chunk has been unloaded, don't tick
@ -319,26 +320,32 @@ bool cHopperEntity::MoveItemsOut(cChunk & a_Chunk, Int64 a_CurrentTick)
// Call proper moving function, based on the blocktype present at the coords: // Call proper moving function, based on the blocktype present at the coords:
bool res = false; bool res = false;
switch (DestChunk->GetBlock(rx, by, rz)) switch (DestChunk->GetBlock(OutRelX, OutY, OutRelZ))
{ {
case E_BLOCK_CHEST: case E_BLOCK_CHEST:
{ {
// Chests have special handling because of double-chests // Chests have special handling because of double-chests
res = MoveItemsToChest(*DestChunk, bx, by, bz); res = MoveItemsToChest(*DestChunk, OutX, OutY, OutZ);
break; break;
} }
case E_BLOCK_LIT_FURNACE: case E_BLOCK_LIT_FURNACE:
case E_BLOCK_FURNACE: case E_BLOCK_FURNACE:
{ {
// Furnaces have special handling because of the direction-to-slot relation // Furnaces have special handling because of the direction-to-slot relation
res = MoveItemsToFurnace(*DestChunk, bx, by, bz, Meta); res = MoveItemsToFurnace(*DestChunk, OutX, OutY, OutZ, Meta);
break; break;
} }
case E_BLOCK_DISPENSER: case E_BLOCK_DISPENSER:
case E_BLOCK_DROPPER: case E_BLOCK_DROPPER:
case E_BLOCK_HOPPER: case E_BLOCK_HOPPER:
{ {
res = MoveItemsToGrid(*(cBlockEntityWithItems *)DestChunk->GetBlockEntity(bx, by, bz)); cBlockEntityWithItems * BlockEntity = (cBlockEntityWithItems *)DestChunk->GetBlockEntity(OutX, OutY, OutZ);
if (BlockEntity == NULL)
{
LOGWARNING("%s: A block entity was not found where expected at {%d, %d, %d}", __FUNCTION__, OutX, OutY, OutZ);
return false;
}
res = MoveItemsToGrid(*BlockEntity);
break; break;
} }
} }
@ -359,7 +366,13 @@ bool cHopperEntity::MoveItemsOut(cChunk & a_Chunk, Int64 a_CurrentTick)
/// Moves items from a chest (dblchest) above the hopper into this hopper. Returns true if contents have changed. /// Moves items from a chest (dblchest) above the hopper into this hopper. Returns true if contents have changed.
bool cHopperEntity::MoveItemsFromChest(cChunk & a_Chunk) bool cHopperEntity::MoveItemsFromChest(cChunk & a_Chunk)
{ {
if (MoveItemsFromGrid(*(cChestEntity *)a_Chunk.GetBlockEntity(m_PosX, m_PosY + 1, m_PosZ))) cChestEntity * Chest = (cChestEntity *)a_Chunk.GetBlockEntity(m_PosX, m_PosY + 1, m_PosZ);
if (Chest == NULL)
{
LOGWARNING("%s: A chest entity was not found where expected, at {%d, %d, %d}", __FUNCTION__, m_PosX, m_PosY + 1, m_PosZ);
return false;
}
if (MoveItemsFromGrid(*Chest))
{ {
// Moved the item from the chest directly above the hopper // Moved the item from the chest directly above the hopper
return true; return true;
@ -389,10 +402,18 @@ bool cHopperEntity::MoveItemsFromChest(cChunk & a_Chunk)
{ {
continue; continue;
} }
if (MoveItemsFromGrid(*(cChestEntity *)Neighbor->GetBlockEntity(x, m_PosY, z))) Chest = (cChestEntity *)Neighbor->GetBlockEntity(m_PosX + Coords[i].x, m_PosY + 1, m_PosZ + Coords[i].z);
if (Chest == NULL)
{
LOGWARNING("%s: A chest entity was not found where expected, at {%d, %d, %d}", __FUNCTION__, m_PosX + Coords[i].x, m_PosY + 1, m_PosZ + Coords[i].z);
}
else
{
if (MoveItemsFromGrid(*Chest))
{ {
return true; return true;
} }
}
return false; return false;
} }
@ -408,7 +429,11 @@ bool cHopperEntity::MoveItemsFromChest(cChunk & a_Chunk)
bool cHopperEntity::MoveItemsFromFurnace(cChunk & a_Chunk) bool cHopperEntity::MoveItemsFromFurnace(cChunk & a_Chunk)
{ {
cFurnaceEntity * Furnace = (cFurnaceEntity *)a_Chunk.GetBlockEntity(m_PosX, m_PosY + 1, m_PosZ); cFurnaceEntity * Furnace = (cFurnaceEntity *)a_Chunk.GetBlockEntity(m_PosX, m_PosY + 1, m_PosZ);
ASSERT(Furnace != NULL); if (Furnace == NULL)
{
LOGWARNING("%s: A furnace entity was not found where expected, at {%d, %d, %d}", __FUNCTION__, m_PosX, m_PosY + 1, m_PosZ);
return false;
}
// Try move from the output slot: // Try move from the output slot:
if (MoveItemsFromSlot(*Furnace, cFurnaceEntity::fsOutput, true)) if (MoveItemsFromSlot(*Furnace, cFurnaceEntity::fsOutput, true))
@ -517,7 +542,13 @@ bool cHopperEntity::MoveItemsFromSlot(cBlockEntityWithItems & a_Entity, int a_Sl
bool cHopperEntity::MoveItemsToChest(cChunk & a_Chunk, int a_BlockX, int a_BlockY, int a_BlockZ) bool cHopperEntity::MoveItemsToChest(cChunk & a_Chunk, int a_BlockX, int a_BlockY, int a_BlockZ)
{ {
// Try the chest directly connected to the hopper: // Try the chest directly connected to the hopper:
if (MoveItemsToGrid(*(cChestEntity *)a_Chunk.GetBlockEntity(a_BlockX, a_BlockY, a_BlockZ))) cChestEntity * Chest = (cChestEntity *)a_Chunk.GetBlockEntity(a_BlockX, a_BlockY, a_BlockZ);
if (Chest == NULL)
{
LOGWARNING("%s: A chest entity was not found where expected, at {%d, %d, %d}", __FUNCTION__, a_BlockX, a_BlockY, a_BlockZ);
return false;
}
if (MoveItemsToGrid(*Chest))
{ {
return true; return true;
} }
@ -534,19 +565,27 @@ bool cHopperEntity::MoveItemsToChest(cChunk & a_Chunk, int a_BlockX, int a_Block
{0, 1}, {0, 1},
{0, -1}, {0, -1},
} ; } ;
int RelX = a_BlockX - a_Chunk.GetPosX() * cChunkDef::Width;
int RelZ = a_BlockZ - a_Chunk.GetPosZ() * cChunkDef::Width;
for (size_t i = 0; i < ARRAYCOUNT(Coords); i++) for (size_t i = 0; i < ARRAYCOUNT(Coords); i++)
{ {
int x = m_RelX + Coords[i].x; int x = RelX + Coords[i].x;
int z = m_RelZ + Coords[i].z; int z = RelZ + Coords[i].z;
cChunk * Neighbor = a_Chunk.GetRelNeighborChunkAdjustCoords(x, z); cChunk * Neighbor = a_Chunk.GetRelNeighborChunkAdjustCoords(x, z);
if ( if (
(Neighbor == NULL) || (Neighbor == NULL) ||
(Neighbor->GetBlock(x, m_PosY + 1, z) != E_BLOCK_CHEST) (Neighbor->GetBlock(x, a_BlockY, z) != E_BLOCK_CHEST)
) )
{ {
continue; continue;
} }
if (MoveItemsToGrid(*(cChestEntity *)Neighbor->GetBlockEntity(a_BlockX, a_BlockY, a_BlockZ))) Chest = (cChestEntity *)Neighbor->GetBlockEntity(a_BlockX + Coords[i].x, a_BlockY, a_BlockZ + Coords[i].z);
if (Chest == NULL)
{
LOGWARNING("%s: A chest entity was not found where expected, at {%d, %d, %d} (%d, %d)", __FUNCTION__, a_BlockX + Coords[i].x, a_BlockY, a_BlockZ + Coords[i].z, x, z);
continue;
}
if (MoveItemsToGrid(*Chest))
{ {
return true; return true;
} }

View File

@ -9,6 +9,7 @@
cBlockInfo cBlockInfo::ms_Info[256]; cBlockInfo cBlockInfo::ms_Info[256];
static bool g_IsBlockInfoInitialized = false;
@ -43,6 +44,11 @@ cBlockInfo::~cBlockInfo()
cBlockInfo & cBlockInfo::Get(BLOCKTYPE a_Type) cBlockInfo & cBlockInfo::Get(BLOCKTYPE a_Type)
{ {
if (!g_IsBlockInfoInitialized)
{
cBlockInfo::Initialize();
g_IsBlockInfoInitialized = true;
}
return ms_Info[a_Type]; return ms_Info[a_Type];
} }
@ -448,18 +454,3 @@ void cBlockInfo::Initialize(void)
// This is actually just some code that needs to run at program startup, so it is wrapped into a global var's constructor:
class cBlockInfoInitializer
{
public:
cBlockInfoInitializer(void)
{
cBlockInfo::Initialize();
}
} BlockInfoInitializer;

View File

@ -45,9 +45,16 @@ void cBlockDoorHandler::OnDestroyed(cChunkInterface & a_ChunkInterface, cWorldIn
void cBlockDoorHandler::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) void cBlockDoorHandler::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)
{ {
UNUSED(a_WorldInterface);
UNUSED(a_BlockFace);
UNUSED(a_CursorX);
UNUSED(a_CursorY);
UNUSED(a_CursorZ);
if (a_ChunkInterface.GetBlock(a_BlockX, a_BlockY, a_BlockZ) == E_BLOCK_WOODEN_DOOR) if (a_ChunkInterface.GetBlock(a_BlockX, a_BlockY, a_BlockZ) == E_BLOCK_WOODEN_DOOR)
{ {
ChangeDoor(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ); ChangeDoor(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ);
a_Player->GetWorld()->BroadcastSoundParticleEffect(1003, a_BlockX, a_BlockY, a_BlockZ, 0, a_Player->GetClientHandle());
} }
} }

View File

@ -45,6 +45,7 @@ public:
// Standing aside - use last direction // Standing aside - use last direction
a_ChunkInterface.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, OldMetaData); a_ChunkInterface.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, OldMetaData);
} }
a_Player->GetWorld()->BroadcastSoundParticleEffect(1003, a_BlockX, a_BlockY, a_BlockZ, 0, a_Player->GetClientHandle());
} }

View File

@ -85,6 +85,91 @@
/*
// Tests the meta rotation and mirroring.
// Note that the cMetaRotator needs to have its assert paths disabled for this test to work!
static class cBlockHandlerRotationTester
{
public:
cBlockHandlerRotationTester(void)
{
printf("Performing block handlers test...\n");
for (BLOCKTYPE Type = 0; Type < E_BLOCK_MAX_TYPE_ID; Type++)
{
cBlockHandler * Handler = cBlockInfo::GetHandler(Type);
if (Handler == NULL)
{
printf("NULL handler for block type %d!\n", Type);
continue;
}
AString BlockName = ItemTypeToString(Type);
for (NIBBLETYPE Meta = 0; Meta < 16; Meta++)
{
// Test the CW / CCW rotations:
NIBBLETYPE TestMeta;
TestMeta = Handler->MetaRotateCW(Handler->MetaRotateCW(Handler->MetaRotateCW(Handler->MetaRotateCW(Meta))));
if (TestMeta != Meta)
{
// 4 CW rotations should produce no change in the meta
printf("Handler for blocktype %d (%s) fails CW 4-rotation test for meta %d: got back %d\n", Type, BlockName.c_str(), Meta, TestMeta);
}
TestMeta = Handler->MetaRotateCCW(Handler->MetaRotateCCW(Handler->MetaRotateCCW(Handler->MetaRotateCCW(Meta))));
if (TestMeta != Meta)
{
// 4 CCW rotations should produce no change in the meta
printf("Handler for blocktype %d (%s) fails CCW 4-rotation test for meta %d: got back %d\n", Type, BlockName.c_str(), Meta, TestMeta);
}
TestMeta = Handler->MetaRotateCCW(Handler->MetaRotateCW(Meta));
if (TestMeta != Meta)
{
// CCW rotation of a CW rotation should produce no change in the meta
printf("Handler for blocktype %d (%s) fails CCW(CW) rotation test for meta %d: got back %d\n", Type, BlockName.c_str(), Meta, TestMeta);
}
TestMeta = Handler->MetaRotateCW(Handler->MetaRotateCCW(Meta));
if (TestMeta != Meta)
{
// CW rotation of a CCW rotation should produce no change in the meta
printf("Handler for blocktype %d (%s) fails CW(CCW) rotation test for meta %d: got back %d\n", Type, BlockName.c_str(), Meta, TestMeta);
}
// Test the mirroring:
TestMeta = Handler->MetaMirrorXY(Handler->MetaMirrorXY(Meta));
if (TestMeta != Meta)
{
// Double-mirroring should produce the same meta:
printf("Handler for blocktype %d (%s) fails XY mirror test for meta %d: got back %d\n", Type, BlockName.c_str(), Meta, TestMeta);
}
TestMeta = Handler->MetaMirrorXZ(Handler->MetaMirrorXZ(Meta));
if (TestMeta != Meta)
{
// Double-mirroring should produce the same meta:
printf("Handler for blocktype %d (%s) fails XZ mirror test for meta %d: got back %d\n", Type, BlockName.c_str(), Meta, TestMeta);
}
TestMeta = Handler->MetaMirrorYZ(Handler->MetaMirrorYZ(Meta));
if (TestMeta != Meta)
{
// Double-mirroring should produce the same meta:
printf("Handler for blocktype %d (%s) fails YZ mirror test for meta %d: got back %d\n", Type, BlockName.c_str(), Meta, TestMeta);
}
// Test mirror-rotating:
TestMeta = Handler->MetaRotateCW(Handler->MetaRotateCW(Handler->MetaMirrorXY(Handler->MetaMirrorYZ(Meta))));
if (TestMeta != Meta)
{
// 2 CW rotations should be the same as XY, YZ mirroring:
printf("Handler for blocktype %d (%s) fails rotation-mirror test for meta %d: got back %d\n", Type, BlockName.c_str(), Meta, TestMeta);
}
}
} // for Type
printf("Block handlers test complete.\n");
}
} g_BlockHandlerRotationTester;
//*/
cBlockHandler * cBlockHandler::CreateBlockHandler(BLOCKTYPE a_BlockType) cBlockHandler * cBlockHandler::CreateBlockHandler(BLOCKTYPE a_BlockType)
{ {
switch(a_BlockType) switch(a_BlockType)
@ -175,7 +260,7 @@ cBlockHandler * cBlockHandler::CreateBlockHandler(BLOCKTYPE a_BlockType)
case E_BLOCK_QUARTZ_BLOCK: return new cBlockQuartzHandler (a_BlockType); case E_BLOCK_QUARTZ_BLOCK: return new cBlockQuartzHandler (a_BlockType);
case E_BLOCK_QUARTZ_STAIRS: return new cBlockStairsHandler (a_BlockType); case E_BLOCK_QUARTZ_STAIRS: return new cBlockStairsHandler (a_BlockType);
case E_BLOCK_RAIL: return new cBlockRailHandler (a_BlockType); case E_BLOCK_RAIL: return new cBlockRailHandler (a_BlockType);
case E_BLOCK_REDSTONE_LAMP_ON: return new cBlockRedstoneLampHandler (a_BlockType); // We need this to change pickups to an off lamp; else 1.7+ clients crash case E_BLOCK_REDSTONE_LAMP_ON: return new cBlockRedstoneLampHandler (a_BlockType);
case E_BLOCK_REDSTONE_ORE: return new cBlockOreHandler (a_BlockType); case E_BLOCK_REDSTONE_ORE: return new cBlockOreHandler (a_BlockType);
case E_BLOCK_REDSTONE_ORE_GLOWING: return new cBlockOreHandler (a_BlockType); case E_BLOCK_REDSTONE_ORE_GLOWING: return new cBlockOreHandler (a_BlockType);
case E_BLOCK_REDSTONE_REPEATER_OFF: return new cBlockRedstoneRepeaterHandler(a_BlockType); case E_BLOCK_REDSTONE_REPEATER_OFF: return new cBlockRedstoneRepeaterHandler(a_BlockType);
@ -207,7 +292,7 @@ cBlockHandler * cBlockHandler::CreateBlockHandler(BLOCKTYPE a_BlockType)
case E_BLOCK_TRAPDOOR: return new cBlockTrapdoorHandler (a_BlockType); case E_BLOCK_TRAPDOOR: return new cBlockTrapdoorHandler (a_BlockType);
case E_BLOCK_TNT: return new cBlockTNTHandler (a_BlockType); case E_BLOCK_TNT: return new cBlockTNTHandler (a_BlockType);
case E_BLOCK_VINES: return new cBlockVineHandler (a_BlockType); case E_BLOCK_VINES: return new cBlockVineHandler (a_BlockType);
case E_BLOCK_WALLSIGN: return new cBlockSignHandler (a_BlockType); case E_BLOCK_WALLSIGN: return new cBlockSignHandler (a_BlockType); // TODO: This needs a special handler
case E_BLOCK_WATER: return new cBlockFluidHandler (a_BlockType); case E_BLOCK_WATER: return new cBlockFluidHandler (a_BlockType);
case E_BLOCK_WOODEN_BUTTON: return new cBlockButtonHandler (a_BlockType); case E_BLOCK_WOODEN_BUTTON: return new cBlockButtonHandler (a_BlockType);
case E_BLOCK_WOODEN_DOOR: return new cBlockDoorHandler (a_BlockType); case E_BLOCK_WOODEN_DOOR: return new cBlockDoorHandler (a_BlockType);

View File

@ -7,12 +7,13 @@
class cBlockLeverHandler : class cBlockLeverHandler :
public cMetaRotator<cBlockHandler, 0x07, 0x04, 0x02, 0x03, 0x01, false> public cMetaRotator<cBlockHandler, 0x07, 0x04, 0x01, 0x03, 0x02, false>
{ {
typedef cMetaRotator<cBlockHandler, 0x07, 0x04, 0x02, 0x03, 0x01, false> super; typedef cMetaRotator<cBlockHandler, 0x07, 0x04, 0x01, 0x03, 0x02, false> super;
public: public:
cBlockLeverHandler(BLOCKTYPE a_BlockType) cBlockLeverHandler(BLOCKTYPE a_BlockType) :
: cMetaRotator<cBlockHandler, 0x07, 0x04, 0x02, 0x03, 0x01, false>(a_BlockType) super(a_BlockType)
{ {
} }
@ -132,7 +133,7 @@ public:
case 0x05: return 0x06; // Ground rotation case 0x05: return 0x06; // Ground rotation
case 0x06: return 0x05; case 0x06: return 0x05;
default: return super::MetaRotateCCW(a_Meta); // Wall Rotation default: return super::MetaRotateCW(a_Meta); // Wall Rotation
} }
} }
} ; } ;

View File

@ -75,13 +75,13 @@ public:
virtual NIBBLETYPE MetaRotateCW(NIBBLETYPE a_Meta) override virtual NIBBLETYPE MetaRotateCW(NIBBLETYPE a_Meta) override
{ {
return (++a_Meta) & 0x0F; return (a_Meta + 4) & 0x0f;
} }
virtual NIBBLETYPE MetaRotateCCW(NIBBLETYPE a_Meta) override virtual NIBBLETYPE MetaRotateCCW(NIBBLETYPE a_Meta) override
{ {
return (--a_Meta) & 0x0F; return (a_Meta + 12) & 0x0f;
} }
virtual NIBBLETYPE MetaMirrorXY(NIBBLETYPE a_Meta) override virtual NIBBLETYPE MetaMirrorXY(NIBBLETYPE a_Meta) override
@ -90,7 +90,7 @@ public:
// There are 16 meta values which correspond to different directions. // There are 16 meta values which correspond to different directions.
// These values are equated to angles on a circle; 0x08 = 180 degrees. // These values are equated to angles on a circle; 0x08 = 180 degrees.
return (a_Meta < 0x08) ? 0x08 + a_Meta : 0x08 - a_Meta; return (a_Meta < 0x08) ? (0x08 + a_Meta) : (0x08 - a_Meta);
} }

View File

@ -124,6 +124,12 @@ public:
return E_BLOCK_AIR; return E_BLOCK_AIR;
} }
virtual NIBBLETYPE MetaMirrorXZ(NIBBLETYPE a_Meta) override
{
// Toggle the 4th bit - up / down:
return (a_Meta ^ 0x08);
}
} ; } ;
@ -167,15 +173,6 @@ public:
ASSERT(!"Unhandled double slab type!"); ASSERT(!"Unhandled double slab type!");
return ""; return "";
} }
virtual NIBBLETYPE MetaMirrorXZ(NIBBLETYPE a_Meta) override
{
NIBBLETYPE OtherMeta = a_Meta & 0x07; // Contains unrelated meta data.
// 8th bit is up/down. 1 right-side-up, 0 is up-side-down.
return (a_Meta & 0x08) ? 0x00 + OtherMeta : 0x01 + OtherMeta;
}
} ; } ;

View File

@ -1616,6 +1616,12 @@ void cChunk::AddBlockEntity(cBlockEntity * a_BlockEntity)
cBlockEntity * cChunk::GetBlockEntity(int a_BlockX, int a_BlockY, int a_BlockZ) cBlockEntity * cChunk::GetBlockEntity(int a_BlockX, int a_BlockY, int a_BlockZ)
{ {
// Check that the query coords are within chunk bounds:
ASSERT(a_BlockX >= m_PosX * cChunkDef::Width);
ASSERT(a_BlockX < m_PosX * cChunkDef::Width + cChunkDef::Width);
ASSERT(a_BlockZ >= m_PosZ * cChunkDef::Width);
ASSERT(a_BlockZ < m_PosZ * cChunkDef::Width + cChunkDef::Width);
for (cBlockEntityList::iterator itr = m_BlockEntities.begin(); itr != m_BlockEntities.end(); ++itr) for (cBlockEntityList::iterator itr = m_BlockEntities.begin(); itr != m_BlockEntities.end(); ++itr)
{ {
if ( if (

View File

@ -231,6 +231,9 @@ AString cClientHandle::FormatMessageType(bool ShouldAppendChatPrefixes, eMessage
AString cClientHandle::GenerateOfflineUUID(const AString & a_Username) AString cClientHandle::GenerateOfflineUUID(const AString & a_Username)
{ {
// Online UUIDs are always version 4 (random)
// We use Version 3 (MD5 hash) UUIDs for the offline UUIDs
// This guarantees that they will never collide with an online UUID and can be distinguished.
// Proper format for a version 3 UUID is: // Proper format for a version 3 UUID is:
// xxxxxxxx-xxxx-3xxx-yxxx-xxxxxxxxxxxx where x is any hexadecimal digit and y is one of 8, 9, A, or B // xxxxxxxx-xxxx-3xxx-yxxx-xxxxxxxxxxxx where x is any hexadecimal digit and y is one of 8, 9, A, or B
@ -253,6 +256,32 @@ AString cClientHandle::GenerateOfflineUUID(const AString & a_Username)
bool cClientHandle::IsUUIDOnline(const AString & a_UUID)
{
// Online UUIDs are always version 4 (random)
// We use Version 3 (MD5 hash) UUIDs for the offline UUIDs
// This guarantees that they will never collide with an online UUID and can be distinguished.
// The version-specifying char is at pos #12 of raw UUID, pos #14 in dashed-UUID.
switch (a_UUID.size())
{
case 32:
{
// This is the UUID format without dashes, the version char is at pos #12:
return (a_UUID[12] == '4');
}
case 36:
{
// This is the UUID format with dashes, the version char is at pos #14:
return (a_UUID[14] == '4');
}
}
return false;
}
void cClientHandle::Kick(const AString & a_Reason) void cClientHandle::Kick(const AString & a_Reason)
{ {
if (m_State >= csAuthenticating) // Don't log pings if (m_State >= csAuthenticating) // Don't log pings

View File

@ -63,7 +63,7 @@ public:
const AString & GetIPString(void) const { return m_IPString; } const AString & GetIPString(void) const { return m_IPString; }
cPlayer* GetPlayer() { return m_Player; } // tolua_export cPlayer * GetPlayer(void) { return m_Player; } // tolua_export
const AString & GetUUID(void) const { return m_UUID; } // tolua_export const AString & GetUUID(void) const { return m_UUID; } // tolua_export
void SetUUID(const AString & a_UUID) { m_UUID = a_UUID; } void SetUUID(const AString & a_UUID) { m_UUID = a_UUID; }
@ -76,9 +76,16 @@ public:
/** Generates an UUID based on the player name provided. /** Generates an UUID based on the player name provided.
This is used for the offline (non-auth) mode, when there's no UUID source. This is used for the offline (non-auth) mode, when there's no UUID source.
Each username generates a unique and constant UUID, so that when the player reconnects with the same name, their UUID is the same. */ Each username generates a unique and constant UUID, so that when the player reconnects with the same name, their UUID is the same.
Returns a 36-char UUID (with dashes). */
static AString GenerateOfflineUUID(const AString & a_Username); // tolua_export static AString GenerateOfflineUUID(const AString & a_Username); // tolua_export
/** Returns true if the UUID is generated by online auth, false if it is an offline-generated UUID.
We use Version-3 UUIDs for offline UUIDs, online UUIDs are Version-4, thus we can tell them apart.
Accepts both 32-char and 36-char UUIDs (with and without dashes).
If the string given is not a valid UUID, returns false. */
static bool IsUUIDOnline(const AString & a_UUID); // tolua_export
/** Formats the type of message with the proper color and prefix for sending to the client. **/ /** Formats the type of message with the proper color and prefix for sending to the client. **/
static AString FormatMessageType(bool ShouldAppendChatPrefixes, eMessageType a_ChatPrefix, const AString & a_AdditionalData); static AString FormatMessageType(bool ShouldAppendChatPrefixes, eMessageType a_ChatPrefix, const AString & a_AdditionalData);

View File

@ -211,6 +211,17 @@ void cPrefab::Draw(cChunkDesc & a_Dest, const Vector3i & a_Placement, int a_NumR
int ChunkStartZ = a_Dest.GetChunkZ() * cChunkDef::Width; int ChunkStartZ = a_Dest.GetChunkZ() * cChunkDef::Width;
Placement.Move(-ChunkStartX, 0, -ChunkStartZ); Placement.Move(-ChunkStartX, 0, -ChunkStartZ);
const cBlockArea & Image = m_BlockArea[a_NumRotations]; const cBlockArea & Image = m_BlockArea[a_NumRotations];
// If the placement is outside this chunk, bail out:
if (
(Placement.x > cChunkDef::Width) || (Placement.x + Image.GetSizeX() < 0) ||
(Placement.z > cChunkDef::Width) || (Placement.z + Image.GetSizeZ() < 0)
)
{
return;
}
// Write the image:
a_Dest.WriteBlockArea(Image, Placement.x, Placement.y, Placement.z, m_MergeStrategy); a_Dest.WriteBlockArea(Image, Placement.x, Placement.y, Placement.z, m_MergeStrategy);
// If requested, draw the floor (from the bottom of the prefab down to the nearest non-air) // If requested, draw the floor (from the bottom of the prefab down to the nearest non-air)

View File

@ -59,21 +59,20 @@ void cIncrementalRedstoneSimulator::RedstoneAddBlock(int a_BlockX, int a_BlockY,
int RelZ = 0; int RelZ = 0;
BLOCKTYPE Block; BLOCKTYPE Block;
NIBBLETYPE Meta; NIBBLETYPE Meta;
cChunk * Chunk; cChunk * OtherChunk = a_Chunk;
if (a_OtherChunk != NULL) if (a_OtherChunk != NULL)
{ {
RelX = a_BlockX - a_OtherChunk->GetPosX() * cChunkDef::Width; RelX = a_BlockX - a_OtherChunk->GetPosX() * cChunkDef::Width;
RelZ = a_BlockZ - a_OtherChunk->GetPosZ() * cChunkDef::Width; RelZ = a_BlockZ - a_OtherChunk->GetPosZ() * cChunkDef::Width;
a_OtherChunk->GetBlockTypeMeta(RelX, a_BlockY, RelZ, Block, Meta); a_OtherChunk->GetBlockTypeMeta(RelX, a_BlockY, RelZ, Block, Meta);
Chunk = a_OtherChunk; OtherChunk = a_OtherChunk;
} }
else else
{ {
RelX = a_BlockX - a_Chunk->GetPosX() * cChunkDef::Width; RelX = a_BlockX - a_Chunk->GetPosX() * cChunkDef::Width;
RelZ = a_BlockZ - a_Chunk->GetPosZ() * cChunkDef::Width; RelZ = a_BlockZ - a_Chunk->GetPosZ() * cChunkDef::Width;
a_Chunk->GetBlockTypeMeta(RelX, a_BlockY, RelZ, Block, Meta); a_Chunk->GetBlockTypeMeta(RelX, a_BlockY, RelZ, Block, Meta);
Chunk = a_Chunk;
} }
// Every time a block is changed (AddBlock called), we want to go through all lists and check to see if the coordiantes stored within are still valid // Every time a block is changed (AddBlock called), we want to go through all lists and check to see if the coordiantes stored within are still valid
@ -92,7 +91,8 @@ void cIncrementalRedstoneSimulator::RedstoneAddBlock(int a_BlockX, int a_BlockY,
{ {
LOGD("cIncrementalRedstoneSimulator: Erased block @ {%i, %i, %i} from powered blocks list as it no longer connected to a source", itr->a_BlockPos.x, itr->a_BlockPos.y, itr->a_BlockPos.z); LOGD("cIncrementalRedstoneSimulator: Erased block @ {%i, %i, %i} from powered blocks list as it no longer connected to a source", itr->a_BlockPos.x, itr->a_BlockPos.y, itr->a_BlockPos.z);
itr = PoweredBlocks->erase(itr); itr = PoweredBlocks->erase(itr);
Chunk->SetIsRedstoneDirty(true); a_Chunk->SetIsRedstoneDirty(true);
OtherChunk->SetIsRedstoneDirty(true);
continue; continue;
} }
else if ( else if (
@ -107,21 +107,23 @@ void cIncrementalRedstoneSimulator::RedstoneAddBlock(int a_BlockX, int a_BlockY,
{ {
LOGD("cIncrementalRedstoneSimulator: Erased block @ {%i, %i, %i} from powered blocks list due to present/past metadata mismatch", itr->a_BlockPos.x, itr->a_BlockPos.y, itr->a_BlockPos.z); LOGD("cIncrementalRedstoneSimulator: Erased block @ {%i, %i, %i} from powered blocks list due to present/past metadata mismatch", itr->a_BlockPos.x, itr->a_BlockPos.y, itr->a_BlockPos.z);
itr = PoweredBlocks->erase(itr); itr = PoweredBlocks->erase(itr);
Chunk->SetIsRedstoneDirty(true); a_Chunk->SetIsRedstoneDirty(true);
OtherChunk->SetIsRedstoneDirty(true);
continue; continue;
} }
else if (Block == E_BLOCK_DAYLIGHT_SENSOR) else if (Block == E_BLOCK_DAYLIGHT_SENSOR)
{ {
if (!m_World.IsChunkLighted(Chunk->GetPosX(), Chunk->GetPosZ())) if (!m_World.IsChunkLighted(OtherChunk->GetPosX(), OtherChunk->GetPosZ()))
{ {
m_World.QueueLightChunk(Chunk->GetPosX(), Chunk->GetPosZ()); m_World.QueueLightChunk(OtherChunk->GetPosX(), OtherChunk->GetPosZ());
} }
else else
{ {
if (Chunk->GetTimeAlteredLight(Chunk->GetSkyLight(RelX, a_BlockY + 1, RelZ)) <= 7) if (OtherChunk->GetTimeAlteredLight(OtherChunk->GetSkyLight(RelX, a_BlockY + 1, RelZ)) <= 7)
{ {
itr = PoweredBlocks->erase(itr); itr = PoweredBlocks->erase(itr);
Chunk->SetIsRedstoneDirty(true); a_Chunk->SetIsRedstoneDirty(true);
OtherChunk->SetIsRedstoneDirty(true);
continue; continue;
} }
} }
@ -139,7 +141,8 @@ void cIncrementalRedstoneSimulator::RedstoneAddBlock(int a_BlockX, int a_BlockY,
{ {
LOGD("cIncrementalRedstoneSimulator: Erased block @ {%i, %i, %i} from linked powered blocks list as it is no longer connected to a source", itr->a_BlockPos.x, itr->a_BlockPos.y, itr->a_BlockPos.z); LOGD("cIncrementalRedstoneSimulator: Erased block @ {%i, %i, %i} from linked powered blocks list as it is no longer connected to a source", itr->a_BlockPos.x, itr->a_BlockPos.y, itr->a_BlockPos.z);
itr = LinkedPoweredBlocks->erase(itr); itr = LinkedPoweredBlocks->erase(itr);
Chunk->SetIsRedstoneDirty(true); a_Chunk->SetIsRedstoneDirty(true);
OtherChunk->SetIsRedstoneDirty(true);
continue; continue;
} }
else if ( else if (
@ -153,7 +156,8 @@ void cIncrementalRedstoneSimulator::RedstoneAddBlock(int a_BlockX, int a_BlockY,
{ {
LOGD("cIncrementalRedstoneSimulator: Erased block @ {%i, %i, %i} from linked powered blocks list due to present/past metadata mismatch", itr->a_BlockPos.x, itr->a_BlockPos.y, itr->a_BlockPos.z); LOGD("cIncrementalRedstoneSimulator: Erased block @ {%i, %i, %i} from linked powered blocks list due to present/past metadata mismatch", itr->a_BlockPos.x, itr->a_BlockPos.y, itr->a_BlockPos.z);
itr = LinkedPoweredBlocks->erase(itr); itr = LinkedPoweredBlocks->erase(itr);
Chunk->SetIsRedstoneDirty(true); a_Chunk->SetIsRedstoneDirty(true);
OtherChunk->SetIsRedstoneDirty(true);
continue; continue;
} }
} }
@ -163,7 +167,8 @@ void cIncrementalRedstoneSimulator::RedstoneAddBlock(int a_BlockX, int a_BlockY,
{ {
LOGD("cIncrementalRedstoneSimulator: Erased block @ {%i, %i, %i} from linked powered blocks list as it is no longer powered through a valid middle block", itr->a_BlockPos.x, itr->a_BlockPos.y, itr->a_BlockPos.z); LOGD("cIncrementalRedstoneSimulator: Erased block @ {%i, %i, %i} from linked powered blocks list as it is no longer powered through a valid middle block", itr->a_BlockPos.x, itr->a_BlockPos.y, itr->a_BlockPos.z);
itr = LinkedPoweredBlocks->erase(itr); itr = LinkedPoweredBlocks->erase(itr);
Chunk->SetIsRedstoneDirty(true); a_Chunk->SetIsRedstoneDirty(true);
OtherChunk->SetIsRedstoneDirty(true);
continue; continue;
} }
} }
@ -343,6 +348,7 @@ void cIncrementalRedstoneSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int
case E_BLOCK_REDSTONE_REPEATER_ON: case E_BLOCK_REDSTONE_REPEATER_ON:
{ {
HandleRedstoneRepeater(dataitr->x, dataitr->y, dataitr->z, dataitr->Data); HandleRedstoneRepeater(dataitr->x, dataitr->y, dataitr->z, dataitr->Data);
break;
} }
case E_BLOCK_REDSTONE_TORCH_OFF: case E_BLOCK_REDSTONE_TORCH_OFF:
case E_BLOCK_REDSTONE_TORCH_ON: case E_BLOCK_REDSTONE_TORCH_ON:
@ -519,9 +525,12 @@ void cIncrementalRedstoneSimulator::HandleFenceGate(int a_RelBlockX, int a_RelBl
if (AreCoordsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ)) if (AreCoordsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ))
{ {
if (!AreCoordsSimulated(a_RelBlockX, a_RelBlockY, a_RelBlockZ, true)) if (!AreCoordsSimulated(a_RelBlockX, a_RelBlockY, a_RelBlockZ, true))
{
if ((MetaData & 0x4) == 0)
{ {
m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, MetaData | 0x4); m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, MetaData | 0x4);
m_Chunk->BroadcastSoundParticleEffect(1003, BlockX, a_RelBlockY, BlockZ, 0); m_Chunk->BroadcastSoundParticleEffect(1003, BlockX, a_RelBlockY, BlockZ, 0);
}
SetPlayerToggleableBlockAsSimulated(a_RelBlockX, a_RelBlockY, a_RelBlockZ, true); SetPlayerToggleableBlockAsSimulated(a_RelBlockX, a_RelBlockY, a_RelBlockZ, true);
} }
} }
@ -529,8 +538,11 @@ void cIncrementalRedstoneSimulator::HandleFenceGate(int a_RelBlockX, int a_RelBl
{ {
if (!AreCoordsSimulated(a_RelBlockX, a_RelBlockY, a_RelBlockZ, false)) if (!AreCoordsSimulated(a_RelBlockX, a_RelBlockY, a_RelBlockZ, false))
{ {
m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, MetaData & 0xFFFFFFFB); if ((MetaData & 0x4) != 0)
{
m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, MetaData & ~0x04);
m_Chunk->BroadcastSoundParticleEffect(1003, BlockX, a_RelBlockY, BlockZ, 0); m_Chunk->BroadcastSoundParticleEffect(1003, BlockX, a_RelBlockY, BlockZ, 0);
}
SetPlayerToggleableBlockAsSimulated(a_RelBlockX, a_RelBlockY, a_RelBlockZ, false); SetPlayerToggleableBlockAsSimulated(a_RelBlockX, a_RelBlockY, a_RelBlockZ, false);
} }
} }
@ -758,7 +770,7 @@ void cIncrementalRedstoneSimulator::HandleRedstoneRepeater(int a_RelBlockX, int
void cIncrementalRedstoneSimulator::HandleRedstoneRepeaterDelays() void cIncrementalRedstoneSimulator::HandleRedstoneRepeaterDelays()
{ {
for (RepeatersDelayList::iterator itr = m_RepeatersDelayList->begin(); itr != m_RepeatersDelayList->end(); itr++) for (RepeatersDelayList::iterator itr = m_RepeatersDelayList->begin(); itr != m_RepeatersDelayList->end();)
{ {
if (itr->a_ElapsedTicks >= itr->a_DelayTicks) // Has the elapsed ticks reached the target ticks? if (itr->a_ElapsedTicks >= itr->a_DelayTicks) // Has the elapsed ticks reached the target ticks?
@ -804,7 +816,7 @@ void cIncrementalRedstoneSimulator::HandleRedstoneRepeaterDelays()
{ {
m_Chunk->SetBlock(RelBlockX, RelBlockY, RelBlockZ, E_BLOCK_REDSTONE_REPEATER_OFF, Meta); m_Chunk->SetBlock(RelBlockX, RelBlockY, RelBlockZ, E_BLOCK_REDSTONE_REPEATER_OFF, Meta);
} }
m_RepeatersDelayList->erase(itr); itr = m_RepeatersDelayList->erase(itr);
} }
else else
{ {
@ -813,6 +825,7 @@ void cIncrementalRedstoneSimulator::HandleRedstoneRepeaterDelays()
// I am confounded to say why. Perhaps optimisation failure. // I am confounded to say why. Perhaps optimisation failure.
LOGD("Incremented a repeater @ {%i %i %i} | Elapsed ticks: %i | Target delay: %i", itr->a_RelBlockPos.x, itr->a_RelBlockPos.y, itr->a_RelBlockPos.z, itr->a_ElapsedTicks, itr->a_DelayTicks); LOGD("Incremented a repeater @ {%i %i %i} | Elapsed ticks: %i | Target delay: %i", itr->a_RelBlockPos.x, itr->a_RelBlockPos.y, itr->a_RelBlockPos.z, itr->a_ElapsedTicks, itr->a_DelayTicks);
itr->a_ElapsedTicks++; itr->a_ElapsedTicks++;
itr++;
} }
} }
} }
@ -1072,19 +1085,17 @@ void cIncrementalRedstoneSimulator::HandleNoteBlock(int a_RelBlockX, int a_RelBl
void cIncrementalRedstoneSimulator::HandleDaylightSensor(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ) void cIncrementalRedstoneSimulator::HandleDaylightSensor(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ)
{ {
int a_ChunkX, a_ChunkZ; int BlockX = (m_Chunk->GetPosX() * cChunkDef::Width) + a_RelBlockX, BlockZ = (m_Chunk->GetPosZ() * cChunkDef::Width) + a_RelBlockZ;
cChunkDef::BlockToChunk(a_RelBlockX, a_RelBlockZ, a_ChunkX, a_ChunkZ); int ChunkX, ChunkZ;
cChunkDef::BlockToChunk(BlockX, BlockZ, ChunkX, ChunkZ);
if (!m_World.IsChunkLighted(a_ChunkX, a_ChunkZ)) if (!m_World.IsChunkLighted(ChunkX, ChunkZ))
{ {
m_World.QueueLightChunk(a_ChunkX, a_ChunkZ); m_World.QueueLightChunk(ChunkX, ChunkZ);
} }
else else
{ {
int BlockX = (m_Chunk->GetPosX() * cChunkDef::Width) + a_RelBlockX; if (m_Chunk->GetTimeAlteredLight(m_World.GetBlockSkyLight(BlockX, a_RelBlockY + 1, BlockZ)) > 8)
int BlockZ = (m_Chunk->GetPosZ() * cChunkDef::Width) + a_RelBlockZ;
NIBBLETYPE SkyLight = m_Chunk->GetTimeAlteredLight(m_World.GetBlockSkyLight(BlockX, a_RelBlockY + 1, BlockZ));
if (SkyLight > 8)
{ {
SetAllDirsAsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ); SetAllDirsAsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ);
} }

View File

@ -14,7 +14,9 @@ cVoronoiMap::cVoronoiMap(int a_Seed, int a_CellSize) :
m_Noise1(a_Seed + 1), m_Noise1(a_Seed + 1),
m_Noise2(a_Seed + 2), m_Noise2(a_Seed + 2),
m_Noise3(a_Seed + 3), m_Noise3(a_Seed + 3),
m_CellSize(a_CellSize) m_CellSize(a_CellSize),
m_CurrentCellX(9999999), // Cell coords that are definitely out of the range for normal generator, so that the first query will overwrite them
m_CurrentCellZ(9999999)
{ {
} }

View File

@ -345,6 +345,7 @@ void cNBTChunkSerializer::AddBasicEntity(cEntity * a_Entity, const AString & a_C
m_Writer.AddDouble("", a_Entity->GetYaw()); m_Writer.AddDouble("", a_Entity->GetYaw());
m_Writer.AddDouble("", a_Entity->GetPitch()); m_Writer.AddDouble("", a_Entity->GetPitch());
m_Writer.EndList(); m_Writer.EndList();
m_Writer.AddShort("Health", a_Entity->GetHealth());
} }
@ -576,7 +577,6 @@ void cNBTChunkSerializer::AddPickupEntity(cPickup * a_Pickup)
m_Writer.BeginCompound(""); m_Writer.BeginCompound("");
AddBasicEntity(a_Pickup, "Item"); AddBasicEntity(a_Pickup, "Item");
AddItem(a_Pickup->GetItem(), -1, "Item"); AddItem(a_Pickup->GetItem(), -1, "Item");
m_Writer.AddShort("Health", (Int16)(unsigned char)a_Pickup->GetHealth());
m_Writer.AddShort("Age", (Int16)a_Pickup->GetAge()); m_Writer.AddShort("Age", (Int16)a_Pickup->GetAge());
m_Writer.EndCompound(); m_Writer.EndCompound();
} }
@ -679,7 +679,6 @@ void cNBTChunkSerializer::AddExpOrbEntity(cExpOrb * a_ExpOrb)
{ {
m_Writer.BeginCompound(""); m_Writer.BeginCompound("");
AddBasicEntity(a_ExpOrb, "XPOrb"); 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("Age", (Int16)a_ExpOrb->GetAge());
m_Writer.AddShort("Value", (Int16)a_ExpOrb->GetReward()); m_Writer.AddShort("Value", (Int16)a_ExpOrb->GetReward());
m_Writer.EndCompound(); m_Writer.EndCompound();

View File

@ -1462,13 +1462,6 @@ void cWSSAnvil::LoadPickupFromNBT(cEntityList & a_Entities, const cParsedNBT & a
return; return;
} }
// Load health:
int Health = a_NBT.FindChildByName(a_TagIdx, "Health");
if (Health > 0)
{
Pickup->SetHealth((int) (a_NBT.GetShort(Health) & 0xFF));
}
// Load age: // Load age:
int Age = a_NBT.FindChildByName(a_TagIdx, "Age"); int Age = a_NBT.FindChildByName(a_TagIdx, "Age");
if (Age > 0) if (Age > 0)
@ -1513,13 +1506,6 @@ void cWSSAnvil::LoadExpOrbFromNBT(cEntityList & a_Entities, const cParsedNBT & a
return; return;
} }
// Load Health:
int Health = a_NBT.FindChildByName(a_TagIdx, "Health");
if (Health > 0)
{
ExpOrb->SetHealth((int) (a_NBT.GetShort(Health) & 0xFF));
}
// Load Age: // Load Age:
int Age = a_NBT.FindChildByName(a_TagIdx, "Age"); int Age = a_NBT.FindChildByName(a_TagIdx, "Age");
if (Age > 0) if (Age > 0)
@ -2438,6 +2424,13 @@ bool cWSSAnvil::LoadEntityBaseFromNBT(cEntity & a_Entity, const cParsedNBT & a_N
a_Entity.SetYaw(Rotation[0]); a_Entity.SetYaw(Rotation[0]);
a_Entity.SetRoll(Rotation[1]); a_Entity.SetRoll(Rotation[1]);
// Load health:
int Health = a_NBT.FindChildByName(a_TagIdx, "Health");
if (Health > 0)
{
a_Entity.SetHealth(a_NBT.GetShort(Health));
}
return true; return true;
} }