Merge branch 'master' of https://github.com/mc-server/MCServer into portals
This commit is contained in:
commit
bd5df3d3b9
@ -1,6 +1,6 @@
|
||||
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)
|
||||
derouinw
|
||||
Diusrex
|
||||
@ -27,6 +27,6 @@ tonibm19
|
||||
UltraCoderRU
|
||||
worktycho
|
||||
xoft
|
||||
Yeeeeezus - Donated AlchemistVillage prefabs
|
||||
Yeeeeezus (Donated AlchemistVillage prefabs)
|
||||
|
||||
Please add yourself to this list if you contribute to MCServer.
|
||||
|
@ -523,13 +523,16 @@ end
|
||||
|
||||
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." },
|
||||
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." },
|
||||
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" },
|
||||
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." },
|
||||
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" },
|
||||
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)." },
|
||||
|
@ -346,7 +346,7 @@ end
|
||||
|
||||
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
|
||||
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
|
||||
Player:SendMessage(cChatColor.LightGray .. "Block {" .. BlockX .. ", " .. BlockY .. ", " .. BlockZ .. "}: air:" .. Meta);
|
||||
@ -356,7 +356,7 @@ function OnUsingBlazeRod(Player, BlockX, BlockY, BlockZ, BlockFace, CursorX, Cur
|
||||
end
|
||||
|
||||
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
|
||||
Player:SendMessage(cChatColor.LightGray .. "Block {" .. X .. ", " .. Y .. ", " .. Z .. "}: air:" .. Meta);
|
||||
else
|
||||
|
@ -122,6 +122,13 @@ void cChestEntity::UsedBy(cPlayer * a_Player)
|
||||
|
||||
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:
|
||||
class cOpenDouble :
|
||||
public cChestCallback
|
||||
@ -135,6 +142,12 @@ void cChestEntity::OpenNewWindow(void)
|
||||
|
||||
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:
|
||||
cChestEntity * Primary = a_Chest;
|
||||
cChestEntity * Secondary = m_ThisChest;
|
||||
|
@ -294,23 +294,24 @@ bool cHopperEntity::MoveItemsOut(cChunk & a_Chunk, Int64 a_CurrentTick)
|
||||
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);
|
||||
if (!GetOutputBlockPos(Meta, bx, by, bz))
|
||||
if (!GetOutputBlockPos(Meta, OutX, OutY, OutZ))
|
||||
{
|
||||
// Not attached to another container
|
||||
return false;
|
||||
}
|
||||
if (by < 0)
|
||||
if (OutY < 0)
|
||||
{
|
||||
// Cannot output below the zero-th block level
|
||||
return false;
|
||||
}
|
||||
|
||||
// Convert coords to relative:
|
||||
int rx = bx - a_Chunk.GetPosX() * cChunkDef::Width;
|
||||
int rz = bz - a_Chunk.GetPosZ() * cChunkDef::Width;
|
||||
cChunk * DestChunk = a_Chunk.GetRelNeighborChunkAdjustCoords(rx, rz);
|
||||
int OutRelX = OutX - a_Chunk.GetPosX() * cChunkDef::Width;
|
||||
int OutRelZ = OutZ - a_Chunk.GetPosZ() * cChunkDef::Width;
|
||||
cChunk * DestChunk = a_Chunk.GetRelNeighborChunkAdjustCoords(OutRelX, OutRelZ);
|
||||
if (DestChunk == NULL)
|
||||
{
|
||||
// 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:
|
||||
bool res = false;
|
||||
switch (DestChunk->GetBlock(rx, by, rz))
|
||||
switch (DestChunk->GetBlock(OutRelX, OutY, OutRelZ))
|
||||
{
|
||||
case E_BLOCK_CHEST:
|
||||
{
|
||||
// Chests have special handling because of double-chests
|
||||
res = MoveItemsToChest(*DestChunk, bx, by, bz);
|
||||
res = MoveItemsToChest(*DestChunk, OutX, OutY, OutZ);
|
||||
break;
|
||||
}
|
||||
case E_BLOCK_LIT_FURNACE:
|
||||
case E_BLOCK_FURNACE:
|
||||
{
|
||||
// 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;
|
||||
}
|
||||
case E_BLOCK_DISPENSER:
|
||||
case E_BLOCK_DROPPER:
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -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.
|
||||
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
|
||||
return true;
|
||||
@ -389,9 +402,17 @@ bool cHopperEntity::MoveItemsFromChest(cChunk & a_Chunk)
|
||||
{
|
||||
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)
|
||||
{
|
||||
return true;
|
||||
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 false;
|
||||
}
|
||||
@ -408,7 +429,11 @@ bool cHopperEntity::MoveItemsFromChest(cChunk & a_Chunk)
|
||||
bool cHopperEntity::MoveItemsFromFurnace(cChunk & a_Chunk)
|
||||
{
|
||||
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:
|
||||
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)
|
||||
{
|
||||
// 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;
|
||||
}
|
||||
@ -534,19 +565,27 @@ bool cHopperEntity::MoveItemsToChest(cChunk & a_Chunk, int a_BlockX, int a_Block
|
||||
{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++)
|
||||
{
|
||||
int x = m_RelX + Coords[i].x;
|
||||
int z = m_RelZ + Coords[i].z;
|
||||
int x = RelX + Coords[i].x;
|
||||
int z = RelZ + Coords[i].z;
|
||||
cChunk * Neighbor = a_Chunk.GetRelNeighborChunkAdjustCoords(x, z);
|
||||
if (
|
||||
(Neighbor == NULL) ||
|
||||
(Neighbor->GetBlock(x, m_PosY + 1, z) != E_BLOCK_CHEST)
|
||||
(Neighbor->GetBlock(x, a_BlockY, z) != E_BLOCK_CHEST)
|
||||
)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
|
||||
cBlockInfo cBlockInfo::ms_Info[256];
|
||||
static bool g_IsBlockInfoInitialized = false;
|
||||
|
||||
|
||||
|
||||
@ -43,6 +44,11 @@ cBlockInfo::~cBlockInfo()
|
||||
|
||||
cBlockInfo & cBlockInfo::Get(BLOCKTYPE a_Type)
|
||||
{
|
||||
if (!g_IsBlockInfoInitialized)
|
||||
{
|
||||
cBlockInfo::Initialize();
|
||||
g_IsBlockInfoInitialized = true;
|
||||
}
|
||||
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;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
ChangeDoor(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ);
|
||||
a_Player->GetWorld()->BroadcastSoundParticleEffect(1003, a_BlockX, a_BlockY, a_BlockZ, 0, a_Player->GetClientHandle());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -45,6 +45,7 @@ public:
|
||||
// Standing aside - use last direction
|
||||
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());
|
||||
}
|
||||
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
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_STAIRS: return new cBlockStairsHandler (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_GLOWING: return new cBlockOreHandler (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_TNT: return new cBlockTNTHandler (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_WOODEN_BUTTON: return new cBlockButtonHandler (a_BlockType);
|
||||
case E_BLOCK_WOODEN_DOOR: return new cBlockDoorHandler (a_BlockType);
|
||||
|
@ -7,12 +7,13 @@
|
||||
|
||||
|
||||
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:
|
||||
cBlockLeverHandler(BLOCKTYPE a_BlockType)
|
||||
: cMetaRotator<cBlockHandler, 0x07, 0x04, 0x02, 0x03, 0x01, false>(a_BlockType)
|
||||
cBlockLeverHandler(BLOCKTYPE a_BlockType) :
|
||||
super(a_BlockType)
|
||||
{
|
||||
}
|
||||
|
||||
@ -132,7 +133,7 @@ public:
|
||||
case 0x05: return 0x06; // Ground rotation
|
||||
case 0x06: return 0x05;
|
||||
|
||||
default: return super::MetaRotateCCW(a_Meta); // Wall Rotation
|
||||
default: return super::MetaRotateCW(a_Meta); // Wall Rotation
|
||||
}
|
||||
}
|
||||
} ;
|
||||
|
@ -75,13 +75,13 @@ public:
|
||||
|
||||
virtual NIBBLETYPE MetaRotateCW(NIBBLETYPE a_Meta) override
|
||||
{
|
||||
return (++a_Meta) & 0x0F;
|
||||
return (a_Meta + 4) & 0x0f;
|
||||
}
|
||||
|
||||
|
||||
virtual NIBBLETYPE MetaRotateCCW(NIBBLETYPE a_Meta) override
|
||||
{
|
||||
return (--a_Meta) & 0x0F;
|
||||
return (a_Meta + 12) & 0x0f;
|
||||
}
|
||||
|
||||
virtual NIBBLETYPE MetaMirrorXY(NIBBLETYPE a_Meta) override
|
||||
@ -90,7 +90,7 @@ public:
|
||||
|
||||
// There are 16 meta values which correspond to different directions.
|
||||
// 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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -124,6 +124,12 @@ public:
|
||||
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!");
|
||||
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;
|
||||
}
|
||||
} ;
|
||||
|
||||
|
||||
|
@ -1616,6 +1616,12 @@ void cChunk::AddBlockEntity(cBlockEntity * a_BlockEntity)
|
||||
|
||||
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)
|
||||
{
|
||||
if (
|
||||
|
@ -231,6 +231,9 @@ AString cClientHandle::FormatMessageType(bool ShouldAppendChatPrefixes, eMessage
|
||||
|
||||
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:
|
||||
// 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)
|
||||
{
|
||||
if (m_State >= csAuthenticating) // Don't log pings
|
||||
|
@ -63,7 +63,7 @@ public:
|
||||
|
||||
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
|
||||
void SetUUID(const AString & a_UUID) { m_UUID = a_UUID; }
|
||||
@ -76,9 +76,16 @@ public:
|
||||
|
||||
/** 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. */
|
||||
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
|
||||
|
||||
/** 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. **/
|
||||
static AString FormatMessageType(bool ShouldAppendChatPrefixes, eMessageType a_ChatPrefix, const AString & a_AdditionalData);
|
||||
|
||||
|
@ -211,6 +211,17 @@ void cPrefab::Draw(cChunkDesc & a_Dest, const Vector3i & a_Placement, int a_NumR
|
||||
int ChunkStartZ = a_Dest.GetChunkZ() * cChunkDef::Width;
|
||||
Placement.Move(-ChunkStartX, 0, -ChunkStartZ);
|
||||
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);
|
||||
|
||||
// If requested, draw the floor (from the bottom of the prefab down to the nearest non-air)
|
||||
|
@ -59,21 +59,20 @@ void cIncrementalRedstoneSimulator::RedstoneAddBlock(int a_BlockX, int a_BlockY,
|
||||
int RelZ = 0;
|
||||
BLOCKTYPE Block;
|
||||
NIBBLETYPE Meta;
|
||||
cChunk * Chunk;
|
||||
cChunk * OtherChunk = a_Chunk;
|
||||
|
||||
if (a_OtherChunk != NULL)
|
||||
{
|
||||
RelX = a_BlockX - a_OtherChunk->GetPosX() * cChunkDef::Width;
|
||||
RelZ = a_BlockZ - a_OtherChunk->GetPosZ() * cChunkDef::Width;
|
||||
a_OtherChunk->GetBlockTypeMeta(RelX, a_BlockY, RelZ, Block, Meta);
|
||||
Chunk = a_OtherChunk;
|
||||
OtherChunk = a_OtherChunk;
|
||||
}
|
||||
else
|
||||
{
|
||||
RelX = a_BlockX - a_Chunk->GetPosX() * cChunkDef::Width;
|
||||
RelZ = a_BlockZ - a_Chunk->GetPosZ() * cChunkDef::Width;
|
||||
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
|
||||
@ -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);
|
||||
itr = PoweredBlocks->erase(itr);
|
||||
Chunk->SetIsRedstoneDirty(true);
|
||||
a_Chunk->SetIsRedstoneDirty(true);
|
||||
OtherChunk->SetIsRedstoneDirty(true);
|
||||
continue;
|
||||
}
|
||||
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);
|
||||
itr = PoweredBlocks->erase(itr);
|
||||
Chunk->SetIsRedstoneDirty(true);
|
||||
a_Chunk->SetIsRedstoneDirty(true);
|
||||
OtherChunk->SetIsRedstoneDirty(true);
|
||||
continue;
|
||||
}
|
||||
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
|
||||
{
|
||||
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);
|
||||
Chunk->SetIsRedstoneDirty(true);
|
||||
a_Chunk->SetIsRedstoneDirty(true);
|
||||
OtherChunk->SetIsRedstoneDirty(true);
|
||||
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);
|
||||
itr = LinkedPoweredBlocks->erase(itr);
|
||||
Chunk->SetIsRedstoneDirty(true);
|
||||
a_Chunk->SetIsRedstoneDirty(true);
|
||||
OtherChunk->SetIsRedstoneDirty(true);
|
||||
continue;
|
||||
}
|
||||
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);
|
||||
itr = LinkedPoweredBlocks->erase(itr);
|
||||
Chunk->SetIsRedstoneDirty(true);
|
||||
a_Chunk->SetIsRedstoneDirty(true);
|
||||
OtherChunk->SetIsRedstoneDirty(true);
|
||||
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);
|
||||
itr = LinkedPoweredBlocks->erase(itr);
|
||||
Chunk->SetIsRedstoneDirty(true);
|
||||
a_Chunk->SetIsRedstoneDirty(true);
|
||||
OtherChunk->SetIsRedstoneDirty(true);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@ -343,6 +348,7 @@ void cIncrementalRedstoneSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int
|
||||
case E_BLOCK_REDSTONE_REPEATER_ON:
|
||||
{
|
||||
HandleRedstoneRepeater(dataitr->x, dataitr->y, dataitr->z, dataitr->Data);
|
||||
break;
|
||||
}
|
||||
case E_BLOCK_REDSTONE_TORCH_OFF:
|
||||
case E_BLOCK_REDSTONE_TORCH_ON:
|
||||
@ -520,8 +526,11 @@ void cIncrementalRedstoneSimulator::HandleFenceGate(int a_RelBlockX, int a_RelBl
|
||||
{
|
||||
if (!AreCoordsSimulated(a_RelBlockX, a_RelBlockY, a_RelBlockZ, true))
|
||||
{
|
||||
m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, MetaData | 0x4);
|
||||
m_Chunk->BroadcastSoundParticleEffect(1003, BlockX, a_RelBlockY, BlockZ, 0);
|
||||
if ((MetaData & 0x4) == 0)
|
||||
{
|
||||
m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, MetaData | 0x4);
|
||||
m_Chunk->BroadcastSoundParticleEffect(1003, BlockX, a_RelBlockY, BlockZ, 0);
|
||||
}
|
||||
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))
|
||||
{
|
||||
m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, MetaData & 0xFFFFFFFB);
|
||||
m_Chunk->BroadcastSoundParticleEffect(1003, BlockX, a_RelBlockY, BlockZ, 0);
|
||||
if ((MetaData & 0x4) != 0)
|
||||
{
|
||||
m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, MetaData & ~0x04);
|
||||
m_Chunk->BroadcastSoundParticleEffect(1003, BlockX, a_RelBlockY, BlockZ, 0);
|
||||
}
|
||||
SetPlayerToggleableBlockAsSimulated(a_RelBlockX, a_RelBlockY, a_RelBlockZ, false);
|
||||
}
|
||||
}
|
||||
@ -758,7 +770,7 @@ void cIncrementalRedstoneSimulator::HandleRedstoneRepeater(int a_RelBlockX, int
|
||||
|
||||
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?
|
||||
@ -804,7 +816,7 @@ void cIncrementalRedstoneSimulator::HandleRedstoneRepeaterDelays()
|
||||
{
|
||||
m_Chunk->SetBlock(RelBlockX, RelBlockY, RelBlockZ, E_BLOCK_REDSTONE_REPEATER_OFF, Meta);
|
||||
}
|
||||
m_RepeatersDelayList->erase(itr);
|
||||
itr = m_RepeatersDelayList->erase(itr);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -813,6 +825,7 @@ void cIncrementalRedstoneSimulator::HandleRedstoneRepeaterDelays()
|
||||
// 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);
|
||||
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)
|
||||
{
|
||||
int a_ChunkX, a_ChunkZ;
|
||||
cChunkDef::BlockToChunk(a_RelBlockX, a_RelBlockZ, a_ChunkX, a_ChunkZ);
|
||||
int BlockX = (m_Chunk->GetPosX() * cChunkDef::Width) + a_RelBlockX, BlockZ = (m_Chunk->GetPosZ() * cChunkDef::Width) + a_RelBlockZ;
|
||||
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
|
||||
{
|
||||
int BlockX = (m_Chunk->GetPosX() * cChunkDef::Width) + a_RelBlockX;
|
||||
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)
|
||||
if (m_Chunk->GetTimeAlteredLight(m_World.GetBlockSkyLight(BlockX, a_RelBlockY + 1, BlockZ)) > 8)
|
||||
{
|
||||
SetAllDirsAsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ);
|
||||
}
|
||||
|
@ -14,7 +14,9 @@ cVoronoiMap::cVoronoiMap(int a_Seed, int a_CellSize) :
|
||||
m_Noise1(a_Seed + 1),
|
||||
m_Noise2(a_Seed + 2),
|
||||
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)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -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->GetPitch());
|
||||
m_Writer.EndList();
|
||||
m_Writer.AddShort("Health", a_Entity->GetHealth());
|
||||
}
|
||||
|
||||
|
||||
@ -576,7 +577,6 @@ void cNBTChunkSerializer::AddPickupEntity(cPickup * a_Pickup)
|
||||
m_Writer.BeginCompound("");
|
||||
AddBasicEntity(a_Pickup, "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.EndCompound();
|
||||
}
|
||||
@ -679,7 +679,6 @@ 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();
|
||||
|
@ -1461,13 +1461,6 @@ void cWSSAnvil::LoadPickupFromNBT(cEntityList & a_Entities, const cParsedNBT & a
|
||||
{
|
||||
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");
|
||||
@ -1513,13 +1506,6 @@ void cWSSAnvil::LoadExpOrbFromNBT(cEntityList & a_Entities, const cParsedNBT & a
|
||||
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)
|
||||
@ -2437,6 +2423,13 @@ bool cWSSAnvil::LoadEntityBaseFromNBT(cEntity & a_Entity, const cParsedNBT & a_N
|
||||
}
|
||||
a_Entity.SetYaw(Rotation[0]);
|
||||
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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user