Fix sending incorrect date values on world change
Yak shave: make more things use cTickTime. Fix a couple of incorrect modulo-on-millisecond-value by making them use WorldTickAge.
This commit is contained in:
parent
a2a2226179
commit
4cd49d7eca
@ -9138,24 +9138,6 @@ a_Player:OpenWindow(Window);
|
|||||||
},
|
},
|
||||||
Notes = "Returns the relative walk speed of this mob. Standard is 1.0",
|
Notes = "Returns the relative walk speed of this mob. Standard is 1.0",
|
||||||
},
|
},
|
||||||
GetSpawnDelay =
|
|
||||||
{
|
|
||||||
IsStatic = true,
|
|
||||||
Params =
|
|
||||||
{
|
|
||||||
{
|
|
||||||
Name = "MobFamily",
|
|
||||||
Type = "cMonster#eFamily",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Returns =
|
|
||||||
{
|
|
||||||
{
|
|
||||||
Type = "number",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Notes = "Returns the spawn delay - the number of game ticks between spawn attempts - for the specified mob family.",
|
|
||||||
},
|
|
||||||
HasCustomName =
|
HasCustomName =
|
||||||
{
|
{
|
||||||
Returns =
|
Returns =
|
||||||
@ -11392,10 +11374,6 @@ a_Player:OpenWindow(Window);
|
|||||||
},
|
},
|
||||||
Constants =
|
Constants =
|
||||||
{
|
{
|
||||||
EATING_TICKS =
|
|
||||||
{
|
|
||||||
Notes = "Number of ticks required for consuming an item.",
|
|
||||||
},
|
|
||||||
MAX_FOOD_LEVEL =
|
MAX_FOOD_LEVEL =
|
||||||
{
|
{
|
||||||
Notes = "The maximum food level value. When the food level is at this value, the player cannot eat.",
|
Notes = "The maximum food level value. When the food level is at this value, the player cannot eat.",
|
||||||
|
@ -1076,10 +1076,6 @@ World:ForEachChestInChunk(Player:GetChunkX(), Player:GetChunkZ(),
|
|||||||
{
|
{
|
||||||
Notes = "Width (X) of the internal {{cItemGrid}} representing the hopper contents.",
|
Notes = "Width (X) of the internal {{cItemGrid}} representing the hopper contents.",
|
||||||
},
|
},
|
||||||
TICKS_PER_TRANSFER =
|
|
||||||
{
|
|
||||||
Notes = "Number of ticks between when the hopper transfers items.",
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
Inherits = "cBlockEntityWithItems",
|
Inherits = "cBlockEntityWithItems",
|
||||||
},
|
},
|
||||||
|
@ -2338,6 +2338,36 @@ static int tolua_cClientHandle_SendPluginMessage(lua_State * L)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static int tolua_cClientHandle_SendTimeUpdate(lua_State * L)
|
||||||
|
{
|
||||||
|
cLuaState S(L);
|
||||||
|
if (
|
||||||
|
!S.CheckParamSelf("cClientHandle") ||
|
||||||
|
!S.CheckParamNumber(2, 3) ||
|
||||||
|
!S.CheckParamBool(4) ||
|
||||||
|
!S.CheckParamEnd(5)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
cClientHandle * Client;
|
||||||
|
cTickTimeLong::rep WorldAge, WorldDate;
|
||||||
|
bool DoDayLightCycle;
|
||||||
|
S.GetStackValues(1, Client, WorldAge, WorldDate, DoDayLightCycle);
|
||||||
|
if (Client == nullptr)
|
||||||
|
{
|
||||||
|
return S.ApiParamError("Invalid 'self'");
|
||||||
|
}
|
||||||
|
|
||||||
|
Client->SendTimeUpdate(cTickTimeLong(WorldAge), cTickTimeLong(WorldDate), DoDayLightCycle);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int tolua_cClientHandle_GetForgeMods(lua_State * L)
|
static int tolua_cClientHandle_GetForgeMods(lua_State * L)
|
||||||
{
|
{
|
||||||
cLuaState S(L);
|
cLuaState S(L);
|
||||||
@ -4361,6 +4391,7 @@ void cManualBindings::Bind(lua_State * tolua_S)
|
|||||||
|
|
||||||
tolua_function(tolua_S, "GetForgeMods", tolua_cClientHandle_GetForgeMods);
|
tolua_function(tolua_S, "GetForgeMods", tolua_cClientHandle_GetForgeMods);
|
||||||
tolua_function(tolua_S, "SendPluginMessage", tolua_cClientHandle_SendPluginMessage);
|
tolua_function(tolua_S, "SendPluginMessage", tolua_cClientHandle_SendPluginMessage);
|
||||||
|
tolua_function(tolua_S, "SendTimeUpdate", tolua_cClientHandle_SendTimeUpdate);
|
||||||
tolua_function(tolua_S, "GetUUID", tolua_cClientHandle_GetUUID);
|
tolua_function(tolua_S, "GetUUID", tolua_cClientHandle_GetUUID);
|
||||||
tolua_function(tolua_S, "GenerateOfflineUUID", tolua_cClientHandle_GenerateOfflineUUID);
|
tolua_function(tolua_S, "GenerateOfflineUUID", tolua_cClientHandle_GenerateOfflineUUID);
|
||||||
tolua_function(tolua_S, "IsUUIDOnline", tolua_cClientHandle_IsUUIDOnline);
|
tolua_function(tolua_S, "IsUUIDOnline", tolua_cClientHandle_IsUUIDOnline);
|
||||||
|
@ -1266,6 +1266,70 @@ static int tolua_cWorld_GetSignLines(lua_State * tolua_S)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static int tolua_cWorld_GetTimeOfDay(lua_State * tolua_S)
|
||||||
|
{
|
||||||
|
// Check params:
|
||||||
|
cLuaState L(tolua_S);
|
||||||
|
if (
|
||||||
|
!L.CheckParamSelf("cWorld") ||
|
||||||
|
!L.CheckParamEnd(2)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get params:
|
||||||
|
cWorld * Self = nullptr;
|
||||||
|
L.GetStackValues(1, Self);
|
||||||
|
if (Self == nullptr)
|
||||||
|
{
|
||||||
|
return L.ApiParamError("Invalid 'self'");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call the function:
|
||||||
|
const auto Time = Self->GetTimeOfDay();
|
||||||
|
|
||||||
|
// Push the returned value:
|
||||||
|
L.Push(Time.count());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static int tolua_cWorld_GetWorldAge(lua_State * tolua_S)
|
||||||
|
{
|
||||||
|
// Check params:
|
||||||
|
cLuaState L(tolua_S);
|
||||||
|
if (
|
||||||
|
!L.CheckParamSelf("cWorld") ||
|
||||||
|
!L.CheckParamEnd(2)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get params:
|
||||||
|
cWorld * Self = nullptr;
|
||||||
|
L.GetStackValues(1, Self);
|
||||||
|
if (Self == nullptr)
|
||||||
|
{
|
||||||
|
return L.ApiParamError("Invalid 'self'");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call the function:
|
||||||
|
const auto Time = Self->GetWorldAge();
|
||||||
|
|
||||||
|
// Push the returned value:
|
||||||
|
L.Push(static_cast<lua_Number>(Time.count()));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int tolua_cWorld_PrepareChunk(lua_State * tolua_S)
|
static int tolua_cWorld_PrepareChunk(lua_State * tolua_S)
|
||||||
{
|
{
|
||||||
/* Function signature:
|
/* Function signature:
|
||||||
@ -1459,6 +1523,37 @@ static int tolua_cWorld_SetSignLines(lua_State * tolua_S)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static int tolua_cWorld_SetTimeOfDay(lua_State * tolua_S)
|
||||||
|
{
|
||||||
|
// Check params:
|
||||||
|
cLuaState L(tolua_S);
|
||||||
|
if (
|
||||||
|
!L.CheckParamSelf("cWorld") ||
|
||||||
|
!L.CheckParamNumber(2) ||
|
||||||
|
!L.CheckParamEnd(3)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get params:
|
||||||
|
cWorld * Self = nullptr;
|
||||||
|
cTickTime::rep Time;
|
||||||
|
L.GetStackValues(1, Self, Time);
|
||||||
|
if (Self == nullptr)
|
||||||
|
{
|
||||||
|
return L.ApiParamError("Invalid 'self'");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call the function:
|
||||||
|
Self->SetTimeOfDay(cTickTime(Time));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int tolua_cWorld_ScheduleTask(lua_State * tolua_S)
|
static int tolua_cWorld_ScheduleTask(lua_State * tolua_S)
|
||||||
{
|
{
|
||||||
// Function signature:
|
// Function signature:
|
||||||
@ -1490,7 +1585,7 @@ static int tolua_cWorld_ScheduleTask(lua_State * tolua_S)
|
|||||||
return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Could not store the callback parameter");
|
return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Could not store the callback parameter");
|
||||||
}
|
}
|
||||||
|
|
||||||
World->ScheduleTask(NumTicks, [Task](cWorld & a_World)
|
World->ScheduleTask(cTickTime(NumTicks), [Task](cWorld & a_World)
|
||||||
{
|
{
|
||||||
Task->Call(&a_World);
|
Task->Call(&a_World);
|
||||||
}
|
}
|
||||||
@ -1624,17 +1719,16 @@ void cManualBindings::BindWorld(lua_State * tolua_S)
|
|||||||
tolua_function(tolua_S, "GetBlockSkyLight", tolua_cWorld_GetBlockSkyLight);
|
tolua_function(tolua_S, "GetBlockSkyLight", tolua_cWorld_GetBlockSkyLight);
|
||||||
tolua_function(tolua_S, "GetBlockTypeMeta", tolua_cWorld_GetBlockTypeMeta);
|
tolua_function(tolua_S, "GetBlockTypeMeta", tolua_cWorld_GetBlockTypeMeta);
|
||||||
tolua_function(tolua_S, "GetSignLines", tolua_cWorld_GetSignLines);
|
tolua_function(tolua_S, "GetSignLines", tolua_cWorld_GetSignLines);
|
||||||
|
tolua_function(tolua_S, "GetTimeOfDay", tolua_cWorld_GetTimeOfDay);
|
||||||
|
tolua_function(tolua_S, "GetWorldAge", tolua_cWorld_GetWorldAge);
|
||||||
tolua_function(tolua_S, "PrepareChunk", tolua_cWorld_PrepareChunk);
|
tolua_function(tolua_S, "PrepareChunk", tolua_cWorld_PrepareChunk);
|
||||||
tolua_function(tolua_S, "QueueTask", tolua_cWorld_QueueTask);
|
tolua_function(tolua_S, "QueueTask", tolua_cWorld_QueueTask);
|
||||||
tolua_function(tolua_S, "ScheduleTask", tolua_cWorld_ScheduleTask);
|
tolua_function(tolua_S, "ScheduleTask", tolua_cWorld_ScheduleTask);
|
||||||
tolua_function(tolua_S, "SetBlock", tolua_cWorld_SetBlock);
|
tolua_function(tolua_S, "SetBlock", tolua_cWorld_SetBlock);
|
||||||
tolua_function(tolua_S, "SetSignLines", tolua_cWorld_SetSignLines);
|
tolua_function(tolua_S, "SetSignLines", tolua_cWorld_SetSignLines);
|
||||||
|
tolua_function(tolua_S, "SetTimeOfDay", tolua_cWorld_SetTimeOfDay);
|
||||||
tolua_function(tolua_S, "SpawnSplitExperienceOrbs", tolua_cWorld_SpawnSplitExperienceOrbs);
|
tolua_function(tolua_S, "SpawnSplitExperienceOrbs", tolua_cWorld_SpawnSplitExperienceOrbs);
|
||||||
tolua_function(tolua_S, "TryGetHeight", tolua_cWorld_TryGetHeight);
|
tolua_function(tolua_S, "TryGetHeight", tolua_cWorld_TryGetHeight);
|
||||||
tolua_endmodule(tolua_S);
|
tolua_endmodule(tolua_S);
|
||||||
tolua_endmodule(tolua_S);
|
tolua_endmodule(tolua_S);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -541,7 +541,7 @@ bool cPluginManager::CallHookExecuteCommand(cPlayer * a_Player, const AStringVec
|
|||||||
if (world != nullptr)
|
if (world != nullptr)
|
||||||
{
|
{
|
||||||
worldName = world->GetName();
|
worldName = world->GetName();
|
||||||
worldAge = world->GetWorldAge();
|
worldAge = world->GetWorldAge().count();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -296,8 +296,10 @@ void cBeaconEntity::SendTo(cClientHandle & a_Client)
|
|||||||
|
|
||||||
bool cBeaconEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
|
bool cBeaconEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
|
||||||
{
|
{
|
||||||
// Update the beacon every 4 seconds
|
using namespace std::chrono_literals;
|
||||||
if ((GetWorld()->GetWorldAge() % 80) == 0)
|
|
||||||
|
// Update the beacon every 4 seconds:
|
||||||
|
if ((GetWorld()->GetWorldTickAge() % 4s) == 0s)
|
||||||
{
|
{
|
||||||
UpdateBeacon();
|
UpdateBeacon();
|
||||||
GiveEffects();
|
GiveEffects();
|
||||||
|
@ -288,8 +288,8 @@ void cBrewingstandEntity::OnSlotChanged(cItemGrid * a_ItemGrid, int a_SlotNum)
|
|||||||
|
|
||||||
void cBrewingstandEntity::UpdateProgressBars(bool a_ForceUpdate)
|
void cBrewingstandEntity::UpdateProgressBars(bool a_ForceUpdate)
|
||||||
{
|
{
|
||||||
/** Sending an update every 3th tick, using a higher value lets look the progressbar ugly */
|
// Send an update every 3rd tick, using a higher value makes the progressbar look ugly:
|
||||||
if (!a_ForceUpdate && (m_World->GetWorldAge() % 3 != 0))
|
if (!a_ForceUpdate && ((m_World->GetWorldTickAge() % 3_tick) != 0_tick))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -388,8 +388,8 @@ bool cFurnaceEntity::CanCookInputToOutput(void) const
|
|||||||
|
|
||||||
void cFurnaceEntity::UpdateProgressBars(bool a_ForceUpdate)
|
void cFurnaceEntity::UpdateProgressBars(bool a_ForceUpdate)
|
||||||
{
|
{
|
||||||
// In order to preserve bandwidth, an update is sent only every 10th tick
|
// In order to preserve bandwidth, an update is sent only every 10th tick:
|
||||||
if (!a_ForceUpdate && (m_World->GetWorldAge() % 10 != 0))
|
if (!a_ForceUpdate && ((m_World->GetWorldTickAge() % 10_tick) != 0_tick))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,13 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// How many ticks at minimum between two item transfers to or from the hopper.
|
||||||
|
#define TICKS_PER_TRANSFER 8_tick
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
cHopperEntity::cHopperEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld * a_World):
|
cHopperEntity::cHopperEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld * a_World):
|
||||||
Super(a_BlockType, a_BlockMeta, a_Pos, ContentsWidth, ContentsHeight, a_World),
|
Super(a_BlockType, a_BlockMeta, a_Pos, ContentsWidth, ContentsHeight, a_World),
|
||||||
m_LastMoveItemsInTick(0),
|
m_LastMoveItemsInTick(0),
|
||||||
@ -76,14 +83,14 @@ void cHopperEntity::CopyFrom(const cBlockEntity & a_Src)
|
|||||||
bool cHopperEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
|
bool cHopperEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
|
||||||
{
|
{
|
||||||
UNUSED(a_Dt);
|
UNUSED(a_Dt);
|
||||||
Int64 CurrentTick = a_Chunk.GetWorld()->GetWorldAge();
|
|
||||||
|
|
||||||
bool isDirty = false;
|
bool isDirty = false;
|
||||||
if (!m_Locked)
|
if (!m_Locked)
|
||||||
{
|
{
|
||||||
isDirty = MoveItemsIn (a_Chunk, CurrentTick) || isDirty;
|
const auto CurrentTick = a_Chunk.GetWorld()->GetWorldAge();
|
||||||
isDirty = MovePickupsIn(a_Chunk, CurrentTick) || isDirty;
|
isDirty = MoveItemsIn(a_Chunk, CurrentTick) || isDirty;
|
||||||
isDirty = MoveItemsOut (a_Chunk, CurrentTick) || isDirty;
|
isDirty = MovePickupsIn(a_Chunk) || isDirty;
|
||||||
|
isDirty = MoveItemsOut(a_Chunk, CurrentTick) || isDirty;
|
||||||
}
|
}
|
||||||
return isDirty;
|
return isDirty;
|
||||||
}
|
}
|
||||||
@ -147,7 +154,7 @@ void cHopperEntity::OpenNewWindow(void)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cHopperEntity::MoveItemsIn(cChunk & a_Chunk, Int64 a_CurrentTick)
|
bool cHopperEntity::MoveItemsIn(cChunk & a_Chunk, const cTickTimeLong a_CurrentTick)
|
||||||
{
|
{
|
||||||
if (m_Pos.y >= cChunkDef::Height)
|
if (m_Pos.y >= cChunkDef::Height)
|
||||||
{
|
{
|
||||||
@ -155,7 +162,7 @@ bool cHopperEntity::MoveItemsIn(cChunk & a_Chunk, Int64 a_CurrentTick)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (a_CurrentTick - m_LastMoveItemsInTick < TICKS_PER_TRANSFER)
|
if ((a_CurrentTick - m_LastMoveItemsInTick) < TICKS_PER_TRANSFER)
|
||||||
{
|
{
|
||||||
// Too early after the previous transfer
|
// Too early after the previous transfer
|
||||||
return false;
|
return false;
|
||||||
@ -201,10 +208,8 @@ bool cHopperEntity::MoveItemsIn(cChunk & a_Chunk, Int64 a_CurrentTick)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cHopperEntity::MovePickupsIn(cChunk & a_Chunk, Int64 a_CurrentTick)
|
bool cHopperEntity::MovePickupsIn(cChunk & a_Chunk)
|
||||||
{
|
{
|
||||||
UNUSED(a_CurrentTick);
|
|
||||||
|
|
||||||
class cHopperPickupSearchCallback
|
class cHopperPickupSearchCallback
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -290,9 +295,9 @@ bool cHopperEntity::MovePickupsIn(cChunk & a_Chunk, Int64 a_CurrentTick)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cHopperEntity::MoveItemsOut(cChunk & a_Chunk, Int64 a_CurrentTick)
|
bool cHopperEntity::MoveItemsOut(cChunk & a_Chunk, const cTickTimeLong a_CurrentTick)
|
||||||
{
|
{
|
||||||
if (a_CurrentTick - m_LastMoveItemsOutTick < TICKS_PER_TRANSFER)
|
if ((a_CurrentTick - m_LastMoveItemsOutTick) < TICKS_PER_TRANSFER)
|
||||||
{
|
{
|
||||||
// Too early after the previous transfer
|
// Too early after the previous transfer
|
||||||
return false;
|
return false;
|
||||||
|
@ -30,8 +30,7 @@ public:
|
|||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
ContentsHeight = 1,
|
ContentsHeight = 1,
|
||||||
ContentsWidth = 5,
|
ContentsWidth = 5
|
||||||
TICKS_PER_TRANSFER = 8, ///< How many ticks at minimum between two item transfers to or from the hopper
|
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
// tolua_end
|
// tolua_end
|
||||||
@ -48,8 +47,8 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
Int64 m_LastMoveItemsInTick;
|
cTickTimeLong m_LastMoveItemsInTick;
|
||||||
Int64 m_LastMoveItemsOutTick;
|
cTickTimeLong m_LastMoveItemsOutTick;
|
||||||
|
|
||||||
// cBlockEntity overrides:
|
// cBlockEntity overrides:
|
||||||
virtual void CopyFrom(const cBlockEntity & a_Src) override;
|
virtual void CopyFrom(const cBlockEntity & a_Src) override;
|
||||||
@ -61,13 +60,13 @@ protected:
|
|||||||
void OpenNewWindow(void);
|
void OpenNewWindow(void);
|
||||||
|
|
||||||
/** Moves items from the container above it into this hopper. Returns true if the contents have changed. */
|
/** Moves items from the container above it into this hopper. Returns true if the contents have changed. */
|
||||||
bool MoveItemsIn(cChunk & a_Chunk, Int64 a_CurrentTick);
|
bool MoveItemsIn(cChunk & a_Chunk, cTickTimeLong a_CurrentTick);
|
||||||
|
|
||||||
/** Moves pickups from above this hopper into it. Returns true if the contents have changed. */
|
/** Moves pickups from above this hopper into it. Returns true if the contents have changed. */
|
||||||
bool MovePickupsIn(cChunk & a_Chunk, Int64 a_CurrentTick);
|
bool MovePickupsIn(cChunk & a_Chunk);
|
||||||
|
|
||||||
/** Moves items out from this hopper into the destination. Returns true if the contents have changed. */
|
/** Moves items out from this hopper into the destination. Returns true if the contents have changed. */
|
||||||
bool MoveItemsOut(cChunk & a_Chunk, Int64 a_CurrentTick);
|
bool MoveItemsOut(cChunk & a_Chunk, cTickTimeLong 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 MoveItemsFromChest(cChunk & a_Chunk);
|
bool MoveItemsFromChest(cChunk & a_Chunk);
|
||||||
|
@ -92,8 +92,10 @@ void cMobSpawnerEntity::UpdateActiveState(void)
|
|||||||
|
|
||||||
bool cMobSpawnerEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
|
bool cMobSpawnerEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
|
||||||
{
|
{
|
||||||
// Update the active flag every 5 seconds
|
using namespace std::chrono_literals;
|
||||||
if ((m_World->GetWorldAge() % 100) == 0)
|
|
||||||
|
// Update the active flag every 5 seconds:
|
||||||
|
if ((m_World->GetWorldTickAge() % 5s) == 0s)
|
||||||
{
|
{
|
||||||
UpdateActiveState();
|
UpdateActiveState();
|
||||||
}
|
}
|
||||||
|
@ -75,7 +75,7 @@ bool cBlockBedHandler::OnUse(
|
|||||||
|
|
||||||
// Sleeping is allowed only during night and thunderstorms:
|
// Sleeping is allowed only during night and thunderstorms:
|
||||||
if (
|
if (
|
||||||
!(((a_WorldInterface.GetTimeOfDay() > 12541) && (a_WorldInterface.GetTimeOfDay() < 23458)) ||
|
!(((a_WorldInterface.GetTimeOfDay() > 12541_tick) && (a_WorldInterface.GetTimeOfDay() < 23458_tick)) ||
|
||||||
(a_Player.GetWorld()->GetWeather() == wThunderstorm))
|
(a_Player.GetWorld()->GetWeather() == wThunderstorm))
|
||||||
) // Source: https://minecraft.gamepedia.com/Bed#Sleeping
|
) // Source: https://minecraft.gamepedia.com/Bed#Sleeping
|
||||||
{
|
{
|
||||||
@ -146,7 +146,7 @@ bool cBlockBedHandler::OnUse(
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
a_WorldInterface.SetTimeOfDay(0);
|
a_WorldInterface.SetTimeOfDay(0_tick);
|
||||||
a_ChunkInterface.SetBlockMeta(a_BlockPos, Meta & 0x0b); // Clear the "occupied" bit of the bed's block
|
a_ChunkInterface.SetBlockMeta(a_BlockPos, Meta & 0x0b); // Clear the "occupied" bit of the bed's block
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -193,7 +193,7 @@ private:
|
|||||||
The given block type is checked when the task is executed to ensure the position still contains a button. */
|
The given block type is checked when the task is executed to ensure the position still contains a button. */
|
||||||
static void QueueButtonRelease(cWorld & a_ButtonWorld, const Vector3i a_Position, const BLOCKTYPE a_BlockType)
|
static void QueueButtonRelease(cWorld & a_ButtonWorld, const Vector3i a_Position, const BLOCKTYPE a_BlockType)
|
||||||
{
|
{
|
||||||
const auto TickDelay = (a_BlockType == E_BLOCK_STONE_BUTTON) ? 20 : 30;
|
const auto TickDelay = (a_BlockType == E_BLOCK_STONE_BUTTON) ? 20_tick : 30_tick;
|
||||||
a_ButtonWorld.ScheduleTask(
|
a_ButtonWorld.ScheduleTask(
|
||||||
TickDelay,
|
TickDelay,
|
||||||
[a_Position, a_BlockType](cWorld & a_World)
|
[a_Position, a_BlockType](cWorld & a_World)
|
||||||
|
@ -56,7 +56,7 @@ void cBlockPistonHandler::ExtendPiston(Vector3i a_BlockPos, cWorld & a_World)
|
|||||||
// However, we don't confuse animation with the underlying state of the world, so emulate by delaying 1 tick
|
// However, we don't confuse animation with the underlying state of the world, so emulate by delaying 1 tick
|
||||||
// (Probably why vanilla has so many dupe glitches with sand and pistons lolol)
|
// (Probably why vanilla has so many dupe glitches with sand and pistons lolol)
|
||||||
|
|
||||||
a_World.ScheduleTask(1, [a_BlockPos](cWorld & World)
|
a_World.ScheduleTask(1_tick, [a_BlockPos](cWorld & World)
|
||||||
{
|
{
|
||||||
BLOCKTYPE pistonBlock;
|
BLOCKTYPE pistonBlock;
|
||||||
NIBBLETYPE pistonMeta;
|
NIBBLETYPE pistonMeta;
|
||||||
@ -108,7 +108,7 @@ void cBlockPistonHandler::RetractPiston(Vector3i a_BlockPos, cWorld & a_World)
|
|||||||
a_World.BroadcastBlockAction(a_BlockPos, PistonRetractAction, pistonMeta, pistonBlock);
|
a_World.BroadcastBlockAction(a_BlockPos, PistonRetractAction, pistonMeta, pistonBlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
a_World.ScheduleTask(1, [a_BlockPos](cWorld & World)
|
a_World.ScheduleTask(1_tick, [a_BlockPos](cWorld & World)
|
||||||
{
|
{
|
||||||
BLOCKTYPE pistonBlock;
|
BLOCKTYPE pistonBlock;
|
||||||
NIBBLETYPE pistonMeta;
|
NIBBLETYPE pistonMeta;
|
||||||
|
@ -21,8 +21,8 @@ class cWorldInterface
|
|||||||
public:
|
public:
|
||||||
virtual ~cWorldInterface() {}
|
virtual ~cWorldInterface() {}
|
||||||
|
|
||||||
virtual int GetTimeOfDay(void) const = 0;
|
virtual cTickTime GetTimeOfDay(void) const = 0;
|
||||||
virtual Int64 GetWorldAge(void) const = 0;
|
virtual cTickTimeLong GetWorldAge(void) const = 0;
|
||||||
|
|
||||||
virtual eDimension GetDimension(void) const = 0;
|
virtual eDimension GetDimension(void) const = 0;
|
||||||
|
|
||||||
@ -70,7 +70,7 @@ public:
|
|||||||
If any chunk in the box is missing, ignores the entities in that chunk silently. */
|
If any chunk in the box is missing, ignores the entities in that chunk silently. */
|
||||||
virtual bool ForEachEntityInBox(const cBoundingBox & a_Box, cEntityCallback a_Callback) = 0;
|
virtual bool ForEachEntityInBox(const cBoundingBox & a_Box, cEntityCallback a_Callback) = 0;
|
||||||
|
|
||||||
virtual void SetTimeOfDay(int a_TimeOfDay) = 0;
|
virtual void SetTimeOfDay(cTickTime a_TimeOfDay) = 0;
|
||||||
|
|
||||||
/** Returns true if it is raining or storming at the specified location. This takes into account biomes. */
|
/** Returns true if it is raining or storming at the specified location. This takes into account biomes. */
|
||||||
virtual bool IsWeatherWetAt(int a_BlockX, int a_BlockZ) = 0;
|
virtual bool IsWeatherWetAt(int a_BlockX, int a_BlockZ) = 0;
|
||||||
|
@ -596,7 +596,7 @@ void cWorld::BroadcastTimeUpdate(const cClientHandle * a_Exclude)
|
|||||||
{
|
{
|
||||||
ForClientsInWorld(*this, a_Exclude, [&](cClientHandle & a_Client)
|
ForClientsInWorld(*this, a_Exclude, [&](cClientHandle & a_Client)
|
||||||
{
|
{
|
||||||
a_Client.SendTimeUpdate(GetWorldAge(), std::chrono::duration_cast<cTickTimeLong>(m_WorldDate).count(), IsDaylightCycleEnabled());
|
a_Client.SendTimeUpdate(GetWorldAge(), GetWorldDate(), IsDaylightCycleEnabled());
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -538,6 +538,8 @@ void cClientHandle::UnloadOutOfRangeChunks(void)
|
|||||||
m_Player->GetWorld()->RemoveChunkClient(itr->m_ChunkX, itr->m_ChunkZ, this);
|
m_Player->GetWorld()->RemoveChunkClient(itr->m_ChunkX, itr->m_ChunkZ, this);
|
||||||
SendUnloadChunk(itr->m_ChunkX, itr->m_ChunkZ);
|
SendUnloadChunk(itr->m_ChunkX, itr->m_ChunkZ);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_LastUnloadCheck = m_Player->GetWorld()->GetWorldAge();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1981,6 +1983,8 @@ bool cClientHandle::CheckBlockInteractionsRate(void)
|
|||||||
|
|
||||||
void cClientHandle::Tick(float a_Dt)
|
void cClientHandle::Tick(float a_Dt)
|
||||||
{
|
{
|
||||||
|
using namespace std::chrono_literals;
|
||||||
|
|
||||||
// anticheat fastbreak
|
// anticheat fastbreak
|
||||||
if (m_HasStartedDigging)
|
if (m_HasStartedDigging)
|
||||||
{
|
{
|
||||||
@ -2069,8 +2073,8 @@ void cClientHandle::Tick(float a_Dt)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unload all chunks that are out of the view distance (every 5 seconds)
|
// Unload all chunks that are out of the view distance (every 5 seconds):
|
||||||
if ((m_Player->GetWorld()->GetWorldAge() % 100) == 0)
|
if ((m_Player->GetWorld()->GetWorldAge() - m_LastUnloadCheck) > 5s)
|
||||||
{
|
{
|
||||||
UnloadOutOfRangeChunks();
|
UnloadOutOfRangeChunks();
|
||||||
}
|
}
|
||||||
@ -3012,7 +3016,7 @@ void cClientHandle::SendTitleTimes(int a_FadeInTicks, int a_DisplayTicks, int a_
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cClientHandle::SendTimeUpdate(Int64 a_WorldAge, Int64 a_WorldDate, bool a_DoDaylightCycle)
|
void cClientHandle::SendTimeUpdate(const cTickTimeLong a_WorldAge, const cTickTimeLong a_WorldDate, const bool a_DoDaylightCycle)
|
||||||
{
|
{
|
||||||
m_Protocol->SendTimeUpdate(a_WorldAge, a_WorldDate, a_DoDaylightCycle);
|
m_Protocol->SendTimeUpdate(a_WorldAge, a_WorldDate, a_DoDaylightCycle);
|
||||||
}
|
}
|
||||||
|
@ -216,7 +216,7 @@ public: // tolua_export
|
|||||||
void SendTabCompletionResults (const AStringVector & a_Results);
|
void SendTabCompletionResults (const AStringVector & a_Results);
|
||||||
void SendThunderbolt (int a_BlockX, int a_BlockY, int a_BlockZ);
|
void SendThunderbolt (int a_BlockX, int a_BlockY, int a_BlockZ);
|
||||||
void SendTitleTimes (int a_FadeInTicks, int a_DisplayTicks, int a_FadeOutTicks); // tolua_export
|
void SendTitleTimes (int a_FadeInTicks, int a_DisplayTicks, int a_FadeOutTicks); // tolua_export
|
||||||
void SendTimeUpdate (Int64 a_WorldAge, Int64 a_WorldDate, bool a_DoDaylightCycle); // tolua_export
|
void SendTimeUpdate (cTickTimeLong a_WorldAge, cTickTimeLong a_WorldDate, bool a_DoDaylightCycle);
|
||||||
void SendUnleashEntity (const cEntity & a_Entity);
|
void SendUnleashEntity (const cEntity & a_Entity);
|
||||||
void SendUnloadChunk (int a_ChunkX, int a_ChunkZ);
|
void SendUnloadChunk (int a_ChunkX, int a_ChunkZ);
|
||||||
void SendUpdateBlockEntity (cBlockEntity & a_BlockEntity);
|
void SendUpdateBlockEntity (cBlockEntity & a_BlockEntity);
|
||||||
@ -478,6 +478,9 @@ private:
|
|||||||
int m_LastStreamedChunkX;
|
int m_LastStreamedChunkX;
|
||||||
int m_LastStreamedChunkZ;
|
int m_LastStreamedChunkZ;
|
||||||
|
|
||||||
|
/** The last time UnloadOutOfRangeChunks was called. */
|
||||||
|
cTickTimeLong m_LastUnloadCheck;
|
||||||
|
|
||||||
/** Number of ticks since the last network packet was received (increased in Tick(), reset in OnReceivedData()) */
|
/** Number of ticks since the last network packet was received (increased in Tick(), reset in OnReceivedData()) */
|
||||||
std::atomic<int> m_TicksSinceLastPacket;
|
std::atomic<int> m_TicksSinceLastPacket;
|
||||||
|
|
||||||
|
@ -103,11 +103,10 @@ void cDeadlockDetect::Execute(void)
|
|||||||
{
|
{
|
||||||
// Check the world ages:
|
// Check the world ages:
|
||||||
cRoot::Get()->ForEachWorld([=](cWorld & a_World)
|
cRoot::Get()->ForEachWorld([=](cWorld & a_World)
|
||||||
{
|
{
|
||||||
CheckWorldAge(a_World.GetName(), a_World.GetWorldAge());
|
CheckWorldAge(a_World.GetName(), a_World.GetWorldAge());
|
||||||
return false;
|
return false;
|
||||||
}
|
});
|
||||||
);
|
|
||||||
|
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(CYCLE_MILLISECONDS));
|
std::this_thread::sleep_for(std::chrono::milliseconds(CYCLE_MILLISECONDS));
|
||||||
} // while (should run)
|
} // while (should run)
|
||||||
@ -117,7 +116,7 @@ void cDeadlockDetect::Execute(void)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cDeadlockDetect::SetWorldAge(const AString & a_WorldName, Int64 a_Age)
|
void cDeadlockDetect::SetWorldAge(const AString & a_WorldName, const cTickTimeLong a_Age)
|
||||||
{
|
{
|
||||||
m_WorldAges[a_WorldName].m_Age = a_Age;
|
m_WorldAges[a_WorldName].m_Age = a_Age;
|
||||||
m_WorldAges[a_WorldName].m_NumCyclesSame = 0;
|
m_WorldAges[a_WorldName].m_NumCyclesSame = 0;
|
||||||
@ -127,7 +126,7 @@ void cDeadlockDetect::SetWorldAge(const AString & a_WorldName, Int64 a_Age)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cDeadlockDetect::CheckWorldAge(const AString & a_WorldName, Int64 a_Age)
|
void cDeadlockDetect::CheckWorldAge(const AString & a_WorldName, const cTickTimeLong a_Age)
|
||||||
{
|
{
|
||||||
WorldAges::iterator itr = m_WorldAges.find(a_WorldName);
|
WorldAges::iterator itr = m_WorldAges.find(a_WorldName);
|
||||||
if (itr == m_WorldAges.end())
|
if (itr == m_WorldAges.end())
|
||||||
@ -157,14 +156,14 @@ void cDeadlockDetect::CheckWorldAge(const AString & a_WorldName, Int64 a_Age)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cDeadlockDetect::DeadlockDetected(const AString & a_WorldName, Int64 a_WorldAge)
|
void cDeadlockDetect::DeadlockDetected(const AString & a_WorldName, const cTickTimeLong a_WorldAge)
|
||||||
{
|
{
|
||||||
LOGERROR("Deadlock detected: world %s has been stuck at age %lld. Aborting the server.",
|
LOGERROR("Deadlock detected: world %s has been stuck at age %lld. Aborting the server.",
|
||||||
a_WorldName.c_str(), static_cast<long long>(a_WorldAge)
|
a_WorldName.c_str(), static_cast<long long>(a_WorldAge.count())
|
||||||
);
|
);
|
||||||
ListTrackedCSs();
|
ListTrackedCSs();
|
||||||
ASSERT(!"Deadlock detected");
|
ASSERT(!"Deadlock detected");
|
||||||
abort();
|
std::abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -182,7 +181,3 @@ void cDeadlockDetect::ListTrackedCSs(void)
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@ protected:
|
|||||||
struct sWorldAge
|
struct sWorldAge
|
||||||
{
|
{
|
||||||
/** Last m_WorldAge that has been detected in this world */
|
/** Last m_WorldAge that has been detected in this world */
|
||||||
Int64 m_Age;
|
cTickTimeLong m_Age;
|
||||||
|
|
||||||
/** Number of cycles for which the age has been the same */
|
/** Number of cycles for which the age has been the same */
|
||||||
int m_NumCyclesSame;
|
int m_NumCyclesSame;
|
||||||
@ -71,16 +71,16 @@ protected:
|
|||||||
// cIsThread overrides:
|
// cIsThread overrides:
|
||||||
virtual void Execute(void) override;
|
virtual void Execute(void) override;
|
||||||
|
|
||||||
/** Sets the initial world age */
|
/** Sets the initial world age. */
|
||||||
void SetWorldAge(const AString & a_WorldName, Int64 a_Age);
|
void SetWorldAge(const AString & a_WorldName, cTickTimeLong a_Age);
|
||||||
|
|
||||||
/** Checks if the world's age has changed, updates the world's stats; calls DeadlockDetected() if deadlock detected */
|
/** Checks if the world's age has changed, updates the world's stats; calls DeadlockDetected() if deadlock detected. */
|
||||||
void CheckWorldAge(const AString & a_WorldName, Int64 a_Age);
|
void CheckWorldAge(const AString & a_WorldName, cTickTimeLong a_Age);
|
||||||
|
|
||||||
/** Called when a deadlock is detected in a world. Aborts the server.
|
/** Called when a deadlock is detected in a world. Aborts the server.
|
||||||
a_WorldName is the name of the world whose age has triggered the detection.
|
a_WorldName is the name of the world whose age has triggered the detection.
|
||||||
a_WorldAge is the age (in ticks) in which the world is stuck. */
|
a_WorldAge is the age (in ticks) in which the world is stuck. */
|
||||||
[[noreturn]] void DeadlockDetected(const AString & a_WorldName, Int64 a_WorldAge);
|
[[noreturn]] void DeadlockDetected(const AString & a_WorldName, cTickTimeLong a_WorldAge);
|
||||||
|
|
||||||
/** Outputs a listing of the tracked CSs, together with their name and state. */
|
/** Outputs a listing of the tracked CSs, together with their name and state. */
|
||||||
void ListTrackedCSs();
|
void ListTrackedCSs();
|
||||||
|
@ -46,8 +46,8 @@ void cBoat::BroadcastMovementUpdate(const cClientHandle * a_Exclude)
|
|||||||
// Cannot use super::BroadcastMovementUpdate here, broadcasting position when not
|
// Cannot use super::BroadcastMovementUpdate here, broadcasting position when not
|
||||||
// expected by the client breaks things. See https://github.com/cuberite/cuberite/pull/4488
|
// expected by the client breaks things. See https://github.com/cuberite/cuberite/pull/4488
|
||||||
|
|
||||||
// Process packet sending every two ticks
|
// Process packet sending every two ticks:
|
||||||
if (GetWorld()->GetWorldAge() % 2 != 0)
|
if ((GetWorld()->GetWorldTickAge() % 2_tick) != 0_tick)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1884,8 +1884,8 @@ void cEntity::TeleportToCoords(double a_PosX, double a_PosY, double a_PosZ)
|
|||||||
|
|
||||||
void cEntity::BroadcastMovementUpdate(const cClientHandle * a_Exclude)
|
void cEntity::BroadcastMovementUpdate(const cClientHandle * a_Exclude)
|
||||||
{
|
{
|
||||||
// Process packet sending every two ticks
|
// Process packet sending every two ticks:
|
||||||
if (GetWorld()->GetWorldAge() % 2 != 0)
|
if ((GetWorld()->GetWorldTickAge() % 2_tick) != 0_tick)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -59,8 +59,8 @@ const int cPlayer::MAX_HEALTH = 20;
|
|||||||
|
|
||||||
const int cPlayer::MAX_FOOD_LEVEL = 20;
|
const int cPlayer::MAX_FOOD_LEVEL = 20;
|
||||||
|
|
||||||
/** Number of ticks it takes to eat an item */
|
// Number of ticks it takes to eat an item.
|
||||||
const int cPlayer::EATING_TICKS = 30;
|
#define EATING_TICKS 30_tick
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -530,7 +530,7 @@ void cPlayer::StartEating(void)
|
|||||||
void cPlayer::FinishEating(void)
|
void cPlayer::FinishEating(void)
|
||||||
{
|
{
|
||||||
// Reset the timer:
|
// Reset the timer:
|
||||||
m_EatingFinishTick = -1;
|
m_EatingFinishTick = -1_tick;
|
||||||
|
|
||||||
// Send the packets:
|
// Send the packets:
|
||||||
m_ClientHandle->SendEntityStatus(*this, esPlayerEatingAccepted);
|
m_ClientHandle->SendEntityStatus(*this, esPlayerEatingAccepted);
|
||||||
@ -553,7 +553,7 @@ void cPlayer::FinishEating(void)
|
|||||||
|
|
||||||
void cPlayer::AbortEating(void)
|
void cPlayer::AbortEating(void)
|
||||||
{
|
{
|
||||||
m_EatingFinishTick = -1;
|
m_EatingFinishTick = -1_tick;
|
||||||
m_World->BroadcastEntityMetadata(*this);
|
m_World->BroadcastEntityMetadata(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2929,7 +2929,7 @@ void cPlayer::TickFreezeCode()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (GetWorld()->GetWorldAge() % 100 == 0)
|
else if ((GetWorld()->GetWorldTickAge() % 100_tick) == 0_tick)
|
||||||
{
|
{
|
||||||
// Despite the client side freeze, the player may be able to move a little by
|
// Despite the client side freeze, the player may be able to move a little by
|
||||||
// Jumping or canceling flight. Re-freeze every now and then
|
// Jumping or canceling flight. Re-freeze every now and then
|
||||||
@ -3115,7 +3115,7 @@ void cPlayer::OnAddToWorld(cWorld & a_World)
|
|||||||
m_ClientHandle->SendWeather(a_World.GetWeather());
|
m_ClientHandle->SendWeather(a_World.GetWeather());
|
||||||
|
|
||||||
// Send time:
|
// Send time:
|
||||||
m_ClientHandle->SendTimeUpdate(a_World.GetWorldAge(), a_World.GetTimeOfDay(), a_World.IsDaylightCycleEnabled());
|
m_ClientHandle->SendTimeUpdate(a_World.GetWorldAge(), a_World.GetWorldDate(), a_World.IsDaylightCycleEnabled());
|
||||||
|
|
||||||
// Finally, deliver the notification hook:
|
// Finally, deliver the notification hook:
|
||||||
cRoot::Get()->GetPluginManager()->CallHookPlayerSpawned(*this);
|
cRoot::Get()->GetPluginManager()->CallHookPlayerSpawned(*this);
|
||||||
@ -3298,7 +3298,7 @@ void cPlayer::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
|
|||||||
{
|
{
|
||||||
m_World->CollectPickupsByPlayer(*this);
|
m_World->CollectPickupsByPlayer(*this);
|
||||||
|
|
||||||
if ((m_EatingFinishTick >= 0) && (m_EatingFinishTick <= m_World->GetWorldAge()))
|
if ((m_EatingFinishTick >= 0_tick) && (m_EatingFinishTick <= m_World->GetWorldAge()))
|
||||||
{
|
{
|
||||||
FinishEating();
|
FinishEating();
|
||||||
}
|
}
|
||||||
|
@ -86,9 +86,6 @@ public:
|
|||||||
|
|
||||||
static const int MAX_FOOD_LEVEL;
|
static const int MAX_FOOD_LEVEL;
|
||||||
|
|
||||||
/** Number of ticks it takes to eat an item */
|
|
||||||
static const int EATING_TICKS;
|
|
||||||
|
|
||||||
// tolua_end
|
// tolua_end
|
||||||
|
|
||||||
CLASS_PROTODEF(cPlayer)
|
CLASS_PROTODEF(cPlayer)
|
||||||
@ -371,7 +368,7 @@ public:
|
|||||||
void AddFoodExhaustion(double a_Exhaustion);
|
void AddFoodExhaustion(double a_Exhaustion);
|
||||||
|
|
||||||
/** Returns true if the player is currently in the process of eating the currently equipped item */
|
/** Returns true if the player is currently in the process of eating the currently equipped item */
|
||||||
bool IsEating(void) const { return (m_EatingFinishTick >= 0); }
|
bool IsEating(void) const { return m_EatingFinishTick >= 0_tick; }
|
||||||
|
|
||||||
/** Returns true if the player is currently flying */
|
/** Returns true if the player is currently flying */
|
||||||
bool IsFlying(void) const { return m_IsFlying; }
|
bool IsFlying(void) const { return m_IsFlying; }
|
||||||
@ -734,7 +731,7 @@ private:
|
|||||||
bool m_IsVisible;
|
bool m_IsVisible;
|
||||||
|
|
||||||
/** The world tick in which eating will be finished. -1 if not eating */
|
/** The world tick in which eating will be finished. -1 if not eating */
|
||||||
Int64 m_EatingFinishTick;
|
cTickTimeLong m_EatingFinishTick;
|
||||||
|
|
||||||
/** Player Xp level */
|
/** Player Xp level */
|
||||||
int m_LifetimeTotalXp;
|
int m_LifetimeTotalXp;
|
||||||
|
@ -338,14 +338,14 @@ T Clamp(T a_Value, T a_Min, T a_Max)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** Floors a value, then casts it to C (an int by default) */
|
/** Floors a value, then casts it to C (an int by default). */
|
||||||
template <typename C = int, typename T>
|
template <typename C = int, typename T>
|
||||||
typename std::enable_if<std::is_arithmetic<T>::value, C>::type FloorC(T a_Value)
|
typename std::enable_if<std::is_arithmetic<T>::value, C>::type FloorC(T a_Value)
|
||||||
{
|
{
|
||||||
return static_cast<C>(std::floor(a_Value));
|
return static_cast<C>(std::floor(a_Value));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Ceils a value, then casts it to C (an int by default) */
|
/** Ceils a value, then casts it to C (an int by default). */
|
||||||
template <typename C = int, typename T>
|
template <typename C = int, typename T>
|
||||||
typename std::enable_if<std::is_arithmetic<T>::value, C>::type CeilC(T a_Value)
|
typename std::enable_if<std::is_arithmetic<T>::value, C>::type CeilC(T a_Value)
|
||||||
{
|
{
|
||||||
@ -356,9 +356,17 @@ typename std::enable_if<std::is_arithmetic<T>::value, C>::type CeilC(T a_Value)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
// a tick is 50 ms
|
// A time duration representing a Minecraft tick (50 ms), capable of storing at least 32'767 ticks.
|
||||||
using cTickTime = std::chrono::duration<int, std::ratio_multiply<std::chrono::milliseconds::period, std::ratio<50>>>;
|
using cTickTime = std::chrono::duration<signed int, std::ratio_multiply<std::chrono::milliseconds::period, std::ratio<50>>>;
|
||||||
using cTickTimeLong = std::chrono::duration<Int64, cTickTime::period>;
|
|
||||||
|
// A time duration representing a Minecraft tick (50 ms), capable of storing at least a 64 bit signed duration.
|
||||||
|
using cTickTimeLong = std::chrono::duration<signed long long int, cTickTime::period>;
|
||||||
|
|
||||||
|
/** Converts a literal to a tick time. */
|
||||||
|
constexpr cTickTimeLong operator ""_tick(const unsigned long long a_Ticks)
|
||||||
|
{
|
||||||
|
return cTickTimeLong(a_Ticks);
|
||||||
|
}
|
||||||
|
|
||||||
using ContiguousByteBuffer = std::basic_string<std::byte>;
|
using ContiguousByteBuffer = std::basic_string<std::byte>;
|
||||||
using ContiguousByteBufferView = std::basic_string_view<std::byte>;
|
using ContiguousByteBufferView = std::basic_string_view<std::byte>;
|
||||||
|
@ -39,7 +39,6 @@ int cMobCensus::GetCapMultiplier(cMonster::eFamily a_MobFamily)
|
|||||||
case cMonster::mfAmbient: return 16;
|
case cMonster::mfAmbient: return 16;
|
||||||
case cMonster::mfWater: return 5;
|
case cMonster::mfWater: return 5;
|
||||||
case cMonster::mfNoSpawn:
|
case cMonster::mfNoSpawn:
|
||||||
case cMonster::mfUnhandled:
|
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@ void cCaveSpider::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_EMPersonality = (GetWorld()->GetTimeOfDay() < (12000 + 1000)) ? PASSIVE : AGGRESSIVE;
|
m_EMPersonality = (GetWorld()->GetTimeOfDay() < 13000_tick) ? PASSIVE : AGGRESSIVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1150,34 +1150,26 @@ cMonster::eFamily cMonster::FamilyFromType(eMonsterType a_Type)
|
|||||||
case mtZombieHorse: return mfPassive;
|
case mtZombieHorse: return mfPassive;
|
||||||
case mtZombiePigman: return mfHostile;
|
case mtZombiePigman: return mfHostile;
|
||||||
case mtZombieVillager: return mfHostile;
|
case mtZombieVillager: return mfHostile;
|
||||||
|
case mtInvalidType: break;
|
||||||
default:
|
|
||||||
{
|
|
||||||
ASSERT(!"Unhandled mob type");
|
|
||||||
return mfUnhandled;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
UNREACHABLE("Unhandled mob type");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int cMonster::GetSpawnDelay(cMonster::eFamily a_MobFamily)
|
cTickTime cMonster::GetSpawnDelay(cMonster::eFamily a_MobFamily)
|
||||||
{
|
{
|
||||||
switch (a_MobFamily)
|
switch (a_MobFamily)
|
||||||
{
|
{
|
||||||
case mfHostile: return 40;
|
case mfHostile: return 40_tick;
|
||||||
case mfPassive: return 40;
|
case mfPassive: return 40_tick;
|
||||||
case mfAmbient: return 40;
|
case mfAmbient: return 40_tick;
|
||||||
case mfWater: return 400;
|
case mfWater: return 400_tick;
|
||||||
case mfNoSpawn: return -1;
|
case mfNoSpawn: return -1_tick;
|
||||||
default:
|
|
||||||
{
|
|
||||||
ASSERT(!"Unhandled mob family");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
UNREACHABLE("Unhandled mob family");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1654,7 +1646,7 @@ bool cMonster::WouldBurnAt(Vector3d a_Location, cChunk & a_Chunk)
|
|||||||
|
|
||||||
if (
|
if (
|
||||||
(Chunk->GetBlock(Rel) != E_BLOCK_SOULSAND) && // Not on soulsand
|
(Chunk->GetBlock(Rel) != E_BLOCK_SOULSAND) && // Not on soulsand
|
||||||
(GetWorld()->GetTimeOfDay() < 12000 + 1000) && // Daytime
|
(GetWorld()->GetTimeOfDay() < 13000_tick) && // Daytime
|
||||||
Chunk->IsWeatherSunnyAt(Rel.x, Rel.z) && // Not raining
|
Chunk->IsWeatherSunnyAt(Rel.x, Rel.z) && // Not raining
|
||||||
!IsInWater() // Isn't swimming
|
!IsInWater() // Isn't swimming
|
||||||
)
|
)
|
||||||
|
@ -32,8 +32,7 @@ public:
|
|||||||
mfAmbient = 2, // Bats
|
mfAmbient = 2, // Bats
|
||||||
mfWater = 3, // Squid, Guardian
|
mfWater = 3, // Squid, Guardian
|
||||||
|
|
||||||
mfNoSpawn,
|
mfNoSpawn
|
||||||
mfUnhandled, // Nothing. Be sure this is the last and the others are in order
|
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
// tolua_end
|
// tolua_end
|
||||||
@ -187,11 +186,11 @@ public:
|
|||||||
/** Returns the mob family based on the type */
|
/** Returns the mob family based on the type */
|
||||||
static eFamily FamilyFromType(eMonsterType a_MobType);
|
static eFamily FamilyFromType(eMonsterType a_MobType);
|
||||||
|
|
||||||
/** Returns the spawn delay (number of game ticks between spawn attempts) for the given mob family */
|
|
||||||
static int GetSpawnDelay(cMonster::eFamily a_MobFamily);
|
|
||||||
|
|
||||||
// tolua_end
|
// tolua_end
|
||||||
|
|
||||||
|
/** Returns the spawn delay (number of game ticks between spawn attempts) for the given mob family */
|
||||||
|
static cTickTime GetSpawnDelay(cMonster::eFamily a_MobFamily);
|
||||||
|
|
||||||
/** Translates the MobType enum to the vanilla nbt name */
|
/** Translates the MobType enum to the vanilla nbt name */
|
||||||
static AString MobTypeToVanillaNBT(eMonsterType a_MobType);
|
static AString MobTypeToVanillaNBT(eMonsterType a_MobType);
|
||||||
|
|
||||||
|
@ -438,7 +438,7 @@ public:
|
|||||||
virtual void SendTabCompletionResults (const AStringVector & a_Results) = 0;
|
virtual void SendTabCompletionResults (const AStringVector & a_Results) = 0;
|
||||||
virtual void SendThunderbolt (int a_BlockX, int a_BlockY, int a_BlockZ) = 0;
|
virtual void SendThunderbolt (int a_BlockX, int a_BlockY, int a_BlockZ) = 0;
|
||||||
virtual void SendTitleTimes (int a_FadeInTicks, int a_DisplayTicks, int a_FadeOutTicks) = 0;
|
virtual void SendTitleTimes (int a_FadeInTicks, int a_DisplayTicks, int a_FadeOutTicks) = 0;
|
||||||
virtual void SendTimeUpdate (Int64 a_WorldAge, Int64 a_WorldDate, bool a_DoDaylightCycle) = 0;
|
virtual void SendTimeUpdate (cTickTimeLong a_WorldAge, cTickTimeLong a_WorldDate, bool a_DoDaylightCycle) = 0;
|
||||||
virtual void SendUnleashEntity (const cEntity & a_Entity) = 0;
|
virtual void SendUnleashEntity (const cEntity & a_Entity) = 0;
|
||||||
virtual void SendUnloadChunk (int a_ChunkX, int a_ChunkZ) = 0;
|
virtual void SendUnloadChunk (int a_ChunkX, int a_ChunkZ) = 0;
|
||||||
virtual void SendUpdateBlockEntity (cBlockEntity & a_BlockEntity) = 0;
|
virtual void SendUpdateBlockEntity (cBlockEntity & a_BlockEntity) = 0;
|
||||||
|
@ -1566,20 +1566,23 @@ void cProtocol_1_8_0::SendTitleTimes(int a_FadeInTicks, int a_DisplayTicks, int
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cProtocol_1_8_0::SendTimeUpdate(Int64 a_WorldAge, Int64 a_WorldDate, bool a_DoDaylightCycle)
|
void cProtocol_1_8_0::SendTimeUpdate(const cTickTimeLong a_WorldAge, const cTickTimeLong a_WorldDate, const bool a_DoDaylightCycle)
|
||||||
{
|
{
|
||||||
ASSERT(m_State == 3); // In game mode?
|
ASSERT(m_State == 3); // In game mode?
|
||||||
|
|
||||||
if (!a_DoDaylightCycle)
|
cPacketizer Pkt(*this, pktTimeUpdate);
|
||||||
|
Pkt.WriteBEInt64(a_WorldAge.count());
|
||||||
|
|
||||||
|
if (a_DoDaylightCycle)
|
||||||
|
{
|
||||||
|
Pkt.WriteBEInt64(a_WorldDate.count());
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
// Negating the date stops time from advancing on the client
|
// Negating the date stops time from advancing on the client
|
||||||
// (the std::min construction is to handle the case where the date is exactly zero):
|
// (the std::min construction is to handle the case where the date is exactly zero):
|
||||||
a_WorldDate = std::min(-a_WorldDate, -1LL);
|
Pkt.WriteBEInt64(std::min(-a_WorldDate.count(), -1LL));
|
||||||
}
|
}
|
||||||
|
|
||||||
cPacketizer Pkt(*this, pktTimeUpdate);
|
|
||||||
Pkt.WriteBEInt64(a_WorldAge);
|
|
||||||
Pkt.WriteBEInt64(a_WorldDate);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -119,7 +119,7 @@ public:
|
|||||||
virtual void SendTabCompletionResults (const AStringVector & a_Results) override;
|
virtual void SendTabCompletionResults (const AStringVector & a_Results) override;
|
||||||
virtual void SendThunderbolt (int a_BlockX, int a_BlockY, int a_BlockZ) override;
|
virtual void SendThunderbolt (int a_BlockX, int a_BlockY, int a_BlockZ) override;
|
||||||
virtual void SendTitleTimes (int a_FadeInTicks, int a_DisplayTicks, int a_FadeOutTicks) override;
|
virtual void SendTitleTimes (int a_FadeInTicks, int a_DisplayTicks, int a_FadeOutTicks) override;
|
||||||
virtual void SendTimeUpdate (Int64 a_WorldAge, Int64 a_WorldDate, bool a_DoDaylightCycle) override;
|
virtual void SendTimeUpdate (cTickTimeLong a_WorldAge, cTickTimeLong a_WorldDate, bool a_DoDaylightCycle) override;
|
||||||
virtual void SendUnleashEntity (const cEntity & a_Entity) override;
|
virtual void SendUnleashEntity (const cEntity & a_Entity) override;
|
||||||
virtual void SendUnloadChunk (int a_ChunkX, int a_ChunkZ) override;
|
virtual void SendUnloadChunk (int a_ChunkX, int a_ChunkZ) override;
|
||||||
virtual void SendUpdateBlockEntity (cBlockEntity & a_BlockEntity) override;
|
virtual void SendUpdateBlockEntity (cBlockEntity & a_BlockEntity) override;
|
||||||
|
@ -18,7 +18,7 @@ namespace DaylightSensorHandler
|
|||||||
}
|
}
|
||||||
|
|
||||||
// The [0, 1) proportion of the current day that has elapsed.
|
// The [0, 1) proportion of the current day that has elapsed.
|
||||||
const auto ProportionOfDay = a_Chunk.GetWorld()->GetTimeOfDay() * (static_cast<float>(M_PI) / 12000.f);
|
const auto ProportionOfDay = a_Chunk.GetWorld()->GetTimeOfDay().count() * (static_cast<float>(M_PI) / 12000.f);
|
||||||
|
|
||||||
// The curved value of darkened skylight, with outputs somewhat similar to Vanilla.
|
// The curved value of darkened skylight, with outputs somewhat similar to Vanilla.
|
||||||
const auto RawOutput = a_Chunk.GetSkyLightAltered(a_Position) * (0.6f * std::sin(ProportionOfDay) + 0.5f);
|
const auto RawOutput = a_Chunk.GetSkyLightAltered(a_Position) * (0.6f * std::sin(ProportionOfDay) + 0.5f);
|
||||||
|
@ -108,7 +108,7 @@ cWorld::cTickThread::cTickThread(cWorld & a_World) :
|
|||||||
void cWorld::cTickThread::Execute(void)
|
void cWorld::cTickThread::Execute(void)
|
||||||
{
|
{
|
||||||
auto LastTime = std::chrono::steady_clock::now();
|
auto LastTime = std::chrono::steady_clock::now();
|
||||||
auto TickTime = std::chrono::duration_cast<std::chrono::milliseconds>(cTickTime(1));
|
auto TickTime = std::chrono::duration_cast<std::chrono::milliseconds>(1_tick);
|
||||||
|
|
||||||
while (!m_ShouldTerminate)
|
while (!m_ShouldTerminate)
|
||||||
{
|
{
|
||||||
@ -117,10 +117,10 @@ void cWorld::cTickThread::Execute(void)
|
|||||||
m_World.Tick(WaitTime, TickTime);
|
m_World.Tick(WaitTime, TickTime);
|
||||||
TickTime = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - NowTime);
|
TickTime = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - NowTime);
|
||||||
|
|
||||||
if (TickTime < cTickTime(1))
|
if (TickTime < 1_tick)
|
||||||
{
|
{
|
||||||
// Stretch tick time until it's at least 1 tick
|
// Stretch tick time until it's at least 1 tick:
|
||||||
std::this_thread::sleep_for(cTickTime(1) - TickTime);
|
std::this_thread::sleep_for(1_tick - TickTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
LastTime = NowTime;
|
LastTime = NowTime;
|
||||||
@ -404,7 +404,7 @@ cWorld::cWorld(
|
|||||||
cComposableGenerator::InitializeGeneratorDefaults(IniFile, m_Dimension);
|
cComposableGenerator::InitializeGeneratorDefaults(IniFile, m_Dimension);
|
||||||
|
|
||||||
InitializeAndLoadMobSpawningValues(IniFile);
|
InitializeAndLoadMobSpawningValues(IniFile);
|
||||||
SetTimeOfDay(IniFile.GetValueSetI("General", "TimeInTicks", GetTimeOfDay()));
|
m_WorldDate = cTickTime(IniFile.GetValueSetI("General", "TimeInTicks", GetWorldDate().count()));
|
||||||
|
|
||||||
// preallocate some memory for ticking blocks so we don't need to allocate that often
|
// preallocate some memory for ticking blocks so we don't need to allocate that often
|
||||||
m_BlockTickQueue.reserve(1000);
|
m_BlockTickQueue.reserve(1000);
|
||||||
@ -434,10 +434,10 @@ cWorld::cWorld(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Init of the spawn monster time (as they are supposed to have different spawn rate)
|
// Init of the spawn monster time (as they are supposed to have different spawn rate)
|
||||||
m_LastSpawnMonster.emplace(cMonster::mfHostile, cTickTimeLong(0));
|
m_LastSpawnMonster.emplace(cMonster::mfHostile, 0_tick);
|
||||||
m_LastSpawnMonster.emplace(cMonster::mfPassive, cTickTimeLong(0));
|
m_LastSpawnMonster.emplace(cMonster::mfPassive, 0_tick);
|
||||||
m_LastSpawnMonster.emplace(cMonster::mfAmbient, cTickTimeLong(0));
|
m_LastSpawnMonster.emplace(cMonster::mfAmbient, 0_tick);
|
||||||
m_LastSpawnMonster.emplace(cMonster::mfWater, cTickTimeLong(0));
|
m_LastSpawnMonster.emplace(cMonster::mfWater, 0_tick);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -475,31 +475,49 @@ void cWorld::CastThunderbolt(Vector3i a_Block)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
int cWorld::GetTimeOfDay(void) const
|
cTickTime cWorld::GetTimeOfDay(void) const
|
||||||
{
|
{
|
||||||
using namespace std::chrono_literals;
|
using namespace std::chrono_literals;
|
||||||
|
|
||||||
return std::chrono::duration_cast<cTickTime>(m_WorldDate % 20min).count();
|
return std::chrono::duration_cast<cTickTime>(m_WorldDate % 20min);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Int64 cWorld::GetWorldAge(void) const
|
cTickTimeLong cWorld::GetWorldAge(void) const
|
||||||
{
|
{
|
||||||
return std::chrono::duration_cast<cTickTimeLong>(m_WorldAge).count();
|
return std::chrono::duration_cast<cTickTimeLong>(m_WorldAge);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cWorld::SetTimeOfDay(int a_TimeOfDay)
|
cTickTimeLong cWorld::GetWorldDate() const
|
||||||
|
{
|
||||||
|
return std::chrono::duration_cast<cTickTimeLong>(m_WorldDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
cTickTimeLong cWorld::GetWorldTickAge() const
|
||||||
|
{
|
||||||
|
return m_WorldTickAge;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cWorld::SetTimeOfDay(const cTickTime a_TimeOfDay)
|
||||||
{
|
{
|
||||||
using namespace std::chrono_literals;
|
using namespace std::chrono_literals;
|
||||||
|
|
||||||
m_WorldDate = (m_WorldDate / 20min) * 20min + cTickTime(a_TimeOfDay);
|
m_WorldDate = (m_WorldDate / 20min) * 20min + a_TimeOfDay;
|
||||||
UpdateSkyDarkness();
|
UpdateSkyDarkness();
|
||||||
BroadcastTimeUpdate();
|
BroadcastTimeUpdate();
|
||||||
}
|
}
|
||||||
@ -955,7 +973,7 @@ void cWorld::Stop(cDeadlockDetect & a_DeadlockDetect)
|
|||||||
IniFile.SetValueB("Mechanics", "UseChatPrefixes", m_bUseChatPrefixes);
|
IniFile.SetValueB("Mechanics", "UseChatPrefixes", m_bUseChatPrefixes);
|
||||||
IniFile.SetValueB("General", "IsDaylightCycleEnabled", m_IsDaylightCycleEnabled);
|
IniFile.SetValueB("General", "IsDaylightCycleEnabled", m_IsDaylightCycleEnabled);
|
||||||
IniFile.SetValueI("General", "Weather", static_cast<int>(m_Weather));
|
IniFile.SetValueI("General", "Weather", static_cast<int>(m_Weather));
|
||||||
IniFile.SetValueI("General", "TimeInTicks", GetTimeOfDay());
|
IniFile.SetValueI("General", "TimeInTicks", GetWorldDate().count());
|
||||||
IniFile.SetValueI("General", "WorldAgeMS", static_cast<Int64>(m_WorldAge.count()));
|
IniFile.SetValueI("General", "WorldAgeMS", static_cast<Int64>(m_WorldAge.count()));
|
||||||
IniFile.WriteFile(m_IniFileName);
|
IniFile.WriteFile(m_IniFileName);
|
||||||
|
|
||||||
@ -988,7 +1006,7 @@ void cWorld::Tick(std::chrono::milliseconds a_Dt, std::chrono::milliseconds a_La
|
|||||||
cPluginManager::Get()->CallHookWorldTick(*this, a_Dt, a_LastTickDurationMSec);
|
cPluginManager::Get()->CallHookWorldTick(*this, a_Dt, a_LastTickDurationMSec);
|
||||||
|
|
||||||
m_WorldAge += a_Dt;
|
m_WorldAge += a_Dt;
|
||||||
m_WorldTickAge += 1;
|
m_WorldTickAge++;
|
||||||
|
|
||||||
if (m_IsDaylightCycleEnabled)
|
if (m_IsDaylightCycleEnabled)
|
||||||
{
|
{
|
||||||
@ -998,14 +1016,14 @@ void cWorld::Tick(std::chrono::milliseconds a_Dt, std::chrono::milliseconds a_La
|
|||||||
UpdateSkyDarkness();
|
UpdateSkyDarkness();
|
||||||
|
|
||||||
// Broadcast time update every 64 ticks (3.2 seconds):
|
// Broadcast time update every 64 ticks (3.2 seconds):
|
||||||
if ((m_WorldTickAge % 64) == 0)
|
if ((m_WorldTickAge % 64_tick) == 0_tick)
|
||||||
{
|
{
|
||||||
BroadcastTimeUpdate();
|
BroadcastTimeUpdate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Broadcast player list pings every 256 ticks (12.8 seconds):
|
// Broadcast player list pings every 256 ticks (12.8 seconds):
|
||||||
if ((m_WorldTickAge % 256) == 0)
|
if ((m_WorldTickAge % 256_tick) == 0_tick)
|
||||||
{
|
{
|
||||||
BroadcastPlayerListUpdatePing();
|
BroadcastPlayerListUpdatePing();
|
||||||
}
|
}
|
||||||
@ -1098,15 +1116,14 @@ void cWorld::TickMobs(std::chrono::milliseconds a_Dt)
|
|||||||
for (size_t i = 0; i < ARRAYCOUNT(AllFamilies); i++)
|
for (size_t i = 0; i < ARRAYCOUNT(AllFamilies); i++)
|
||||||
{
|
{
|
||||||
cMonster::eFamily Family = AllFamilies[i];
|
cMonster::eFamily Family = AllFamilies[i];
|
||||||
cTickTime SpawnDelay = cTickTime(cMonster::GetSpawnDelay(Family));
|
|
||||||
if (
|
if (
|
||||||
(m_LastSpawnMonster[Family] > m_WorldAge - SpawnDelay) || // Not reached the needed ticks before the next round
|
(m_LastSpawnMonster[Family] > (m_WorldTickAge - cMonster::GetSpawnDelay(Family))) || // Not reached the needed ticks before the next round
|
||||||
MobCensus.IsCapped(Family)
|
MobCensus.IsCapped(Family)
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
m_LastSpawnMonster[Family] = std::chrono::duration_cast<cTickTimeLong>(m_WorldAge);
|
m_LastSpawnMonster[Family] = m_WorldTickAge;
|
||||||
cMobSpawner Spawner(Family, m_AllowedMobs);
|
cMobSpawner Spawner(Family, m_AllowedMobs);
|
||||||
if (Spawner.CanSpawnAnything())
|
if (Spawner.CanSpawnAnything())
|
||||||
{
|
{
|
||||||
@ -1258,11 +1275,9 @@ void cWorld::TickQueuedTasks(void)
|
|||||||
|
|
||||||
// Partition everything to be executed by returning false to move to end of list if time reached
|
// Partition everything to be executed by returning false to move to end of list if time reached
|
||||||
auto MoveBeginIterator = std::partition(m_Tasks.begin(), m_Tasks.end(), [this](const decltype(m_Tasks)::value_type & a_Task)
|
auto MoveBeginIterator = std::partition(m_Tasks.begin(), m_Tasks.end(), [this](const decltype(m_Tasks)::value_type & a_Task)
|
||||||
{
|
{
|
||||||
const auto WorldAgeTicks = std::chrono::duration_cast<cTickTimeLong>(m_WorldAge).count();
|
return a_Task.first >= m_WorldAge;
|
||||||
return (a_Task.first >= WorldAgeTicks);
|
});
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
// Cut all the due tasks from m_Tasks into Tasks:
|
// Cut all the due tasks from m_Tasks into Tasks:
|
||||||
Tasks.insert(
|
Tasks.insert(
|
||||||
@ -1286,11 +1301,11 @@ void cWorld::TickQueuedTasks(void)
|
|||||||
|
|
||||||
void cWorld::UpdateSkyDarkness(void)
|
void cWorld::UpdateSkyDarkness(void)
|
||||||
{
|
{
|
||||||
const int TIME_SUNSET = 12000;
|
const auto TIME_SUNSET = 12000_tick;
|
||||||
const int TIME_NIGHT_START = 13187;
|
const auto TIME_NIGHT_START = 13187_tick;
|
||||||
const int TIME_NIGHT_END = 22812;
|
const auto TIME_NIGHT_END = 22812_tick;
|
||||||
const int TIME_SUNRISE = 23999;
|
const auto TIME_SUNRISE = 23999_tick;
|
||||||
const int TIME_SPAWN_DIVISOR = 148;
|
const auto TIME_SPAWN_DIVISOR = 148_tick;
|
||||||
|
|
||||||
const auto TempTime = GetTimeOfDay();
|
const auto TempTime = GetTimeOfDay();
|
||||||
if (TempTime <= TIME_SUNSET)
|
if (TempTime <= TIME_SUNSET)
|
||||||
@ -1448,7 +1463,7 @@ bool cWorld::GrowTreeFromSapling(Vector3i a_BlockPos)
|
|||||||
{
|
{
|
||||||
cNoise Noise(m_Generator.GetSeed());
|
cNoise Noise(m_Generator.GetSeed());
|
||||||
sSetBlockVector Logs, Other;
|
sSetBlockVector Logs, Other;
|
||||||
auto WorldAge = static_cast<int>(std::chrono::duration_cast<cTickTimeLong>(m_WorldAge).count() & 0xffffffff);
|
auto WorldAge = static_cast<int>(m_WorldTickAge.count() & 0xffffffff);
|
||||||
auto SaplingMeta = GetBlockMeta(a_BlockPos);
|
auto SaplingMeta = GetBlockMeta(a_BlockPos);
|
||||||
switch (SaplingMeta & 0x07)
|
switch (SaplingMeta & 0x07)
|
||||||
{
|
{
|
||||||
@ -1577,7 +1592,7 @@ bool cWorld::GrowTreeByBiome(const Vector3i a_BlockPos)
|
|||||||
{
|
{
|
||||||
cNoise Noise(m_Generator.GetSeed());
|
cNoise Noise(m_Generator.GetSeed());
|
||||||
sSetBlockVector Logs, Other;
|
sSetBlockVector Logs, Other;
|
||||||
auto seq = static_cast<int>(std::chrono::duration_cast<cTickTimeLong>(m_WorldAge).count() & 0xffffffff);
|
auto seq = static_cast<int>(m_WorldTickAge.count() & 0xffffffff);
|
||||||
GetTreeImageByBiome(a_BlockPos, Noise, seq, GetBiomeAt(a_BlockPos.x, a_BlockPos.z), Logs, Other);
|
GetTreeImageByBiome(a_BlockPos, Noise, seq, GetBiomeAt(a_BlockPos.x, a_BlockPos.z), Logs, Other);
|
||||||
Other.insert(Other.begin(), Logs.begin(), Logs.end());
|
Other.insert(Other.begin(), Logs.begin(), Logs.end());
|
||||||
Logs.clear();
|
Logs.clear();
|
||||||
@ -2192,7 +2207,7 @@ bool cWorld::HasChunkAnyClients(int a_ChunkX, int a_ChunkZ) const
|
|||||||
|
|
||||||
void cWorld::UnloadUnusedChunks(void)
|
void cWorld::UnloadUnusedChunks(void)
|
||||||
{
|
{
|
||||||
m_LastChunkCheck = std::chrono::duration_cast<cTickTimeLong>(m_WorldAge);
|
m_LastChunkCheck = m_WorldAge;
|
||||||
m_ChunkMap.UnloadUnusedChunks();
|
m_ChunkMap.UnloadUnusedChunks();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2668,7 +2683,7 @@ void cWorld::SaveAllChunks(void)
|
|||||||
{
|
{
|
||||||
if (IsSavingEnabled())
|
if (IsSavingEnabled())
|
||||||
{
|
{
|
||||||
m_LastSave = std::chrono::duration_cast<cTickTimeLong>(m_WorldAge);
|
m_LastSave = m_WorldAge;
|
||||||
m_ChunkMap.SaveAllChunks();
|
m_ChunkMap.SaveAllChunks();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2696,9 +2711,9 @@ void cWorld::QueueTask(std::function<void(cWorld &)> a_Task)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cWorld::ScheduleTask(int a_DelayTicks, std::function<void (cWorld &)> a_Task)
|
void cWorld::ScheduleTask(const cTickTime a_DelayTicks, std::function<void (cWorld &)> a_Task)
|
||||||
{
|
{
|
||||||
Int64 TargetTick = a_DelayTicks + std::chrono::duration_cast<cTickTimeLong>(m_WorldAge).count();
|
const auto TargetTick = a_DelayTicks + m_WorldAge;
|
||||||
|
|
||||||
// Insert the task into the list of scheduled tasks
|
// Insert the task into the list of scheduled tasks
|
||||||
{
|
{
|
||||||
|
22
src/World.h
22
src/World.h
@ -106,16 +106,11 @@ public:
|
|||||||
BroadcastTimeUpdate();
|
BroadcastTimeUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual int GetTimeOfDay(void) const override;
|
|
||||||
virtual Int64 GetWorldAge(void) const override;
|
|
||||||
|
|
||||||
void SetTicksUntilWeatherChange(int a_WeatherInterval)
|
void SetTicksUntilWeatherChange(int a_WeatherInterval)
|
||||||
{
|
{
|
||||||
m_WeatherInterval = a_WeatherInterval;
|
m_WeatherInterval = a_WeatherInterval;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void SetTimeOfDay(int a_TimeOfDay) override;
|
|
||||||
|
|
||||||
/** Returns the default weather interval for the specific weather type.
|
/** Returns the default weather interval for the specific weather type.
|
||||||
Returns -1 for any unknown weather. */
|
Returns -1 for any unknown weather. */
|
||||||
int GetDefaultWeatherInterval(eWeather a_Weather) const;
|
int GetDefaultWeatherInterval(eWeather a_Weather) const;
|
||||||
@ -150,6 +145,13 @@ public:
|
|||||||
|
|
||||||
// tolua_end
|
// tolua_end
|
||||||
|
|
||||||
|
virtual cTickTime GetTimeOfDay(void) const override;
|
||||||
|
virtual cTickTimeLong GetWorldAge(void) const override;
|
||||||
|
cTickTimeLong GetWorldDate() const;
|
||||||
|
cTickTimeLong GetWorldTickAge() const;
|
||||||
|
|
||||||
|
virtual void SetTimeOfDay(cTickTime a_TimeOfDay) override;
|
||||||
|
|
||||||
/** Retrieves the world height at the specified coords; returns false if chunk not loaded / generated */
|
/** Retrieves the world height at the specified coords; returns false if chunk not loaded / generated */
|
||||||
bool TryGetHeight(int a_BlockX, int a_BlockZ, int & a_Height); // Exported in ManualBindings.cpp
|
bool TryGetHeight(int a_BlockX, int a_BlockZ, int & a_Height); // Exported in ManualBindings.cpp
|
||||||
|
|
||||||
@ -754,7 +756,7 @@ public:
|
|||||||
void QueueTask(std::function<void(cWorld &)> a_Task); // Exported in ManualBindings.cpp
|
void QueueTask(std::function<void(cWorld &)> a_Task); // Exported in ManualBindings.cpp
|
||||||
|
|
||||||
/** Queues a lambda task onto the tick thread, with the specified delay. */
|
/** Queues a lambda task onto the tick thread, with the specified delay. */
|
||||||
void ScheduleTask(int a_DelayTicks, std::function<void(cWorld &)> a_Task);
|
void ScheduleTask(cTickTime a_DelayTicks, std::function<void(cWorld &)> a_Task);
|
||||||
|
|
||||||
/** Returns the number of chunks loaded */
|
/** Returns the number of chunks loaded */
|
||||||
size_t GetNumChunks() const; // tolua_export
|
size_t GetNumChunks() const; // tolua_export
|
||||||
@ -993,10 +995,10 @@ private:
|
|||||||
/** The time since this world began, in ticks.
|
/** The time since this world began, in ticks.
|
||||||
Monotonic, but does not persist across restarts.
|
Monotonic, but does not persist across restarts.
|
||||||
Used for less important but heavy tasks that run periodically. These tasks don't need to follow wallclock time, and slowing their rate down if TPS drops is desirable. */
|
Used for less important but heavy tasks that run periodically. These tasks don't need to follow wallclock time, and slowing their rate down if TPS drops is desirable. */
|
||||||
unsigned long long m_WorldTickAge;
|
cTickTimeLong m_WorldTickAge;
|
||||||
|
|
||||||
cTickTimeLong m_LastChunkCheck; // The last WorldAge (in ticks) in which unloading and possibly saving was triggered
|
std::chrono::milliseconds m_LastChunkCheck; // The last WorldAge in which unloading and possibly saving was triggered.
|
||||||
cTickTimeLong m_LastSave; // The last WorldAge (in ticks) in which save-all was triggerred
|
std::chrono::milliseconds m_LastSave; // The last WorldAge in which save-all was triggerred.
|
||||||
std::map<cMonster::eFamily, cTickTimeLong> m_LastSpawnMonster; // The last WorldAge (in ticks) in which a monster was spawned (for each megatype of monster) // MG TODO : find a way to optimize without creating unmaintenability (if mob IDs are becoming unrowed)
|
std::map<cMonster::eFamily, cTickTimeLong> m_LastSpawnMonster; // The last WorldAge (in ticks) in which a monster was spawned (for each megatype of monster) // MG TODO : find a way to optimize without creating unmaintenability (if mob IDs are becoming unrowed)
|
||||||
|
|
||||||
NIBBLETYPE m_SkyDarkness;
|
NIBBLETYPE m_SkyDarkness;
|
||||||
@ -1093,7 +1095,7 @@ private:
|
|||||||
cCriticalSection m_CSTasks;
|
cCriticalSection m_CSTasks;
|
||||||
|
|
||||||
/** Tasks that have been queued onto the tick thread, possibly to be executed at target tick in the future; guarded by m_CSTasks */
|
/** Tasks that have been queued onto the tick thread, possibly to be executed at target tick in the future; guarded by m_CSTasks */
|
||||||
std::vector<std::pair<Int64, std::function<void(cWorld &)>>> m_Tasks;
|
std::vector<std::pair<std::chrono::milliseconds, std::function<void(cWorld &)>>> m_Tasks;
|
||||||
|
|
||||||
/** Guards m_EntitiesToAdd */
|
/** Guards m_EntitiesToAdd */
|
||||||
cCriticalSection m_CSEntitiesToAdd;
|
cCriticalSection m_CSEntitiesToAdd;
|
||||||
|
@ -1252,7 +1252,7 @@ void NBTChunkSerializer::Serialize(const cWorld & aWorld, cChunkCoords aCoords,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Save the world age to the chunk data. Required by vanilla and mcedit.
|
// Save the world age to the chunk data. Required by vanilla and mcedit.
|
||||||
aWriter.AddLong("LastUpdate", aWorld.GetWorldAge());
|
aWriter.AddLong("LastUpdate", aWorld.GetWorldAge().count());
|
||||||
|
|
||||||
// Store the flag that the chunk has all the ores, trees, dungeons etc. Cuberite chunks are always complete.
|
// Store the flag that the chunk has all the ores, trees, dungeons etc. Cuberite chunks are always complete.
|
||||||
aWriter.AddByte("TerrainPopulated", 1);
|
aWriter.AddByte("TerrainPopulated", 1);
|
||||||
|
@ -109,8 +109,8 @@ cWSSAnvil::cWSSAnvil(cWorld * a_World, int a_CompressionFactor) :
|
|||||||
Writer.AddInt("SpawnY", FloorC(a_World->GetSpawnY()));
|
Writer.AddInt("SpawnY", FloorC(a_World->GetSpawnY()));
|
||||||
Writer.AddInt("SpawnZ", FloorC(a_World->GetSpawnZ()));
|
Writer.AddInt("SpawnZ", FloorC(a_World->GetSpawnZ()));
|
||||||
Writer.AddInt("version", 19133);
|
Writer.AddInt("version", 19133);
|
||||||
Writer.AddLong("DayTime", a_World->GetTimeOfDay());
|
Writer.AddLong("DayTime", a_World->GetWorldDate().count());
|
||||||
Writer.AddLong("Time", a_World->GetWorldAge());
|
Writer.AddLong("Time", a_World->GetWorldAge().count());
|
||||||
Writer.AddLong("SizeOnDisk", 0);
|
Writer.AddLong("SizeOnDisk", 0);
|
||||||
Writer.AddString("generatorName", "default");
|
Writer.AddString("generatorName", "default");
|
||||||
Writer.AddString("generatorOptions", "");
|
Writer.AddString("generatorOptions", "");
|
||||||
|
Loading…
Reference in New Issue
Block a user