summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Bindings/ManualBindings.cpp32
-rw-r--r--src/Bindings/PluginLua.cpp83
-rw-r--r--src/Bindings/PluginLua.h83
-rw-r--r--src/Blocks/BlockPiston.cpp16
-rw-r--r--src/Blocks/BlockPiston.h2
-rw-r--r--src/CheckBasicStyle.lua6
-rw-r--r--src/Entities/ArrowEntity.cpp13
-rw-r--r--src/Entities/Entity.cpp10
-rw-r--r--src/Entities/ProjectileEntity.cpp7
-rw-r--r--src/Generating/BioGen.cpp36
-rw-r--r--src/Generating/IntGen.h68
-rw-r--r--src/World.cpp30
-rw-r--r--src/World.h51
13 files changed, 287 insertions, 150 deletions
diff --git a/src/Bindings/ManualBindings.cpp b/src/Bindings/ManualBindings.cpp
index 035be55ae..cdc01ae09 100644
--- a/src/Bindings/ManualBindings.cpp
+++ b/src/Bindings/ManualBindings.cpp
@@ -1299,23 +1299,27 @@ tolua_lerror:
class cLuaWorldTask :
- public cWorld::cTask
+ public cWorld::cTask,
+ public cPluginLua::cResettable
{
public:
cLuaWorldTask(cPluginLua & a_Plugin, int a_FnRef) :
- m_Plugin(a_Plugin),
+ cPluginLua::cResettable(a_Plugin),
m_FnRef(a_FnRef)
{
}
protected:
- cPluginLua & m_Plugin;
int m_FnRef;
// cWorld::cTask overrides:
virtual void Run(cWorld & a_World) override
{
- m_Plugin.Call(m_FnRef, &a_World);
+ cCSLock Lock(m_CSPlugin);
+ if (m_Plugin != nullptr)
+ {
+ m_Plugin->Call(m_FnRef, &a_World);
+ }
}
} ;
@@ -1354,7 +1358,9 @@ static int tolua_cWorld_QueueTask(lua_State * tolua_S)
return lua_do_error(tolua_S, "Error in function call '#funcname#': Could not get function reference of parameter #1");
}
- self->QueueTask(make_unique<cLuaWorldTask>(*Plugin, FnRef));
+ auto task = std::make_shared<cLuaWorldTask>(*Plugin, FnRef);
+ Plugin->AddResettable(task);
+ self->QueueTask(task);
return 0;
}
@@ -1363,23 +1369,27 @@ static int tolua_cWorld_QueueTask(lua_State * tolua_S)
class cLuaScheduledWorldTask :
- public cWorld::cTask
+ public cWorld::cTask,
+ public cPluginLua::cResettable
{
public:
cLuaScheduledWorldTask(cPluginLua & a_Plugin, int a_FnRef) :
- m_Plugin(a_Plugin),
+ cPluginLua::cResettable(a_Plugin),
m_FnRef(a_FnRef)
{
}
protected:
- cPluginLua & m_Plugin;
int m_FnRef;
// cWorld::cTask overrides:
virtual void Run(cWorld & a_World) override
{
- m_Plugin.Call(m_FnRef, &a_World);
+ cCSLock Lock(m_CSPlugin);
+ if (m_Plugin != nullptr)
+ {
+ m_Plugin->Call(m_FnRef, &a_World);
+ }
}
};
@@ -1425,7 +1435,9 @@ static int tolua_cWorld_ScheduleTask(lua_State * tolua_S)
int DelayTicks = (int)tolua_tonumber(tolua_S, 2, 0);
- World->ScheduleTask(DelayTicks, new cLuaScheduledWorldTask(*Plugin, FnRef));
+ auto task = std::make_shared<cLuaScheduledWorldTask>(*Plugin, FnRef);
+ Plugin->AddResettable(task);
+ World->ScheduleTask(DelayTicks, task);
return 0;
}
diff --git a/src/Bindings/PluginLua.cpp b/src/Bindings/PluginLua.cpp
index 263d1f005..0a2a8411d 100644
--- a/src/Bindings/PluginLua.cpp
+++ b/src/Bindings/PluginLua.cpp
@@ -6,10 +6,11 @@
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
#ifdef __APPLE__
-#define LUA_USE_MACOSX
+ #define LUA_USE_MACOSX
#else
-#define LUA_USE_POSIX
+ #define LUA_USE_POSIX
#endif
+
#include "PluginLua.h"
#include "../CommandOutput.h"
#include "PluginManager.h"
@@ -52,24 +53,40 @@ cPluginLua::~cPluginLua()
void cPluginLua::Close(void)
{
- if (m_LuaState.IsValid())
- {
- // Release all the references in the hook map:
- for (cHookMap::iterator itrH = m_HookMap.begin(), endH = m_HookMap.end(); itrH != endH; ++itrH)
- {
- for (cLuaRefs::iterator itrR = itrH->second.begin(), endR = itrH->second.end(); itrR != endR; ++itrR)
- {
- delete *itrR;
- } // for itrR - itrH->second[]
- } // for itrH - m_HookMap[]
- m_HookMap.clear();
-
- m_LuaState.Close();
- }
- else
+ cCSLock Lock(m_CriticalSection);
+
+ // If already closed, bail out:
+ if (!m_LuaState.IsValid())
{
+ ASSERT(m_Resettables.empty());
ASSERT(m_HookMap.empty());
+ return;
}
+
+ // Notify and remove all m_Resettables (unlock the m_CriticalSection while resetting them):
+ cResettablePtrs resettables;
+ std::swap(m_Resettables, resettables);
+ {
+ cCSUnlock Unlock(Lock);
+ for (auto resettable: resettables)
+ {
+ resettable->Reset();
+ }
+ m_Resettables.clear();
+ } // cCSUnlock (m_CriticalSection)
+
+ // Release all the references in the hook map:
+ for (cHookMap::iterator itrH = m_HookMap.begin(), endH = m_HookMap.end(); itrH != endH; ++itrH)
+ {
+ for (cLuaRefs::iterator itrR = itrH->second.begin(), endR = itrH->second.end(); itrR != endR; ++itrR)
+ {
+ delete *itrR;
+ } // for itrR - itrH->second[]
+ } // for itrH - m_HookMap[]
+ m_HookMap.clear();
+
+ // Close the Lua engine:
+ m_LuaState.Close();
}
@@ -1709,6 +1726,16 @@ int cPluginLua::CallFunctionFromForeignState(
+void cPluginLua::AddResettable(cPluginLua::cResettablePtr a_Resettable)
+{
+ cCSLock Lock(m_CriticalSection);
+ m_Resettables.push_back(a_Resettable);
+}
+
+
+
+
+
AString cPluginLua::HandleWebRequest(const HTTPRequest * a_Request)
{
cCSLock Lock(m_CriticalSection);
@@ -1826,3 +1853,25 @@ void cPluginLua::CallbackWindowSlotChanged(int a_FnRef, cWindow & a_Window, int
+
+////////////////////////////////////////////////////////////////////////////////
+// cPluginLua::cResettable:
+
+cPluginLua::cResettable::cResettable(cPluginLua & a_Plugin):
+ m_Plugin(&a_Plugin)
+{
+}
+
+
+
+
+
+void cPluginLua::cResettable::Reset(void)
+{
+ cCSLock Lock(m_CSPlugin);
+ m_Plugin = nullptr;
+}
+
+
+
+
diff --git a/src/Bindings/PluginLua.h b/src/Bindings/PluginLua.h
index 4f3529fc9..c14b02687 100644
--- a/src/Bindings/PluginLua.h
+++ b/src/Bindings/PluginLua.h
@@ -59,6 +59,37 @@ public:
/** RAII lock for m_Plugin.m_CriticalSection */
cCSLock m_Lock;
} ;
+
+
+
+ /** A base class that represents something related to a plugin
+ The plugin can reset this class so that the instance can continue to exist but will not engage the (possibly non-existent) plugin anymore.
+ This is used for scheduled tasks etc., so that they can be queued and reset when the plugin is terminated, without removing them from the queue. */
+ class cResettable
+ {
+ public:
+ /** Creates a new instance bound to the specified plugin. */
+ cResettable(cPluginLua & a_Plugin);
+
+ // Force a virtual destructor in descendants:
+ virtual ~cResettable() {}
+
+ /** Resets the plugin instance stored within.
+ The instance will continue to exist, but should not call into the plugin anymore. */
+ virtual void Reset(void);
+
+ protected:
+ /** The plugin that this instance references.
+ If nullptr, the plugin has already unloaded and the instance should bail out any processing.
+ Protected against multithreaded access by m_CSPlugin. */
+ cPluginLua * m_Plugin;
+
+ /** The mutex protecting m_Plugin against multithreaded access. */
+ cCriticalSection m_CSPlugin;
+ };
+
+ typedef SharedPtr<cResettable> cResettablePtr;
+ typedef std::vector<cResettablePtr> cResettablePtrs;
cPluginLua(const AString & a_PluginDirectory);
@@ -187,42 +218,16 @@ public:
int a_ParamEnd
);
- // The following templates allow calls to arbitrary Lua functions residing in the plugin:
-
- /** Call a Lua function with 0 args */
- template <typename FnT> bool Call(FnT a_Fn)
- {
- cCSLock Lock(m_CriticalSection);
- return m_LuaState.Call(a_Fn);
- }
-
- /** Call a Lua function with 1 arg */
- template <typename FnT, typename ArgT0> bool Call(FnT a_Fn, ArgT0 a_Arg0)
+ /** Call a Lua function residing in the plugin. */
+ template <typename FnT, typename... Args>
+ bool Call(FnT a_Fn, Args && ... a_Args)
{
cCSLock Lock(m_CriticalSection);
- return m_LuaState.Call(a_Fn, a_Arg0);
+ return m_LuaState.Call(a_Fn, a_Args...);
}
- /** Call a Lua function with 2 args */
- template <typename FnT, typename ArgT0, typename ArgT1> bool Call(FnT a_Fn, ArgT0 a_Arg0, ArgT1 a_Arg1)
- {
- cCSLock Lock(m_CriticalSection);
- return m_LuaState.Call(a_Fn, a_Arg0, a_Arg1);
- }
-
- /** Call a Lua function with 3 args */
- template <typename FnT, typename ArgT0, typename ArgT1, typename ArgT2> bool Call(FnT a_Fn, ArgT0 a_Arg0, ArgT1 a_Arg1, ArgT2 a_Arg2)
- {
- cCSLock Lock(m_CriticalSection);
- return m_LuaState.Call(a_Fn, a_Arg0, a_Arg1, a_Arg2);
- }
-
- /** Call a Lua function with 4 args */
- template <typename FnT, typename ArgT0, typename ArgT1, typename ArgT2, typename ArgT3> bool Call(FnT a_Fn, ArgT0 a_Arg0, ArgT1 a_Arg1, ArgT2 a_Arg2, ArgT3 a_Arg3)
- {
- cCSLock Lock(m_CriticalSection);
- return m_LuaState.Call(a_Fn, a_Arg0, a_Arg1, a_Arg2, a_Arg3);
- }
+ /** Adds the specified cResettable instance to m_Resettables, so that it is notified when the plugin is being closed. */
+ void AddResettable(cResettablePtr a_Resettable);
protected:
/** Maps command name into Lua function reference */
@@ -234,15 +239,27 @@ protected:
/** Maps hook types into arrays of Lua function references to call for each hook type */
typedef std::map<int, cLuaRefs> cHookMap;
+
+ /** The mutex protecting m_LuaState and each of the m_Resettables[] against multithreaded use. */
cCriticalSection m_CriticalSection;
+
+ /** The plugin's Lua state. */
cLuaState m_LuaState;
+ /** Objects that need notification when the plugin is about to be unloaded. */
+ cResettablePtrs m_Resettables;
+
+ /** In-game commands that the plugin has registered. */
CommandMap m_Commands;
+
+ /** Console commands that the plugin has registered. */
CommandMap m_ConsoleCommands;
+ /** Hooks that the plugin has registered. */
cHookMap m_HookMap;
- /** Releases all Lua references and closes the LuaState */
+
+ /** Releases all Lua references, notifies and removes all m_Resettables[] and closes the m_LuaState. */
void Close(void);
} ; // tolua_export
diff --git a/src/Blocks/BlockPiston.cpp b/src/Blocks/BlockPiston.cpp
index 8d245cabe..d9f4913d8 100644
--- a/src/Blocks/BlockPiston.cpp
+++ b/src/Blocks/BlockPiston.cpp
@@ -61,6 +61,16 @@ void cBlockPistonHandler::OnDestroyed(cChunkInterface & a_ChunkInterface, cWorld
+void cBlockPistonHandler::ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta)
+{
+ // Returning Piston Item without Direction-Metavalue
+ a_Pickups.push_back(cItem(m_BlockType, 1));
+}
+
+
+
+
+
bool cBlockPistonHandler::GetPlacementBlockTypeMeta(
cChunkInterface & a_ChunkInterface, cPlayer * a_Player,
int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
@@ -169,7 +179,7 @@ void cBlockPistonHandler::ExtendPiston(int a_BlockX, int a_BlockY, int a_BlockZ,
a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, pistonBlock, pistonMeta | 0x8);
a_World->SetBlock(extx, exty, extz, E_BLOCK_PISTON_EXTENSION, pistonMeta | (IsSticky(pistonBlock) ? 8 : 0), false);
- a_World->ScheduleTask(PISTON_TICK_DELAY, new cWorld::cTaskSendBlockToAllPlayers(ScheduledBlocks));
+ a_World->ScheduleTask(PISTON_TICK_DELAY, std::make_shared<cWorld::cTaskSendBlockToAllPlayers>(ScheduledBlocks));
}
@@ -219,7 +229,7 @@ void cBlockPistonHandler::RetractPiston(int a_BlockX, int a_BlockY, int a_BlockZ
std::vector<Vector3i> ScheduledBlocks;
ScheduledBlocks.push_back(Vector3i(a_BlockX, a_BlockY, a_BlockZ));
ScheduledBlocks.push_back(Vector3i(tempx, tempy, tempz));
- a_World->ScheduleTask(PISTON_TICK_DELAY + 1, new cWorld::cTaskSendBlockToAllPlayers(ScheduledBlocks));
+ a_World->ScheduleTask(PISTON_TICK_DELAY + 1, std::make_shared<cWorld::cTaskSendBlockToAllPlayers>(ScheduledBlocks));
return;
}
}
@@ -229,7 +239,7 @@ void cBlockPistonHandler::RetractPiston(int a_BlockX, int a_BlockY, int a_BlockZ
std::vector<Vector3i> ScheduledBlocks;
ScheduledBlocks.push_back(Vector3i(a_BlockX, a_BlockY, a_BlockZ));
- a_World->ScheduleTask(PISTON_TICK_DELAY + 1, new cWorld::cTaskSendBlockToAllPlayers(ScheduledBlocks));
+ a_World->ScheduleTask(PISTON_TICK_DELAY + 1, std::make_shared<cWorld::cTaskSendBlockToAllPlayers>(ScheduledBlocks));
}
diff --git a/src/Blocks/BlockPiston.h b/src/Blocks/BlockPiston.h
index f868f4d8e..9a891025a 100644
--- a/src/Blocks/BlockPiston.h
+++ b/src/Blocks/BlockPiston.h
@@ -15,6 +15,8 @@ public:
virtual void OnDestroyed(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, int a_BlockX, int a_BlockY, int a_BlockZ) override;
+ virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override;
+
virtual bool GetPlacementBlockTypeMeta(
cChunkInterface & a_ChunkInterface, cPlayer * a_Player,
int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
diff --git a/src/CheckBasicStyle.lua b/src/CheckBasicStyle.lua
index 648a5711b..19156b537 100644
--- a/src/CheckBasicStyle.lua
+++ b/src/CheckBasicStyle.lua
@@ -101,9 +101,9 @@ local g_ViolationPatterns =
{"&&[^(]+!=", "Add parenthesis around comparison"},
{"!=[^)]+||", "Add parenthesis around comparison"},
{"||[^(]+!=", "Add parenthesis around comparison"},
- {"<[^)T][^)]*&&", "Add parenthesis around comparison"}, -- Must take special care of templates: "template <T> fn(Args && ...)"
- {"&&[^(]+<", "Add parenthesis around comparison"},
- {"<[^)T][^)]*||", "Add parenthesis around comparison"}, -- Must take special care of templates: "template <T> fn(Args && ...)"
+ {"<[^)>]*&&", "Add parenthesis around comparison"}, -- Must take special care of templates: "template <T> fn(Args && ...)"
+ -- Cannot check a < following a && due to functions of the form x fn(y&& a, z<b> c)
+ {"<[^)>]*||", "Add parenthesis around comparison"}, -- Must take special care of templates: "template <T> fn(Args && ...)"
{"||[^(]+<", "Add parenthesis around comparison"},
-- Cannot check ">" because of "obj->m_Flag &&". Check at least ">=":
{">=[^)]+&&", "Add parenthesis around comparison"},
diff --git a/src/Entities/ArrowEntity.cpp b/src/Entities/ArrowEntity.cpp
index 0fbbfb681..3c1fabb1b 100644
--- a/src/Entities/ArrowEntity.cpp
+++ b/src/Entities/ArrowEntity.cpp
@@ -72,14 +72,8 @@ bool cArrowEntity::CanPickup(const cPlayer & a_Player) const
void cArrowEntity::OnHitSolidBlock(const Vector3d & a_HitPos, eBlockFace a_HitFace)
{
- if (GetSpeed().EqualsEps(Vector3d(0, 0, 0), 0.0000001))
- {
- SetSpeed(GetLookVector().NormalizeCopy() * 0.1); // Ensure that no division by zero happens later
- }
-
Vector3d Hit = a_HitPos;
- Vector3d SinkMovement = (GetSpeed() / 1000);
- Hit += SinkMovement * (0.0005 / SinkMovement.Length()); // Make arrow sink into block a centimetre so it lodges (but not to far so it goes black clientside)
+ Hit += GetSpeed().NormalizeCopy() / 100000; // Make arrow sink into block a bit so it lodges (TODO: investigate how to stop them going so far so that they become black clientside)
super::OnHitSolidBlock(Hit, a_HitFace);
Vector3i BlockHit = Hit.Floor();
@@ -195,11 +189,6 @@ void cArrowEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
if (m_IsInGround)
{
- // When an arrow hits, the client doesn't think its in the ground and keeps on moving, IF BroadcastMovementUpdate() and TeleportEntity was called during flight, AT ALL
- // Fix is to simply not sync with the client and send a teleport to confirm pos after arrow has stabilised (around 1 sec after landing)
- // We can afford to do this because xoft's algorithm for trajectory is near perfect, so things are pretty close anyway without sync
- // Besides, this seems to be what the vanilla server does, note how arrows teleport half a second after they hit to the server position
-
if (!m_HasTeleported) // Sent a teleport already, don't do again
{
if (m_HitGroundTimer > std::chrono::milliseconds(500))
diff --git a/src/Entities/Entity.cpp b/src/Entities/Entity.cpp
index 1bc4690e1..039c58ee4 100644
--- a/src/Entities/Entity.cpp
+++ b/src/Entities/Entity.cpp
@@ -1263,7 +1263,7 @@ bool cEntity::DetectPortal()
{
if (GetWorld()->GetDimension() == dimOverworld)
{
- if (GetWorld()->GetNetherWorldName().empty() && GetWorld()->GetEndWorldName().empty())
+ if (GetWorld()->GetLinkedNetherWorldName().empty() && GetWorld()->GetLinkedEndWorldName().empty())
{
// Teleportation to either dimension not enabled, don't bother proceeding
return false;
@@ -1314,7 +1314,7 @@ bool cEntity::DetectPortal()
}
else
{
- if (GetWorld()->GetNetherWorldName().empty())
+ if (GetWorld()->GetLinkedNetherWorldName().empty())
{
return false;
}
@@ -1327,7 +1327,7 @@ bool cEntity::DetectPortal()
((cPlayer *)this)->GetClientHandle()->SendRespawn(dimNether);
}
- return MoveToWorld(cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetNetherWorldName(), dimNether, GetWorld()->GetName()), false);
+ return MoveToWorld(cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetLinkedNetherWorldName(), dimNether, GetWorld()->GetName()), false);
}
}
case E_BLOCK_END_PORTAL:
@@ -1358,7 +1358,7 @@ bool cEntity::DetectPortal()
}
else
{
- if (GetWorld()->GetEndWorldName().empty())
+ if (GetWorld()->GetLinkedEndWorldName().empty())
{
return false;
}
@@ -1371,7 +1371,7 @@ bool cEntity::DetectPortal()
((cPlayer *)this)->GetClientHandle()->SendRespawn(dimEnd);
}
- return MoveToWorld(cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetEndWorldName(), dimEnd, GetWorld()->GetName()), false);
+ return MoveToWorld(cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetLinkedEndWorldName(), dimEnd, GetWorld()->GetName()), false);
}
}
diff --git a/src/Entities/ProjectileEntity.cpp b/src/Entities/ProjectileEntity.cpp
index 4f20bfae6..21ec4e63a 100644
--- a/src/Entities/ProjectileEntity.cpp
+++ b/src/Entities/ProjectileEntity.cpp
@@ -334,12 +334,7 @@ AString cProjectileEntity::GetMCAClassName(void) const
void cProjectileEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
{
super::Tick(a_Dt, a_Chunk);
-
- // TODO: see BroadcastMovementUpdate; RelativeMove packet jerkiness affects projectiles too (cause of sympton described in cArrowEntity::Tick())
- if (GetProjectileKind() != pkArrow)
- {
- BroadcastMovementUpdate();
- }
+ BroadcastMovementUpdate();
}
diff --git a/src/Generating/BioGen.cpp b/src/Generating/BioGen.cpp
index 265db30ad..867155ad2 100644
--- a/src/Generating/BioGen.cpp
+++ b/src/Generating/BioGen.cpp
@@ -941,21 +941,21 @@ public:
cBioGenGrown(int a_Seed)
{
auto FinalRivers =
- std::make_shared<cIntGenSmooth<8>> (a_Seed + 1,
- std::make_shared<cIntGenZoom <10>> (a_Seed + 2,
- std::make_shared<cIntGenRiver <7>> (a_Seed + 3,
- std::make_shared<cIntGenZoom <9>> (a_Seed + 4,
- std::make_shared<cIntGenSmooth<6>> (a_Seed + 5,
- std::make_shared<cIntGenZoom <8>> (a_Seed + 8,
- std::make_shared<cIntGenSmooth<6>> (a_Seed + 5,
- std::make_shared<cIntGenZoom <8>> (a_Seed + 9,
- std::make_shared<cIntGenSmooth<6>> (a_Seed + 5,
- std::make_shared<cIntGenZoom <8>> (a_Seed + 10,
- std::make_shared<cIntGenSmooth<6>> (a_Seed + 5,
- std::make_shared<cIntGenSmooth<8>> (a_Seed + 6,
- std::make_shared<cIntGenZoom <10>> (a_Seed + 11,
- std::make_shared<cIntGenChoice<2, 7>>(a_Seed + 12
- ))))))))))))));
+
+ std::make_shared<cIntGenChoice<2, 7>>(a_Seed + 12)
+ | MakeIntGen<cIntGenZoom <10>>(a_Seed + 11)
+ | MakeIntGen<cIntGenSmooth<8>>(a_Seed + 6)
+ | MakeIntGen<cIntGenSmooth<6>>(a_Seed + 5)
+ | MakeIntGen<cIntGenZoom <8>>(a_Seed + 10)
+ | MakeIntGen<cIntGenSmooth<6>>(a_Seed + 5)
+ | MakeIntGen<cIntGenZoom <8>>(a_Seed + 9)
+ | MakeIntGen<cIntGenSmooth<6>>(a_Seed + 5)
+ | MakeIntGen<cIntGenZoom <8>>(a_Seed + 8)
+ | MakeIntGen<cIntGenSmooth<6>>(a_Seed + 5)
+ | MakeIntGen<cIntGenZoom <9>>(a_Seed + 4)
+ | MakeIntGen<cIntGenRiver <7>>(a_Seed + 3)
+ | MakeIntGen<cIntGenZoom <10>>(a_Seed + 2)
+ | MakeIntGen<cIntGenSmooth<8>>(a_Seed + 1);
auto alteration =
std::make_shared<cIntGenZoom <8>>(a_Seed,
@@ -1000,9 +1000,9 @@ public:
std::make_shared<cIntGenReplaceRandomly<6>> (a_Seed + 101, bgIce, bgTemperate, 150,
std::make_shared<cIntGenAddIslands <6>> (a_Seed + 2000, 200,
std::make_shared<cIntGenSetRandomly <6>> (a_Seed + 9, 50, bgOcean,
- std::make_shared<cIntGenZoom <6>> (a_Seed + 10,
- std::make_shared<cIntGenLandOcean <5>> (a_Seed + 100, 30
- )))))))))))))))))))))))))))))));
+ std::make_shared<cIntGenLandOcean <5>> (a_Seed + 100, 30)
+ | MakeIntGen<cIntGenZoom <6>> (a_Seed + 10)
+ )))))))))))))))))))))))))))));
m_Gen =
std::make_shared<cIntGenSmooth <16>>(a_Seed,
diff --git a/src/Generating/IntGen.h b/src/Generating/IntGen.h
index b25e378c0..854563f41 100644
--- a/src/Generating/IntGen.h
+++ b/src/Generating/IntGen.h
@@ -31,6 +31,8 @@ by using templates.
#include "../BiomeDef.h"
+#include <tuple>
+
@@ -53,6 +55,9 @@ template <int SizeX, int SizeZ = SizeX>
class cIntGen
{
public:
+
+ typedef cIntGen<SizeX, SizeZ> IntGenType;
+
/** Force a virtual destructor in all descendants.
Descendants contain virtual functions and are referred to via pointer-to-base, so they need a virtual destructor. */
virtual ~cIntGen() {}
@@ -62,9 +67,70 @@ public:
/** Generates the array of templated size into a_Values, based on given min coords. */
virtual void GetInts(int a_MinX, int a_MinZ, Values & a_Values) = 0;
+
+};
+
+// Code adapted from http://stackoverflow.com/questions/7858817/unpacking-a-tuple-to-call-a-matching-function-pointer
+
+template<int... >
+struct sSeq
+{
+};
+
+template<int N, int... S>
+struct sGens : sGens<N - 1, N - 1, S...>
+{
+};
+
+template<int... S>
+struct sGens<0, S...>
+{
+ typedef sSeq<S...> type;
+};
+
+
+template<class Gen, class... Args>
+class cIntGenFactory
+{
+
+public:
+
+ typedef Gen Generator;
+
+ cIntGenFactory(Args&&... a_args) :
+ m_args(std::make_tuple<Args...>(std::forward<Args>(a_args)...))
+ {
+ }
+
+ template <class LhsGen>
+ std::shared_ptr<Gen> construct(LhsGen&& a_Lhs)
+ {
+ return construct_impl<LhsGen>(std::forward<LhsGen>(a_Lhs), typename sGens<sizeof...(Args)>::type());
+ }
+
+
+private:
+ std::tuple<Args...> m_args;
+
+ template <class LhsGen, int... S>
+ std::shared_ptr<Gen> construct_impl(LhsGen&& a_Lhs, sSeq<S...>)
+ {
+ return std::make_shared<Gen>(std::get<S>(m_args)..., std::forward<LhsGen>(a_Lhs));
+ }
+
};
+template<class T, class RhsGen, class... Args>
+std::shared_ptr<RhsGen> operator| (std::shared_ptr<T> a_Lhs, cIntGenFactory<RhsGen, Args...> a_Rhs)
+{
+ return a_Rhs.construct(static_cast<std::shared_ptr<typename T::IntGenType>>(a_Lhs));
+}
+template<class Gen, class... Args>
+cIntGenFactory<Gen, Args...> MakeIntGen(Args&&... a_Args)
+{
+ return cIntGenFactory<Gen, Args...>(std::forward<Args>(a_Args)...);
+}
@@ -688,7 +754,7 @@ public:
int IdxZ = z * SizeX;
for (int x = 0; x < SizeX; x++)
{
- int val = a_Values[x + IdxZ];
+ size_t val = (size_t)a_Values[x + IdxZ];
const cBiomesInGroups & Biomes = (val > bgfRare) ?
rareBiomesInGroups[(val & (bgfRare - 1)) % ARRAYCOUNT(rareBiomesInGroups)] :
biomesInGroups[val % ARRAYCOUNT(biomesInGroups)];
diff --git a/src/World.cpp b/src/World.cpp
index 292ff9b94..7d63a8a52 100644
--- a/src/World.cpp
+++ b/src/World.cpp
@@ -259,9 +259,9 @@ void cWorld::cTickThread::Execute(void)
////////////////////////////////////////////////////////////////////////////////
// cWorld:
-cWorld::cWorld(const AString & a_WorldName, eDimension a_Dimension, const AString & a_OverworldName) :
+cWorld::cWorld(const AString & a_WorldName, eDimension a_Dimension, const AString & a_LinkedOverworldName) :
m_WorldName(a_WorldName),
- m_OverworldName(a_OverworldName),
+ m_LinkedOverworldName(a_LinkedOverworldName),
m_IniFileName(m_WorldName + "/world.ini"),
m_StorageSchema("Default"),
#ifdef __arm__
@@ -604,12 +604,12 @@ void cWorld::Start(void)
if (GetDimension() == dimOverworld)
{
- m_NetherWorldName = IniFile.GetValueSet("LinkedWorlds", "NetherWorldName", GetName() + "_nether");
- m_EndWorldName = IniFile.GetValueSet("LinkedWorlds", "EndWorldName", GetName() + "_end");
+ m_LinkedNetherWorldName = IniFile.GetValueSet("LinkedWorlds", "NetherWorldName", GetName() + "_nether");
+ m_LinkedEndWorldName = IniFile.GetValueSet("LinkedWorlds", "EndWorldName", GetName() + "_end");
}
else
{
- m_OverworldName = IniFile.GetValueSet("LinkedWorlds", "OverworldName", GetLinkedOverworldName());
+ m_LinkedOverworldName = IniFile.GetValueSet("LinkedWorlds", "OverworldName", GetLinkedOverworldName());
}
// Adjust the enum-backed variables into their respective bounds:
@@ -884,18 +884,18 @@ void cWorld::Stop(void)
IniFile.ReadFile(m_IniFileName);
if (GetDimension() == dimOverworld)
{
- IniFile.SetValue("LinkedWorlds", "NetherWorldName", m_NetherWorldName);
- IniFile.SetValue("LinkedWorlds", "EndWorldName", m_EndWorldName);
+ IniFile.SetValue("LinkedWorlds", "NetherWorldName", m_LinkedNetherWorldName);
+ IniFile.SetValue("LinkedWorlds", "EndWorldName", m_LinkedEndWorldName);
}
else
{
- IniFile.SetValue("LinkedWorlds", "OverworldName", m_OverworldName);
+ IniFile.SetValue("LinkedWorlds", "OverworldName", m_LinkedOverworldName);
}
- IniFile.SetValueI("Physics", "TNTShrapnelLevel", (int)m_TNTShrapnelLevel);
+ IniFile.SetValueI("Physics", "TNTShrapnelLevel", static_cast<int>(m_TNTShrapnelLevel));
IniFile.SetValueB("Mechanics", "CommandBlocksEnabled", m_bCommandBlocksEnabled);
IniFile.SetValueB("Mechanics", "UseChatPrefixes", m_bUseChatPrefixes);
IniFile.SetValueB("General", "IsDaylightCycleEnabled", m_IsDaylightCycleEnabled);
- IniFile.SetValueI("General", "Weather", (int)m_Weather);
+ IniFile.SetValueI("General", "Weather", static_cast<int>(m_Weather));
IniFile.SetValueI("General", "TimeInTicks", GetTimeOfDay());
IniFile.WriteFile(m_IniFileName);
@@ -3167,14 +3167,14 @@ void cWorld::SaveAllChunks(void)
void cWorld::QueueSaveAllChunks(void)
{
- QueueTask(make_unique<cWorld::cTaskSaveAllChunks>());
+ QueueTask(std::make_shared<cWorld::cTaskSaveAllChunks>());
}
-void cWorld::QueueTask(std::unique_ptr<cTask> a_Task)
+void cWorld::QueueTask(cTaskPtr a_Task)
{
cCSLock Lock(m_CSTasks);
m_Tasks.push_back(std::move(a_Task));
@@ -3184,7 +3184,7 @@ void cWorld::QueueTask(std::unique_ptr<cTask> a_Task)
-void cWorld::ScheduleTask(int a_DelayTicks, cTask * a_Task)
+void cWorld::ScheduleTask(int a_DelayTicks, cTaskPtr a_Task)
{
Int64 TargetTick = a_DelayTicks + std::chrono::duration_cast<cTickTimeLong>(m_WorldAge).count();
@@ -3194,11 +3194,11 @@ void cWorld::ScheduleTask(int a_DelayTicks, cTask * a_Task)
{
if ((*itr)->m_TargetTick >= TargetTick)
{
- m_ScheduledTasks.insert(itr, make_unique<cScheduledTask>(TargetTick, a_Task));
+ m_ScheduledTasks.insert(itr, cScheduledTaskPtr(new cScheduledTask(TargetTick, a_Task)));
return;
}
}
- m_ScheduledTasks.push_back(make_unique<cScheduledTask>(TargetTick, a_Task));
+ m_ScheduledTasks.push_back(cScheduledTaskPtr(new cScheduledTask(TargetTick, a_Task)));
}
diff --git a/src/World.h b/src/World.h
index 0decc8c6e..ffc10a9e4 100644
--- a/src/World.h
+++ b/src/World.h
@@ -106,7 +106,8 @@ public:
virtual void Run(cWorld & a_World) = 0;
} ;
- typedef std::vector<std::unique_ptr<cTask>> cTasks;
+ typedef SharedPtr<cTask> cTaskPtr;
+ typedef std::vector<cTaskPtr> cTasks;
class cTaskSaveAllChunks :
@@ -673,14 +674,14 @@ public:
bool ShouldBroadcastAchievementMessages(void) const { return m_BroadcastAchievementMessages; }
- AString GetNetherWorldName(void) const { return m_NetherWorldName; }
- void SetNetherWorldName(const AString & a_Name) { m_NetherWorldName = a_Name; }
+ AString GetLinkedNetherWorldName(void) const { return m_LinkedNetherWorldName; }
+ void SetLinkedNetherWorldName(const AString & a_Name) { m_LinkedNetherWorldName = a_Name; }
- AString GetEndWorldName(void) const { return m_EndWorldName; }
- void SetEndWorldName(const AString & a_Name) { m_EndWorldName = a_Name; }
+ AString GetLinkedEndWorldName(void) const { return m_LinkedEndWorldName; }
+ void SetLinkedEndWorldName(const AString & a_Name) { m_LinkedEndWorldName = a_Name; }
- AString GetLinkedOverworldName(void) const { return m_OverworldName; }
- void SetLinkedOverworldName(const AString & a_Name) { m_OverworldName = a_Name; }
+ AString GetLinkedOverworldName(void) const { return m_LinkedOverworldName; }
+ void SetLinkedOverworldName(const AString & a_Name) { m_LinkedOverworldName = a_Name; }
// tolua_end
@@ -691,11 +692,10 @@ public:
void QueueSaveAllChunks(void); // tolua_export
/** Queues a task onto the tick thread. The task object will be deleted once the task is finished */
- void QueueTask(std::unique_ptr<cTask> a_Task); // Exported in ManualBindings.cpp
+ void QueueTask(cTaskPtr a_Task); // Exported in ManualBindings.cpp
- /** Queues a task onto the tick thread, with the specified delay.
- The task object will be deleted once the task is finished */
- void ScheduleTask(int a_DelayTicks, cTask * a_Task);
+ /** Queues a task onto the tick thread, with the specified delay. */
+ void ScheduleTask(int a_DelayTicks, cTaskPtr a_Task);
/** Returns the number of chunks loaded */
int GetNumChunks() const; // tolua_export
@@ -867,20 +867,16 @@ private:
{
public:
Int64 m_TargetTick;
- cTask * m_Task;
+ cTaskPtr m_Task;
/** Creates a new scheduled task; takes ownership of the task object passed to it. */
- cScheduledTask(Int64 a_TargetTick, cTask * a_Task) :
+ cScheduledTask(Int64 a_TargetTick, cTaskPtr a_Task) :
m_TargetTick(a_TargetTick),
m_Task(a_Task)
{
}
- virtual ~cScheduledTask()
- {
- delete m_Task;
- m_Task = nullptr;
- }
+ virtual ~cScheduledTask() {}
};
typedef std::unique_ptr<cScheduledTask> cScheduledTaskPtr;
@@ -889,10 +885,9 @@ private:
AString m_WorldName;
- /** The name of the world that a portal in this world should link to
- Only has effect if this world is a nether or end world, as it is used by entities to see which world to teleport to when in a portal
- */
- AString m_OverworldName;
+ /** The name of the overworld that portals in this world should link to.
+ Only has effect if this world is a Nether or End world. */
+ AString m_LinkedOverworldName;
AString m_IniFileName;
@@ -985,11 +980,13 @@ private:
/** The maximum view distance that a player can have in this world. */
int m_MaxViewDistance;
- /** Name of the nether world */
- AString m_NetherWorldName;
+ /** Name of the nether world - where Nether portals should teleport.
+ Only used when this world is an Overworld. */
+ AString m_LinkedNetherWorldName;
- /** Name of the end world */
- AString m_EndWorldName;
+ /** Name of the End world - where End portals should teleport.
+ Only used when this world is an Overworld. */
+ AString m_LinkedEndWorldName;
cChunkGenerator m_Generator;
@@ -1049,7 +1046,7 @@ private:
cSetChunkDataPtrs m_SetChunkDataQueue;
- cWorld(const AString & a_WorldName, eDimension a_Dimension = dimOverworld, const AString & a_OverworldName = "");
+ cWorld(const AString & a_WorldName, eDimension a_Dimension = dimOverworld, const AString & a_LinkedOverworldName = "");
virtual ~cWorld();
void Tick(std::chrono::milliseconds a_Dt, std::chrono::milliseconds a_LastTickDurationMSec);