summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/Bindings/LuaChunkStay.cpp173
-rw-r--r--src/Bindings/LuaChunkStay.h73
-rw-r--r--src/Bindings/LuaState.cpp69
-rw-r--r--src/Bindings/LuaState.h17
-rw-r--r--src/Bindings/ManualBindings.cpp49
-rw-r--r--src/Bindings/PluginLua.h28
-rw-r--r--src/CMakeLists.txt85
-rw-r--r--src/Chunk.cpp1
-rw-r--r--src/Chunk.h110
-rw-r--r--src/ChunkDef.h1
-rw-r--r--src/ChunkMap.cpp194
-rw-r--r--src/ChunkMap.h199
-rw-r--r--src/ChunkStay.cpp137
-rw-r--r--src/ChunkStay.h97
-rw-r--r--src/LightingThread.cpp163
-rw-r--r--src/LightingThread.h77
-rw-r--r--src/World.cpp12
-rw-r--r--src/World.h3
18 files changed, 1030 insertions, 458 deletions
diff --git a/src/Bindings/LuaChunkStay.cpp b/src/Bindings/LuaChunkStay.cpp
new file mode 100644
index 000000000..0e982637f
--- /dev/null
+++ b/src/Bindings/LuaChunkStay.cpp
@@ -0,0 +1,173 @@
+
+// LuaChunkStay.cpp
+
+// Implements the cLuaChunkStay class representing a cChunkStay binding for plugins, used by cWorld:ChunkStay() Lua API
+
+#include "Globals.h"
+#include "LuaChunkStay.h"
+#include "PluginLua.h"
+#include "../World.h"
+
+
+
+
+
+cLuaChunkStay::cLuaChunkStay(cPluginLua & a_Plugin) :
+ m_Plugin(a_Plugin),
+ m_LuaState(NULL)
+{
+}
+
+
+
+
+
+bool cLuaChunkStay::AddChunks(int a_ChunkCoordTableStackPos)
+{
+ // This function is expected to be called just once, with all the coords in a table
+ ASSERT(m_Chunks.empty());
+
+ cPluginLua::cOperation Op(m_Plugin);
+ cLuaState & L = Op();
+
+ // Check that we got a table:
+ if (!lua_istable(L, a_ChunkCoordTableStackPos))
+ {
+ LOGWARNING("%s: The parameter is not a table of coords (got %s). Ignoring the call.",
+ __FUNCTION__, lua_typename(L, lua_type(L, a_ChunkCoordTableStackPos))
+ );
+ L.LogStackTrace();
+ return false;
+ }
+
+ // Add each set of coords:
+ int NumChunks = luaL_getn(L, a_ChunkCoordTableStackPos);
+ m_Chunks.reserve(NumChunks);
+ for (int idx = 1; idx <= NumChunks; idx++)
+ {
+ // Push the idx-th element of the array onto stack top, check that it's a table:
+ lua_rawgeti(L, a_ChunkCoordTableStackPos, idx);
+ if (!lua_istable(L, -1))
+ {
+ LOGWARNING("%s: Element #%d is not a table (got %s). Ignoring the element.",
+ __FUNCTION__, idx, lua_typename(L, -1)
+ );
+ L.LogStackTrace();
+ lua_pop(L, 1);
+ continue;
+ }
+ AddChunkCoord(L, idx);
+ lua_pop(L, 1);
+ }
+
+ // If there are no chunks, log a warning and return failure:
+ if (m_Chunks.empty())
+ {
+ LOGWARNING("%s: Zero chunks to stay.", __FUNCTION__);
+ L.LogStackTrace();
+ return false;
+ }
+
+ // All ok
+ return true;
+}
+
+
+
+
+
+void cLuaChunkStay::AddChunkCoord(cLuaState & L, int a_Index)
+{
+ // Check that the element has 2 coords:
+ int NumCoords = luaL_getn(L, -1);
+ if (NumCoords != 2)
+ {
+ LOGWARNING("%s: Element #%d doesn't contain 2 coords (got %d). Ignoring the element.",
+ __FUNCTION__, a_Index, NumCoords
+ );
+ return;
+ }
+
+ // Read the two coords from the element:
+ lua_rawgeti(L, -1, 1);
+ lua_rawgeti(L, -2, 2);
+ int ChunkX = luaL_checkint(L, -2);
+ int ChunkZ = luaL_checkint(L, -1);
+ lua_pop(L, 2);
+
+ // Check that a coord is not yet present:
+ for (cChunkCoordsVector::iterator itr = m_Chunks.begin(), end = m_Chunks.end(); itr != end; ++itr)
+ {
+ if ((itr->m_ChunkX == ChunkX) && (itr->m_ChunkZ == ChunkZ))
+ {
+ LOGWARNING("%s: Element #%d is a duplicate, ignoring it.",
+ __FUNCTION__, a_Index
+ );
+ return;
+ }
+ } // for itr - m_Chunks[]
+
+ m_Chunks.push_back(cChunkCoords(ChunkX, ZERO_CHUNK_Y, ChunkZ));
+}
+
+
+
+
+
+void cLuaChunkStay::Enable(cChunkMap & a_ChunkMap, int a_OnChunkAvailableStackPos, int a_OnAllChunksAvailableStackPos)
+{
+ // Get the references to the callback functions:
+ m_LuaState = &m_Plugin.GetLuaState();
+ m_OnChunkAvailable.RefStack(*m_LuaState, a_OnChunkAvailableStackPos);
+ m_OnAllChunksAvailable.RefStack(*m_LuaState, a_OnAllChunksAvailableStackPos);
+
+ // Enable the ChunkStay:
+ super::Enable(a_ChunkMap);
+}
+
+
+
+
+
+void cLuaChunkStay::OnChunkAvailable(int a_ChunkX, int a_ChunkZ)
+{
+ // DEBUG:
+ LOGD("LuaChunkStay: Chunk [%d, %d] is now available, calling the callback...", a_ChunkX, a_ChunkZ);
+
+ cPluginLua::cOperation Op(m_Plugin);
+ Op().Call((int)m_OnChunkAvailable, a_ChunkX, a_ChunkZ);
+}
+
+
+
+
+
+bool cLuaChunkStay::OnAllChunksAvailable(void)
+{
+ {
+ // Call the callback:
+ cPluginLua::cOperation Op(m_Plugin);
+ Op().Call((int)m_OnAllChunksAvailable);
+
+ // Remove the callback references - they won't be needed anymore
+ m_OnChunkAvailable.UnRef();
+ m_OnAllChunksAvailable.UnRef();
+ }
+
+ // Disable the ChunkStay by returning true
+ return true;
+}
+
+
+
+
+
+void cLuaChunkStay::OnDisabled(void)
+{
+ // This object is no longer needed, delete it
+ delete this;
+}
+
+
+
+
diff --git a/src/Bindings/LuaChunkStay.h b/src/Bindings/LuaChunkStay.h
new file mode 100644
index 000000000..49ab9a0ad
--- /dev/null
+++ b/src/Bindings/LuaChunkStay.h
@@ -0,0 +1,73 @@
+
+// LuaChunkStay.h
+
+// Declares the cLuaChunkStay class representing a cChunkStay binding for plugins, used by cWorld:ChunkStay() Lua API
+
+
+
+
+
+#pragma once
+
+#include "LuaState.h"
+#include "../ChunkStay.h"
+
+
+
+
+
+// fwd:
+class cPluginLua;
+
+
+
+
+
+class cLuaChunkStay
+ : public cChunkStay
+{
+ typedef cChunkStay super;
+
+public:
+ cLuaChunkStay(cPluginLua & a_Plugin);
+
+ ~cLuaChunkStay() { }
+
+ /** Adds chunks in the specified on-stack Lua table.
+ Returns true if any chunk added, false (plus log warning) if none. */
+ bool AddChunks(int a_ChunkCoordTableStackPos);
+
+ /** Enables the ChunkStay for the specified chunkmap, with the specified Lua callbacks. */
+ void Enable(cChunkMap & a_ChunkMap, int a_OnChunkAvailableStackPos, int a_OnAllChunksAvailableStackPos);
+
+protected:
+ /** The plugin which has created the ChunkStay, via cWorld:ChunkStay() binding method. */
+ cPluginLua & m_Plugin;
+
+ /** The Lua state associated with the callbacks. Only valid when enabled. */
+ cLuaState * m_LuaState;
+
+ /** The Lua function to call in OnChunkAvailable. Only valid when enabled. */
+ cLuaState::cRef m_OnChunkAvailable;
+
+ /** The Lua function to call in OnAllChunksAvailable. Only valid when enabled. */
+ cLuaState::cRef m_OnAllChunksAvailable;
+
+
+ // cChunkStay overrides:
+ virtual void OnChunkAvailable(int a_ChunkX, int a_ChunkZ) override;
+ virtual bool OnAllChunksAvailable(void) override;
+ virtual void OnDisabled(void) override;
+
+ /** Adds a single chunk coord from the table at the top of the Lua stack.
+ Expects the top element to be a table, checks that it contains two numbers.
+ Uses those two numbers as chunk coords appended to m_Chunks.
+ If the coords are already present, gives a warning and ignores the pair.
+ The a_Index parameter is only for the error messages. */
+ void AddChunkCoord(cLuaState & a_LuaState, int a_Index);
+} ;
+
+
+
+
+
diff --git a/src/Bindings/LuaState.cpp b/src/Bindings/LuaState.cpp
index ac5ce47e1..24e64d9b2 100644
--- a/src/Bindings/LuaState.cpp
+++ b/src/Bindings/LuaState.cpp
@@ -735,17 +735,20 @@ bool cLuaState::CallFunction(int a_NumResults)
ASSERT(lua_isfunction(m_LuaState, -m_NumCurrentFunctionArgs - 1)); // The function to call
ASSERT(lua_isfunction(m_LuaState, -m_NumCurrentFunctionArgs - 2)); // The error handler
- int s = lua_pcall(m_LuaState, m_NumCurrentFunctionArgs, a_NumResults, -m_NumCurrentFunctionArgs - 2);
+ // Save the current "stack" state and reset, in case the callback calls another function:
+ AString CurrentFunctionName;
+ std::swap(m_CurrentFunctionName, CurrentFunctionName);
+ int NumArgs = m_NumCurrentFunctionArgs;
+ m_NumCurrentFunctionArgs = -1;
+
+ // Call the function:
+ int s = lua_pcall(m_LuaState, NumArgs, a_NumResults, -NumArgs - 2);
if (s != 0)
{
// The error has already been printed together with the stacktrace
- LOGWARNING("Error in %s calling function %s()", m_SubsystemName.c_str(), m_CurrentFunctionName.c_str());
- m_NumCurrentFunctionArgs = -1;
- m_CurrentFunctionName.clear();
+ LOGWARNING("Error in %s calling function %s()", m_SubsystemName.c_str(), CurrentFunctionName.c_str());
return false;
}
- m_NumCurrentFunctionArgs = -1;
- m_CurrentFunctionName.clear();
// Remove the error handler from the stack:
lua_remove(m_LuaState, -a_NumResults - 1);
@@ -1206,7 +1209,7 @@ void cLuaState::LogStack(const char * a_Header)
void cLuaState::LogStack(lua_State * a_LuaState, const char * a_Header)
{
LOGD((a_Header != NULL) ? a_Header : "Lua C API Stack contents:");
- for (int i = lua_gettop(a_LuaState); i >= 0; i--)
+ for (int i = lua_gettop(a_LuaState); i > 0; i--)
{
AString Value;
int Type = lua_type(a_LuaState, i);
@@ -1240,13 +1243,21 @@ int cLuaState::ReportFnCallErrors(lua_State * a_LuaState)
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// cLuaState::cRef:
+cLuaState::cRef::cRef(void) :
+ m_LuaState(NULL),
+ m_Ref(LUA_REFNIL)
+{
+}
+
+
+
+
+
cLuaState::cRef::cRef(cLuaState & a_LuaState, int a_StackPos) :
- m_LuaState(a_LuaState)
+ m_LuaState(NULL),
+ m_Ref(LUA_REFNIL)
{
- ASSERT(m_LuaState.IsValid());
-
- lua_pushvalue(m_LuaState, a_StackPos); // Push a copy of the value at a_StackPos onto the stack
- m_Ref = luaL_ref(m_LuaState, LUA_REGISTRYINDEX);
+ RefStack(a_LuaState, a_StackPos);
}
@@ -1255,12 +1266,42 @@ cLuaState::cRef::cRef(cLuaState & a_LuaState, int a_StackPos) :
cLuaState::cRef::~cRef()
{
- ASSERT(m_LuaState.IsValid());
+ if (m_LuaState != NULL)
+ {
+ UnRef();
+ }
+}
+
+
+
+
+
+void cLuaState::cRef::RefStack(cLuaState & a_LuaState, int a_StackPos)
+{
+ ASSERT(a_LuaState.IsValid());
+ if (m_LuaState != NULL)
+ {
+ UnRef();
+ }
+ m_LuaState = &a_LuaState;
+ lua_pushvalue(a_LuaState, a_StackPos); // Push a copy of the value at a_StackPos onto the stack
+ m_Ref = luaL_ref(a_LuaState, LUA_REGISTRYINDEX);
+}
+
+
+
+
+
+void cLuaState::cRef::UnRef(void)
+{
+ ASSERT(m_LuaState->IsValid()); // The reference should be destroyed before destroying the LuaState
if (IsValid())
{
- luaL_unref(m_LuaState, LUA_REGISTRYINDEX, m_Ref);
+ luaL_unref(*m_LuaState, LUA_REGISTRYINDEX, m_Ref);
}
+ m_LuaState = NULL;
+ m_Ref = LUA_REFNIL;
}
diff --git a/src/Bindings/LuaState.h b/src/Bindings/LuaState.h
index dda45bb28..1c9c99e69 100644
--- a/src/Bindings/LuaState.h
+++ b/src/Bindings/LuaState.h
@@ -65,14 +65,27 @@ class cLuaState
{
public:
- /** Used for storing references to object in the global registry */
+ /** Used for storing references to object in the global registry.
+ Can be bound (contains a reference) or unbound (doesn't contain reference).
+ The reference can also be reset by calling RefStack(). */
class cRef
{
public:
+ /** Creates an unbound reference object. */
+ cRef(void);
+
/** Creates a reference in the specified LuaState for object at the specified StackPos */
cRef(cLuaState & a_LuaState, int a_StackPos);
+
~cRef();
+ /** Creates a reference to Lua object at the specified stack pos, binds this object to it.
+ Calls UnRef() first if previously bound to another reference. */
+ void RefStack(cLuaState & a_LuaState, int a_StackPos);
+
+ /** Removes the bound reference, resets the object to Unbound state. */
+ void UnRef(void);
+
/** Returns true if the reference is valid */
bool IsValid(void) const {return (m_Ref != LUA_REFNIL); }
@@ -80,7 +93,7 @@ public:
operator int(void) const { return m_Ref; }
protected:
- cLuaState & m_LuaState;
+ cLuaState * m_LuaState;
int m_Ref;
} ;
diff --git a/src/Bindings/ManualBindings.cpp b/src/Bindings/ManualBindings.cpp
index 841ec5cf2..f0bad92e8 100644
--- a/src/Bindings/ManualBindings.cpp
+++ b/src/Bindings/ManualBindings.cpp
@@ -8,6 +8,7 @@
#include "PluginLua.h"
#include "PluginManager.h"
#include "LuaWindow.h"
+#include "LuaChunkStay.h"
#include "../Root.h"
#include "../World.h"
#include "../Entities/Player.h"
@@ -1638,6 +1639,53 @@ static int tolua_cPluginManager_CallPlugin(lua_State * tolua_S)
+static int tolua_cWorld_ChunkStay(lua_State * tolua_S)
+{
+ /* Function signature:
+ World:ChunkStay(ChunkCoordTable, OnChunkAvailable, OnAllChunksAvailable)
+ ChunkCoordTable == { {Chunk1x, Chunk1z}, {Chunk2x, Chunk2z}, ... }
+ */
+
+ cLuaState L(tolua_S);
+ if (
+ !L.CheckParamUserType(1, "cWorld") ||
+ !L.CheckParamTable (2) ||
+ !L.CheckParamFunction(3, 4)
+ )
+ {
+ return 0;
+ }
+
+ cPluginLua * Plugin = GetLuaPlugin(tolua_S);
+ if (Plugin == NULL)
+ {
+ return 0;
+ }
+ cLuaChunkStay * ChunkStay = new cLuaChunkStay(*Plugin);
+
+ // Read the params:
+ cWorld * World = (cWorld *)tolua_tousertype(tolua_S, 1, NULL);
+ if (World == NULL)
+ {
+ LOGWARNING("World:ChunkStay(): invalid world parameter");
+ L.LogStackTrace();
+ return 0;
+ }
+ L.LogStack("Before AddChunks()");
+ if (!ChunkStay->AddChunks(2))
+ {
+ return 0;
+ }
+ L.LogStack("After params read");
+
+ ChunkStay->Enable(*World->GetChunkMap(), 3, 4);
+ return 0;
+}
+
+
+
+
+
static int tolua_cPlayer_GetGroups(lua_State* tolua_S)
{
cPlayer* self = (cPlayer*) tolua_tousertype(tolua_S,1,0);
@@ -2360,6 +2408,7 @@ void ManualBindings::Bind(lua_State * tolua_S)
tolua_endmodule(tolua_S);
tolua_beginmodule(tolua_S, "cWorld");
+ tolua_function(tolua_S, "ChunkStay", tolua_cWorld_ChunkStay);
tolua_function(tolua_S, "DoWithBlockEntityAt", tolua_DoWithXYZ<cWorld, cBlockEntity, &cWorld::DoWithBlockEntityAt>);
tolua_function(tolua_S, "DoWithChestAt", tolua_DoWithXYZ<cWorld, cChestEntity, &cWorld::DoWithChestAt>);
tolua_function(tolua_S, "DoWithDispenserAt", tolua_DoWithXYZ<cWorld, cDispenserEntity, &cWorld::DoWithDispenserAt>);
diff --git a/src/Bindings/PluginLua.h b/src/Bindings/PluginLua.h
index ad0cfbe5a..a177f5288 100644
--- a/src/Bindings/PluginLua.h
+++ b/src/Bindings/PluginLua.h
@@ -35,7 +35,33 @@ class cPluginLua :
public:
// tolua_end
- cPluginLua( const AString & a_PluginDirectory );
+ /** A RAII-style mutex lock for accessing the internal LuaState.
+ This will be the only way to retrieve the plugin's LuaState;
+ therefore it directly supports accessing the LuaState of the locked plugin.
+ Usage:
+ cPluginLua::cOperation Op(SomePlugin);
+ Op().Call(...) // Call a function in the plugin's LuaState
+ */
+ class cOperation
+ {
+ public:
+ cOperation(cPluginLua & a_Plugin) :
+ m_Plugin(a_Plugin),
+ m_Lock(a_Plugin.m_CriticalSection)
+ {
+ }
+
+ cLuaState & operator ()(void) { return m_Plugin.m_LuaState; }
+
+ protected:
+ cPluginLua & m_Plugin;
+
+ /** RAII lock for m_Plugin.m_CriticalSection */
+ cCSLock m_Lock;
+ } ;
+
+
+ cPluginLua(const AString & a_PluginDirectory);
~cPluginLua();
virtual void OnDisable(void) override;
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 944150a44..6ba952f92 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -20,60 +20,60 @@ if (NOT MSVC)
set(BINDING_DEPENDECIES
${CMAKE_CURRENT_SOURCE_DIR}/Bindings/virtual_method_hooks.lua
${CMAKE_CURRENT_SOURCE_DIR}/Bindings/AllToLua.pkg
- ChunkDef.h
- BiomeDef.h
- OSSupport/File.h
Bindings/LuaFunctions.h
- Bindings/PluginManager.h
+ Bindings/LuaWindow.h
Bindings/Plugin.h
Bindings/PluginLua.h
+ Bindings/PluginManager.h
Bindings/WebPlugin.h
- Bindings/LuaWindow.h
+ BiomeDef.h
+ BlockArea.h
+ BlockEntities/BlockEntity.h
+ BlockEntities/BlockEntityWithItems.h
+ BlockEntities/ChestEntity.h
+ BlockEntities/DispenserEntity.h
+ BlockEntities/DropSpenserEntity.h
+ BlockEntities/DropperEntity.h
+ BlockEntities/FurnaceEntity.h
+ BlockEntities/HopperEntity.h
+ BlockEntities/JukeboxEntity.h
+ BlockEntities/NoteEntity.h
+ BlockEntities/SignEntity.h
BlockID.h
- StringUtils.h
- Defines.h
+ BoundingBox.h
ChatColor.h
+ ChunkDef.h
ClientHandle.h
+ CraftingRecipes.h
+ Cuboid.h
+ Defines.h
+ Enchantments.h
+ Entities/Effects.h
Entities/Entity.h
Entities/Floater.h
Entities/Pawn.h
- Entities/Player.h
Entities/Pickup.h
+ Entities/Player.h
Entities/ProjectileEntity.h
Entities/TNTEntity.h
- Entities/Effects.h
- Server.h
- World.h
+ Generating/ChunkDesc.h
+ Group.h
Inventory.h
- Enchantments.h
Item.h
ItemGrid.h
- BlockEntities/BlockEntity.h
- BlockEntities/BlockEntityWithItems.h
- BlockEntities/ChestEntity.h
- BlockEntities/DropSpenserEntity.h
- BlockEntities/DispenserEntity.h
- BlockEntities/DropperEntity.h
- BlockEntities/FurnaceEntity.h
- BlockEntities/HopperEntity.h
- BlockEntities/JukeboxEntity.h
- BlockEntities/NoteEntity.h
- BlockEntities/SignEntity.h
- WebAdmin.h
- Root.h
- Vector3f.h
- Vector3d.h
- Vector3i.h
Matrix4f.h
- Cuboid.h
- BoundingBox.h
+ Mobs/Monster.h
+ OSSupport/File.h
+ Root.h
+ Server.h
+ StringUtils.h
Tracer.h
- Group.h
- BlockArea.h
- Generating/ChunkDesc.h
- CraftingRecipes.h
UI/Window.h
- Mobs/Monster.h
+ Vector3d.h
+ Vector3f.h
+ Vector3i.h
+ WebAdmin.h
+ World.h
)
include_directories(Bindings)
@@ -91,7 +91,18 @@ if (NOT MSVC)
DEPENDS ${BINDING_DEPENDECIES}
)
#add cpp files here
- add_library(Bindings Bindings/PluginManager Bindings/LuaState Bindings/WebPlugin Bindings/Bindings Bindings/ManualBindings Bindings/LuaWindow Bindings/Plugin Bindings/PluginLua Bindings/WebPlugin)
+ add_library(Bindings
+ Bindings/Bindings
+ Bindings/LuaChunkStay
+ Bindings/LuaState
+ Bindings/LuaWindow
+ Bindings/ManualBindings
+ Bindings/Plugin
+ Bindings/PluginLua
+ Bindings/PluginManager
+ Bindings/WebPlugin
+ Bindings/WebPlugin
+ )
target_link_libraries(Bindings lua sqlite tolualib)
@@ -143,6 +154,7 @@ else ()
"${PATH}/*.cpp"
"${PATH}/*.h"
"${PATH}/*.rc"
+ "${PATH}/*.pkg"
)
source_group("${PATH}" FILES ${FOLDER_FILES})
endfunction(includefolder)
@@ -154,6 +166,7 @@ else ()
file(GLOB_RECURSE SOURCE
"*.cpp"
"*.h"
+ "*.pkg"
)
include_directories("${PROJECT_SOURCE_DIR}")
diff --git a/src/Chunk.cpp b/src/Chunk.cpp
index b48bfe65e..3028d24d0 100644
--- a/src/Chunk.cpp
+++ b/src/Chunk.cpp
@@ -422,7 +422,6 @@ bool cChunk::HasBlockEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ)
-/// Sets or resets the internal flag that prevents chunk from being unloaded
void cChunk::Stay(bool a_Stay)
{
m_StayCount += (a_Stay ? 1 : -1);
diff --git a/src/Chunk.h b/src/Chunk.h
index 3dc83b157..93eba217e 100644
--- a/src/Chunk.h
+++ b/src/Chunk.h
@@ -85,10 +85,10 @@ public:
void MarkLoaded(void); // Marks the chunk as freshly loaded. Fails if the chunk is already valid
void MarkLoadFailed(void); // Marks the chunk as failed to load. Ignored is the chunk is already valid
- /// Gets all chunk data, calls the a_Callback's methods for each data type
+ /** Gets all chunk data, calls the a_Callback's methods for each data type */
void GetAllData(cChunkDataCallback & a_Callback);
- /// Sets all chunk data
+ /** Sets all chunk data */
void SetAllData(
const BLOCKTYPE * a_BlockTypes,
const NIBBLETYPE * a_BlockMeta,
@@ -104,27 +104,29 @@ public:
const cChunkDef::BlockNibbles & a_SkyLight
);
- /// Copies m_BlockData into a_BlockTypes, only the block types
+ /** Copies m_BlockData into a_BlockTypes, only the block types */
void GetBlockTypes(BLOCKTYPE * a_BlockTypes);
- /// Writes the specified cBlockArea at the coords specified. Note that the coords may extend beyond the chunk!
+ /** Writes the specified cBlockArea at the coords specified. Note that the coords may extend beyond the chunk! */
void WriteBlockArea(cBlockArea & a_Area, int a_MinBlockX, int a_MinBlockY, int a_MinBlockZ, int a_DataTypes);
- /// Returns true if there is a block entity at the coords specified
+ /** Returns true if there is a block entity at the coords specified */
bool HasBlockEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ);
- /// Sets or resets the internal flag that prevents chunk from being unloaded
+ /** Sets or resets the internal flag that prevents chunk from being unloaded.
+ The flag is cumulative - it can be set multiple times and then needs to be un-set that many times
+ before the chunk is unloadable again. */
void Stay(bool a_Stay = true);
- /// Recence all mobs proximities to players in order to know what to do with them
+ /** Recence all mobs proximities to players in order to know what to do with them */
void CollectMobCensus(cMobCensus& toFill);
- /// Try to Spawn Monsters inside chunk
+ /** Try to Spawn Monsters inside chunk */
void SpawnMobs(cMobSpawner& a_MobSpawner);
void Tick(float a_Dt);
- /// Ticks a single block. Used by cWorld::TickQueuedBlocks() to tick the queued blocks
+ /** Ticks a single block. Used by cWorld::TickQueuedBlocks() to tick the queued blocks */
void TickBlock(int a_RelX, int a_RelY, int a_RelZ);
int GetPosX(void) const { return m_PosX; }
@@ -137,13 +139,13 @@ public:
// SetBlock() does a lot of work (heightmap, tickblocks, blockentities) so a BlockIdx version doesn't make sense
void SetBlock( const Vector3i & a_RelBlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta ) { SetBlock( a_RelBlockPos.x, a_RelBlockPos.y, a_RelBlockPos.z, a_BlockType, a_BlockMeta ); }
- /// Queues a block change till the specified world tick
+ /** Queues a block change till the specified world tick */
void QueueSetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Int64 a_Tick, BLOCKTYPE a_PreviousBlockType = E_BLOCK_AIR);
- /// Queues block for ticking (m_ToTickQueue)
+ /** Queues block for ticking (m_ToTickQueue) */
void QueueTickBlock(int a_RelX, int a_RelY, int a_RelZ);
- /// Queues all 6 neighbors of the specified block for ticking (m_ToTickQueue). If any are outside the chunk, relays the checking to the proper neighboring chunk
+ /** Queues all 6 neighbors of the specified block for ticking (m_ToTickQueue). If any are outside the chunk, relays the checking to the proper neighboring chunk */
void QueueTickBlockNeighbors(int a_RelX, int a_RelY, int a_RelZ);
void FastSetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType, BLOCKTYPE a_BlockMeta ); // Doesn't force block updates on neighbors, use for simple changes such as grass growing etc.
@@ -175,14 +177,14 @@ public:
void CollectPickupsByPlayer(cPlayer * a_Player);
- /// Sets the sign text. Returns true if successful. Also sends update packets to all clients in the chunk
+ /** Sets the sign text. Returns true if successful. Also sends update packets to all clients in the chunk */
bool SetSignLines(int a_RelX, int a_RelY, int a_RelZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4);
int GetHeight( int a_X, int a_Z );
void SendBlockTo(int a_RelX, int a_RelY, int a_RelZ, cClientHandle * a_Client);
- /// Adds a client to the chunk; returns true if added, false if already there
+ /** Adds a client to the chunk; returns true if added, false if already there */
bool AddClient (cClientHandle* a_Client );
void RemoveClient (cClientHandle* a_Client );
@@ -193,55 +195,55 @@ public:
void RemoveEntity(cEntity * a_Entity);
bool HasEntity(int a_EntityID);
- /// Calls the callback for each entity; returns true if all entities processed, false if the callback aborted by returning true
+ /** Calls the callback for each entity; returns true if all entities processed, false if the callback aborted by returning true */
bool ForEachEntity(cEntityCallback & a_Callback); // Lua-accessible
- /// Calls the callback if the entity with the specified ID is found, with the entity object as the callback param. Returns true if entity found.
+ /** Calls the callback if the entity with the specified ID is found, with the entity object as the callback param. Returns true if entity found. */
bool DoWithEntityByID(int a_EntityID, cEntityCallback & a_Callback, bool & a_CallbackResult); // Lua-accessible
- /// Calls the callback for each block entity; returns true if all block entities processed, false if the callback aborted by returning true
+ /** Calls the callback for each block entity; returns true if all block entities processed, false if the callback aborted by returning true */
bool ForEachBlockEntity(cBlockEntityCallback & a_Callback); // Lua-accessible
- /// Calls the callback for each chest; returns true if all chests processed, false if the callback aborted by returning true
+ /** Calls the callback for each chest; returns true if all chests processed, false if the callback aborted by returning true */
bool ForEachChest(cChestCallback & a_Callback); // Lua-accessible
- /// Calls the callback for each dispenser; returns true if all dispensers processed, false if the callback aborted by returning true
+ /** Calls the callback for each dispenser; returns true if all dispensers processed, false if the callback aborted by returning true */
bool ForEachDispenser(cDispenserCallback & a_Callback);
- /// Calls the callback for each dropper; returns true if all droppers processed, false if the callback aborted by returning true
+ /** Calls the callback for each dropper; returns true if all droppers processed, false if the callback aborted by returning true */
bool ForEachDropper(cDropperCallback & a_Callback);
- /// Calls the callback for each dropspenser; returns true if all dropspensers processed, false if the callback aborted by returning true
+ /** Calls the callback for each dropspenser; returns true if all dropspensers processed, false if the callback aborted by returning true */
bool ForEachDropSpenser(cDropSpenserCallback & a_Callback);
- /// Calls the callback for each furnace; returns true if all furnaces processed, false if the callback aborted by returning true
+ /** Calls the callback for each furnace; returns true if all furnaces processed, false if the callback aborted by returning true */
bool ForEachFurnace(cFurnaceCallback & a_Callback); // Lua-accessible
- /// Calls the callback for the block entity at the specified coords; returns false if there's no block entity at those coords, true if found
+ /** Calls the callback for the block entity at the specified coords; returns false if there's no block entity at those coords, true if found */
bool DoWithBlockEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBlockEntityCallback & a_Callback); // Lua-acessible
- /// Calls the callback for the chest at the specified coords; returns false if there's no chest at those coords, true if found
+ /** Calls the callback for the chest at the specified coords; returns false if there's no chest at those coords, true if found */
bool DoWithChestAt(int a_BlockX, int a_BlockY, int a_BlockZ, cChestCallback & a_Callback); // Lua-acessible
- /// Calls the callback for the dispenser at the specified coords; returns false if there's no dispenser at those coords or callback returns true, returns true if found
+ /** Calls the callback for the dispenser at the specified coords; returns false if there's no dispenser at those coords or callback returns true, returns true if found */
bool DoWithDispenserAt(int a_BlockX, int a_BlockY, int a_BlockZ, cDispenserCallback & a_Callback);
- /// Calls the callback for the dispenser at the specified coords; returns false if there's no dropper at those coords or callback returns true, returns true if found
+ /** Calls the callback for the dispenser at the specified coords; returns false if there's no dropper at those coords or callback returns true, returns true if found */
bool DoWithDropperAt(int a_BlockX, int a_BlockY, int a_BlockZ, cDropperCallback & a_Callback);
- /// Calls the callback for the dispenser at the specified coords; returns false if there's no dropspenser at those coords or callback returns true, returns true if found
+ /** Calls the callback for the dispenser at the specified coords; returns false if there's no dropspenser at those coords or callback returns true, returns true if found */
bool DoWithDropSpenserAt(int a_BlockX, int a_BlockY, int a_BlockZ, cDropSpenserCallback & a_Callback);
- /// Calls the callback for the furnace at the specified coords; returns false if there's no furnace at those coords or callback returns true, returns true if found
+ /** Calls the callback for the furnace at the specified coords; returns false if there's no furnace at those coords or callback returns true, returns true if found */
bool DoWithFurnaceAt(int a_BlockX, int a_BlockY, int a_BlockZ, cFurnaceCallback & a_Callback); // Lua-accessible
- /// Calls the callback for the noteblock at the specified coords; returns false if there's no noteblock at those coords or callback returns true, returns true if found
+ /** Calls the callback for the noteblock at the specified coords; returns false if there's no noteblock at those coords or callback returns true, returns true if found */
bool DoWithNoteBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cNoteBlockCallback & a_Callback);
- /// Calls the callback for the command block at the specified coords; returns false if there's no command block at those coords or callback returns true, returns true if found
+ /** Calls the callback for the command block at the specified coords; returns false if there's no command block at those coords or callback returns true, returns true if found */
bool DoWithCommandBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cCommandBlockCallback & a_Callback);
- /// Retrieves the test on the sign at the specified coords; returns false if there's no sign at those coords, true if found
+ /** Retrieves the test on the sign at the specified coords; returns false if there's no sign at those coords, true if found */
bool GetSignLines (int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4); // Lua-accessible
void UseBlockEntity(cPlayer * a_Player, int a_X, int a_Y, int a_Z); // [x, y, z] in world block coords
@@ -292,7 +294,7 @@ public:
m_IsSaving = false;
}
- /// Sets the blockticking to start at the specified block. Only one blocktick may be set, second call overwrites the first call
+ /** Sets the blockticking to start at the specified block. Only one blocktick may be set, second call overwrites the first call */
inline void SetNextBlockTick(int a_RelX, int a_RelY, int a_RelZ)
{
m_BlockTickX = a_RelX;
@@ -310,34 +312,34 @@ public:
inline NIBBLETYPE GetBlockLight(int a_Idx) const {return cChunkDef::GetNibble(m_BlockLight, a_Idx); }
inline NIBBLETYPE GetSkyLight (int a_Idx) const {return cChunkDef::GetNibble(m_BlockSkyLight, a_Idx); }
- /// Same as GetBlock(), but relative coords needn't be in this chunk (uses m_Neighbor-s or m_ChunkMap in such a case); returns true on success
+ /** Same as GetBlock(), but relative coords needn't be in this chunk (uses m_Neighbor-s or m_ChunkMap in such a case); returns true on success */
bool UnboundedRelGetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta) const;
- /// Same as GetBlockType(), but relative coords needn't be in this chunk (uses m_Neighbor-s or m_ChunkMap in such a case); returns true on success
+ /** Same as GetBlockType(), but relative coords needn't be in this chunk (uses m_Neighbor-s or m_ChunkMap in such a case); returns true on success */
bool UnboundedRelGetBlockType(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE & a_BlockType) const;
- /// Same as GetBlockMeta(), but relative coords needn't be in this chunk (uses m_Neighbor-s or m_ChunkMap in such a case); returns true on success
+ /** Same as GetBlockMeta(), but relative coords needn't be in this chunk (uses m_Neighbor-s or m_ChunkMap in such a case); returns true on success */
bool UnboundedRelGetBlockMeta(int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE & a_BlockMeta) const;
- /// Same as GetBlockBlockLight(), but relative coords needn't be in this chunk (uses m_Neighbor-s or m_ChunkMap in such a case); returns true on success
+ /** Same as GetBlockBlockLight(), but relative coords needn't be in this chunk (uses m_Neighbor-s or m_ChunkMap in such a case); returns true on success */
bool UnboundedRelGetBlockBlockLight(int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE & a_BlockLight) const;
- /// Same as GetBlockSkyLight(), but relative coords needn't be in this chunk (uses m_Neighbor-s or m_ChunkMap in such a case); returns true on success
+ /** Same as GetBlockSkyLight(), but relative coords needn't be in this chunk (uses m_Neighbor-s or m_ChunkMap in such a case); returns true on success */
bool UnboundedRelGetBlockSkyLight(int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE & a_SkyLight) const;
- /// Queries both BlockLight and SkyLight, relative coords needn't be in this chunk (uses m_Neighbor-s or m_ChunkMap in such a case); returns true on success
+ /** Queries both BlockLight and SkyLight, relative coords needn't be in this chunk (uses m_Neighbor-s or m_ChunkMap in such a case); returns true on success */
bool UnboundedRelGetBlockLights(int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE & a_BlockLight, NIBBLETYPE & a_SkyLight) const;
- /// Same as SetBlock(), but relative coords needn't be in this chunk (uses m_Neighbor-s or m_ChunkMap in such a case); returns true on success
+ /** Same as SetBlock(), but relative coords needn't be in this chunk (uses m_Neighbor-s or m_ChunkMap in such a case); returns true on success */
bool UnboundedRelSetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta);
- /// Same as FastSetBlock(), but relative coords needn't be in this chunk (uses m_Neighbor-s or m_ChunkMap in such a case); returns true on success
+ /** Same as FastSetBlock(), but relative coords needn't be in this chunk (uses m_Neighbor-s or m_ChunkMap in such a case); returns true on success */
bool UnboundedRelFastSetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta);
- /// Same as QueueTickBlock(), but relative coords needn't be in this chunk (uses m_Neighbor-s in such a case), ignores unsuccessful attempts
+ /** Same as QueueTickBlock(), but relative coords needn't be in this chunk (uses m_Neighbor-s in such a case), ignores unsuccessful attempts */
void UnboundedQueueTickBlock(int a_RelX, int a_RelY, int a_RelZ);
- /// Light alterations based on time
+ /** Light alterations based on time */
NIBBLETYPE GetTimeAlteredLight(NIBBLETYPE a_Skylight) const;
@@ -389,7 +391,7 @@ private:
cEntityList m_Entities;
cBlockEntityList m_BlockEntities;
- /// Number of times the chunk has been requested to stay (by various cChunkStay objects); if zero, the chunk can be unloaded
+ /** Number of times the chunk has been requested to stay (by various cChunkStay objects); if zero, the chunk can be unloaded */
int m_StayCount;
int m_PosX, m_PosY, m_PosZ;
@@ -427,40 +429,40 @@ private:
void RemoveBlockEntity(cBlockEntity * a_BlockEntity);
void AddBlockEntity (cBlockEntity * a_BlockEntity);
- /// Creates a block entity for each block that needs a block entity and doesn't have one in the list
+ /** Creates a block entity for each block that needs a block entity and doesn't have one in the list */
void CreateBlockEntities(void);
- /// Wakes up each simulator for its specific blocks; through all the blocks in the chunk
+ /** Wakes up each simulator for its specific blocks; through all the blocks in the chunk */
void WakeUpSimulators(void);
// Makes a copy of the list
cClientHandleList GetAllClients(void) const {return m_LoadedByClient; }
- /// Sends m_PendingSendBlocks to all clients
+ /** Sends m_PendingSendBlocks to all clients */
void BroadcastPendingBlockChanges(void);
- /// Checks the block scheduled for checking in m_ToTickBlocks[]
+ /** Checks the block scheduled for checking in m_ToTickBlocks[] */
void CheckBlocks();
- /// Ticks several random blocks in the chunk
+ /** Ticks several random blocks in the chunk */
void TickBlocks(void);
- /// Adds snow to the top of snowy biomes and hydrates farmland / fills cauldrons in rainy biomes
+ /** Adds snow to the top of snowy biomes and hydrates farmland / fills cauldrons in rainy biomes */
void ApplyWeatherToTop(void);
- /// Grows sugarcane by the specified number of blocks, but no more than 3 blocks high (used by both bonemeal and ticking)
+ /** Grows sugarcane by the specified number of blocks, but no more than 3 blocks high (used by both bonemeal and ticking) */
void GrowSugarcane (int a_RelX, int a_RelY, int a_RelZ, int a_NumBlocks);
- /// Grows cactus by the specified number of blocks, but no more than 3 blocks high (used by both bonemeal and ticking)
+ /** Grows cactus by the specified number of blocks, but no more than 3 blocks high (used by both bonemeal and ticking) */
void GrowCactus (int a_RelX, int a_RelY, int a_RelZ, int a_NumBlocks);
- /// Grows a melon or a pumpkin next to the block specified (assumed to be the stem)
+ /** Grows a melon or a pumpkin next to the block specified (assumed to be the stem) */
void GrowMelonPumpkin(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType, MTRand & a_Random);
- /// Called by Tick() when an entity moves out of this chunk into a neighbor; moves the entity and sends spawn / despawn packet to clients
+ /** Called by Tick() when an entity moves out of this chunk into a neighbor; moves the entity and sends spawn / despawn packet to clients */
void MoveEntityToNewChunk(cEntity * a_Entity);
- /// Processes all blocks that have been scheduled for replacement by the QueueSetBlock() function
+ /** Processes all blocks that have been scheduled for replacement by the QueueSetBlock() function */
void ProcessQueuedSetBlocks(void);
};
diff --git a/src/ChunkDef.h b/src/ChunkDef.h
index 1c4aa6aca..f48dc4fd5 100644
--- a/src/ChunkDef.h
+++ b/src/ChunkDef.h
@@ -481,6 +481,7 @@ public:
} ;
typedef std::list<cChunkCoords> cChunkCoordsList;
+typedef std::vector<cChunkCoords> cChunkCoordsVector;
diff --git a/src/ChunkMap.cpp b/src/ChunkMap.cpp
index 6acea903b..0c5a8d9b9 100644
--- a/src/ChunkMap.cpp
+++ b/src/ChunkMap.cpp
@@ -134,7 +134,7 @@ cChunkMap::cChunkLayer * cChunkMap::GetLayerForChunk(int a_ChunkX, int a_ChunkZ)
-cChunkPtr cChunkMap::GetChunk( int a_ChunkX, int a_ChunkY, int a_ChunkZ )
+cChunkPtr cChunkMap::GetChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
{
// No need to lock m_CSLayers, since it's already locked by the operation that called us
ASSERT(m_CSLayers.IsLockedByCurrentThread());
@@ -897,17 +897,34 @@ void cChunkMap::SetChunkData(
bool a_MarkDirty
)
{
- cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunkNoLoad(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ);
- if (Chunk == NULL)
- {
- return;
- }
- Chunk->SetAllData(a_BlockTypes, a_BlockMeta, a_BlockLight, a_BlockSkyLight, a_HeightMap, a_BiomeMap, a_BlockEntities);
-
- if (a_MarkDirty)
{
- Chunk->MarkDirty();
+ cCSLock Lock(m_CSLayers);
+ cChunkPtr Chunk = GetChunkNoLoad(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ);
+ if (Chunk == NULL)
+ {
+ return;
+ }
+ Chunk->SetAllData(a_BlockTypes, a_BlockMeta, a_BlockLight, a_BlockSkyLight, a_HeightMap, a_BiomeMap, a_BlockEntities);
+
+ if (a_MarkDirty)
+ {
+ Chunk->MarkDirty();
+ }
+
+ // Notify relevant ChunkStays:
+ for (cChunkStays::iterator itr = m_ChunkStays.begin(); itr != m_ChunkStays.end(); )
+ {
+ if ((*itr)->ChunkAvailable(a_ChunkX, a_ChunkZ))
+ {
+ cChunkStays::iterator cur = itr;
+ ++itr;
+ m_ChunkStays.erase(cur);
+ }
+ else
+ {
+ ++itr;
+ }
+ } // for itr - m_ChunkStays[]
}
// Notify plugins of the chunk becoming available
@@ -2206,24 +2223,6 @@ bool cChunkMap::SetSignLines(int a_BlockX, int a_BlockY, int a_BlockZ, const ASt
-void cChunkMap::ChunksStay(const cChunkCoordsList & a_Chunks, bool a_Stay)
-{
- cCSLock Lock(m_CSLayers);
- for (cChunkCoordsList::const_iterator itr = a_Chunks.begin(); itr != a_Chunks.end(); ++itr)
- {
- cChunkPtr Chunk = GetChunkNoLoad(itr->m_ChunkX, itr->m_ChunkY, itr->m_ChunkZ);
- if (Chunk == NULL)
- {
- continue;
- }
- Chunk->Stay(a_Stay);
- }
-}
-
-
-
-
-
void cChunkMap::MarkChunkRegenerating(int a_ChunkX, int a_ChunkZ)
{
cCSLock Lock(m_CSLayers);
@@ -2810,12 +2809,16 @@ void cChunkMap::cChunkLayer::UnloadUnusedChunks(void)
-void cChunkMap::FastSetBlock(int a_X, int a_Y, int a_Z, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
+void cChunkMap::FastSetBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
{
cCSLock Lock(m_CSFastSetBlock);
- m_FastSetBlockQueue.push_back(sSetBlock(a_X, a_Y, a_Z, a_BlockType, a_BlockMeta));
+ m_FastSetBlockQueue.push_back(sSetBlock(a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta));
}
+
+
+
+
void cChunkMap::FastSetQueuedBlocks()
{
// Asynchronously set blocks:
@@ -2834,110 +2837,75 @@ void cChunkMap::FastSetQueuedBlocks()
}
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// cChunkStay:
-
-cChunkStay::cChunkStay(cWorld * a_World) :
- m_World(a_World),
- m_IsEnabled(false)
-{
-}
-
-
-
-
-
-cChunkStay::~cChunkStay()
-{
- Clear();
-}
-
-
-
-
-
-void cChunkStay::Clear(void)
-{
- if (m_IsEnabled)
- {
- Disable();
- }
- m_Chunks.clear();
-}
-
-
-void cChunkStay::Add(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
+void cChunkMap::AddChunkStay(cChunkStay & a_ChunkStay)
{
- ASSERT(!m_IsEnabled);
-
- for (cChunkCoordsList::const_iterator itr = m_Chunks.begin(); itr != m_Chunks.end(); ++itr)
+ cCSLock Lock(m_CSLayers);
+
+ // Add it to the list:
+ ASSERT(std::find(m_ChunkStays.begin(), m_ChunkStays.end(), &a_ChunkStay) == m_ChunkStays.end()); // Has not yet been added
+ m_ChunkStays.push_back(&a_ChunkStay);
+
+ // Schedule all chunks to be loaded / generated, and mark each as locked:
+ const cChunkCoordsVector & WantedChunks = a_ChunkStay.GetChunks();
+ for (cChunkCoordsVector::const_iterator itr = WantedChunks.begin(); itr != WantedChunks.end(); ++itr)
{
- if ((itr->m_ChunkX == a_ChunkX) && (itr->m_ChunkY == a_ChunkY) && (itr->m_ChunkZ == a_ChunkZ))
+ cChunkPtr Chunk = GetChunk(itr->m_ChunkX, itr->m_ChunkY, itr->m_ChunkZ);
+ if (Chunk == NULL)
{
- // Already present
- return;
+ continue;
}
- } // for itr - Chunks[]
- m_Chunks.push_back(cChunkCoords(a_ChunkX, a_ChunkY, a_ChunkZ));
+ Chunk->Stay(true);
+ if (Chunk->IsValid())
+ {
+ a_ChunkStay.ChunkAvailable(itr->m_ChunkX, itr->m_ChunkZ);
+ }
+ } // for itr - WantedChunks[]
}
-void cChunkStay::Remove(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
+/** Removes the specified cChunkStay descendant from the internal list of ChunkStays. */
+void cChunkMap::DelChunkStay(cChunkStay & a_ChunkStay)
{
- ASSERT(!m_IsEnabled);
-
- for (cChunkCoordsList::iterator itr = m_Chunks.begin(); itr != m_Chunks.end(); ++itr)
+ cCSLock Lock(m_CSLayers);
+
+ // Remove from the list of active chunkstays:
+ bool HasFound = false;
+ for (cChunkStays::iterator itr = m_ChunkStays.begin(), end = m_ChunkStays.end(); itr != end; ++itr)
{
- if ((itr->m_ChunkX == a_ChunkX) && (itr->m_ChunkY == a_ChunkY) && (itr->m_ChunkZ == a_ChunkZ))
+ if (*itr == &a_ChunkStay)
{
- // Found, un-"stay"
- m_Chunks.erase(itr);
- return;
+ m_ChunkStays.erase(itr);
+ HasFound = true;
+ break;
}
- } // for itr - m_Chunks[]
-}
-
-
-
-
-
-void cChunkStay::Enable(void)
-{
- ASSERT(!m_IsEnabled);
+ } // for itr - m_ChunkStays[]
- m_World->ChunksStay(*this, true);
- m_IsEnabled = true;
-}
-
-
-
-
-
-void cChunkStay::Load(void)
-{
- for (cChunkCoordsList::iterator itr = m_Chunks.begin(); itr != m_Chunks.end(); ++itr)
+ if (!HasFound)
{
- m_World->TouchChunk(itr->m_ChunkX, itr->m_ChunkY, itr->m_ChunkZ);
- } // for itr - m_Chunks[]
+ ASSERT(!"Removing a cChunkStay that hasn't been added!");
+ return;
+ }
+
+ // Unmark all contained chunks:
+ const cChunkCoordsVector & Chunks = a_ChunkStay.GetChunks();
+ for (cChunkCoordsVector::const_iterator itr = Chunks.begin(), end = Chunks.end(); itr != end; ++itr)
+ {
+ cChunkPtr Chunk = GetChunkNoLoad(itr->m_ChunkX, itr->m_ChunkY, itr->m_ChunkZ);
+ if (Chunk == NULL)
+ {
+ continue;
+ }
+ Chunk->Stay(false);
+ } // for itr - Chunks[]
}
-void cChunkStay::Disable(void)
-{
- ASSERT(m_IsEnabled);
-
- m_World->ChunksStay(*this, false);
- m_IsEnabled = false;
-}
-
-
-
diff --git a/src/ChunkMap.h b/src/ChunkMap.h
index 62c74d81c..d713d0cf5 100644
--- a/src/ChunkMap.h
+++ b/src/ChunkMap.h
@@ -85,19 +85,19 @@ public:
void BroadcastThunderbolt(int a_BlockX, int a_BlockY, int a_BlockZ, const cClientHandle * a_Exclude = NULL);
void BroadcastUseBed(const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ );
- /// Sends the block entity, if it is at the coords specified, to a_Client
+ /** Sends the block entity, if it is at the coords specified, to a_Client */
void SendBlockEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cClientHandle & a_Client);
- /// a_Player rclked block entity at the coords specified, handle it
+ /** a_Player rclked block entity at the coords specified, handle it */
void UseBlockEntity(cPlayer * a_Player, int a_X, int a_Y, int a_Z);
- /// Calls the callback for the chunk specified, with ChunkMapCS locked; returns false if the chunk doesn't exist, otherwise returns the same value as the callback
+ /** Calls the callback for the chunk specified, with ChunkMapCS locked; returns false if the chunk doesn't exist, otherwise returns the same value as the callback */
bool DoWithChunk(int a_ChunkX, int a_ChunkZ, cChunkCallback & a_Callback);
- /// Wakes up simulators for the specified block
+ /** Wakes up simulators for the specified block */
void WakeUpSimulators(int a_BlockX, int a_BlockY, int a_BlockZ);
- /// Wakes up the simulators for the specified area of blocks
+ /** Wakes up the simulators for the specified area of blocks */
void WakeUpSimulatorsInArea(int a_MinBlockX, int a_MaxBlockX, int a_MinBlockY, int a_MaxBlockY, int a_MinBlockZ, int a_MaxBlockZ);
void MarkChunkDirty (int a_ChunkX, int a_ChunkZ);
@@ -130,7 +130,7 @@ public:
bool GetChunkData (int a_ChunkX, int a_ChunkZ, cChunkDataCallback & a_Callback);
- /// Copies the chunk's blocktypes into a_Blocks; returns true if successful
+ /** Copies the chunk's blocktypes into a_Blocks; returns true if successful */
bool GetChunkBlockTypes (int a_ChunkX, int a_ChunkZ, BLOCKTYPE * a_Blocks);
bool IsChunkValid (int a_ChunkX, int a_ChunkZ);
@@ -153,154 +153,151 @@ public:
bool GetBlockTypeMeta (int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta);
bool GetBlockInfo (int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_Meta, NIBBLETYPE & a_SkyLight, NIBBLETYPE & a_BlockLight);
- /// Replaces world blocks with a_Blocks, if they are of type a_FilterBlockType
+ /** Replaces world blocks with a_Blocks, if they are of type a_FilterBlockType */
void ReplaceBlocks(const sSetBlockVector & a_Blocks, BLOCKTYPE a_FilterBlockType);
- /// Special function used for growing trees, replaces only blocks that tree may overwrite
+ /** Special function used for growing trees, replaces only blocks that tree may overwrite */
void ReplaceTreeBlocks(const sSetBlockVector & a_Blocks);
EMCSBiome GetBiomeAt (int a_BlockX, int a_BlockZ);
- /// Retrieves block types of the specified blocks. If a chunk is not loaded, doesn't modify the block. Returns true if all blocks were read.
+ /** Retrieves block types of the specified blocks. If a chunk is not loaded, doesn't modify the block. Returns true if all blocks were read. */
bool GetBlocks(sSetBlockVector & a_Blocks, bool a_ContinueOnFailure);
bool DigBlock (int a_X, int a_Y, int a_Z);
void SendBlockTo(int a_X, int a_Y, int a_Z, cPlayer * a_Player);
- /// Compares clients of two chunks, calls the callback accordingly
+ /** Compares clients of two chunks, calls the callback accordingly */
void CompareChunkClients(int a_ChunkX1, int a_ChunkZ1, int a_ChunkX2, int a_ChunkZ2, cClientDiffCallback & a_Callback);
- /// Compares clients of two chunks, calls the callback accordingly
+ /** Compares clients of two chunks, calls the callback accordingly */
void CompareChunkClients(cChunk * a_Chunk1, cChunk * a_Chunk2, cClientDiffCallback & a_Callback);
- /// Adds client to a chunk, if not already present; returns true if added, false if present
+ /** Adds client to a chunk, if not already present; returns true if added, false if present */
bool AddChunkClient(int a_ChunkX, int a_ChunkZ, cClientHandle * a_Client);
- /// Removes the client from the chunk
+ /** Removes the client from the chunk */
void RemoveChunkClient(int a_ChunkX, int a_ChunkZ, cClientHandle * a_Client);
- /// Removes the client from all chunks it is present in
+ /** Removes the client from all chunks it is present in */
void RemoveClientFromChunks(cClientHandle * a_Client);
- /// Adds the entity to its appropriate chunk, takes ownership of the entity pointer
+ /** Adds the entity to its appropriate chunk, takes ownership of the entity pointer */
void AddEntity(cEntity * a_Entity);
- /// Returns true if the entity with specified ID is present in the chunks
+ /** Returns true if the entity with specified ID is present in the chunks */
bool HasEntity(int a_EntityID);
- /// Removes the entity from its appropriate chunk
+ /** Removes the entity from its appropriate chunk */
void RemoveEntity(cEntity * a_Entity);
- /// Calls the callback for each entity in the entire world; returns true if all entities processed, false if the callback aborted by returning true
+ /** Calls the callback for each entity in the entire world; returns true if all entities processed, false if the callback aborted by returning true */
bool ForEachEntity(cEntityCallback & a_Callback); // Lua-accessible
- /// Calls the callback for each entity in the specified chunk; returns true if all entities processed, false if the callback aborted by returning true
+ /** Calls the callback for each entity in the specified chunk; returns true if all entities processed, false if the callback aborted by returning true */
bool ForEachEntityInChunk(int a_ChunkX, int a_ChunkZ, cEntityCallback & a_Callback); // Lua-accessible
- /// Destroys and returns a list of blocks destroyed in the explosion at the specified coordinates
+ /** Destroys and returns a list of blocks destroyed in the explosion at the specified coordinates */
void DoExplosionAt(double a_ExplosionSize, double a_BlockX, double a_BlockY, double a_BlockZ, cVector3iArray & a_BlockAffected);
- /// Calls the callback if the entity with the specified ID is found, with the entity object as the callback param. Returns true if entity found and callback returned false.
+ /** Calls the callback if the entity with the specified ID is found, with the entity object as the callback param. Returns true if entity found and callback returned false. */
bool DoWithEntityByID(int a_UniqueID, cEntityCallback & a_Callback); // Lua-accessible
- /// Calls the callback for each block entity in the specified chunk; returns true if all block entities processed, false if the callback aborted by returning true
+ /** Calls the callback for each block entity in the specified chunk; returns true if all block entities processed, false if the callback aborted by returning true */
bool ForEachBlockEntityInChunk(int a_ChunkX, int a_ChunkZ, cBlockEntityCallback & a_Callback); // Lua-accessible
- /// Calls the callback for each chest in the specified chunk; returns true if all chests processed, false if the callback aborted by returning true
+ /** Calls the callback for each chest in the specified chunk; returns true if all chests processed, false if the callback aborted by returning true */
bool ForEachChestInChunk(int a_ChunkX, int a_ChunkZ, cChestCallback & a_Callback); // Lua-accessible
- /// Calls the callback for each dispenser in the specified chunk; returns true if all dispensers processed, false if the callback aborted by returning true
+ /** Calls the callback for each dispenser in the specified chunk; returns true if all dispensers processed, false if the callback aborted by returning true */
bool ForEachDispenserInChunk(int a_ChunkX, int a_ChunkZ, cDispenserCallback & a_Callback);
- /// Calls the callback for each dropper in the specified chunk; returns true if all droppers processed, false if the callback aborted by returning true
+ /** Calls the callback for each dropper in the specified chunk; returns true if all droppers processed, false if the callback aborted by returning true */
bool ForEachDropperInChunk(int a_ChunkX, int a_ChunkZ, cDropperCallback & a_Callback);
- /// Calls the callback for each dropspenser in the specified chunk; returns true if all dropspensers processed, false if the callback aborted by returning true
+ /** Calls the callback for each dropspenser in the specified chunk; returns true if all dropspensers processed, false if the callback aborted by returning true */
bool ForEachDropSpenserInChunk(int a_ChunkX, int a_ChunkZ, cDropSpenserCallback & a_Callback);
- /// Calls the callback for each furnace in the specified chunk; returns true if all furnaces processed, false if the callback aborted by returning true
+ /** Calls the callback for each furnace in the specified chunk; returns true if all furnaces processed, false if the callback aborted by returning true */
bool ForEachFurnaceInChunk(int a_ChunkX, int a_ChunkZ, cFurnaceCallback & a_Callback); // Lua-accessible
- /// Calls the callback for the block entity at the specified coords; returns false if there's no block entity at those coords, true if found
+ /** Calls the callback for the block entity at the specified coords; returns false if there's no block entity at those coords, true if found */
bool DoWithBlockEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBlockEntityCallback & a_Callback); // Lua-acessible
- /// Calls the callback for the chest at the specified coords; returns false if there's no chest at those coords, true if found
+ /** Calls the callback for the chest at the specified coords; returns false if there's no chest at those coords, true if found */
bool DoWithChestAt(int a_BlockX, int a_BlockY, int a_BlockZ, cChestCallback & a_Callback); // Lua-acessible
- /// Calls the callback for the dispenser at the specified coords; returns false if there's no dispenser at those coords or callback returns true, returns true if found
+ /** Calls the callback for the dispenser at the specified coords; returns false if there's no dispenser at those coords or callback returns true, returns true if found */
bool DoWithDispenserAt(int a_BlockX, int a_BlockY, int a_BlockZ, cDispenserCallback & a_Callback); // Lua-accessible
- /// Calls the callback for the dropper at the specified coords; returns false if there's no dropper at those coords or callback returns true, returns true if found
+ /** Calls the callback for the dropper at the specified coords; returns false if there's no dropper at those coords or callback returns true, returns true if found */
bool DoWithDropperAt(int a_BlockX, int a_BlockY, int a_BlockZ, cDropperCallback & a_Callback); // Lua-accessible
- /// Calls the callback for the dropspenser at the specified coords; returns false if there's no dropspenser at those coords or callback returns true, returns true if found
+ /** Calls the callback for the dropspenser at the specified coords; returns false if there's no dropspenser at those coords or callback returns true, returns true if found */
bool DoWithDropSpenserAt(int a_BlockX, int a_BlockY, int a_BlockZ, cDropSpenserCallback & a_Callback); // Lua-accessible
- /// Calls the callback for the furnace at the specified coords; returns false if there's no furnace at those coords or callback returns true, returns true if found
+ /** Calls the callback for the furnace at the specified coords; returns false if there's no furnace at those coords or callback returns true, returns true if found */
bool DoWithFurnaceAt(int a_BlockX, int a_BlockY, int a_BlockZ, cFurnaceCallback & a_Callback); // Lua-accessible
- /// Calls the callback for the noteblock at the specified coords; returns false if there's no noteblock at those coords or callback returns true, returns true if found
+ /** Calls the callback for the noteblock at the specified coords; returns false if there's no noteblock at those coords or callback returns true, returns true if found */
bool DoWithNoteBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cNoteBlockCallback & a_Callback); // Lua-accessible
- /// Calls the callback for the command block at the specified coords; returns false if there's no command block at those coords or callback returns true, returns true if found
+ /** Calls the callback for the command block at the specified coords; returns false if there's no command block at those coords or callback returns true, returns true if found */
bool DoWithCommandBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cCommandBlockCallback & a_Callback); // Lua-accessible
- /// Retrieves the test on the sign at the specified coords; returns false if there's no sign at those coords, true if found
+ /** Retrieves the test on the sign at the specified coords; returns false if there's no sign at those coords, true if found */
bool GetSignLines (int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4); // Lua-accessible
- /// Touches the chunk, causing it to be loaded or generated
+ /** Touches the chunk, causing it to be loaded or generated */
void TouchChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ);
- /// Loads the chunk, if not already loaded. Doesn't generate. Returns true if chunk valid (even if already loaded before)
+ /** Loads the chunk, if not already loaded. Doesn't generate. Returns true if chunk valid (even if already loaded before) */
bool LoadChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ);
- /// Loads the chunks specified. Doesn't report failure, other than chunks being !IsValid()
+ /** Loads the chunks specified. Doesn't report failure, other than chunks being !IsValid() */
void LoadChunks(const cChunkCoordsList & a_Chunks);
- /// Marks the chunk as failed-to-load
+ /** Marks the chunk as failed-to-load */
void ChunkLoadFailed(int a_ChunkX, int a_ChunkY, int a_ChunkZ);
- /// Sets the sign text. Returns true if sign text changed.
+ /** Sets the sign text. Returns true if sign text changed. */
bool SetSignLines(int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4);
- /// Marks (a_Stay == true) or unmarks (a_Stay == false) chunks as non-unloadable; to be used only by cChunkStay!
- void ChunksStay(const cChunkCoordsList & a_Chunks, bool a_Stay = true);
-
- /// Marks the chunk as being regenerated - all its clients want that chunk again (used by cWorld::RegenerateChunk() )
+ /** Marks the chunk as being regenerated - all its clients want that chunk again (used by cWorld::RegenerateChunk() ) */
void MarkChunkRegenerating(int a_ChunkX, int a_ChunkZ);
bool IsChunkLighted(int a_ChunkX, int a_ChunkZ);
- /// Calls the callback for each chunk in the coords specified (all cords are inclusive). Returns true if all chunks have been processed successfully
+ /** Calls the callback for each chunk in the coords specified (all cords are inclusive). Returns true if all chunks have been processed successfully */
bool ForEachChunkInRect(int a_MinChunkX, int a_MaxChunkX, int a_MinChunkZ, int a_MaxChunkZ, cChunkDataCallback & a_Callback);
- /// Writes the block area into the specified coords. Returns true if all chunks have been processed. Prefer cBlockArea::Write() instead.
+ /** Writes the block area into the specified coords. Returns true if all chunks have been processed. Prefer cBlockArea::Write() instead. */
bool WriteBlockArea(cBlockArea & a_Area, int a_MinBlockX, int a_MinBlockY, int a_MinBlockZ, int a_DataTypes);
- /// Returns the number of valid chunks and the number of dirty chunks
+ /** Returns the number of valid chunks and the number of dirty chunks */
void GetChunkStats(int & a_NumChunksValid, int & a_NumChunksDirty);
- /// Grows a melon or a pumpkin next to the block specified (assumed to be the stem)
+ /** Grows a melon or a pumpkin next to the block specified (assumed to be the stem) */
void GrowMelonPumpkin(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, MTRand & a_Rand);
- /// Grows a sugarcane present at the block specified by the amount of blocks specified, up to the max height specified in the config
+ /** Grows a sugarcane present at the block specified by the amount of blocks specified, up to the max height specified in the config */
void GrowSugarcane(int a_BlockX, int a_BlockY, int a_BlockZ, int a_NumBlocksToGrow);
- /// Grows a cactus present at the block specified by the amount of blocks specified, up to the max height specified in the config
+ /** Grows a cactus present at the block specified by the amount of blocks specified, up to the max height specified in the config */
void GrowCactus(int a_BlockX, int a_BlockY, int a_BlockZ, int a_NumBlocksToGrow);
- /// Sets the blockticking to start at the specified block. Only one blocktick per chunk may be set, second call overwrites the first call
+ /** Sets the blockticking to start at the specified block. Only one blocktick per chunk may be set, second call overwrites the first call */
void SetNextBlockTick(int a_BlockX, int a_BlockY, int a_BlockZ);
- /// Make a Mob census, of all mobs, their family, their chunk and theyr distance to closest player
+ /** Make a Mob census, of all mobs, their family, their chunk and theyr distance to closest player */
void CollectMobCensus(cMobCensus& a_ToFill);
- /// Try to Spawn Monsters inside all Chunks
+ /** Try to Spawn Monsters inside all Chunks */
void SpawnMobs(cMobSpawner& a_MobSpawner);
void Tick(float a_Dt);
- /// Ticks a single block. Used by cWorld::TickQueuedBlocks() to tick the queued blocks
+ /** Ticks a single block. Used by cWorld::TickQueuedBlocks() to tick the queued blocks */
void TickBlock(int a_BlockX, int a_BlockY, int a_BlockZ);
void UnloadUnusedChunks(void);
@@ -312,15 +309,20 @@ public:
void ChunkValidated(void); // Called by chunks that have become valid
- /// Queues the specified block for ticking (block update)
+ /** Queues the specified block for ticking (block update) */
void QueueTickBlock(int a_BlockX, int a_BlockY, int a_BlockZ);
- /// Returns the CS for locking the chunkmap; only cWorld::cLock may use this function!
+ /** Returns the CS for locking the chunkmap; only cWorld::cLock may use this function! */
cCriticalSection & GetCS(void) { return m_CSLayers; }
private:
- friend class cChunk; // The chunks can manipulate neighbors while in their Tick() method, using LockedGetBlock() and LockedSetBlock()
+ // The chunks can manipulate neighbors while in their Tick() method, using LockedGetBlock() and LockedSetBlock()
+ friend class cChunk;
+
+ // The chunkstay can (de-)register itself using AddChunkStay() and DelChunkStay()
+ friend class cChunkStay;
+
class cChunkLayer
{
@@ -328,10 +330,10 @@ private:
cChunkLayer(int a_LayerX, int a_LayerZ, cChunkMap * a_Parent);
~cChunkLayer();
- /// Always returns an assigned chunkptr, but the chunk needn't be valid (loaded / generated) - callers must check
+ /** Always returns an assigned chunkptr, but the chunk needn't be valid (loaded / generated) - callers must check */
cChunkPtr GetChunk( int a_ChunkX, int a_ChunkY, int a_ChunkZ );
- /// Returns the specified chunk, or NULL if not created yet
+ /** Returns the specified chunk, or NULL if not created yet */
cChunk * FindChunk(int a_ChunkX, int a_ChunkZ);
int GetX(void) const {return m_LayerX; }
@@ -344,22 +346,22 @@ private:
void Save(void);
void UnloadUnusedChunks(void);
- /// Collect a mob census, of all mobs, their megatype, their chunk and their distance o closest player
+ /** Collect a mob census, of all mobs, their megatype, their chunk and their distance o closest player */
void CollectMobCensus(cMobCensus& a_ToFill);
- /// Try to Spawn Monsters inside all Chunks
+ /** Try to Spawn Monsters inside all Chunks */
void SpawnMobs(cMobSpawner& a_MobSpawner);
void Tick(float a_Dt);
void RemoveClient(cClientHandle * a_Client);
- /// Calls the callback for each entity in the entire world; returns true if all entities processed, false if the callback aborted by returning true
+ /** Calls the callback for each entity in the entire world; returns true if all entities processed, false if the callback aborted by returning true */
bool ForEachEntity(cEntityCallback & a_Callback); // Lua-accessible
- /// Calls the callback if the entity with the specified ID is found, with the entity object as the callback param. Returns true if entity found.
+ /** Calls the callback if the entity with the specified ID is found, with the entity object as the callback param. Returns true if entity found. */
bool DoWithEntityByID(int a_EntityID, cEntityCallback & a_Callback, bool & a_CallbackReturn); // Lua-accessible
- /// Returns true if there is an entity with the specified ID within this layer's chunks
+ /** Returns true if there is an entity with the specified ID within this layer's chunks */
bool HasEntity(int a_EntityID);
protected:
@@ -372,17 +374,19 @@ private:
};
typedef std::list<cChunkLayer *> cChunkLayerList;
+
+ typedef std::list<cChunkStay *> cChunkStays;
- /// Finds the cChunkLayer object responsible for the specified chunk; returns NULL if not found. Assumes m_CSLayers is locked.
+ /** Finds the cChunkLayer object responsible for the specified chunk; returns NULL if not found. Assumes m_CSLayers is locked. */
cChunkLayer * FindLayerForChunk(int a_ChunkX, int a_ChunkZ);
- /// Returns the specified cChunkLayer object; returns NULL if not found. Assumes m_CSLayers is locked.
+ /** Returns the specified cChunkLayer object; returns NULL if not found. Assumes m_CSLayers is locked. */
cChunkLayer * FindLayer(int a_LayerX, int a_LayerZ);
- /// Returns the cChunkLayer object responsible for the specified chunk; creates it if not found.
+ /** Returns the cChunkLayer object responsible for the specified chunk; creates it if not found. */
cChunkLayer * GetLayerForChunk (int a_ChunkX, int a_ChunkZ);
- /// Returns the specified cChunkLayer object; creates it if not found.
+ /** Returns the specified cChunkLayer object; creates it if not found. */
cChunkLayer * GetLayer(int a_LayerX, int a_LayerZ);
void RemoveLayer(cChunkLayer * a_Layer);
@@ -395,67 +399,42 @@ private:
cCriticalSection m_CSFastSetBlock;
sSetBlockList m_FastSetBlockQueue;
+
+ /** The cChunkStay descendants that are currently enabled in this chunkmap */
+ cChunkStays m_ChunkStays;
cChunkPtr GetChunk (int a_ChunkX, int a_ChunkY, int a_ChunkZ); // Also queues the chunk for loading / generating if not valid
cChunkPtr GetChunkNoGen (int a_ChunkX, int a_ChunkY, int a_ChunkZ); // Also queues the chunk for loading if not valid; doesn't generate
cChunkPtr GetChunkNoLoad(int a_ChunkX, int a_ChunkY, int a_ChunkZ); // Doesn't load, doesn't generate
- /// Gets a block in any chunk while in the cChunk's Tick() method; returns true if successful, false if chunk not loaded (doesn't queue load)
+ /** Gets a block in any chunk while in the cChunk's Tick() method; returns true if successful, false if chunk not loaded (doesn't queue load) */
bool LockedGetBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta);
- /// Gets a block type in any chunk while in the cChunk's Tick() method; returns true if successful, false if chunk not loaded (doesn't queue load)
+ /** Gets a block type in any chunk while in the cChunk's Tick() method; returns true if successful, false if chunk not loaded (doesn't queue load) */
bool LockedGetBlockType(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE & a_BlockType);
- /// Gets a block meta in any chunk while in the cChunk's Tick() method; returns true if successful, false if chunk not loaded (doesn't queue load)
+ /** Gets a block meta in any chunk while in the cChunk's Tick() method; returns true if successful, false if chunk not loaded (doesn't queue load) */
bool LockedGetBlockMeta(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE & a_BlockMeta);
- /// Sets a block in any chunk while in the cChunk's Tick() method; returns true if successful, false if chunk not loaded (doesn't queue load)
+ /** Sets a block in any chunk while in the cChunk's Tick() method; returns true if successful, false if chunk not loaded (doesn't queue load) */
bool LockedSetBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta);
- /// Fast-sets a block in any chunk while in the cChunk's Tick() method; returns true if successful, false if chunk not loaded (doesn't queue load)
+ /** Fast-sets a block in any chunk while in the cChunk's Tick() method; returns true if successful, false if chunk not loaded (doesn't queue load) */
bool LockedFastSetBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta);
- /// Locates a chunk ptr in the chunkmap; doesn't create it when not found; assumes m_CSLayers is locked. To be called only from cChunkMap.
+ /** Locates a chunk ptr in the chunkmap; doesn't create it when not found; assumes m_CSLayers is locked. To be called only from cChunkMap. */
cChunk * FindChunk(int a_ChunkX, int a_ChunkZ);
-};
-
-
-
-
-/** Makes chunks stay loaded until this object is cleared or destroyed
-Works by setting internal flags in the cChunk that it should not be unloaded.
-To optimize for speed, cChunkStay has an Enabled flag, it will "stay" the chunks only when enabled and it will refuse manipulations when enabled
-The object itself is not made thread-safe, it's supposed to be used from a single thread only.
-*/
-class cChunkStay
-{
-public:
- cChunkStay(cWorld * a_World);
- ~cChunkStay();
-
- void Clear(void);
-
- void Add(int a_ChunkX, int a_ChunkY, int a_ChunkZ);
- void Remove(int a_ChunkX, int a_ChunkY, int a_ChunkZ);
-
- void Enable(void);
- void Disable(void);
+ /** Adds a new cChunkStay descendant to the internal list of ChunkStays; loads its chunks.
+ To be used only by cChunkStay; others should use cChunkStay::Enable() instead */
+ void AddChunkStay(cChunkStay & a_ChunkStay);
- /// Queues each chunk in m_Chunks[] for loading / generating
- void Load(void);
+ /** Removes the specified cChunkStay descendant from the internal list of ChunkStays.
+ To be used only by cChunkStay; others should use cChunkStay::Disable() instead */
+ void DelChunkStay(cChunkStay & a_ChunkStay);
- // Allow cChunkStay be passed to functions expecting a const cChunkCoordsList &
- operator const cChunkCoordsList(void) const {return m_Chunks; }
-
-protected:
+};
- cWorld * m_World;
-
- bool m_IsEnabled;
-
- cChunkCoordsList m_Chunks;
-} ;
diff --git a/src/ChunkStay.cpp b/src/ChunkStay.cpp
new file mode 100644
index 000000000..6b1d5ee34
--- /dev/null
+++ b/src/ChunkStay.cpp
@@ -0,0 +1,137 @@
+
+// ChunkStay.cpp
+
+// Implements the cChunkStay class representing a base for classes that keep chunks loaded
+
+#include "Globals.h"
+#include "ChunkStay.h"
+#include "ChunkMap.h"
+
+
+
+
+
+cChunkStay::cChunkStay(void) :
+ m_ChunkMap(NULL)
+{
+}
+
+
+
+
+
+cChunkStay::~cChunkStay()
+{
+ Clear();
+}
+
+
+
+
+
+void cChunkStay::Clear(void)
+{
+ if (m_ChunkMap != NULL)
+ {
+ Disable();
+ }
+ m_Chunks.clear();
+}
+
+
+
+
+
+void cChunkStay::Add(int a_ChunkX, int a_ChunkZ)
+{
+ ASSERT(m_ChunkMap == NULL);
+
+ for (cChunkCoordsVector::const_iterator itr = m_Chunks.begin(); itr != m_Chunks.end(); ++itr)
+ {
+ if ((itr->m_ChunkX == a_ChunkX) && (itr->m_ChunkZ == a_ChunkZ))
+ {
+ // Already present
+ return;
+ }
+ } // for itr - Chunks[]
+ m_Chunks.push_back(cChunkCoords(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ));
+}
+
+
+
+
+
+void cChunkStay::Remove(int a_ChunkX, int a_ChunkZ)
+{
+ ASSERT(m_ChunkMap == NULL);
+
+ for (cChunkCoordsVector::iterator itr = m_Chunks.begin(); itr != m_Chunks.end(); ++itr)
+ {
+ if ((itr->m_ChunkX == a_ChunkX) && (itr->m_ChunkZ == a_ChunkZ))
+ {
+ // Found, un-"stay"
+ m_Chunks.erase(itr);
+ return;
+ }
+ } // for itr - m_Chunks[]
+}
+
+
+
+
+
+void cChunkStay::Enable(cChunkMap & a_ChunkMap)
+{
+ ASSERT(m_ChunkMap == NULL);
+
+ m_OutstandingChunks = m_Chunks;
+ m_ChunkMap = &a_ChunkMap;
+ a_ChunkMap.AddChunkStay(*this);
+}
+
+
+
+
+
+void cChunkStay::Disable(void)
+{
+ ASSERT(m_ChunkMap != NULL);
+
+ m_ChunkMap->DelChunkStay(*this);
+ m_ChunkMap = NULL;
+}
+
+
+
+
+
+bool cChunkStay::ChunkAvailable(int a_ChunkX, int a_ChunkZ)
+{
+ // Check if this is a chunk that we want:
+ bool IsMine = false;
+ for (cChunkCoordsVector::iterator itr = m_OutstandingChunks.begin(), end = m_OutstandingChunks.end(); itr != end; ++itr)
+ {
+ if ((itr->m_ChunkX == a_ChunkX) && (itr->m_ChunkZ == a_ChunkZ))
+ {
+ m_OutstandingChunks.erase(itr);
+ IsMine = true;
+ break;
+ }
+ } // for itr - m_OutstandingChunks[]
+ if (!IsMine)
+ {
+ return false;
+ }
+
+ // Call the appropriate callbacks:
+ OnChunkAvailable(a_ChunkX, a_ChunkZ);
+ if (m_OutstandingChunks.empty())
+ {
+ return OnAllChunksAvailable();
+ }
+ return false;
+}
+
+
+
+
diff --git a/src/ChunkStay.h b/src/ChunkStay.h
new file mode 100644
index 000000000..80b084aee
--- /dev/null
+++ b/src/ChunkStay.h
@@ -0,0 +1,97 @@
+
+// ChunkStay.h
+
+/* Declares the cChunkStay class representing a base for classes that want to wait for certain chunks to load,
+then do some action on them. While the object is enabled, the chunks contained within are locked and will
+not unload
+*/
+
+
+
+
+
+#pragma once
+
+
+
+
+
+// fwd
+class cChunkMap;
+
+
+
+
+
+/** Makes chunks stay loaded until this object is cleared or destroyed
+Works by setting internal flags in the cChunk that it should not be unloaded.
+To optimize for speed, cChunkStay has an Enabled flag, it will "stay" the chunks only when enabled
+and it will refuse chunk-list manipulations when enabled.
+The object itself is not made thread-safe, it's supposed to be used from a single thread only.
+This class is abstract, the descendants are expected to provide the OnChunkAvailable() and
+the OnAllChunksAvailable() callback implementations. Note that those are called from the contexts of
+different threads' - the caller, the Loader or the Generator thread.
+*/
+class cChunkStay
+{
+public:
+ cChunkStay(void);
+ ~cChunkStay();
+
+ void Clear(void);
+
+ /** Adds a chunk to be locked from unloading.
+ To be used only while the ChunkStay object is not enabled. */
+ void Add(int a_ChunkX, int a_ChunkZ);
+
+ /** Releases the chunk so that it's no longer locked from unloading.
+ To be used only while the ChunkStay object is not enabled. */
+ void Remove(int a_ChunkX, int a_ChunkZ);
+
+ /** Enables the ChunkStay on the specified chunkmap, causing it to load and generate chunks.
+ All the contained chunks are queued for loading / generating. */
+ void Enable (cChunkMap & a_ChunkMap);
+
+ /** Disables the ChunkStay, the chunks are released and the ChunkStay
+ object can be edited with Add() and Remove() again*/
+ virtual void Disable(void);
+
+ /** Returns all the chunks that should be kept */
+ const cChunkCoordsVector & GetChunks(void) const { return m_Chunks; }
+
+ /** Called when a specific chunk become available. */
+ virtual void OnChunkAvailable(int a_ChunkX, int a_ChunkZ) = 0;
+
+ /** Caled once all of the contained chunks are available.
+ If returns true, the ChunkStay is automatically disabled by the ChunkMap; if it returns false, the ChunkStay is kept. */
+ virtual bool OnAllChunksAvailable(void) = 0;
+
+ /** Called by the ChunkMap when the ChunkStay is disabled. The object may choose to delete itself. */
+ virtual void OnDisabled(void) = 0;
+
+protected:
+
+ friend class cChunkMap;
+
+
+ /** The chunkmap where the object is enabled.
+ Valid only after call to Enable() and before Disable(). */
+ cChunkMap * m_ChunkMap;
+
+ /** The list of chunks to lock from unloading. */
+ cChunkCoordsVector m_Chunks;
+
+ /** The chunks that still need loading */
+ cChunkCoordsVector m_OutstandingChunks;
+
+
+ /** Called by cChunkMap when a chunk is available, checks m_NumLoaded and triggers the appropriate callbacks.
+ May be called for chunks outside this ChunkStay.
+ Returns true if the ChunkStay is to be automatically disabled by the ChunkMap; returns false to keep the ChunkStay. */
+ bool ChunkAvailable(int a_ChunkX, int a_ChunkZ);
+} ;
+
+
+
+
+
diff --git a/src/LightingThread.cpp b/src/LightingThread.cpp
index a823c08cc..9c81d004d 100644
--- a/src/LightingThread.cpp
+++ b/src/LightingThread.cpp
@@ -6,6 +6,7 @@
#include "Globals.h"
#include "LightingThread.h"
#include "ChunkMap.h"
+#include "ChunkStay.h"
#include "World.h"
@@ -109,9 +110,14 @@ void cLightingThread::Stop(void)
{
{
cCSLock Lock(m_CS);
- for (sItems::iterator itr = m_Queue.begin(), end = m_Queue.end(); itr != end; ++itr)
+ for (cChunkStays::iterator itr = m_PendingQueue.begin(), end = m_PendingQueue.end(); itr != end; ++itr)
{
- delete itr->m_ChunkStay;
+ delete *itr;
+ }
+ m_PendingQueue.clear();
+ for (cChunkStays::iterator itr = m_Queue.begin(), end = m_Queue.end(); itr != end; ++itr)
+ {
+ delete *itr;
}
m_Queue.clear();
}
@@ -129,25 +135,14 @@ void cLightingThread::QueueChunk(int a_ChunkX, int a_ChunkZ, cChunkCoordCallback
{
ASSERT(m_World != NULL); // Did you call Start() properly?
- cChunkStay * ChunkStay = new cChunkStay(m_World);
- ChunkStay->Add(a_ChunkX + 1, ZERO_CHUNK_Y, a_ChunkZ + 1);
- ChunkStay->Add(a_ChunkX + 1, ZERO_CHUNK_Y, a_ChunkZ);
- ChunkStay->Add(a_ChunkX + 1, ZERO_CHUNK_Y, a_ChunkZ - 1);
- ChunkStay->Add(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ + 1);
- ChunkStay->Add(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ);
- ChunkStay->Add(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ - 1);
- ChunkStay->Add(a_ChunkX - 1, ZERO_CHUNK_Y, a_ChunkZ + 1);
- ChunkStay->Add(a_ChunkX - 1, ZERO_CHUNK_Y, a_ChunkZ);
- ChunkStay->Add(a_ChunkX - 1, ZERO_CHUNK_Y, a_ChunkZ - 1);
- ChunkStay->Enable();
- ChunkStay->Load();
- cCSLock Lock(m_CS);
- m_Queue.push_back(sItem(a_ChunkX, a_ChunkZ, ChunkStay, a_CallbackAfter));
- if (m_Queue.size() > WARN_ON_QUEUE_SIZE)
+ cChunkStay * ChunkStay = new cLightingChunkStay(*this, a_ChunkX, a_ChunkZ, a_CallbackAfter);
{
- LOGINFO("Lighting thread overloaded, %d items in queue", m_Queue.size());
+ // The ChunkStay will enqueue itself using the QueueChunkStay() once it is fully loaded
+ // In the meantime, put it into the PendingQueue so that it can be removed when stopping the thread
+ cCSLock Lock(m_CS);
+ m_PendingQueue.push_back(ChunkStay);
}
- m_evtItemAdded.Set();
+ ChunkStay->Enable(*m_World->GetChunkMap());
}
@@ -157,7 +152,7 @@ void cLightingThread::QueueChunk(int a_ChunkX, int a_ChunkZ, cChunkCoordCallback
void cLightingThread::WaitForQueueEmpty(void)
{
cCSLock Lock(m_CS);
- while (!m_ShouldTerminate && (!m_Queue.empty() || !m_PostponedQueue.empty()))
+ while (!m_ShouldTerminate && (!m_Queue.empty() || !m_PendingQueue.empty()))
{
cCSUnlock Unlock(Lock);
m_evtQueueEmpty.Wait();
@@ -171,43 +166,7 @@ void cLightingThread::WaitForQueueEmpty(void)
size_t cLightingThread::GetQueueLength(void)
{
cCSLock Lock(m_CS);
- return m_Queue.size() + m_PostponedQueue.size();
-}
-
-
-
-
-
-void cLightingThread::ChunkReady(int a_ChunkX, int a_ChunkZ)
-{
- // Check all the items in the m_PostponedQueue, if the chunk is their neighbor, move the item to m_Queue
-
- bool NewlyAdded = false;
- {
- cCSLock Lock(m_CS);
- for (sItems::iterator itr = m_PostponedQueue.begin(); itr != m_PostponedQueue.end(); )
- {
- if (
- (itr->x - a_ChunkX >= -1) && (itr->x - a_ChunkX <= 1) &&
- (itr->z - a_ChunkZ >= -1) && (itr->z - a_ChunkZ <= 1)
- )
- {
- // It is a neighbor
- m_Queue.push_back(*itr);
- itr = m_PostponedQueue.erase(itr);
- NewlyAdded = true;
- }
- else
- {
- ++itr;
- }
- } // for itr - m_PostponedQueue[]
- } // Lock(m_CS)
-
- if (NewlyAdded)
- {
- m_evtItemAdded.Set(); // Notify the thread it has some work to do
- }
+ return m_Queue.size() + m_PendingQueue.size();
}
@@ -233,14 +192,14 @@ void cLightingThread::Execute(void)
}
// Process one items from the queue:
- sItem Item;
+ cLightingChunkStay * Item;
{
cCSLock Lock(m_CS);
if (m_Queue.empty())
{
continue;
}
- Item = m_Queue.front();
+ Item = (cLightingChunkStay *)m_Queue.front();
m_Queue.pop_front();
if (m_Queue.empty())
{
@@ -248,7 +207,7 @@ void cLightingThread::Execute(void)
}
} // CSLock(m_CS)
- LightChunk(Item);
+ LightChunk(*Item);
}
}
@@ -257,23 +216,11 @@ void cLightingThread::Execute(void)
-void cLightingThread::LightChunk(cLightingThread::sItem & a_Item)
+void cLightingThread::LightChunk(cLightingChunkStay & a_Item)
{
cChunkDef::BlockNibbles BlockLight, SkyLight;
- if (!ReadChunks(a_Item.x, a_Item.z))
- {
- // Neighbors not available. Re-queue in the postponed queue
- cCSLock Lock(m_CS);
- m_PostponedQueue.push_back(a_Item);
- return;
- }
-
- /*
- // DEBUG: torch somewhere:
- m_BlockTypes[19 + 24 * cChunkDef::Width * 3 + (m_HeightMap[24 + 24 * cChunkDef::Width * 3] / 2) * BlocksPerYLayer] = E_BLOCK_TORCH;
- // m_HeightMap[24 + 24 * cChunkDef::Width * 3]++;
- */
+ ReadChunks(a_Item.m_ChunkX, a_Item.m_ChunkZ);
PrepareBlockLight();
CalcLight(m_BlockLight);
@@ -339,13 +286,13 @@ void cLightingThread::LightChunk(cLightingThread::sItem & a_Item)
CompressLight(m_BlockLight, BlockLight);
CompressLight(m_SkyLight, SkyLight);
- m_World->ChunkLighted(a_Item.x, a_Item.z, BlockLight, SkyLight);
+ m_World->ChunkLighted(a_Item.m_ChunkX, a_Item.m_ChunkZ, BlockLight, SkyLight);
- if (a_Item.m_Callback != NULL)
+ if (a_Item.m_CallbackAfter != NULL)
{
- a_Item.m_Callback->Call(a_Item.x, a_Item.z);
+ a_Item.m_CallbackAfter->Call(a_Item.m_ChunkX, a_Item.m_ChunkZ);
}
- delete a_Item.m_ChunkStay;
+ delete &a_Item;
}
@@ -561,3 +508,63 @@ void cLightingThread::CompressLight(NIBBLETYPE * a_LightArray, NIBBLETYPE * a_Ch
+
+void cLightingThread::QueueChunkStay(cLightingChunkStay & a_ChunkStay)
+{
+ // Move the ChunkStay from the Pending queue to the lighting queue.
+ {
+ cCSLock Lock(m_CS);
+ m_PendingQueue.remove(&a_ChunkStay);
+ m_Queue.push_back(&a_ChunkStay);
+ }
+ m_evtItemAdded.Set();
+}
+
+
+
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// cLightingThread::cLightingChunkStay:
+
+cLightingThread::cLightingChunkStay::cLightingChunkStay(cLightingThread & a_LightingThread, int a_ChunkX, int a_ChunkZ, cChunkCoordCallback * a_CallbackAfter) :
+ m_LightingThread(a_LightingThread),
+ m_ChunkX(a_ChunkX),
+ m_ChunkZ(a_ChunkZ),
+ m_CallbackAfter(a_CallbackAfter)
+{
+ Add(a_ChunkX + 1, a_ChunkZ + 1);
+ Add(a_ChunkX + 1, a_ChunkZ);
+ Add(a_ChunkX + 1, a_ChunkZ - 1);
+ Add(a_ChunkX, a_ChunkZ + 1);
+ Add(a_ChunkX, a_ChunkZ);
+ Add(a_ChunkX, a_ChunkZ - 1);
+ Add(a_ChunkX - 1, a_ChunkZ + 1);
+ Add(a_ChunkX - 1, a_ChunkZ);
+ Add(a_ChunkX - 1, a_ChunkZ - 1);
+}
+
+
+
+
+
+bool cLightingThread::cLightingChunkStay::OnAllChunksAvailable(void)
+{
+ m_LightingThread.QueueChunkStay(*this);
+
+ // Keep the ChunkStay alive:
+ return false;
+}
+
+
+
+
+
+void cLightingThread::cLightingChunkStay::OnDisabled(void)
+{
+ // Nothing needed in this callback
+}
+
+
+
+
diff --git a/src/LightingThread.h b/src/LightingThread.h
index d8ce59f01..81dd9d61f 100644
--- a/src/LightingThread.h
+++ b/src/LightingThread.h
@@ -33,6 +33,7 @@ Chunks from m_PostponedQueue are moved back into m_Queue when their neighbors ge
#include "OSSupport/IsThread.h"
#include "ChunkDef.h"
+#include "ChunkStay.h"
@@ -41,9 +42,6 @@ Chunks from m_PostponedQueue are moved back into m_Queue when their neighbors ge
// fwd: "cWorld.h"
class cWorld;
-// fwd: "cChunkMap.h"
-class cChunkStay;
-
@@ -62,43 +60,50 @@ public:
void Stop(void);
- /// Queues the entire chunk for lighting
+ /** Queues the entire chunk for lighting */
void QueueChunk(int a_ChunkX, int a_ChunkZ, cChunkCoordCallback * a_CallbackAfter = NULL);
- /// Blocks until the queue is empty or the thread is terminated
+ /** Blocks until the queue is empty or the thread is terminated */
void WaitForQueueEmpty(void);
size_t GetQueueLength(void);
- /// Called from cWorld when a chunk gets valid. Chunks in m_PostponedQueue may need moving into m_Queue
- void ChunkReady(int a_ChunkX, int a_ChunkZ);
-
protected:
- struct sItem
+ class cLightingChunkStay :
+ public cChunkStay
{
- int x, z;
- cChunkStay * m_ChunkStay;
- cChunkCoordCallback * m_Callback;
+ public:
+ cLightingThread & m_LightingThread;
+ int m_ChunkX;
+ int m_ChunkZ;
+ cChunkCoordCallback * m_CallbackAfter;
- sItem(void) {} // empty default constructor needed
- sItem(int a_X, int a_Z, cChunkStay * a_ChunkStay, cChunkCoordCallback * a_Callback) :
- x(a_X),
- z(a_Z),
- m_ChunkStay(a_ChunkStay),
- m_Callback(a_Callback)
- {
- }
+ cLightingChunkStay(cLightingThread & a_LightingThread, int a_ChunkX, int a_ChunkZ, cChunkCoordCallback * a_CallbackAfter);
+
+ protected:
+ virtual void OnChunkAvailable(int a_ChunkX, int a_ChunkZ) override {}
+ virtual bool OnAllChunksAvailable(void) override;
+ virtual void OnDisabled(void) override;
} ;
- typedef std::list<sItem> sItems;
+ typedef std::list<cChunkStay *> cChunkStays;
+
- cWorld * m_World;
+ cWorld * m_World;
+
+ /** The mutex to protect m_Queue and m_PendingQueue */
cCriticalSection m_CS;
- sItems m_Queue;
- sItems m_PostponedQueue; // Chunks that have been postponed due to missing neighbors
- cEvent m_evtItemAdded; // Set when queue is appended, or to stop the thread
- cEvent m_evtQueueEmpty; // Set when the queue gets empty
+
+ /** The ChunkStays that are loaded and are waiting to be lit. */
+ cChunkStays m_Queue;
+
+ /** The ChunkStays that are waiting for load. Used for stopping the thread. */
+ cChunkStays m_PendingQueue;
+
+ cEvent m_evtItemAdded; // Set when queue is appended, or to stop the thread
+ cEvent m_evtQueueEmpty; // Set when the queue gets empty
+
// Buffers for the 3x3 chunk data
// These buffers alone are 1.7 MiB in size, therefore they cannot be located on the stack safely - some architectures may have only 1 MiB for stack, or even less
@@ -124,29 +129,29 @@ protected:
virtual void Execute(void) override;
- /// Lights the entire chunk. If neighbor chunks don't exist, touches them and re-queues the chunk
- void LightChunk(sItem & a_Item);
+ /** Lights the entire chunk. If neighbor chunks don't exist, touches them and re-queues the chunk */
+ void LightChunk(cLightingChunkStay & a_Item);
- /// Prepares m_BlockTypes and m_HeightMap data; returns false if any of the chunks fail. Zeroes out the light arrays
+ /** Prepares m_BlockTypes and m_HeightMap data; returns false if any of the chunks fail. Zeroes out the light arrays */
bool ReadChunks(int a_ChunkX, int a_ChunkZ);
- /// Uses m_HeightMap to initialize the m_SkyLight[] data; fills in seeds for the skylight
+ /** Uses m_HeightMap to initialize the m_SkyLight[] data; fills in seeds for the skylight */
void PrepareSkyLight(void);
- /// Uses m_BlockTypes to initialize the m_BlockLight[] data; fills in seeds for the blocklight
+ /** Uses m_BlockTypes to initialize the m_BlockLight[] data; fills in seeds for the blocklight */
void PrepareBlockLight(void);
- /// Calculates light in the light array specified, using stored seeds
+ /** Calculates light in the light array specified, using stored seeds */
void CalcLight(NIBBLETYPE * a_Light);
- /// Does one step in the light calculation - one seed propagation and seed recalculation
+ /** Does one step in the light calculation - one seed propagation and seed recalculation */
void CalcLightStep(
NIBBLETYPE * a_Light,
int a_NumSeedsIn, unsigned char * a_IsSeedIn, unsigned int * a_SeedIdxIn,
int & a_NumSeedsOut, unsigned char * a_IsSeedOut, unsigned int * a_SeedIdxOut
);
- /// Compresses from 1-block-per-byte (faster calc) into 2-blocks-per-byte (MC storage):
+ /** Compresses from 1-block-per-byte (faster calc) into 2-blocks-per-byte (MC storage): */
void CompressLight(NIBBLETYPE * a_LightArray, NIBBLETYPE * a_ChunkLight);
inline void PropagateLight(
@@ -174,6 +179,10 @@ protected:
}
}
+ /** Queues a chunkstay that has all of its chunks loaded.
+ Called by cLightingChunkStay when all of its chunks are loaded. */
+ void QueueChunkStay(cLightingChunkStay & a_ChunkStay);
+
} ;
diff --git a/src/World.cpp b/src/World.cpp
index 662a9a4b8..c2149e4c0 100644
--- a/src/World.cpp
+++ b/src/World.cpp
@@ -2148,9 +2148,6 @@ void cWorld::SetChunkData(
{
m_ChunkSender.ChunkReady(a_ChunkX, a_ChunkZ);
}
-
- // Notify the lighting thread that the chunk has become valid (in case it is a neighbor of a postponed chunk):
- m_Lighting.ChunkReady(a_ChunkX, a_ChunkZ);
}
@@ -2564,15 +2561,6 @@ bool cWorld::SetCommandBlockCommand(int a_BlockX, int a_BlockY, int a_BlockZ, co
-void cWorld::ChunksStay(const cChunkCoordsList & a_Chunks, bool a_Stay)
-{
- m_ChunkMap->ChunksStay(a_Chunks, a_Stay);
-}
-
-
-
-
-
void cWorld::RegenerateChunk(int a_ChunkX, int a_ChunkZ)
{
m_ChunkMap->MarkChunkRegenerating(a_ChunkX, a_ChunkZ);
diff --git a/src/World.h b/src/World.h
index 0174be03b..26f3993e0 100644
--- a/src/World.h
+++ b/src/World.h
@@ -320,9 +320,6 @@ public:
/** Sets the command block command. Returns true if command changed. */
bool SetCommandBlockCommand(int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Command); // tolua_export
- /** Marks (a_Stay == true) or unmarks (a_Stay == false) chunks as non-unloadable. To be used only by cChunkStay! */
- void ChunksStay(const cChunkCoordsList & a_Chunks, bool a_Stay = true);
-
/** Regenerate the given chunk: */
void RegenerateChunk(int a_ChunkX, int a_ChunkZ); // tolua_export