Merge pull request #3416 from cuberite/JsonSerializerErrorReport
LuaJson: Report serialization errors instead of crashing.
This commit is contained in:
commit
733401ec5f
@ -9476,7 +9476,7 @@ end
|
|||||||
Type = "string",
|
Type = "string",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Notes = "Serializes the input table into a Json string. The options table, if present, is used to adjust the formatting of the serialized string, see below for details.",
|
Notes = "Serializes the input table into a Json string. The options table, if present, is used to adjust the formatting of the serialized string, see below for details. <br/>Returns nil and error message if the table cannot be serialized (eg. contains both an array part and a dictionary part).",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
AdditionalInfo =
|
AdditionalInfo =
|
||||||
|
@ -15,7 +15,7 @@ function Initialize(a_Plugin)
|
|||||||
cPluginManager.AddHook(cPluginManager.HOOK_TICK, OnTick1);
|
cPluginManager.AddHook(cPluginManager.HOOK_TICK, OnTick1);
|
||||||
cPluginManager.AddHook(cPluginManager.HOOK_TICK, OnTick2);
|
cPluginManager.AddHook(cPluginManager.HOOK_TICK, OnTick2);
|
||||||
--]]
|
--]]
|
||||||
|
|
||||||
local PM = cPluginManager;
|
local PM = cPluginManager;
|
||||||
PM:AddHook(cPluginManager.HOOK_PLAYER_USING_BLOCK, OnPlayerUsingBlock);
|
PM:AddHook(cPluginManager.HOOK_PLAYER_USING_BLOCK, OnPlayerUsingBlock);
|
||||||
PM:AddHook(cPluginManager.HOOK_PLAYER_USING_ITEM, OnPlayerUsingItem);
|
PM:AddHook(cPluginManager.HOOK_PLAYER_USING_ITEM, OnPlayerUsingItem);
|
||||||
@ -38,24 +38,24 @@ function Initialize(a_Plugin)
|
|||||||
|
|
||||||
-- Load the InfoReg shared library:
|
-- Load the InfoReg shared library:
|
||||||
dofile(cPluginManager:GetPluginsPath() .. "/InfoReg.lua")
|
dofile(cPluginManager:GetPluginsPath() .. "/InfoReg.lua")
|
||||||
|
|
||||||
-- Bind all the commands:
|
-- Bind all the commands:
|
||||||
RegisterPluginInfoCommands();
|
RegisterPluginInfoCommands();
|
||||||
|
|
||||||
-- Bind all the console commands:
|
-- Bind all the console commands:
|
||||||
RegisterPluginInfoConsoleCommands();
|
RegisterPluginInfoConsoleCommands();
|
||||||
|
|
||||||
a_Plugin:AddWebTab("Debuggers", HandleRequest_Debuggers)
|
a_Plugin:AddWebTab("Debuggers", HandleRequest_Debuggers)
|
||||||
a_Plugin:AddWebTab("StressTest", HandleRequest_StressTest)
|
a_Plugin:AddWebTab("StressTest", HandleRequest_StressTest)
|
||||||
|
|
||||||
-- Enable the following line for BlockArea / Generator interface testing:
|
-- Enable the following line for BlockArea / Generator interface testing:
|
||||||
-- PluginManager:AddHook(Plugin, cPluginManager.HOOK_CHUNK_GENERATED);
|
-- PluginManager:AddHook(Plugin, cPluginManager.HOOK_CHUNK_GENERATED);
|
||||||
|
|
||||||
-- TestBlockAreas()
|
-- TestBlockAreas()
|
||||||
-- TestSQLiteBindings()
|
-- TestSQLiteBindings()
|
||||||
-- TestExpatBindings()
|
-- TestExpatBindings()
|
||||||
TestPluginCalls()
|
TestPluginCalls()
|
||||||
|
|
||||||
TestBlockAreasString()
|
TestBlockAreasString()
|
||||||
TestStringBase64()
|
TestStringBase64()
|
||||||
-- TestUUIDFromName()
|
-- TestUUIDFromName()
|
||||||
@ -63,7 +63,7 @@ function Initialize(a_Plugin)
|
|||||||
TestFileExt()
|
TestFileExt()
|
||||||
-- TestFileLastMod()
|
-- TestFileLastMod()
|
||||||
TestPluginInterface()
|
TestPluginInterface()
|
||||||
|
|
||||||
local LastSelfMod = cFile:GetLastModificationTime(a_Plugin:GetLocalFolder() .. "/Debuggers.lua")
|
local LastSelfMod = cFile:GetLastModificationTime(a_Plugin:GetLocalFolder() .. "/Debuggers.lua")
|
||||||
LOG("Debuggers.lua last modified on " .. os.date("%Y-%m-%dT%H:%M:%S", LastSelfMod))
|
LOG("Debuggers.lua last modified on " .. os.date("%Y-%m-%dT%H:%M:%S", LastSelfMod))
|
||||||
|
|
||||||
@ -75,7 +75,7 @@ function Initialize(a_Plugin)
|
|||||||
:SetMessageType(mtInfo)
|
:SetMessageType(mtInfo)
|
||||||
)
|
)
|
||||||
--]]
|
--]]
|
||||||
|
|
||||||
-- Test the crash in #1889:
|
-- Test the crash in #1889:
|
||||||
cPluginManager:AddHook(cPluginManager.HOOK_PLAYER_RIGHT_CLICKING_ENTITY,
|
cPluginManager:AddHook(cPluginManager.HOOK_PLAYER_RIGHT_CLICKING_ENTITY,
|
||||||
function (a_CBPlayer, a_CBEntity)
|
function (a_CBPlayer, a_CBEntity)
|
||||||
@ -87,7 +87,7 @@ function Initialize(a_Plugin)
|
|||||||
)
|
)
|
||||||
end
|
end
|
||||||
)
|
)
|
||||||
|
|
||||||
return true
|
return true
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -105,7 +105,7 @@ function TestPluginInterface()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
)
|
)
|
||||||
|
|
||||||
cPluginManager:ForEachPlugin(
|
cPluginManager:ForEachPlugin(
|
||||||
function (a_CBPlugin)
|
function (a_CBPlugin)
|
||||||
LOG("Plugin in " .. a_CBPlugin:GetFolderName() .. " has an API name of " .. a_CBPlugin:GetName() .. " and status " .. a_CBPlugin:GetStatus())
|
LOG("Plugin in " .. a_CBPlugin:GetFolderName() .. " has an API name of " .. a_CBPlugin:GetName() .. " and status " .. a_CBPlugin:GetStatus())
|
||||||
@ -156,7 +156,7 @@ function TestPluginCalls()
|
|||||||
-- Note the signature: function ReturnColorFromChar( Split, char ) ... return cChatColog.Gray ... end
|
-- Note the signature: function ReturnColorFromChar( Split, char ) ... return cChatColog.Gray ... end
|
||||||
-- The Split parameter should be a table, but it is not used in that function anyway,
|
-- The Split parameter should be a table, but it is not used in that function anyway,
|
||||||
-- so we can get away with passing nil to it.
|
-- so we can get away with passing nil to it.
|
||||||
|
|
||||||
LOG("Debuggers: Calling NoSuchPlugin.FnName()...")
|
LOG("Debuggers: Calling NoSuchPlugin.FnName()...")
|
||||||
cPluginManager:CallPlugin("NoSuchPlugin", "FnName", "SomeParam")
|
cPluginManager:CallPlugin("NoSuchPlugin", "FnName", "SomeParam")
|
||||||
LOG("Debuggers: Calling Core.NoSuchFunction()...")
|
LOG("Debuggers: Calling Core.NoSuchFunction()...")
|
||||||
@ -177,7 +177,7 @@ end
|
|||||||
|
|
||||||
function TestBlockAreas()
|
function TestBlockAreas()
|
||||||
LOG("Testing block areas...");
|
LOG("Testing block areas...");
|
||||||
|
|
||||||
-- Debug block area merging:
|
-- Debug block area merging:
|
||||||
local BA1 = cBlockArea();
|
local BA1 = cBlockArea();
|
||||||
local BA2 = cBlockArea();
|
local BA2 = cBlockArea();
|
||||||
@ -192,7 +192,7 @@ function TestBlockAreas()
|
|||||||
else
|
else
|
||||||
BA1:Create(16, 16, 16);
|
BA1:Create(16, 16, 16);
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Debug block area cuboid filling:
|
-- Debug block area cuboid filling:
|
||||||
BA1:FillRelCuboid(2, 9, 2, 8, 2, 8, cBlockArea.baTypes, E_BLOCK_GOLD_BLOCK);
|
BA1:FillRelCuboid(2, 9, 2, 8, 2, 8, cBlockArea.baTypes, E_BLOCK_GOLD_BLOCK);
|
||||||
BA1:RelLine(2, 2, 2, 9, 8, 8, cBlockArea.baTypes or cBlockArea.baMetas, E_BLOCK_SAPLING, E_META_SAPLING_BIRCH);
|
BA1:RelLine(2, 2, 2, 9, 8, 8, cBlockArea.baTypes or cBlockArea.baMetas, E_BLOCK_SAPLING, E_META_SAPLING_BIRCH);
|
||||||
@ -204,18 +204,18 @@ function TestBlockAreas()
|
|||||||
BA1:SaveToSchematicFile("schematics/lt_XY.schematic");
|
BA1:SaveToSchematicFile("schematics/lt_XY.schematic");
|
||||||
BA1:MirrorXYNoMeta();
|
BA1:MirrorXYNoMeta();
|
||||||
BA1:SaveToSchematicFile("schematics/lt_XY2.schematic");
|
BA1:SaveToSchematicFile("schematics/lt_XY2.schematic");
|
||||||
|
|
||||||
BA1:MirrorXZNoMeta();
|
BA1:MirrorXZNoMeta();
|
||||||
BA1:SaveToSchematicFile("schematics/lt_XZ.schematic");
|
BA1:SaveToSchematicFile("schematics/lt_XZ.schematic");
|
||||||
BA1:MirrorXZNoMeta();
|
BA1:MirrorXZNoMeta();
|
||||||
BA1:SaveToSchematicFile("schematics/lt_XZ2.schematic");
|
BA1:SaveToSchematicFile("schematics/lt_XZ2.schematic");
|
||||||
|
|
||||||
BA1:MirrorYZNoMeta();
|
BA1:MirrorYZNoMeta();
|
||||||
BA1:SaveToSchematicFile("schematics/lt_YZ.schematic");
|
BA1:SaveToSchematicFile("schematics/lt_YZ.schematic");
|
||||||
BA1:MirrorYZNoMeta();
|
BA1:MirrorYZNoMeta();
|
||||||
BA1:SaveToSchematicFile("schematics/lt_YZ2.schematic");
|
BA1:SaveToSchematicFile("schematics/lt_YZ2.schematic");
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Debug block area rotation:
|
-- Debug block area rotation:
|
||||||
if (BA1:LoadFromSchematicFile("schematics/rot.schematic")) then
|
if (BA1:LoadFromSchematicFile("schematics/rot.schematic")) then
|
||||||
BA1:RotateCWNoMeta();
|
BA1:RotateCWNoMeta();
|
||||||
@ -246,23 +246,23 @@ function TestBlockAreas()
|
|||||||
BA1:SaveToSchematicFile("schematics/ltm_XY.schematic");
|
BA1:SaveToSchematicFile("schematics/ltm_XY.schematic");
|
||||||
BA1:MirrorXY();
|
BA1:MirrorXY();
|
||||||
BA1:SaveToSchematicFile("schematics/ltm_XY2.schematic");
|
BA1:SaveToSchematicFile("schematics/ltm_XY2.schematic");
|
||||||
|
|
||||||
BA1:MirrorXZ();
|
BA1:MirrorXZ();
|
||||||
BA1:SaveToSchematicFile("schematics/ltm_XZ.schematic");
|
BA1:SaveToSchematicFile("schematics/ltm_XZ.schematic");
|
||||||
BA1:MirrorXZ();
|
BA1:MirrorXZ();
|
||||||
BA1:SaveToSchematicFile("schematics/ltm_XZ2.schematic");
|
BA1:SaveToSchematicFile("schematics/ltm_XZ2.schematic");
|
||||||
|
|
||||||
BA1:MirrorYZ();
|
BA1:MirrorYZ();
|
||||||
BA1:SaveToSchematicFile("schematics/ltm_YZ.schematic");
|
BA1:SaveToSchematicFile("schematics/ltm_YZ.schematic");
|
||||||
BA1:MirrorYZ();
|
BA1:MirrorYZ();
|
||||||
BA1:SaveToSchematicFile("schematics/ltm_YZ2.schematic");
|
BA1:SaveToSchematicFile("schematics/ltm_YZ2.schematic");
|
||||||
end
|
end
|
||||||
|
|
||||||
LOG("Block areas test ended");
|
LOG("Block areas test ended");
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -281,7 +281,7 @@ function TestBlockAreasString()
|
|||||||
local f = io.open("schematics/StringTest.schematic", "wb")
|
local f = io.open("schematics/StringTest.schematic", "wb")
|
||||||
f:write(Data)
|
f:write(Data)
|
||||||
f:close()
|
f:close()
|
||||||
|
|
||||||
-- Load a second area from that file:
|
-- Load a second area from that file:
|
||||||
local BA2 = cBlockArea()
|
local BA2 = cBlockArea()
|
||||||
if not(BA2:LoadFromSchematicFile("schematics/StringTest.schematic")) then
|
if not(BA2:LoadFromSchematicFile("schematics/StringTest.schematic")) then
|
||||||
@ -289,7 +289,7 @@ function TestBlockAreasString()
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
BA2:Clear()
|
BA2:Clear()
|
||||||
|
|
||||||
-- Load another area from a string in that file:
|
-- Load another area from a string in that file:
|
||||||
f = io.open("schematics/StringTest.schematic", "rb")
|
f = io.open("schematics/StringTest.schematic", "rb")
|
||||||
Data = f:read("*all")
|
Data = f:read("*all")
|
||||||
@ -308,11 +308,11 @@ function TestStringBase64()
|
|||||||
for i = 0, 255 do
|
for i = 0, 255 do
|
||||||
s = s .. string.char(i)
|
s = s .. string.char(i)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Roundtrip through Base64:
|
-- Roundtrip through Base64:
|
||||||
local Base64 = Base64Encode(s)
|
local Base64 = Base64Encode(s)
|
||||||
local UnBase64 = Base64Decode(Base64)
|
local UnBase64 = Base64Decode(Base64)
|
||||||
|
|
||||||
assert(UnBase64 == s)
|
assert(UnBase64 == s)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -322,7 +322,7 @@ end
|
|||||||
|
|
||||||
function TestUUIDFromName()
|
function TestUUIDFromName()
|
||||||
LOG("Testing UUID-from-Name resolution...")
|
LOG("Testing UUID-from-Name resolution...")
|
||||||
|
|
||||||
-- Test by querying a few existing names, along with a non-existent one:
|
-- Test by querying a few existing names, along with a non-existent one:
|
||||||
local PlayerNames =
|
local PlayerNames =
|
||||||
{
|
{
|
||||||
@ -332,7 +332,7 @@ function TestUUIDFromName()
|
|||||||
}
|
}
|
||||||
-- WARNING: Blocking operation! DO NOT USE IN TICK THREAD!
|
-- WARNING: Blocking operation! DO NOT USE IN TICK THREAD!
|
||||||
local UUIDs = cMojangAPI:GetUUIDsFromPlayerNames(PlayerNames)
|
local UUIDs = cMojangAPI:GetUUIDsFromPlayerNames(PlayerNames)
|
||||||
|
|
||||||
-- Log the results:
|
-- Log the results:
|
||||||
for _, name in ipairs(PlayerNames) do
|
for _, name in ipairs(PlayerNames) do
|
||||||
local UUID = UUIDs[name]
|
local UUID = UUIDs[name]
|
||||||
@ -342,7 +342,7 @@ function TestUUIDFromName()
|
|||||||
LOG(" UUID(" .. name .. ") = \"" .. UUID .. "\"")
|
LOG(" UUID(" .. name .. ") = \"" .. UUID .. "\"")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Test once more with the same players, valid-only. This should go directly from cache, so fast.
|
-- Test once more with the same players, valid-only. This should go directly from cache, so fast.
|
||||||
LOG("Testing again with the same valid players...")
|
LOG("Testing again with the same valid players...")
|
||||||
local ValidPlayerNames =
|
local ValidPlayerNames =
|
||||||
@ -371,7 +371,7 @@ function TestUUIDFromName()
|
|||||||
"notch", -- Valid player name, but not cached (most likely :)
|
"notch", -- Valid player name, but not cached (most likely :)
|
||||||
}
|
}
|
||||||
UUIDs = cMojangAPI:GetUUIDsFromPlayerNames(PlayerNames3, true)
|
UUIDs = cMojangAPI:GetUUIDsFromPlayerNames(PlayerNames3, true)
|
||||||
|
|
||||||
-- Log the results:
|
-- Log the results:
|
||||||
for _, name in ipairs(PlayerNames3) do
|
for _, name in ipairs(PlayerNames3) do
|
||||||
local UUID = UUIDs[name]
|
local UUID = UUIDs[name]
|
||||||
@ -383,7 +383,7 @@ function TestUUIDFromName()
|
|||||||
end
|
end
|
||||||
|
|
||||||
LOG("UUID-from-Name resolution tests finished.")
|
LOG("UUID-from-Name resolution tests finished.")
|
||||||
|
|
||||||
LOG("Performing a Name-from-UUID test...")
|
LOG("Performing a Name-from-UUID test...")
|
||||||
-- local NameToTest = "aloe_vera"
|
-- local NameToTest = "aloe_vera"
|
||||||
local NameToTest = "xoft"
|
local NameToTest = "xoft"
|
||||||
@ -410,7 +410,7 @@ end
|
|||||||
|
|
||||||
function TestSQLiteBindings()
|
function TestSQLiteBindings()
|
||||||
LOG("Testing SQLite bindings...");
|
LOG("Testing SQLite bindings...");
|
||||||
|
|
||||||
-- Debug SQLite binding
|
-- Debug SQLite binding
|
||||||
local TestDB, ErrCode, ErrMsg = sqlite3.open("test.sqlite");
|
local TestDB, ErrCode, ErrMsg = sqlite3.open("test.sqlite");
|
||||||
if (TestDB ~= nil) then
|
if (TestDB ~= nil) then
|
||||||
@ -439,7 +439,7 @@ function TestSQLiteBindings()
|
|||||||
-- This happens if for example SQLite cannot open the file (eg. a folder with the same name exists)
|
-- This happens if for example SQLite cannot open the file (eg. a folder with the same name exists)
|
||||||
LOG("SQLite3 failed to open DB! (" .. ErrCode .. ", " .. ErrMsg ..")");
|
LOG("SQLite3 failed to open DB! (" .. ErrCode .. ", " .. ErrMsg ..")");
|
||||||
end
|
end
|
||||||
|
|
||||||
LOG("SQLite bindings test ended");
|
LOG("SQLite bindings test ended");
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -449,7 +449,7 @@ end
|
|||||||
|
|
||||||
function TestExpatBindings()
|
function TestExpatBindings()
|
||||||
LOG("Testing Expat bindings...");
|
LOG("Testing Expat bindings...");
|
||||||
|
|
||||||
-- Debug LuaExpat bindings:
|
-- Debug LuaExpat bindings:
|
||||||
local count = 0
|
local count = 0
|
||||||
callbacks = {
|
callbacks = {
|
||||||
@ -472,7 +472,7 @@ function TestExpatBindings()
|
|||||||
p:parse("\n");
|
p:parse("\n");
|
||||||
p:parse(); -- finishes the document
|
p:parse(); -- finishes the document
|
||||||
p:close(); -- closes the parser
|
p:close(); -- closes the parser
|
||||||
|
|
||||||
LOG("Expat bindings test ended");
|
LOG("Expat bindings test ended");
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -490,7 +490,7 @@ function OnUsingBlazeRod(Player, BlockX, BlockY, BlockZ, BlockFace, CursorX, Cur
|
|||||||
local TempItem = cItem(Type, 1, Meta);
|
local TempItem = cItem(Type, 1, Meta);
|
||||||
Player:SendMessage(cChatColor.LightGray .. "Block {" .. BlockX .. ", " .. BlockY .. ", " .. BlockZ .. "}: " .. ItemToFullString(TempItem) .. " (" .. Type .. ":" .. Meta .. ")");
|
Player:SendMessage(cChatColor.LightGray .. "Block {" .. BlockX .. ", " .. BlockY .. ", " .. BlockZ .. "}: " .. ItemToFullString(TempItem) .. " (" .. Type .. ":" .. Meta .. ")");
|
||||||
end
|
end
|
||||||
|
|
||||||
local X, Y, Z = AddFaceDirection(BlockX, BlockY, BlockZ, BlockFace);
|
local X, Y, Z = AddFaceDirection(BlockX, BlockY, BlockZ, BlockFace);
|
||||||
Valid, Type, Meta = Player:GetWorld():GetBlockTypeMeta(X, Y, Z);
|
Valid, Type, Meta = Player:GetWorld():GetBlockTypeMeta(X, Y, Z);
|
||||||
if (Type == E_BLOCK_AIR) then
|
if (Type == E_BLOCK_AIR) then
|
||||||
@ -517,27 +517,27 @@ function OnUsingDiamond(Player, BlockX, BlockY, BlockZ, BlockFace, CursorX, Curs
|
|||||||
|
|
||||||
LOG("Size before cropping: " .. Area:GetSizeX() .. " x " .. Area:GetSizeY() .. " x " .. Area:GetSizeZ());
|
LOG("Size before cropping: " .. Area:GetSizeX() .. " x " .. Area:GetSizeY() .. " x " .. Area:GetSizeZ());
|
||||||
Area:DumpToRawFile("crop0.dat");
|
Area:DumpToRawFile("crop0.dat");
|
||||||
|
|
||||||
Area:Crop(2, 3, 0, 0, 0, 0);
|
Area:Crop(2, 3, 0, 0, 0, 0);
|
||||||
LOG("Size after cropping 1: " .. Area:GetSizeX() .. " x " .. Area:GetSizeY() .. " x " .. Area:GetSizeZ());
|
LOG("Size after cropping 1: " .. Area:GetSizeX() .. " x " .. Area:GetSizeY() .. " x " .. Area:GetSizeZ());
|
||||||
Area:DumpToRawFile("crop1.dat");
|
Area:DumpToRawFile("crop1.dat");
|
||||||
|
|
||||||
Area:Crop(2, 3, 0, 0, 0, 0);
|
Area:Crop(2, 3, 0, 0, 0, 0);
|
||||||
LOG("Size after cropping 2: " .. Area:GetSizeX() .. " x " .. Area:GetSizeY() .. " x " .. Area:GetSizeZ());
|
LOG("Size after cropping 2: " .. Area:GetSizeX() .. " x " .. Area:GetSizeY() .. " x " .. Area:GetSizeZ());
|
||||||
Area:DumpToRawFile("crop2.dat");
|
Area:DumpToRawFile("crop2.dat");
|
||||||
|
|
||||||
Area:Expand(2, 3, 0, 0, 0, 0);
|
Area:Expand(2, 3, 0, 0, 0, 0);
|
||||||
LOG("Size after expanding 1: " .. Area:GetSizeX() .. " x " .. Area:GetSizeY() .. " x " .. Area:GetSizeZ());
|
LOG("Size after expanding 1: " .. Area:GetSizeX() .. " x " .. Area:GetSizeY() .. " x " .. Area:GetSizeZ());
|
||||||
Area:DumpToRawFile("expand1.dat");
|
Area:DumpToRawFile("expand1.dat");
|
||||||
|
|
||||||
Area:Expand(3, 2, 1, 1, 0, 0);
|
Area:Expand(3, 2, 1, 1, 0, 0);
|
||||||
LOG("Size after expanding 2: " .. Area:GetSizeX() .. " x " .. Area:GetSizeY() .. " x " .. Area:GetSizeZ());
|
LOG("Size after expanding 2: " .. Area:GetSizeX() .. " x " .. Area:GetSizeY() .. " x " .. Area:GetSizeZ());
|
||||||
Area:DumpToRawFile("expand2.dat");
|
Area:DumpToRawFile("expand2.dat");
|
||||||
|
|
||||||
Area:Crop(0, 0, 0, 0, 3, 2);
|
Area:Crop(0, 0, 0, 0, 3, 2);
|
||||||
LOG("Size after cropping 3: " .. Area:GetSizeX() .. " x " .. Area:GetSizeY() .. " x " .. Area:GetSizeZ());
|
LOG("Size after cropping 3: " .. Area:GetSizeX() .. " x " .. Area:GetSizeY() .. " x " .. Area:GetSizeZ());
|
||||||
Area:DumpToRawFile("crop3.dat");
|
Area:DumpToRawFile("crop3.dat");
|
||||||
|
|
||||||
Area:Crop(0, 0, 3, 2, 0, 0);
|
Area:Crop(0, 0, 3, 2, 0, 0);
|
||||||
LOG("Size after cropping 4: " .. Area:GetSizeX() .. " x " .. Area:GetSizeY() .. " x " .. Area:GetSizeZ());
|
LOG("Size after cropping 4: " .. Area:GetSizeX() .. " x " .. Area:GetSizeY() .. " x " .. Area:GetSizeZ());
|
||||||
Area:DumpToRawFile("crop4.dat");
|
Area:DumpToRawFile("crop4.dat");
|
||||||
@ -571,7 +571,7 @@ end
|
|||||||
function OnUsingEnderPearl(Player, BlockX, BlockY, BlockZ, BlockFace, CursorX, CursorY, CursorZ)
|
function OnUsingEnderPearl(Player, BlockX, BlockY, BlockZ, BlockFace, CursorX, CursorY, CursorZ)
|
||||||
-- Rclk with an ender pearl saves a predefined area around the cursor into a .schematic file. Also tests area copying
|
-- Rclk with an ender pearl saves a predefined area around the cursor into a .schematic file. Also tests area copying
|
||||||
local Area = cBlockArea();
|
local Area = cBlockArea();
|
||||||
if not(Area:Read(Player:GetWorld(),
|
if not(Area:Read(Player:GetWorld(),
|
||||||
BlockX - 8, BlockX + 8, BlockY - 8, BlockY + 8, BlockZ - 8, BlockZ + 8)
|
BlockX - 8, BlockX + 8, BlockY - 8, BlockY + 8, BlockZ - 8, BlockZ + 8)
|
||||||
) then
|
) then
|
||||||
LOG("LUA: Area couldn't be read");
|
LOG("LUA: Area couldn't be read");
|
||||||
@ -717,14 +717,14 @@ function OnTick()
|
|||||||
table.remove(g_DropSpensersToActivate, i);
|
table.remove(g_DropSpensersToActivate, i);
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-- If GCOnTick > 0, do a garbage-collect and decrease by one
|
-- If GCOnTick > 0, do a garbage-collect and decrease by one
|
||||||
if (GCOnTick > 0) then
|
if (GCOnTick > 0) then
|
||||||
collectgarbage();
|
collectgarbage();
|
||||||
GCOnTick = GCOnTick - 1;
|
GCOnTick = GCOnTick - 1;
|
||||||
end
|
end
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -741,8 +741,8 @@ function OnWorldTick(a_World, a_Dt)
|
|||||||
a_World:ForEachPlayer(
|
a_World:ForEachPlayer(
|
||||||
function(a_Player)
|
function(a_Player)
|
||||||
a_Player:SendMessage(
|
a_Player:SendMessage(
|
||||||
tostring(Tick / 10) ..
|
tostring(Tick / 10) ..
|
||||||
" > FS: fl " .. a_Player:GetFoodLevel() ..
|
" > FS: fl " .. a_Player:GetFoodLevel() ..
|
||||||
"; sat " .. a_Player:GetFoodSaturationLevel() ..
|
"; sat " .. a_Player:GetFoodSaturationLevel() ..
|
||||||
"; exh " .. a_Player:GetFoodExhaustionLevel()
|
"; exh " .. a_Player:GetFoodExhaustionLevel()
|
||||||
);
|
);
|
||||||
@ -782,7 +782,7 @@ end
|
|||||||
function OnChunkGenerated(a_World, a_ChunkX, a_ChunkZ, a_ChunkDesc)
|
function OnChunkGenerated(a_World, a_ChunkX, a_ChunkZ, a_ChunkDesc)
|
||||||
-- Get the topmost block coord:
|
-- Get the topmost block coord:
|
||||||
local Height = a_ChunkDesc:GetHeight(0, 0);
|
local Height = a_ChunkDesc:GetHeight(0, 0);
|
||||||
|
|
||||||
-- Create a sign there:
|
-- Create a sign there:
|
||||||
a_ChunkDesc:SetBlockTypeMeta(0, Height + 1, 0, E_BLOCK_SIGN_POST, 0);
|
a_ChunkDesc:SetBlockTypeMeta(0, Height + 1, 0, E_BLOCK_SIGN_POST, 0);
|
||||||
local BlockEntity = a_ChunkDesc:GetBlockEntity(0, Height + 1, 0);
|
local BlockEntity = a_ChunkDesc:GetBlockEntity(0, Height + 1, 0);
|
||||||
@ -827,7 +827,7 @@ end
|
|||||||
|
|
||||||
function HandleListEntitiesCmd(Split, Player)
|
function HandleListEntitiesCmd(Split, Player)
|
||||||
local NumEntities = 0;
|
local NumEntities = 0;
|
||||||
|
|
||||||
local ListEntity = function(Entity)
|
local ListEntity = function(Entity)
|
||||||
if (Entity:IsDestroyed()) then
|
if (Entity:IsDestroyed()) then
|
||||||
-- The entity has already been destroyed, don't list it
|
-- The entity has already been destroyed, don't list it
|
||||||
@ -842,7 +842,7 @@ function HandleListEntitiesCmd(Split, Player)
|
|||||||
end
|
end
|
||||||
NumEntities = NumEntities + 1;
|
NumEntities = NumEntities + 1;
|
||||||
end
|
end
|
||||||
|
|
||||||
Player:SendMessage("Listing all entities...");
|
Player:SendMessage("Listing all entities...");
|
||||||
Player:GetWorld():ForEachEntity(ListEntity);
|
Player:GetWorld():ForEachEntity(ListEntity);
|
||||||
Player:SendMessage("List finished, " .. NumEntities .. " entities listed");
|
Player:SendMessage("List finished, " .. NumEntities .. " entities listed");
|
||||||
@ -855,7 +855,7 @@ end
|
|||||||
|
|
||||||
function HandleKillEntitiesCmd(Split, Player)
|
function HandleKillEntitiesCmd(Split, Player)
|
||||||
local NumEntities = 0;
|
local NumEntities = 0;
|
||||||
|
|
||||||
local KillEntity = function(Entity)
|
local KillEntity = function(Entity)
|
||||||
-- kill everything except for players:
|
-- kill everything except for players:
|
||||||
if (Entity:GetEntityType() ~= cEntity.etPlayer) then
|
if (Entity:GetEntityType() ~= cEntity.etPlayer) then
|
||||||
@ -863,7 +863,7 @@ function HandleKillEntitiesCmd(Split, Player)
|
|||||||
NumEntities = NumEntities + 1;
|
NumEntities = NumEntities + 1;
|
||||||
end;
|
end;
|
||||||
end
|
end
|
||||||
|
|
||||||
Player:SendMessage("Killing all entities...");
|
Player:SendMessage("Killing all entities...");
|
||||||
Player:GetWorld():ForEachEntity(KillEntity);
|
Player:GetWorld():ForEachEntity(KillEntity);
|
||||||
Player:SendMessage("Killed " .. NumEntities .. " entities.");
|
Player:SendMessage("Killed " .. NumEntities .. " entities.");
|
||||||
@ -900,7 +900,7 @@ function HandleTestWndCmd(a_Split, a_Player)
|
|||||||
a_Player:SendMessage("Usage: /testwnd [WindowType WindowSizeX WindowSizeY]");
|
a_Player:SendMessage("Usage: /testwnd [WindowType WindowSizeX WindowSizeY]");
|
||||||
return true;
|
return true;
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Test out the OnClosing callback's ability to refuse to close the window
|
-- Test out the OnClosing callback's ability to refuse to close the window
|
||||||
local attempt = 1;
|
local attempt = 1;
|
||||||
local OnClosing = function(Window, Player, CanRefuse)
|
local OnClosing = function(Window, Player, CanRefuse)
|
||||||
@ -908,12 +908,12 @@ function HandleTestWndCmd(a_Split, a_Player)
|
|||||||
attempt = attempt + 1;
|
attempt = attempt + 1;
|
||||||
return CanRefuse and (attempt <= 3); -- refuse twice, then allow, unless CanRefuse is set to true
|
return CanRefuse and (attempt <= 3); -- refuse twice, then allow, unless CanRefuse is set to true
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Log the slot changes
|
-- Log the slot changes
|
||||||
local OnSlotChanged = function(Window, SlotNum)
|
local OnSlotChanged = function(Window, SlotNum)
|
||||||
LOG("Window \"" .. Window:GetWindowTitle() .. "\" slot " .. SlotNum .. " changed.");
|
LOG("Window \"" .. Window:GetWindowTitle() .. "\" slot " .. SlotNum .. " changed.");
|
||||||
end
|
end
|
||||||
|
|
||||||
local Window = cLuaWindow(WindowType, WindowSizeX, WindowSizeY, "TestWnd");
|
local Window = cLuaWindow(WindowType, WindowSizeX, WindowSizeY, "TestWnd");
|
||||||
local Item2 = cItem(E_ITEM_DIAMOND_SWORD, 1, 0, "1=1");
|
local Item2 = cItem(E_ITEM_DIAMOND_SWORD, 1, 0, "1=1");
|
||||||
local Item3 = cItem(E_ITEM_DIAMOND_SHOVEL);
|
local Item3 = cItem(E_ITEM_DIAMOND_SHOVEL);
|
||||||
@ -929,13 +929,13 @@ function HandleTestWndCmd(a_Split, a_Player)
|
|||||||
Window:SetSlot(a_Player, 4, Item5);
|
Window:SetSlot(a_Player, 4, Item5);
|
||||||
Window:SetOnClosing(OnClosing);
|
Window:SetOnClosing(OnClosing);
|
||||||
Window:SetOnSlotChanged(OnSlotChanged);
|
Window:SetOnSlotChanged(OnSlotChanged);
|
||||||
|
|
||||||
a_Player:OpenWindow(Window);
|
a_Player:OpenWindow(Window);
|
||||||
|
|
||||||
-- To make sure that the object has the correct life-management in Lua,
|
-- To make sure that the object has the correct life-management in Lua,
|
||||||
-- let's garbage-collect in the following few ticks
|
-- let's garbage-collect in the following few ticks
|
||||||
GCOnTick = 10;
|
GCOnTick = 10;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -1024,12 +1024,12 @@ function HandleFoodLevelCmd(a_Split, a_Player)
|
|||||||
a_Player:SendMessage("Missing an argument: the food level to set");
|
a_Player:SendMessage("Missing an argument: the food level to set");
|
||||||
return true;
|
return true;
|
||||||
end
|
end
|
||||||
|
|
||||||
a_Player:SetFoodLevel(tonumber(a_Split[2]));
|
a_Player:SetFoodLevel(tonumber(a_Split[2]));
|
||||||
a_Player:SetFoodSaturationLevel(5);
|
a_Player:SetFoodSaturationLevel(5);
|
||||||
a_Player:SetFoodExhaustionLevel(0);
|
a_Player:SetFoodExhaustionLevel(0);
|
||||||
a_Player:SendMessage(
|
a_Player:SendMessage(
|
||||||
"Food level set to " .. a_Player:GetFoodLevel() ..
|
"Food level set to " .. a_Player:GetFoodLevel() ..
|
||||||
", saturation reset to " .. a_Player:GetFoodSaturationLevel() ..
|
", saturation reset to " .. a_Player:GetFoodSaturationLevel() ..
|
||||||
" and exhaustion reset to " .. a_Player:GetFoodExhaustionLevel()
|
" and exhaustion reset to " .. a_Player:GetFoodExhaustionLevel()
|
||||||
);
|
);
|
||||||
@ -1053,17 +1053,17 @@ function HandleSpideyCmd(a_Split, a_Player)
|
|||||||
World:SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_COBWEB, 0);
|
World:SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_COBWEB, 0);
|
||||||
end
|
end
|
||||||
};
|
};
|
||||||
|
|
||||||
local EyePos = a_Player:GetEyePosition();
|
local EyePos = a_Player:GetEyePosition();
|
||||||
local LookVector = a_Player:GetLookVector();
|
local LookVector = a_Player:GetLookVector();
|
||||||
LookVector:Normalize();
|
LookVector:Normalize();
|
||||||
|
|
||||||
-- Start cca 2 blocks away from the eyes
|
-- Start cca 2 blocks away from the eyes
|
||||||
local Start = EyePos + LookVector + LookVector;
|
local Start = EyePos + LookVector + LookVector;
|
||||||
local End = EyePos + LookVector * 50;
|
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.x, Start.y, Start.z, End.x, End.y, End.z);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -1099,7 +1099,7 @@ function HandleArrowCmd(a_Split, a_Player)
|
|||||||
local Speed = a_Player:GetLookVector();
|
local Speed = a_Player:GetLookVector();
|
||||||
Speed:Normalize();
|
Speed:Normalize();
|
||||||
Pos = Pos + Speed;
|
Pos = Pos + Speed;
|
||||||
|
|
||||||
World:CreateProjectile(Pos.x, Pos.y, Pos.z, cProjectileEntity.pkArrow, a_Player, Speed * 10);
|
World:CreateProjectile(Pos.x, Pos.y, Pos.z, cProjectileEntity.pkArrow, a_Player, Speed * 10);
|
||||||
return true;
|
return true;
|
||||||
end
|
end
|
||||||
@ -1114,7 +1114,7 @@ function HandleFireballCmd(a_Split, a_Player)
|
|||||||
local Speed = a_Player:GetLookVector();
|
local Speed = a_Player:GetLookVector();
|
||||||
Speed:Normalize();
|
Speed:Normalize();
|
||||||
Pos = Pos + Speed * 2;
|
Pos = Pos + Speed * 2;
|
||||||
|
|
||||||
World:CreateProjectile(Pos.x, Pos.y, Pos.z, cProjectileEntity.pkGhastFireball, a_Player, Speed * 10);
|
World:CreateProjectile(Pos.x, Pos.y, Pos.z, cProjectileEntity.pkGhastFireball, a_Player, Speed * 10);
|
||||||
return true;
|
return true;
|
||||||
end
|
end
|
||||||
@ -1134,7 +1134,7 @@ end
|
|||||||
|
|
||||||
function HandleRemoveXp(a_Split, a_Player)
|
function HandleRemoveXp(a_Split, a_Player)
|
||||||
a_Player:SetCurrentExperience(0);
|
a_Player:SetCurrentExperience(0);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -1217,7 +1217,7 @@ end
|
|||||||
|
|
||||||
function HandleSched(a_Split, a_Player)
|
function HandleSched(a_Split, a_Player)
|
||||||
local World = a_Player:GetWorld()
|
local World = a_Player:GetWorld()
|
||||||
|
|
||||||
-- Schedule a broadcast of a countdown message:
|
-- Schedule a broadcast of a countdown message:
|
||||||
for i = 1, 10 do
|
for i = 1, 10 do
|
||||||
World:ScheduleTask(i * 20,
|
World:ScheduleTask(i * 20,
|
||||||
@ -1226,7 +1226,7 @@ function HandleSched(a_Split, a_Player)
|
|||||||
end
|
end
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Schedule a broadcast of the final message and a note to the originating player
|
-- Schedule a broadcast of the final message and a note to the originating player
|
||||||
-- Note that we CANNOT use the a_Player in the callback - what if the player disconnected?
|
-- Note that we CANNOT use the a_Player in the callback - what if the player disconnected?
|
||||||
-- Therefore we store the player's EntityID
|
-- Therefore we store the player's EntityID
|
||||||
@ -1246,7 +1246,7 @@ function HandleSched(a_Split, a_Player)
|
|||||||
)
|
)
|
||||||
end
|
end
|
||||||
)
|
)
|
||||||
|
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -1362,7 +1362,7 @@ end
|
|||||||
|
|
||||||
function OnPluginMessage(a_Client, a_Channel, a_Message)
|
function OnPluginMessage(a_Client, a_Channel, a_Message)
|
||||||
LOGINFO("Received a plugin message from client " .. a_Client:GetUsername() .. ": channel '" .. a_Channel .. "', message '" .. a_Message .. "'");
|
LOGINFO("Received a plugin message from client " .. a_Client:GetUsername() .. ": channel '" .. a_Channel .. "', message '" .. a_Message .. "'");
|
||||||
|
|
||||||
if (a_Channel == "REGISTER") then
|
if (a_Channel == "REGISTER") then
|
||||||
if (a_Message:find("WECUI")) then
|
if (a_Message:find("WECUI")) then
|
||||||
-- The client has WorldEditCUI mod installed, test the comm by sending a few WECUI messages:
|
-- The client has WorldEditCUI mod installed, test the comm by sending a few WECUI messages:
|
||||||
@ -1389,29 +1389,29 @@ function HandleChunkStay(a_Split, a_Player)
|
|||||||
-- As an example of using ChunkStay, this call will load 3x3 chunks around the specified chunk coords,
|
-- As an example of using ChunkStay, this call will load 3x3 chunks around the specified chunk coords,
|
||||||
-- then build an obsidian pillar in the middle of each one.
|
-- then build an obsidian pillar in the middle of each one.
|
||||||
-- Once complete, the player will be teleported to the middle pillar
|
-- Once complete, the player will be teleported to the middle pillar
|
||||||
|
|
||||||
if (#a_Split ~= 3) then
|
if (#a_Split ~= 3) then
|
||||||
a_Player:SendMessageInfo("Usage: /cs <ChunkX> <ChunkZ>")
|
a_Player:SendMessageInfo("Usage: /cs <ChunkX> <ChunkZ>")
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
local ChunkX = tonumber(a_Split[2])
|
local ChunkX = tonumber(a_Split[2])
|
||||||
local ChunkZ = tonumber(a_Split[3])
|
local ChunkZ = tonumber(a_Split[3])
|
||||||
if ((ChunkX == nil) or (ChunkZ == nil)) then
|
if ((ChunkX == nil) or (ChunkZ == nil)) then
|
||||||
a_Player:SendMessageFailure("Invalid chunk coords.")
|
a_Player:SendMessageFailure("Invalid chunk coords.")
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
local World = a_Player:GetWorld()
|
local World = a_Player:GetWorld()
|
||||||
local PlayerID = a_Player:GetUniqueID()
|
local PlayerID = a_Player:GetUniqueID()
|
||||||
a_Player:SendMessageInfo("Loading chunks, stand by...");
|
a_Player:SendMessageInfo("Loading chunks, stand by...");
|
||||||
|
|
||||||
-- Set the wanted chunks:
|
-- Set the wanted chunks:
|
||||||
local Chunks = {}
|
local Chunks = {}
|
||||||
for z = -1, 1 do for x = -1, 1 do
|
for z = -1, 1 do for x = -1, 1 do
|
||||||
table.insert(Chunks, {ChunkX + x, ChunkZ + z})
|
table.insert(Chunks, {ChunkX + x, ChunkZ + z})
|
||||||
end end
|
end end
|
||||||
|
|
||||||
-- The function that is called when all chunks are available
|
-- The function that is called when all chunks are available
|
||||||
-- Will perform the actual action with all those chunks
|
-- Will perform the actual action with all those chunks
|
||||||
-- Note that the player needs to be referenced using their EntityID - in case they disconnect before the chunks load
|
-- Note that the player needs to be referenced using their EntityID - in case they disconnect before the chunks load
|
||||||
@ -1425,7 +1425,7 @@ function HandleChunkStay(a_Split, a_Player)
|
|||||||
World:SetBlock(BlockX, y, BlockZ, E_BLOCK_OBSIDIAN, 0)
|
World:SetBlock(BlockX, y, BlockZ, E_BLOCK_OBSIDIAN, 0)
|
||||||
end
|
end
|
||||||
end end
|
end end
|
||||||
|
|
||||||
-- Teleport the player there for visual inspection:
|
-- Teleport the player there for visual inspection:
|
||||||
World:DoWithEntityByID(PlayerID,
|
World:DoWithEntityByID(PlayerID,
|
||||||
function (a_CallbackPlayer)
|
function (a_CallbackPlayer)
|
||||||
@ -1434,7 +1434,7 @@ function HandleChunkStay(a_Split, a_Player)
|
|||||||
end
|
end
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- This function will be called for each chunk that is made available
|
-- This function will be called for each chunk that is made available
|
||||||
-- Note that the player needs to be referenced using their EntityID - in case they disconnect before the chunks load
|
-- Note that the player needs to be referenced using their EntityID - in case they disconnect before the chunks load
|
||||||
local OnChunkAvailable = function(a_ChunkX, a_ChunkZ)
|
local OnChunkAvailable = function(a_ChunkX, a_ChunkZ)
|
||||||
@ -1445,7 +1445,7 @@ function HandleChunkStay(a_Split, a_Player)
|
|||||||
end
|
end
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Process the ChunkStay:
|
-- Process the ChunkStay:
|
||||||
World:ChunkStay(Chunks, OnChunkAvailable, OnAllChunksAvailable)
|
World:ChunkStay(Chunks, OnChunkAvailable, OnAllChunksAvailable)
|
||||||
return true
|
return true
|
||||||
@ -1463,13 +1463,13 @@ function HandleCompo(a_Split, a_Player)
|
|||||||
msg:AddTextPart(" rules! ")
|
msg:AddTextPart(" rules! ")
|
||||||
msg:AddRunCommandPart("Set morning", "/time set 0")
|
msg:AddRunCommandPart("Set morning", "/time set 0")
|
||||||
a_Player:SendMessage(msg)
|
a_Player:SendMessage(msg)
|
||||||
|
|
||||||
-- Broadcast another one to the world:
|
-- Broadcast another one to the world:
|
||||||
local msg2 = cCompositeChat()
|
local msg2 = cCompositeChat()
|
||||||
msg2:AddSuggestCommandPart(a_Player:GetName(), "/tell " .. a_Player:GetName() .. " ")
|
msg2:AddSuggestCommandPart(a_Player:GetName(), "/tell " .. a_Player:GetName() .. " ")
|
||||||
msg2:AddTextPart(" knows how to use cCompositeChat!");
|
msg2:AddTextPart(" knows how to use cCompositeChat!");
|
||||||
a_Player:GetWorld():BroadcastChat(msg2)
|
a_Player:GetWorld():BroadcastChat(msg2)
|
||||||
|
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -1500,7 +1500,7 @@ function HandleSetBiome(a_Split, a_Player)
|
|||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local BlockX = math.floor(a_Player:GetPosX())
|
local BlockX = math.floor(a_Player:GetPosX())
|
||||||
local BlockZ = math.floor(a_Player:GetPosZ())
|
local BlockZ = math.floor(a_Player:GetPosZ())
|
||||||
a_Player:GetWorld():SetAreaBiome(BlockX - Size, BlockX + Size, BlockZ - Size, BlockZ + Size, Biome)
|
a_Player:GetWorld():SetAreaBiome(BlockX - Size, BlockX + Size, BlockZ - Size, BlockZ + Size, Biome)
|
||||||
@ -1526,7 +1526,7 @@ function HandleWESel(a_Split, a_Player)
|
|||||||
a_Player:SendMessage(cCompositeChat():SetMessageType(mtFailure):AddTextPart("Cannot adjust selection, the selection is not a cuboid"))
|
a_Player:SendMessage(cCompositeChat():SetMessageType(mtFailure):AddTextPart("Cannot adjust selection, the selection is not a cuboid"))
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Get the selection:
|
-- Get the selection:
|
||||||
local SelCuboid = cCuboid()
|
local SelCuboid = cCuboid()
|
||||||
local IsSuccess = cPluginManager:CallPlugin("WorldEdit", "GetPlayerCuboidSelection", a_Player, SelCuboid)
|
local IsSuccess = cPluginManager:CallPlugin("WorldEdit", "GetPlayerCuboidSelection", a_Player, SelCuboid)
|
||||||
@ -1534,11 +1534,11 @@ function HandleWESel(a_Split, a_Player)
|
|||||||
a_Player:SendMessage(cCompositeChat():SetMessageType(mtFailure):AddTextPart("Cannot adjust selection, WorldEdit reported failure while getting current selection"))
|
a_Player:SendMessage(cCompositeChat():SetMessageType(mtFailure):AddTextPart("Cannot adjust selection, WorldEdit reported failure while getting current selection"))
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Adjust the selection:
|
-- Adjust the selection:
|
||||||
local NumBlocks = tonumber(a_Split[2] or "1") or 1
|
local NumBlocks = tonumber(a_Split[2] or "1") or 1
|
||||||
SelCuboid:Expand(NumBlocks, NumBlocks, 0, 0, NumBlocks, NumBlocks)
|
SelCuboid:Expand(NumBlocks, NumBlocks, 0, 0, NumBlocks, NumBlocks)
|
||||||
|
|
||||||
-- Set the selection:
|
-- Set the selection:
|
||||||
IsSuccess = cPluginManager:CallPlugin("WorldEdit", "SetPlayerCuboidSelection", a_Player, SelCuboid)
|
IsSuccess = cPluginManager:CallPlugin("WorldEdit", "SetPlayerCuboidSelection", a_Player, SelCuboid)
|
||||||
if not(IsSuccess) then
|
if not(IsSuccess) then
|
||||||
@ -1571,7 +1571,7 @@ function OnProjectileHitBlock(a_Projectile, a_BlockX, a_BlockY, a_BlockZ, a_Bloc
|
|||||||
-- Test projectile hooks by setting the blocks they hit on fire:
|
-- Test projectile hooks by setting the blocks they hit on fire:
|
||||||
local BlockX, BlockY, BlockZ = AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace)
|
local BlockX, BlockY, BlockZ = AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace)
|
||||||
local World = a_Projectile:GetWorld()
|
local World = a_Projectile:GetWorld()
|
||||||
|
|
||||||
World:SetBlock(BlockX, BlockY, BlockZ, E_BLOCK_FIRE, 0)
|
World:SetBlock(BlockX, BlockY, BlockZ, E_BLOCK_FIRE, 0)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -1734,7 +1734,7 @@ function HandleConsoleInh(a_Split, a_FullCmd)
|
|||||||
if (world == nil) then
|
if (world == nil) then
|
||||||
return true, "Cannot test inheritance, no default world"
|
return true, "Cannot test inheritance, no default world"
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Install the hook, if needed:
|
-- Install the hook, if needed:
|
||||||
if not(isInhHookInstalled) then
|
if not(isInhHookInstalled) then
|
||||||
cPluginManager:AddHook(cPluginManager.HOOK_SPAWNING_ENTITY,
|
cPluginManager:AddHook(cPluginManager.HOOK_SPAWNING_ENTITY,
|
||||||
@ -1748,7 +1748,7 @@ function HandleConsoleInh(a_Split, a_FullCmd)
|
|||||||
)
|
)
|
||||||
isInhHookInstalled = true
|
isInhHookInstalled = true
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Create the projectile:
|
-- Create the projectile:
|
||||||
LOG("Creating a " .. kindStr .. " projectile in world " .. world:GetName() .. "...")
|
LOG("Creating a " .. kindStr .. " projectile in world " .. world:GetName() .. "...")
|
||||||
local msg
|
local msg
|
||||||
@ -1762,7 +1762,7 @@ function HandleConsoleInh(a_Split, a_FullCmd)
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
LOG("Entity created, ID #" .. entityID)
|
LOG("Entity created, ID #" .. entityID)
|
||||||
|
|
||||||
-- Call a function on the newly created entity:
|
-- Call a function on the newly created entity:
|
||||||
local hasExecutedCallback = false
|
local hasExecutedCallback = false
|
||||||
world:DoWithEntityByID(
|
world:DoWithEntityByID(
|
||||||
@ -1780,11 +1780,11 @@ function HandleConsoleInh(a_Split, a_FullCmd)
|
|||||||
msg = "The callback failed to execute"
|
msg = "The callback failed to execute"
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
msg = "Inheritance test finished"
|
msg = "Inheritance test finished"
|
||||||
end
|
end
|
||||||
)
|
)
|
||||||
|
|
||||||
return true, msg
|
return true, msg
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -1798,7 +1798,7 @@ function HandleConsoleLoadChunk(a_Split)
|
|||||||
if (numParams ~= 3) and (numParams ~= 4) then
|
if (numParams ~= 3) and (numParams ~= 4) then
|
||||||
return true, "Usage: " .. a_Split[1] .. " <ChunkX> <ChunkZ> [<WorldName>]"
|
return true, "Usage: " .. a_Split[1] .. " <ChunkX> <ChunkZ> [<WorldName>]"
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Get the chunk coords:
|
-- Get the chunk coords:
|
||||||
local chunkX = tonumber(a_Split[2])
|
local chunkX = tonumber(a_Split[2])
|
||||||
if (chunkX == nil) then
|
if (chunkX == nil) then
|
||||||
@ -1819,7 +1819,7 @@ function HandleConsoleLoadChunk(a_Split)
|
|||||||
return true, "There's no world named '" .. a_Split[4] .. "'."
|
return true, "There's no world named '" .. a_Split[4] .. "'."
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Queue a ChunkStay for the chunk, log a message when the chunk is loaded:
|
-- Queue a ChunkStay for the chunk, log a message when the chunk is loaded:
|
||||||
world:ChunkStay({{chunkX, chunkZ}}, nil,
|
world:ChunkStay({{chunkX, chunkZ}}, nil,
|
||||||
function()
|
function()
|
||||||
@ -1839,7 +1839,7 @@ function HandleConsolePrepareChunk(a_Split)
|
|||||||
if (numParams ~= 3) and (numParams ~= 4) then
|
if (numParams ~= 3) and (numParams ~= 4) then
|
||||||
return true, "Usage: " .. a_Split[1] .. " <ChunkX> <ChunkZ> [<WorldName>]"
|
return true, "Usage: " .. a_Split[1] .. " <ChunkX> <ChunkZ> [<WorldName>]"
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Get the chunk coords:
|
-- Get the chunk coords:
|
||||||
local chunkX = tonumber(a_Split[2])
|
local chunkX = tonumber(a_Split[2])
|
||||||
if (chunkX == nil) then
|
if (chunkX == nil) then
|
||||||
@ -1860,7 +1860,7 @@ function HandleConsolePrepareChunk(a_Split)
|
|||||||
return true, "There's no world named '" .. a_Split[4] .. "'."
|
return true, "There's no world named '" .. a_Split[4] .. "'."
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Queue the chunk for preparing, log a message when prepared:
|
-- Queue the chunk for preparing, log a message when prepared:
|
||||||
world:PrepareChunk(chunkX, chunkZ,
|
world:PrepareChunk(chunkX, chunkZ,
|
||||||
function(a_CBChunkX, a_CBChunkZ)
|
function(a_CBChunkX, a_CBChunkZ)
|
||||||
@ -1942,7 +1942,7 @@ function HandleConsoleTestBbox(a_Split, a_EntireCmd)
|
|||||||
LOG(" {" .. intersection:GetMinX() .. ", " .. intersection:GetMinY() .. ", " .. intersection:GetMinZ() .. "}")
|
LOG(" {" .. intersection:GetMinX() .. ", " .. intersection:GetMinY() .. ", " .. intersection:GetMinZ() .. "}")
|
||||||
LOG(" {" .. intersection:GetMaxX() .. ", " .. intersection:GetMaxY() .. ", " .. intersection:GetMaxZ() .. "}")
|
LOG(" {" .. intersection:GetMaxX() .. ", " .. intersection:GetMaxY() .. ", " .. intersection:GetMaxZ() .. "}")
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Test line intersection:
|
-- Test line intersection:
|
||||||
local lines =
|
local lines =
|
||||||
{
|
{
|
||||||
@ -1959,7 +1959,7 @@ function HandleConsoleTestBbox(a_Split, a_EntireCmd)
|
|||||||
assert(coeff == coeff2)
|
assert(coeff == coeff2)
|
||||||
assert(face == face2)
|
assert(face == face2)
|
||||||
end
|
end
|
||||||
|
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -1970,7 +1970,7 @@ end
|
|||||||
function HandleConsoleTestCall(a_Split, a_EntireCmd)
|
function HandleConsoleTestCall(a_Split, a_EntireCmd)
|
||||||
LOG("Testing inter-plugin calls")
|
LOG("Testing inter-plugin calls")
|
||||||
LOG("Note: These will fail if the Core plugin is not enabled")
|
LOG("Note: These will fail if the Core plugin is not enabled")
|
||||||
|
|
||||||
-- Test calling the HandleConsoleWeather handler:
|
-- Test calling the HandleConsoleWeather handler:
|
||||||
local pm = cPluginManager
|
local pm = cPluginManager
|
||||||
LOG("Calling Core's HandleConsoleWeather")
|
LOG("Calling Core's HandleConsoleWeather")
|
||||||
@ -1985,7 +1985,7 @@ function HandleConsoleTestCall(a_Split, a_EntireCmd)
|
|||||||
else
|
else
|
||||||
LOG("FAILED")
|
LOG("FAILED")
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Test injecting some code:
|
-- Test injecting some code:
|
||||||
LOG("Injecting code into the Core plugin")
|
LOG("Injecting code into the Core plugin")
|
||||||
isSuccess = pm:CallPlugin("Core", "dofile", pm:GetCurrentPlugin():GetLocalFolder() .. "/Inject.lua")
|
isSuccess = pm:CallPlugin("Core", "dofile", pm:GetCurrentPlugin():GetLocalFolder() .. "/Inject.lua")
|
||||||
@ -1994,7 +1994,7 @@ function HandleConsoleTestCall(a_Split, a_EntireCmd)
|
|||||||
else
|
else
|
||||||
LOG("FAILED")
|
LOG("FAILED")
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Test the full capabilities of the table-passing API, using the injected function:
|
-- Test the full capabilities of the table-passing API, using the injected function:
|
||||||
LOG("Calling injected code")
|
LOG("Calling injected code")
|
||||||
isSuccess = pm:CallPlugin("Core", "injectedPrintParams",
|
isSuccess = pm:CallPlugin("Core", "injectedPrintParams",
|
||||||
@ -2039,14 +2039,19 @@ function HandleConsoleTestJson(a_Split, a_EntireCmd)
|
|||||||
assert(t2 == nil)
|
assert(t2 == nil)
|
||||||
assert(type(msg) == "string")
|
assert(type(msg) == "string")
|
||||||
LOG("Json parsing an invalid string: Error message returned: " .. msg)
|
LOG("Json parsing an invalid string: Error message returned: " .. msg)
|
||||||
|
|
||||||
LOG("Json parsing test succeeded")
|
LOG("Json parsing test succeeded")
|
||||||
|
|
||||||
LOG("Testing Json serializing...")
|
LOG("Testing Json serializing...")
|
||||||
local s1 = cJson:Serialize({a = 1, b = "2", c = {3, "4", 5}, d = true}, {indentation = " "})
|
local s1, msg1 = cJson:Serialize({a = 1, b = "2", c = {3, "4", 5}, d = true}, {indentation = " "})
|
||||||
LOG("Serialization result: " .. (s1 or "<nil>"))
|
LOG("Serialization result: " .. (s1 or ("ERROR: " .. (msg1 or "<no message>"))))
|
||||||
|
|
||||||
|
local s2, msg2 = cJson:Serialize({valueA = 1, valueB = {3, badValue = "4", 5}, d = true}, {indentation = " "})
|
||||||
|
assert(not(s2), "Serialization should have failed")
|
||||||
|
LOG("Serialization correctly failed with message: " .. (msg2 or "<no message>"))
|
||||||
|
|
||||||
LOG("Json serializing test succeeded")
|
LOG("Json serializing test succeeded")
|
||||||
|
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -2067,7 +2072,7 @@ function HandleConsoleTestTracer(a_Split, a_EntireCmd)
|
|||||||
end
|
end
|
||||||
Coords[i] = v
|
Coords[i] = v
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Get the world in which to test:
|
-- Get the world in which to test:
|
||||||
local World
|
local World
|
||||||
if (a_Split[8]) then
|
if (a_Split[8]) then
|
||||||
@ -2078,7 +2083,7 @@ function HandleConsoleTestTracer(a_Split, a_EntireCmd)
|
|||||||
if not(World) then
|
if not(World) then
|
||||||
return true, "No such world"
|
return true, "No such world"
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Define the callbacks to use for tracing:
|
-- Define the callbacks to use for tracing:
|
||||||
local Callbacks =
|
local Callbacks =
|
||||||
{
|
{
|
||||||
@ -2120,7 +2125,7 @@ function HandleConsoleTestTracer(a_Split, a_EntireCmd)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Load the chunks and do the trace once loaded:
|
-- Load the chunks and do the trace once loaded:
|
||||||
World:ChunkStay(Chunks,
|
World:ChunkStay(Chunks,
|
||||||
nil,
|
nil,
|
||||||
@ -2211,7 +2216,7 @@ function HandleConsoleUuid(a_Split, a_EntireCmd)
|
|||||||
if not(playerName) then
|
if not(playerName) then
|
||||||
return true, "Usage: uuid <PlayerName>"
|
return true, "Usage: uuid <PlayerName>"
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Query with cache:
|
-- Query with cache:
|
||||||
LOG("Player " .. playerName .. ":")
|
LOG("Player " .. playerName .. ":")
|
||||||
local cachedUuid = cMojangAPI:GetUUIDFromPlayerName(playerName, true)
|
local cachedUuid = cMojangAPI:GetUUIDFromPlayerName(playerName, true)
|
||||||
@ -2220,7 +2225,7 @@ function HandleConsoleUuid(a_Split, a_EntireCmd)
|
|||||||
else
|
else
|
||||||
LOG(" - in the cache: \"" .. cachedUuid .. "\"")
|
LOG(" - in the cache: \"" .. cachedUuid .. "\"")
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Query online:
|
-- Query online:
|
||||||
local onlineUuid = cMojangAPI:GetUUIDFromPlayerName(playerName, false)
|
local onlineUuid = cMojangAPI:GetUUIDFromPlayerName(playerName, false)
|
||||||
if not(onlineUuid) then
|
if not(onlineUuid) then
|
||||||
@ -2228,7 +2233,7 @@ function HandleConsoleUuid(a_Split, a_EntireCmd)
|
|||||||
else
|
else
|
||||||
LOG(" - online: \"" .. onlineUuid .. "\"")
|
LOG(" - online: \"" .. onlineUuid .. "\"")
|
||||||
end
|
end
|
||||||
|
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -2241,13 +2246,13 @@ function HandleConsoleBBox(a_Split)
|
|||||||
local v1 = Vector3d(1, 1, 1)
|
local v1 = Vector3d(1, 1, 1)
|
||||||
local v2 = Vector3d(5, 5, 5)
|
local v2 = Vector3d(5, 5, 5)
|
||||||
local v3 = Vector3d(11, 11, 11)
|
local v3 = Vector3d(11, 11, 11)
|
||||||
|
|
||||||
if (bbox:IsInside(v1)) then
|
if (bbox:IsInside(v1)) then
|
||||||
LOG("v1 is inside bbox")
|
LOG("v1 is inside bbox")
|
||||||
else
|
else
|
||||||
LOG("v1 is not inside bbox")
|
LOG("v1 is not inside bbox")
|
||||||
end
|
end
|
||||||
|
|
||||||
if (bbox:IsInside(v2)) then
|
if (bbox:IsInside(v2)) then
|
||||||
LOG("v2 is inside bbox")
|
LOG("v2 is inside bbox")
|
||||||
else
|
else
|
||||||
@ -2265,25 +2270,25 @@ function HandleConsoleBBox(a_Split)
|
|||||||
else
|
else
|
||||||
LOG("v1*v2 is not inside bbox")
|
LOG("v1*v2 is not inside bbox")
|
||||||
end
|
end
|
||||||
|
|
||||||
if (bbox:IsInside(v2, v1)) then
|
if (bbox:IsInside(v2, v1)) then
|
||||||
LOG("v2*v1 is inside bbox")
|
LOG("v2*v1 is inside bbox")
|
||||||
else
|
else
|
||||||
LOG("v2*v1 is not inside bbox")
|
LOG("v2*v1 is not inside bbox")
|
||||||
end
|
end
|
||||||
|
|
||||||
if (bbox:IsInside(v1, v3)) then
|
if (bbox:IsInside(v1, v3)) then
|
||||||
LOG("v1*v3 is inside bbox")
|
LOG("v1*v3 is inside bbox")
|
||||||
else
|
else
|
||||||
LOG("v1*v3 is not inside bbox")
|
LOG("v1*v3 is not inside bbox")
|
||||||
end
|
end
|
||||||
|
|
||||||
if (bbox:IsInside(v2, v3)) then
|
if (bbox:IsInside(v2, v3)) then
|
||||||
LOG("v2*v3 is inside bbox")
|
LOG("v2*v3 is inside bbox")
|
||||||
else
|
else
|
||||||
LOG("v2*v3 is not inside bbox")
|
LOG("v2*v3 is not inside bbox")
|
||||||
end
|
end
|
||||||
|
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -2298,7 +2303,7 @@ function HandleConsoleDownload(a_Split)
|
|||||||
if (not(url) or not(fnam)) then
|
if (not(url) or not(fnam)) then
|
||||||
return true, "Missing parameters. Usage: download <url> <filename>"
|
return true, "Missing parameters. Usage: download <url> <filename>"
|
||||||
end
|
end
|
||||||
|
|
||||||
local callbacks =
|
local callbacks =
|
||||||
{
|
{
|
||||||
OnStatusLine = function (self, a_HttpVersion, a_Status, a_Rest)
|
OnStatusLine = function (self, a_HttpVersion, a_Status, a_Rest)
|
||||||
@ -2306,7 +2311,7 @@ function HandleConsoleDownload(a_Split)
|
|||||||
LOG("Cannot download " .. url .. ", HTTP error code " .. a_Status)
|
LOG("Cannot download " .. url .. ", HTTP error code " .. a_Status)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local f, err = io.open(fnam, "wb")
|
local f, err = io.open(fnam, "wb")
|
||||||
if not(f) then
|
if not(f) then
|
||||||
LOG("Cannot download " .. url .. ", error opening the file " .. fnam .. ": " .. (err or "<no message>"))
|
LOG("Cannot download " .. url .. ", error opening the file " .. fnam .. ": " .. (err or "<no message>"))
|
||||||
@ -2320,7 +2325,7 @@ function HandleConsoleDownload(a_Split)
|
|||||||
self.m_File:write(a_Data)
|
self.m_File:write(a_Data)
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
|
|
||||||
OnBodyFinished = function (self)
|
OnBodyFinished = function (self)
|
||||||
if (self.m_File) then
|
if (self.m_File) then
|
||||||
self.m_File:close()
|
self.m_File:close()
|
||||||
@ -2328,7 +2333,7 @@ function HandleConsoleDownload(a_Split)
|
|||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
}
|
}
|
||||||
|
|
||||||
local isSuccess, msg = cUrlClient:Get(url, callbacks)
|
local isSuccess, msg = cUrlClient:Get(url, callbacks)
|
||||||
if not(isSuccess) then
|
if not(isSuccess) then
|
||||||
LOG("Cannot start an URL download: " .. (msg or "<no message>"))
|
LOG("Cannot start an URL download: " .. (msg or "<no message>"))
|
||||||
@ -2353,15 +2358,15 @@ function HandleBlkCmd(a_Split, a_Player)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
};
|
};
|
||||||
|
|
||||||
local EyePos = a_Player:GetEyePosition();
|
local EyePos = a_Player:GetEyePosition();
|
||||||
local LookVector = a_Player:GetLookVector();
|
local LookVector = a_Player:GetLookVector();
|
||||||
LookVector:Normalize();
|
LookVector:Normalize();
|
||||||
|
|
||||||
local End = EyePos + LookVector * 50;
|
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.x, EyePos.y, EyePos.z, End.x, End.y, End.z);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -22,6 +22,53 @@ static Json::Value JsonSerializeValue(cLuaState & a_LuaState);
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/** Exception thrown when the input cannot be serialized.
|
||||||
|
Keeps track of the error message and the problematic value's path in the table.
|
||||||
|
*/
|
||||||
|
class CannotSerializeException:
|
||||||
|
public std::runtime_error
|
||||||
|
{
|
||||||
|
typedef std::runtime_error Super;
|
||||||
|
public:
|
||||||
|
/** Constructs a new instance of the exception based on the provided values directly. */
|
||||||
|
explicit CannotSerializeException(const AString & a_ValueName, const char * a_ErrorMsg):
|
||||||
|
Super(a_ErrorMsg),
|
||||||
|
m_ValueName(a_ValueName)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Constructs a new instance of the exception based on the provided values directly. */
|
||||||
|
explicit CannotSerializeException(int a_ValueIndex, const char * a_ErrorMsg):
|
||||||
|
Super(a_ErrorMsg),
|
||||||
|
m_ValueName(Printf("%d", a_ValueIndex))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Constructs a new instance of the exception that takes the error message and value name from the parent, and prefix the value name with the specified prefix.
|
||||||
|
Used for prefixing the value name's path along the call stack that lead to the main exception. */
|
||||||
|
explicit CannotSerializeException(const CannotSerializeException & a_Parent, const AString & a_ValueNamePrefix):
|
||||||
|
Super(a_Parent.what()),
|
||||||
|
m_ValueName(a_ValueNamePrefix + "." + a_Parent.m_ValueName)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Constructs a new instance of the exception that takes the error message and value name from the parent, and prefix the value name with the specified prefix.
|
||||||
|
Used for prefixing the value name's path along the call stack that lead to the main exception. */
|
||||||
|
explicit CannotSerializeException(const CannotSerializeException & a_Parent, int a_ValueNamePrefixIndex):
|
||||||
|
Super(a_Parent.what()),
|
||||||
|
m_ValueName(Printf("%d", a_ValueNamePrefixIndex) + "." + a_Parent.m_ValueName)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
const AString & GetValueName() const { return m_ValueName; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
AString m_ValueName;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** Pushes the specified Json array as a table on top of the specified Lua state.
|
/** Pushes the specified Json array as a table on top of the specified Lua state.
|
||||||
Assumes that a_Value is an array. */
|
Assumes that a_Value is an array. */
|
||||||
@ -136,14 +183,36 @@ static Json::Value JsonSerializeTable(cLuaState & a_LuaState)
|
|||||||
{
|
{
|
||||||
int idx;
|
int idx;
|
||||||
a_LuaState.GetStackValue(-2, idx);
|
a_LuaState.GetStackValue(-2, idx);
|
||||||
res[idx - 1] = JsonSerializeValue(a_LuaState);
|
try
|
||||||
|
{
|
||||||
|
res[idx - 1] = JsonSerializeValue(a_LuaState);
|
||||||
|
}
|
||||||
|
catch (const CannotSerializeException & exc)
|
||||||
|
{
|
||||||
|
throw CannotSerializeException(exc, idx);
|
||||||
|
}
|
||||||
|
catch (const std::exception & exc) // Cannot catch Json::Exception, because it's not properly defined
|
||||||
|
{
|
||||||
|
throw CannotSerializeException(idx, exc.what());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
AString name;
|
AString name;
|
||||||
if (a_LuaState.GetStackValue(-2, name))
|
if (a_LuaState.GetStackValue(-2, name))
|
||||||
{
|
{
|
||||||
res[name] = JsonSerializeValue(a_LuaState);
|
try
|
||||||
|
{
|
||||||
|
res[name] = JsonSerializeValue(a_LuaState);
|
||||||
|
}
|
||||||
|
catch (const CannotSerializeException & exc)
|
||||||
|
{
|
||||||
|
throw CannotSerializeException(exc, name);
|
||||||
|
}
|
||||||
|
catch (const std::exception & exc) // Cannot catch Json::Exception, because it's not properly defined
|
||||||
|
{
|
||||||
|
throw CannotSerializeException(name, exc.what());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
lua_pop(a_LuaState, 1);
|
lua_pop(a_LuaState, 1);
|
||||||
@ -259,7 +328,17 @@ static int tolua_cJson_Serialize(lua_State * a_LuaState)
|
|||||||
|
|
||||||
// Push the table to the top of the Lua stack, and call the serializing function:
|
// Push the table to the top of the Lua stack, and call the serializing function:
|
||||||
lua_pushvalue(L, 2);
|
lua_pushvalue(L, 2);
|
||||||
Json::Value root = JsonSerializeValue(L);
|
Json::Value root;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
root = JsonSerializeValue(L);
|
||||||
|
}
|
||||||
|
catch (const CannotSerializeException & exc)
|
||||||
|
{
|
||||||
|
lua_pushnil(L);
|
||||||
|
L.Push(Printf("Cannot serialize into Json, value \"%s\" caused an error \"%s\"", exc.GetValueName().c_str(), exc.what()));
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
|
|
||||||
// Create the writer, with all properties (optional param 3) applied to it:
|
// Create the writer, with all properties (optional param 3) applied to it:
|
||||||
|
Loading…
Reference in New Issue
Block a user