Use Vector3 for cLineBlockTracer and cBlockTracer (#4715)
* cLineBlockTracer uses Vector
This commit is contained in:
parent
c4ca11b372
commit
1565d9b3ce
@ -1010,6 +1010,7 @@ the most popular tracing reasons - line of sight and solid hits.
|
||||
},
|
||||
}, -- LineOfSightTrace
|
||||
Trace =
|
||||
{
|
||||
{
|
||||
IsStatic = true,
|
||||
Params =
|
||||
@ -1029,9 +1030,27 @@ the most popular tracing reasons - line of sight and solid hits.
|
||||
Type = "boolean",
|
||||
},
|
||||
},
|
||||
Notes = "(OBSOLETE, use the Vector3-based overload instead) Performs the trace on the specified line. Returns true if the entire trace was processed (no callback returned true)",
|
||||
},
|
||||
{
|
||||
IsStatic = true,
|
||||
Params =
|
||||
{
|
||||
{ Name = "World", Type = "cWorld" },
|
||||
{ Name = "Callbacks", Type = "table" },
|
||||
{ Name = "Start", Type = "Vector3d" },
|
||||
{ Name = "End", Type = "Vector3d" },
|
||||
},
|
||||
Returns =
|
||||
{
|
||||
{
|
||||
Type = "boolean",
|
||||
},
|
||||
},
|
||||
Notes = "Performs the trace on the specified line. Returns true if the entire trace was processed (no callback returned true)",
|
||||
},
|
||||
},
|
||||
},
|
||||
Constants =
|
||||
{
|
||||
losAir =
|
||||
@ -1064,7 +1083,39 @@ The Callbacks in the Trace() function is a table that contains named functions.
|
||||
individual functions from that table for the events that occur on the line - hitting a block, going out of
|
||||
valid world data etc. The following table lists all the available callbacks. If the callback function is
|
||||
not defined, Cuberite skips it. Each function can return a bool value, if it returns true, the tracing is
|
||||
aborted and Trace() returns false.</p>
|
||||
aborted and Trace() returns false.<br>
|
||||
Note: The folowing can only be used when using the Vector3-based Trace() function. When using
|
||||
the number-based overload, the callbacks receive number-based coordinates (see Deprecated
|
||||
Callbacks below).</p>
|
||||
<p>
|
||||
<table><tr><th>Name</th><th>Parameters</th><th>Notes</th></tr>
|
||||
<tr><td>OnNextBlock</td><td>BlockPos, BlockType, BlockMeta, EntryFace</td>
|
||||
<td>Called when the ray hits a new valid block. The block type and meta is given. EntryFace is one of the
|
||||
BLOCK_FACE_ constants indicating which "side" of the block got hit by the ray.</td></tr>
|
||||
<tr><td>OnNextBlockNoData</td><td>BlockPos, EntryFace</td>
|
||||
<td>Called when the ray hits a new block, but the block is in an unloaded chunk - no valid data is
|
||||
available. Only the coords and the entry face are given.</td></tr>
|
||||
<tr><td>OnOutOfWorld</td><td>BlockPos</td>
|
||||
<td>Called when the ray goes outside of the world (Y-wise); the coords specify the exact exit point. Note
|
||||
that for other paths than lines (considered for future implementations) the path may leave the world and
|
||||
go back in again later, in such a case this callback is followed by OnIntoWorld() and further
|
||||
OnNextBlock() calls.</td></tr>
|
||||
<tr><td>OnIntoWorld</td><td>BlockPos</td>
|
||||
<td>Called when the ray enters the world (Y-wise); the coords specify the exact entry point.</td></tr>
|
||||
<tr><td>OnNoMoreHits</td><td> </td>
|
||||
<td>Called when the path is sure not to hit any more blocks. This is the final callback, no more
|
||||
callbacks are called after this function. Unlike the other callbacks, this function doesn't have a return
|
||||
value.</td></tr>
|
||||
<tr><td>OnNoChunk</td><td> </td>
|
||||
<td>Called when the ray enters a chunk that is not loaded. This usually means that the tracing is aborted.
|
||||
Unlike the other callbacks, this function doesn't have a return value.</td></tr>
|
||||
</table>
|
||||
]],
|
||||
},
|
||||
{
|
||||
Header = "Deprecated Callbacks",
|
||||
Contents = [[
|
||||
When using the deprecated number-based Trace function, Cuberite will instead assume the following signatures for the callbacks:</p>
|
||||
<p>
|
||||
<table><tr><th>Name</th><th>Parameters</th><th>Notes</th></tr>
|
||||
<tr><td>OnNextBlock</td><td>BlockX, BlockY, BlockZ, BlockType, BlockMeta, EntryFace</td>
|
||||
@ -1080,14 +1131,8 @@ aborted and Trace() returns false.</p>
|
||||
OnNextBlock() calls.</td></tr>
|
||||
<tr><td>OnIntoWorld</td><td>X, Y, Z</td>
|
||||
<td>Called when the ray enters the world (Y-wise); the coords specify the exact entry point.</td></tr>
|
||||
<tr><td>OnNoMoreHits</td><td> </td>
|
||||
<td>Called when the path is sure not to hit any more blocks. This is the final callback, no more
|
||||
callbacks are called after this function. Unlike the other callbacks, this function doesn't have a return
|
||||
value.</td></tr>
|
||||
<tr><td>OnNoChunk</td><td> </td>
|
||||
<td>Called when the ray enters a chunk that is not loaded. This usually means that the tracing is aborted.
|
||||
Unlike the other callbacks, this function doesn't have a return value.</td></tr>
|
||||
</table>
|
||||
|
||||
]],
|
||||
},
|
||||
{
|
||||
@ -1101,12 +1146,12 @@ function HandleSpideyCmd(a_Split, a_Player)
|
||||
local World = a_Player:GetWorld();
|
||||
|
||||
local Callbacks = {
|
||||
OnNextBlock = function(a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta)
|
||||
OnNextBlock = function(a_BlockPos, a_BlockType, a_BlockMeta)
|
||||
if (a_BlockType ~= E_BLOCK_AIR) then
|
||||
-- abort the trace
|
||||
return true;
|
||||
end
|
||||
World:SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_COBWEB, 0);
|
||||
World:SetBlock(a_BlockPos, E_BLOCK_COBWEB, 0);
|
||||
end
|
||||
};
|
||||
|
||||
@ -1118,7 +1163,7 @@ function HandleSpideyCmd(a_Split, a_Player)
|
||||
local Start = EyePos + LookVector + LookVector;
|
||||
local End = EyePos + LookVector * 50;
|
||||
|
||||
cLineBlockTracer.Trace(World, Callbacks, Start.x, Start.y, Start.z, End.x, End.y, End.z);
|
||||
cLineBlockTracer.Trace(World, Callbacks, Start, End);
|
||||
|
||||
return true;
|
||||
end
|
||||
|
@ -1178,12 +1178,12 @@ function HandleSpideyCmd(a_Split, a_Player)
|
||||
local World = a_Player:GetWorld();
|
||||
|
||||
local Callbacks = {
|
||||
OnNextBlock = function(a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta)
|
||||
OnNextBlock = function(a_BlockPos, a_BlockType, a_BlockMeta)
|
||||
if (a_BlockType ~= E_BLOCK_AIR) then
|
||||
-- abort the trace
|
||||
return true;
|
||||
end
|
||||
World:SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_COBWEB, 0);
|
||||
World:SetBlock(a_BlockPos, E_BLOCK_COBWEB, 0);
|
||||
end
|
||||
};
|
||||
|
||||
@ -1195,7 +1195,7 @@ function HandleSpideyCmd(a_Split, a_Player)
|
||||
local Start = EyePos + LookVector + LookVector;
|
||||
local End = EyePos + LookVector * 50;
|
||||
|
||||
cLineBlockTracer.Trace(World, Callbacks, Start.x, Start.y, Start.z, End.x, End.y, End.z);
|
||||
cLineBlockTracer.Trace(World, Callbacks, Start, End);
|
||||
|
||||
return true;
|
||||
end
|
||||
@ -2421,6 +2421,89 @@ function HandleConsoleTestTracer(a_Split, a_EntireCmd)
|
||||
return true, "No such world"
|
||||
end
|
||||
|
||||
-- Define the callbacks to use for tracing:
|
||||
local Callbacks =
|
||||
{
|
||||
OnNextBlock = function(a_BlockPos, a_BlockType, a_BlockMeta, a_EntryFace)
|
||||
LOG(string.format("{%d, %d, %d}: %s", a_Block.x, a_Block.y, a_Block.z, ItemToString(cItem(a_BlockType, 1, a_BlockMeta))))
|
||||
end,
|
||||
OnNextBlockNoData = function(a_BlockPos, a_EntryFace)
|
||||
LOG(string.format("{%d, %d, %d} (no data)", a_Block.x, a_Block.y, a_Block.z))
|
||||
end,
|
||||
OnNoChunk = function()
|
||||
LOG("Chunk not loaded")
|
||||
end,
|
||||
OnNoMoreHits = function()
|
||||
LOG("Trace finished")
|
||||
end,
|
||||
OnOutOfWorld = function()
|
||||
LOG("Out of world")
|
||||
end,
|
||||
OnIntoWorld = function()
|
||||
LOG("Into world")
|
||||
end,
|
||||
}
|
||||
|
||||
-- Approximate the chunks needed for the trace by iterating over all chunks and measuring their center's distance from the traced line
|
||||
local Chunks = {}
|
||||
local sx = math.floor(Coords[1] / 16)
|
||||
local sz = math.floor(Coords[3] / 16)
|
||||
local ex = math.floor(Coords[4] / 16)
|
||||
local ez = math.floor(Coords[6] / 16)
|
||||
local sgnx = (sx < ex) and 1 or -1
|
||||
local sgnz = (sz < ez) and 1 or -1
|
||||
for z = sz, ez, sgnz do
|
||||
local ChunkCenterZ = z * 16 + 8
|
||||
for x = sx, ex, sgnx do
|
||||
local ChunkCenterX = x * 16 + 8
|
||||
local sqdist = SqDistPtFromLine(ChunkCenterX, ChunkCenterZ, Coords[1], Coords[3], Coords[4], Coords[6])
|
||||
if (sqdist <= 128) then
|
||||
table.insert(Chunks, {x, z})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Load the chunks and do the trace once loaded:
|
||||
local startPos = Vector3i(Coords[1], Coords[2], Coords[3])
|
||||
local endPos = Vector3i(Coords[4], Coords[5], Coords[6])
|
||||
World:ChunkStay(Chunks,
|
||||
nil,
|
||||
function()
|
||||
cLineBlockTracer:Trace(World, Callbacks, startPos, endPos)
|
||||
end
|
||||
)
|
||||
return true
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
function HandleConsoleTestTracerDeprecated(a_Split, a_EntireCmd)
|
||||
-- Check required params:
|
||||
if not(a_Split[7]) then
|
||||
return true, "Usage: " .. a_Split[1] .. " <x1> <y1> <z1> <x2> <y2> <z2> [<WorldName>]"
|
||||
end
|
||||
local Coords = {}
|
||||
for i = 1, 6 do
|
||||
local v = tonumber(a_Split[i + 1])
|
||||
if not(v) then
|
||||
return true, "Parameter " .. (i + 1) .. " (" .. tostring(a_Split[i + 1]) .. ") not a number "
|
||||
end
|
||||
Coords[i] = v
|
||||
end
|
||||
|
||||
-- Get the world in which to test:
|
||||
local World
|
||||
if (a_Split[8]) then
|
||||
World = cRoot:GetWorld(a_Split[2])
|
||||
else
|
||||
World = cRoot:Get():GetDefaultWorld()
|
||||
end
|
||||
if not(World) then
|
||||
return true, "No such world"
|
||||
end
|
||||
|
||||
-- Define the callbacks to use for tracing:
|
||||
local Callbacks =
|
||||
{
|
||||
@ -2716,9 +2799,9 @@ function HandleBlkCmd(a_Split, a_Player)
|
||||
local World = a_Player:GetWorld();
|
||||
|
||||
local Callbacks = {
|
||||
OnNextBlock = function(a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta)
|
||||
OnNextBlock = function(a_BlockPos, a_BlockType, a_BlockMeta)
|
||||
if (a_BlockType ~= E_BLOCK_AIR) then
|
||||
a_Player:SendMessage("Block at " .. a_BlockX .. ", " .. a_BlockY .. ", " .. a_BlockZ .. " is " .. a_BlockType .. ":" .. a_BlockMeta)
|
||||
a_Player:SendMessage("Block at " .. a_BlockPos.x .. ", " .. a_BlockPos.y .. ", " .. a_BlockPos.z .. " is " .. a_BlockType .. ":" .. a_BlockMeta)
|
||||
return true;
|
||||
end
|
||||
end
|
||||
@ -2730,7 +2813,7 @@ function HandleBlkCmd(a_Split, a_Player)
|
||||
|
||||
local End = EyePos + LookVector * 50;
|
||||
|
||||
cLineBlockTracer.Trace(World, Callbacks, EyePos.x, EyePos.y, EyePos.z, End.x, End.y, End.z);
|
||||
cLineBlockTracer.Trace(World, Callbacks, EyePos, End);
|
||||
|
||||
return true;
|
||||
end
|
||||
@ -2760,6 +2843,3 @@ function HandleTeamsCmd(a_Split, a_Player)
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -392,6 +392,12 @@ g_PluginInfo =
|
||||
HelpString = "Tests the cLineBlockTracer",
|
||||
},
|
||||
|
||||
["testtracerdeprecated"] =
|
||||
{
|
||||
Handler = HandleConsoleTestTracerDeprecated,
|
||||
HelpString = "Tests the cLineBlockTracer's deprecated API",
|
||||
},
|
||||
|
||||
["testurlclient"] =
|
||||
{
|
||||
Handler = HandleConsoleTestUrlClient,
|
||||
@ -414,4 +420,3 @@ g_PluginInfo =
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -2823,65 +2823,68 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool OnNextBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, eBlockFace a_EntryFace) override
|
||||
virtual bool OnNextBlock(Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, eBlockFace a_EntryFace) override
|
||||
{
|
||||
bool res = false;
|
||||
if (!m_Callbacks->CallTableFn(
|
||||
if (m_Callbacks->CallTableFn(
|
||||
"OnNextBlock",
|
||||
a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta, a_EntryFace,
|
||||
cLuaState::Return, res
|
||||
))
|
||||
a_BlockPos,
|
||||
a_BlockType,
|
||||
a_BlockMeta,
|
||||
a_EntryFace,
|
||||
cLuaState::Return, res)
|
||||
)
|
||||
{
|
||||
return res;
|
||||
}
|
||||
// No such function in the table, skip the callback
|
||||
return false;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
virtual bool OnNextBlockNoData(int a_BlockX, int a_BlockY, int a_BlockZ, char a_EntryFace) override
|
||||
virtual bool OnNextBlockNoData(Vector3i a_BlockPos, char a_EntryFace) override
|
||||
{
|
||||
bool res = false;
|
||||
if (!m_Callbacks->CallTableFn(
|
||||
if (m_Callbacks->CallTableFn(
|
||||
"OnNextBlockNoData",
|
||||
a_BlockX, a_BlockY, a_BlockZ, a_EntryFace,
|
||||
cLuaState::Return, res
|
||||
))
|
||||
a_BlockPos,
|
||||
a_EntryFace,
|
||||
cLuaState::Return, res)
|
||||
)
|
||||
{
|
||||
return res;
|
||||
}
|
||||
// No such function in the table, skip the callback
|
||||
return false;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
virtual bool OnOutOfWorld(double a_BlockX, double a_BlockY, double a_BlockZ) override
|
||||
virtual bool OnOutOfWorld(Vector3d a_BlockPos) override
|
||||
{
|
||||
bool res = false;
|
||||
if (!m_Callbacks->CallTableFn(
|
||||
if (m_Callbacks->CallTableFn(
|
||||
"OnOutOfWorld",
|
||||
a_BlockX, a_BlockY, a_BlockZ,
|
||||
cLuaState::Return, res
|
||||
))
|
||||
a_BlockPos,
|
||||
cLuaState::Return, res)
|
||||
)
|
||||
{
|
||||
return res;
|
||||
}
|
||||
// No such function in the table, skip the callback
|
||||
return false;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
virtual bool OnIntoWorld(double a_BlockX, double a_BlockY, double a_BlockZ) override
|
||||
virtual bool OnIntoWorld(Vector3d a_BlockPos) override
|
||||
{
|
||||
bool res = false;
|
||||
if (!m_Callbacks->CallTableFn(
|
||||
"OnIntoWorld",
|
||||
a_BlockX, a_BlockY, a_BlockZ,
|
||||
cLuaState::Return, res
|
||||
))
|
||||
if (m_Callbacks->CallTableFn("OnIntoWorld",
|
||||
a_BlockPos,
|
||||
cLuaState::Return, res)
|
||||
)
|
||||
{
|
||||
return res;
|
||||
}
|
||||
// No such function in the table, skip the callback
|
||||
return false;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
virtual void OnNoMoreHits(void) override
|
||||
{
|
||||
@ -2901,6 +2904,87 @@ protected:
|
||||
|
||||
|
||||
|
||||
/** Provides interface between a Lua table of callbacks and the cBlockTracer::cCallbacks
|
||||
This is the deprecated version of cLuaBlockTracerCallback, used when the plugin calls
|
||||
the Trace function with number-based coords. */
|
||||
class cLuaBlockTracerCallbacksOld :
|
||||
public cLuaBlockTracerCallbacks
|
||||
{
|
||||
public:
|
||||
cLuaBlockTracerCallbacksOld(cLuaState::cTableRefPtr && a_Callbacks):
|
||||
cLuaBlockTracerCallbacks(std::move(a_Callbacks))
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool OnNextBlock(Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, eBlockFace a_EntryFace) override
|
||||
{
|
||||
bool res = false;
|
||||
if (m_Callbacks->CallTableFn(
|
||||
"OnNextBlock",
|
||||
a_BlockPos.x, a_BlockPos.y, a_BlockPos.z,
|
||||
a_BlockType,
|
||||
a_BlockMeta,
|
||||
a_EntryFace,
|
||||
cLuaState::Return, res)
|
||||
)
|
||||
{
|
||||
return res;
|
||||
}
|
||||
// No such function in the table, skip the callback
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool OnNextBlockNoData(Vector3i a_BlockPos, char a_EntryFace) override
|
||||
{
|
||||
bool res = false;
|
||||
if (m_Callbacks->CallTableFn(
|
||||
"OnNextBlockNoData",
|
||||
a_BlockPos.x, a_BlockPos.y, a_BlockPos.z,
|
||||
a_EntryFace,
|
||||
cLuaState::Return, res)
|
||||
)
|
||||
{
|
||||
return res;
|
||||
}
|
||||
// No such function in the table, skip the callback
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool OnOutOfWorld(Vector3d a_BlockPos) override
|
||||
{
|
||||
bool res = false;
|
||||
if (m_Callbacks->CallTableFn(
|
||||
"OnOutOfWorld",
|
||||
a_BlockPos.x, a_BlockPos.y, a_BlockPos.z,
|
||||
cLuaState::Return, res)
|
||||
)
|
||||
{
|
||||
return res;
|
||||
}
|
||||
// No such function in the table, skip the callback
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool OnIntoWorld(Vector3d a_BlockPos) override
|
||||
{
|
||||
bool res = false;
|
||||
if (m_Callbacks->CallTableFn(
|
||||
"OnIntoWorld",
|
||||
a_BlockPos.x, a_BlockPos.y, a_BlockPos.z,
|
||||
cLuaState::Return, res)
|
||||
)
|
||||
{
|
||||
return res;
|
||||
}
|
||||
// No such function in the table, skip the callback
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static int tolua_cLineBlockTracer_FirstSolidHitTrace(lua_State * tolua_S)
|
||||
{
|
||||
/* Supported function signatures:
|
||||
@ -3100,8 +3184,10 @@ static int tolua_cLineBlockTracer_LineOfSightTrace(lua_State * tolua_S)
|
||||
static int tolua_cLineBlockTracer_Trace(lua_State * tolua_S)
|
||||
{
|
||||
/* Supported function signatures:
|
||||
cLineBlockTracer:Trace(World, Callbacks, StartX, StartY, StartZ, EndX, EndY, EndZ) // Canonical
|
||||
cLineBlockTracer.Trace(World, Callbacks, StartX, StartY, StartZ, EndX, EndY, EndZ)
|
||||
cLineBlockTracer:Trace(World, Callbacks, StartX, StartY, StartZ, EndX, EndY, EndZ) // Canonical // DEPRECATED
|
||||
cLineBlockTracer.Trace(World, Callbacks, StartX, StartY, StartZ, EndX, EndY, EndZ) // DEPRECATED
|
||||
cLineBlockTracer:Trace(World, Callbacks, Start, End) // Canonical
|
||||
cLineBlockTracer.Trace(World, Callbacks, Start, End)
|
||||
*/
|
||||
|
||||
// If the first param is the cLineBlockTracer class, shift param index by one:
|
||||
@ -3116,9 +3202,7 @@ static int tolua_cLineBlockTracer_Trace(lua_State * tolua_S)
|
||||
cLuaState L(tolua_S);
|
||||
if (
|
||||
!L.CheckParamUserType(idx, "cWorld") ||
|
||||
!L.CheckParamTable (idx + 1) ||
|
||||
!L.CheckParamNumber (idx + 2, idx + 7) ||
|
||||
!L.CheckParamEnd (idx + 8)
|
||||
!L.CheckParamTable (idx + 1)
|
||||
)
|
||||
{
|
||||
return 0;
|
||||
@ -3126,23 +3210,55 @@ static int tolua_cLineBlockTracer_Trace(lua_State * tolua_S)
|
||||
|
||||
// Get the params:
|
||||
cWorld * world;
|
||||
double startX, startY, startZ;
|
||||
double endX, endY, endZ;
|
||||
Vector3d start;
|
||||
Vector3d end;
|
||||
cLuaState::cTableRefPtr callbacks;
|
||||
if (!L.GetStackValues(idx, world, callbacks, startX, startY, startZ, endX, endY, endZ))
|
||||
if (
|
||||
L.IsParamNumber (idx + 2) &&
|
||||
L.IsParamNumber (idx + 3) &&
|
||||
L.IsParamNumber (idx + 4) &&
|
||||
L.IsParamNumber (idx + 5) &&
|
||||
L.IsParamNumber (idx + 6) &&
|
||||
L.IsParamNumber (idx + 7) &&
|
||||
L.CheckParamEnd (idx + 8)
|
||||
)
|
||||
{
|
||||
if (!L.GetStackValues(idx, world, callbacks, start.x, start.y, start.z, end.x, end.y, end.z))
|
||||
{
|
||||
LOGWARNING("cLineBlockTracer:Trace(): Cannot read parameters (starting at idx %d), aborting the trace.", idx);
|
||||
L.LogStackTrace();
|
||||
L.LogStackValues("Values on the stack");
|
||||
return 0;
|
||||
}
|
||||
|
||||
LOGWARNING("cLineBlockTracer:Trace(): Using plain numbers is deprecated, use Vector3 coords instead.");
|
||||
L.LogStackTrace();
|
||||
// Trace:
|
||||
cLuaBlockTracerCallbacks tracerCallbacks(std::move(callbacks));
|
||||
bool res = cLineBlockTracer::Trace(*world, tracerCallbacks, startX, startY, startZ, endX, endY, endZ);
|
||||
cLuaBlockTracerCallbacksOld tracerCallbacks(std::move(callbacks));
|
||||
bool res = cLineBlockTracer::Trace(*world, tracerCallbacks, start, end);
|
||||
tolua_pushboolean(L, res ? 1 : 0);
|
||||
return 1;
|
||||
}
|
||||
else if (
|
||||
L.IsParamVector3(idx + 2) &&
|
||||
L.IsParamVector3(idx + 3) &&
|
||||
L.CheckParamEnd (idx + 4)
|
||||
)
|
||||
{
|
||||
if (!L.GetStackValues(idx, world, callbacks, start, end))
|
||||
{
|
||||
LOGWARNING("cLineBlockTracer:Trace(): Cannot read parameters (starting at idx %d), aborting the trace.", idx);
|
||||
L.LogStackTrace();
|
||||
L.LogStackValues("Values on the stack");
|
||||
return 0;
|
||||
}
|
||||
// Trace:
|
||||
cLuaBlockTracerCallbacks tracerCallbacks(std::move(callbacks));
|
||||
bool res = cLineBlockTracer::Trace(*world, tracerCallbacks, start, end);
|
||||
tolua_pushboolean(L, res ? 1 : 0);
|
||||
return 1;
|
||||
}
|
||||
return L.ApiParamError("Invalid overload of cLineBlockTracer:Trace()");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -40,45 +40,39 @@ public:
|
||||
/** Called on each block encountered along the path, including the first block (path start)
|
||||
When this callback returns true, the tracing is aborted.
|
||||
*/
|
||||
virtual bool OnNextBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, eBlockFace a_EntryFace) = 0;
|
||||
virtual bool OnNextBlock(Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, eBlockFace a_EntryFace) = 0;
|
||||
|
||||
/** Called on each block encountered along the path, including the first block (path start), if chunk data is not loaded
|
||||
When this callback returns true, the tracing is aborted.
|
||||
*/
|
||||
virtual bool OnNextBlockNoData(int a_BlockX, int a_BlockY, int a_BlockZ, char a_EntryFace)
|
||||
virtual bool OnNextBlockNoData(Vector3i a_BlockPos, char a_EntryFace)
|
||||
{
|
||||
UNUSED(a_BlockX);
|
||||
UNUSED(a_BlockY);
|
||||
UNUSED(a_BlockZ);
|
||||
UNUSED(a_BlockPos);
|
||||
UNUSED(a_EntryFace);
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Called when the path goes out of world, either below (a_BlockY < 0) or above (a_BlockY >= cChunkDef::Height)
|
||||
/** Called when the path goes out of world, either below (a_BlockPos.y < 0) or above (a_BlockPos.y >= cChunkDef::Height)
|
||||
The coords specify the exact point at which the path exited the world.
|
||||
If this callback returns true, the tracing is aborted.
|
||||
Note that some paths can go out of the world and come back again (parabola),
|
||||
in such a case this callback is followed by OnIntoWorld() and further OnNextBlock() calls
|
||||
*/
|
||||
virtual bool OnOutOfWorld(double a_BlockX, double a_BlockY, double a_BlockZ)
|
||||
virtual bool OnOutOfWorld(Vector3d a_BlockPos)
|
||||
{
|
||||
UNUSED(a_BlockX);
|
||||
UNUSED(a_BlockY);
|
||||
UNUSED(a_BlockZ);
|
||||
UNUSED(a_BlockPos);
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Called when the path goes into the world, from either below (a_BlockY < 0) or above (a_BlockY >= cChunkDef::Height)
|
||||
/** Called when the path goes into the world, from either below (a_BlockPos.y < 0) or above (a_BlockPos.y >= cChunkDef::Height)
|
||||
The coords specify the exact point at which the path entered the world.
|
||||
If this callback returns true, the tracing is aborted.
|
||||
Note that some paths can go out of the world and come back again (parabola),
|
||||
in such a case this callback is followed by further OnNextBlock() calls
|
||||
*/
|
||||
virtual bool OnIntoWorld(double a_BlockX, double a_BlockY, double a_BlockZ)
|
||||
virtual bool OnIntoWorld(Vector3d a_BlockPos)
|
||||
{
|
||||
UNUSED(a_BlockX);
|
||||
UNUSED(a_BlockY);
|
||||
UNUSED(a_BlockZ);
|
||||
UNUSED(a_BlockPos);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -50,7 +50,7 @@ protected:
|
||||
double m_SlowdownCoeff;
|
||||
|
||||
// cCallbacks overrides:
|
||||
virtual bool OnNextBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, eBlockFace a_EntryFace) override
|
||||
virtual bool OnNextBlock(Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, eBlockFace a_EntryFace) override
|
||||
{
|
||||
/*
|
||||
// DEBUG:
|
||||
@ -65,7 +65,7 @@ protected:
|
||||
if (cBlockInfo::IsSolid(a_BlockType))
|
||||
{
|
||||
// The projectile hit a solid block, calculate the exact hit coords:
|
||||
cBoundingBox bb(a_BlockX, a_BlockX + 1, a_BlockY, a_BlockY + 1, a_BlockZ, a_BlockZ + 1); // Bounding box of the block hit
|
||||
cBoundingBox bb(a_BlockPos, a_BlockPos + Vector3i(1, 1, 1)); // Bounding box of the block hit
|
||||
const Vector3d LineStart = m_Projectile->GetPosition(); // Start point for the imaginary line that goes through the block hit
|
||||
const Vector3d LineEnd = LineStart + m_Projectile->GetSpeed(); // End point for the imaginary line that goes through the block hit
|
||||
double LineCoeff = 0; // Used to calculate where along the line an intersection with the bounding box occurs
|
||||
@ -75,7 +75,7 @@ protected:
|
||||
{
|
||||
Vector3d Intersection = LineStart + m_Projectile->GetSpeed() * LineCoeff; // Point where projectile goes into the hit block
|
||||
|
||||
if (cPluginManager::Get()->CallHookProjectileHitBlock(*m_Projectile, a_BlockX, a_BlockY, a_BlockZ, Face, Intersection))
|
||||
if (cPluginManager::Get()->CallHookProjectileHitBlock(*m_Projectile, a_BlockPos.x, a_BlockPos.y, a_BlockPos.z, Face, Intersection))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -455,6 +455,3 @@ void cProjectileEntity::CollectedBy(cPlayer & a_Dest)
|
||||
UNUSED(a_Dest);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -52,11 +52,11 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool OnNextBlock(int a_CBBlockX, int a_CBBlockY, int a_CBBlockZ, BLOCKTYPE a_CBBlockType, NIBBLETYPE a_CBBlockMeta, eBlockFace a_CBEntryFace) override
|
||||
virtual bool OnNextBlock(Vector3i a_CBBlockPos, BLOCKTYPE a_CBBlockType, NIBBLETYPE a_CBBlockMeta, eBlockFace a_CBEntryFace) override
|
||||
{
|
||||
if (a_CBBlockType != E_BLOCK_AIR)
|
||||
{
|
||||
m_Pos.Set(a_CBBlockX, a_CBBlockY, a_CBBlockZ);
|
||||
m_Pos = a_CBBlockPos;
|
||||
m_HasFound = true;
|
||||
return true;
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool OnNextBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, eBlockFace a_EntryFace) override
|
||||
virtual bool OnNextBlock(Vector3i a_BlockPosition, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, eBlockFace a_EntryFace) override
|
||||
{
|
||||
if (IsBlockWater(a_BlockType))
|
||||
{
|
||||
@ -52,7 +52,7 @@ public:
|
||||
return false;
|
||||
}
|
||||
m_HasHitFluid = true;
|
||||
m_Pos.Set(a_BlockX, a_BlockY, a_BlockZ);
|
||||
m_Pos = a_BlockPosition;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -197,7 +197,7 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool OnNextBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, eBlockFace a_EntryFace) override
|
||||
virtual bool OnNextBlock(Vector3i a_BlockPosition, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, eBlockFace a_EntryFace) override
|
||||
{
|
||||
if (IsBlockWater(a_BlockType) || IsBlockLava(a_BlockType))
|
||||
{
|
||||
@ -206,7 +206,7 @@ public:
|
||||
return false;
|
||||
}
|
||||
m_HasHitFluid = true;
|
||||
m_Pos.Set(a_BlockX, a_BlockY, a_BlockZ);
|
||||
m_Pos = a_BlockPosition;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -217,7 +217,7 @@ public:
|
||||
Vector3d Start(a_Player->GetEyePosition() + a_Player->GetLookVector());
|
||||
Vector3d End(a_Player->GetEyePosition() + a_Player->GetLookVector() * 5);
|
||||
|
||||
Tracer.Trace(Start.x, Start.y, Start.z, End.x, End.y, End.z);
|
||||
Tracer.Trace(Start, End);
|
||||
|
||||
if (!Callbacks.m_HasHitFluid)
|
||||
{
|
||||
@ -244,7 +244,7 @@ public:
|
||||
NIBBLETYPE m_ReplacedBlockMeta;
|
||||
eBlockFace m_EntryFace;
|
||||
|
||||
virtual bool OnNextBlock(int a_CBBlockX, int a_CBBlockY, int a_CBBlockZ, BLOCKTYPE a_CBBlockType, NIBBLETYPE a_CBBlockMeta, eBlockFace a_CBEntryFace) override
|
||||
virtual bool OnNextBlock(Vector3i a_CBBlockPos, BLOCKTYPE a_CBBlockType, NIBBLETYPE a_CBBlockMeta, eBlockFace a_CBEntryFace) override
|
||||
{
|
||||
if ((a_CBBlockType != E_BLOCK_AIR) && !IsBlockLiquid(a_CBBlockType))
|
||||
{
|
||||
@ -253,9 +253,9 @@ public:
|
||||
m_EntryFace = static_cast<eBlockFace>(a_CBEntryFace);
|
||||
if (!cFluidSimulator::CanWashAway(a_CBBlockType))
|
||||
{
|
||||
AddFaceDirection(a_CBBlockX, a_CBBlockY, a_CBBlockZ, a_CBEntryFace); // Was an unwashawayable block, can't overwrite it!
|
||||
a_CBBlockPos = AddFaceDirection(a_CBBlockPos, a_CBEntryFace); // Was an unwashawayable block, can't overwrite it!
|
||||
}
|
||||
m_Pos.Set(a_CBBlockX, a_CBBlockY, a_CBBlockZ); // (Block could be washed away, replace it)
|
||||
m_Pos = a_CBBlockPos; // (Block could be washed away, replace it)
|
||||
return true; // Abort tracing
|
||||
}
|
||||
return false;
|
||||
@ -269,7 +269,7 @@ public:
|
||||
// cLineBlockTracer::Trace() returns true when whole line was traversed. By returning true from the callback when we hit something,
|
||||
// we ensure that this never happens if liquid could be placed
|
||||
// Use this to judge whether the position is valid
|
||||
if (!Tracer.Trace(Start.x, Start.y, Start.z, End.x, End.y, End.z))
|
||||
if (!Tracer.Trace(Start, End))
|
||||
{
|
||||
a_BlockPos = Callbacks.m_Pos;
|
||||
a_BlockType = Callbacks.m_ReplacedBlockType;
|
||||
|
@ -66,7 +66,7 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool OnNextBlock(int a_CBBlockX, int a_CBBlockY, int a_CBBlockZ, BLOCKTYPE a_CBBlockType, NIBBLETYPE a_CBBlockMeta, eBlockFace a_CBEntryFace) override
|
||||
virtual bool OnNextBlock(Vector3i a_CBBlockPos, BLOCKTYPE a_CBBlockType, NIBBLETYPE a_CBBlockMeta, eBlockFace a_CBEntryFace) override
|
||||
{
|
||||
if (IsBlockWater(a_CBBlockType))
|
||||
{
|
||||
@ -74,7 +74,7 @@ public:
|
||||
{
|
||||
return false;
|
||||
}
|
||||
AddFaceDirection(a_CBBlockX, a_CBBlockY, a_CBBlockZ, BLOCK_FACE_YP); // Always place pad at top of water block
|
||||
a_CBBlockPos = AddFaceDirection(a_CBBlockPos, BLOCK_FACE_YP); // Always place pad at top of water block
|
||||
if (
|
||||
!IsBlockWater(a_CBBlockType) &&
|
||||
cBlockInfo::FullyOccupiesVoxel(a_CBBlockType)
|
||||
@ -84,7 +84,7 @@ public:
|
||||
return true;
|
||||
}
|
||||
m_HasHitFluid = true;
|
||||
m_Pos.Set(a_CBBlockX, a_CBBlockY, a_CBBlockZ);
|
||||
m_Pos = a_CBBlockPos;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -96,7 +96,7 @@ public:
|
||||
} Callbacks;
|
||||
auto Start = a_Player->GetEyePosition() + a_Player->GetLookVector();
|
||||
auto End = a_Player->GetEyePosition() + a_Player->GetLookVector() * 5;
|
||||
cLineBlockTracer::Trace(*a_Player->GetWorld(), Callbacks, Start.x, Start.y, Start.z, End.x, End.y, End.z);
|
||||
cLineBlockTracer::Trace(*a_Player->GetWorld(), Callbacks, Start, End);
|
||||
|
||||
if (Callbacks.m_HasHitFluid)
|
||||
{
|
||||
|
@ -16,21 +16,11 @@
|
||||
|
||||
cLineBlockTracer::cLineBlockTracer(cWorld & a_World, cCallbacks & a_Callbacks) :
|
||||
Super(a_World, a_Callbacks),
|
||||
m_StartX(0.0),
|
||||
m_StartY(0.0),
|
||||
m_StartZ(0.0),
|
||||
m_EndX(0.0),
|
||||
m_EndY(0.0),
|
||||
m_EndZ(0.0),
|
||||
m_DiffX(0.0),
|
||||
m_DiffY(0.0),
|
||||
m_DiffZ(0.0),
|
||||
m_DirX(0),
|
||||
m_DirY(0),
|
||||
m_DirZ(0),
|
||||
m_CurrentX(0),
|
||||
m_CurrentY(0),
|
||||
m_CurrentZ(0),
|
||||
m_Start(),
|
||||
m_End(),
|
||||
m_Diff(),
|
||||
m_Dir(),
|
||||
m_Current(),
|
||||
m_CurrentFace(BLOCK_FACE_NONE)
|
||||
{
|
||||
}
|
||||
@ -39,10 +29,10 @@ cLineBlockTracer::cLineBlockTracer(cWorld & a_World, cCallbacks & a_Callbacks) :
|
||||
|
||||
|
||||
|
||||
bool cLineBlockTracer::Trace(cWorld & a_World, cBlockTracer::cCallbacks & a_Callbacks, const Vector3d & a_Start, const Vector3d & a_End)
|
||||
bool cLineBlockTracer::Trace(cWorld & a_World, cBlockTracer::cCallbacks & a_Callbacks, const Vector3d a_Start, const Vector3d a_End)
|
||||
{
|
||||
cLineBlockTracer Tracer(a_World, a_Callbacks);
|
||||
return Tracer.Trace(a_Start.x, a_Start.y, a_Start.z, a_End.x, a_End.y, a_End.z);
|
||||
return Tracer.Trace(a_Start, a_End);
|
||||
}
|
||||
|
||||
|
||||
@ -64,7 +54,7 @@ bool cLineBlockTracer::LineOfSightTrace(cWorld & a_World, const Vector3d & a_Sta
|
||||
m_IsLavaOpaque(a_IsLavaOpaque)
|
||||
{}
|
||||
|
||||
virtual bool OnNextBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, eBlockFace a_EntryFace) override
|
||||
virtual bool OnNextBlock(Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, eBlockFace a_EntryFace) override
|
||||
{
|
||||
switch (a_BlockType)
|
||||
{
|
||||
@ -108,7 +98,7 @@ bool cLineBlockTracer::FirstSolidHitTrace(
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool OnNextBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, eBlockFace a_EntryFace) override
|
||||
virtual bool OnNextBlock(Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, eBlockFace a_EntryFace) override
|
||||
{
|
||||
if (!cBlockInfo::IsSolid(a_BlockType))
|
||||
{
|
||||
@ -116,9 +106,9 @@ bool cLineBlockTracer::FirstSolidHitTrace(
|
||||
}
|
||||
|
||||
// We hit a solid block, calculate the exact hit coords and abort trace:
|
||||
m_HitBlockCoords.Set(a_BlockX, a_BlockY, a_BlockZ);
|
||||
m_HitBlockCoords = a_BlockPos;
|
||||
m_HitBlockFace = a_EntryFace;
|
||||
cBoundingBox bb(a_BlockX, a_BlockX + 1, a_BlockY, a_BlockY + 1, a_BlockZ, a_BlockZ + 1); // Bounding box of the block hit
|
||||
cBoundingBox bb(a_BlockPos, a_BlockPos + Vector3i(1, 1, 1)); // Bounding box of the block hit
|
||||
double LineCoeff = 0; // Used to calculate where along the line an intersection with the bounding box occurs
|
||||
eBlockFace Face; // Face hit
|
||||
if (!bb.CalcLineIntersection(m_Start, m_End, LineCoeff, Face))
|
||||
@ -144,64 +134,46 @@ bool cLineBlockTracer::FirstSolidHitTrace(
|
||||
|
||||
|
||||
|
||||
bool cLineBlockTracer::Trace(cWorld & a_World, cBlockTracer::cCallbacks &a_Callbacks, double a_StartX, double a_StartY, double a_StartZ, double a_EndX, double a_EndY, double a_EndZ)
|
||||
{
|
||||
cLineBlockTracer Tracer(a_World, a_Callbacks);
|
||||
return Tracer.Trace(a_StartX, a_StartY, a_StartZ, a_EndX, a_EndY, a_EndZ);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cLineBlockTracer::Trace(double a_StartX, double a_StartY, double a_StartZ, double a_EndX, double a_EndY, double a_EndZ)
|
||||
bool cLineBlockTracer::Trace(const Vector3d a_Start, const Vector3d a_End)
|
||||
{
|
||||
// Initialize the member veriables:
|
||||
m_StartX = a_StartX;
|
||||
m_StartY = a_StartY;
|
||||
m_StartZ = a_StartZ;
|
||||
m_EndX = a_EndX;
|
||||
m_EndY = a_EndY;
|
||||
m_EndZ = a_EndZ;
|
||||
m_DirX = (m_StartX < m_EndX) ? 1 : -1;
|
||||
m_DirY = (m_StartY < m_EndY) ? 1 : -1;
|
||||
m_DirZ = (m_StartZ < m_EndZ) ? 1 : -1;
|
||||
m_Start = a_Start;
|
||||
m_End = a_End;
|
||||
m_Dir.x = (m_Start.x < m_End.x) ? 1 : -1;
|
||||
m_Dir.y = (m_Start.y < m_End.y) ? 1 : -1;
|
||||
m_Dir.z = (m_Start.z < m_End.z) ? 1 : -1;
|
||||
m_CurrentFace = BLOCK_FACE_NONE;
|
||||
|
||||
// Check the start coords, adjust into the world:
|
||||
if (m_StartY < 0)
|
||||
if (m_Start.y < 0)
|
||||
{
|
||||
if (m_EndY < 0)
|
||||
if (m_End.y < 0)
|
||||
{
|
||||
// Nothing to trace
|
||||
m_Callbacks->OnNoMoreHits();
|
||||
return true;
|
||||
}
|
||||
FixStartBelowWorld();
|
||||
m_Callbacks->OnIntoWorld(m_StartX, m_StartY, m_StartZ);
|
||||
m_Callbacks->OnIntoWorld(m_Start);
|
||||
}
|
||||
else if (m_StartY >= cChunkDef::Height)
|
||||
else if (m_Start.y >= cChunkDef::Height)
|
||||
{
|
||||
if (m_EndY >= cChunkDef::Height)
|
||||
if (m_End.y >= cChunkDef::Height)
|
||||
{
|
||||
m_Callbacks->OnNoMoreHits();
|
||||
return true;
|
||||
}
|
||||
FixStartAboveWorld();
|
||||
m_Callbacks->OnIntoWorld(m_StartX, m_StartY, m_StartZ);
|
||||
m_Callbacks->OnIntoWorld(m_Start);
|
||||
}
|
||||
|
||||
m_CurrentX = FloorC(m_StartX);
|
||||
m_CurrentY = FloorC(m_StartY);
|
||||
m_CurrentZ = FloorC(m_StartZ);
|
||||
m_Current = m_Start.Floor();
|
||||
|
||||
m_DiffX = m_EndX - m_StartX;
|
||||
m_DiffY = m_EndY - m_StartY;
|
||||
m_DiffZ = m_EndZ - m_StartZ;
|
||||
m_Diff = m_End - m_Start;
|
||||
|
||||
// The actual trace is handled with ChunkMapCS locked by calling our ChunkCallback for the specified chunk
|
||||
int BlockX = FloorC(m_StartX);
|
||||
int BlockZ = FloorC(m_StartZ);
|
||||
int BlockX = FloorC(m_Start.x);
|
||||
int BlockZ = FloorC(m_Start.z);
|
||||
int ChunkX, ChunkZ;
|
||||
cChunkDef::BlockToChunk(BlockX, BlockZ, ChunkX, ChunkZ);
|
||||
return m_World->DoWithChunk(ChunkX, ChunkZ, [this](cChunk & a_Chunk) { return ChunkCallback(&a_Chunk); });
|
||||
@ -216,8 +188,8 @@ void cLineBlockTracer::FixStartAboveWorld(void)
|
||||
// We must set the start Y to less than cChunkDef::Height so that it is considered inside the world later on
|
||||
// Therefore we use an EPS-offset from the height, as small as reasonably possible.
|
||||
const double Height = static_cast<double>(cChunkDef::Height) - 0.00001;
|
||||
CalcXZIntersection(Height, m_StartX, m_StartZ);
|
||||
m_StartY = Height;
|
||||
CalcXZIntersection(Height, m_Start.x, m_Start.z);
|
||||
m_Start.y = Height;
|
||||
}
|
||||
|
||||
|
||||
@ -226,8 +198,8 @@ void cLineBlockTracer::FixStartAboveWorld(void)
|
||||
|
||||
void cLineBlockTracer::FixStartBelowWorld(void)
|
||||
{
|
||||
CalcXZIntersection(0, m_StartX, m_StartZ);
|
||||
m_StartY = 0;
|
||||
CalcXZIntersection(0, m_Start.x, m_Start.z);
|
||||
m_Start.y = 0;
|
||||
}
|
||||
|
||||
|
||||
@ -236,9 +208,9 @@ void cLineBlockTracer::FixStartBelowWorld(void)
|
||||
|
||||
void cLineBlockTracer::CalcXZIntersection(double a_Y, double & a_IntersectX, double & a_IntersectZ)
|
||||
{
|
||||
double Ratio = (m_StartY - a_Y) / (m_StartY - m_EndY);
|
||||
a_IntersectX = m_StartX + (m_EndX - m_StartX) * Ratio;
|
||||
a_IntersectZ = m_StartZ + (m_EndZ - m_StartZ) * Ratio;
|
||||
double Ratio = (m_Start.y - a_Y) / (m_Start.y - m_End.y);
|
||||
a_IntersectX = m_Start.x + (m_End.x - m_Start.x) * Ratio;
|
||||
a_IntersectZ = m_Start.z + (m_End.z - m_Start.z) * Ratio;
|
||||
}
|
||||
|
||||
|
||||
@ -259,10 +231,10 @@ bool cLineBlockTracer::MoveToNextBlock(void)
|
||||
|
||||
// Calculate the next YZ wall hit:
|
||||
double Coeff = 1;
|
||||
if (std::abs(m_DiffX) > EPS)
|
||||
if (std::abs(m_Diff.x) > EPS)
|
||||
{
|
||||
double DestX = (m_DirX > 0) ? (m_CurrentX + 1) : m_CurrentX;
|
||||
double CoeffX = (DestX - m_StartX) / m_DiffX;
|
||||
double DestX = (m_Dir.x > 0) ? (m_Current.x + 1) : m_Current.x;
|
||||
double CoeffX = (DestX - m_Start.x) / m_Diff.x;
|
||||
if (CoeffX <= 1) // We need to include equality for the last block in the trace
|
||||
{
|
||||
Coeff = CoeffX;
|
||||
@ -271,10 +243,10 @@ bool cLineBlockTracer::MoveToNextBlock(void)
|
||||
}
|
||||
|
||||
// If the next XZ wall hit is closer, use it instead:
|
||||
if (std::abs(m_DiffY) > EPS)
|
||||
if (std::abs(m_Diff.y) > EPS)
|
||||
{
|
||||
double DestY = (m_DirY > 0) ? (m_CurrentY + 1) : m_CurrentY;
|
||||
double CoeffY = (DestY - m_StartY) / m_DiffY;
|
||||
double DestY = (m_Dir.y > 0) ? (m_Current.y + 1) : m_Current.y;
|
||||
double CoeffY = (DestY - m_Start.y) / m_Diff.y;
|
||||
if (CoeffY <= Coeff) // We need to include equality for the last block in the trace
|
||||
{
|
||||
Coeff = CoeffY;
|
||||
@ -283,10 +255,10 @@ bool cLineBlockTracer::MoveToNextBlock(void)
|
||||
}
|
||||
|
||||
// If the next XY wall hit is closer, use it instead:
|
||||
if (std::abs(m_DiffZ) > EPS)
|
||||
if (std::abs(m_Diff.z) > EPS)
|
||||
{
|
||||
double DestZ = (m_DirZ > 0) ? (m_CurrentZ + 1) : m_CurrentZ;
|
||||
double CoeffZ = (DestZ - m_StartZ) / m_DiffZ;
|
||||
double DestZ = (m_Dir.z > 0) ? (m_Current.z + 1) : m_Current.z;
|
||||
double CoeffZ = (DestZ - m_Start.z) / m_Diff.z;
|
||||
if (CoeffZ <= Coeff) // We need to include equality for the last block in the trace
|
||||
{
|
||||
Direction = dirZ;
|
||||
@ -296,9 +268,9 @@ bool cLineBlockTracer::MoveToNextBlock(void)
|
||||
// Based on the wall hit, adjust the current coords
|
||||
switch (Direction)
|
||||
{
|
||||
case dirX: m_CurrentX += m_DirX; m_CurrentFace = (m_DirX > 0) ? BLOCK_FACE_XM : BLOCK_FACE_XP; break;
|
||||
case dirY: m_CurrentY += m_DirY; m_CurrentFace = (m_DirY > 0) ? BLOCK_FACE_YM : BLOCK_FACE_YP; break;
|
||||
case dirZ: m_CurrentZ += m_DirZ; m_CurrentFace = (m_DirZ > 0) ? BLOCK_FACE_ZM : BLOCK_FACE_ZP; break;
|
||||
case dirX: m_Current.x += m_Dir.x; m_CurrentFace = (m_Dir.x > 0) ? BLOCK_FACE_XM : BLOCK_FACE_XP; break;
|
||||
case dirY: m_Current.y += m_Dir.y; m_CurrentFace = (m_Dir.y > 0) ? BLOCK_FACE_YM : BLOCK_FACE_YP; break;
|
||||
case dirZ: m_Current.z += m_Dir.z; m_CurrentFace = (m_Dir.z > 0) ? BLOCK_FACE_ZM : BLOCK_FACE_ZP; break;
|
||||
case dirNONE: return false;
|
||||
}
|
||||
return true;
|
||||
@ -310,7 +282,7 @@ bool cLineBlockTracer::MoveToNextBlock(void)
|
||||
|
||||
bool cLineBlockTracer::ChunkCallback(cChunk * a_Chunk)
|
||||
{
|
||||
ASSERT((m_CurrentY >= 0) && (m_CurrentY < cChunkDef::Height)); // This should be provided by FixStartAboveWorld() / FixStartBelowWorld()
|
||||
ASSERT((m_Current.y >= 0) && (m_Current.y < cChunkDef::Height)); // This should be provided by FixStartAboveWorld() / FixStartBelowWorld()
|
||||
|
||||
// This is the actual line tracing loop.
|
||||
for (;;)
|
||||
@ -330,12 +302,12 @@ bool cLineBlockTracer::ChunkCallback(cChunk * a_Chunk)
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((m_CurrentY < 0) || (m_CurrentY >= cChunkDef::Height))
|
||||
if ((m_Current.y < 0) || (m_Current.y >= cChunkDef::Height))
|
||||
{
|
||||
// We've gone out of the world, that's the end of this trace
|
||||
double IntersectX, IntersectZ;
|
||||
CalcXZIntersection(m_CurrentY, IntersectX, IntersectZ);
|
||||
if (m_Callbacks->OnOutOfWorld(IntersectX, m_CurrentY, IntersectZ))
|
||||
CalcXZIntersection(m_Current.y, IntersectX, IntersectZ);
|
||||
if (m_Callbacks->OnOutOfWorld({IntersectX, double(m_Current.y), IntersectZ}))
|
||||
{
|
||||
// The callback terminated the trace
|
||||
return false;
|
||||
@ -345,7 +317,7 @@ bool cLineBlockTracer::ChunkCallback(cChunk * a_Chunk)
|
||||
}
|
||||
|
||||
// Update the current chunk
|
||||
a_Chunk = a_Chunk->GetNeighborChunk(m_CurrentX, m_CurrentZ);
|
||||
a_Chunk = a_Chunk->GetNeighborChunk(m_Current.x, m_Current.z);
|
||||
if (a_Chunk == nullptr)
|
||||
{
|
||||
m_Callbacks->OnNoChunk();
|
||||
@ -356,16 +328,16 @@ bool cLineBlockTracer::ChunkCallback(cChunk * a_Chunk)
|
||||
{
|
||||
BLOCKTYPE BlockType;
|
||||
NIBBLETYPE BlockMeta;
|
||||
int RelX = m_CurrentX - a_Chunk->GetPosX() * cChunkDef::Width;
|
||||
int RelZ = m_CurrentZ - a_Chunk->GetPosZ() * cChunkDef::Width;
|
||||
a_Chunk->GetBlockTypeMeta(RelX, m_CurrentY, RelZ, BlockType, BlockMeta);
|
||||
if (m_Callbacks->OnNextBlock(m_CurrentX, m_CurrentY, m_CurrentZ, BlockType, BlockMeta, m_CurrentFace))
|
||||
int RelX = m_Current.x - a_Chunk->GetPosX() * cChunkDef::Width;
|
||||
int RelZ = m_Current.z - a_Chunk->GetPosZ() * cChunkDef::Width;
|
||||
a_Chunk->GetBlockTypeMeta(RelX, m_Current.y, RelZ, BlockType, BlockMeta);
|
||||
if (m_Callbacks->OnNextBlock(m_Current, BlockType, BlockMeta, m_CurrentFace))
|
||||
{
|
||||
// The callback terminated the trace
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (m_Callbacks->OnNextBlockNoData(m_CurrentX, m_CurrentY, m_CurrentZ, m_CurrentFace))
|
||||
else if (m_Callbacks->OnNextBlockNoData(m_Current, m_CurrentFace))
|
||||
{
|
||||
// The callback terminated the trace
|
||||
return false;
|
||||
@ -375,4 +347,3 @@ bool cLineBlockTracer::ChunkCallback(cChunk * a_Chunk)
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -45,15 +45,13 @@ public:
|
||||
cLineBlockTracer(cWorld & a_World, cCallbacks & a_Callbacks);
|
||||
|
||||
/** Traces one line between Start and End; returns true if the entire line was traced (until OnNoMoreHits()) */
|
||||
bool Trace(double a_StartX, double a_StartY, double a_StartZ, double a_EndX, double a_EndY, double a_EndZ);
|
||||
bool Trace(Vector3d a_Start, Vector3d a_End);
|
||||
|
||||
|
||||
// Utility functions for simple one-line usage:
|
||||
|
||||
/** Traces one line between Start and End; returns true if the entire line was traced (until OnNoMoreHits()) */
|
||||
static bool Trace(cWorld & a_World, cCallbacks & a_Callbacks, double a_StartX, double a_StartY, double a_StartZ, double a_EndX, double a_EndY, double a_EndZ);
|
||||
|
||||
/** Traces one line between Start and End; returns true if the entire line was traced (until OnNoMoreHits()) */
|
||||
static bool Trace(cWorld & a_World, cCallbacks & a_Callbacks, const Vector3d & a_Start, const Vector3d & a_End);
|
||||
static bool Trace(cWorld & a_World, cCallbacks & a_Callbacks, const Vector3d a_Start, const Vector3d a_End);
|
||||
|
||||
/** Returns true if the two positions are within line of sight (not obscured by blocks).
|
||||
a_Sight specifies which blocks are considered transparent for the trace, is an OR-combination of eLineOfSight constants. */
|
||||
@ -75,19 +73,19 @@ public:
|
||||
|
||||
protected:
|
||||
/** The start point of the trace */
|
||||
double m_StartX, m_StartY, m_StartZ;
|
||||
Vector3d m_Start;
|
||||
|
||||
/** The end point of the trace */
|
||||
double m_EndX, m_EndY, m_EndZ;
|
||||
Vector3d m_End;
|
||||
|
||||
/** The difference in coords, End - Start */
|
||||
double m_DiffX, m_DiffY, m_DiffZ;
|
||||
Vector3d m_Diff;
|
||||
|
||||
/** The increment at which the block coords are going from Start to End; either +1 or -1 */
|
||||
int m_DirX, m_DirY, m_DirZ;
|
||||
Vector3i m_Dir;
|
||||
|
||||
/** The current block */
|
||||
int m_CurrentX, m_CurrentY, m_CurrentZ;
|
||||
Vector3i m_Current;
|
||||
|
||||
/** The face through which the current block has been entered */
|
||||
eBlockFace m_CurrentFace;
|
||||
@ -110,5 +108,3 @@ protected:
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user