Revert "Replace ItemCallbacks with lambdas (#3948)"
This reverts commit 496c337cdf
.
This commit is contained in:
parent
700bbdabf5
commit
49c443896d
@ -1,4 +1,4 @@
|
||||
|
||||
|
||||
// LuaState.cpp
|
||||
|
||||
// Implements the cLuaState class representing the wrapper over lua_State *, provides associated helper functions
|
||||
|
@ -1,4 +1,4 @@
|
||||
|
||||
|
||||
// LuaState.h
|
||||
|
||||
// Declares the cLuaState class representing the wrapper over lua_State *, provides associated helper functions
|
||||
|
@ -54,15 +54,22 @@ cLuaWindow::~cLuaWindow()
|
||||
m_Contents.RemoveListener(*this);
|
||||
|
||||
// Close open lua window from players, to avoid dangling pointers
|
||||
cRoot::Get()->ForEachPlayer([this](cPlayer & a_Player)
|
||||
class cPlayerCallback : public cPlayerListCallback
|
||||
{
|
||||
virtual bool Item(cPlayer * a_Player)
|
||||
{
|
||||
if (a_Player.GetWindow() == this)
|
||||
if (a_Player->GetWindow() == m_LuaWindow)
|
||||
{
|
||||
a_Player.CloseWindow(false);
|
||||
a_Player->CloseWindow(false);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
);
|
||||
cLuaWindow * m_LuaWindow;
|
||||
public:
|
||||
cPlayerCallback(cLuaWindow & a_LuaWindow) { m_LuaWindow = &a_LuaWindow; }
|
||||
} PlayerCallback(*this);
|
||||
|
||||
cRoot::Get()->ForEachPlayer(PlayerCallback);
|
||||
|
||||
// Must delete slot areas now, because they are referencing this->m_Contents and would try to access it in cWindow's
|
||||
// destructor, when the member is already gone.
|
||||
|
@ -1,4 +1,4 @@
|
||||
|
||||
|
||||
// LuaWindow.h
|
||||
|
||||
// Declares the cLuaWindow class representing a virtual window that plugins may create and open for the player
|
||||
@ -9,14 +9,13 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include "LuaState.h"
|
||||
#include "../UI/Window.h"
|
||||
#include "../ItemGrid.h"
|
||||
|
||||
|
||||
class cPlayer;
|
||||
using cPlayerListCallback = std::function<bool(cPlayer &)>;
|
||||
typedef cItemCallback<cPlayer> cPlayerListCallback;
|
||||
|
||||
|
||||
/** A window that has been created by a Lua plugin and is handled entirely by that plugin
|
||||
|
@ -1483,29 +1483,44 @@ static int tolua_cPluginManager_CallPlugin(lua_State * tolua_S)
|
||||
}
|
||||
|
||||
// Call the destination plugin using a plugin callback:
|
||||
int NumReturns = 0;
|
||||
auto PluginCallback = [&](cPlugin & a_Plugin)
|
||||
class cCallback :
|
||||
public cPluginManager::cPluginCallback
|
||||
{
|
||||
public:
|
||||
int m_NumReturns;
|
||||
|
||||
cCallback(const AString & a_FunctionName, cLuaState & a_SrcLuaState) :
|
||||
m_NumReturns(0),
|
||||
m_FunctionName(a_FunctionName),
|
||||
m_SrcLuaState(a_SrcLuaState)
|
||||
{
|
||||
if (!a_Plugin.IsLoaded())
|
||||
}
|
||||
protected:
|
||||
const AString & m_FunctionName;
|
||||
cLuaState & m_SrcLuaState;
|
||||
|
||||
virtual bool Item(cPlugin * a_Plugin) override
|
||||
{
|
||||
if (!a_Plugin->IsLoaded())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
NumReturns = static_cast<cPluginLua &>(a_Plugin).CallFunctionFromForeignState(
|
||||
FunctionName, L, 4, lua_gettop(L)
|
||||
m_NumReturns = static_cast<cPluginLua *>(a_Plugin)->CallFunctionFromForeignState(
|
||||
m_FunctionName, m_SrcLuaState, 4, lua_gettop(m_SrcLuaState)
|
||||
);
|
||||
return true;
|
||||
};
|
||||
|
||||
if (!cPluginManager::Get()->DoWithPlugin(PluginName, PluginCallback))
|
||||
}
|
||||
} Callback(FunctionName, L);
|
||||
if (!cPluginManager::Get()->DoWithPlugin(PluginName, Callback))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (NumReturns < 0)
|
||||
if (Callback.m_NumReturns < 0)
|
||||
{
|
||||
// The call has failed, there are zero return values. Do NOT return negative number (Lua considers that a "yield")
|
||||
return 0;
|
||||
}
|
||||
return NumReturns;
|
||||
return Callback.m_NumReturns;
|
||||
}
|
||||
|
||||
|
||||
@ -3228,29 +3243,42 @@ static int tolua_cRoot_DoWithPlayerByUUID(lua_State * tolua_S)
|
||||
return 0;
|
||||
}
|
||||
|
||||
class cCallback :
|
||||
public cPlayerListCallback
|
||||
{
|
||||
public:
|
||||
cCallback(cLuaState & a_LuaState) :
|
||||
m_LuaState(a_LuaState)
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool Item(cPlayer * a_Player) override
|
||||
{
|
||||
bool ret = false;
|
||||
m_LuaState.Call(m_FnRef, a_Player, cLuaState::Return, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
cLuaState & m_LuaState;
|
||||
cLuaState::cRef m_FnRef;
|
||||
} Callback(L);
|
||||
|
||||
// Get parameters:
|
||||
cRoot * Self;
|
||||
cUUID PlayerUUID;
|
||||
cLuaState::cRef FnRef;
|
||||
L.GetStackValues(1, Self, PlayerUUID, FnRef);
|
||||
L.GetStackValues(1, Self, PlayerUUID, Callback.m_FnRef);
|
||||
|
||||
if (PlayerUUID.IsNil())
|
||||
{
|
||||
return L.ApiParamError("Expected a non-nil UUID for parameter #1");
|
||||
}
|
||||
if (!FnRef.IsValid())
|
||||
if (!Callback.m_FnRef.IsValid())
|
||||
{
|
||||
return L.ApiParamError("Expected a valid callback function for parameter #2");
|
||||
}
|
||||
|
||||
// Call the function:
|
||||
bool res = Self->DoWithPlayerByUUID(PlayerUUID, [&](cPlayer & a_Player)
|
||||
{
|
||||
bool ret = false;
|
||||
L.Call(FnRef, &a_Player, cLuaState::Return, ret);
|
||||
return ret;
|
||||
}
|
||||
);
|
||||
bool res = Self->DoWithPlayerByUUID(PlayerUUID, Callback);
|
||||
|
||||
// Push the result as the return value:
|
||||
L.Push(res);
|
||||
|
@ -1,4 +1,4 @@
|
||||
|
||||
|
||||
// ManualBindings.h
|
||||
|
||||
// Declares the cManualBindings class used as a namespace for functions exported to the Lua API manually
|
||||
@ -57,7 +57,7 @@ public:
|
||||
template <
|
||||
class Ty1,
|
||||
class Ty2,
|
||||
bool (Ty1::*DoWithFn)(const AString &, const std::function<bool(Ty2 &)> &)
|
||||
bool (Ty1::*DoWithFn)(const AString &, cItemCallback<Ty2> &)
|
||||
>
|
||||
static int DoWith(lua_State * tolua_S)
|
||||
{
|
||||
@ -89,14 +89,28 @@ public:
|
||||
return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a valid callback function for parameter #2");
|
||||
}
|
||||
|
||||
// Call the DoWith function:
|
||||
bool res = (Self->*DoWithFn)(ItemName, [&](Ty2 & a_Item)
|
||||
class cLuaCallback : public cItemCallback<Ty2>
|
||||
{
|
||||
public:
|
||||
cLuaCallback(cLuaState & a_LuaState, cLuaState::cRef & a_FnRef):
|
||||
m_LuaState(a_LuaState),
|
||||
m_FnRef(a_FnRef)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
virtual bool Item(Ty2 * a_Item) override
|
||||
{
|
||||
bool ret = false;
|
||||
L.Call(FnRef, &a_Item, cLuaState::Return, ret);
|
||||
m_LuaState.Call(m_FnRef, a_Item, cLuaState::Return, ret);
|
||||
return ret;
|
||||
}
|
||||
);
|
||||
cLuaState & m_LuaState;
|
||||
cLuaState::cRef & m_FnRef;
|
||||
} Callback(L, FnRef);
|
||||
|
||||
// Call the DoWith function:
|
||||
bool res = (Self->*DoWithFn)(ItemName, Callback);
|
||||
|
||||
// Push the result as the return value:
|
||||
L.Push(res);
|
||||
@ -111,7 +125,7 @@ public:
|
||||
template <
|
||||
class Ty1,
|
||||
class Ty2,
|
||||
bool (Ty1::*DoWithFn)(const AString &, const std::function<bool(Ty2 &)> &)
|
||||
bool (Ty1::*DoWithFn)(const AString &, cItemCallback<Ty2> &)
|
||||
>
|
||||
static int StaticDoWith(lua_State * tolua_S)
|
||||
{
|
||||
@ -138,14 +152,28 @@ public:
|
||||
return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a valid callback function for parameter #2");
|
||||
}
|
||||
|
||||
// Call the DoWith function:
|
||||
bool res = (Ty1::Get()->*DoWithFn)(ItemName, [&](Ty2 & a_Item)
|
||||
class cLuaCallback : public cItemCallback<Ty2>
|
||||
{
|
||||
public:
|
||||
cLuaCallback(cLuaState & a_LuaState, cLuaState::cRef & a_FnRef):
|
||||
m_LuaState(a_LuaState),
|
||||
m_FnRef(a_FnRef)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
virtual bool Item(Ty2 * a_Item) override
|
||||
{
|
||||
bool ret = false;
|
||||
L.Call(FnRef, &a_Item, cLuaState::Return, ret);
|
||||
m_LuaState.Call(m_FnRef, a_Item, cLuaState::Return, ret);
|
||||
return ret;
|
||||
}
|
||||
);
|
||||
cLuaState & m_LuaState;
|
||||
cLuaState::cRef & m_FnRef;
|
||||
} Callback(L, FnRef);
|
||||
|
||||
// Call the DoWith function:
|
||||
bool res = (Ty1::Get()->*DoWithFn)(ItemName, Callback);
|
||||
|
||||
// Push the result as the return value:
|
||||
L.Push(res);
|
||||
@ -159,7 +187,7 @@ public:
|
||||
template <
|
||||
class Ty1,
|
||||
class Ty2,
|
||||
bool (Ty1::*DoWithFn)(UInt32, const std::function<bool(Ty2 &)> &)
|
||||
bool (Ty1::*DoWithFn)(UInt32, cItemCallback<Ty2> &)
|
||||
>
|
||||
static int DoWithID(lua_State * tolua_S)
|
||||
{
|
||||
@ -187,14 +215,28 @@ public:
|
||||
return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a valid callback function for parameter #2");
|
||||
}
|
||||
|
||||
// Call the DoWith function:
|
||||
bool res = (Self->*DoWithFn)(ItemID, [&](Ty2 & a_Item)
|
||||
class cLuaCallback : public cItemCallback<Ty2>
|
||||
{
|
||||
public:
|
||||
cLuaCallback(cLuaState & a_LuaState, cLuaState::cRef & a_FnRef):
|
||||
m_LuaState(a_LuaState),
|
||||
m_FnRef(a_FnRef)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
virtual bool Item(Ty2 * a_Item) override
|
||||
{
|
||||
bool ret = false;
|
||||
L.Call(FnRef, &a_Item, cLuaState::Return, ret);
|
||||
m_LuaState.Call(m_FnRef, a_Item, cLuaState::Return, ret);
|
||||
return ret;
|
||||
}
|
||||
);
|
||||
cLuaState & m_LuaState;
|
||||
cLuaState::cRef & m_FnRef;
|
||||
} Callback(L, FnRef);
|
||||
|
||||
// Call the DoWith function:
|
||||
bool res = (Self->*DoWithFn)(ItemID, Callback);
|
||||
|
||||
// Push the result as the return value:
|
||||
L.Push(res);
|
||||
@ -209,7 +251,7 @@ public:
|
||||
template <
|
||||
class SELF,
|
||||
class ITEM,
|
||||
bool (SELF::*DoWithFn)(int, int, int, const std::function<bool(ITEM &)> &)
|
||||
bool (SELF::*DoWithFn)(int, int, int, cItemCallback<ITEM> &)
|
||||
>
|
||||
static int DoWithXYZ(lua_State * tolua_S)
|
||||
{
|
||||
@ -240,14 +282,28 @@ public:
|
||||
return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a valid callback function for parameter #5");
|
||||
}
|
||||
|
||||
// Call the DoWith function:
|
||||
bool res = (Self->*DoWithFn)(BlockX, BlockY, BlockZ, [&](ITEM & a_Item)
|
||||
class cLuaCallback : public cItemCallback<ITEM>
|
||||
{
|
||||
public:
|
||||
cLuaCallback(cLuaState & a_LuaState, cLuaState::cRef & a_FnRef):
|
||||
m_LuaState(a_LuaState),
|
||||
m_FnRef(a_FnRef)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
virtual bool Item(ITEM * a_Item) override
|
||||
{
|
||||
bool ret = false;
|
||||
L.Call(FnRef, &a_Item, cLuaState::Return, ret);
|
||||
m_LuaState.Call(m_FnRef, a_Item, cLuaState::Return, ret);
|
||||
return ret;
|
||||
}
|
||||
);
|
||||
cLuaState & m_LuaState;
|
||||
cLuaState::cRef & m_FnRef;
|
||||
} Callback(L, FnRef);
|
||||
|
||||
// Call the DoWith function:
|
||||
bool res = (Self->*DoWithFn)(BlockX, BlockY, BlockZ, Callback);
|
||||
|
||||
// Push the result as the return value:
|
||||
L.Push(res);
|
||||
@ -262,7 +318,7 @@ public:
|
||||
template <
|
||||
class SELF,
|
||||
class ITEM,
|
||||
bool (SELF::*DoWithFn)(int, int, int, const std::function<bool(ITEM &)> &),
|
||||
bool (SELF::*DoWithFn)(int, int, int, cItemCallback<ITEM> &),
|
||||
bool (SELF::*CoordCheckFn)(int, int, int) const
|
||||
>
|
||||
static int DoWithXYZ(lua_State * tolua_S)
|
||||
@ -300,14 +356,28 @@ public:
|
||||
).c_str());
|
||||
}
|
||||
|
||||
// Call the DoWith function:
|
||||
bool res = (Self->*DoWithFn)(BlockX, BlockY, BlockZ, [&](ITEM & a_Item)
|
||||
class cLuaCallback : public cItemCallback<ITEM>
|
||||
{
|
||||
public:
|
||||
cLuaCallback(cLuaState & a_LuaState, cLuaState::cRef & a_FnRef):
|
||||
m_LuaState(a_LuaState),
|
||||
m_FnRef(a_FnRef)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
virtual bool Item(ITEM * a_Item) override
|
||||
{
|
||||
bool ret = false;
|
||||
L.Call(FnRef, &a_Item, cLuaState::Return, ret);
|
||||
m_LuaState.Call(m_FnRef, a_Item, cLuaState::Return, ret);
|
||||
return ret;
|
||||
}
|
||||
);
|
||||
cLuaState & m_LuaState;
|
||||
cLuaState::cRef & m_FnRef;
|
||||
} Callback(L, FnRef);
|
||||
|
||||
// Call the DoWith function:
|
||||
bool res = (Self->*DoWithFn)(BlockX, BlockY, BlockZ, Callback);
|
||||
|
||||
// Push the result as the return value:
|
||||
L.Push(res);
|
||||
@ -321,7 +391,7 @@ public:
|
||||
template <
|
||||
class Ty1,
|
||||
class Ty2,
|
||||
bool (Ty1::*ForEachFn)(int, int, const std::function<bool(Ty2 &)> &)
|
||||
bool (Ty1::*ForEachFn)(int, int, cItemCallback<Ty2> &)
|
||||
>
|
||||
static int ForEachInChunk(lua_State * tolua_S)
|
||||
{
|
||||
@ -351,14 +421,28 @@ public:
|
||||
return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a valid callback function for parameter #4");
|
||||
}
|
||||
|
||||
// Call the DoWith function:
|
||||
bool res = (Self->*ForEachFn)(ChunkX, ChunkZ, [&](Ty2 & a_Item)
|
||||
class cLuaCallback : public cItemCallback<Ty2>
|
||||
{
|
||||
public:
|
||||
cLuaCallback(cLuaState & a_LuaState, cLuaState::cRef & a_FnRef):
|
||||
m_LuaState(a_LuaState),
|
||||
m_FnRef(a_FnRef)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
virtual bool Item(Ty2 * a_Item) override
|
||||
{
|
||||
bool ret = false;
|
||||
L.Call(FnRef, &a_Item, cLuaState::Return, ret);
|
||||
m_LuaState.Call(m_FnRef, a_Item, cLuaState::Return, ret);
|
||||
return ret;
|
||||
}
|
||||
);
|
||||
cLuaState & m_LuaState;
|
||||
cLuaState::cRef & m_FnRef;
|
||||
} Callback(L, FnRef);
|
||||
|
||||
// Call the DoWith function:
|
||||
bool res = (Self->*ForEachFn)(ChunkX, ChunkZ, Callback);
|
||||
|
||||
// Push the result as the return value:
|
||||
L.Push(res);
|
||||
@ -372,7 +456,7 @@ public:
|
||||
template <
|
||||
class Ty1,
|
||||
class Ty2,
|
||||
bool (Ty1::*ForEachFn)(const cBoundingBox &, const std::function<bool(Ty2 &)> &)
|
||||
bool (Ty1::*ForEachFn)(const cBoundingBox &, cItemCallback<Ty2> &)
|
||||
>
|
||||
static int ForEachInBox(lua_State * tolua_S)
|
||||
{
|
||||
@ -404,19 +488,36 @@ public:
|
||||
return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a valid callback function for parameter #2");
|
||||
}
|
||||
|
||||
bool res = (Self->*ForEachFn)(*Box, [&](Ty2 & a_Item)
|
||||
// Callback wrapper for the Lua function:
|
||||
class cLuaCallback : public cItemCallback<Ty2>
|
||||
{
|
||||
public:
|
||||
cLuaCallback(cLuaState & a_LuaState, cLuaState::cRef & a_FuncRef) :
|
||||
m_LuaState(a_LuaState),
|
||||
m_FnRef(a_FuncRef)
|
||||
{
|
||||
bool ret = false;
|
||||
if (!L.Call(FnRef, &a_Item, cLuaState::Return, ret))
|
||||
}
|
||||
|
||||
private:
|
||||
cLuaState & m_LuaState;
|
||||
cLuaState::cRef & m_FnRef;
|
||||
|
||||
// cItemCallback<Ty2> overrides:
|
||||
virtual bool Item(Ty2 * a_Item) override
|
||||
{
|
||||
bool res = false;
|
||||
if (!m_LuaState.Call(m_FnRef, a_Item, cLuaState::Return, res))
|
||||
{
|
||||
LOGWARNING("Failed to call Lua callback");
|
||||
L.LogStackTrace();
|
||||
m_LuaState.LogStackTrace();
|
||||
return true; // Abort enumeration
|
||||
}
|
||||
|
||||
return ret;
|
||||
return res;
|
||||
}
|
||||
);
|
||||
} Callback(L, FnRef);
|
||||
|
||||
bool res = (Self->*ForEachFn)(*Box, Callback);
|
||||
|
||||
// Push the result as the return value:
|
||||
L.Push(res);
|
||||
@ -430,7 +531,7 @@ public:
|
||||
template <
|
||||
class Ty1,
|
||||
class Ty2,
|
||||
bool (Ty1::*ForEachFn)(const std::function<bool(Ty2 &)> &)
|
||||
bool (Ty1::*ForEachFn)(cItemCallback<Ty2> &)
|
||||
>
|
||||
static int ForEach(lua_State * tolua_S)
|
||||
{
|
||||
@ -457,14 +558,29 @@ public:
|
||||
return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a valid callback function for parameter #1");
|
||||
}
|
||||
|
||||
// Call the enumeration:
|
||||
bool res = (Self->*ForEachFn)([&](Ty2 & a_Item)
|
||||
class cLuaCallback : public cItemCallback<Ty2>
|
||||
{
|
||||
public:
|
||||
cLuaCallback(cLuaState & a_LuaState, cLuaState::cRef & a_FnRef):
|
||||
m_LuaState(a_LuaState),
|
||||
m_FnRef(a_FnRef)
|
||||
{
|
||||
bool ret = false; // By default continue the enumeration
|
||||
L.Call(FnRef, &a_Item, cLuaState::Return, ret);
|
||||
return ret;
|
||||
}
|
||||
);
|
||||
|
||||
private:
|
||||
cLuaState & m_LuaState;
|
||||
cLuaState::cRef & m_FnRef;
|
||||
|
||||
virtual bool Item(Ty2 * a_Item) override
|
||||
{
|
||||
bool res = false; // By default continue the enumeration
|
||||
m_LuaState.Call(m_FnRef, a_Item, cLuaState::Return, res);
|
||||
return res;
|
||||
}
|
||||
} Callback(L, FnRef);
|
||||
|
||||
// Call the enumeration:
|
||||
bool res = (Self->*ForEachFn)(Callback);
|
||||
|
||||
// Push the return value:
|
||||
L.Push(res);
|
||||
@ -479,7 +595,7 @@ public:
|
||||
template <
|
||||
class Ty1,
|
||||
class Ty2,
|
||||
bool (Ty1::*ForEachFn)(const std::function<bool(Ty2 &)> &)
|
||||
bool (Ty1::*ForEachFn)(cItemCallback<Ty2> &)
|
||||
>
|
||||
static int StaticForEach(lua_State * tolua_S)
|
||||
{
|
||||
@ -500,14 +616,29 @@ public:
|
||||
return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a valid callback function for parameter #1");
|
||||
}
|
||||
|
||||
// Call the enumeration:
|
||||
bool res = (Ty1::Get()->*ForEachFn)([&](Ty2 & a_Item)
|
||||
class cLuaCallback : public cItemCallback<Ty2>
|
||||
{
|
||||
public:
|
||||
cLuaCallback(cLuaState & a_LuaState, cLuaState::cRef & a_FnRef):
|
||||
m_LuaState(a_LuaState),
|
||||
m_FnRef(a_FnRef)
|
||||
{
|
||||
bool ret = false; // By default continue the enumeration
|
||||
L.Call(FnRef, &a_Item, cLuaState::Return, ret);
|
||||
return ret;
|
||||
}
|
||||
);
|
||||
|
||||
private:
|
||||
cLuaState & m_LuaState;
|
||||
cLuaState::cRef & m_FnRef;
|
||||
|
||||
virtual bool Item(Ty2 * a_Item) override
|
||||
{
|
||||
bool res = false; // By default continue the enumeration
|
||||
m_LuaState.Call(m_FnRef, a_Item, cLuaState::Return, res);
|
||||
return res;
|
||||
}
|
||||
} Callback(L, FnRef);
|
||||
|
||||
// Call the enumeration:
|
||||
bool res = (Ty1::Get()->*ForEachFn)(Callback);
|
||||
|
||||
// Push the return value:
|
||||
L.Push(res);
|
||||
|
@ -1,4 +1,4 @@
|
||||
|
||||
|
||||
// ManualBindings_World.cpp
|
||||
|
||||
// Implements the manual Lua API bindings for the cWorld class
|
||||
@ -237,10 +237,10 @@ static int tolua_cWorld_DoWithPlayerByUUID(lua_State * tolua_S)
|
||||
}
|
||||
|
||||
// Call the function:
|
||||
bool res = Self->DoWithPlayerByUUID(PlayerUUID, [&](cPlayer & a_Player)
|
||||
bool res = Self->DoWithPlayerByUUID(PlayerUUID, [&](cPlayer * a_Player)
|
||||
{
|
||||
bool ret = false;
|
||||
L.Call(FnRef, &a_Player, cLuaState::Return, ret);
|
||||
L.Call(FnRef, a_Player, cLuaState::Return, ret);
|
||||
return ret;
|
||||
}
|
||||
);
|
||||
|
@ -1,4 +1,4 @@
|
||||
|
||||
|
||||
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
|
||||
|
||||
#include "PluginManager.h"
|
||||
@ -1993,14 +1993,14 @@ bool cPluginManager::IsValidHookType(int a_HookType)
|
||||
|
||||
|
||||
|
||||
bool cPluginManager::DoWithPlugin(const AString & a_PluginName, const cPluginCallback & a_Callback)
|
||||
bool cPluginManager::DoWithPlugin(const AString & a_PluginName, cPluginCallback & a_Callback)
|
||||
{
|
||||
// TODO: Implement locking for plugins
|
||||
for (auto & plugin: m_Plugins)
|
||||
{
|
||||
if (plugin->GetName() == a_PluginName)
|
||||
{
|
||||
return a_Callback(*plugin);
|
||||
return a_Callback.Item(plugin.get());
|
||||
}
|
||||
}
|
||||
return false;
|
||||
@ -2010,12 +2010,12 @@ bool cPluginManager::DoWithPlugin(const AString & a_PluginName, const cPluginCal
|
||||
|
||||
|
||||
|
||||
bool cPluginManager::ForEachPlugin(const cPluginCallback & a_Callback)
|
||||
bool cPluginManager::ForEachPlugin(cPluginCallback & a_Callback)
|
||||
{
|
||||
// TODO: Implement locking for plugins
|
||||
for (auto & plugin: m_Plugins)
|
||||
{
|
||||
if (a_Callback(*plugin))
|
||||
if (a_Callback.Item(plugin.get()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -1,9 +1,8 @@
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
#include "Defines.h"
|
||||
#include <functional>
|
||||
|
||||
|
||||
|
||||
@ -195,7 +194,7 @@ public:
|
||||
|
||||
|
||||
/** The interface used for enumerating and extern-calling plugins */
|
||||
using cPluginCallback = std::function<bool(cPlugin &)>;
|
||||
typedef cItemCallback<cPlugin> cPluginCallback;
|
||||
|
||||
typedef std::list<cPlugin *> PluginList;
|
||||
|
||||
@ -373,18 +372,18 @@ public:
|
||||
|
||||
/** Calls the specified callback with the plugin object of the specified plugin.
|
||||
Returns false if plugin not found, otherwise returns the value that the callback has returned. */
|
||||
bool DoWithPlugin(const AString & a_PluginName, const cPluginCallback & a_Callback);
|
||||
bool DoWithPlugin(const AString & a_PluginName, cPluginCallback & a_Callback);
|
||||
|
||||
/** Calls the specified callback for each plugin in m_Plugins.
|
||||
Returns true if all plugins have been reported, false if the callback has aborted the enumeration by returning true. */
|
||||
bool ForEachPlugin(const cPluginCallback & a_Callback);
|
||||
bool ForEachPlugin(cPluginCallback & a_Callback);
|
||||
|
||||
/** Returns the name of the folder (cPlugin::GetFolderName()) from which the specified plugin was loaded. */
|
||||
AString GetPluginFolderName(const AString & a_PluginName); // tolua_export
|
||||
|
||||
/** Returns the path where individual plugins' folders are expected.
|
||||
The path doesn't end in a slash. */
|
||||
static AString GetPluginsPath(void) { return FILE_IO_PREFIX "Plugins"; } // tolua_export
|
||||
static AString GetPluginsPath(void) { return FILE_IO_PREFIX + AString("Plugins"); } // tolua_export
|
||||
|
||||
private:
|
||||
friend class cRoot;
|
||||
|
@ -1,4 +1,4 @@
|
||||
|
||||
|
||||
// BlockArea.cpp
|
||||
|
||||
// NOTE: compile.sh checks for this file in order to determine if this is the Cuberite folder.
|
||||
@ -2239,7 +2239,7 @@ int cBlockArea::MakeIndex(int a_RelX, int a_RelY, int a_RelZ) const
|
||||
|
||||
|
||||
|
||||
bool cBlockArea::DoWithBlockEntityRelAt(int a_RelX, int a_RelY, int a_RelZ, const cBlockEntityCallback & a_Callback)
|
||||
bool cBlockArea::DoWithBlockEntityRelAt(int a_RelX, int a_RelY, int a_RelZ, cItemCallback<cBlockEntity> & a_Callback)
|
||||
{
|
||||
ASSERT(IsValidRelCoords(a_RelX, a_RelY, a_RelZ));
|
||||
if (!HasBlockEntities())
|
||||
@ -2252,14 +2252,14 @@ bool cBlockArea::DoWithBlockEntityRelAt(int a_RelX, int a_RelY, int a_RelZ, cons
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return a_Callback(*itr->second);
|
||||
return a_Callback.Item(itr->second);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cBlockArea::DoWithBlockEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cBlockEntityCallback & a_Callback)
|
||||
bool cBlockArea::DoWithBlockEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ, cItemCallback<cBlockEntity> & a_Callback)
|
||||
{
|
||||
return DoWithBlockEntityRelAt(a_BlockX - m_Origin.x, a_BlockY - m_Origin.y, a_BlockZ - m_Origin.z, a_Callback);
|
||||
}
|
||||
@ -2268,7 +2268,7 @@ bool cBlockArea::DoWithBlockEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ, c
|
||||
|
||||
|
||||
|
||||
bool cBlockArea::ForEachBlockEntity(const cBlockEntityCallback & a_Callback)
|
||||
bool cBlockArea::ForEachBlockEntity(cItemCallback<cBlockEntity> & a_Callback)
|
||||
{
|
||||
if (!HasBlockEntities())
|
||||
{
|
||||
@ -2276,7 +2276,7 @@ bool cBlockArea::ForEachBlockEntity(const cBlockEntityCallback & a_Callback)
|
||||
}
|
||||
for (auto & keyPair: *m_BlockEntities)
|
||||
{
|
||||
if (a_Callback(*keyPair.second))
|
||||
if (a_Callback.Item(keyPair.second))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
|
||||
|
||||
// BlockArea.h
|
||||
|
||||
// Interfaces to the cBlockArea object representing an area of block data that can be queried from cWorld and then accessed again without further queries
|
||||
@ -17,14 +17,13 @@
|
||||
#include "ForEachChunkProvider.h"
|
||||
#include "ChunkDataCallback.h"
|
||||
#include "Cuboid.h"
|
||||
#include <functional>
|
||||
|
||||
|
||||
|
||||
|
||||
// fwd:
|
||||
class cCuboid;
|
||||
using cBlockEntityCallback = std::function<bool(cBlockEntity &)>;
|
||||
|
||||
|
||||
|
||||
|
||||
@ -377,18 +376,18 @@ public:
|
||||
/** Calls the callback for the block entity at the specified coords.
|
||||
Returns false if there is no block entity at those coords, or the block area doesn't have baBlockEntities.
|
||||
Returns the value that the callback has returned if there is a block entity. */
|
||||
bool DoWithBlockEntityRelAt(int a_RelX, int a_RelY, int a_RelZ, const cBlockEntityCallback & a_Callback);
|
||||
bool DoWithBlockEntityRelAt(int a_RelX, int a_RelY, int a_RelZ, cItemCallback<cBlockEntity> & a_Callback);
|
||||
|
||||
/** Calls the callback for the block entity at the specified coords.
|
||||
Returns false if there is no block entity at those coords.
|
||||
Returns the value that the callback has returned if there is a block entity. */
|
||||
bool DoWithBlockEntityAt (int a_BlockX, int a_BlockY, int a_BlockZ, const cBlockEntityCallback & a_Callback);
|
||||
bool DoWithBlockEntityAt (int a_BlockX, int a_BlockY, int a_BlockZ, cItemCallback<cBlockEntity> & a_Callback);
|
||||
|
||||
/** Calls the callback for all the block entities.
|
||||
If the callback returns true, aborts the enumeration and returns false.
|
||||
If the callback returns true, continues with the next BE.
|
||||
Returns true if all block entities have been enumerated (including the case when there is none or the area is without baBlockEntities). */
|
||||
bool ForEachBlockEntity(const cBlockEntityCallback & a_Callback);
|
||||
bool ForEachBlockEntity(cItemCallback<cBlockEntity> & a_Callback);
|
||||
|
||||
/** Direct read-only access to block entities. */
|
||||
const cBlockEntities & GetBlockEntities(void) const { ASSERT(HasBlockEntities()); return *m_BlockEntities; }
|
||||
|
@ -1,4 +1,4 @@
|
||||
|
||||
|
||||
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
|
||||
|
||||
#include "BeaconEntity.h"
|
||||
@ -195,21 +195,33 @@ void cBeaconEntity::UpdateBeacon(void)
|
||||
GetWindow()->SetProperty(0, m_BeaconLevel);
|
||||
}
|
||||
|
||||
Vector3d BeaconPosition(m_PosX, m_PosY, m_PosZ);
|
||||
GetWorld()->ForEachPlayer([=](cPlayer & a_Player)
|
||||
class cPlayerCallback :
|
||||
public cPlayerListCallback
|
||||
{
|
||||
public:
|
||||
cPlayerCallback(Vector3d a_Position):
|
||||
m_Position(a_Position)
|
||||
{
|
||||
Vector3d Distance = BeaconPosition - a_Player.GetPosition();
|
||||
}
|
||||
|
||||
virtual bool Item(cPlayer * a_Player)
|
||||
{
|
||||
Vector3d Distance = m_Position - a_Player->GetPosition();
|
||||
if (
|
||||
(std::abs(Distance.y) <= 14) &&
|
||||
(std::abs(Distance.x) <= 20) &&
|
||||
(std::abs(Distance.z) <= 20)
|
||||
)
|
||||
{
|
||||
a_Player.AwardAchievement(eStatistic::achFullBeacon);
|
||||
a_Player->AwardAchievement(eStatistic::achFullBeacon);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
);
|
||||
|
||||
private:
|
||||
Vector3d m_Position;
|
||||
} PlayerCallback(Vector3d(m_PosX, m_PosY, m_PosZ));
|
||||
GetWorld()->ForEachPlayer(PlayerCallback);
|
||||
}
|
||||
}
|
||||
|
||||
@ -237,28 +249,46 @@ void cBeaconEntity::GiveEffects(void)
|
||||
SecondaryEffect = m_SecondaryEffect;
|
||||
}
|
||||
|
||||
Vector3d BeaconPosition(m_PosX, m_PosY, m_PosZ);
|
||||
GetWorld()->ForEachPlayer([=](cPlayer & a_Player)
|
||||
class cPlayerCallback : public cPlayerListCallback
|
||||
{
|
||||
int m_Radius;
|
||||
Vector3d m_Position;
|
||||
cEntityEffect::eType m_PrimaryEffect, m_SecondaryEffect;
|
||||
short m_EffectLevel;
|
||||
|
||||
virtual bool Item(cPlayer * a_Player)
|
||||
{
|
||||
auto PlayerPosition = a_Player.GetPosition();
|
||||
if (PlayerPosition.y > BeaconPosition.y)
|
||||
Vector3d PlayerPosition = Vector3d(a_Player->GetPosition());
|
||||
if (PlayerPosition.y > m_Position.y)
|
||||
{
|
||||
PlayerPosition.y = BeaconPosition.y;
|
||||
PlayerPosition.y = m_Position.y;
|
||||
}
|
||||
|
||||
// TODO: Vanilla minecraft uses an AABB check instead of a radius one
|
||||
if ((PlayerPosition - BeaconPosition).Length() <= Radius)
|
||||
if ((PlayerPosition - m_Position).Length() <= m_Radius)
|
||||
{
|
||||
a_Player.AddEntityEffect(m_PrimaryEffect, 180, EffectLevel);
|
||||
a_Player->AddEntityEffect(m_PrimaryEffect, 180, m_EffectLevel);
|
||||
|
||||
if (m_SecondaryEffect != cEntityEffect::effNoEffect)
|
||||
{
|
||||
a_Player.AddEntityEffect(m_SecondaryEffect, 180, 0);
|
||||
a_Player->AddEntityEffect(m_SecondaryEffect, 180, 0);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
);
|
||||
|
||||
public:
|
||||
cPlayerCallback(int a_Radius, Vector3d a_Position, cEntityEffect::eType a_PrimaryEffect, cEntityEffect::eType a_SecondaryEffect, short a_EffectLevel):
|
||||
m_Radius(a_Radius),
|
||||
m_Position(a_Position),
|
||||
m_PrimaryEffect(a_PrimaryEffect),
|
||||
m_SecondaryEffect(a_SecondaryEffect),
|
||||
m_EffectLevel(a_EffectLevel)
|
||||
{
|
||||
}
|
||||
|
||||
} PlayerCallback(Radius, Vector3d(m_PosX, m_PosY, m_PosZ), m_PrimaryEffect, SecondaryEffect, EffectLevel);
|
||||
GetWorld()->ForEachPlayer(PlayerCallback);
|
||||
}
|
||||
|
||||
|
||||
|
@ -138,18 +138,33 @@ bool cChestEntity::UsedBy(cPlayer * a_Player)
|
||||
void cChestEntity::ScanNeighbours()
|
||||
{
|
||||
// Callback for finding neighbouring chest:
|
||||
auto FindNeighbour = [this](cChestEntity & a_Chest)
|
||||
class cFindNeighbour :
|
||||
public cChestCallback
|
||||
{
|
||||
if (a_Chest.GetBlockType() != m_BlockType)
|
||||
public:
|
||||
cChestEntity * m_Neighbour;
|
||||
BLOCKTYPE m_ChestType;
|
||||
|
||||
cFindNeighbour(BLOCKTYPE a_ChestType) :
|
||||
m_Neighbour(nullptr),
|
||||
m_ChestType(a_ChestType)
|
||||
{
|
||||
// Neighboring block is not the same type of chest
|
||||
return true;
|
||||
}
|
||||
m_Neighbour = &a_Chest;
|
||||
return false;
|
||||
|
||||
virtual bool Item(cChestEntity * a_Chest) override
|
||||
{
|
||||
if (a_Chest->GetBlockType() != m_ChestType)
|
||||
{
|
||||
// Neighboring block is not the same type of chest
|
||||
return true;
|
||||
}
|
||||
m_Neighbour = a_Chest;
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
// Scan horizontally adjacent blocks for any neighbouring chest of the same type:
|
||||
cFindNeighbour FindNeighbour(m_BlockType);
|
||||
if (
|
||||
m_World->DoWithChestAt(m_PosX - 1, m_PosY, m_PosZ, FindNeighbour) ||
|
||||
m_World->DoWithChestAt(m_PosX + 1, m_PosY, m_PosZ, FindNeighbour) ||
|
||||
@ -157,6 +172,7 @@ void cChestEntity::ScanNeighbours()
|
||||
m_World->DoWithChestAt(m_PosX, m_PosY, m_PosZ + 1, FindNeighbour)
|
||||
)
|
||||
{
|
||||
m_Neighbour = FindNeighbour.m_Neighbour;
|
||||
m_Neighbour->m_Neighbour = this;
|
||||
// Force neighbour's window shut. Does Mojang server do this or should a double window open?
|
||||
m_Neighbour->DestroyWindow();
|
||||
|
@ -193,7 +193,8 @@ bool cHopperEntity::MovePickupsIn(cChunk & a_Chunk, Int64 a_CurrentTick)
|
||||
{
|
||||
UNUSED(a_CurrentTick);
|
||||
|
||||
class cHopperPickupSearchCallback
|
||||
class cHopperPickupSearchCallback :
|
||||
public cEntityCallback
|
||||
{
|
||||
public:
|
||||
cHopperPickupSearchCallback(const Vector3i & a_Pos, cItemGrid & a_Contents) :
|
||||
@ -203,20 +204,22 @@ bool cHopperEntity::MovePickupsIn(cChunk & a_Chunk, Int64 a_CurrentTick)
|
||||
{
|
||||
}
|
||||
|
||||
bool operator () (cEntity & a_Entity)
|
||||
virtual bool Item(cEntity * a_Entity) override
|
||||
{
|
||||
if (!a_Entity.IsPickup())
|
||||
ASSERT(a_Entity != nullptr);
|
||||
|
||||
if (!a_Entity->IsPickup())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Vector3f EntityPos = a_Entity.GetPosition();
|
||||
Vector3f EntityPos = a_Entity->GetPosition();
|
||||
Vector3f BlockPos(m_Pos.x + 0.5f, static_cast<float>(m_Pos.y) + 1, m_Pos.z + 0.5f); // One block above hopper, and search from center outwards
|
||||
double Distance = (EntityPos - BlockPos).Length();
|
||||
|
||||
if (Distance < 0.5)
|
||||
{
|
||||
if (TrySuckPickupIn(static_cast<cPickup &>(a_Entity)))
|
||||
if (TrySuckPickupIn(static_cast<cPickup *>(a_Entity)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -225,9 +228,9 @@ bool cHopperEntity::MovePickupsIn(cChunk & a_Chunk, Int64 a_CurrentTick)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TrySuckPickupIn(cPickup & a_Pickup)
|
||||
bool TrySuckPickupIn(cPickup * a_Pickup)
|
||||
{
|
||||
cItem & Item = a_Pickup.GetItem();
|
||||
cItem & Item = a_Pickup->GetItem();
|
||||
|
||||
for (int i = 0; i < ContentsWidth * ContentsHeight; i++)
|
||||
{
|
||||
@ -235,7 +238,7 @@ bool cHopperEntity::MovePickupsIn(cChunk & a_Chunk, Int64 a_CurrentTick)
|
||||
{
|
||||
m_bFoundPickupsAbove = true;
|
||||
m_Contents.SetSlot(i, Item);
|
||||
a_Pickup.Destroy(); // Kill pickup
|
||||
a_Pickup->Destroy(); // Kill pickup
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -249,7 +252,7 @@ bool cHopperEntity::MovePickupsIn(cChunk & a_Chunk, Int64 a_CurrentTick)
|
||||
|
||||
if (Item.IsEmpty())
|
||||
{
|
||||
a_Pickup.Destroy(); // Kill pickup if all items were added
|
||||
a_Pickup->Destroy(); // Kill pickup if all items were added
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
|
||||
|
||||
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
|
||||
|
||||
#include "MobSpawnerEntity.h"
|
||||
@ -138,36 +138,47 @@ void cMobSpawnerEntity::SpawnEntity(void)
|
||||
return;
|
||||
}
|
||||
|
||||
auto MobType = m_Entity;
|
||||
bool EntitiesSpawned = m_World->DoWithChunk(GetChunkX(), GetChunkZ(), [&](cChunk & a_Chunk)
|
||||
class cCallback : public cChunkCallback
|
||||
{
|
||||
public:
|
||||
cCallback(int a_RelX, int a_RelY, int a_RelZ, eMonsterType a_MobType, int a_NearbyEntitiesNum) :
|
||||
m_RelX(a_RelX),
|
||||
m_RelY(a_RelY),
|
||||
m_RelZ(a_RelZ),
|
||||
m_MobType(a_MobType),
|
||||
m_NearbyEntitiesNum(a_NearbyEntitiesNum)
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool Item(cChunk * a_Chunk)
|
||||
{
|
||||
auto & Random = GetRandomProvider();
|
||||
|
||||
bool HaveSpawnedEntity = false;
|
||||
bool EntitiesSpawned = false;
|
||||
for (size_t i = 0; i < 4; i++)
|
||||
{
|
||||
if (NearbyEntities >= 6)
|
||||
if (m_NearbyEntitiesNum >= 6)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
int RelX = m_RelX + static_cast<int>((Random.RandReal<double>() - Random.RandReal<double>()) * 4.0);
|
||||
int RelY = m_PosY + Random.RandInt(-1, 1);
|
||||
int RelY = m_RelY + Random.RandInt(-1, 1);
|
||||
int RelZ = m_RelZ + static_cast<int>((Random.RandReal<double>() - Random.RandReal<double>()) * 4.0);
|
||||
|
||||
cChunk * Chunk = a_Chunk.GetRelNeighborChunkAdjustCoords(RelX, RelZ);
|
||||
cChunk * Chunk = a_Chunk->GetRelNeighborChunkAdjustCoords(RelX, RelZ);
|
||||
if ((Chunk == nullptr) || !Chunk->IsValid())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
EMCSBiome Biome = Chunk->GetBiomeAt(RelX, RelZ);
|
||||
|
||||
if (cMobSpawner::CanSpawnHere(Chunk, RelX, RelY, RelZ, MobType, Biome))
|
||||
if (cMobSpawner::CanSpawnHere(Chunk, RelX, RelY, RelZ, m_MobType, Biome))
|
||||
{
|
||||
double PosX = Chunk->GetPosX() * cChunkDef::Width + RelX;
|
||||
double PosZ = Chunk->GetPosZ() * cChunkDef::Width + RelZ;
|
||||
|
||||
auto Monster = cMonster::NewMonsterFromType(MobType);
|
||||
auto Monster = cMonster::NewMonsterFromType(m_MobType);
|
||||
if (Monster == nullptr)
|
||||
{
|
||||
continue;
|
||||
@ -177,7 +188,7 @@ void cMobSpawnerEntity::SpawnEntity(void)
|
||||
Monster->SetYaw(Random.RandReal(360.0f));
|
||||
if (Chunk->GetWorld()->SpawnMobFinalize(std::move(Monster)) != cEntity::INVALID_ID)
|
||||
{
|
||||
HaveSpawnedEntity = true;
|
||||
EntitiesSpawned = true;
|
||||
Chunk->BroadcastSoundParticleEffect(
|
||||
EffectID::PARTICLE_MOBSPAWN,
|
||||
static_cast<int>(PosX * 8.0),
|
||||
@ -185,15 +196,19 @@ void cMobSpawnerEntity::SpawnEntity(void)
|
||||
static_cast<int>(PosZ * 8.0),
|
||||
0
|
||||
);
|
||||
NearbyEntities++;
|
||||
m_NearbyEntitiesNum++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return EntitiesSpawned;
|
||||
}
|
||||
);
|
||||
protected:
|
||||
int m_RelX, m_RelY, m_RelZ;
|
||||
eMonsterType m_MobType;
|
||||
int m_NearbyEntitiesNum;
|
||||
} Callback(m_RelX, m_PosY, m_RelZ, m_Entity, NearbyEntities);
|
||||
|
||||
if (EntitiesSpawned)
|
||||
if (m_World->DoWithChunk(GetChunkX(), GetChunkZ(), Callback))
|
||||
{
|
||||
ResetTimer();
|
||||
}
|
||||
|
@ -1,12 +1,12 @@
|
||||
|
||||
|
||||
// BlockBed.cpp
|
||||
|
||||
#include "Globals.h"
|
||||
#include "BlockBed.h"
|
||||
|
||||
#include "BroadcastInterface.h"
|
||||
#include "Entities/../World.h"
|
||||
#include "Entities/Player.h"
|
||||
#include "../World.h"
|
||||
#include "../BoundingBox.h"
|
||||
#include "../Mobs/Monster.h"
|
||||
#include "../BlockEntities/BedEntity.h"
|
||||
@ -53,6 +53,66 @@ void cBlockBedHandler::OnDestroyed(cChunkInterface & a_ChunkInterface, cWorldInt
|
||||
|
||||
|
||||
|
||||
class cFindMobs :
|
||||
public cEntityCallback
|
||||
{
|
||||
virtual bool Item(cEntity * a_Entity) override
|
||||
{
|
||||
return (
|
||||
(a_Entity->GetEntityType() == cEntity::etMonster) &&
|
||||
(static_cast<cMonster*>(a_Entity)->GetMobFamily() == cMonster::mfHostile)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class cTimeFastForwardTester :
|
||||
public cPlayerListCallback
|
||||
{
|
||||
virtual bool Item(cPlayer * a_Player) override
|
||||
{
|
||||
if (!a_Player->IsInBed())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class cPlayerBedStateUnsetter :
|
||||
public cPlayerListCallback
|
||||
{
|
||||
public:
|
||||
cPlayerBedStateUnsetter(Vector3i a_Position, cChunkInterface & a_ChunkInterface) :
|
||||
m_Position(a_Position),
|
||||
m_ChunkInterface(a_ChunkInterface)
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool Item(cPlayer * a_Player) override
|
||||
{
|
||||
cBlockBedHandler::SetBedOccupationState(m_ChunkInterface, a_Player->GetLastBedPos(), false);
|
||||
a_Player->SetIsInBed(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
Vector3i m_Position;
|
||||
cChunkInterface & m_ChunkInterface;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cBlockBedHandler::OnUse(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ)
|
||||
{
|
||||
if (a_WorldInterface.GetDimension() != dimOverworld)
|
||||
@ -73,14 +133,7 @@ bool cBlockBedHandler::OnUse(cChunkInterface & a_ChunkInterface, cWorldInterface
|
||||
}
|
||||
else
|
||||
{
|
||||
auto FindMobs = [](cEntity & a_Entity)
|
||||
{
|
||||
return (
|
||||
(a_Entity.GetEntityType() == cEntity::etMonster) &&
|
||||
(static_cast<cMonster&>(a_Entity).GetMobFamily() == cMonster::mfHostile)
|
||||
);
|
||||
};
|
||||
|
||||
cFindMobs FindMobs;
|
||||
if (!a_Player.GetWorld()->ForEachEntityInBox(cBoundingBox(a_Player.GetPosition() - Vector3i(0, 5, 0), 8, 10), FindMobs))
|
||||
{
|
||||
a_Player.SendMessageFailure("You may not rest now, there are monsters nearby");
|
||||
@ -111,24 +164,11 @@ bool cBlockBedHandler::OnUse(cChunkInterface & a_ChunkInterface, cWorldInterface
|
||||
a_Player.SetIsInBed(true);
|
||||
a_Player.SendMessageSuccess("Home position set successfully");
|
||||
|
||||
auto TimeFastForwardTester = [](cPlayer & a_OtherPlayer)
|
||||
cTimeFastForwardTester Tester;
|
||||
if (a_WorldInterface.ForEachPlayer(Tester))
|
||||
{
|
||||
if (!a_OtherPlayer.IsInBed())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
if (a_WorldInterface.ForEachPlayer(TimeFastForwardTester))
|
||||
{
|
||||
a_WorldInterface.ForEachPlayer([&](cPlayer & a_OtherPlayer)
|
||||
{
|
||||
cBlockBedHandler::SetBedOccupationState(a_ChunkInterface, a_OtherPlayer.GetLastBedPos(), false);
|
||||
a_OtherPlayer.SetIsInBed(false);
|
||||
return false;
|
||||
}
|
||||
);
|
||||
cPlayerBedStateUnsetter Unsetter(Vector3i(a_BlockX + PillowDirection.x, a_BlockY, a_BlockZ + PillowDirection.z), a_ChunkInterface);
|
||||
a_WorldInterface.ForEachPlayer(Unsetter);
|
||||
a_WorldInterface.SetTimeOfDay(0);
|
||||
a_ChunkInterface.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, Meta & 0x0b); // Clear the "occupied" bit of the bed's block
|
||||
}
|
||||
@ -144,12 +184,25 @@ bool cBlockBedHandler::OnUse(cChunkInterface & a_ChunkInterface, cWorldInterface
|
||||
|
||||
void cBlockBedHandler::OnPlacedByPlayer(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer & a_Player, const sSetBlock & a_BlockChange)
|
||||
{
|
||||
a_Player.GetWorld()->DoWithBedAt(a_BlockChange.GetX(), a_BlockChange.GetY(), a_BlockChange.GetZ(), [&](cBedEntity & a_Bed)
|
||||
class cBedColor :
|
||||
public cBedCallback
|
||||
{
|
||||
public:
|
||||
short m_Color;
|
||||
|
||||
cBedColor(short a_Color) :
|
||||
m_Color(a_Color)
|
||||
{
|
||||
a_Bed.SetColor(a_Player.GetEquippedItem().m_ItemDamage);
|
||||
}
|
||||
|
||||
virtual bool Item(cBedEntity * a_Bed) override
|
||||
{
|
||||
a_Bed->SetColor(m_Color);
|
||||
return true;
|
||||
}
|
||||
);
|
||||
};
|
||||
cBedColor BedCallback(a_Player.GetEquippedItem().m_ItemDamage);
|
||||
a_Player.GetWorld()->DoWithBedAt(a_BlockChange.GetX(), a_BlockChange.GetY(), a_BlockChange.GetZ(), BedCallback);
|
||||
}
|
||||
|
||||
|
||||
@ -158,12 +211,19 @@ void cBlockBedHandler::OnPlacedByPlayer(cChunkInterface & a_ChunkInterface, cWor
|
||||
|
||||
void cBlockBedHandler::ConvertToPickups(cWorldInterface & a_WorldInterface, cItems & a_Pickups, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ)
|
||||
{
|
||||
short Color = E_META_WOOL_RED;
|
||||
a_WorldInterface.DoWithBedAt(a_BlockX, a_BlockY, a_BlockZ, [&](cBedEntity & a_Bed)
|
||||
class cBedColor :
|
||||
public cBedCallback
|
||||
{
|
||||
public:
|
||||
short m_Color = E_META_WOOL_RED;
|
||||
|
||||
virtual bool Item(cBedEntity * a_Bed) override
|
||||
{
|
||||
Color = a_Bed.GetColor();
|
||||
m_Color = a_Bed->GetColor();
|
||||
return true;
|
||||
}
|
||||
);
|
||||
a_Pickups.Add(cItem(E_ITEM_BED, 1, Color));
|
||||
};
|
||||
cBedColor BedCallback;
|
||||
a_WorldInterface.DoWithBedAt(a_BlockX, a_BlockY, a_BlockZ, BedCallback);
|
||||
a_Pickups.Add(cItem(E_ITEM_BED, 1, BedCallback.m_Color));
|
||||
}
|
||||
|
@ -30,32 +30,36 @@ public:
|
||||
return;
|
||||
}
|
||||
|
||||
a_WorldInterface.DoWithBlockEntityAt(a_BlockX, a_BlockY, a_BlockZ, [](cBlockEntity & a_BlockEntity)
|
||||
class cCallback : public cBlockEntityCallback
|
||||
{
|
||||
virtual bool Item(cBlockEntity * a_BlockEntity)
|
||||
{
|
||||
if (a_BlockEntity.GetBlockType() != E_BLOCK_HEAD)
|
||||
if (a_BlockEntity->GetBlockType() != E_BLOCK_HEAD)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
auto & MobHeadEntity = static_cast<cMobHeadEntity&>(a_BlockEntity);
|
||||
cMobHeadEntity * MobHeadEntity = static_cast<cMobHeadEntity*>(a_BlockEntity);
|
||||
|
||||
cItems Pickups;
|
||||
Pickups.Add(E_ITEM_HEAD, 1, static_cast<short>(MobHeadEntity.GetType()));
|
||||
Pickups.Add(E_ITEM_HEAD, 1, static_cast<short>(MobHeadEntity->GetType()));
|
||||
auto & r1 = GetRandomProvider();
|
||||
|
||||
// Mid-block position first
|
||||
double MicroX, MicroY, MicroZ;
|
||||
MicroX = MobHeadEntity.GetPosX() + 0.5;
|
||||
MicroY = MobHeadEntity.GetPosY() + 0.5;
|
||||
MicroZ = MobHeadEntity.GetPosZ() + 0.5;
|
||||
MicroX = MobHeadEntity->GetPosX() + 0.5;
|
||||
MicroY = MobHeadEntity->GetPosY() + 0.5;
|
||||
MicroZ = MobHeadEntity->GetPosZ() + 0.5;
|
||||
|
||||
// Add random offset second
|
||||
MicroX += r1.RandReal<double>(-0.5, 0.5);
|
||||
MicroZ += r1.RandReal<double>(-0.5, 0.5);
|
||||
|
||||
MobHeadEntity.GetWorld()->SpawnItemPickups(Pickups, MicroX, MicroY, MicroZ);
|
||||
MobHeadEntity->GetWorld()->SpawnItemPickups(Pickups, MicroX, MicroY, MicroZ);
|
||||
return false;
|
||||
}
|
||||
);
|
||||
} Callback;
|
||||
|
||||
a_WorldInterface.DoWithBlockEntityAt(a_BlockX, a_BlockY, a_BlockZ, Callback);
|
||||
}
|
||||
|
||||
virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) override
|
||||
|
@ -1,18 +1,15 @@
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include "../Mobs/MonsterTypes.h"
|
||||
|
||||
class cBedEntity;
|
||||
class cBlockEntity;
|
||||
|
||||
typedef cItemCallback<cBlockEntity> cBlockEntityCallback;
|
||||
class cBroadcastInterface;
|
||||
class cItems;
|
||||
class cPlayer;
|
||||
|
||||
using cBedCallback = std::function<bool(cBedEntity &)>;
|
||||
using cBlockEntityCallback = std::function<bool(cBlockEntity &)>;
|
||||
using cPlayerListCallback = std::function<bool(cPlayer &)>;
|
||||
|
||||
|
||||
|
||||
@ -31,10 +28,7 @@ public:
|
||||
|
||||
virtual void DoExplosionAt(double a_ExplosionSize, double a_BlockX, double a_BlockY, double a_BlockZ, bool a_CanCauseFire, eExplosionSource a_Source, void * a_SourceData) = 0;
|
||||
|
||||
virtual bool DoWithBedAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cBedCallback & a_Callback) = 0;
|
||||
|
||||
/** 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 */
|
||||
virtual bool DoWithBlockEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cBlockEntityCallback & a_Callback) = 0;
|
||||
virtual bool DoWithBedAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBedCallback & a_Callback) = 0;
|
||||
|
||||
/** 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) = 0;
|
||||
@ -52,16 +46,19 @@ public:
|
||||
Returns the UniqueID of the spawned experience orb, or cEntity::INVALID_ID on failure. */
|
||||
virtual UInt32 SpawnExperienceOrb(double a_X, double a_Y, double a_Z, int a_Reward) = 0;
|
||||
|
||||
/** 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 */
|
||||
virtual bool DoWithBlockEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBlockEntityCallback & a_Callback) = 0;
|
||||
|
||||
/** Sends the block on those coords to the player */
|
||||
virtual void SendBlockTo(int a_BlockX, int a_BlockY, int a_BlockZ, cPlayer & a_Player) = 0;
|
||||
|
||||
/** Calls the callback for each player in the list; returns true if all players processed, false if the callback aborted by returning true */
|
||||
virtual bool ForEachPlayer(const cPlayerListCallback & a_Callback) = 0;
|
||||
virtual bool ForEachPlayer(cItemCallback<cPlayer> & a_Callback) = 0;
|
||||
|
||||
/** Calls the callback for each entity that has a nonempty intersection with the specified boundingbox.
|
||||
Returns true if all entities processed, false if the callback aborted by returning true.
|
||||
If any chunk in the box is missing, ignores the entities in that chunk silently. */
|
||||
virtual bool ForEachEntityInBox(const cBoundingBox & a_Box, const cEntityCallback & a_Callback) = 0;
|
||||
virtual bool ForEachEntityInBox(const cBoundingBox & a_Box, cEntityCallback & a_Callback) = 0;
|
||||
|
||||
virtual void SetTimeOfDay(int a_TimeOfDay) = 0;
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
|
||||
|
||||
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
|
||||
|
||||
#ifndef _WIN32
|
||||
@ -2114,12 +2114,17 @@ bool cChunk::HasEntity(UInt32 a_EntityID)
|
||||
|
||||
|
||||
|
||||
bool cChunk::ForEachEntity(const cEntityCallback & a_Callback)
|
||||
bool cChunk::ForEachEntity(cEntityCallback & a_Callback)
|
||||
{
|
||||
// The entity list is locked by the parent chunkmap's CS
|
||||
for (const auto & Entity : m_Entities)
|
||||
for (auto itr = m_Entities.begin(), itr2 = itr; itr != m_Entities.end(); itr = itr2)
|
||||
{
|
||||
if (Entity->IsTicking() && a_Callback(*Entity))
|
||||
++itr2;
|
||||
if (!(*itr)->IsTicking())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (a_Callback.Item(itr->get()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -2131,22 +2136,23 @@ bool cChunk::ForEachEntity(const cEntityCallback & a_Callback)
|
||||
|
||||
|
||||
|
||||
bool cChunk::ForEachEntityInBox(const cBoundingBox & a_Box, const cEntityCallback & a_Callback)
|
||||
bool cChunk::ForEachEntityInBox(const cBoundingBox & a_Box, cEntityCallback & a_Callback)
|
||||
{
|
||||
// The entity list is locked by the parent chunkmap's CS
|
||||
for (const auto & Entity : m_Entities)
|
||||
for (auto itr = m_Entities.begin(), itr2 = itr; itr != m_Entities.end(); itr = itr2)
|
||||
{
|
||||
if (!Entity->IsTicking())
|
||||
++itr2;
|
||||
if (!(*itr)->IsTicking())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
cBoundingBox EntBox(Entity->GetPosition(), Entity->GetWidth() / 2, Entity->GetHeight());
|
||||
cBoundingBox EntBox((*itr)->GetPosition(), (*itr)->GetWidth() / 2, (*itr)->GetHeight());
|
||||
if (!EntBox.DoesIntersect(a_Box))
|
||||
{
|
||||
// The entity is not in the specified box
|
||||
continue;
|
||||
}
|
||||
if (a_Callback(*Entity))
|
||||
if (a_Callback.Item(itr->get()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -2158,14 +2164,23 @@ bool cChunk::ForEachEntityInBox(const cBoundingBox & a_Box, const cEntityCallbac
|
||||
|
||||
|
||||
|
||||
bool cChunk::DoWithEntityByID(UInt32 a_EntityID, const cEntityCallback & a_Callback, bool & a_CallbackResult)
|
||||
bool cChunk::DoWithEntityByID(UInt32 a_EntityID, cEntityCallback & a_Callback, bool & a_CallbackResult)
|
||||
{
|
||||
return DoWithEntityByID(a_EntityID, std::bind(&cEntityCallback::Item, &a_Callback, std::placeholders::_1), a_CallbackResult);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cChunk::DoWithEntityByID(UInt32 a_EntityID, cLambdaEntityCallback a_Callback, bool & a_CallbackResult)
|
||||
{
|
||||
// The entity list is locked by the parent chunkmap's CS
|
||||
for (const auto & Entity : m_Entities)
|
||||
{
|
||||
if ((Entity->GetUniqueID() == a_EntityID) && (Entity->IsTicking()))
|
||||
{
|
||||
a_CallbackResult = a_Callback(*Entity);
|
||||
a_CallbackResult = a_Callback(Entity.get());
|
||||
return true;
|
||||
}
|
||||
} // for itr - m_Entitites[]
|
||||
@ -2177,7 +2192,7 @@ bool cChunk::DoWithEntityByID(UInt32 a_EntityID, const cEntityCallback & a_Callb
|
||||
|
||||
|
||||
template <class tyEntity, BLOCKTYPE... tBlocktype>
|
||||
bool cChunk::GenericForEachBlockEntity(const std::function<bool(tyEntity &)> & a_Callback)
|
||||
bool cChunk::GenericForEachBlockEntity(cItemCallback<tyEntity>& a_Callback)
|
||||
{
|
||||
// The blockentity list is locked by the parent chunkmap's CS
|
||||
for (auto & KeyPair : m_BlockEntities)
|
||||
@ -2188,7 +2203,7 @@ bool cChunk::GenericForEachBlockEntity(const std::function<bool(tyEntity &)> & a
|
||||
(IsOneOf<tBlocktype...>(Block->GetBlockType()))
|
||||
)
|
||||
{
|
||||
if (a_Callback(*static_cast<tyEntity *>(Block)))
|
||||
if (a_Callback.Item(static_cast<tyEntity *>(Block)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -2201,7 +2216,7 @@ bool cChunk::GenericForEachBlockEntity(const std::function<bool(tyEntity &)> & a
|
||||
|
||||
|
||||
|
||||
bool cChunk::ForEachBlockEntity(const cBlockEntityCallback & a_Callback)
|
||||
bool cChunk::ForEachBlockEntity(cBlockEntityCallback & a_Callback)
|
||||
{
|
||||
return GenericForEachBlockEntity<cBlockEntity>(a_Callback);
|
||||
}
|
||||
@ -2210,7 +2225,7 @@ bool cChunk::ForEachBlockEntity(const cBlockEntityCallback & a_Callback)
|
||||
|
||||
|
||||
|
||||
bool cChunk::ForEachBrewingstand(const cBrewingstandCallback & a_Callback)
|
||||
bool cChunk::ForEachBrewingstand(cBrewingstandCallback & a_Callback)
|
||||
{
|
||||
return GenericForEachBlockEntity<cBrewingstandEntity,
|
||||
E_BLOCK_BREWING_STAND
|
||||
@ -2221,7 +2236,7 @@ bool cChunk::ForEachBrewingstand(const cBrewingstandCallback & a_Callback)
|
||||
|
||||
|
||||
|
||||
bool cChunk::ForEachChest(const cChestCallback & a_Callback)
|
||||
bool cChunk::ForEachChest(cChestCallback & a_Callback)
|
||||
{
|
||||
return GenericForEachBlockEntity<cChestEntity,
|
||||
E_BLOCK_CHEST
|
||||
@ -2232,7 +2247,7 @@ bool cChunk::ForEachChest(const cChestCallback & a_Callback)
|
||||
|
||||
|
||||
|
||||
bool cChunk::ForEachDispenser(const cDispenserCallback & a_Callback)
|
||||
bool cChunk::ForEachDispenser(cDispenserCallback & a_Callback)
|
||||
{
|
||||
return GenericForEachBlockEntity<cDispenserEntity,
|
||||
E_BLOCK_DISPENSER
|
||||
@ -2243,7 +2258,7 @@ bool cChunk::ForEachDispenser(const cDispenserCallback & a_Callback)
|
||||
|
||||
|
||||
|
||||
bool cChunk::ForEachDropper(const cDropperCallback & a_Callback)
|
||||
bool cChunk::ForEachDropper(cDropperCallback & a_Callback)
|
||||
{
|
||||
return GenericForEachBlockEntity<cDropperEntity,
|
||||
E_BLOCK_DROPPER
|
||||
@ -2254,7 +2269,7 @@ bool cChunk::ForEachDropper(const cDropperCallback & a_Callback)
|
||||
|
||||
|
||||
|
||||
bool cChunk::ForEachDropSpenser(const cDropSpenserCallback & a_Callback)
|
||||
bool cChunk::ForEachDropSpenser(cDropSpenserCallback & a_Callback)
|
||||
{
|
||||
return GenericForEachBlockEntity<cDropSpenserEntity,
|
||||
E_BLOCK_DISPENSER,
|
||||
@ -2266,7 +2281,7 @@ bool cChunk::ForEachDropSpenser(const cDropSpenserCallback & a_Callback)
|
||||
|
||||
|
||||
|
||||
bool cChunk::ForEachFurnace(const cFurnaceCallback & a_Callback)
|
||||
bool cChunk::ForEachFurnace(cFurnaceCallback & a_Callback)
|
||||
{
|
||||
return GenericForEachBlockEntity<cFurnaceEntity,
|
||||
E_BLOCK_FURNACE,
|
||||
@ -2279,7 +2294,7 @@ bool cChunk::ForEachFurnace(const cFurnaceCallback & a_Callback)
|
||||
|
||||
|
||||
template <class tyEntity, BLOCKTYPE... tBlocktype>
|
||||
bool cChunk::GenericDoWithBlockEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ, const std::function<bool(tyEntity &)> & a_Callback)
|
||||
bool cChunk::GenericDoWithBlockEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ, cItemCallback<tyEntity>& a_Callback)
|
||||
{
|
||||
// The blockentity list is locked by the parent chunkmap's CS
|
||||
cBlockEntity * Block = GetBlockEntity(a_BlockX, a_BlockY, a_BlockZ);
|
||||
@ -2294,14 +2309,14 @@ bool cChunk::GenericDoWithBlockEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ
|
||||
{
|
||||
return false; // Not any of the given tBlocktypes
|
||||
}
|
||||
return !a_Callback(*static_cast<tyEntity *>(Block));
|
||||
return !a_Callback.Item(static_cast<tyEntity *>(Block));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cChunk::DoWithBlockEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cBlockEntityCallback & a_Callback)
|
||||
bool cChunk::DoWithBlockEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBlockEntityCallback & a_Callback)
|
||||
{
|
||||
return GenericDoWithBlockEntityAt<cBlockEntity>(a_BlockX, a_BlockY, a_BlockZ, a_Callback);
|
||||
}
|
||||
@ -2309,7 +2324,7 @@ bool cChunk::DoWithBlockEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ, const
|
||||
|
||||
|
||||
|
||||
bool cChunk::DoWithBeaconAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cBeaconCallback & a_Callback)
|
||||
bool cChunk::DoWithBeaconAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBeaconCallback & a_Callback)
|
||||
{
|
||||
return GenericDoWithBlockEntityAt<cBeaconEntity,
|
||||
E_BLOCK_BEACON
|
||||
@ -2319,7 +2334,7 @@ bool cChunk::DoWithBeaconAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cBea
|
||||
|
||||
|
||||
|
||||
bool cChunk::DoWithBedAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cBedCallback & a_Callback)
|
||||
bool cChunk::DoWithBedAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBedCallback & a_Callback)
|
||||
{
|
||||
return GenericDoWithBlockEntityAt<cBedEntity,
|
||||
E_BLOCK_BED
|
||||
@ -2329,7 +2344,7 @@ bool cChunk::DoWithBedAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cBedCal
|
||||
|
||||
|
||||
|
||||
bool cChunk::DoWithBrewingstandAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cBrewingstandCallback & a_Callback)
|
||||
bool cChunk::DoWithBrewingstandAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBrewingstandCallback & a_Callback)
|
||||
{
|
||||
return GenericDoWithBlockEntityAt<cBrewingstandEntity,
|
||||
E_BLOCK_BREWING_STAND
|
||||
@ -2340,7 +2355,7 @@ bool cChunk::DoWithBrewingstandAt(int a_BlockX, int a_BlockY, int a_BlockZ, cons
|
||||
|
||||
|
||||
|
||||
bool cChunk::DoWithChestAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cChestCallback & a_Callback)
|
||||
bool cChunk::DoWithChestAt(int a_BlockX, int a_BlockY, int a_BlockZ, cChestCallback & a_Callback)
|
||||
{
|
||||
return GenericDoWithBlockEntityAt<cChestEntity,
|
||||
E_BLOCK_CHEST,
|
||||
@ -2352,7 +2367,7 @@ bool cChunk::DoWithChestAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cChes
|
||||
|
||||
|
||||
|
||||
bool cChunk::DoWithDispenserAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cDispenserCallback & a_Callback)
|
||||
bool cChunk::DoWithDispenserAt(int a_BlockX, int a_BlockY, int a_BlockZ, cDispenserCallback & a_Callback)
|
||||
{
|
||||
return GenericDoWithBlockEntityAt<cDispenserEntity,
|
||||
E_BLOCK_DISPENSER
|
||||
@ -2363,7 +2378,7 @@ bool cChunk::DoWithDispenserAt(int a_BlockX, int a_BlockY, int a_BlockZ, const c
|
||||
|
||||
|
||||
|
||||
bool cChunk::DoWithDropperAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cDropperCallback & a_Callback)
|
||||
bool cChunk::DoWithDropperAt(int a_BlockX, int a_BlockY, int a_BlockZ, cDropperCallback & a_Callback)
|
||||
{
|
||||
return GenericDoWithBlockEntityAt<cDropperEntity,
|
||||
E_BLOCK_DROPPER
|
||||
@ -2374,7 +2389,7 @@ bool cChunk::DoWithDropperAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cDr
|
||||
|
||||
|
||||
|
||||
bool cChunk::DoWithDropSpenserAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cDropSpenserCallback & a_Callback)
|
||||
bool cChunk::DoWithDropSpenserAt(int a_BlockX, int a_BlockY, int a_BlockZ, cDropSpenserCallback & a_Callback)
|
||||
{
|
||||
return GenericDoWithBlockEntityAt<cDropSpenserEntity,
|
||||
E_BLOCK_DISPENSER,
|
||||
@ -2386,7 +2401,7 @@ bool cChunk::DoWithDropSpenserAt(int a_BlockX, int a_BlockY, int a_BlockZ, const
|
||||
|
||||
|
||||
|
||||
bool cChunk::DoWithFurnaceAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cFurnaceCallback & a_Callback)
|
||||
bool cChunk::DoWithFurnaceAt(int a_BlockX, int a_BlockY, int a_BlockZ, cFurnaceCallback & a_Callback)
|
||||
{
|
||||
return GenericDoWithBlockEntityAt<cFurnaceEntity,
|
||||
E_BLOCK_FURNACE,
|
||||
@ -2398,7 +2413,7 @@ bool cChunk::DoWithFurnaceAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cFu
|
||||
|
||||
|
||||
|
||||
bool cChunk::DoWithNoteBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cNoteBlockCallback & a_Callback)
|
||||
bool cChunk::DoWithNoteBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cNoteBlockCallback & a_Callback)
|
||||
{
|
||||
return GenericDoWithBlockEntityAt<cNoteEntity,
|
||||
E_BLOCK_NOTE_BLOCK
|
||||
@ -2409,7 +2424,7 @@ bool cChunk::DoWithNoteBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, const c
|
||||
|
||||
|
||||
|
||||
bool cChunk::DoWithCommandBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cCommandBlockCallback & a_Callback)
|
||||
bool cChunk::DoWithCommandBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cCommandBlockCallback & a_Callback)
|
||||
{
|
||||
return GenericDoWithBlockEntityAt<cCommandBlockEntity,
|
||||
E_BLOCK_COMMAND_BLOCK
|
||||
@ -2420,7 +2435,7 @@ bool cChunk::DoWithCommandBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cons
|
||||
|
||||
|
||||
|
||||
bool cChunk::DoWithMobHeadAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cMobHeadCallback & a_Callback)
|
||||
bool cChunk::DoWithMobHeadAt(int a_BlockX, int a_BlockY, int a_BlockZ, cMobHeadCallback & a_Callback)
|
||||
{
|
||||
return GenericDoWithBlockEntityAt<cMobHeadEntity,
|
||||
E_BLOCK_HEAD
|
||||
@ -2431,7 +2446,7 @@ bool cChunk::DoWithMobHeadAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cMo
|
||||
|
||||
|
||||
|
||||
bool cChunk::DoWithFlowerPotAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cFlowerPotCallback & a_Callback)
|
||||
bool cChunk::DoWithFlowerPotAt(int a_BlockX, int a_BlockY, int a_BlockZ, cFlowerPotCallback & a_Callback)
|
||||
{
|
||||
return GenericDoWithBlockEntityAt<cFlowerPotEntity,
|
||||
E_BLOCK_FLOWER_POT
|
||||
|
66
src/Chunk.h
66
src/Chunk.h
@ -1,4 +1,4 @@
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Entities/Entity.h"
|
||||
@ -37,7 +37,18 @@ class cMobCensus;
|
||||
class cMobSpawner;
|
||||
class cSetChunkData;
|
||||
|
||||
typedef std::list<cClientHandle *> cClientHandleList;
|
||||
typedef std::list<cClientHandle *> cClientHandleList;
|
||||
typedef cItemCallback<cEntity> cEntityCallback;
|
||||
typedef cItemCallback<cBeaconEntity> cBeaconCallback;
|
||||
typedef cItemCallback<cBedEntity> cBedCallback;
|
||||
typedef cItemCallback<cBrewingstandEntity> cBrewingstandCallback;
|
||||
typedef cItemCallback<cChestEntity> cChestCallback;
|
||||
typedef cItemCallback<cDispenserEntity> cDispenserCallback;
|
||||
typedef cItemCallback<cFurnaceEntity> cFurnaceCallback;
|
||||
typedef cItemCallback<cNoteEntity> cNoteBlockCallback;
|
||||
typedef cItemCallback<cCommandBlockEntity> cCommandBlockCallback;
|
||||
typedef cItemCallback<cMobHeadEntity> cMobHeadCallback;
|
||||
typedef cItemCallback<cFlowerPotEntity> cFlowerPotCallback;
|
||||
|
||||
// A convenience macro for calling GetChunkAndRelByAbsolute.
|
||||
#define PREPARE_REL_AND_CHUNK(Position, OriginalChunk) cChunk * Chunk; Vector3i Rel; bool RelSuccess = (OriginalChunk).GetChunkAndRelByAbsolute(Position, &Chunk, Rel);
|
||||
@ -247,86 +258,87 @@ public:
|
||||
bool HasEntity(UInt32 a_EntityID);
|
||||
|
||||
/** Calls the callback for each entity; returns true if all entities processed, false if the callback aborted by returning true */
|
||||
bool ForEachEntity(const cEntityCallback & a_Callback); // Lua-accessible
|
||||
bool ForEachEntity(cEntityCallback & a_Callback); // Lua-accessible
|
||||
|
||||
/** Calls the callback for each entity that has a nonempty intersection with the specified boundingbox.
|
||||
Returns true if all entities processed, false if the callback aborted by returning true. */
|
||||
bool ForEachEntityInBox(const cBoundingBox & a_Box, const cEntityCallback & a_Callback); // Lua-accessible
|
||||
bool ForEachEntityInBox(const cBoundingBox & a_Box, 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. */
|
||||
bool DoWithEntityByID(UInt32 a_EntityID, const cEntityCallback & a_Callback, bool & a_CallbackResult); // Lua-accessible
|
||||
bool DoWithEntityByID(UInt32 a_EntityID, cEntityCallback & a_Callback, bool & a_CallbackResult); // Lua-accessible
|
||||
bool DoWithEntityByID(UInt32 a_EntityID, cLambdaEntityCallback a_Callback, bool & a_CallbackResult); // Lambda version
|
||||
|
||||
/** Calls the callback for each tyEntity; returns true if all block entities processed, false if the callback aborted by returning true
|
||||
tBlocktypes are all blocktypes convertible to tyEntity which are to be called. If no block type is given the callback is called for every block entity
|
||||
Accessible only from within Chunk.cpp */
|
||||
template <class tyEntity, BLOCKTYPE... tBlocktype>
|
||||
bool GenericForEachBlockEntity(const std::function<bool(tyEntity &)> & a_Callback);
|
||||
bool GenericForEachBlockEntity(cItemCallback<tyEntity>& a_Callback);
|
||||
|
||||
/** Calls the callback for each block entity; returns true if all block entities processed, false if the callback aborted by returning true */
|
||||
bool ForEachBlockEntity(const cBlockEntityCallback & a_Callback); // Lua-accessible
|
||||
bool ForEachBlockEntity(cBlockEntityCallback & a_Callback); // Lua-accessible
|
||||
|
||||
/** Calls the callback for each brewingstand; returns true if all brewingstands processed, false if the callback aborted by returning true */
|
||||
bool ForEachBrewingstand(const cBrewingstandCallback & a_Callback); // Lua-accessible
|
||||
bool ForEachBrewingstand(cBrewingstandCallback & a_Callback); // Lua-accessible
|
||||
|
||||
/** Calls the callback for each chest; returns true if all chests processed, false if the callback aborted by returning true */
|
||||
bool ForEachChest(const cChestCallback & a_Callback); // Lua-accessible
|
||||
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 */
|
||||
bool ForEachDispenser(const cDispenserCallback & a_Callback);
|
||||
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 */
|
||||
bool ForEachDropper(const cDropperCallback & a_Callback);
|
||||
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 */
|
||||
bool ForEachDropSpenser(const cDropSpenserCallback & a_Callback);
|
||||
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 */
|
||||
bool ForEachFurnace(const cFurnaceCallback & a_Callback); // Lua-accessible
|
||||
bool ForEachFurnace(cFurnaceCallback & a_Callback); // Lua-accessible
|
||||
|
||||
/** Calls the callback for the tyEntity at the specified coords; returns false if there's no such block entity at those coords, true if found
|
||||
tBlocktype is a list of the blocktypes to be called. If no BLOCKTYPE template arguments are given the callback is called for any block entity
|
||||
Accessible only from within Chunk.cpp */
|
||||
template <class tyEntity, BLOCKTYPE... tBlocktype>
|
||||
bool GenericDoWithBlockEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ, const std::function<bool(tyEntity &)> & a_Callback);
|
||||
bool GenericDoWithBlockEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ, cItemCallback<tyEntity>& a_Callback);
|
||||
|
||||
/** 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, const cBlockEntityCallback & a_Callback); // Lua-acessible
|
||||
bool DoWithBlockEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBlockEntityCallback & a_Callback); // Lua-acessible
|
||||
|
||||
/** Calls the callback for the beacon at the specified coords; returns false if there's no beacon at those coords, true if found */
|
||||
bool DoWithBeaconAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cBeaconCallback & a_Callback); // Lua-acessible
|
||||
bool DoWithBeaconAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBeaconCallback & a_Callback); // Lua-acessible
|
||||
|
||||
/** Calls the callback for the brewingstand at the specified coords; returns false if there's no brewingstand at those coords, true if found */
|
||||
bool DoWithBrewingstandAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cBrewingstandCallback & a_Callback); // Lua-acessible
|
||||
bool DoWithBrewingstandAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBrewingstandCallback & a_Callback); // Lua-acessible
|
||||
|
||||
/** Calls the callback for the bed at the specified coords; returns false if there's no bed at those coords, true if found */
|
||||
bool DoWithBedAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cBedCallback & a_Callback); // Lua-acessible
|
||||
bool DoWithBedAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBedCallback & 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 */
|
||||
bool DoWithChestAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cChestCallback & a_Callback); // Lua-acessible
|
||||
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 */
|
||||
bool DoWithDispenserAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cDispenserCallback & a_Callback);
|
||||
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 */
|
||||
bool DoWithDropperAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cDropperCallback & a_Callback);
|
||||
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 */
|
||||
bool DoWithDropSpenserAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cDropSpenserCallback & a_Callback);
|
||||
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 */
|
||||
bool DoWithFurnaceAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cFurnaceCallback & a_Callback); // Lua-accessible
|
||||
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 */
|
||||
bool DoWithNoteBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cNoteBlockCallback & a_Callback);
|
||||
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 */
|
||||
bool DoWithCommandBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cCommandBlockCallback & a_Callback);
|
||||
bool DoWithCommandBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cCommandBlockCallback & a_Callback);
|
||||
|
||||
/** Calls the callback for the mob head block at the specified coords; returns false if there's no mob head block at those coords or callback returns true, returns true if found */
|
||||
bool DoWithMobHeadAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cMobHeadCallback & a_Callback);
|
||||
bool DoWithMobHeadAt(int a_BlockX, int a_BlockY, int a_BlockZ, cMobHeadCallback & a_Callback);
|
||||
|
||||
/** Calls the callback for the flower pot at the specified coords; returns false if there's no flower pot at those coords or callback returns true, returns true if found */
|
||||
bool DoWithFlowerPotAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cFlowerPotCallback & a_Callback);
|
||||
bool DoWithFlowerPotAt(int a_BlockX, int a_BlockY, int a_BlockZ, cFlowerPotCallback & 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 */
|
||||
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
|
||||
|
131
src/ChunkMap.cpp
131
src/ChunkMap.cpp
@ -1,4 +1,4 @@
|
||||
|
||||
|
||||
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
|
||||
|
||||
#include "ChunkMap.h"
|
||||
@ -731,7 +731,7 @@ bool cChunkMap::UseBlockEntity(cPlayer * a_Player, int a_BlockX, int a_BlockY, i
|
||||
|
||||
|
||||
|
||||
bool cChunkMap::DoWithChunk(int a_ChunkX, int a_ChunkZ, const cChunkCallback & a_Callback)
|
||||
bool cChunkMap::DoWithChunk(int a_ChunkX, int a_ChunkZ, cChunkCallback & a_Callback)
|
||||
{
|
||||
cCSLock Lock(m_CSChunks);
|
||||
cChunkPtr Chunk = GetChunkNoLoad(a_ChunkX, a_ChunkZ);
|
||||
@ -739,15 +739,30 @@ bool cChunkMap::DoWithChunk(int a_ChunkX, int a_ChunkZ, const cChunkCallback & a
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return a_Callback(*Chunk);
|
||||
return a_Callback.Item(Chunk);
|
||||
}
|
||||
|
||||
|
||||
bool cChunkMap::DoWithChunkAt(Vector3i a_BlockPos, const cChunkCallback & a_Callback)
|
||||
bool cChunkMap::DoWithChunkAt(Vector3i a_BlockPos, std::function<bool(cChunk &)> a_Callback)
|
||||
{
|
||||
int ChunkX, ChunkZ;
|
||||
cChunkDef::BlockToChunk(a_BlockPos.x, a_BlockPos.z, ChunkX, ChunkZ);
|
||||
return DoWithChunk(ChunkX, ChunkZ, a_Callback);
|
||||
struct cCallBackWrapper : cChunkCallback
|
||||
{
|
||||
cCallBackWrapper(std::function<bool(cChunk &)> a_InnerCallback) :
|
||||
m_Callback(a_InnerCallback)
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool Item(cChunk * a_Chunk)
|
||||
{
|
||||
return m_Callback(*a_Chunk);
|
||||
}
|
||||
|
||||
private:
|
||||
std::function<bool(cChunk &)> m_Callback;
|
||||
} callback(a_Callback);
|
||||
return DoWithChunk(ChunkX, ChunkZ, callback);
|
||||
}
|
||||
|
||||
|
||||
@ -1583,7 +1598,7 @@ OwnedEntity cChunkMap::RemoveEntity(cEntity & a_Entity)
|
||||
|
||||
|
||||
|
||||
bool cChunkMap::ForEachEntity(const cEntityCallback & a_Callback)
|
||||
bool cChunkMap::ForEachEntity(cEntityCallback & a_Callback)
|
||||
{
|
||||
cCSLock Lock(m_CSChunks);
|
||||
for (const auto & Chunk : m_Chunks)
|
||||
@ -1600,7 +1615,7 @@ bool cChunkMap::ForEachEntity(const cEntityCallback & a_Callback)
|
||||
|
||||
|
||||
|
||||
bool cChunkMap::ForEachEntityInChunk(int a_ChunkX, int a_ChunkZ, const cEntityCallback & a_Callback)
|
||||
bool cChunkMap::ForEachEntityInChunk(int a_ChunkX, int a_ChunkZ, cEntityCallback & a_Callback)
|
||||
{
|
||||
cCSLock Lock(m_CSChunks);
|
||||
cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, a_ChunkZ);
|
||||
@ -1615,7 +1630,7 @@ bool cChunkMap::ForEachEntityInChunk(int a_ChunkX, int a_ChunkZ, const cEntityCa
|
||||
|
||||
|
||||
|
||||
bool cChunkMap::ForEachEntityInBox(const cBoundingBox & a_Box, const cEntityCallback & a_Callback)
|
||||
bool cChunkMap::ForEachEntityInBox(const cBoundingBox & a_Box, cEntityCallback & a_Callback)
|
||||
{
|
||||
// Calculate the chunk range for the box:
|
||||
int MinChunkX = FloorC(a_Box.GetMinX() / cChunkDef::Width);
|
||||
@ -1777,41 +1792,60 @@ void cChunkMap::DoExplosionAt(double a_ExplosionSize, double a_BlockX, double a_
|
||||
area.Write(*m_World, bx - ExplosionSizeInt, MinY, bz - ExplosionSizeInt);
|
||||
}
|
||||
|
||||
Vector3d ExplosionPos{ a_BlockX, a_BlockY, a_BlockZ };
|
||||
cBoundingBox bbTNT(ExplosionPos, 0.5, 1);
|
||||
bbTNT.Expand(ExplosionSizeInt * 2, ExplosionSizeInt * 2, ExplosionSizeInt * 2);
|
||||
|
||||
ForEachEntity([&](cEntity & a_Entity)
|
||||
class cTNTDamageCallback :
|
||||
public cEntityCallback
|
||||
{
|
||||
public:
|
||||
cTNTDamageCallback(cBoundingBox & a_CBBBTNT, Vector3d a_CBExplosionPos, int a_CBExplosionSize) :
|
||||
m_bbTNT(a_CBBBTNT),
|
||||
m_ExplosionPos(a_CBExplosionPos),
|
||||
m_ExplosionSize(a_CBExplosionSize)
|
||||
{
|
||||
if (a_Entity.IsPickup() && (a_Entity.GetTicksAlive() < 20))
|
||||
}
|
||||
|
||||
virtual bool Item(cEntity * a_Entity) override
|
||||
{
|
||||
if (a_Entity->IsPickup() && (a_Entity->GetTicksAlive() < 20))
|
||||
{
|
||||
// If pickup age is smaller than one second, it is invincible (so we don't kill pickups that were just spawned)
|
||||
return false;
|
||||
}
|
||||
|
||||
Vector3d DistanceFromExplosion = a_Entity.GetPosition() - ExplosionPos;
|
||||
Vector3d DistanceFromExplosion = a_Entity->GetPosition() - m_ExplosionPos;
|
||||
|
||||
if (!a_Entity.IsTNT() && !a_Entity.IsFallingBlock()) // Don't apply damage to other TNT entities and falling blocks, they should be invincible
|
||||
if (!a_Entity->IsTNT() && !a_Entity->IsFallingBlock()) // Don't apply damage to other TNT entities and falling blocks, they should be invincible
|
||||
{
|
||||
cBoundingBox bbEntity(a_Entity.GetPosition(), a_Entity.GetWidth() / 2, a_Entity.GetHeight());
|
||||
cBoundingBox bbEntity(a_Entity->GetPosition(), a_Entity->GetWidth() / 2, a_Entity->GetHeight());
|
||||
|
||||
if (!bbTNT.IsInside(bbEntity)) // If bbEntity is inside bbTNT, not vice versa!
|
||||
if (!m_bbTNT.IsInside(bbEntity)) // If bbEntity is inside bbTNT, not vice versa!
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Ensure that the damage dealt is inversely proportional to the distance to the TNT centre - the closer a player is, the harder they are hit
|
||||
a_Entity.TakeDamage(dtExplosion, nullptr, static_cast<int>((1 / DistanceFromExplosion.Length()) * 6 * ExplosionSizeInt), 0);
|
||||
a_Entity->TakeDamage(dtExplosion, nullptr, static_cast<int>((1 / DistanceFromExplosion.Length()) * 6 * m_ExplosionSize), 0);
|
||||
}
|
||||
|
||||
// Apply force to entities around the explosion - code modified from World.cpp DoExplosionAt()
|
||||
DistanceFromExplosion.Normalize();
|
||||
DistanceFromExplosion *= ExplosionSizeInt * ExplosionSizeInt;
|
||||
a_Entity.AddSpeed(DistanceFromExplosion);
|
||||
DistanceFromExplosion *= m_ExplosionSize * m_ExplosionSize;
|
||||
a_Entity->AddSpeed(DistanceFromExplosion);
|
||||
|
||||
return false;
|
||||
}
|
||||
);
|
||||
|
||||
protected:
|
||||
cBoundingBox & m_bbTNT;
|
||||
Vector3d m_ExplosionPos;
|
||||
int m_ExplosionSize;
|
||||
};
|
||||
|
||||
cBoundingBox bbTNT(Vector3d(a_BlockX, a_BlockY, a_BlockZ), 0.5, 1);
|
||||
bbTNT.Expand(ExplosionSizeInt * 2, ExplosionSizeInt * 2, ExplosionSizeInt * 2);
|
||||
|
||||
|
||||
cTNTDamageCallback TNTDamageCallback(bbTNT, Vector3d(a_BlockX, a_BlockY, a_BlockZ), ExplosionSizeInt);
|
||||
ForEachEntity(TNTDamageCallback);
|
||||
|
||||
// Wake up all simulators for the area, so that water and lava flows and sand falls into the blasted holes (FS #391):
|
||||
m_World->GetSimulatorManager()->WakeUpArea(cCuboid(
|
||||
@ -1824,7 +1858,16 @@ void cChunkMap::DoExplosionAt(double a_ExplosionSize, double a_BlockX, double a_
|
||||
|
||||
|
||||
|
||||
bool cChunkMap::DoWithEntityByID(UInt32 a_UniqueID, const cEntityCallback & a_Callback)
|
||||
bool cChunkMap::DoWithEntityByID(UInt32 a_UniqueID, cEntityCallback & a_Callback)
|
||||
{
|
||||
return DoWithEntityByID(a_UniqueID, std::bind(&cEntityCallback::Item, &a_Callback, std::placeholders::_1));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cChunkMap::DoWithEntityByID(UInt32 a_UniqueID, cLambdaEntityCallback a_Callback)
|
||||
{
|
||||
cCSLock Lock(m_CSChunks);
|
||||
bool res = false;
|
||||
@ -1842,7 +1885,7 @@ bool cChunkMap::DoWithEntityByID(UInt32 a_UniqueID, const cEntityCallback & a_Ca
|
||||
|
||||
|
||||
|
||||
bool cChunkMap::ForEachBlockEntityInChunk(int a_ChunkX, int a_ChunkZ, const cBlockEntityCallback & a_Callback)
|
||||
bool cChunkMap::ForEachBlockEntityInChunk(int a_ChunkX, int a_ChunkZ, cBlockEntityCallback & a_Callback)
|
||||
{
|
||||
cCSLock Lock(m_CSChunks);
|
||||
cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, a_ChunkZ);
|
||||
@ -1857,7 +1900,7 @@ bool cChunkMap::ForEachBlockEntityInChunk(int a_ChunkX, int a_ChunkZ, const cBlo
|
||||
|
||||
|
||||
|
||||
bool cChunkMap::ForEachBrewingstandInChunk(int a_ChunkX, int a_ChunkZ, const cBrewingstandCallback & a_Callback)
|
||||
bool cChunkMap::ForEachBrewingstandInChunk(int a_ChunkX, int a_ChunkZ, cBrewingstandCallback & a_Callback)
|
||||
{
|
||||
cCSLock Lock(m_CSChunks);
|
||||
cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, a_ChunkZ);
|
||||
@ -1872,7 +1915,7 @@ bool cChunkMap::ForEachBrewingstandInChunk(int a_ChunkX, int a_ChunkZ, const cBr
|
||||
|
||||
|
||||
|
||||
bool cChunkMap::ForEachChestInChunk(int a_ChunkX, int a_ChunkZ, const cChestCallback & a_Callback)
|
||||
bool cChunkMap::ForEachChestInChunk(int a_ChunkX, int a_ChunkZ, cChestCallback & a_Callback)
|
||||
{
|
||||
cCSLock Lock(m_CSChunks);
|
||||
cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, a_ChunkZ);
|
||||
@ -1887,7 +1930,7 @@ bool cChunkMap::ForEachChestInChunk(int a_ChunkX, int a_ChunkZ, const cChestCall
|
||||
|
||||
|
||||
|
||||
bool cChunkMap::ForEachDispenserInChunk(int a_ChunkX, int a_ChunkZ, const cDispenserCallback & a_Callback)
|
||||
bool cChunkMap::ForEachDispenserInChunk(int a_ChunkX, int a_ChunkZ, cDispenserCallback & a_Callback)
|
||||
{
|
||||
cCSLock Lock(m_CSChunks);
|
||||
cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, a_ChunkZ);
|
||||
@ -1902,7 +1945,7 @@ bool cChunkMap::ForEachDispenserInChunk(int a_ChunkX, int a_ChunkZ, const cDispe
|
||||
|
||||
|
||||
|
||||
bool cChunkMap::ForEachDropperInChunk(int a_ChunkX, int a_ChunkZ, const cDropperCallback & a_Callback)
|
||||
bool cChunkMap::ForEachDropperInChunk(int a_ChunkX, int a_ChunkZ, cDropperCallback & a_Callback)
|
||||
{
|
||||
cCSLock Lock(m_CSChunks);
|
||||
cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, a_ChunkZ);
|
||||
@ -1917,7 +1960,7 @@ bool cChunkMap::ForEachDropperInChunk(int a_ChunkX, int a_ChunkZ, const cDropper
|
||||
|
||||
|
||||
|
||||
bool cChunkMap::ForEachDropSpenserInChunk(int a_ChunkX, int a_ChunkZ, const cDropSpenserCallback & a_Callback)
|
||||
bool cChunkMap::ForEachDropSpenserInChunk(int a_ChunkX, int a_ChunkZ, cDropSpenserCallback & a_Callback)
|
||||
{
|
||||
cCSLock Lock(m_CSChunks);
|
||||
cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, a_ChunkZ);
|
||||
@ -1932,7 +1975,7 @@ bool cChunkMap::ForEachDropSpenserInChunk(int a_ChunkX, int a_ChunkZ, const cDro
|
||||
|
||||
|
||||
|
||||
bool cChunkMap::ForEachFurnaceInChunk(int a_ChunkX, int a_ChunkZ, const cFurnaceCallback & a_Callback)
|
||||
bool cChunkMap::ForEachFurnaceInChunk(int a_ChunkX, int a_ChunkZ, cFurnaceCallback & a_Callback)
|
||||
{
|
||||
cCSLock Lock(m_CSChunks);
|
||||
cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, a_ChunkZ);
|
||||
@ -1947,7 +1990,7 @@ bool cChunkMap::ForEachFurnaceInChunk(int a_ChunkX, int a_ChunkZ, const cFurnace
|
||||
|
||||
|
||||
|
||||
bool cChunkMap::DoWithBlockEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cBlockEntityCallback & a_Callback)
|
||||
bool cChunkMap::DoWithBlockEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBlockEntityCallback & a_Callback)
|
||||
{
|
||||
int ChunkX, ChunkZ;
|
||||
int BlockX = a_BlockX, BlockY = a_BlockY, BlockZ = a_BlockZ;
|
||||
@ -1965,7 +2008,7 @@ bool cChunkMap::DoWithBlockEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ, co
|
||||
|
||||
|
||||
|
||||
bool cChunkMap::DoWithBeaconAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cBeaconCallback & a_Callback)
|
||||
bool cChunkMap::DoWithBeaconAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBeaconCallback & a_Callback)
|
||||
{
|
||||
int ChunkX, ChunkZ;
|
||||
int BlockX = a_BlockX, BlockY = a_BlockY, BlockZ = a_BlockZ;
|
||||
@ -1983,7 +2026,7 @@ bool cChunkMap::DoWithBeaconAt(int a_BlockX, int a_BlockY, int a_BlockZ, const c
|
||||
|
||||
|
||||
|
||||
bool cChunkMap::DoWithBedAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cBedCallback & a_Callback)
|
||||
bool cChunkMap::DoWithBedAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBedCallback & a_Callback)
|
||||
{
|
||||
int ChunkX, ChunkZ;
|
||||
int BlockX = a_BlockX, BlockY = a_BlockY, BlockZ = a_BlockZ;
|
||||
@ -2001,7 +2044,7 @@ bool cChunkMap::DoWithBedAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cBed
|
||||
|
||||
|
||||
|
||||
bool cChunkMap::DoWithBrewingstandAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cBrewingstandCallback & a_Callback)
|
||||
bool cChunkMap::DoWithBrewingstandAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBrewingstandCallback & a_Callback)
|
||||
{
|
||||
int ChunkX, ChunkZ;
|
||||
int BlockX = a_BlockX, BlockY = a_BlockY, BlockZ = a_BlockZ;
|
||||
@ -2019,7 +2062,7 @@ bool cChunkMap::DoWithBrewingstandAt(int a_BlockX, int a_BlockY, int a_BlockZ, c
|
||||
|
||||
|
||||
|
||||
bool cChunkMap::DoWithChestAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cChestCallback & a_Callback)
|
||||
bool cChunkMap::DoWithChestAt(int a_BlockX, int a_BlockY, int a_BlockZ, cChestCallback & a_Callback)
|
||||
{
|
||||
int ChunkX, ChunkZ;
|
||||
int BlockX = a_BlockX, BlockY = a_BlockY, BlockZ = a_BlockZ;
|
||||
@ -2037,7 +2080,7 @@ bool cChunkMap::DoWithChestAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cC
|
||||
|
||||
|
||||
|
||||
bool cChunkMap::DoWithDispenserAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cDispenserCallback & a_Callback)
|
||||
bool cChunkMap::DoWithDispenserAt(int a_BlockX, int a_BlockY, int a_BlockZ, cDispenserCallback & a_Callback)
|
||||
{
|
||||
int ChunkX, ChunkZ;
|
||||
int BlockX = a_BlockX, BlockY = a_BlockY, BlockZ = a_BlockZ;
|
||||
@ -2055,7 +2098,7 @@ bool cChunkMap::DoWithDispenserAt(int a_BlockX, int a_BlockY, int a_BlockZ, cons
|
||||
|
||||
|
||||
|
||||
bool cChunkMap::DoWithDropperAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cDropperCallback & a_Callback)
|
||||
bool cChunkMap::DoWithDropperAt(int a_BlockX, int a_BlockY, int a_BlockZ, cDropperCallback & a_Callback)
|
||||
{
|
||||
int ChunkX, ChunkZ;
|
||||
int BlockX = a_BlockX, BlockY = a_BlockY, BlockZ = a_BlockZ;
|
||||
@ -2073,7 +2116,7 @@ bool cChunkMap::DoWithDropperAt(int a_BlockX, int a_BlockY, int a_BlockZ, const
|
||||
|
||||
|
||||
|
||||
bool cChunkMap::DoWithDropSpenserAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cDropSpenserCallback & a_Callback)
|
||||
bool cChunkMap::DoWithDropSpenserAt(int a_BlockX, int a_BlockY, int a_BlockZ, cDropSpenserCallback & a_Callback)
|
||||
{
|
||||
int ChunkX, ChunkZ;
|
||||
int BlockX = a_BlockX, BlockY = a_BlockY, BlockZ = a_BlockZ;
|
||||
@ -2091,7 +2134,7 @@ bool cChunkMap::DoWithDropSpenserAt(int a_BlockX, int a_BlockY, int a_BlockZ, co
|
||||
|
||||
|
||||
|
||||
bool cChunkMap::DoWithFurnaceAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cFurnaceCallback & a_Callback)
|
||||
bool cChunkMap::DoWithFurnaceAt(int a_BlockX, int a_BlockY, int a_BlockZ, cFurnaceCallback & a_Callback)
|
||||
{
|
||||
int ChunkX, ChunkZ;
|
||||
int BlockX = a_BlockX, BlockY = a_BlockY, BlockZ = a_BlockZ;
|
||||
@ -2108,7 +2151,7 @@ bool cChunkMap::DoWithFurnaceAt(int a_BlockX, int a_BlockY, int a_BlockZ, const
|
||||
|
||||
|
||||
|
||||
bool cChunkMap::DoWithNoteBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cNoteBlockCallback & a_Callback)
|
||||
bool cChunkMap::DoWithNoteBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cNoteBlockCallback & a_Callback)
|
||||
{
|
||||
int ChunkX, ChunkZ;
|
||||
int BlockX = a_BlockX, BlockY = a_BlockY, BlockZ = a_BlockZ;
|
||||
@ -2125,7 +2168,7 @@ bool cChunkMap::DoWithNoteBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cons
|
||||
|
||||
|
||||
|
||||
bool cChunkMap::DoWithCommandBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cCommandBlockCallback & a_Callback)
|
||||
bool cChunkMap::DoWithCommandBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cCommandBlockCallback & a_Callback)
|
||||
{
|
||||
int ChunkX, ChunkZ;
|
||||
int BlockX = a_BlockX, BlockY = a_BlockY, BlockZ = a_BlockZ;
|
||||
@ -2143,7 +2186,7 @@ bool cChunkMap::DoWithCommandBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, c
|
||||
|
||||
|
||||
|
||||
bool cChunkMap::DoWithMobHeadAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cMobHeadCallback & a_Callback)
|
||||
bool cChunkMap::DoWithMobHeadAt(int a_BlockX, int a_BlockY, int a_BlockZ, cMobHeadCallback & a_Callback)
|
||||
{
|
||||
int ChunkX, ChunkZ;
|
||||
int BlockX = a_BlockX, BlockY = a_BlockY, BlockZ = a_BlockZ;
|
||||
@ -2161,7 +2204,7 @@ bool cChunkMap::DoWithMobHeadAt(int a_BlockX, int a_BlockY, int a_BlockZ, const
|
||||
|
||||
|
||||
|
||||
bool cChunkMap::DoWithFlowerPotAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cFlowerPotCallback & a_Callback)
|
||||
bool cChunkMap::DoWithFlowerPotAt(int a_BlockX, int a_BlockY, int a_BlockZ, cFlowerPotCallback & a_Callback)
|
||||
{
|
||||
int ChunkX, ChunkZ;
|
||||
int BlockX = a_BlockX, BlockY = a_BlockY, BlockZ = a_BlockZ;
|
||||
@ -2399,7 +2442,7 @@ bool cChunkMap::ForEachChunkInRect(int a_MinChunkX, int a_MaxChunkX, int a_MinCh
|
||||
|
||||
|
||||
|
||||
bool cChunkMap::ForEachLoadedChunk(const std::function<bool(int, int)> & a_Callback)
|
||||
bool cChunkMap::ForEachLoadedChunk(std::function<bool(int, int)> a_Callback)
|
||||
{
|
||||
cCSLock Lock(m_CSChunks);
|
||||
for (const auto & Chunk : m_Chunks)
|
||||
|
@ -1,4 +1,4 @@
|
||||
|
||||
|
||||
// cChunkMap.h
|
||||
|
||||
// Interfaces to the cChunkMap class representing the chunk storage for a single world
|
||||
@ -38,23 +38,25 @@ class cSetChunkData;
|
||||
class cBoundingBox;
|
||||
class cDeadlockDetect;
|
||||
|
||||
typedef std::list<cClientHandle *> cClientHandleList;
|
||||
typedef cChunk * cChunkPtr;
|
||||
using cEntityCallback = std::function<bool(cEntity &)>;
|
||||
using cBeaconCallback = std::function<bool(cBeaconEntity &)>;
|
||||
using cBedCallback = std::function<bool(cBedEntity &)>;
|
||||
using cBlockEntityCallback = std::function<bool(cBlockEntity &)>;
|
||||
using cBrewingstandCallback = std::function<bool(cBrewingstandEntity &)>;
|
||||
using cChestCallback = std::function<bool(cChestEntity &)>;
|
||||
using cChunkCallback = std::function<bool(cChunk &)>;
|
||||
using cDispenserCallback = std::function<bool(cDispenserEntity &)>;
|
||||
using cDropperCallback = std::function<bool(cDropperEntity &)>;
|
||||
using cDropSpenserCallback = std::function<bool(cDropSpenserEntity &)>;
|
||||
using cFurnaceCallback = std::function<bool(cFurnaceEntity &)>;
|
||||
using cNoteBlockCallback = std::function<bool(cNoteEntity &)>;
|
||||
using cCommandBlockCallback = std::function<bool(cCommandBlockEntity &)>;
|
||||
using cMobHeadCallback = std::function<bool(cMobHeadEntity &)>;
|
||||
using cFlowerPotCallback = std::function<bool(cFlowerPotEntity &)>;
|
||||
typedef std::list<cClientHandle *> cClientHandleList;
|
||||
typedef cChunk * cChunkPtr;
|
||||
typedef cItemCallback<cEntity> cEntityCallback;
|
||||
typedef cItemCallback<cBlockEntity> cBlockEntityCallback;
|
||||
typedef cItemCallback<cBeaconEntity> cBeaconCallback;
|
||||
typedef cItemCallback<cBedEntity> cBedCallback;
|
||||
typedef cItemCallback<cBrewingstandEntity> cBrewingstandCallback;
|
||||
typedef cItemCallback<cChestEntity> cChestCallback;
|
||||
typedef cItemCallback<cDispenserEntity> cDispenserCallback;
|
||||
typedef cItemCallback<cDropperEntity> cDropperCallback;
|
||||
typedef cItemCallback<cDropSpenserEntity> cDropSpenserCallback;
|
||||
typedef cItemCallback<cFlowerPotEntity> cFlowerPotCallback;
|
||||
typedef cItemCallback<cFurnaceEntity> cFurnaceCallback;
|
||||
typedef cItemCallback<cNoteEntity> cNoteBlockCallback;
|
||||
typedef cItemCallback<cCommandBlockEntity> cCommandBlockCallback;
|
||||
typedef cItemCallback<cMobHeadEntity> cMobHeadCallback;
|
||||
typedef cItemCallback<cChunk> cChunkCallback;
|
||||
|
||||
typedef std::function<bool (cEntity *)> cLambdaEntityCallback;
|
||||
|
||||
|
||||
|
||||
@ -104,10 +106,10 @@ public:
|
||||
bool 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 */
|
||||
bool DoWithChunk(int a_ChunkX, int a_ChunkZ, const cChunkCallback & a_Callback);
|
||||
bool DoWithChunk(int a_ChunkX, int a_ChunkZ, cChunkCallback & a_Callback);
|
||||
|
||||
/** Calls the callback for the chunk at the block position specified, with ChunkMapCS locked; returns false if the chunk doesn't exist, otherwise returns the same value as the callback */
|
||||
bool DoWithChunkAt(Vector3i a_BlockPos, const cChunkCallback & a_Callback);
|
||||
bool DoWithChunkAt(Vector3i a_BlockPos, std::function<bool(cChunk &)> a_Callback);
|
||||
|
||||
/** Wakes up simulators for the specified block */
|
||||
void WakeUpSimulators(Vector3i a_Block);
|
||||
@ -228,101 +230,102 @@ public:
|
||||
OwnedEntity 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 */
|
||||
bool ForEachEntity(const cEntityCallback & a_Callback); // Lua-accessible
|
||||
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 */
|
||||
bool ForEachEntityInChunk(int a_ChunkX, int a_ChunkZ, const cEntityCallback & a_Callback); // Lua-accessible
|
||||
bool ForEachEntityInChunk(int a_ChunkX, int a_ChunkZ, cEntityCallback & a_Callback); // Lua-accessible
|
||||
|
||||
/** Calls the callback for each entity that has a nonempty intersection with the specified boundingbox.
|
||||
Returns true if all entities processed, false if the callback aborted by returning true.
|
||||
If any chunk in the box is missing, ignores the entities in that chunk silently. */
|
||||
bool ForEachEntityInBox(const cBoundingBox & a_Box, const cEntityCallback & a_Callback); // Lua-accessible
|
||||
bool ForEachEntityInBox(const cBoundingBox & a_Box, cEntityCallback & a_Callback); // Lua-accessible
|
||||
|
||||
/** 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. */
|
||||
bool DoWithEntityByID(UInt32 a_EntityID, const cEntityCallback & a_Callback); // Lua-accessible
|
||||
bool DoWithEntityByID(UInt32 a_EntityID, cEntityCallback & a_Callback); // Lua-accessible
|
||||
bool DoWithEntityByID(UInt32 a_EntityID, cLambdaEntityCallback a_Callback); // Lambda version
|
||||
|
||||
/** 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, const cBlockEntityCallback & a_Callback); // Lua-accessible
|
||||
bool ForEachBlockEntityInChunk(int a_ChunkX, int a_ChunkZ, cBlockEntityCallback & a_Callback); // Lua-accessible
|
||||
|
||||
/** Calls the callback for brewingstand in the specified chunk.
|
||||
Returns true if all brewingstands processed, false if the callback aborted by returning true. */
|
||||
bool ForEachBrewingstandInChunk(int a_ChunkX, int a_ChunkZ, const cBrewingstandCallback & a_Callback); // Lua-accessible
|
||||
bool ForEachBrewingstandInChunk(int a_ChunkX, int a_ChunkZ, cBrewingstandCallback & 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. */
|
||||
bool ForEachChestInChunk(int a_ChunkX, int a_ChunkZ, const cChestCallback & a_Callback); // Lua-accessible
|
||||
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. */
|
||||
bool ForEachDispenserInChunk(int a_ChunkX, int a_ChunkZ, const cDispenserCallback & a_Callback);
|
||||
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. */
|
||||
bool ForEachDropperInChunk(int a_ChunkX, int a_ChunkZ, const cDropperCallback & a_Callback);
|
||||
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. */
|
||||
bool ForEachDropSpenserInChunk(int a_ChunkX, int a_ChunkZ, const cDropSpenserCallback & a_Callback);
|
||||
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. */
|
||||
bool ForEachFurnaceInChunk(int a_ChunkX, int a_ChunkZ, const cFurnaceCallback & a_Callback); // Lua-accessible
|
||||
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. */
|
||||
bool DoWithBlockEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cBlockEntityCallback & a_Callback); // Lua-acessible
|
||||
bool DoWithBlockEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBlockEntityCallback & a_Callback); // Lua-acessible
|
||||
|
||||
/** Calls the callback for the beacon at the specified coords.
|
||||
Returns false if there's no beacon at those coords, true if found. */
|
||||
bool DoWithBeaconAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cBeaconCallback & a_Callback); // Lua-acessible
|
||||
bool DoWithBeaconAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBeaconCallback & a_Callback); // Lua-acessible
|
||||
|
||||
/** Calls the callback for the bed at the specified coords.
|
||||
Returns false if there's no bed at those coords, true if found. */
|
||||
bool DoWithBedAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cBedCallback & a_Callback); // Lua-acessible
|
||||
bool DoWithBedAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBedCallback & a_Callback); // Lua-acessible
|
||||
|
||||
/** Calls the callback for the brewingstand at the specified coords; returns false if there's no brewingstand at those coords, true if found */
|
||||
bool DoWithBrewingstandAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cBrewingstandCallback & a_Callback); // Lua-acessible
|
||||
bool DoWithBrewingstandAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBrewingstandCallback & 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. */
|
||||
bool DoWithChestAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cChestCallback & a_Callback); // Lua-acessible
|
||||
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. */
|
||||
bool DoWithDispenserAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cDispenserCallback & a_Callback); // Lua-accessible
|
||||
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. */
|
||||
bool DoWithDropperAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cDropperCallback & a_Callback); // Lua-accessible
|
||||
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. */
|
||||
bool DoWithDropSpenserAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cDropSpenserCallback & a_Callback); // Lua-accessible
|
||||
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. */
|
||||
bool DoWithFurnaceAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cFurnaceCallback & a_Callback); // Lua-accessible
|
||||
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. */
|
||||
bool DoWithNoteBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cNoteBlockCallback & a_Callback); // Lua-accessible
|
||||
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. */
|
||||
bool DoWithCommandBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cCommandBlockCallback & a_Callback); // Lua-accessible
|
||||
bool DoWithCommandBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cCommandBlockCallback & a_Callback); // Lua-accessible
|
||||
|
||||
/** Calls the callback for the mob head block at the specified coords.
|
||||
Returns false if there's no mob head block at those coords or callback returns true, returns true if found. */
|
||||
bool DoWithMobHeadAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cMobHeadCallback & a_Callback); // Lua-accessible
|
||||
bool DoWithMobHeadAt(int a_BlockX, int a_BlockY, int a_BlockZ, cMobHeadCallback & a_Callback); // Lua-accessible
|
||||
|
||||
/** Calls the callback for the flower pot at the specified coords.
|
||||
Returns false if there's no flower pot at those coords or callback returns true, returns true if found. */
|
||||
bool DoWithFlowerPotAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cFlowerPotCallback & a_Callback); // Lua-accessible
|
||||
bool DoWithFlowerPotAt(int a_BlockX, int a_BlockY, int a_BlockZ, cFlowerPotCallback & 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. */
|
||||
@ -360,7 +363,7 @@ public:
|
||||
bool ForEachChunkInRect(int a_MinChunkX, int a_MaxChunkX, int a_MinChunkZ, int a_MaxChunkZ, cChunkDataCallback & a_Callback);
|
||||
|
||||
/** Calls the callback for each loaded chunk. Returns true if all chunks have been processed successfully */
|
||||
bool ForEachLoadedChunk(const std::function<bool(int, int)> & a_Callback);
|
||||
bool ForEachLoadedChunk(std::function<bool(int, int)> a_Callback);
|
||||
|
||||
/** 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);
|
||||
|
@ -1660,9 +1660,9 @@ void cClientHandle::HandleSlotSelected(Int16 a_SlotNum)
|
||||
|
||||
void cClientHandle::HandleSpectate(const cUUID & a_PlayerUUID)
|
||||
{
|
||||
m_Player->GetWorld()->DoWithPlayerByUUID(a_PlayerUUID, [=](cPlayer & a_ToSpectate)
|
||||
m_Player->GetWorld()->DoWithPlayerByUUID(a_PlayerUUID, [=](cPlayer * a_ToSpectate)
|
||||
{
|
||||
m_Player->TeleportToEntity(a_ToSpectate);
|
||||
m_Player->TeleportToEntity(*a_ToSpectate);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
@ -1734,9 +1734,9 @@ void cClientHandle::HandleUseEntity(UInt32 a_TargetEntityID, bool a_IsLeftClick)
|
||||
// If the player is a spectator, let him spectate
|
||||
if (m_Player->IsGameModeSpectator() && a_IsLeftClick)
|
||||
{
|
||||
m_Player->GetWorld()->DoWithEntityByID(a_TargetEntityID, [=](cEntity & a_Entity)
|
||||
m_Player->GetWorld()->DoWithEntityByID(a_TargetEntityID, [=](cEntity * a_Entity)
|
||||
{
|
||||
m_Player->AttachTo(&a_Entity);
|
||||
m_Player->AttachTo(a_Entity);
|
||||
return true;
|
||||
});
|
||||
return;
|
||||
@ -1745,18 +1745,20 @@ void cClientHandle::HandleUseEntity(UInt32 a_TargetEntityID, bool a_IsLeftClick)
|
||||
// If it is a right click, call the entity's OnRightClicked() handler:
|
||||
if (!a_IsLeftClick)
|
||||
{
|
||||
cWorld * World = m_Player->GetWorld();
|
||||
World->DoWithEntityByID(a_TargetEntityID, [=](cEntity & a_Entity)
|
||||
class cRclkEntity : public cEntityCallback
|
||||
{
|
||||
cPlayer & m_Player;
|
||||
virtual bool Item(cEntity * a_Entity) override
|
||||
{
|
||||
if (
|
||||
cPluginManager::Get()->CallHookPlayerRightClickingEntity(*m_Player, a_Entity) ||
|
||||
cPluginManager::Get()->CallHookPlayerRightClickingEntity(m_Player, *a_Entity) ||
|
||||
(
|
||||
m_Player->IsGameModeSpectator() && // Spectators cannot interact with every entity
|
||||
m_Player.IsGameModeSpectator() && // Spectators cannot interact with every entity
|
||||
(
|
||||
!a_Entity.IsMinecart() || // They can only interact with minecarts
|
||||
!a_Entity->IsMinecart() || // They can only interact with minecarts
|
||||
(
|
||||
(static_cast<cMinecart &>(a_Entity).GetPayload() != cMinecart::mpChest) && // And only if the type matches a minecart with a chest or
|
||||
(static_cast<cMinecart &>(a_Entity).GetPayload() != cMinecart::mpHopper) // a minecart with a hopper
|
||||
(reinterpret_cast<cMinecart *>(a_Entity)->GetPayload() != cMinecart::mpChest) && // And only if the type matches a minecart with a chest or
|
||||
(reinterpret_cast<cMinecart *>(a_Entity)->GetPayload() != cMinecart::mpHopper) // a minecart with a hopper
|
||||
)
|
||||
)
|
||||
)
|
||||
@ -1764,34 +1766,52 @@ void cClientHandle::HandleUseEntity(UInt32 a_TargetEntityID, bool a_IsLeftClick)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
a_Entity.OnRightClicked(*m_Player);
|
||||
a_Entity->OnRightClicked(m_Player);
|
||||
return false;
|
||||
}
|
||||
);
|
||||
public:
|
||||
cRclkEntity(cPlayer & a_Player) : m_Player(a_Player) {}
|
||||
} Callback (*m_Player);
|
||||
|
||||
cWorld * World = m_Player->GetWorld();
|
||||
World->DoWithEntityByID(a_TargetEntityID, Callback);
|
||||
return;
|
||||
}
|
||||
|
||||
// If it is a left click, attack the entity:
|
||||
m_Player->GetWorld()->DoWithEntityByID(a_TargetEntityID, [=](cEntity & a_Entity)
|
||||
class cDamageEntity : public cEntityCallback
|
||||
{
|
||||
public:
|
||||
cPlayer * m_Me;
|
||||
|
||||
cDamageEntity(cPlayer * a_Player) :
|
||||
m_Me(a_Player)
|
||||
{
|
||||
if (!a_Entity.GetWorld()->IsPVPEnabled())
|
||||
}
|
||||
|
||||
virtual bool Item(cEntity * a_Entity) override
|
||||
{
|
||||
if (!a_Entity->GetWorld()->IsPVPEnabled())
|
||||
{
|
||||
// PVP is disabled, disallow players hurting other players:
|
||||
if (a_Entity.IsPlayer())
|
||||
if (a_Entity->IsPlayer())
|
||||
{
|
||||
// Player is hurting another player which is not allowed when PVP is disabled so ignore it
|
||||
return true;
|
||||
}
|
||||
}
|
||||
a_Entity.TakeDamage(*m_Player);
|
||||
m_Player->AddFoodExhaustion(0.3);
|
||||
if (a_Entity.IsPawn())
|
||||
a_Entity->TakeDamage(*m_Me);
|
||||
m_Me->AddFoodExhaustion(0.3);
|
||||
if (a_Entity->IsPawn())
|
||||
{
|
||||
m_Player->NotifyNearbyWolves(static_cast<cPawn*>(&a_Entity), true);
|
||||
m_Me->NotifyNearbyWolves(static_cast<cPawn*>(a_Entity), true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
);
|
||||
} Callback(m_Player);
|
||||
|
||||
cWorld * World = m_Player->GetWorld();
|
||||
World->DoWithEntityByID(a_TargetEntityID, Callback);
|
||||
}
|
||||
|
||||
|
||||
@ -1840,8 +1860,17 @@ bool cClientHandle::CheckMultiLogin(const AString & a_Username)
|
||||
return false;
|
||||
}
|
||||
|
||||
class cCallback :
|
||||
public cPlayerListCallback
|
||||
{
|
||||
virtual bool Item(cPlayer * a_Player) override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
} Callback;
|
||||
|
||||
// Check if the player is in any World.
|
||||
if (cRoot::Get()->DoWithPlayer(a_Username, [](cPlayer &) { return true; }))
|
||||
if (cRoot::Get()->DoWithPlayer(a_Username, Callback))
|
||||
{
|
||||
Kick("A player of the username is already logged in");
|
||||
return false;
|
||||
|
@ -56,12 +56,25 @@ bool cDeadlockDetect::Start(int a_IntervalSec)
|
||||
m_IntervalSec = a_IntervalSec;
|
||||
|
||||
// Read the initial world data:
|
||||
cRoot::Get()->ForEachWorld([=](cWorld & a_World)
|
||||
class cFillIn :
|
||||
public cWorldListCallback
|
||||
{
|
||||
public:
|
||||
cFillIn(cDeadlockDetect * a_Detect) :
|
||||
m_Detect(a_Detect)
|
||||
{
|
||||
SetWorldAge(a_World.GetName(), a_World.GetWorldAge());
|
||||
}
|
||||
|
||||
virtual bool Item(cWorld * a_World) override
|
||||
{
|
||||
m_Detect->SetWorldAge(a_World->GetName(), a_World->GetWorldAge());
|
||||
return false;
|
||||
}
|
||||
);
|
||||
|
||||
protected:
|
||||
cDeadlockDetect * m_Detect;
|
||||
} FillIn(this);
|
||||
cRoot::Get()->ForEachWorld(FillIn);
|
||||
return super::Start();
|
||||
}
|
||||
|
||||
@ -102,12 +115,25 @@ void cDeadlockDetect::Execute(void)
|
||||
while (!m_ShouldTerminate)
|
||||
{
|
||||
// Check the world ages:
|
||||
cRoot::Get()->ForEachWorld([=](cWorld & a_World)
|
||||
class cChecker :
|
||||
public cWorldListCallback
|
||||
{
|
||||
public:
|
||||
cChecker(cDeadlockDetect * a_Detect) :
|
||||
m_Detect(a_Detect)
|
||||
{
|
||||
CheckWorldAge(a_World.GetName(), a_World.GetWorldAge());
|
||||
}
|
||||
|
||||
protected:
|
||||
cDeadlockDetect * m_Detect;
|
||||
|
||||
virtual bool Item(cWorld * a_World) override
|
||||
{
|
||||
m_Detect->CheckWorldAge(a_World->GetName(), a_World->GetWorldAge());
|
||||
return false;
|
||||
}
|
||||
);
|
||||
} Checker(this);
|
||||
cRoot::Get()->ForEachWorld(Checker);
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(CYCLE_MILLISECONDS));
|
||||
} // while (should run)
|
||||
|
@ -304,22 +304,38 @@ void cEntity::TakeDamage(eDamageType a_DamageType, cEntity * a_Attacker, int a_R
|
||||
|
||||
void cEntity::TakeDamage(eDamageType a_DamageType, UInt32 a_AttackerID, int a_RawDamage, double a_KnockbackAmount)
|
||||
{
|
||||
m_World->DoWithEntityByID(a_AttackerID, [=](cEntity & a_Attacker)
|
||||
class cFindEntity : public cEntityCallback
|
||||
{
|
||||
public:
|
||||
|
||||
cEntity * m_Entity;
|
||||
eDamageType m_DamageType;
|
||||
int m_RawDamage;
|
||||
double m_KnockbackAmount;
|
||||
|
||||
virtual bool Item(cEntity * a_Attacker) override
|
||||
{
|
||||
cPawn * Attacker;
|
||||
if (a_Attacker.IsPawn())
|
||||
if (a_Attacker->IsPawn())
|
||||
{
|
||||
Attacker = static_cast<cPawn*>(&a_Attacker);
|
||||
Attacker = static_cast<cPawn*>(a_Attacker);
|
||||
}
|
||||
else
|
||||
{
|
||||
Attacker = nullptr;
|
||||
}
|
||||
|
||||
TakeDamage(a_DamageType, Attacker, a_RawDamage, a_KnockbackAmount);
|
||||
|
||||
m_Entity->TakeDamage(m_DamageType, Attacker, m_RawDamage, m_KnockbackAmount);
|
||||
return true;
|
||||
}
|
||||
);
|
||||
} Callback;
|
||||
|
||||
Callback.m_Entity = this;
|
||||
Callback.m_DamageType = a_DamageType;
|
||||
Callback.m_RawDamage = a_RawDamage;
|
||||
Callback.m_KnockbackAmount = a_KnockbackAmount;
|
||||
m_World->DoWithEntityByID(a_AttackerID, Callback);
|
||||
}
|
||||
|
||||
|
||||
@ -650,7 +666,7 @@ bool cEntity::ArmorCoversAgainst(eDamageType a_DamageType)
|
||||
|
||||
int cEntity::GetEnchantmentCoverAgainst(const cEntity * a_Attacker, eDamageType a_DamageType, int a_Damage)
|
||||
{
|
||||
int TotalEPF = 0;
|
||||
int TotalEPF = 0.0;
|
||||
|
||||
const cItem ArmorItems[] = { GetEquippedHelmet(), GetEquippedChestplate(), GetEquippedLeggings(), GetEquippedBoots() };
|
||||
for (size_t i = 0; i < ARRAYCOUNT(ArmorItems); i++)
|
||||
|
@ -13,7 +13,8 @@
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// cFloaterEntityCollisionCallback
|
||||
class cFloaterEntityCollisionCallback
|
||||
class cFloaterEntityCollisionCallback :
|
||||
public cEntityCallback
|
||||
{
|
||||
public:
|
||||
cFloaterEntityCollisionCallback(cFloater * a_Floater, const Vector3d & a_Pos, const Vector3d & a_NextPos) :
|
||||
@ -24,14 +25,14 @@ public:
|
||||
m_HitEntity(nullptr)
|
||||
{
|
||||
}
|
||||
bool operator () (cEntity & a_Entity)
|
||||
virtual bool Item(cEntity * a_Entity) override
|
||||
{
|
||||
if (!a_Entity.IsMob()) // Floaters can only pull mobs not other entities.
|
||||
if (!a_Entity->IsMob()) // Floaters can only pull mobs not other entities.
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
cBoundingBox EntBox(a_Entity.GetPosition(), a_Entity.GetWidth() / 2, a_Entity.GetHeight());
|
||||
cBoundingBox EntBox(a_Entity->GetPosition(), a_Entity->GetWidth() / 2, a_Entity->GetHeight());
|
||||
|
||||
double LineCoeff;
|
||||
eBlockFace Face;
|
||||
@ -46,7 +47,7 @@ public:
|
||||
{
|
||||
// The entity is closer than anything we've stored so far, replace it as the potential victim
|
||||
m_MinCoeff = LineCoeff;
|
||||
m_HitEntity = &a_Entity;
|
||||
m_HitEntity = a_Entity;
|
||||
}
|
||||
|
||||
// Don't break the enumeration, we want all the entities
|
||||
@ -74,6 +75,32 @@ protected:
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// cFloaterCheckEntityExist
|
||||
class cFloaterCheckEntityExist :
|
||||
public cEntityCallback
|
||||
{
|
||||
public:
|
||||
cFloaterCheckEntityExist(void) :
|
||||
m_EntityExists(false)
|
||||
{
|
||||
}
|
||||
|
||||
bool Item(cEntity * a_Entity) override
|
||||
{
|
||||
m_EntityExists = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DoesExist(void) const { return m_EntityExists; }
|
||||
protected:
|
||||
bool m_EntityExists;
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
cFloater::cFloater(double a_X, double a_Y, double a_Z, Vector3d a_Speed, UInt32 a_PlayerID, int a_CountDownTime) :
|
||||
cEntity(etFloater, a_X, a_Y, a_Z, 0.2, 0.2),
|
||||
m_BitePos(Vector3d(a_X, a_Y, a_Z)),
|
||||
@ -173,16 +200,18 @@ void cFloater::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_World->DoWithEntityByID(m_PlayerID, [](cEntity &) { return true; })) // The owner doesn't exist anymore. Destroy the floater entity.
|
||||
cFloaterCheckEntityExist EntityCallback;
|
||||
m_World->DoWithEntityByID(m_PlayerID, EntityCallback);
|
||||
if (!EntityCallback.DoesExist()) // The owner doesn't exist anymore. Destroy the floater entity.
|
||||
{
|
||||
Destroy(true);
|
||||
}
|
||||
|
||||
if (m_AttachedMobID != cEntity::INVALID_ID)
|
||||
{
|
||||
if (!m_World->DoWithEntityByID(m_AttachedMobID, [](cEntity &) { return true; }))
|
||||
m_World->DoWithEntityByID(m_AttachedMobID, EntityCallback); // The mob the floater was attached to doesn't exist anymore.
|
||||
if (!EntityCallback.DoesExist())
|
||||
{
|
||||
// The mob the floater was attached to doesn't exist anymore.
|
||||
m_AttachedMobID = cEntity::INVALID_ID;
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
|
||||
|
||||
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
|
||||
|
||||
#include "LeashKnot.h"
|
||||
@ -38,42 +38,58 @@ void cLeashKnot::OnRightClicked(cPlayer & a_Player)
|
||||
|
||||
|
||||
|
||||
void cLeashKnot::TiePlayersLeashedMobs(cPlayer & a_Player, bool a_ShouldBroadcast)
|
||||
void cLeashKnot::TiePlayersLeashedMobs(cPlayer & a_Player, bool a_ShouldBroadCast)
|
||||
{
|
||||
// Check leashed nearby mobs to tie them to this knot
|
||||
// taking world from player (instead from this) because this can be called before entity was initialized
|
||||
a_Player.GetWorld()->ForEachEntityInBox(cBoundingBox(GetPosition(), 8, 8, -4), [&](cEntity & a_Entity)
|
||||
class LookForLeasheds : public cEntityCallback
|
||||
{
|
||||
public:
|
||||
cLeashKnot * m_Knot;
|
||||
cPlayer * m_Player;
|
||||
bool m_ShouldBroadcast;
|
||||
|
||||
LookForLeasheds(cLeashKnot * a_Knot, cPlayer * a_PlayerLeashedTo, bool a_ShouldBroadcast) :
|
||||
m_Knot(a_Knot),
|
||||
m_Player(a_PlayerLeashedTo),
|
||||
m_ShouldBroadcast(a_ShouldBroadcast)
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool Item(cEntity * a_Entity) override
|
||||
{
|
||||
// If the entity is not a monster skip it
|
||||
if (a_Entity.GetEntityType() != cEntity::eEntityType::etMonster)
|
||||
if (a_Entity->GetEntityType() != cEntity::eEntityType::etMonster)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
auto & PotentialLeashed = static_cast<cMonster&>(a_Entity);
|
||||
cMonster * PotentialLeashed = static_cast<cMonster*>(a_Entity);
|
||||
|
||||
// If can't be leashed skip it
|
||||
if (!PotentialLeashed.CanBeLeashed())
|
||||
if (!PotentialLeashed->CanBeLeashed())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// If it's not leashed to the player skip it
|
||||
if (
|
||||
!PotentialLeashed.IsLeashed() ||
|
||||
!PotentialLeashed.GetLeashedTo()->IsPlayer() ||
|
||||
(PotentialLeashed.GetLeashedTo()->GetUniqueID() != a_Player.GetUniqueID())
|
||||
!PotentialLeashed->IsLeashed() ||
|
||||
!PotentialLeashed->GetLeashedTo()->IsPlayer() ||
|
||||
(PotentialLeashed->GetLeashedTo()->GetUniqueID() != m_Player->GetUniqueID())
|
||||
)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// All conditions met, unleash from player and leash to fence
|
||||
PotentialLeashed.Unleash(false, false);
|
||||
PotentialLeashed.LeashTo(*this, a_ShouldBroadcast);
|
||||
PotentialLeashed->Unleash(false, false);
|
||||
PotentialLeashed->LeashTo(*m_Knot, m_ShouldBroadcast);
|
||||
return false;
|
||||
}
|
||||
);
|
||||
} LookForLeashedsCallback(this, &a_Player, a_ShouldBroadCast);
|
||||
|
||||
// taking world from player (instead from this) because this can be called before entity was initialized
|
||||
a_Player.GetWorld()->ForEachEntityInBox(cBoundingBox(GetPosition(), 8, 8, -4), LookForLeashedsCallback);
|
||||
}
|
||||
|
||||
|
||||
@ -142,19 +158,26 @@ void cLeashKnot::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
|
||||
|
||||
cLeashKnot * cLeashKnot::FindKnotAtPos(cWorldInterface & a_WorldInterface, Vector3i a_BlockPos)
|
||||
{
|
||||
cLeashKnot * LeashKnot = nullptr;
|
||||
a_WorldInterface.ForEachEntityInBox(cBoundingBox(a_BlockPos, 0.5, 1), [&](cEntity & a_Entity)
|
||||
class LookForKnot : public cEntityCallback
|
||||
{
|
||||
public:
|
||||
cLeashKnot * m_LeashKnot = nullptr;
|
||||
|
||||
virtual bool Item(cEntity * a_Entity) override
|
||||
{
|
||||
if (a_Entity.IsLeashKnot())
|
||||
if (a_Entity->IsLeashKnot())
|
||||
{
|
||||
LeashKnot = static_cast<cLeashKnot *>(&a_Entity);
|
||||
m_LeashKnot = reinterpret_cast<cLeashKnot *>(a_Entity);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
);
|
||||
|
||||
return LeashKnot;
|
||||
} CallbackFindKnot;
|
||||
|
||||
a_WorldInterface.ForEachEntityInBox(cBoundingBox(a_BlockPos, 0.5, 1), CallbackFindKnot);
|
||||
|
||||
return CallbackFindKnot.m_LeashKnot;
|
||||
}
|
||||
|
||||
|
||||
|
@ -20,7 +20,8 @@
|
||||
|
||||
|
||||
|
||||
class cMinecartCollisionCallback
|
||||
class cMinecartCollisionCallback :
|
||||
public cEntityCallback
|
||||
{
|
||||
public:
|
||||
cMinecartCollisionCallback(Vector3d a_Pos, double a_Height, double a_Width, UInt32 a_UniqueID, UInt32 a_AttacheeUniqueID) :
|
||||
@ -34,31 +35,33 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
bool operator () (cEntity & a_Entity)
|
||||
virtual bool Item(cEntity * a_Entity) override
|
||||
{
|
||||
ASSERT(a_Entity != nullptr);
|
||||
|
||||
if (
|
||||
(
|
||||
!a_Entity.IsPlayer() ||
|
||||
static_cast<cPlayer &>(a_Entity).IsGameModeSpectator() // Spectators doesn't collide with anything
|
||||
!a_Entity->IsPlayer() ||
|
||||
reinterpret_cast<cPlayer *>(a_Entity)->IsGameModeSpectator() // Spectators doesn't collide with anything
|
||||
) &&
|
||||
!a_Entity.IsMob() &&
|
||||
!a_Entity.IsMinecart() &&
|
||||
!a_Entity.IsBoat()
|
||||
!a_Entity->IsMob() &&
|
||||
!a_Entity->IsMinecart() &&
|
||||
!a_Entity->IsBoat()
|
||||
)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if ((a_Entity.GetUniqueID() == m_UniqueID) || (a_Entity.GetUniqueID() == m_AttacheeUniqueID))
|
||||
else if ((a_Entity->GetUniqueID() == m_UniqueID) || (a_Entity->GetUniqueID() == m_AttacheeUniqueID))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
cBoundingBox bbEntity(a_Entity.GetPosition(), a_Entity.GetWidth() / 2, a_Entity.GetHeight());
|
||||
cBoundingBox bbEntity(a_Entity->GetPosition(), a_Entity->GetWidth() / 2, a_Entity->GetHeight());
|
||||
cBoundingBox bbMinecart(Vector3d(m_Pos.x, floor(m_Pos.y), m_Pos.z), m_Width / 2, m_Height);
|
||||
|
||||
if (bbEntity.DoesIntersect(bbMinecart))
|
||||
{
|
||||
m_CollidedEntityPos = a_Entity.GetPosition();
|
||||
m_CollidedEntityPos = a_Entity->GetPosition();
|
||||
m_DoesIntersect = true;
|
||||
return true;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
|
||||
|
||||
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
|
||||
|
||||
#include "Pawn.h"
|
||||
@ -80,37 +80,49 @@ void cPawn::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
|
||||
Effect->OnTick(*this);
|
||||
}
|
||||
|
||||
// Spectators cannot push entities around
|
||||
if ((!IsPlayer()) || (!static_cast<cPlayer *>(this)->IsGameModeSpectator()))
|
||||
class Pusher : public cEntityCallback
|
||||
{
|
||||
m_World->ForEachEntityInBox(cBoundingBox(GetPosition(), GetWidth(), GetHeight()), [=](cEntity & a_Entity)
|
||||
public:
|
||||
cEntity * m_Pusher;
|
||||
|
||||
Pusher(cEntity * a_Pusher) :
|
||||
m_Pusher(a_Pusher)
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool Item(cEntity * a_Entity) override
|
||||
{
|
||||
if (a_Entity->GetUniqueID() == m_Pusher->GetUniqueID())
|
||||
{
|
||||
if (a_Entity.GetUniqueID() == GetUniqueID())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// we only push other mobs, boats and minecarts
|
||||
if ((a_Entity.GetEntityType() != etMonster) && (a_Entity.GetEntityType() != etMinecart) && (a_Entity.GetEntityType() != etBoat))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// do not push a boat / minecart you're sitting in
|
||||
if (IsAttachedTo(&a_Entity))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Vector3d v3Delta = a_Entity.GetPosition() - GetPosition();
|
||||
v3Delta.y = 0.0; // we only push sideways
|
||||
v3Delta *= 1.0 / (v3Delta.Length() + 0.01); // we push harder if we're close
|
||||
// QUESTION: is there an additional multiplier for this? current shoving seems a bit weak
|
||||
|
||||
a_Entity.AddSpeed(v3Delta);
|
||||
return false;
|
||||
}
|
||||
);
|
||||
|
||||
// we only push other mobs, boats and minecarts
|
||||
if ((a_Entity->GetEntityType() != etMonster) && (a_Entity->GetEntityType() != etMinecart) && (a_Entity->GetEntityType() != etBoat))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// do not push a boat / minecart you're sitting in
|
||||
if (m_Pusher->IsAttachedTo(a_Entity))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Vector3d v3Delta = a_Entity->GetPosition() - m_Pusher->GetPosition();
|
||||
v3Delta.y = 0.0; // we only push sideways
|
||||
v3Delta *= 1.0 / (v3Delta.Length() + 0.01); // we push harder if we're close
|
||||
// QUESTION: is there an additional multiplier for this? current shoving seems a bit weak
|
||||
|
||||
a_Entity->AddSpeed(v3Delta);
|
||||
return false;
|
||||
}
|
||||
} Callback(this);
|
||||
|
||||
// Spectators cannot push entities around
|
||||
if ((!IsPlayer()) || (!reinterpret_cast<cPlayer *>(this)->IsGameModeSpectator()))
|
||||
{
|
||||
m_World->ForEachEntityInBox(cBoundingBox(GetPosition(), GetWidth(), GetHeight()), Callback);
|
||||
}
|
||||
|
||||
super::Tick(a_Dt, a_Chunk);
|
||||
|
@ -17,7 +17,8 @@
|
||||
|
||||
|
||||
|
||||
class cPickupCombiningCallback
|
||||
class cPickupCombiningCallback :
|
||||
public cEntityCallback
|
||||
{
|
||||
public:
|
||||
cPickupCombiningCallback(Vector3d a_Position, cPickup * a_Pickup) :
|
||||
@ -27,21 +28,21 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
bool operator () (cEntity & a_Entity)
|
||||
virtual bool Item(cEntity * a_Entity) override
|
||||
{
|
||||
ASSERT(a_Entity.IsTicking());
|
||||
if (!a_Entity.IsPickup() || (a_Entity.GetUniqueID() <= m_Pickup->GetUniqueID()) || !a_Entity.IsOnGround())
|
||||
ASSERT(a_Entity->IsTicking());
|
||||
if (!a_Entity->IsPickup() || (a_Entity->GetUniqueID() <= m_Pickup->GetUniqueID()) || !a_Entity->IsOnGround())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
Vector3d EntityPos = a_Entity.GetPosition();
|
||||
Vector3d EntityPos = a_Entity->GetPosition();
|
||||
double Distance = (EntityPos - m_Position).Length();
|
||||
|
||||
auto & OtherPickup = static_cast<cPickup &>(a_Entity);
|
||||
cItem & Item = OtherPickup.GetItem();
|
||||
if ((Distance < 1.2) && Item.IsEqual(m_Pickup->GetItem()) && OtherPickup.CanCombine())
|
||||
cPickup * OtherPickup = static_cast<cPickup *>(a_Entity);
|
||||
cItem & Item = OtherPickup->GetItem();
|
||||
if ((Distance < 1.2) && Item.IsEqual(m_Pickup->GetItem()) && OtherPickup->CanCombine())
|
||||
{
|
||||
short CombineCount = Item.m_ItemCount;
|
||||
if ((CombineCount + m_Pickup->GetItem().m_ItemCount) > Item.GetMaxStackSize())
|
||||
@ -63,16 +64,16 @@ public:
|
||||
int DiffX = FloorC(m_Pickup->GetPosX() * 32.0) - FloorC(EntityPos.x * 32.0);
|
||||
int DiffY = FloorC(m_Pickup->GetPosY() * 32.0) - FloorC(EntityPos.y * 32.0);
|
||||
int DiffZ = FloorC(m_Pickup->GetPosZ() * 32.0) - FloorC(EntityPos.z * 32.0);
|
||||
a_Entity.GetWorld()->BroadcastEntityRelMove(a_Entity, static_cast<char>(DiffX), static_cast<char>(DiffY), static_cast<char>(DiffZ));
|
||||
a_Entity->GetWorld()->BroadcastEntityRelMove(*a_Entity, static_cast<char>(DiffX), static_cast<char>(DiffY), static_cast<char>(DiffZ));
|
||||
/* End of experimental animation */
|
||||
a_Entity.Destroy();
|
||||
a_Entity->Destroy();
|
||||
|
||||
// Reset the timer
|
||||
m_Pickup->SetAge(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
a_Entity.GetWorld()->BroadcastEntityMetadata(a_Entity);
|
||||
a_Entity->GetWorld()->BroadcastEntityMetadata(*a_Entity);
|
||||
}
|
||||
m_FoundMatchingPickup = true;
|
||||
}
|
||||
|
@ -1005,21 +1005,36 @@ bool cPlayer::DoTakeDamage(TakeDamageInfo & a_TDI)
|
||||
void cPlayer::NotifyNearbyWolves(cPawn * a_Opponent, bool a_IsPlayerInvolved)
|
||||
{
|
||||
ASSERT(a_Opponent != nullptr);
|
||||
class LookForWolves : public cEntityCallback
|
||||
{
|
||||
public:
|
||||
cPlayer * m_Player;
|
||||
cPawn * m_Attacker;
|
||||
bool m_IsPlayerInvolved;
|
||||
|
||||
m_World->ForEachEntityInBox(cBoundingBox(GetPosition(), 16), [&] (cEntity & a_Entity)
|
||||
LookForWolves(cPlayer * a_Me, cPawn * a_MyAttacker, bool a_PlayerInvolved) :
|
||||
m_Player(a_Me),
|
||||
m_Attacker(a_MyAttacker),
|
||||
m_IsPlayerInvolved(a_PlayerInvolved)
|
||||
{
|
||||
if (a_Entity.IsMob())
|
||||
}
|
||||
|
||||
virtual bool Item(cEntity * a_Entity) override
|
||||
{
|
||||
if (a_Entity->IsMob())
|
||||
{
|
||||
auto & Mob = static_cast<cMonster&>(a_Entity);
|
||||
if (Mob.GetMobType() == mtWolf)
|
||||
cMonster * Mob = static_cast<cMonster*>(a_Entity);
|
||||
if (Mob->GetMobType() == mtWolf)
|
||||
{
|
||||
auto & Wolf = static_cast<cWolf&>(Mob);
|
||||
Wolf.ReceiveNearbyFightInfo(GetUUID(), a_Opponent, a_IsPlayerInvolved);
|
||||
cWolf * Wolf = static_cast<cWolf*>(Mob);
|
||||
Wolf->ReceiveNearbyFightInfo(m_Player->GetUUID(), m_Attacker, m_IsPlayerInvolved);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
);
|
||||
} Callback(this, a_Opponent, a_IsPlayerInvolved);
|
||||
|
||||
m_World->ForEachEntityInBox(cBoundingBox(GetPosition(), 16), Callback);
|
||||
}
|
||||
|
||||
|
||||
@ -2417,12 +2432,17 @@ void cPlayer::HandleFloater()
|
||||
{
|
||||
return;
|
||||
}
|
||||
m_World->DoWithEntityByID(m_FloaterID, [](cEntity & a_Entity)
|
||||
class cFloaterCallback :
|
||||
public cEntityCallback
|
||||
{
|
||||
public:
|
||||
virtual bool Item(cEntity * a_Entity) override
|
||||
{
|
||||
a_Entity.Destroy(true);
|
||||
a_Entity->Destroy(true);
|
||||
return true;
|
||||
}
|
||||
);
|
||||
} Callback;
|
||||
m_World->DoWithEntityByID(m_FloaterID, Callback);
|
||||
SetIsFishing(false);
|
||||
}
|
||||
|
||||
@ -2666,18 +2686,29 @@ bool cPlayer::DoesPlacingBlocksIntersectEntity(const sSetBlockVector & a_Blocks)
|
||||
cWorld * World = GetWorld();
|
||||
|
||||
// Check to see if any entity intersects any block being placed
|
||||
return !World->ForEachEntityInBox(PlacingBounds, [&](cEntity & a_Entity)
|
||||
{
|
||||
// The distance inside the block the entity can still be.
|
||||
const double EPSILON = 0.0005;
|
||||
class DoesIntersectBlock : public cEntityCallback
|
||||
{
|
||||
public:
|
||||
const std::vector<cBoundingBox> & m_BoundingBoxes;
|
||||
|
||||
if (!a_Entity.DoesPreventBlockPlacement())
|
||||
// The distance inside the block the entity can still be.
|
||||
const double EPSILON = 0.0005;
|
||||
|
||||
DoesIntersectBlock(const std::vector<cBoundingBox> & a_BoundingBoxes) :
|
||||
m_BoundingBoxes(a_BoundingBoxes)
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool Item(cEntity * a_Entity) override
|
||||
{
|
||||
if (!a_Entity->DoesPreventBlockPlacement())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
cBoundingBox EntBox(a_Entity.GetPosition(), a_Entity.GetWidth() / 2, a_Entity.GetHeight());
|
||||
for (auto BlockBox : PlacementBoxes)
|
||||
cBoundingBox EntBox(a_Entity->GetPosition(), a_Entity->GetWidth() / 2, a_Entity->GetHeight());
|
||||
for (auto BlockBox: m_BoundingBoxes)
|
||||
{
|
||||
|
||||
// Put in a little bit of wiggle room
|
||||
BlockBox.Expand(-EPSILON, -EPSILON, -EPSILON);
|
||||
if (EntBox.DoesIntersect(BlockBox))
|
||||
@ -2687,7 +2718,15 @@ bool cPlayer::DoesPlacingBlocksIntersectEntity(const sSetBlockVector & a_Blocks)
|
||||
}
|
||||
return false;
|
||||
}
|
||||
);
|
||||
} Callback(PlacementBoxes);
|
||||
|
||||
// See if any entities in that bounding box collide with anyone
|
||||
if (!World->ForEachEntityInBox(PlacingBounds, Callback))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
@ -126,7 +126,8 @@ protected:
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// cProjectileEntityCollisionCallback:
|
||||
|
||||
class cProjectileEntityCollisionCallback
|
||||
class cProjectileEntityCollisionCallback :
|
||||
public cEntityCallback
|
||||
{
|
||||
public:
|
||||
cProjectileEntityCollisionCallback(cProjectileEntity * a_Projectile, const Vector3d & a_Pos, const Vector3d & a_NextPos) :
|
||||
@ -139,11 +140,11 @@ public:
|
||||
}
|
||||
|
||||
|
||||
bool operator () (cEntity & a_Entity)
|
||||
virtual bool Item(cEntity * a_Entity) override
|
||||
{
|
||||
if (
|
||||
(&a_Entity == m_Projectile) || // Do not check collisions with self
|
||||
(a_Entity.GetUniqueID() == m_Projectile->GetCreatorUniqueID()) // Do not check whoever shot the projectile
|
||||
(a_Entity == m_Projectile) || // Do not check collisions with self
|
||||
(a_Entity->GetUniqueID() == m_Projectile->GetCreatorUniqueID()) // Do not check whoever shot the projectile
|
||||
)
|
||||
{
|
||||
// Don't check creator only for the first 5 ticks so that projectiles can collide with the creator
|
||||
@ -153,7 +154,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
cBoundingBox EntBox(a_Entity.GetPosition(), a_Entity.GetWidth() / 2, a_Entity.GetHeight());
|
||||
cBoundingBox EntBox(a_Entity->GetPosition(), a_Entity->GetWidth() / 2, a_Entity->GetHeight());
|
||||
|
||||
// Instead of colliding the bounding box with another bounding box in motion, we collide an enlarged bounding box with a hairline.
|
||||
// The results should be good enough for our purposes
|
||||
@ -167,20 +168,20 @@ public:
|
||||
}
|
||||
|
||||
if (
|
||||
!a_Entity.IsMob() &&
|
||||
!a_Entity.IsMinecart() &&
|
||||
!a_Entity->IsMob() &&
|
||||
!a_Entity->IsMinecart() &&
|
||||
(
|
||||
!a_Entity.IsPlayer() ||
|
||||
static_cast<cPlayer &>(a_Entity).IsGameModeSpectator()
|
||||
!a_Entity->IsPlayer() ||
|
||||
static_cast<cPlayer *>(a_Entity)->IsGameModeSpectator()
|
||||
) &&
|
||||
!a_Entity.IsBoat()
|
||||
!a_Entity->IsBoat()
|
||||
)
|
||||
{
|
||||
// Not an entity that interacts with a projectile
|
||||
return false;
|
||||
}
|
||||
|
||||
if (cPluginManager::Get()->CallHookProjectileHitEntity(*m_Projectile, a_Entity))
|
||||
if (cPluginManager::Get()->CallHookProjectileHitEntity(*m_Projectile, *a_Entity))
|
||||
{
|
||||
// A plugin disagreed.
|
||||
return false;
|
||||
@ -190,7 +191,7 @@ public:
|
||||
{
|
||||
// The entity is closer than anything we've stored so far, replace it as the potential victim
|
||||
m_MinCoeff = LineCoeff;
|
||||
m_HitEntity = &a_Entity;
|
||||
m_HitEntity = a_Entity;
|
||||
}
|
||||
|
||||
// Don't break the enumeration, we want all the entities
|
||||
@ -326,13 +327,20 @@ void cProjectileEntity::OnHitEntity(cEntity & a_EntityHit, const Vector3d & a_Hi
|
||||
// If we were created by a player and we hit a pawn, notify attacking player's wolves
|
||||
if (a_EntityHit.IsPawn() && (GetCreatorName() != ""))
|
||||
{
|
||||
auto EntityHit = static_cast<cPawn *>(&a_EntityHit);
|
||||
m_World->DoWithEntityByID(GetCreatorUniqueID(), [=](cEntity & a_Hitter)
|
||||
class cNotifyWolves : public cEntityCallback
|
||||
{
|
||||
public:
|
||||
cPawn * m_EntityHit;
|
||||
|
||||
virtual bool Item(cEntity * a_Hitter) override
|
||||
{
|
||||
static_cast<cPlayer&>(a_Hitter).NotifyNearbyWolves(EntityHit, true);
|
||||
static_cast<cPlayer*>(a_Hitter)->NotifyNearbyWolves(m_EntityHit, true);
|
||||
return true;
|
||||
}
|
||||
);
|
||||
} Callback;
|
||||
|
||||
Callback.m_EntityHit = static_cast<cPawn*>(&a_EntityHit);
|
||||
m_World->DoWithEntityByID(GetCreatorUniqueID(), Callback);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,60 @@
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// cSplashPotionEntityCallback:
|
||||
|
||||
/** Used to distribute the splashed potion effect among nearby entities */
|
||||
class cSplashPotionCallback :
|
||||
public cEntityCallback
|
||||
{
|
||||
public:
|
||||
/** Creates the callback.
|
||||
@param a_HitPos The position where the splash potion has splashed
|
||||
@param a_EntityEffectType The effect type of the potion
|
||||
@param a_EntityEffect The effect description */
|
||||
cSplashPotionCallback(const Vector3d & a_HitPos, cEntityEffect::eType a_EntityEffectType, const cEntityEffect & a_EntityEffect) :
|
||||
m_HitPos(a_HitPos),
|
||||
m_EntityEffectType(a_EntityEffectType),
|
||||
m_EntityEffect(a_EntityEffect)
|
||||
{
|
||||
}
|
||||
|
||||
/** Called by cWorld::ForEachEntity(), adds the stored entity effect to the entity, if it is close enough. */
|
||||
virtual bool Item(cEntity * a_Entity) override
|
||||
{
|
||||
if (!a_Entity->IsPawn())
|
||||
{
|
||||
// Not an entity that can take effects
|
||||
return false;
|
||||
}
|
||||
|
||||
double SplashDistance = (a_Entity->GetPosition() - m_HitPos).Length();
|
||||
if (SplashDistance >= 20)
|
||||
{
|
||||
// Too far away
|
||||
return false;
|
||||
}
|
||||
|
||||
// y = -0.25x + 1, where x is the distance from the player. Approximation for potion splash.
|
||||
// TODO: better equation
|
||||
double Reduction = -0.25 * SplashDistance + 1.0;
|
||||
Reduction = std::max(Reduction, 0.0);
|
||||
|
||||
static_cast<cPawn *>(a_Entity)->AddEntityEffect(m_EntityEffectType, m_EntityEffect.GetDuration(), m_EntityEffect.GetIntensity(), Reduction);
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
const Vector3d & m_HitPos;
|
||||
cEntityEffect::eType m_EntityEffectType;
|
||||
const cEntityEffect & m_EntityEffect;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// cSplashPotionEntity:
|
||||
|
||||
@ -65,30 +119,8 @@ void cSplashPotionEntity::OnHitEntity(cEntity & a_EntityHit, const Vector3d & a_
|
||||
|
||||
void cSplashPotionEntity::Splash(const Vector3d & a_HitPos)
|
||||
{
|
||||
m_World->ForEachEntity([=](cEntity & a_Entity)
|
||||
{
|
||||
if (!a_Entity.IsPawn())
|
||||
{
|
||||
// Not an entity that can take effects
|
||||
return false;
|
||||
}
|
||||
|
||||
double SplashDistance = (a_Entity.GetPosition() - a_HitPos).Length();
|
||||
if (SplashDistance >= 20)
|
||||
{
|
||||
// Too far away
|
||||
return false;
|
||||
}
|
||||
|
||||
// y = -0.25x + 1, where x is the distance from the player. Approximation for potion splash.
|
||||
// TODO: better equation
|
||||
double Reduction = -0.25 * SplashDistance + 1.0;
|
||||
Reduction = std::max(Reduction, 0.0);
|
||||
|
||||
static_cast<cPawn &>(a_Entity).AddEntityEffect(m_EntityEffectType, m_EntityEffect.GetDuration(), m_EntityEffect.GetIntensity(), Reduction);
|
||||
return false;
|
||||
}
|
||||
);
|
||||
cSplashPotionCallback Callback(a_HitPos, m_EntityEffectType, m_EntityEffect);
|
||||
m_World->ForEachEntity(Callback);
|
||||
|
||||
m_World->BroadcastSoundParticleEffect(
|
||||
EffectID::PARTICLE_SPLASH_POTION,
|
||||
|
@ -74,12 +74,29 @@ void cThrownEnderPearlEntity::TeleportCreator(const Vector3d & a_HitPos)
|
||||
return;
|
||||
}
|
||||
|
||||
GetWorld()->FindAndDoWithPlayer(m_CreatorData.m_Name, [=](cPlayer & a_Entity)
|
||||
class cProjectileCreatorCallbackForPlayers : public cPlayerListCallback
|
||||
{
|
||||
public:
|
||||
cProjectileCreatorCallbackForPlayers(cEntity * a_Attacker, Vector3i a_CallbackHitPos) :
|
||||
m_Attacker(a_Attacker),
|
||||
m_HitPos(a_CallbackHitPos)
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool Item(cPlayer * a_Entity) override
|
||||
{
|
||||
// Teleport the creator here, make them take 5 damage:
|
||||
a_Entity.TeleportToCoords(a_HitPos.x, a_HitPos.y + 0.2, a_HitPos.z);
|
||||
a_Entity.TakeDamage(dtEnderPearl, this, 5, 0);
|
||||
a_Entity->TeleportToCoords(m_HitPos.x, m_HitPos.y + 0.2, m_HitPos.z);
|
||||
a_Entity->TakeDamage(dtEnderPearl, m_Attacker, 5, 0);
|
||||
return true;
|
||||
}
|
||||
);
|
||||
|
||||
private:
|
||||
|
||||
cEntity * m_Attacker;
|
||||
Vector3i m_HitPos;
|
||||
};
|
||||
|
||||
cProjectileCreatorCallbackForPlayers PCCFP(this, a_HitPos);
|
||||
GetWorld()->FindAndDoWithPlayer(m_CreatorData.m_Name, PCCFP);
|
||||
}
|
||||
|
@ -416,6 +416,20 @@ template class SizeChecker<UInt8, 1>;
|
||||
|
||||
|
||||
|
||||
|
||||
/** A generic interface used mainly in ForEach() functions */
|
||||
template <typename Type> class cItemCallback
|
||||
{
|
||||
public:
|
||||
virtual ~cItemCallback() {}
|
||||
|
||||
/** Called for each item in the internal list; return true to stop the loop, or false to continue enumerating */
|
||||
virtual bool Item(Type * a_Type) = 0;
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
|
||||
/** Clamp X to the specified range. */
|
||||
template <typename T>
|
||||
T Clamp(T a_Value, T a_Min, T a_Max)
|
||||
|
@ -20,7 +20,8 @@
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// cFloaterCallback
|
||||
class cFloaterCallback
|
||||
class cFloaterCallback :
|
||||
public cEntityCallback
|
||||
{
|
||||
public:
|
||||
cFloaterCallback(void) :
|
||||
@ -29,14 +30,13 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
bool operator () (cEntity & a_Entity)
|
||||
virtual bool Item(cEntity * a_Entity) override
|
||||
{
|
||||
auto & Floater = static_cast<cFloater &>(a_Entity);
|
||||
m_CanPickup = Floater.CanPickup();
|
||||
m_Pos = Floater.GetPosition();
|
||||
m_BitePos = Floater.GetBitePos();
|
||||
m_AttachedMobID = Floater.GetAttachedMobID();
|
||||
Floater.Destroy(true);
|
||||
m_CanPickup = reinterpret_cast<cFloater *>(a_Entity)->CanPickup();
|
||||
m_Pos = Vector3d(a_Entity->GetPosX(), a_Entity->GetPosY(), a_Entity->GetPosZ());
|
||||
m_BitePos = reinterpret_cast<cFloater *>(a_Entity)->GetBitePos();
|
||||
m_AttachedMobID = reinterpret_cast<cFloater *>(a_Entity)->GetAttachedMobID();
|
||||
a_Entity->Destroy(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -57,6 +57,33 @@ protected:
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// cSweepEntityCallback:
|
||||
|
||||
class cSweepEntityCallback :
|
||||
public cEntityCallback
|
||||
{
|
||||
public:
|
||||
cSweepEntityCallback(Vector3d a_PlayerPos) :
|
||||
m_PlayerPos(a_PlayerPos)
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool Item(cEntity * a_Entity) override
|
||||
{
|
||||
Vector3d Speed = m_PlayerPos - a_Entity->GetPosition();
|
||||
a_Entity->AddSpeed(Speed);
|
||||
return true;
|
||||
}
|
||||
|
||||
protected:
|
||||
Vector3d m_PlayerPos;
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class cItemFishingRodHandler :
|
||||
public cItemHandler
|
||||
{
|
||||
@ -90,13 +117,8 @@ public:
|
||||
|
||||
if (FloaterInfo.IsAttached())
|
||||
{
|
||||
a_World->DoWithEntityByID(FloaterInfo.GetAttachedMobID(), [=](cEntity & a_Entity)
|
||||
{
|
||||
Vector3d Speed = a_Player->GetPosition() - a_Entity.GetPosition();
|
||||
a_Entity.AddSpeed(Speed);
|
||||
return true;
|
||||
}
|
||||
);
|
||||
cSweepEntityCallback SweepEntity(a_Player->GetPosition());
|
||||
a_World->DoWithEntityByID(FloaterInfo.GetAttachedMobID(), SweepEntity);
|
||||
}
|
||||
else if (FloaterInfo.CanPickup())
|
||||
{
|
||||
|
@ -62,30 +62,42 @@ public:
|
||||
int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace
|
||||
)
|
||||
{
|
||||
auto HeadType = static_cast<eMobHeadType>(a_EquippedItem.m_ItemDamage);
|
||||
auto BlockMeta = static_cast<NIBBLETYPE>(a_BlockFace);
|
||||
|
||||
// Use a callback to set the properties of the mob head block entity:
|
||||
a_World.DoWithBlockEntityAt(a_BlockX, a_BlockY, a_BlockZ, [&](cBlockEntity & a_BlockEntity)
|
||||
class cCallback : public cBlockEntityCallback
|
||||
{
|
||||
cPlayer & m_Player;
|
||||
eMobHeadType m_HeadType;
|
||||
NIBBLETYPE m_BlockMeta;
|
||||
|
||||
virtual bool Item(cBlockEntity * a_BlockEntity)
|
||||
{
|
||||
if (a_BlockEntity.GetBlockType() != E_BLOCK_HEAD)
|
||||
if (a_BlockEntity->GetBlockType() != E_BLOCK_HEAD)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
auto & MobHeadEntity = static_cast<cMobHeadEntity &>(a_BlockEntity);
|
||||
auto MobHeadEntity = static_cast<cMobHeadEntity *>(a_BlockEntity);
|
||||
|
||||
int Rotation = 0;
|
||||
if (BlockMeta == 1)
|
||||
if (m_BlockMeta == 1)
|
||||
{
|
||||
Rotation = FloorC(a_Player.GetYaw() * 16.0f / 360.0f + 0.5f) & 0x0f;
|
||||
Rotation = FloorC(m_Player.GetYaw() * 16.0f / 360.0f + 0.5f) & 0x0f;
|
||||
}
|
||||
|
||||
MobHeadEntity.SetType(HeadType);
|
||||
MobHeadEntity.SetRotation(static_cast<eMobHeadRotation>(Rotation));
|
||||
MobHeadEntity.GetWorld()->BroadcastBlockEntity(MobHeadEntity.GetPosX(), MobHeadEntity.GetPosY(), MobHeadEntity.GetPosZ());
|
||||
MobHeadEntity->SetType(m_HeadType);
|
||||
MobHeadEntity->SetRotation(static_cast<eMobHeadRotation>(Rotation));
|
||||
MobHeadEntity->GetWorld()->BroadcastBlockEntity(MobHeadEntity->GetPosX(), MobHeadEntity->GetPosY(), MobHeadEntity->GetPosZ());
|
||||
return false;
|
||||
}
|
||||
);
|
||||
|
||||
public:
|
||||
cCallback (cPlayer & a_CBPlayer, eMobHeadType a_HeadType, NIBBLETYPE a_BlockMeta) :
|
||||
m_Player(a_CBPlayer),
|
||||
m_HeadType(a_HeadType),
|
||||
m_BlockMeta(a_BlockMeta)
|
||||
{}
|
||||
};
|
||||
cCallback Callback(a_Player, static_cast<eMobHeadType>(a_EquippedItem.m_ItemDamage), static_cast<NIBBLETYPE>(a_BlockFace));
|
||||
a_World.DoWithBlockEntityAt(a_BlockX, a_BlockY, a_BlockZ, Callback);
|
||||
}
|
||||
|
||||
|
||||
@ -231,16 +243,24 @@ public:
|
||||
// If it is a mob head, check the correct head type using the block entity:
|
||||
if (BlockType == E_BLOCK_HEAD)
|
||||
{
|
||||
bool IsWitherHead = false;
|
||||
a_World.DoWithBlockEntityAt(BlockX, BlockY, BlockZ, [&](cBlockEntity & a_Entity)
|
||||
class cHeadCallback: public cBlockEntityCallback
|
||||
{
|
||||
virtual bool Item(cBlockEntity * a_Entity) override
|
||||
{
|
||||
ASSERT(a_Entity.GetBlockType() == E_BLOCK_HEAD);
|
||||
auto & MobHead = static_cast<cMobHeadEntity &>(a_Entity);
|
||||
IsWitherHead = (MobHead.GetType() == SKULL_TYPE_WITHER);
|
||||
ASSERT(a_Entity->GetBlockType() == E_BLOCK_HEAD);
|
||||
cMobHeadEntity * MobHead = static_cast<cMobHeadEntity *>(a_Entity);
|
||||
m_IsWitherHead = (MobHead->GetType() == SKULL_TYPE_WITHER);
|
||||
return true;
|
||||
}
|
||||
);
|
||||
if (!IsWitherHead)
|
||||
public:
|
||||
cHeadCallback(void):
|
||||
m_IsWitherHead(false)
|
||||
{
|
||||
}
|
||||
bool m_IsWitherHead;
|
||||
} callback;
|
||||
a_World.DoWithBlockEntityAt(BlockX, BlockY, BlockZ, callback);
|
||||
if (!callback.m_IsWitherHead)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -267,18 +287,25 @@ public:
|
||||
/** Awards the achievement to all players close to the specified point. */
|
||||
void AwardSpawnWitherAchievement(cWorld & a_World, int a_BlockX, int a_BlockY, int a_BlockZ)
|
||||
{
|
||||
Vector3f Pos{ static_cast<float>(a_BlockX), static_cast<float>(a_BlockY), static_cast<float>(a_BlockZ) };
|
||||
a_World.ForEachPlayer([=](cPlayer & a_Player)
|
||||
class cPlayerCallback : public cPlayerListCallback
|
||||
{
|
||||
Vector3f m_Pos;
|
||||
|
||||
virtual bool Item(cPlayer * a_Player)
|
||||
{
|
||||
// If player is close, award achievement:
|
||||
double Dist = (a_Player.GetPosition() - Pos).Length();
|
||||
double Dist = (a_Player->GetPosition() - m_Pos).Length();
|
||||
if (Dist < 50.0)
|
||||
{
|
||||
a_Player.AwardAchievement(achSpawnWither);
|
||||
a_Player->AwardAchievement(achSpawnWither);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
);
|
||||
|
||||
public:
|
||||
cPlayerCallback(const Vector3f & a_Pos) : m_Pos(a_Pos) {}
|
||||
} PlayerCallback(Vector3f(static_cast<float>(a_BlockX), static_cast<float>(a_BlockY), static_cast<float>(a_BlockZ)));
|
||||
a_World.ForEachPlayer(PlayerCallback);
|
||||
}
|
||||
|
||||
|
||||
|
@ -199,12 +199,12 @@ bool cLineBlockTracer::Trace(double a_StartX, double a_StartY, double a_StartZ,
|
||||
m_DiffY = m_EndY - m_StartY;
|
||||
m_DiffZ = m_EndZ - m_StartZ;
|
||||
|
||||
// The actual trace is handled with ChunkMapCS locked by calling our ChunkCallback for the specified chunk
|
||||
// The actual trace is handled with ChunkMapCS locked by calling our Item() for the specified chunk
|
||||
int BlockX = FloorC(m_StartX);
|
||||
int BlockZ = FloorC(m_StartZ);
|
||||
int ChunkX, ChunkZ;
|
||||
cChunkDef::BlockToChunk(BlockX, BlockZ, ChunkX, ChunkZ);
|
||||
return m_World->DoWithChunk(ChunkX, ChunkZ, [this](cChunk & a_Chunk) { return ChunkCallback(&a_Chunk); });
|
||||
return m_World->DoWithChunk(ChunkX, ChunkZ, *this);
|
||||
}
|
||||
|
||||
|
||||
@ -308,7 +308,7 @@ bool cLineBlockTracer::MoveToNextBlock(void)
|
||||
|
||||
|
||||
|
||||
bool cLineBlockTracer::ChunkCallback(cChunk * a_Chunk)
|
||||
bool cLineBlockTracer::Item(cChunk * a_Chunk)
|
||||
{
|
||||
ASSERT((m_CurrentY >= 0) && (m_CurrentY < cChunkDef::Height)); // This should be provided by FixStartAboveWorld() / FixStartBelowWorld()
|
||||
|
||||
|
@ -18,12 +18,17 @@
|
||||
// fwd: Chunk.h
|
||||
class cChunk;
|
||||
|
||||
// fwd: cChunkMap.h
|
||||
typedef cItemCallback<cChunk> cChunkCallback;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class cLineBlockTracer :
|
||||
public cBlockTracer
|
||||
public cBlockTracer,
|
||||
public cChunkCallback
|
||||
{
|
||||
typedef cBlockTracer super;
|
||||
|
||||
@ -104,7 +109,8 @@ protected:
|
||||
/** Moves m_Current to the next block on the line; returns false if no move is possible (reached the end) */
|
||||
bool MoveToNextBlock(void);
|
||||
|
||||
bool ChunkCallback(cChunk * a_Chunk);
|
||||
// cChunkCallback overrides:
|
||||
virtual bool Item(cChunk * a_Chunk) override;
|
||||
} ;
|
||||
|
||||
|
||||
|
42
src/Map.cpp
42
src/Map.cpp
@ -120,17 +120,27 @@ bool cMap::UpdatePixel(unsigned int a_X, unsigned int a_Z)
|
||||
int RelX = BlockX - (ChunkX * cChunkDef::Width);
|
||||
int RelZ = BlockZ - (ChunkZ * cChunkDef::Width);
|
||||
|
||||
ASSERT(m_World != nullptr);
|
||||
class cCalculatePixelCb :
|
||||
public cChunkCallback
|
||||
{
|
||||
cMap * m_Map;
|
||||
|
||||
ColorID PixelData;
|
||||
m_World->DoWithChunk(ChunkX, ChunkZ, [&](cChunk & a_Chunk)
|
||||
int m_RelX, m_RelZ;
|
||||
|
||||
ColorID m_PixelData;
|
||||
|
||||
public:
|
||||
cCalculatePixelCb(cMap * a_Map, int a_RelX, int a_RelZ)
|
||||
: m_Map(a_Map), m_RelX(a_RelX), m_RelZ(a_RelZ), m_PixelData(E_BASE_COLOR_TRANSPARENT) {}
|
||||
|
||||
virtual bool Item(cChunk * a_Chunk) override
|
||||
{
|
||||
if (!a_Chunk.IsValid())
|
||||
if (!a_Chunk->IsValid())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (GetDimension() == dimNether)
|
||||
if (m_Map->GetDimension() == dimNether)
|
||||
{
|
||||
// TODO 2014-02-22 xdot: Nether maps
|
||||
|
||||
@ -141,22 +151,22 @@ bool cMap::UpdatePixel(unsigned int a_X, unsigned int a_Z)
|
||||
BLOCKTYPE TargetBlock;
|
||||
NIBBLETYPE TargetMeta;
|
||||
|
||||
auto Height = a_Chunk.GetHeight(RelX, RelZ);
|
||||
auto Height = a_Chunk->GetHeight(m_RelX, m_RelZ);
|
||||
auto ChunkHeight = cChunkDef::Height;
|
||||
a_Chunk.GetBlockTypeMeta(RelX, Height, RelZ, TargetBlock, TargetMeta);
|
||||
a_Chunk->GetBlockTypeMeta(m_RelX, Height, m_RelZ, TargetBlock, TargetMeta);
|
||||
auto ColourID = BlockHandler(TargetBlock)->GetMapBaseColourID(TargetMeta);
|
||||
|
||||
if (IsBlockWater(TargetBlock))
|
||||
{
|
||||
ChunkHeight /= 4;
|
||||
while (((--Height) != -1) && IsBlockWater(a_Chunk.GetBlock(RelX, Height, RelZ)))
|
||||
while (((--Height) != -1) && IsBlockWater(a_Chunk->GetBlock(m_RelX, Height, m_RelZ)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (ColourID == 0)
|
||||
{
|
||||
while (((--Height) != -1) && ((ColourID = BlockHandler(a_Chunk.GetBlock(RelX, Height, RelZ))->GetMapBaseColourID(a_Chunk.GetMeta(RelX, Height, RelZ))) == 0))
|
||||
while (((--Height) != -1) && ((ColourID = BlockHandler(a_Chunk->GetBlock(m_RelX, Height, m_RelZ))->GetMapBaseColourID(a_Chunk->GetMeta(m_RelX, Height, m_RelZ))) == 0))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@ -164,12 +174,20 @@ bool cMap::UpdatePixel(unsigned int a_X, unsigned int a_Z)
|
||||
|
||||
// Multiply base color ID by 4 and add brightness ID
|
||||
const int BrightnessIDSize = static_cast<int>(BrightnessID.size());
|
||||
PixelData = ColourID * 4 + BrightnessID[static_cast<size_t>(Clamp<int>((BrightnessIDSize * Height) / ChunkHeight, 0, BrightnessIDSize - 1))];
|
||||
m_PixelData = ColourID * 4 + BrightnessID[static_cast<size_t>(Clamp<int>((BrightnessIDSize * Height) / ChunkHeight, 0, BrightnessIDSize - 1))];
|
||||
return false;
|
||||
}
|
||||
);
|
||||
|
||||
SetPixel(a_X, a_Z, PixelData);
|
||||
ColorID GetPixelData(void) const
|
||||
{
|
||||
return m_PixelData;
|
||||
}
|
||||
} CalculatePixelCb(this, RelX, RelZ);
|
||||
|
||||
ASSERT(m_World != nullptr);
|
||||
m_World->DoWithChunk(ChunkX, ChunkZ, CalculatePixelCb);
|
||||
|
||||
SetPixel(a_X, a_Z, CalculatePixelCb.GetPixelData());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
|
||||
|
||||
// MapManager.cpp
|
||||
|
||||
#include "Globals.h"
|
||||
@ -22,7 +22,7 @@ cMapManager::cMapManager(cWorld * a_World)
|
||||
|
||||
|
||||
|
||||
bool cMapManager::DoWithMap(UInt32 a_ID, const cMapCallback & a_Callback)
|
||||
bool cMapManager::DoWithMap(UInt32 a_ID, cMapCallback & a_Callback)
|
||||
{
|
||||
cCSLock Lock(m_CS);
|
||||
cMap * Map = GetMapData(a_ID);
|
||||
@ -33,7 +33,7 @@ bool cMapManager::DoWithMap(UInt32 a_ID, const cMapCallback & a_Callback)
|
||||
}
|
||||
else
|
||||
{
|
||||
a_Callback(*Map);
|
||||
a_Callback.Item(Map);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
|
||||
|
||||
// MapManager.h
|
||||
|
||||
|
||||
@ -11,13 +11,12 @@
|
||||
|
||||
|
||||
|
||||
#include <functional>
|
||||
#include "Map.h"
|
||||
|
||||
|
||||
|
||||
|
||||
using cMapCallback = std::function<bool(cMap &)>;
|
||||
typedef cItemCallback<cMap> cMapCallback;
|
||||
|
||||
|
||||
|
||||
@ -42,7 +41,7 @@ public:
|
||||
/** Calls the callback for the map with the specified ID.
|
||||
Returns true if the map was found and the callback called, false if map not found.
|
||||
Callback return value is ignored. */
|
||||
bool DoWithMap(UInt32 a_ID, const cMapCallback & a_Callback); // Exported in ManualBindings.cpp
|
||||
bool DoWithMap(UInt32 a_ID, cMapCallback & a_Callback); // Exported in ManualBindings.cpp
|
||||
|
||||
/** Ticks each registered map */
|
||||
void TickMaps(void);
|
||||
|
@ -369,7 +369,7 @@ cMonster * cMobSpawner::TryToSpawnHere(cChunk * a_Chunk, int a_RelX, int a_RelY,
|
||||
auto NewMobPtr = newMob.get();
|
||||
if (newMob)
|
||||
{
|
||||
m_Spawned.push_back(std::move(newMob));
|
||||
m_Spawned.insert(std::move(newMob));
|
||||
}
|
||||
return NewMobPtr;
|
||||
}
|
||||
@ -390,6 +390,15 @@ void cMobSpawner::NewPack()
|
||||
|
||||
|
||||
|
||||
cMobSpawner::tSpawnedContainer & cMobSpawner::getSpawned(void)
|
||||
{
|
||||
return m_Spawned;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cMobSpawner::CanSpawnAnything(void)
|
||||
{
|
||||
return !m_AllowedTypes.empty();
|
||||
|
@ -37,10 +37,8 @@ public :
|
||||
// return true if there is at least one allowed type
|
||||
bool CanSpawnAnything(void);
|
||||
|
||||
std::vector<std::unique_ptr<cMonster>> & getSpawned(void)
|
||||
{
|
||||
return m_Spawned;
|
||||
}
|
||||
typedef const std::set<std::unique_ptr<cMonster>> tSpawnedContainer;
|
||||
tSpawnedContainer & getSpawned(void);
|
||||
|
||||
/** Returns true if specified type of mob can spawn on specified block */
|
||||
static bool CanSpawnHere(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ, eMonsterType a_MobType, EMCSBiome a_Biome);
|
||||
@ -57,7 +55,7 @@ protected :
|
||||
std::set<eMonsterType> m_AllowedTypes;
|
||||
bool m_NewPack;
|
||||
eMonsterType m_MobType;
|
||||
std::vector<std::unique_ptr<cMonster>> m_Spawned;
|
||||
std::set<std::unique_ptr<cMonster>> m_Spawned;
|
||||
} ;
|
||||
|
||||
|
||||
|
@ -81,16 +81,21 @@ void cCreeper::GetDrops(cItems & a_Drops, cEntity * a_Killer)
|
||||
a_Killer->IsProjectile() &&
|
||||
((reinterpret_cast<cProjectileEntity *>(a_Killer))->GetCreatorUniqueID() != cEntity::INVALID_ID))
|
||||
{
|
||||
auto ProjectileCreatorCallback = [](cEntity & a_Entity)
|
||||
class cProjectileCreatorCallback : public cEntityCallback
|
||||
{
|
||||
public:
|
||||
cProjectileCreatorCallback(void) {}
|
||||
|
||||
virtual bool Item(cEntity * a_Entity) override
|
||||
{
|
||||
if (a_Entity.IsMob() && ((static_cast<cMonster &>(a_Entity)).GetMobType() == mtSkeleton))
|
||||
if (a_Entity->IsMob() && ((reinterpret_cast<cMonster *>(a_Entity))->GetMobType() == mtSkeleton))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
if (GetWorld()->DoWithEntityByID(static_cast<cProjectileEntity *>(a_Killer)->GetCreatorUniqueID(), ProjectileCreatorCallback))
|
||||
}
|
||||
} PCC;
|
||||
if (GetWorld()->DoWithEntityByID((reinterpret_cast<cProjectileEntity *>(a_Killer))->GetCreatorUniqueID(), PCC))
|
||||
{
|
||||
AddRandomDropItem(a_Drops, 1, 1, static_cast<short>(m_World->GetTickRandomNumber(11) + E_ITEM_FIRST_DISC));
|
||||
}
|
||||
|
@ -10,7 +10,8 @@
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// cPlayerLookCheck
|
||||
class cPlayerLookCheck
|
||||
class cPlayerLookCheck :
|
||||
public cPlayerListCallback
|
||||
{
|
||||
public:
|
||||
cPlayerLookCheck(Vector3d a_EndermanPos, int a_SightDistance) :
|
||||
@ -20,29 +21,29 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
bool operator () (cPlayer & a_Player)
|
||||
virtual bool Item(cPlayer * a_Player) override
|
||||
{
|
||||
// Don't check players who cannot be targeted
|
||||
if (!a_Player.CanMobsTarget())
|
||||
if (!a_Player->CanMobsTarget())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Don't check players who are more than SightDistance (64) blocks away
|
||||
auto Direction = m_EndermanPos - a_Player.GetPosition();
|
||||
auto Direction = m_EndermanPos - a_Player->GetPosition();
|
||||
if (Direction.Length() > m_SightDistance)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Don't check if the player has a pumpkin on his head
|
||||
if (a_Player.GetEquippedHelmet().m_ItemType == E_BLOCK_PUMPKIN)
|
||||
if (a_Player->GetEquippedHelmet().m_ItemType == E_BLOCK_PUMPKIN)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the player's crosshair is within 5 degrees of the enderman, it counts as looking
|
||||
auto LookVector = a_Player.GetLookVector();
|
||||
auto LookVector = a_Player->GetLookVector();
|
||||
auto dot = Direction.Dot(LookVector);
|
||||
if (dot <= cos(0.09)) // 0.09 rad ~ 5 degrees
|
||||
{
|
||||
@ -50,13 +51,13 @@ public:
|
||||
}
|
||||
|
||||
// TODO: Check if endermen are angered through water in Vanilla
|
||||
if (!cLineBlockTracer::LineOfSightTrace(*a_Player.GetWorld(), m_EndermanPos, a_Player.GetPosition(), cLineBlockTracer::losAirWater))
|
||||
if (!cLineBlockTracer::LineOfSightTrace(*a_Player->GetWorld(), m_EndermanPos, a_Player->GetPosition(), cLineBlockTracer::losAirWater))
|
||||
{
|
||||
// No direct line of sight
|
||||
return false;
|
||||
}
|
||||
|
||||
m_Player = &a_Player;
|
||||
m_Player = a_Player;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -90,25 +90,30 @@ void cOcelot::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
|
||||
|
||||
void cOcelot::TickFollowPlayer()
|
||||
{
|
||||
Vector3d OwnerPos;
|
||||
bool OwnerFlying = false;
|
||||
auto Callback = [&](cPlayer & a_Player)
|
||||
class cCallback :
|
||||
public cPlayerListCallback
|
||||
{
|
||||
OwnerPos = a_Player.GetPosition();
|
||||
OwnerFlying = a_Player.IsFlying();
|
||||
return true;
|
||||
};
|
||||
virtual bool Item(cPlayer * a_Player) override
|
||||
{
|
||||
OwnerPos = a_Player->GetPosition();
|
||||
OwnerFlying = a_Player->IsFlying();
|
||||
return true;
|
||||
}
|
||||
public:
|
||||
Vector3d OwnerPos;
|
||||
bool OwnerFlying;
|
||||
} Callback;
|
||||
|
||||
if (m_World->DoWithPlayerByUUID(m_OwnerUUID, Callback))
|
||||
{
|
||||
// The player is present in the world, follow him:
|
||||
double Distance = (OwnerPos - GetPosition()).Length();
|
||||
double Distance = (Callback.OwnerPos - GetPosition()).Length();
|
||||
if (Distance > 12)
|
||||
{
|
||||
if (!OwnerFlying)
|
||||
if (!Callback.OwnerFlying)
|
||||
{
|
||||
OwnerPos.y = FindFirstNonAirBlockPosition(OwnerPos.x, OwnerPos.z);
|
||||
TeleportToCoords(OwnerPos.x, OwnerPos.y, OwnerPos.z);
|
||||
Callback.OwnerPos.y = FindFirstNonAirBlockPosition(Callback.OwnerPos.x, Callback.OwnerPos.z);
|
||||
TeleportToCoords(Callback.OwnerPos.x, Callback.OwnerPos.y, Callback.OwnerPos.z);
|
||||
}
|
||||
}
|
||||
if (Distance < 2)
|
||||
@ -117,9 +122,9 @@ void cOcelot::TickFollowPlayer()
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!OwnerFlying)
|
||||
if (!Callback.OwnerFlying)
|
||||
{
|
||||
MoveToPosition(OwnerPos);
|
||||
MoveToPosition(Callback.OwnerPos);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -200,19 +205,27 @@ void cOcelot::SpawnOn(cClientHandle & a_ClientHandle)
|
||||
|
||||
|
||||
|
||||
class cFindSittingCat :
|
||||
public cEntityCallback
|
||||
{
|
||||
virtual bool Item(cEntity * a_Entity) override
|
||||
{
|
||||
return (
|
||||
(a_Entity->GetEntityType() == cEntity::etMonster) &&
|
||||
(static_cast<cMonster *>(a_Entity)->GetMobType() == eMonsterType::mtOcelot) &&
|
||||
(static_cast<cOcelot *>(a_Entity)->IsSitting())
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cOcelot::IsCatSittingOnBlock(cWorld * a_World, Vector3d a_BlockPosition)
|
||||
{
|
||||
return a_World->ForEachEntityInBox(
|
||||
cBoundingBox(Vector3d(a_BlockPosition.x, a_BlockPosition.y + 1, a_BlockPosition.z), 1),
|
||||
[=](cEntity & a_Entity)
|
||||
{
|
||||
return (
|
||||
(a_Entity.GetEntityType() == cEntity::etMonster) &&
|
||||
(static_cast<cMonster &>(a_Entity).GetMobType() == eMonsterType::mtOcelot) &&
|
||||
(static_cast<cOcelot &>(a_Entity).IsSitting())
|
||||
);
|
||||
}
|
||||
);
|
||||
cFindSittingCat FindSittingCat;
|
||||
return a_World->ForEachEntityInBox(cBoundingBox(Vector3d(a_BlockPosition.x, a_BlockPosition.y + 1, a_BlockPosition.z), 1), FindSittingCat);
|
||||
}
|
||||
|
||||
|
||||
|
@ -109,18 +109,23 @@ void cPassiveMonster::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
|
||||
Vector3f Pos = (GetPosition() + m_LovePartner->GetPosition()) * 0.5;
|
||||
UInt32 BabyID = m_World->SpawnMob(Pos.x, Pos.y, Pos.z, GetMobType(), true);
|
||||
|
||||
cPassiveMonster * Baby = nullptr;
|
||||
|
||||
m_World->DoWithEntityByID(BabyID, [&](cEntity & a_Entity)
|
||||
class cBabyInheritCallback :
|
||||
public cEntityCallback
|
||||
{
|
||||
public:
|
||||
cPassiveMonster * Baby;
|
||||
cBabyInheritCallback() : Baby(nullptr) { }
|
||||
virtual bool Item(cEntity * a_Entity) override
|
||||
{
|
||||
Baby = static_cast<cPassiveMonster *>(&a_Entity);
|
||||
Baby = static_cast<cPassiveMonster *>(a_Entity);
|
||||
return true;
|
||||
}
|
||||
);
|
||||
} Callback;
|
||||
|
||||
if (Baby != nullptr)
|
||||
m_World->DoWithEntityByID(BabyID, Callback);
|
||||
if (Callback.Baby != nullptr)
|
||||
{
|
||||
Baby->InheritFromParents(this, m_LovePartner);
|
||||
Callback.Baby->InheritFromParents(this, m_LovePartner);
|
||||
}
|
||||
|
||||
m_World->SpawnExperienceOrb(Pos.x, Pos.y, Pos.z, GetRandomProvider().RandInt(1, 6));
|
||||
@ -154,37 +159,49 @@ void cPassiveMonster::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
|
||||
{
|
||||
if (m_LovePartner == nullptr)
|
||||
{
|
||||
m_World->ForEachEntityInBox(cBoundingBox(GetPosition(), 8, 8), [=](cEntity & a_Entity)
|
||||
class LookForLover : public cEntityCallback
|
||||
{
|
||||
public:
|
||||
cEntity * m_Me;
|
||||
|
||||
LookForLover(cEntity * a_Me) :
|
||||
m_Me(a_Me)
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool Item(cEntity * a_Entity) override
|
||||
{
|
||||
// If the entity is not a monster, don't breed with it
|
||||
// Also, do not self-breed
|
||||
if ((a_Entity.GetEntityType() != etMonster) || (&a_Entity == this))
|
||||
if ((a_Entity->GetEntityType() != etMonster) || (a_Entity == m_Me))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
auto & Me = static_cast<cPassiveMonster&>(*this);
|
||||
auto & PotentialPartner = static_cast<cPassiveMonster&>(a_Entity);
|
||||
cPassiveMonster * Me = static_cast<cPassiveMonster*>(m_Me);
|
||||
cPassiveMonster * PotentialPartner = static_cast<cPassiveMonster*>(a_Entity);
|
||||
|
||||
// If the potential partner is not of the same species, don't breed with it
|
||||
if (PotentialPartner.GetMobType() != Me.GetMobType())
|
||||
if (PotentialPartner->GetMobType() != Me->GetMobType())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the potential partner is not in love
|
||||
// Or they already have a mate, do not breed with them
|
||||
if ((!PotentialPartner.IsInLove()) || (PotentialPartner.GetPartner() != nullptr))
|
||||
if ((!PotentialPartner->IsInLove()) || (PotentialPartner->GetPartner() != nullptr))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// All conditions met, let's breed!
|
||||
PotentialPartner.EngageLoveMode(&Me);
|
||||
Me.EngageLoveMode(&PotentialPartner);
|
||||
PotentialPartner->EngageLoveMode(Me);
|
||||
Me->EngageLoveMode(PotentialPartner);
|
||||
return true;
|
||||
}
|
||||
);
|
||||
} Callback(this);
|
||||
|
||||
m_World->ForEachEntityInBox(cBoundingBox(GetPosition(), 8, 8, -4), Callback);
|
||||
}
|
||||
|
||||
m_LoveTimer--;
|
||||
|
@ -101,19 +101,28 @@ void cWither::KilledBy(TakeDamageInfo & a_TDI)
|
||||
{
|
||||
super::KilledBy(a_TDI);
|
||||
|
||||
Vector3d Pos = GetPosition();
|
||||
m_World->ForEachPlayer([=](cPlayer & a_Player)
|
||||
class cPlayerCallback : public cPlayerListCallback
|
||||
{
|
||||
Vector3f m_Pos;
|
||||
|
||||
virtual bool Item(cPlayer * a_Player)
|
||||
{
|
||||
// TODO 2014-05-21 xdot: Vanilla minecraft uses an AABB check instead of a radius one
|
||||
double Dist = (a_Player.GetPosition() - Pos).Length();
|
||||
double Dist = (a_Player->GetPosition() - m_Pos).Length();
|
||||
if (Dist < 50.0)
|
||||
{
|
||||
// If player is close, award achievement
|
||||
a_Player.AwardAchievement(achKillWither);
|
||||
a_Player->AwardAchievement(achKillWither);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
);
|
||||
|
||||
public:
|
||||
cPlayerCallback(const Vector3f & a_Pos) : m_Pos(a_Pos) {}
|
||||
|
||||
} PlayerCallback(GetPosition());
|
||||
|
||||
m_World->ForEachPlayer(PlayerCallback);
|
||||
}
|
||||
|
||||
|
||||
|
@ -80,13 +80,19 @@ void cWolf::NotifyAlliesOfFight(cPawn * a_Opponent)
|
||||
return;
|
||||
}
|
||||
m_NotificationCooldown = 15;
|
||||
|
||||
m_World->DoWithPlayerByUUID(m_OwnerUUID, [=](cPlayer & a_Player)
|
||||
class cCallback : public cPlayerListCallback
|
||||
{
|
||||
virtual bool Item(cPlayer * a_Player) override
|
||||
{
|
||||
a_Player.NotifyNearbyWolves(a_Opponent, false);
|
||||
a_Player->NotifyNearbyWolves(m_Opponent, false);
|
||||
return false;
|
||||
}
|
||||
);
|
||||
public:
|
||||
cPawn * m_Opponent;
|
||||
} Callback;
|
||||
|
||||
Callback.m_Opponent = a_Opponent;
|
||||
m_World->DoWithPlayerByUUID(m_OwnerUUID, Callback);
|
||||
}
|
||||
|
||||
bool cWolf::Attack(std::chrono::milliseconds a_Dt)
|
||||
@ -341,25 +347,30 @@ void cWolf::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
|
||||
|
||||
void cWolf::TickFollowPlayer()
|
||||
{
|
||||
Vector3d OwnerPos;
|
||||
bool OwnerFlying;
|
||||
auto Callback = [&](cPlayer & a_Player)
|
||||
class cCallback :
|
||||
public cPlayerListCallback
|
||||
{
|
||||
OwnerPos = a_Player.GetPosition();
|
||||
OwnerFlying = a_Player.IsFlying();
|
||||
return true;
|
||||
};
|
||||
virtual bool Item(cPlayer * a_Player) override
|
||||
{
|
||||
OwnerPos = a_Player->GetPosition();
|
||||
OwnerFlying = a_Player->IsFlying();
|
||||
return true;
|
||||
}
|
||||
public:
|
||||
Vector3d OwnerPos;
|
||||
bool OwnerFlying;
|
||||
} Callback;
|
||||
|
||||
if (m_World->DoWithPlayerByUUID(m_OwnerUUID, Callback))
|
||||
{
|
||||
// The player is present in the world, follow him:
|
||||
double Distance = (OwnerPos - GetPosition()).Length();
|
||||
double Distance = (Callback.OwnerPos - GetPosition()).Length();
|
||||
if (Distance > 20)
|
||||
{
|
||||
if (!OwnerFlying)
|
||||
if (!Callback.OwnerFlying)
|
||||
{
|
||||
OwnerPos.y = FindFirstNonAirBlockPosition(OwnerPos.x, OwnerPos.z);
|
||||
TeleportToCoords(OwnerPos.x, OwnerPos.y, OwnerPos.z);
|
||||
Callback.OwnerPos.y = FindFirstNonAirBlockPosition(Callback.OwnerPos.x, Callback.OwnerPos.z);
|
||||
TeleportToCoords(Callback.OwnerPos.x, Callback.OwnerPos.y, Callback.OwnerPos.z);
|
||||
SetTarget(nullptr);
|
||||
}
|
||||
}
|
||||
@ -374,9 +385,9 @@ void cWolf::TickFollowPlayer()
|
||||
{
|
||||
if (GetTarget() == nullptr)
|
||||
{
|
||||
if (!OwnerFlying)
|
||||
if (!Callback.OwnerFlying)
|
||||
{
|
||||
MoveToPosition(OwnerPos);
|
||||
MoveToPosition(Callback.OwnerPos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
70
src/Root.cpp
70
src/Root.cpp
@ -1,4 +1,4 @@
|
||||
|
||||
|
||||
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
|
||||
|
||||
#include "Root.h"
|
||||
@ -352,16 +352,22 @@ void cRoot::Start(std::unique_ptr<cSettingsRepositoryInterface> a_OverridesRepo)
|
||||
void cRoot::StopServer()
|
||||
{
|
||||
// Kick all players from the server with custom disconnect message
|
||||
|
||||
bool SentDisconnect = false;
|
||||
cRoot::Get()->ForEachPlayer([&](cPlayer & a_Player)
|
||||
class cPlayerCallback : public cPlayerListCallback
|
||||
{
|
||||
AString m_ShutdownMessage;
|
||||
virtual bool Item(cPlayer * a_Player)
|
||||
{
|
||||
a_Player.GetClientHandlePtr()->Kick(m_Server->GetShutdownMessage());
|
||||
SentDisconnect = true;
|
||||
a_Player->GetClientHandlePtr()->Kick(m_ShutdownMessage);
|
||||
m_HasSentDisconnect = true;
|
||||
return false;
|
||||
}
|
||||
);
|
||||
if (SentDisconnect)
|
||||
public:
|
||||
bool m_HasSentDisconnect;
|
||||
cPlayerCallback(AString a_ShutdownMessage) : m_ShutdownMessage(a_ShutdownMessage) { m_HasSentDisconnect = false; }
|
||||
} PlayerCallback(m_Server->GetShutdownMessage());
|
||||
|
||||
cRoot::Get()->ForEachPlayer(PlayerCallback);
|
||||
if (PlayerCallback.m_HasSentDisconnect)
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||
}
|
||||
@ -578,13 +584,14 @@ cWorld * cRoot::GetWorld(const AString & a_WorldName)
|
||||
|
||||
|
||||
|
||||
bool cRoot::ForEachWorld(const cWorldListCallback & a_Callback)
|
||||
bool cRoot::ForEachWorld(cWorldListCallback & a_Callback)
|
||||
{
|
||||
for (auto & World : m_WorldsByName)
|
||||
for (WorldMap::iterator itr = m_WorldsByName.begin(), itr2 = itr; itr != m_WorldsByName.end(); itr = itr2)
|
||||
{
|
||||
if (World.second != nullptr)
|
||||
++itr2;
|
||||
if (itr->second != nullptr)
|
||||
{
|
||||
if (a_Callback(*World.second))
|
||||
if (a_Callback.Item(itr->second))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -743,7 +750,7 @@ void cRoot::BroadcastChat(const cCompositeChat & a_Message)
|
||||
|
||||
|
||||
|
||||
bool cRoot::ForEachPlayer(const cPlayerListCallback & a_Callback)
|
||||
bool cRoot::ForEachPlayer(cPlayerListCallback & a_Callback)
|
||||
{
|
||||
for (WorldMap::iterator itr = m_WorldsByName.begin(), itr2 = itr; itr != m_WorldsByName.end(); itr = itr2)
|
||||
{
|
||||
@ -760,22 +767,20 @@ bool cRoot::ForEachPlayer(const cPlayerListCallback & a_Callback)
|
||||
|
||||
|
||||
|
||||
bool cRoot::FindAndDoWithPlayer(const AString & a_PlayerName, const cPlayerListCallback & a_Callback)
|
||||
bool cRoot::FindAndDoWithPlayer(const AString & a_PlayerName, cPlayerListCallback & a_Callback)
|
||||
{
|
||||
class cCallback
|
||||
class cCallback : public cPlayerListCallback
|
||||
{
|
||||
size_t m_BestRating;
|
||||
size_t m_NameLength;
|
||||
const AString m_PlayerName;
|
||||
|
||||
public:
|
||||
|
||||
bool operator () (cPlayer & a_Player)
|
||||
virtual bool Item (cPlayer * a_pPlayer)
|
||||
{
|
||||
size_t Rating = RateCompareString (m_PlayerName, a_Player.GetName());
|
||||
size_t Rating = RateCompareString (m_PlayerName, a_pPlayer->GetName());
|
||||
if ((Rating > 0) && (Rating >= m_BestRating))
|
||||
{
|
||||
m_BestMatch = a_Player.GetName();
|
||||
m_BestMatch = a_pPlayer->GetName();
|
||||
if (Rating > m_BestRating)
|
||||
{
|
||||
m_NumMatches = 0;
|
||||
@ -790,6 +795,7 @@ bool cRoot::FindAndDoWithPlayer(const AString & a_PlayerName, const cPlayerListC
|
||||
return false;
|
||||
}
|
||||
|
||||
public:
|
||||
cCallback (const AString & a_CBPlayerName) :
|
||||
m_BestRating(0),
|
||||
m_NameLength(a_CBPlayerName.length()),
|
||||
@ -814,7 +820,7 @@ bool cRoot::FindAndDoWithPlayer(const AString & a_PlayerName, const cPlayerListC
|
||||
|
||||
|
||||
|
||||
bool cRoot::DoWithPlayerByUUID(const cUUID & a_PlayerUUID, const cPlayerListCallback & a_Callback)
|
||||
bool cRoot::DoWithPlayerByUUID(const cUUID & a_PlayerUUID, cPlayerListCallback & a_Callback)
|
||||
{
|
||||
for (WorldMap::iterator itr = m_WorldsByName.begin(); itr != m_WorldsByName.end(); ++itr)
|
||||
{
|
||||
@ -830,7 +836,7 @@ bool cRoot::DoWithPlayerByUUID(const cUUID & a_PlayerUUID, const cPlayerListCall
|
||||
|
||||
|
||||
|
||||
bool cRoot::DoWithPlayer(const AString & a_PlayerName, const cPlayerListCallback & a_Callback)
|
||||
bool cRoot::DoWithPlayer(const AString & a_PlayerName, cPlayerListCallback & a_Callback)
|
||||
{
|
||||
for (auto World : m_WorldsByName)
|
||||
{
|
||||
@ -1022,11 +1028,25 @@ int cRoot::GetFurnaceFuelBurnTime(const cItem & a_Fuel)
|
||||
AStringVector cRoot::GetPlayerTabCompletionMultiWorld(const AString & a_Text)
|
||||
{
|
||||
AStringVector Results;
|
||||
ForEachWorld([&](cWorld & a_World)
|
||||
class cWorldCallback : public cWorldListCallback
|
||||
{
|
||||
public:
|
||||
cWorldCallback(AStringVector & a_Results, const AString & a_Search) :
|
||||
m_Results(a_Results),
|
||||
m_Search(a_Search)
|
||||
{
|
||||
a_World.TabCompleteUserName(a_Text, Results);
|
||||
}
|
||||
|
||||
virtual bool Item(cWorld * a_World) override
|
||||
{
|
||||
a_World->TabCompleteUserName(m_Search, m_Results);
|
||||
return false;
|
||||
}
|
||||
);
|
||||
private:
|
||||
AStringVector & m_Results;
|
||||
const AString & m_Search;
|
||||
} WC(Results, a_Text);
|
||||
|
||||
Get()->ForEachWorld(WC);
|
||||
return Results;
|
||||
}
|
||||
|
17
src/Root.h
17
src/Root.h
@ -1,11 +1,10 @@
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Protocol/Authenticator.h"
|
||||
#include "Protocol/MojangAPI.h"
|
||||
#include "HTTP/HTTPServer.h"
|
||||
#include "Defines.h"
|
||||
#include <functional>
|
||||
#include "RankManager.h"
|
||||
|
||||
|
||||
@ -28,8 +27,8 @@ class cSettingsRepositoryInterface;
|
||||
class cDeadlockDetect;
|
||||
class cUUID;
|
||||
|
||||
using cPlayerListCallback = std::function<bool(cPlayer &)>;
|
||||
using cWorldListCallback = std::function<bool(cWorld &)>;
|
||||
typedef cItemCallback<cPlayer> cPlayerListCallback;
|
||||
typedef cItemCallback<cWorld> cWorldListCallback;
|
||||
|
||||
namespace Json
|
||||
{
|
||||
@ -77,7 +76,7 @@ public:
|
||||
// tolua_end
|
||||
|
||||
/** Calls the callback for each world; returns true if the callback didn't abort (return true) */
|
||||
bool ForEachWorld(const cWorldListCallback & a_Callback); // >> Exported in ManualBindings <<
|
||||
bool ForEachWorld(cWorldListCallback & a_Callback); // >> Exported in ManualBindings <<
|
||||
|
||||
/** Writes chunkstats, for each world and totals, to the output callback */
|
||||
void LogChunkStats(cCommandOutputCallback & a_Output);
|
||||
@ -137,16 +136,16 @@ public:
|
||||
void SaveAllChunks(void); // tolua_export
|
||||
|
||||
/** Calls the callback for each player in all worlds */
|
||||
bool ForEachPlayer(const cPlayerListCallback & a_Callback); // >> EXPORTED IN MANUALBINDINGS <<
|
||||
bool ForEachPlayer(cPlayerListCallback & a_Callback); // >> EXPORTED IN MANUALBINDINGS <<
|
||||
|
||||
/** Finds a player from a partial or complete player name and calls the callback - case-insensitive */
|
||||
bool FindAndDoWithPlayer(const AString & a_PlayerName, const cPlayerListCallback & a_Callback); // >> EXPORTED IN MANUALBINDINGS <<
|
||||
bool FindAndDoWithPlayer(const AString & a_PlayerName, cPlayerListCallback & a_Callback); // >> EXPORTED IN MANUALBINDINGS <<
|
||||
|
||||
/** Finds the player over his uuid and calls the callback */
|
||||
bool DoWithPlayerByUUID(const cUUID & a_PlayerUUID, const cPlayerListCallback & a_Callback); // >> EXPORTED IN MANUALBINDINGS <<
|
||||
bool DoWithPlayerByUUID(const cUUID & a_PlayerUUID, cPlayerListCallback & a_Callback); // >> EXPORTED IN MANUALBINDINGS <<
|
||||
|
||||
/** Finds the player using it's complete username and calls the callback */
|
||||
bool DoWithPlayer(const AString & a_PlayerName, const cPlayerListCallback & a_Callback);
|
||||
bool DoWithPlayer(const AString & a_PlayerName, cPlayerListCallback & a_Callback);
|
||||
|
||||
/** Send playerlist of all worlds to player */
|
||||
void SendPlayerLists(cPlayer * a_DestPlayer);
|
||||
|
@ -1,4 +1,4 @@
|
||||
|
||||
|
||||
// Scoreboard.cpp
|
||||
|
||||
// Implementation of a scoreboard that keeps track of specified objectives
|
||||
@ -487,7 +487,7 @@ cObjective * cScoreboard::GetObjectiveIn(eDisplaySlot a_Slot)
|
||||
|
||||
|
||||
|
||||
bool cScoreboard::ForEachObjectiveWith(cObjective::eType a_Type, const cObjectiveCallback & a_Callback)
|
||||
bool cScoreboard::ForEachObjectiveWith(cObjective::eType a_Type, cObjectiveCallback & a_Callback)
|
||||
{
|
||||
cCSLock Lock(m_CSObjectives);
|
||||
|
||||
@ -496,7 +496,7 @@ bool cScoreboard::ForEachObjectiveWith(cObjective::eType a_Type, const cObjectiv
|
||||
if (it->second.GetType() == a_Type)
|
||||
{
|
||||
// Call callback
|
||||
if (a_Callback(it->second))
|
||||
if (a_Callback.Item(&it->second))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -509,14 +509,14 @@ bool cScoreboard::ForEachObjectiveWith(cObjective::eType a_Type, const cObjectiv
|
||||
|
||||
|
||||
|
||||
bool cScoreboard::ForEachObjective(const cObjectiveCallback & a_Callback)
|
||||
bool cScoreboard::ForEachObjective(cObjectiveCallback & a_Callback)
|
||||
{
|
||||
cCSLock Lock(m_CSObjectives);
|
||||
|
||||
for (cObjectiveMap::iterator it = m_Objectives.begin(); it != m_Objectives.end(); ++it)
|
||||
{
|
||||
// Call callback
|
||||
if (a_Callback(it->second))
|
||||
if (a_Callback.Item(&it->second))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -528,14 +528,14 @@ bool cScoreboard::ForEachObjective(const cObjectiveCallback & a_Callback)
|
||||
|
||||
|
||||
|
||||
bool cScoreboard::ForEachTeam(const cTeamCallback & a_Callback)
|
||||
bool cScoreboard::ForEachTeam(cTeamCallback & a_Callback)
|
||||
{
|
||||
cCSLock Lock(m_CSTeams);
|
||||
|
||||
for (cTeamMap::iterator it = m_Teams.begin(); it != m_Teams.end(); ++it)
|
||||
{
|
||||
// Call callback
|
||||
if (a_Callback(it->second))
|
||||
if (a_Callback.Item(&it->second))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
|
||||
|
||||
// Scoreboard.h
|
||||
|
||||
// Implementation of a scoreboard that keeps track of specified objectives
|
||||
@ -11,15 +11,14 @@
|
||||
|
||||
|
||||
|
||||
#include <functional>
|
||||
|
||||
|
||||
class cObjective;
|
||||
class cTeam;
|
||||
class cWorld;
|
||||
|
||||
using cObjectiveCallback = std::function<bool(cObjective &)>;
|
||||
using cTeamCallback = std::function<bool(cTeam &)>;
|
||||
typedef cItemCallback<cObjective> cObjectiveCallback;
|
||||
typedef cItemCallback<cTeam> cTeamCallback;
|
||||
|
||||
|
||||
|
||||
@ -267,15 +266,15 @@ public:
|
||||
|
||||
/** Execute callback for each objective with the specified type
|
||||
Returns true if all objectives processed, false if the callback aborted by returning true. */
|
||||
bool ForEachObjectiveWith(cObjective::eType a_Type, const cObjectiveCallback & a_Callback);
|
||||
bool ForEachObjectiveWith(cObjective::eType a_Type, cObjectiveCallback & a_Callback);
|
||||
|
||||
/** Execute callback for each objective.
|
||||
Returns true if all objectives have been processed, false if the callback aborted by returning true. */
|
||||
bool ForEachObjective(const cObjectiveCallback & a_Callback); // Exported in ManualBindings.cpp
|
||||
bool ForEachObjective(cObjectiveCallback & a_Callback); // Exported in ManualBindings.cpp
|
||||
|
||||
/** Execute callback for each team.
|
||||
Returns true if all teams have been processed, false if the callback aborted by returning true. */
|
||||
bool ForEachTeam(const cTeamCallback & a_Callback); // Exported in ManualBindings.cpp
|
||||
bool ForEachTeam(cTeamCallback & a_Callback); // Exported in ManualBindings.cpp
|
||||
|
||||
void SetDisplay(cObjective * a_Objective, eDisplaySlot a_Slot);
|
||||
|
||||
|
@ -498,20 +498,26 @@ void cServer::ExecuteConsoleCommand(const AString & a_Cmd, cCommandOutputCallbac
|
||||
}
|
||||
if (split[0] == "destroyentities")
|
||||
{
|
||||
cRoot::Get()->ForEachWorld([](cWorld & a_World)
|
||||
class WorldCallback : public cWorldListCallback
|
||||
{
|
||||
virtual bool Item(cWorld * a_World) override
|
||||
{
|
||||
a_World.ForEachEntity([](cEntity & a_Entity)
|
||||
class EntityCallback : public cEntityCallback
|
||||
{
|
||||
virtual bool Item(cEntity * a_Entity) override
|
||||
{
|
||||
if (!a_Entity.IsPlayer())
|
||||
if (!a_Entity->IsPlayer())
|
||||
{
|
||||
a_Entity.Destroy();
|
||||
a_Entity->Destroy();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
);
|
||||
} EC;
|
||||
a_World->ForEachEntity(EC);
|
||||
return false;
|
||||
}
|
||||
);
|
||||
} WC;
|
||||
cRoot::Get()->ForEachWorld(WC);
|
||||
a_Output.Out("Destroyed all entities");
|
||||
a_Output.Finished();
|
||||
return;
|
||||
|
@ -44,12 +44,17 @@ public:
|
||||
return {};
|
||||
}
|
||||
|
||||
a_World.DoWithCommandBlockAt(a_Position.x, a_Position.y, a_Position.z, [](cCommandBlockEntity & a_CommandBlock)
|
||||
class cSetPowerToCommandBlock : public cCommandBlockCallback
|
||||
{
|
||||
public:
|
||||
virtual bool Item(cCommandBlockEntity * a_CommandBlock) override
|
||||
{
|
||||
a_CommandBlock.Activate();
|
||||
a_CommandBlock->Activate();
|
||||
return false;
|
||||
}
|
||||
);
|
||||
} CmdBlockSP;
|
||||
|
||||
a_World.DoWithCommandBlockAt(a_Position.x, a_Position.y, a_Position.z, CmdBlockSP);
|
||||
return {};
|
||||
}
|
||||
|
||||
|
@ -56,12 +56,18 @@ public:
|
||||
bool WasPoweredPreviously = IsActivated(a_Meta);
|
||||
if (IsPoweredNow && !WasPoweredPreviously)
|
||||
{
|
||||
a_World.DoWithDropSpenserAt(a_Position.x, a_Position.y, a_Position.z, [](cDropSpenserEntity & a_DropSpenser)
|
||||
class cSetPowerToDropSpenser :
|
||||
public cDropSpenserCallback
|
||||
{
|
||||
public:
|
||||
virtual bool Item(cDropSpenserEntity * a_DropSpenser) override
|
||||
{
|
||||
a_DropSpenser.Activate();
|
||||
a_DropSpenser->Activate();
|
||||
return false;
|
||||
}
|
||||
);
|
||||
} DrSpSP;
|
||||
|
||||
a_World.DoWithDropSpenserAt(a_Position.x, a_Position.y, a_Position.z, DrSpSP);
|
||||
}
|
||||
|
||||
// Update the internal dropspenser state if necessary
|
||||
|
@ -45,12 +45,17 @@ public:
|
||||
return {};
|
||||
}
|
||||
|
||||
a_World.DoWithNoteBlockAt(a_Position.x, a_Position.y, a_Position.z, [](cNoteEntity & a_NoteBlock)
|
||||
class cSetPowerToNoteBlock : public cNoteBlockCallback
|
||||
{
|
||||
public:
|
||||
virtual bool Item(cNoteEntity * a_NoteBlock) override
|
||||
{
|
||||
a_NoteBlock.MakeSound();
|
||||
a_NoteBlock->MakeSound();
|
||||
return false;
|
||||
}
|
||||
);
|
||||
} NoteBlockSP;
|
||||
|
||||
a_World.DoWithNoteBlockAt(a_Position.x, a_Position.y, a_Position.z, NoteBlockSP);
|
||||
|
||||
return {};
|
||||
}
|
||||
|
@ -27,37 +27,49 @@ public:
|
||||
{
|
||||
UNUSED(a_Meta);
|
||||
|
||||
unsigned int NumberOfEntities;
|
||||
bool FoundPlayer;
|
||||
a_World.ForEachEntityInBox(cBoundingBox(Vector3d(0.5, 0, 0.5) + a_Position, 0.5, 0.5), [&](cEntity & a_Entity)
|
||||
class cPressurePlateCallback :
|
||||
public cEntityCallback
|
||||
{
|
||||
public:
|
||||
cPressurePlateCallback(void) :
|
||||
m_NumberOfEntities(0),
|
||||
m_FoundPlayer(false)
|
||||
{
|
||||
if (a_Entity.IsPlayer())
|
||||
}
|
||||
|
||||
virtual bool Item(cEntity * a_Entity) override
|
||||
{
|
||||
if (a_Entity->IsPlayer())
|
||||
{
|
||||
FoundPlayer = true;
|
||||
m_FoundPlayer = true;
|
||||
}
|
||||
|
||||
NumberOfEntities++;
|
||||
m_NumberOfEntities++;
|
||||
return false;
|
||||
}
|
||||
);
|
||||
|
||||
unsigned int m_NumberOfEntities;
|
||||
bool m_FoundPlayer;
|
||||
} PressurePlateCallback;
|
||||
a_World.ForEachEntityInBox(cBoundingBox(Vector3d(0.5, 0, 0.5) + a_Position, 0.5, 0.5), PressurePlateCallback);
|
||||
|
||||
switch (a_BlockType)
|
||||
{
|
||||
case E_BLOCK_STONE_PRESSURE_PLATE:
|
||||
{
|
||||
return (FoundPlayer ? 15 : 0);
|
||||
return (PressurePlateCallback.m_FoundPlayer ? 15 : 0);
|
||||
}
|
||||
case E_BLOCK_WOODEN_PRESSURE_PLATE:
|
||||
{
|
||||
return (NumberOfEntities != 0 ? 15 : 0);
|
||||
return (PressurePlateCallback.m_NumberOfEntities != 0 ? 15 : 0);
|
||||
}
|
||||
case E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE:
|
||||
{
|
||||
return std::min(static_cast<unsigned char>(CeilC(NumberOfEntities / 10.f)), static_cast<unsigned char>(15));
|
||||
return std::min(static_cast<unsigned char>(CeilC(PressurePlateCallback.m_NumberOfEntities / 10.f)), static_cast<unsigned char>(15));
|
||||
}
|
||||
case E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE:
|
||||
{
|
||||
return std::min(static_cast<unsigned char>(NumberOfEntities), static_cast<unsigned char>(15));
|
||||
return std::min(static_cast<unsigned char>(PressurePlateCallback.m_NumberOfEntities), static_cast<unsigned char>(15));
|
||||
}
|
||||
default:
|
||||
{
|
||||
|
@ -44,12 +44,17 @@ public:
|
||||
UNUSED(a_Position);
|
||||
UNUSED(a_BlockType);
|
||||
|
||||
UInt8 SignalStrength = 0;
|
||||
auto RearCoordinate = cBlockComparatorHandler::GetRearCoordinate(a_Position, a_Meta & 0x3);
|
||||
a_World.DoWithBlockEntityAt(RearCoordinate.x, RearCoordinate.y, RearCoordinate.z, [&](cBlockEntity & a_BlockEntity)
|
||||
class cContainerCallback : public cBlockEntityCallback
|
||||
{
|
||||
public:
|
||||
cContainerCallback() : m_SignalStrength(0)
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool Item(cBlockEntity * a_BlockEntity) override
|
||||
{
|
||||
// Skip BlockEntities that don't have slots
|
||||
auto BlockEntityWithItems = dynamic_cast<cBlockEntityWithItems *>(&a_BlockEntity);
|
||||
auto BlockEntityWithItems = dynamic_cast<cBlockEntityWithItems *>(a_BlockEntity);
|
||||
if (BlockEntityWithItems == nullptr)
|
||||
{
|
||||
return false;
|
||||
@ -63,18 +68,23 @@ public:
|
||||
Fullness += static_cast<float>(Contents.GetSlot(Slot).m_ItemCount) / Contents.GetSlot(Slot).GetMaxStackSize();
|
||||
}
|
||||
|
||||
SignalStrength = (Fullness < 0.001 /* container empty? */) ? 0 : static_cast<UInt8>(1 + (Fullness / Contents.GetNumSlots()) * 14);
|
||||
m_SignalStrength = (Fullness < 0.001 /* container empty? */) ? 0 : static_cast<unsigned char>(1 + (Fullness / Contents.GetNumSlots()) * 14);
|
||||
return false;
|
||||
}
|
||||
);
|
||||
auto RearPower = SignalStrength;
|
||||
|
||||
unsigned char m_SignalStrength;
|
||||
} CCB;
|
||||
|
||||
auto RearCoordinate = cBlockComparatorHandler::GetRearCoordinate(a_Position, a_Meta & 0x3);
|
||||
a_World.DoWithBlockEntityAt(RearCoordinate.x, RearCoordinate.y, RearCoordinate.z, CCB);
|
||||
auto RearPower = CCB.m_SignalStrength;
|
||||
auto RearType = a_World.GetBlock(RearCoordinate);
|
||||
|
||||
auto PotentialSourceHandler = cIncrementalRedstoneSimulator::GetComponentHandler(RearType);
|
||||
if (PotentialSourceHandler != nullptr)
|
||||
{
|
||||
NIBBLETYPE RearMeta = a_World.GetBlockMeta(RearCoordinate);
|
||||
RearPower = std::max(SignalStrength, PotentialSourceHandler->GetPowerDeliveredToPosition(a_World, RearCoordinate, RearType, RearMeta, a_Position, a_BlockType));
|
||||
RearPower = std::max(CCB.m_SignalStrength, PotentialSourceHandler->GetPowerDeliveredToPosition(a_World, RearCoordinate, RearType, RearMeta, a_Position, a_BlockType));
|
||||
}
|
||||
|
||||
return RearPower;
|
||||
|
@ -1,4 +1,4 @@
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "RedstoneHandler.h"
|
||||
@ -28,15 +28,38 @@ public:
|
||||
UNUSED(a_BlockType);
|
||||
UNUSED(a_Meta);
|
||||
|
||||
int NumberOfPlayers = 0;
|
||||
VERIFY(!a_World.DoWithChestAt(a_Position.x, a_Position.y, a_Position.z, [&](cChestEntity & a_Chest)
|
||||
class cGetTrappedChestPlayers :
|
||||
public cItemCallback<cChestEntity>
|
||||
{
|
||||
public:
|
||||
cGetTrappedChestPlayers(void) :
|
||||
m_NumberOfPlayers(0)
|
||||
{
|
||||
ASSERT(a_Chest.GetBlockType() == E_BLOCK_TRAPPED_CHEST);
|
||||
NumberOfPlayers = a_Chest.GetNumberOfPlayers();
|
||||
}
|
||||
|
||||
virtual ~cGetTrappedChestPlayers() override
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool Item(cChestEntity * a_Chest) override
|
||||
{
|
||||
ASSERT(a_Chest->GetBlockType() == E_BLOCK_TRAPPED_CHEST);
|
||||
m_NumberOfPlayers = a_Chest->GetNumberOfPlayers();
|
||||
return true;
|
||||
}
|
||||
));
|
||||
return static_cast<unsigned char>(std::min(NumberOfPlayers, 15));
|
||||
|
||||
unsigned char GetPowerLevel(void) const
|
||||
{
|
||||
return static_cast<unsigned char>(std::min(m_NumberOfPlayers, 15));
|
||||
}
|
||||
|
||||
private:
|
||||
int m_NumberOfPlayers;
|
||||
|
||||
} GTCP;
|
||||
|
||||
VERIFY(!a_World.DoWithChestAt(a_Position.x, a_Position.y, a_Position.z, GTCP));
|
||||
return GTCP.GetPowerLevel();
|
||||
}
|
||||
|
||||
virtual cVector3iArray Update(cWorld & a_World, const Vector3i & a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override
|
||||
|
@ -39,7 +39,26 @@ public:
|
||||
|
||||
if (Type == E_BLOCK_TRIPWIRE)
|
||||
{
|
||||
if (!a_World.ForEachEntityInBox(cBoundingBox(Vector3d(0.5, 0, 0.5) + Position, 0.5, 0.5), [](cEntity &) { return true; }))
|
||||
class cTripwireCallback :
|
||||
public cEntityCallback
|
||||
{
|
||||
public:
|
||||
cTripwireCallback(void) :
|
||||
m_NumberOfEntities(0),
|
||||
m_FoundPlayer(false)
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool Item(cEntity * a_Entity) override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned int m_NumberOfEntities;
|
||||
bool m_FoundPlayer;
|
||||
} TripwireCallback;
|
||||
|
||||
if (!a_World.ForEachEntityInBox(cBoundingBox(Vector3d(0.5, 0, 0.5) + Position, 0.5, 0.5), TripwireCallback))
|
||||
{
|
||||
FoundActivated = true;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
|
||||
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
|
||||
|
||||
#include "Window.h"
|
||||
#include "WindowOwner.h"
|
||||
@ -362,12 +362,12 @@ void cWindow::OwnerDestroyed()
|
||||
|
||||
|
||||
|
||||
bool cWindow::ForEachPlayer(const cPlayerListCallback & a_Callback)
|
||||
bool cWindow::ForEachPlayer(cItemCallback<cPlayer> & a_Callback)
|
||||
{
|
||||
cCSLock Lock(m_CS);
|
||||
for (auto & Player : m_OpenedBy)
|
||||
for (cPlayerList::iterator itr = m_OpenedBy.begin(), end = m_OpenedBy.end(); itr != end; ++itr)
|
||||
{
|
||||
if (a_Callback(*Player))
|
||||
if (a_Callback.Item(*itr))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -379,12 +379,12 @@ bool cWindow::ForEachPlayer(const cPlayerListCallback & a_Callback)
|
||||
|
||||
|
||||
|
||||
bool cWindow::ForEachClient(cClientHandleCallback & a_Callback)
|
||||
bool cWindow::ForEachClient(cItemCallback<cClientHandle> & a_Callback)
|
||||
{
|
||||
cCSLock Lock(m_CS);
|
||||
for (auto & Player : m_OpenedBy)
|
||||
for (cPlayerList::iterator itr = m_OpenedBy.begin(), end = m_OpenedBy.end(); itr != end; ++itr)
|
||||
{
|
||||
if (a_Callback(*Player->GetClientHandle()))
|
||||
if (a_Callback.Item((*itr)->GetClientHandle()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
|
||||
|
||||
// Window.h
|
||||
|
||||
// Interfaces to the cWindow class representing a UI window for a specific block
|
||||
@ -9,7 +9,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include "../ItemGrid.h"
|
||||
|
||||
|
||||
@ -32,8 +31,7 @@ class cWorld;
|
||||
|
||||
typedef std::list<cPlayer *> cPlayerList;
|
||||
typedef std::vector<cSlotArea *> cSlotAreas;
|
||||
using cPlayerListCallback = std::function<bool(cPlayer &)>;
|
||||
using cClientHandleCallback = std::function<bool(cClientHandle &)>;
|
||||
|
||||
|
||||
|
||||
|
||||
@ -153,10 +151,10 @@ public:
|
||||
void OwnerDestroyed(void);
|
||||
|
||||
/** Calls the callback safely for each player that has this window open; returns true if all players have been enumerated */
|
||||
bool ForEachPlayer(const cPlayerListCallback & a_Callback);
|
||||
bool ForEachPlayer(cItemCallback<cPlayer> & a_Callback);
|
||||
|
||||
/** Calls the callback safely for each client that has this window open; returns true if all clients have been enumerated */
|
||||
bool ForEachClient(cClientHandleCallback & a_Callback);
|
||||
bool ForEachClient(cItemCallback<cClientHandle> & a_Callback);
|
||||
|
||||
/** Called on shift-clicking to distribute the stack into other areas; Modifies a_ItemStack as it is distributed!
|
||||
if a_ShouldApply is true, the changes are written into the slots;
|
||||
|
@ -21,6 +21,30 @@ static const char DEFAULT_WEBADMIN_PORTS[] = "8080";
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// cPlayerAccum:
|
||||
|
||||
/** Helper class - appends all player names together in an HTML list */
|
||||
class cPlayerAccum :
|
||||
public cPlayerListCallback
|
||||
{
|
||||
virtual bool Item(cPlayer * a_Player) override
|
||||
{
|
||||
m_Contents.append("<li>");
|
||||
m_Contents.append(a_Player->GetName());
|
||||
m_Contents.append("</li>");
|
||||
return false;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
AString m_Contents;
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// cWebadminRequestData
|
||||
|
||||
|
196
src/World.cpp
196
src/World.cpp
@ -1,4 +1,4 @@
|
||||
|
||||
|
||||
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
|
||||
|
||||
#include "World.h"
|
||||
@ -1117,52 +1117,59 @@ void cWorld::TickMobs(std::chrono::milliseconds a_Dt)
|
||||
{
|
||||
m_ChunkMap->SpawnMobs(Spawner);
|
||||
// do the spawn
|
||||
for (auto & Mob : Spawner.getSpawned())
|
||||
for (cMobSpawner::tSpawnedContainer::const_iterator itr2 = Spawner.getSpawned().begin(); itr2 != Spawner.getSpawned().end(); ++itr2)
|
||||
{
|
||||
SpawnMobFinalize(std::move(Mob));
|
||||
SpawnMobFinalize(std::move(const_cast<std::unique_ptr<cMonster> &>(*itr2)));
|
||||
}
|
||||
}
|
||||
} // for i - AllFamilies[]
|
||||
} // if (Spawning enabled)
|
||||
|
||||
ForEachEntity([=](cEntity & a_Entity)
|
||||
class cCallback : public cEntityCallback
|
||||
{
|
||||
virtual bool Item(cEntity * a_Entity) override
|
||||
{
|
||||
if (!a_Entity.IsMob())
|
||||
if (!a_Entity->IsMob())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!a_Entity.IsTicking())
|
||||
if (!a_Entity->IsTicking())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
auto & Monster = static_cast<cMonster &>(a_Entity);
|
||||
ASSERT(Monster.GetParentChunk() != nullptr); // A ticking entity must have a valid parent chunk
|
||||
auto Monster = static_cast<cMonster *>(a_Entity);
|
||||
ASSERT(Monster->GetParentChunk() != nullptr); // A ticking entity must have a valid parent chunk
|
||||
|
||||
// Tick close mobs
|
||||
if (Monster.GetParentChunk()->HasAnyClients())
|
||||
if (Monster->GetParentChunk()->HasAnyClients())
|
||||
{
|
||||
Monster.Tick(a_Dt, *(a_Entity.GetParentChunk()));
|
||||
Monster->Tick(m_Dt, *(a_Entity->GetParentChunk()));
|
||||
}
|
||||
// Destroy far hostile mobs except if last target was a player
|
||||
else if ((Monster.GetMobFamily() == cMonster::eFamily::mfHostile) && !Monster.WasLastTargetAPlayer())
|
||||
else if ((Monster->GetMobFamily() == cMonster::eFamily::mfHostile) && !Monster->WasLastTargetAPlayer())
|
||||
{
|
||||
if (Monster.GetMobType() != eMonsterType::mtWolf)
|
||||
if (Monster->GetMobType() != eMonsterType::mtWolf)
|
||||
{
|
||||
Monster.Destroy(true);
|
||||
Monster->Destroy(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto & Wolf = static_cast<cWolf &>(Monster);
|
||||
if (Wolf.IsAngry())
|
||||
auto Wolf = static_cast<cWolf *>(Monster);
|
||||
if (Wolf->IsAngry())
|
||||
{
|
||||
Monster.Destroy(true);
|
||||
Monster->Destroy(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
);
|
||||
public:
|
||||
std::chrono::milliseconds m_Dt;
|
||||
} Callback;
|
||||
|
||||
Callback.m_Dt = a_Dt;
|
||||
ForEachEntity(Callback);
|
||||
}
|
||||
|
||||
|
||||
@ -1314,7 +1321,7 @@ void cWorld::WakeUpSimulatorsInArea(const cCuboid & a_Area)
|
||||
|
||||
|
||||
|
||||
bool cWorld::ForEachBlockEntityInChunk(int a_ChunkX, int a_ChunkZ, const cBlockEntityCallback & a_Callback)
|
||||
bool cWorld::ForEachBlockEntityInChunk(int a_ChunkX, int a_ChunkZ, cBlockEntityCallback & a_Callback)
|
||||
{
|
||||
return m_ChunkMap->ForEachBlockEntityInChunk(a_ChunkX, a_ChunkZ, a_Callback);
|
||||
}
|
||||
@ -1323,7 +1330,7 @@ bool cWorld::ForEachBlockEntityInChunk(int a_ChunkX, int a_ChunkZ, const cBlockE
|
||||
|
||||
|
||||
|
||||
bool cWorld::ForEachBrewingstandInChunk(int a_ChunkX, int a_ChunkZ, const cBrewingstandCallback & a_Callback)
|
||||
bool cWorld::ForEachBrewingstandInChunk(int a_ChunkX, int a_ChunkZ, cBrewingstandCallback & a_Callback)
|
||||
{
|
||||
return m_ChunkMap->ForEachBrewingstandInChunk(a_ChunkX, a_ChunkZ, a_Callback);
|
||||
}
|
||||
@ -1332,7 +1339,7 @@ bool cWorld::ForEachBrewingstandInChunk(int a_ChunkX, int a_ChunkZ, const cBrewi
|
||||
|
||||
|
||||
|
||||
bool cWorld::ForEachChestInChunk(int a_ChunkX, int a_ChunkZ, const cChestCallback & a_Callback)
|
||||
bool cWorld::ForEachChestInChunk(int a_ChunkX, int a_ChunkZ, cChestCallback & a_Callback)
|
||||
{
|
||||
return m_ChunkMap->ForEachChestInChunk(a_ChunkX, a_ChunkZ, a_Callback);
|
||||
}
|
||||
@ -1341,7 +1348,7 @@ bool cWorld::ForEachChestInChunk(int a_ChunkX, int a_ChunkZ, const cChestCallbac
|
||||
|
||||
|
||||
|
||||
bool cWorld::ForEachDispenserInChunk(int a_ChunkX, int a_ChunkZ, const cDispenserCallback & a_Callback)
|
||||
bool cWorld::ForEachDispenserInChunk(int a_ChunkX, int a_ChunkZ, cDispenserCallback & a_Callback)
|
||||
{
|
||||
return m_ChunkMap->ForEachDispenserInChunk(a_ChunkX, a_ChunkZ, a_Callback);
|
||||
}
|
||||
@ -1350,7 +1357,7 @@ bool cWorld::ForEachDispenserInChunk(int a_ChunkX, int a_ChunkZ, const cDispense
|
||||
|
||||
|
||||
|
||||
bool cWorld::ForEachDropperInChunk(int a_ChunkX, int a_ChunkZ, const cDropperCallback & a_Callback)
|
||||
bool cWorld::ForEachDropperInChunk(int a_ChunkX, int a_ChunkZ, cDropperCallback & a_Callback)
|
||||
{
|
||||
return m_ChunkMap->ForEachDropperInChunk(a_ChunkX, a_ChunkZ, a_Callback);
|
||||
}
|
||||
@ -1359,7 +1366,7 @@ bool cWorld::ForEachDropperInChunk(int a_ChunkX, int a_ChunkZ, const cDropperCal
|
||||
|
||||
|
||||
|
||||
bool cWorld::ForEachDropSpenserInChunk(int a_ChunkX, int a_ChunkZ, const cDropSpenserCallback & a_Callback)
|
||||
bool cWorld::ForEachDropSpenserInChunk(int a_ChunkX, int a_ChunkZ, cDropSpenserCallback & a_Callback)
|
||||
{
|
||||
return m_ChunkMap->ForEachDropSpenserInChunk(a_ChunkX, a_ChunkZ, a_Callback);
|
||||
}
|
||||
@ -1368,7 +1375,7 @@ bool cWorld::ForEachDropSpenserInChunk(int a_ChunkX, int a_ChunkZ, const cDropSp
|
||||
|
||||
|
||||
|
||||
bool cWorld::ForEachFurnaceInChunk(int a_ChunkX, int a_ChunkZ, const cFurnaceCallback & a_Callback)
|
||||
bool cWorld::ForEachFurnaceInChunk(int a_ChunkX, int a_ChunkZ, cFurnaceCallback & a_Callback)
|
||||
{
|
||||
return m_ChunkMap->ForEachFurnaceInChunk(a_ChunkX, a_ChunkZ, a_Callback);
|
||||
}
|
||||
@ -1423,7 +1430,7 @@ void cWorld::DoExplosionAt(double a_ExplosionSize, double a_BlockX, double a_Blo
|
||||
|
||||
|
||||
|
||||
bool cWorld::DoWithBlockEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cBlockEntityCallback & a_Callback)
|
||||
bool cWorld::DoWithBlockEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBlockEntityCallback & a_Callback)
|
||||
{
|
||||
return m_ChunkMap->DoWithBlockEntityAt(a_BlockX, a_BlockY, a_BlockZ, a_Callback);
|
||||
}
|
||||
@ -1432,7 +1439,7 @@ bool cWorld::DoWithBlockEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ, const
|
||||
|
||||
|
||||
|
||||
bool cWorld::DoWithBeaconAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cBeaconCallback & a_Callback)
|
||||
bool cWorld::DoWithBeaconAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBeaconCallback & a_Callback)
|
||||
{
|
||||
return m_ChunkMap->DoWithBeaconAt(a_BlockX, a_BlockY, a_BlockZ, a_Callback);
|
||||
}
|
||||
@ -1441,7 +1448,7 @@ bool cWorld::DoWithBeaconAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cBea
|
||||
|
||||
|
||||
|
||||
bool cWorld::DoWithBedAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cBedCallback & a_Callback)
|
||||
bool cWorld::DoWithBedAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBedCallback & a_Callback)
|
||||
{
|
||||
return m_ChunkMap->DoWithBedAt(a_BlockX, a_BlockY, a_BlockZ, a_Callback);
|
||||
}
|
||||
@ -1450,7 +1457,7 @@ bool cWorld::DoWithBedAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cBedCal
|
||||
|
||||
|
||||
|
||||
bool cWorld::DoWithBrewingstandAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cBrewingstandCallback & a_Callback)
|
||||
bool cWorld::DoWithBrewingstandAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBrewingstandCallback & a_Callback)
|
||||
{
|
||||
return m_ChunkMap->DoWithBrewingstandAt(a_BlockX, a_BlockY, a_BlockZ, a_Callback);
|
||||
}
|
||||
@ -1459,7 +1466,7 @@ bool cWorld::DoWithBrewingstandAt(int a_BlockX, int a_BlockY, int a_BlockZ, cons
|
||||
|
||||
|
||||
|
||||
bool cWorld::DoWithChestAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cChestCallback & a_Callback)
|
||||
bool cWorld::DoWithChestAt(int a_BlockX, int a_BlockY, int a_BlockZ, cChestCallback & a_Callback)
|
||||
{
|
||||
return m_ChunkMap->DoWithChestAt(a_BlockX, a_BlockY, a_BlockZ, a_Callback);
|
||||
}
|
||||
@ -1468,7 +1475,7 @@ bool cWorld::DoWithChestAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cChes
|
||||
|
||||
|
||||
|
||||
bool cWorld::DoWithDispenserAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cDispenserCallback & a_Callback)
|
||||
bool cWorld::DoWithDispenserAt(int a_BlockX, int a_BlockY, int a_BlockZ, cDispenserCallback & a_Callback)
|
||||
{
|
||||
return m_ChunkMap->DoWithDispenserAt(a_BlockX, a_BlockY, a_BlockZ, a_Callback);
|
||||
}
|
||||
@ -1477,7 +1484,7 @@ bool cWorld::DoWithDispenserAt(int a_BlockX, int a_BlockY, int a_BlockZ, const c
|
||||
|
||||
|
||||
|
||||
bool cWorld::DoWithDropperAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cDropperCallback & a_Callback)
|
||||
bool cWorld::DoWithDropperAt(int a_BlockX, int a_BlockY, int a_BlockZ, cDropperCallback & a_Callback)
|
||||
{
|
||||
return m_ChunkMap->DoWithDropperAt(a_BlockX, a_BlockY, a_BlockZ, a_Callback);
|
||||
}
|
||||
@ -1486,7 +1493,7 @@ bool cWorld::DoWithDropperAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cDr
|
||||
|
||||
|
||||
|
||||
bool cWorld::DoWithDropSpenserAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cDropSpenserCallback & a_Callback)
|
||||
bool cWorld::DoWithDropSpenserAt(int a_BlockX, int a_BlockY, int a_BlockZ, cDropSpenserCallback & a_Callback)
|
||||
{
|
||||
return m_ChunkMap->DoWithDropSpenserAt(a_BlockX, a_BlockY, a_BlockZ, a_Callback);
|
||||
}
|
||||
@ -1495,7 +1502,7 @@ bool cWorld::DoWithDropSpenserAt(int a_BlockX, int a_BlockY, int a_BlockZ, const
|
||||
|
||||
|
||||
|
||||
bool cWorld::DoWithFurnaceAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cFurnaceCallback & a_Callback)
|
||||
bool cWorld::DoWithFurnaceAt(int a_BlockX, int a_BlockY, int a_BlockZ, cFurnaceCallback & a_Callback)
|
||||
{
|
||||
return m_ChunkMap->DoWithFurnaceAt(a_BlockX, a_BlockY, a_BlockZ, a_Callback);
|
||||
}
|
||||
@ -1504,7 +1511,7 @@ bool cWorld::DoWithFurnaceAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cFu
|
||||
|
||||
|
||||
|
||||
bool cWorld::DoWithNoteBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cNoteBlockCallback & a_Callback)
|
||||
bool cWorld::DoWithNoteBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cNoteBlockCallback & a_Callback)
|
||||
{
|
||||
return m_ChunkMap->DoWithNoteBlockAt(a_BlockX, a_BlockY, a_BlockZ, a_Callback);
|
||||
}
|
||||
@ -1513,7 +1520,7 @@ bool cWorld::DoWithNoteBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, const c
|
||||
|
||||
|
||||
|
||||
bool cWorld::DoWithCommandBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cCommandBlockCallback & a_Callback)
|
||||
bool cWorld::DoWithCommandBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cCommandBlockCallback & a_Callback)
|
||||
{
|
||||
return m_ChunkMap->DoWithCommandBlockAt(a_BlockX, a_BlockY, a_BlockZ, a_Callback);
|
||||
}
|
||||
@ -1522,7 +1529,7 @@ bool cWorld::DoWithCommandBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cons
|
||||
|
||||
|
||||
|
||||
bool cWorld::DoWithMobHeadAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cMobHeadCallback & a_Callback)
|
||||
bool cWorld::DoWithMobHeadAt(int a_BlockX, int a_BlockY, int a_BlockZ, cMobHeadCallback & a_Callback)
|
||||
{
|
||||
return m_ChunkMap->DoWithMobHeadAt(a_BlockX, a_BlockY, a_BlockZ, a_Callback);
|
||||
}
|
||||
@ -1531,7 +1538,7 @@ bool cWorld::DoWithMobHeadAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cMo
|
||||
|
||||
|
||||
|
||||
bool cWorld::DoWithFlowerPotAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cFlowerPotCallback & a_Callback)
|
||||
bool cWorld::DoWithFlowerPotAt(int a_BlockX, int a_BlockY, int a_BlockZ, cFlowerPotCallback & a_Callback)
|
||||
{
|
||||
return m_ChunkMap->DoWithFlowerPotAt(a_BlockX, a_BlockY, a_BlockZ, a_Callback);
|
||||
}
|
||||
@ -1549,7 +1556,7 @@ bool cWorld::GetSignLines(int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_
|
||||
|
||||
|
||||
|
||||
bool cWorld::DoWithChunk(int a_ChunkX, int a_ChunkZ, const cChunkCallback & a_Callback)
|
||||
bool cWorld::DoWithChunk(int a_ChunkX, int a_ChunkZ, cChunkCallback & a_Callback)
|
||||
{
|
||||
return m_ChunkMap->DoWithChunk(a_ChunkX, a_ChunkZ, a_Callback);
|
||||
}
|
||||
@ -1558,7 +1565,31 @@ bool cWorld::DoWithChunk(int a_ChunkX, int a_ChunkZ, const cChunkCallback & a_Ca
|
||||
|
||||
|
||||
|
||||
bool cWorld::DoWithChunkAt(Vector3i a_BlockPos, const cChunkCallback & a_Callback)
|
||||
bool cWorld::DoWithChunk(int a_ChunkX, int a_ChunkZ, std::function<bool(cChunk &)> a_Callback)
|
||||
{
|
||||
struct cCallBackWrapper : cChunkCallback
|
||||
{
|
||||
cCallBackWrapper(std::function<bool(cChunk &)> a_InnerCallback) :
|
||||
m_Callback(a_InnerCallback)
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool Item(cChunk * a_Chunk)
|
||||
{
|
||||
return m_Callback(*a_Chunk);
|
||||
}
|
||||
|
||||
private:
|
||||
std::function<bool(cChunk &)> m_Callback;
|
||||
} callback(a_Callback);
|
||||
return m_ChunkMap->DoWithChunk(a_ChunkX, a_ChunkZ, callback);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cWorld::DoWithChunkAt(Vector3i a_BlockPos, std::function<bool(cChunk &)> a_Callback)
|
||||
{
|
||||
return m_ChunkMap->DoWithChunkAt(a_BlockPos, a_Callback);
|
||||
}
|
||||
@ -3132,13 +3163,18 @@ bool cWorld::IsPlayerReferencedInWorldOrChunk(cPlayer & a_Player)
|
||||
|
||||
|
||||
|
||||
bool cWorld::ForEachPlayer(const cPlayerListCallback & a_Callback)
|
||||
bool cWorld::ForEachPlayer(cPlayerListCallback & a_Callback)
|
||||
{
|
||||
// Calls the callback for each player in the list
|
||||
cCSLock Lock(m_CSPlayers);
|
||||
for (auto & Player : m_Players)
|
||||
for (cPlayerList::iterator itr = m_Players.begin(), itr2 = itr; itr != m_Players.end(); itr = itr2)
|
||||
{
|
||||
if (Player->IsTicking() && a_Callback(*Player))
|
||||
++itr2;
|
||||
if (!(*itr)->IsTicking())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (a_Callback.Item(*itr))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -3150,15 +3186,19 @@ bool cWorld::ForEachPlayer(const cPlayerListCallback & a_Callback)
|
||||
|
||||
|
||||
|
||||
bool cWorld::DoWithPlayer(const AString & a_PlayerName, const cPlayerListCallback & a_Callback)
|
||||
bool cWorld::DoWithPlayer(const AString & a_PlayerName, cPlayerListCallback & a_Callback)
|
||||
{
|
||||
// Calls the callback for the specified player in the list
|
||||
cCSLock Lock(m_CSPlayers);
|
||||
for (auto & Player : m_Players)
|
||||
for (cPlayerList::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
|
||||
{
|
||||
if (Player->IsTicking() && (NoCaseCompare(Player->GetName(), a_PlayerName) == 0))
|
||||
if (!(*itr)->IsTicking())
|
||||
{
|
||||
a_Callback(*Player);
|
||||
continue;
|
||||
}
|
||||
if (NoCaseCompare((*itr)->GetName(), a_PlayerName) == 0)
|
||||
{
|
||||
a_Callback.Item(*itr);
|
||||
return true;
|
||||
}
|
||||
} // for itr - m_Players[]
|
||||
@ -3169,7 +3209,7 @@ bool cWorld::DoWithPlayer(const AString & a_PlayerName, const cPlayerListCallbac
|
||||
|
||||
|
||||
|
||||
bool cWorld::FindAndDoWithPlayer(const AString & a_PlayerNameHint, const cPlayerListCallback & a_Callback)
|
||||
bool cWorld::FindAndDoWithPlayer(const AString & a_PlayerNameHint, cPlayerListCallback & a_Callback)
|
||||
{
|
||||
cPlayer * BestMatch = nullptr;
|
||||
size_t BestRating = 0;
|
||||
@ -3196,7 +3236,7 @@ bool cWorld::FindAndDoWithPlayer(const AString & a_PlayerNameHint, const cPlayer
|
||||
|
||||
if (BestMatch != nullptr)
|
||||
{
|
||||
return a_Callback(*BestMatch);
|
||||
return a_Callback.Item (BestMatch);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -3205,14 +3245,27 @@ bool cWorld::FindAndDoWithPlayer(const AString & a_PlayerNameHint, const cPlayer
|
||||
|
||||
|
||||
|
||||
bool cWorld::DoWithPlayerByUUID(const cUUID & a_PlayerUUID, const cPlayerListCallback & a_Callback)
|
||||
bool cWorld::DoWithPlayerByUUID(const cUUID & a_PlayerUUID, cPlayerListCallback & a_Callback)
|
||||
{
|
||||
return DoWithPlayerByUUID(a_PlayerUUID, std::bind(&cPlayerListCallback::Item, &a_Callback, std::placeholders::_1));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cWorld::DoWithPlayerByUUID(const cUUID & a_PlayerUUID, cLambdaPlayerCallback a_Callback)
|
||||
{
|
||||
cCSLock Lock(m_CSPlayers);
|
||||
for (auto & Player : m_Players)
|
||||
for (cPlayerList::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
|
||||
{
|
||||
if (Player->IsTicking() && (Player->GetUUID() == a_PlayerUUID))
|
||||
if (!(*itr)->IsTicking())
|
||||
{
|
||||
return a_Callback(*Player);
|
||||
continue;
|
||||
}
|
||||
if ((*itr)->GetUUID() == a_PlayerUUID)
|
||||
{
|
||||
return a_Callback(*itr);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
@ -3280,7 +3333,7 @@ void cWorld::SendPlayerList(cPlayer * a_DestPlayer)
|
||||
|
||||
|
||||
|
||||
bool cWorld::ForEachEntity(const cEntityCallback & a_Callback)
|
||||
bool cWorld::ForEachEntity(cEntityCallback & a_Callback)
|
||||
{
|
||||
return m_ChunkMap->ForEachEntity(a_Callback);
|
||||
}
|
||||
@ -3289,7 +3342,7 @@ bool cWorld::ForEachEntity(const cEntityCallback & a_Callback)
|
||||
|
||||
|
||||
|
||||
bool cWorld::ForEachEntityInChunk(int a_ChunkX, int a_ChunkZ, const cEntityCallback & a_Callback)
|
||||
bool cWorld::ForEachEntityInChunk(int a_ChunkX, int a_ChunkZ, cEntityCallback & a_Callback)
|
||||
{
|
||||
return m_ChunkMap->ForEachEntityInChunk(a_ChunkX, a_ChunkZ, a_Callback);
|
||||
}
|
||||
@ -3298,7 +3351,7 @@ bool cWorld::ForEachEntityInChunk(int a_ChunkX, int a_ChunkZ, const cEntityCallb
|
||||
|
||||
|
||||
|
||||
bool cWorld::ForEachEntityInBox(const cBoundingBox & a_Box, const cEntityCallback & a_Callback)
|
||||
bool cWorld::ForEachEntityInBox(const cBoundingBox & a_Box, cEntityCallback & a_Callback)
|
||||
{
|
||||
return m_ChunkMap->ForEachEntityInBox(a_Box, a_Callback);
|
||||
}
|
||||
@ -3307,7 +3360,16 @@ bool cWorld::ForEachEntityInBox(const cBoundingBox & a_Box, const cEntityCallbac
|
||||
|
||||
|
||||
|
||||
bool cWorld::DoWithEntityByID(UInt32 a_UniqueID, const cEntityCallback & a_Callback)
|
||||
bool cWorld::DoWithEntityByID(UInt32 a_UniqueID, cEntityCallback & a_Callback)
|
||||
{
|
||||
return DoWithEntityByID(a_UniqueID, std::bind(&cEntityCallback::Item, &a_Callback, std::placeholders::_1));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cWorld::DoWithEntityByID(UInt32 a_UniqueID, cLambdaEntityCallback a_Callback)
|
||||
{
|
||||
// First check the entities-to-add:
|
||||
{
|
||||
@ -3316,7 +3378,7 @@ bool cWorld::DoWithEntityByID(UInt32 a_UniqueID, const cEntityCallback & a_Callb
|
||||
{
|
||||
if (ent->GetUniqueID() == a_UniqueID)
|
||||
{
|
||||
a_Callback(*ent);
|
||||
a_Callback(ent.get());
|
||||
return true;
|
||||
}
|
||||
} // for ent - m_EntitiesToAdd[]
|
||||
@ -3448,12 +3510,20 @@ bool cWorld::SetSignLines(int a_BlockX, int a_BlockY, int a_BlockZ, const AStrin
|
||||
|
||||
bool cWorld::SetCommandBlockCommand(int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Command)
|
||||
{
|
||||
return DoWithCommandBlockAt(a_BlockX, a_BlockY, a_BlockZ, [&](cCommandBlockEntity & a_CommandBlock)
|
||||
class cUpdateCommandBlock : public cCommandBlockCallback
|
||||
{
|
||||
AString m_Command;
|
||||
public:
|
||||
cUpdateCommandBlock(const AString & a_CallbackCommand) : m_Command(a_CallbackCommand) {}
|
||||
|
||||
virtual bool Item(cCommandBlockEntity * a_CommandBlock) override
|
||||
{
|
||||
a_CommandBlock.SetCommand(a_Command);
|
||||
a_CommandBlock->SetCommand(m_Command);
|
||||
return false;
|
||||
}
|
||||
);
|
||||
} CmdBlockCB (a_Command);
|
||||
|
||||
return DoWithCommandBlockAt(a_BlockX, a_BlockY, a_BlockZ, CmdBlockCB);
|
||||
}
|
||||
|
||||
|
||||
@ -3548,7 +3618,7 @@ bool cWorld::ForEachChunkInRect(int a_MinChunkX, int a_MaxChunkX, int a_MinChunk
|
||||
|
||||
|
||||
|
||||
bool cWorld::ForEachLoadedChunk(const std::function<bool(int, int)> & a_Callback)
|
||||
bool cWorld::ForEachLoadedChunk(std::function<bool(int, int)> a_Callback)
|
||||
{
|
||||
return m_ChunkMap->ForEachLoadedChunk(a_Callback);
|
||||
}
|
||||
@ -3579,7 +3649,7 @@ void cWorld::QueueSaveAllChunks(void)
|
||||
void cWorld::QueueTask(std::function<void(cWorld &)> a_Task)
|
||||
{
|
||||
cCSLock Lock(m_CSTasks);
|
||||
m_Tasks.emplace_back(0, std::move(a_Task));
|
||||
m_Tasks.emplace_back(0, a_Task);
|
||||
}
|
||||
|
||||
|
||||
@ -3593,7 +3663,7 @@ void cWorld::ScheduleTask(int a_DelayTicks, std::function<void (cWorld &)> a_Tas
|
||||
// Insert the task into the list of scheduled tasks
|
||||
{
|
||||
cCSLock Lock(m_CSTasks);
|
||||
m_Tasks.emplace_back(TargetTick, std::move(a_Task));
|
||||
m_Tasks.emplace_back(TargetTick, a_Task);
|
||||
}
|
||||
}
|
||||
|
||||
|
85
src/World.h
85
src/World.h
@ -1,4 +1,4 @@
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#define MAX_PLAYERS 65535
|
||||
@ -58,6 +58,21 @@ typedef std::list< std::pair< std::unique_ptr<cPlayer>, cWorld * > > cAwaitingPl
|
||||
typedef std::unique_ptr<cSetChunkData> cSetChunkDataPtr;
|
||||
typedef std::vector<cSetChunkDataPtr> cSetChunkDataPtrs;
|
||||
|
||||
typedef cItemCallback<cPlayer> cPlayerListCallback;
|
||||
typedef cItemCallback<cEntity> cEntityCallback;
|
||||
typedef cItemCallback<cBeaconEntity> cBeaconCallback;
|
||||
typedef cItemCallback<cBrewingstandEntity> cBrewingstandCallback;
|
||||
typedef cItemCallback<cChestEntity> cChestCallback;
|
||||
typedef cItemCallback<cDispenserEntity> cDispenserCallback;
|
||||
typedef cItemCallback<cFurnaceEntity> cFurnaceCallback;
|
||||
typedef cItemCallback<cNoteEntity> cNoteBlockCallback;
|
||||
typedef cItemCallback<cCommandBlockEntity> cCommandBlockCallback;
|
||||
typedef cItemCallback<cMobHeadEntity> cMobHeadCallback;
|
||||
typedef cItemCallback<cFlowerPotEntity> cFlowerPotCallback;
|
||||
|
||||
typedef std::function<bool (cPlayer *)> cLambdaPlayerCallback;
|
||||
typedef std::function<bool (cEntity *)> cLambdaEntityCallback;
|
||||
|
||||
|
||||
|
||||
|
||||
@ -260,20 +275,21 @@ public:
|
||||
#endif
|
||||
|
||||
/** Calls the callback for each player in the list; returns true if all players processed, false if the callback aborted by returning true */
|
||||
virtual bool ForEachPlayer(const cPlayerListCallback & a_Callback) override; // >> EXPORTED IN MANUALBINDINGS <<
|
||||
virtual bool ForEachPlayer(cPlayerListCallback & a_Callback) override; // >> EXPORTED IN MANUALBINDINGS <<
|
||||
|
||||
/** Calls the callback for the player of the given name; returns true if the player was found and the callback called, false if player not found.
|
||||
Callback return value is ignored. If there are multiple players of the same name, only (random) one is processed by the callback. */
|
||||
bool DoWithPlayer(const AString & a_PlayerName, const cPlayerListCallback & a_Callback); // >> EXPORTED IN MANUALBINDINGS <<
|
||||
bool DoWithPlayer(const AString & a_PlayerName, cPlayerListCallback & a_Callback); // >> EXPORTED IN MANUALBINDINGS <<
|
||||
|
||||
/** Finds a player from a partial or complete player name and calls the callback - case-insensitive */
|
||||
bool FindAndDoWithPlayer(const AString & a_PlayerNameHint, const cPlayerListCallback & a_Callback); // >> EXPORTED IN MANUALBINDINGS <<
|
||||
bool FindAndDoWithPlayer(const AString & a_PlayerNameHint, cPlayerListCallback & a_Callback); // >> EXPORTED IN MANUALBINDINGS <<
|
||||
|
||||
// TODO: This interface is dangerous - rewrite to DoWithClosestPlayer(pos, sight, action)
|
||||
cPlayer * FindClosestPlayer(Vector3d a_Pos, float a_SightLimit, bool a_CheckLineOfSight = true);
|
||||
|
||||
/** Finds the player over his uuid and calls the callback */
|
||||
bool DoWithPlayerByUUID(const cUUID & a_PlayerUUID, const cPlayerListCallback & a_Callback); // >> EXPORTED IN MANUALBINDINGS <<
|
||||
bool DoWithPlayerByUUID(const cUUID & a_PlayerUUID, cPlayerListCallback & a_Callback); // >> EXPORTED IN MANUALBINDINGS <<
|
||||
bool DoWithPlayerByUUID(const cUUID & a_PlayerUUID, cLambdaPlayerCallback a_Callback); // Lambda version
|
||||
|
||||
void SendPlayerList(cPlayer * a_DestPlayer); // Sends playerlist to the player
|
||||
|
||||
@ -286,19 +302,20 @@ public:
|
||||
bool HasEntity(UInt32 a_UniqueID);
|
||||
|
||||
/** 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(const cEntityCallback & a_Callback); // Exported in ManualBindings.cpp
|
||||
bool ForEachEntity(cEntityCallback & a_Callback); // Exported in ManualBindings.cpp
|
||||
|
||||
/** 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, const cEntityCallback & a_Callback); // Exported in ManualBindings.cpp
|
||||
bool ForEachEntityInChunk(int a_ChunkX, int a_ChunkZ, cEntityCallback & a_Callback); // Exported in ManualBindings.cpp
|
||||
|
||||
/** Calls the callback for each entity that has a nonempty intersection with the specified boundingbox.
|
||||
Returns true if all entities processed, false if the callback aborted by returning true.
|
||||
If any chunk in the box is missing, ignores the entities in that chunk silently. */
|
||||
virtual bool ForEachEntityInBox(const cBoundingBox & a_Box, const cEntityCallback & a_Callback) override; // Exported in ManualBindings.cpp
|
||||
virtual bool ForEachEntityInBox(const cBoundingBox & a_Box, cEntityCallback & a_Callback) override; // Exported in ManualBindings.cpp
|
||||
|
||||
/** 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(UInt32 a_UniqueID, const cEntityCallback & a_Callback); // Exported in ManualBindings.cpp
|
||||
bool DoWithEntityByID(UInt32 a_UniqueID, cEntityCallback & a_Callback); // Exported in ManualBindings.cpp
|
||||
bool DoWithEntityByID(UInt32 a_UniqueID, cLambdaEntityCallback a_Callback); // Lambda version
|
||||
|
||||
/** 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);
|
||||
@ -362,7 +379,7 @@ public:
|
||||
virtual bool ForEachChunkInRect(int a_MinChunkX, int a_MaxChunkX, int a_MinChunkZ, int a_MaxChunkZ, cChunkDataCallback & a_Callback) override;
|
||||
|
||||
/** Calls the callback for each loaded chunk. Returns true if all chunks have been processed successfully */
|
||||
bool ForEachLoadedChunk(const std::function<bool(int, int)> & a_Callback);
|
||||
bool ForEachLoadedChunk(std::function<bool(int, int)> a_Callback);
|
||||
|
||||
// tolua_begin
|
||||
|
||||
@ -499,25 +516,25 @@ public:
|
||||
inline cRedstoneSimulator * GetRedstoneSimulator(void) { return m_RedstoneSimulator; }
|
||||
|
||||
/** 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, const cBlockEntityCallback & a_Callback); // Exported in ManualBindings.cpp
|
||||
bool ForEachBlockEntityInChunk(int a_ChunkX, int a_ChunkZ, cBlockEntityCallback & a_Callback); // Exported in ManualBindings.cpp
|
||||
|
||||
/** Calls the callback for each brewingstand in the specified chunk; returns true if all brewingstands processed, false if the callback aborted by returning true */
|
||||
bool ForEachBrewingstandInChunk(int a_ChunkX, int a_ChunkZ, const cBrewingstandCallback & a_Callback); // Exported in ManualBindings.cpp
|
||||
bool ForEachBrewingstandInChunk(int a_ChunkX, int a_ChunkZ, cBrewingstandCallback & a_Callback); // Exported in ManualBindings.cpp
|
||||
|
||||
/** 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, const cChestCallback & a_Callback); // Exported in ManualBindings.cpp
|
||||
bool ForEachChestInChunk(int a_ChunkX, int a_ChunkZ, cChestCallback & a_Callback); // Exported in ManualBindings.cpp
|
||||
|
||||
/** 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, const cDispenserCallback & a_Callback);
|
||||
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 */
|
||||
bool ForEachDropperInChunk(int a_ChunkX, int a_ChunkZ, const cDropperCallback & a_Callback);
|
||||
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 */
|
||||
bool ForEachDropSpenserInChunk(int a_ChunkX, int a_ChunkZ, const cDropSpenserCallback & a_Callback);
|
||||
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 */
|
||||
bool ForEachFurnaceInChunk(int a_ChunkX, int a_ChunkZ, const cFurnaceCallback & a_Callback); // Exported in ManualBindings.cpp
|
||||
bool ForEachFurnaceInChunk(int a_ChunkX, int a_ChunkZ, cFurnaceCallback & a_Callback); // Exported in ManualBindings.cpp
|
||||
|
||||
/** Does an explosion with the specified strength at the specified coordinates.
|
||||
Executes the HOOK_EXPLODING and HOOK_EXPLODED hooks as part of the processing.
|
||||
@ -526,43 +543,43 @@ public:
|
||||
virtual void DoExplosionAt(double a_ExplosionSize, double a_BlockX, double a_BlockY, double a_BlockZ, bool a_CanCauseFire, eExplosionSource a_Source, void * a_SourceData) override;
|
||||
|
||||
/** 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 */
|
||||
virtual bool DoWithBlockEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cBlockEntityCallback & a_Callback) override; // Exported in ManualBindings.cpp
|
||||
virtual bool DoWithBlockEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBlockEntityCallback & a_Callback) override; // Exported in ManualBindings.cpp
|
||||
|
||||
/** Calls the callback for the beacon at the specified coords; returns false if there's no beacon at those coords, true if found */
|
||||
bool DoWithBeaconAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cBeaconCallback & a_Callback); // Exported in ManualBindings.cpp
|
||||
bool DoWithBeaconAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBeaconCallback & a_Callback); // Exported in ManualBindings.cpp
|
||||
|
||||
/** Calls the callback for the bed at the specified coords; returns false if there's no bed at those coords, true if found */
|
||||
virtual bool DoWithBedAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cBedCallback & a_Callback) override; // Exported in ManualBindings.cpp
|
||||
virtual bool DoWithBedAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBedCallback & a_Callback) override; // Exported in ManualBindings.cpp
|
||||
|
||||
/** Calls the callback for the brewingstand at the specified coords; returns false if there's no brewingstand at those coords, true if found */
|
||||
bool DoWithBrewingstandAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cBrewingstandCallback & a_Callback); // Lua-acessible
|
||||
bool DoWithBrewingstandAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBrewingstandCallback & 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 */
|
||||
bool DoWithChestAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cChestCallback & a_Callback); // Exported in ManualBindings.cpp
|
||||
bool DoWithChestAt(int a_BlockX, int a_BlockY, int a_BlockZ, cChestCallback & a_Callback); // Exported in ManualBindings.cpp
|
||||
|
||||
/** 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, const cDispenserCallback & a_Callback); // Exported in ManualBindings.cpp
|
||||
bool DoWithDispenserAt(int a_BlockX, int a_BlockY, int a_BlockZ, cDispenserCallback & a_Callback); // Exported in ManualBindings.cpp
|
||||
|
||||
/** 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, const cDropperCallback & a_Callback); // Exported in ManualBindings.cpp
|
||||
bool DoWithDropperAt(int a_BlockX, int a_BlockY, int a_BlockZ, cDropperCallback & a_Callback); // Exported in ManualBindings.cpp
|
||||
|
||||
/** 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, const cDropSpenserCallback & a_Callback); // Exported in ManualBindings.cpp
|
||||
bool DoWithDropSpenserAt(int a_BlockX, int a_BlockY, int a_BlockZ, cDropSpenserCallback & a_Callback); // Exported in ManualBindings.cpp
|
||||
|
||||
/** 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, const cFurnaceCallback & a_Callback); // Exported in ManualBindings.cpp
|
||||
bool DoWithFurnaceAt(int a_BlockX, int a_BlockY, int a_BlockZ, cFurnaceCallback & a_Callback); // Exported in ManualBindings.cpp
|
||||
|
||||
/** 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, const cNoteBlockCallback & a_Callback); // Exported in ManualBindings.cpp
|
||||
bool DoWithNoteBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cNoteBlockCallback & a_Callback); // Exported in ManualBindings.cpp
|
||||
|
||||
/** 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, const cCommandBlockCallback & a_Callback); // Exported in ManualBindings.cpp
|
||||
bool DoWithCommandBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cCommandBlockCallback & a_Callback); // Exported in ManualBindings.cpp
|
||||
|
||||
/** Calls the callback for the mob head block at the specified coords; returns false if there's no mob head block at those coords or callback returns true, returns true if found */
|
||||
bool DoWithMobHeadAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cMobHeadCallback & a_Callback); // Exported in ManualBindings.cpp
|
||||
bool DoWithMobHeadAt(int a_BlockX, int a_BlockY, int a_BlockZ, cMobHeadCallback & a_Callback); // Exported in ManualBindings.cpp
|
||||
|
||||
/** Calls the callback for the flower pot at the specified coords; returns false if there's no flower pot at those coords or callback returns true, returns true if found */
|
||||
bool DoWithFlowerPotAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cFlowerPotCallback & a_Callback); // Exported in ManualBindings.cpp
|
||||
bool DoWithFlowerPotAt(int a_BlockX, int a_BlockY, int a_BlockZ, cFlowerPotCallback & a_Callback); // Exported in ManualBindings.cpp
|
||||
|
||||
/** 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); // Exported in ManualBindings.cpp
|
||||
@ -570,13 +587,13 @@ public:
|
||||
/** a_Player is using block entity at [x, y, z], handle that: */
|
||||
void UseBlockEntity(cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ) {m_ChunkMap->UseBlockEntity(a_Player, a_BlockX, a_BlockY, a_BlockZ); } // tolua_export
|
||||
|
||||
/** 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, const cChunkCallback & a_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);
|
||||
bool DoWithChunk(int a_ChunkX, int a_ChunkZ, std::function<bool(cChunk &)> a_Callback);
|
||||
|
||||
/** Calls the callback for the chunk at the block position specified, with ChunkMapCS locked.
|
||||
Returns false if the chunk isn't loaded, otherwise returns the same value as the callback */
|
||||
bool DoWithChunkAt(Vector3i a_BlockPos, const cChunkCallback & a_Callback);
|
||||
bool DoWithChunkAt(Vector3i a_BlockPos, std::function<bool(cChunk &)> a_Callback);
|
||||
|
||||
void GrowTreeImage(const sSetBlockVector & a_Blocks);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user