summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--MCServer/Plugins/APIDump/APIDesc.lua8
-rw-r--r--MCServer/Plugins/ChunkWorx/chunkworx_main.lua2
-rw-r--r--MCServer/Plugins/ChunkWorx/chunkworx_web.lua2
m---------MCServer/Plugins/Core0
-rw-r--r--MCServer/Plugins/Debuggers/Debuggers.lua40
-rw-r--r--Tools/ProtoProxy/.gitignore1
-rw-r--r--src/Chunk.cpp32
-rw-r--r--src/Chunk.h8
-rw-r--r--src/ChunkMap.cpp61
-rw-r--r--src/ChunkMap.h9
-rw-r--r--src/ForEachChunkProvider.h27
-rw-r--r--src/World.cpp41
-rw-r--r--src/World.h32
13 files changed, 253 insertions, 10 deletions
diff --git a/MCServer/Plugins/APIDump/APIDesc.lua b/MCServer/Plugins/APIDump/APIDesc.lua
index 33e98df69..fd4b1d947 100644
--- a/MCServer/Plugins/APIDump/APIDesc.lua
+++ b/MCServer/Plugins/APIDump/APIDesc.lua
@@ -2045,6 +2045,7 @@ end
AreCommandBlocksEnabled = { Params = "", Return = "bool", Notes = "Returns whether command blocks are enabled on the (entire) server" },
BroadcastBlockAction = { Params = "BlockX, BlockY, BlockZ, ActionByte1, ActionByte2, BlockType, [{{cClientHandle|ExcludeClient}}]", Return = "", Notes = "Broadcasts the BlockAction packet to all clients who have the appropriate chunk loaded (except ExcludeClient). The contents of the packet are specified by the parameters for the call, the blocktype needn't match the actual block that is present in the world data at the specified location." },
BroadcastChat = { Params = "Message, [{{cClientHandle|ExcludeClient}}]", Return = "", Notes = "Sends the Message to all players in this world, except the optional ExcludeClient. No formatting is done by the server." },
+ BroadcastChatDeath = { Params = "Message, [{{cClientHandle|ExcludeClient}}]", Return = "", Notes = "Prepends Gray [DEATH] / colours entire text (depending on ShouldUseChatPrefixes()) and broadcasts message. For when a player dies." },
BroadcastChatFailure = { Params = "Message, [{{cClientHandle|ExcludeClient}}]", Return = "", Notes = "Prepends Rose [INFO] / colours entire text (depending on ShouldUseChatPrefixes()) and broadcasts message. For a command that failed to run because of insufficient permissions, etc." },
BroadcastChatFatal = { Params = "Message, [{{cClientHandle|ExcludeClient}}]", Return = "", Notes = "Prepends Red [FATAL] / colours entire text (depending on ShouldUseChatPrefixes()) and broadcasts message. For a plugin that crashed, or similar." },
BroadcastChatInfo = { Params = "Message, [{{cClientHandle|ExcludeClient}}]", Return = "", Notes = "Prepends Yellow [INFO] / colours entire text (depending on ShouldUseChatPrefixes()) and broadcasts message. For informational messages, such as command usage." },
@@ -2061,6 +2062,7 @@ end
DoExplosionAt = { Params = "Force, X, Y, Z, CanCauseFire, Source, SourceData", Return = "", Notes = "Creates an explosion of the specified relative force in the specified position. If CanCauseFire is set, the explosion will set blocks on fire, too. The Source parameter specifies the source of the explosion, one of the esXXX constants. The SourceData parameter is specific to each source type, usually it provides more info about the source." },
DoWithBlockEntityAt = { Params = "X, Y, Z, CallbackFunction, [CallbackData]", Return = "bool", Notes = "If there is a block entity at the specified coords, calls the CallbackFunction with the {{cBlockEntity}} parameter representing the block entity. The CallbackFunction has the following signature: <pre class=\"prettyprint lang-lua\">function Callback({{cBlockEntity|BlockEntity}}, [CallbackData])</pre> The function returns false if there is no block entity, or if there is, it returns the bool value that the callback has returned. Use {{tolua}}.cast() to cast the Callback's BlockEntity parameter to the correct {{cBlockEntity}} descendant." },
DoWithChestAt = { Params = "X, Y, Z, CallbackFunction, [CallbackData]", Return = "bool", Notes = "If there is a chest at the specified coords, calls the CallbackFunction with the {{cChestEntity}} parameter representing the chest. The CallbackFunction has the following signature: <pre class=\"prettyprint lang-lua\">function Callback({{cChestEntity|ChestEntity}}, [CallbackData])</pre> The function returns false if there is no chest, or if there is, it returns the bool value that the callback has returned." },
+ DoWithCommandBlockAt = { Params = "X, Y, Z, CallbackFunction, [CallbackData]", Return = "bool", Notes = "If there is a command block at the specified coords, calls the CallbackFunction with the {{cCommandBlockEntity}} parameter representing the command block. The CallbackFunction has the following signature: <pre class=\"prettyprint lang-lua\">function Callback({{cCommandBlockEntity|CommandBlockEntity}}, [CallbackData])</pre> The function returns false if there is no command block, or if there is, it returns the bool value that the callback has returned." },
DoWithDispenserAt = { Params = "X, Y, Z, CallbackFunction, [CallbackData]", Return = "bool", Notes = "If there is a dispenser at the specified coords, calls the CallbackFunction with the {{cDispenserEntity}} parameter representing the dispenser. The CallbackFunction has the following signature: <pre class=\"prettyprint lang-lua\">function Callback({{cDispenserEntity|DispenserEntity}}, [CallbackData])</pre> The function returns false if there is no dispenser, or if there is, it returns the bool value that the callback has returned." },
DoWithDropSpenserAt = { Params = "X, Y, Z, CallbackFunction, [CallbackData]", Return = "bool", Notes = "If there is a dropper or a dispenser at the specified coords, calls the CallbackFunction with the {{cDropSpenserEntity}} parameter representing the dropper or dispenser. The CallbackFunction has the following signature: <pre class=\"prettyprint lang-lua\">function Callback({{cDropSpenserEntity|DropSpenserEntity}}, [CallbackData])</pre> Note that this can be used to access both dispensers and droppers in a similar way. The function returns false if there is neither dispenser nor dropper, or if there is, it returns the bool value that the callback has returned." },
DoWithDropperAt = { Params = "X, Y, Z, CallbackFunction, [CallbackData]", Return = "bool", Notes = "If there is a dropper at the specified coords, calls the CallbackFunction with the {{cDropperEntity}} parameter representing the dropper. The CallbackFunction has the following signature: <pre class=\"prettyprint lang-lua\">function Callback({{cDropperEntity|DropperEntity}}, [CallbackData])</pre> The function returns false if there is no dropper, or if there is, it returns the bool value that the callback has returned." },
@@ -2106,6 +2108,7 @@ end
GetMaxSugarcaneHeight = { Params = "", Return = "number", Notes = "Returns the configured maximum height to which sugarcane will grow naturally." },
GetName = { Params = "", Return = "string", Notes = "Returns the name of the world, as specified in the settings.ini file." },
GetNumChunks = { Params = "", Return = "number", Notes = "Returns the number of chunks currently loaded." },
+ GetScoreBoard = { Params = "", Return = "{{cScoreBoard}}", Notes = "Returns the {{cScoreBoard|ScoreBoard}} object used by this world. " },
GetSignLines = { Params = "BlockX, BlockY, BlockZ", Return = "IsValid, [Line1, Line2, Line3, Line4]", Notes = "Returns true and the lines of a sign at the specified coords, or false if there is no sign at the coords." },
GetSpawnX = { Params = "", Return = "number", Notes = "Returns the X coord of the default spawn" },
GetSpawnY = { Params = "", Return = "number", Notes = "Returns the Y coord of the default spawn" },
@@ -2141,6 +2144,11 @@ end
RegenerateChunk = { Params = "ChunkX, ChunkZ", Return = "", Notes = "Queues the specified chunk to be re-generated, overwriting the current data. To queue a chunk for generating only if it doesn't exist, use the GenerateChunk() instead." },
ScheduleTask = { Params = "DelayTicks, TaskFunction", Return = "", Notes = "Queues the specified function to be executed in the world's tick thread after a the specified number of ticks. This enables operations to be queued for execution in the future. The function signature is <pre class=\"pretty-print lang-lua\">function({{cWorld|World}})</pre>All return values from the function are ignored. Note that it is unsafe to store references to MCServer objects, such as entities, across from the caller to the task handler function; store the EntityID instead." },
SendBlockTo = { Params = "BlockX, BlockY, BlockZ, {{cPlayer|Player}}", Return = "", Notes = "Sends the block at the specified coords to the specified player's client, as an UpdateBlock packet." },
+ SetAreaBiome = {
+ { Params = "MinX, MaxX, MinZ, MaxZ, EMCSBiome", Return = "bool", Notes = "Sets the biome in the rectangular area specified. Returns true if successful, false if any of the chunks were unloaded." },
+ { Params = "{{cCuboid|Cuboid}}, EMCSBiome", Return = "bool", Notes = "Sets the biome in the cuboid specified. Returns true if successful, false if any of the chunks were unloaded. The cuboid needn't be sorted." },
+ },
+ SetBiomeAt = { Params = "BlockX, BlockZ, EMCSBiome", Return = "bool", Notes = "Sets the biome at the specified block coords. Returns true if successful, false otherwise." },
SetBlock = { Params = "BlockX, BlockY, BlockZ, BlockType, BlockMeta", Return = "", Notes = "Sets the block at the specified coords, replaces the block entities for the previous block type, creates a new block entity for the new block, if appropriate, and wakes up the simulators. This is the preferred way to set blocks, as opposed to FastSetBlock(), which is only to be used under special circumstances." },
SetBlockMeta =
{
diff --git a/MCServer/Plugins/ChunkWorx/chunkworx_main.lua b/MCServer/Plugins/ChunkWorx/chunkworx_main.lua
index f74c4ea2d..88ecb3979 100644
--- a/MCServer/Plugins/ChunkWorx/chunkworx_main.lua
+++ b/MCServer/Plugins/ChunkWorx/chunkworx_main.lua
@@ -122,7 +122,7 @@ function OnTick( DeltaTime )
end
end
WW_instance:QueueSaveAllChunks()
- WW_instance:UnloadUnusedChunks()
+ WW_instance:QueueUnloadUnusedChunks()
end
end
end \ No newline at end of file
diff --git a/MCServer/Plugins/ChunkWorx/chunkworx_web.lua b/MCServer/Plugins/ChunkWorx/chunkworx_web.lua
index 44993f81c..6c5eab676 100644
--- a/MCServer/Plugins/ChunkWorx/chunkworx_web.lua
+++ b/MCServer/Plugins/ChunkWorx/chunkworx_web.lua
@@ -44,7 +44,7 @@ function HandleRequest_Generation( Request )
if (Request.PostParams["AGHRRRR"] ~= nil) then
GENERATION_STATE = 0
WW_instance:SaveAllChunks()
- WW_instance:UnloadUnusedChunks()
+ WW_instance:QueueUnloadUnusedChunks()
LOGERROR("" .. PLUGIN:GetName() .. " v" .. PLUGIN:GetVersion() .. ": works ABORTED by admin")
end
--Content = Content .. "<head><meta http-equiv=\"refresh\" content=\"2;\"></head>"
diff --git a/MCServer/Plugins/Core b/MCServer/Plugins/Core
-Subproject 5c8557d4fdfa580c100510cde07a1a778ea2e24
+Subproject 3b416b07a339b3abcbc127070d56eea05b05373
diff --git a/MCServer/Plugins/Debuggers/Debuggers.lua b/MCServer/Plugins/Debuggers/Debuggers.lua
index 60e84c947..66894d835 100644
--- a/MCServer/Plugins/Debuggers/Debuggers.lua
+++ b/MCServer/Plugins/Debuggers/Debuggers.lua
@@ -55,6 +55,7 @@ function Initialize(Plugin)
PM:BindCommand("/sched", "debuggers", HandleSched, "- Schedules a simple countdown using cWorld:ScheduleTask()");
PM:BindCommand("/cs", "debuggers", HandleChunkStay, "- Tests the ChunkStay Lua integration for the specified chunk coords");
PM:BindCommand("/compo", "debuggers", HandleCompo, "- Tests the cCompositeChat bindings")
+ PM:BindCommand("/sb", "debuggers", HandleSetBiome, "- Sets the biome around you to the specified one");
Plugin:AddWebTab("Debuggers", HandleRequest_Debuggers)
Plugin:AddWebTab("StressTest", HandleRequest_StressTest)
@@ -1218,3 +1219,42 @@ end
+
+function HandleSetBiome(a_Split, a_Player)
+ local Biome = biJungle
+ local Size = 20
+ local SplitSize = #a_Split
+ if (SplitSize > 3) then
+ a_Player:SendMessage("Too many parameters. Usage: " .. a_Split[1] .. " <BiomeType>")
+ return true
+ end
+
+ if (SplitSize >= 2) then
+ Biome = StringToBiome(a_Split[2])
+ if (Biome == biInvalidBiome) then
+ a_Player:SendMessage("Unknown biome: '" .. a_Split[2] .. "'. Command ignored.")
+ return true
+ end
+ end
+ if (SplitSize >= 3) then
+ Size = tostring(a_Split[3])
+ if (Size == nil) then
+ a_Player:SendMessage("Unknown size: '" .. a_Split[3] .. "'. Command ignored.")
+ return true
+ end
+ end
+
+ local BlockX = math.floor(a_Player:GetPosX())
+ local BlockZ = math.floor(a_Player:GetPosZ())
+ a_Player:GetWorld():SetAreaBiome(BlockX - Size, BlockX + Size, BlockZ - Size, BlockZ + Size, Biome)
+ a_Player:SendMessage(
+ "Blocks {" .. (BlockX - Size) .. ", " .. (BlockZ - Size) ..
+ "} - {" .. (BlockX + Size) .. ", " .. (BlockZ + Size) ..
+ "} set to biome #" .. tostring(Biome) .. "."
+ )
+ return true
+end
+
+
+
+
diff --git a/Tools/ProtoProxy/.gitignore b/Tools/ProtoProxy/.gitignore
index 8def77d0b..158a30080 100644
--- a/Tools/ProtoProxy/.gitignore
+++ b/Tools/ProtoProxy/.gitignore
@@ -1,6 +1,7 @@
Debug
Release
Logs/
+lib/
*.log
*.nbt
*.sln
diff --git a/src/Chunk.cpp b/src/Chunk.cpp
index 3028d24d0..0587beb9c 100644
--- a/src/Chunk.cpp
+++ b/src/Chunk.cpp
@@ -1652,6 +1652,38 @@ void cChunk::UseBlockEntity(cPlayer * a_Player, int a_X, int a_Y, int a_Z)
+void cChunk::SetBiomeAt(int a_RelX, int a_RelZ, EMCSBiome a_Biome)
+{
+ cChunkDef::SetBiome(m_BiomeMap, a_RelX, a_RelZ, a_Biome);
+ MarkDirty();
+}
+
+
+
+
+
+void cChunk::SetAreaBiome(int a_MinRelX, int a_MaxRelX, int a_MinRelZ, int a_MaxRelZ, EMCSBiome a_Biome)
+{
+ for (int z = a_MinRelZ; z <= a_MaxRelZ; z++)
+ {
+ for (int x = a_MinRelX; x <= a_MaxRelX; x++)
+ {
+ cChunkDef::SetBiome(m_BiomeMap, x, z, a_Biome);
+ }
+ }
+ MarkDirty();
+
+ // Re-send the chunk to all clients:
+ for (cClientHandleList::iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr)
+ {
+ m_World->ForceSendChunkTo(m_PosX, m_PosZ, (*itr));
+ } // for itr - m_LoadedByClient[]
+}
+
+
+
+
+
void cChunk::CollectPickupsByPlayer(cPlayer * a_Player)
{
double PosX = a_Player->GetPosX();
diff --git a/src/Chunk.h b/src/Chunk.h
index 696690068..682ec6170 100644
--- a/src/Chunk.h
+++ b/src/Chunk.h
@@ -175,6 +175,14 @@ public:
EMCSBiome GetBiomeAt(int a_RelX, int a_RelZ) const {return cChunkDef::GetBiome(m_BiomeMap, a_RelX, a_RelZ); }
+ /** Sets the biome at the specified relative coords.
+ Doesn't resend the chunk to clients. */
+ void SetBiomeAt(int a_RelX, int a_RelZ, EMCSBiome a_Biome);
+
+ /** Sets the biome in the specified relative coords area. All the coords are inclusive.
+ Sends the chunk to all relevant clients. */
+ void SetAreaBiome(int a_MinRelX, int a_MaxRelX, int a_MinRelZ, int a_MaxRelZ, EMCSBiome a_Biome);
+
void CollectPickupsByPlayer(cPlayer * a_Player);
/** Sets the sign text. Returns true if successful. Also sends update packets to all clients in the chunk */
diff --git a/src/ChunkMap.cpp b/src/ChunkMap.cpp
index 0c5a8d9b9..01195e8bc 100644
--- a/src/ChunkMap.cpp
+++ b/src/ChunkMap.cpp
@@ -1390,10 +1390,10 @@ void cChunkMap::ReplaceTreeBlocks(const sSetBlockVector & a_Blocks)
EMCSBiome cChunkMap::GetBiomeAt (int a_BlockX, int a_BlockZ)
{
int ChunkX, ChunkZ, X = a_BlockX, Y = 0, Z = a_BlockZ;
- cChunkDef::AbsoluteToRelative( X, Y, Z, ChunkX, ChunkZ );
+ cChunkDef::AbsoluteToRelative(X, Y, Z, ChunkX, ChunkZ);
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunk( ChunkX, ZERO_CHUNK_Y, ChunkZ );
+ cChunkPtr Chunk = GetChunk(ChunkX, ZERO_CHUNK_Y, ChunkZ);
if ((Chunk != NULL) && Chunk->IsValid())
{
return Chunk->GetBiomeAt(X, Z);
@@ -1408,6 +1408,63 @@ EMCSBiome cChunkMap::GetBiomeAt (int a_BlockX, int a_BlockZ)
+bool cChunkMap::SetBiomeAt(int a_BlockX, int a_BlockZ, EMCSBiome a_Biome)
+{
+ int ChunkX, ChunkZ, X = a_BlockX, Y = 0, Z = a_BlockZ;
+ cChunkDef::AbsoluteToRelative(X, Y, Z, ChunkX, ChunkZ);
+
+ cCSLock Lock(m_CSLayers);
+ cChunkPtr Chunk = GetChunk(ChunkX, ZERO_CHUNK_Y, ChunkZ);
+ if ((Chunk != NULL) && Chunk->IsValid())
+ {
+ Chunk->SetBiomeAt(X, Z, a_Biome);
+ return true;
+ }
+ return false;
+}
+
+
+
+
+
+bool cChunkMap::SetAreaBiome(int a_MinX, int a_MaxX, int a_MinZ, int a_MaxZ, EMCSBiome a_Biome)
+{
+ // Translate coords to relative:
+ int Y = 0;
+ int MinChunkX, MinChunkZ, MinX = a_MinX, MinZ = a_MinZ;
+ int MaxChunkX, MaxChunkZ, MaxX = a_MaxX, MaxZ = a_MaxZ;
+ cChunkDef::AbsoluteToRelative(MinX, Y, MinZ, MinChunkX, MinChunkZ);
+ cChunkDef::AbsoluteToRelative(MaxX, Y, MaxZ, MaxChunkX, MaxChunkZ);
+
+ // Go through all chunks, set:
+ bool res = true;
+ cCSLock Lock(m_CSLayers);
+ for (int x = MinChunkX; x <= MaxChunkX; x++)
+ {
+ int MinRelX = (x == MinChunkX) ? MinX : 0;
+ int MaxRelX = (x == MaxChunkX) ? MaxX : cChunkDef::Width - 1;
+ for (int z = MinChunkZ; z <= MaxChunkZ; z++)
+ {
+ int MinRelZ = (z == MinChunkZ) ? MinZ : 0;
+ int MaxRelZ = (z == MaxChunkZ) ? MaxZ : cChunkDef::Width - 1;
+ cChunkPtr Chunk = GetChunkNoLoad(x, ZERO_CHUNK_Y, z);
+ if ((Chunk != NULL) && Chunk->IsValid())
+ {
+ Chunk->SetAreaBiome(MinRelX, MaxRelX, MinRelZ, MaxRelZ, a_Biome);
+ }
+ else
+ {
+ res = false;
+ }
+ } // for z
+ } // for x
+ return res;
+}
+
+
+
+
+
bool cChunkMap::GetBlocks(sSetBlockVector & a_Blocks, bool a_ContinueOnFailure)
{
bool res = true;
diff --git a/src/ChunkMap.h b/src/ChunkMap.h
index d713d0cf5..9f0dd087e 100644
--- a/src/ChunkMap.h
+++ b/src/ChunkMap.h
@@ -159,8 +159,17 @@ public:
/** Special function used for growing trees, replaces only blocks that tree may overwrite */
void ReplaceTreeBlocks(const sSetBlockVector & a_Blocks);
+ /** Returns the biome at the specified coords. Reads the biome from the chunk, if loaded, otherwise uses the world generator to provide the biome value */
EMCSBiome GetBiomeAt (int a_BlockX, int a_BlockZ);
+ /** Sets the biome at the specified coords. Returns true if successful, false if not (chunk not loaded).
+ Doesn't resend the chunk to clients. */
+ bool SetBiomeAt(int a_BlockX, int a_BlockZ, EMCSBiome a_Biome);
+
+ /** Sets the biome at the area. Returns true if successful, false if any subarea failed (chunk not loaded).
+ (Re)sends the chunks to their relevant clients if successful. */
+ bool SetAreaBiome(int a_MinX, int a_MaxX, int a_MinZ, int a_MaxZ, EMCSBiome a_Biome);
+
/** 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);
diff --git a/src/ForEachChunkProvider.h b/src/ForEachChunkProvider.h
index 70cd2196a..6017173ee 100644
--- a/src/ForEachChunkProvider.h
+++ b/src/ForEachChunkProvider.h
@@ -1,14 +1,39 @@
+// ForEachChunkProvider.h
+
+// Declares the cForEachChunkProvider class which acts as an interface for classes that provide a ForEachChunkInRect() function
+// Primarily serves as a decoupling between cBlockArea and cWorld
+
+
+
+
+
#pragma once
-class cChunkDataCallback;
+
+
+// fwd:
+class cChunkDataCallback;
class cBlockArea;
+
+
+
+
class cForEachChunkProvider
{
public:
+ /** Calls the callback for each chunk in the specified range. */
virtual bool ForEachChunkInRect(int a_MinChunkX, int a_MaxChunkX, int a_MinChunkZ, int a_MaxChunkZ, cChunkDataCallback & a_Callback) = 0;
+ /** Writes the block area into the specified coords.
+ Returns true if all chunks have been processed.
+ a_DataTypes is a bitmask of cBlockArea::baXXX constants ORed together.
+ */
virtual bool WriteBlockArea(cBlockArea & a_Area, int a_MinBlockX, int a_MinBlockY, int a_MinBlockZ, int a_DataTypes) = 0;
};
+
+
+
+
diff --git a/src/World.cpp b/src/World.cpp
index d67ad36d1..e57675c44 100644
--- a/src/World.cpp
+++ b/src/World.cpp
@@ -1487,6 +1487,37 @@ EMCSBiome cWorld::GetBiomeAt (int a_BlockX, int a_BlockZ)
+bool cWorld::SetBiomeAt(int a_BlockX, int a_BlockZ, EMCSBiome a_Biome)
+{
+ return m_ChunkMap->SetBiomeAt(a_BlockX, a_BlockZ, a_Biome);
+}
+
+
+
+
+
+bool cWorld::SetAreaBiome(int a_MinX, int a_MaxX, int a_MinZ, int a_MaxZ, EMCSBiome a_Biome)
+{
+ return m_ChunkMap->SetAreaBiome(a_MinX, a_MaxX, a_MinZ, a_MaxZ, a_Biome);
+}
+
+
+
+
+
+bool cWorld::SetAreaBiome(const cCuboid & a_Area, EMCSBiome a_Biome)
+{
+ return SetAreaBiome(
+ std::min(a_Area.p1.x, a_Area.p2.x), std::max(a_Area.p1.x, a_Area.p2.x),
+ std::min(a_Area.p1.z, a_Area.p2.z), std::max(a_Area.p1.z, a_Area.p2.z),
+ a_Biome
+ );
+}
+
+
+
+
+
void cWorld::SetBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
{
m_ChunkMap->SetBlock(*this, a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta);
@@ -2490,6 +2521,16 @@ void cWorld::SendChunkTo(int a_ChunkX, int a_ChunkZ, cClientHandle * a_Client)
+void cWorld::ForceSendChunkTo(int a_ChunkX, int a_ChunkZ, cClientHandle * a_Client)
+{
+ a_Client->AddWantedChunk(a_ChunkX, a_ChunkZ);
+ m_ChunkSender.QueueSendChunkTo(a_ChunkX, a_ChunkZ, a_Client);
+}
+
+
+
+
+
void cWorld::RemoveClientFromChunkSender(cClientHandle * a_Client)
{
m_ChunkSender.RemoveClient(a_Client);
diff --git a/src/World.h b/src/World.h
index 97358b88a..d79de3b87 100644
--- a/src/World.h
+++ b/src/World.h
@@ -47,6 +47,7 @@ class cFurnaceEntity;
class cNoteEntity;
class cMobCensus;
class cCompositeChat;
+class cCuboid;
typedef std::list< cPlayer * > cPlayerList;
@@ -64,7 +65,10 @@ typedef cItemCallback<cCommandBlockEntity> cCommandBlockCallback;
// tolua_begin
-class cWorld : public cForEachChunkProvider, public cWorldInterface, public cBroadcastInterface
+class cWorld :
+ public cForEachChunkProvider,
+ public cWorldInterface,
+ public cBroadcastInterface
{
public:
@@ -303,9 +307,14 @@ public:
/** Removes the client from all chunks it is present in */
void RemoveClientFromChunks(cClientHandle * a_Client);
- /** Sends the chunk to the client specified, if the chunk is valid. If not valid, the request is postponed (ChunkSender will send that chunk when it becomes valid+lighted) */
+ /** Sends the chunk to the client specified, if the client doesn't have the chunk yet.
+ If chunk not valid, the request is postponed (ChunkSender will send that chunk when it becomes valid + lighted). */
void SendChunkTo(int a_ChunkX, int a_ChunkZ, cClientHandle * a_Client);
+ /** Sends the chunk to the client specified, even if the client already has the chunk.
+ If the chunk's not valid, the request is postponed (ChunkSender will send that chunk when it becomes valid + lighted). */
+ void ForceSendChunkTo(int a_ChunkX, int a_ChunkZ, cClientHandle * a_Client);
+
/** Removes client from ChunkSender's queue of chunks to be sent */
void RemoveClientFromChunkSender(cClientHandle * a_Client);
@@ -401,15 +410,15 @@ public:
Prefer cBlockArea::Write() instead, this is the internal implementation; cBlockArea does error checking, too.
a_DataTypes is a bitmask of cBlockArea::baXXX constants ORed together.
*/
- virtual bool WriteBlockArea(cBlockArea & a_Area, int a_MinBlockX, int a_MinBlockY, int a_MinBlockZ, int a_DataTypes);
+ virtual bool WriteBlockArea(cBlockArea & a_Area, int a_MinBlockX, int a_MinBlockY, int a_MinBlockZ, int a_DataTypes) override;
// tolua_begin
/** Spawns item pickups for each item in the list. May compress pickups if too many entities: */
- virtual void SpawnItemPickups(const cItems & a_Pickups, double a_BlockX, double a_BlockY, double a_BlockZ, double a_FlyAwaySpeed = 1.0, bool IsPlayerCreated = false);
+ virtual void SpawnItemPickups(const cItems & a_Pickups, double a_BlockX, double a_BlockY, double a_BlockZ, double a_FlyAwaySpeed = 1.0, bool IsPlayerCreated = false); // override; cannot specify it here due to tolua
/** Spawns item pickups for each item in the list. May compress pickups if too many entities. All pickups get the speed specified: */
- virtual void SpawnItemPickups(const cItems & a_Pickups, double a_BlockX, double a_BlockY, double a_BlockZ, double a_SpeedX, double a_SpeedY, double a_SpeedZ, bool IsPlayerCreated = false);
+ virtual void SpawnItemPickups(const cItems & a_Pickups, double a_BlockX, double a_BlockY, double a_BlockZ, double a_SpeedX, double a_SpeedY, double a_SpeedZ, bool IsPlayerCreated = false); // override; cannot specify it here due to tolua
/** Spawns an falling block entity at the given position. It returns the UniqueID of the spawned falling block. */
int SpawnFallingBlock(int a_X, int a_Y, int a_Z, BLOCKTYPE BlockType, NIBBLETYPE BlockMeta);
@@ -546,6 +555,19 @@ public:
/** Returns the biome at the specified coords. Reads the biome from the chunk, if loaded, otherwise uses the world generator to provide the biome value */
EMCSBiome GetBiomeAt(int a_BlockX, int a_BlockZ);
+
+ /** Sets the biome at the specified coords. Returns true if successful, false if not (chunk not loaded).
+ Doesn't resend the chunk to clients, use ForceSendChunkTo() for that. */
+ bool SetBiomeAt(int a_BlockX, int a_BlockZ, EMCSBiome a_Biome);
+
+ /** Sets the biome at the area. Returns true if successful, false if any subarea failed (chunk not loaded).
+ (Re)sends the chunks to their relevant clients if successful. */
+ bool SetAreaBiome(int a_MinX, int a_MaxX, int a_MinZ, int a_MaxZ, EMCSBiome a_Biome);
+
+ /** Sets the biome at the area. Returns true if successful, false if any subarea failed (chunk not loaded).
+ (Re)sends the chunks to their relevant clients if successful.
+ The cuboid needn't be sorted. */
+ bool SetAreaBiome(const cCuboid & a_Area, EMCSBiome a_Biome);
/** Returns the name of the world */
const AString & GetName(void) const { return m_WorldName; }