2012-10-16 08:20:45 +00:00
-- Global variables
2013-02-02 13:43:55 +00:00
PLUGIN = {}; -- Reference to own plugin object
2013-05-30 19:34:09 +00:00
ShouldDumpFunctions = true ; -- If set to true, all available functions are written to the API.txt file upon plugin initialization
2012-10-16 08:20:45 +00:00
2013-05-26 14:39:04 +00:00
g_DropSpensersToActivate = {}; -- A list of dispensers and droppers (as {World, X, Y Z} quadruplets) that are to be activated every tick
2013-05-25 12:03:20 +00:00
2012-10-16 08:20:45 +00:00
function Initialize ( Plugin )
PLUGIN = Plugin
Plugin : SetName ( "Debuggers" )
Plugin : SetVersion ( 1 )
PluginManager = cRoot : Get (): GetPluginManager ()
2013-05-25 12:03:20 +00:00
PluginManager : AddHook ( Plugin , cPluginManager.HOOK_PLAYER_USING_BLOCK );
2013-02-08 20:57:42 +00:00
PluginManager : AddHook ( Plugin , cPluginManager.HOOK_PLAYER_USING_ITEM );
PluginManager : AddHook ( Plugin , cPluginManager.HOOK_TAKE_DAMAGE );
2013-05-25 12:03:20 +00:00
PluginManager : AddHook ( Plugin , cPluginManager.HOOK_TICK );
2013-05-19 15:45:03 +00:00
2013-05-30 19:34:09 +00:00
PluginManager : BindCommand ( "/le" , "debuggers" , HandleListEntitiesCmd , "Shows a list of all the loaded entities" );
PluginManager : BindCommand ( "/ke" , "debuggers" , HandleKillEntitiesCmd , "Kills all the loaded entities" );
PluginManager : BindCommand ( "/wool" , "debuggers" , HandleWoolCmd , "Sets all your armor to blue wool" );
PluginManager : BindCommand ( "/testwnd" , "debuggers" , HandleTestWndCmd , "Opens up a window using plugin API" );
PluginManager : BindCommand ( "/gc" , "debuggers" , HandleGCCmd , "Activates the Lua garbage collector" );
2013-03-03 14:31:59 +00:00
-- Enable the following line for BlockArea / Generator interface testing:
-- PluginManager:AddHook(Plugin, cPluginManager.HOOK_CHUNK_GENERATED);
2012-10-16 08:20:45 +00:00
LOG ( "Initialized " .. Plugin : GetName () .. " v." .. Plugin : GetVersion ())
2013-01-26 03:44:09 +00:00
2013-05-19 15:45:03 +00:00
-- dump all available API functions and objects:
2013-01-26 03:44:09 +00:00
if ( ShouldDumpFunctions ) then
2013-05-19 15:45:03 +00:00
DumpAPI ();
end
-- TestBlockAreas();
-- TestSQLiteBindings();
-- TestExpatBindings();
return true
end ;
function DumpAPI ()
LOG ( "Dumping all available functions to API.txt..." );
function dump ( prefix , a , Output )
for i , v in pairs ( a ) do
if ( type ( v ) == "table" ) then
if ( GetChar ( i , 1 ) ~= "." ) then
if ( v == _G ) then
LOG ( prefix .. i .. " == _G, CYCLE, ignoring" );
elseif ( v == _G.package ) then
LOG ( prefix .. i .. " == _G.package, ignoring" );
else
dump ( prefix .. i .. "." , v , Output )
2013-02-02 13:43:55 +00:00
end
2013-01-27 02:34:38 +00:00
end
2013-05-19 15:45:03 +00:00
elseif ( type ( v ) == "function" ) then
if ( string.sub ( i , 1 , 2 ) ~= "__" ) then
table.insert ( Output , prefix .. i .. "()" );
end
2013-01-26 03:44:09 +00:00
end
end
2013-05-19 15:45:03 +00:00
end
2013-02-02 13:43:55 +00:00
2013-05-19 15:45:03 +00:00
local Output = {};
dump ( "" , _G , Output );
2013-02-02 13:43:55 +00:00
2013-05-19 15:45:03 +00:00
table.sort ( Output );
local f = io.open ( "API.txt" , "w" );
for i , n in ipairs ( Output ) do
f : write ( n , " \n " );
2013-01-26 03:44:09 +00:00
end
2013-05-19 15:45:03 +00:00
f : close ();
LOG ( "API.txt written." );
end
function TestBlockAreas ()
LOG ( "Testing block areas..." );
2013-02-10 15:15:41 +00:00
-- Debug block area merging:
local BA1 = cBlockArea ();
local BA2 = cBlockArea ();
if ( BA1 : LoadFromSchematicFile ( "schematics/test.schematic" )) then
if ( BA2 : LoadFromSchematicFile ( "schematics/fountain.schematic" )) then
BA2 : SetRelBlockType ( 0 , 0 , 0 , E_BLOCK_LAPIS_BLOCK );
BA2 : SetRelBlockType ( 1 , 0 , 0 , E_BLOCK_LAPIS_BLOCK );
BA2 : SetRelBlockType ( 2 , 0 , 0 , E_BLOCK_LAPIS_BLOCK );
BA1 : Merge ( BA2 , 1 , 10 , 1 , cBlockArea.msImprint );
BA1 : SaveToSchematicFile ( "schematics/merge.schematic" );
end
2013-04-09 13:43:24 +00:00
else
BA1 : Create ( 16 , 16 , 16 );
2013-02-10 15:15:41 +00:00
end
2013-02-11 12:27:02 +00:00
-- Debug block area cuboid filling:
BA1 : FillRelCuboid ( 2 , 9 , 2 , 8 , 2 , 8 , cBlockArea.baTypes , E_BLOCK_GOLD_BLOCK );
2013-02-13 19:54:26 +00:00
BA1 : RelLine ( 2 , 2 , 2 , 9 , 8 , 8 , cBlockArea.baTypes or cBlockArea.baMetas , E_BLOCK_SAPLING , E_META_SAPLING_BIRCH );
2013-02-11 12:27:02 +00:00
BA1 : SaveToSchematicFile ( "schematics/fillrel.schematic" );
2013-01-26 03:44:09 +00:00
2013-03-25 12:16:23 +00:00
-- Debug block area mirroring:
if ( BA1 : LoadFromSchematicFile ( "schematics/lt.schematic" )) then
BA1 : MirrorXYNoMeta ();
BA1 : SaveToSchematicFile ( "schematics/lt_XY.schematic" );
BA1 : MirrorXYNoMeta ();
BA1 : SaveToSchematicFile ( "schematics/lt_XY2.schematic" );
BA1 : MirrorXZNoMeta ();
BA1 : SaveToSchematicFile ( "schematics/lt_XZ.schematic" );
BA1 : MirrorXZNoMeta ();
BA1 : SaveToSchematicFile ( "schematics/lt_XZ2.schematic" );
BA1 : MirrorYZNoMeta ();
BA1 : SaveToSchematicFile ( "schematics/lt_YZ.schematic" );
BA1 : MirrorYZNoMeta ();
BA1 : SaveToSchematicFile ( "schematics/lt_YZ2.schematic" );
end
2013-03-25 20:14:36 +00:00
-- Debug block area rotation:
if ( BA1 : LoadFromSchematicFile ( "schematics/rot.schematic" )) then
BA1 : RotateCWNoMeta ();
BA1 : SaveToSchematicFile ( "schematics/rot1.schematic" );
BA1 : RotateCWNoMeta ();
BA1 : SaveToSchematicFile ( "schematics/rot2.schematic" );
BA1 : RotateCWNoMeta ();
BA1 : SaveToSchematicFile ( "schematics/rot3.schematic" );
BA1 : RotateCWNoMeta ();
BA1 : SaveToSchematicFile ( "schematics/rot4.schematic" );
end
2013-03-25 12:16:23 +00:00
2013-03-26 21:06:12 +00:00
-- Debug block area rotation:
if ( BA1 : LoadFromSchematicFile ( "schematics/rotm.schematic" )) then
BA1 : RotateCCW ();
BA1 : SaveToSchematicFile ( "schematics/rotm1.schematic" );
BA1 : RotateCCW ();
BA1 : SaveToSchematicFile ( "schematics/rotm2.schematic" );
BA1 : RotateCCW ();
BA1 : SaveToSchematicFile ( "schematics/rotm3.schematic" );
BA1 : RotateCCW ();
BA1 : SaveToSchematicFile ( "schematics/rotm4.schematic" );
end
-- Debug block area mirroring:
if ( BA1 : LoadFromSchematicFile ( "schematics/ltm.schematic" )) then
BA1 : MirrorXY ();
BA1 : SaveToSchematicFile ( "schematics/ltm_XY.schematic" );
BA1 : MirrorXY ();
BA1 : SaveToSchematicFile ( "schematics/ltm_XY2.schematic" );
BA1 : MirrorXZ ();
BA1 : SaveToSchematicFile ( "schematics/ltm_XZ.schematic" );
BA1 : MirrorXZ ();
BA1 : SaveToSchematicFile ( "schematics/ltm_XZ2.schematic" );
BA1 : MirrorYZ ();
BA1 : SaveToSchematicFile ( "schematics/ltm_YZ.schematic" );
BA1 : MirrorYZ ();
BA1 : SaveToSchematicFile ( "schematics/ltm_YZ2.schematic" );
end
2013-05-19 15:45:03 +00:00
LOG ( "Block areas test ended" );
end
2013-03-26 21:06:12 +00:00
2013-05-19 15:45:03 +00:00
function TestSQLiteBindings ()
LOG ( "Testing SQLite bindings..." );
2013-04-07 19:28:32 +00:00
-- Debug SQLite binding
local TestDB , ErrCode , ErrMsg = sqlite3.open ( "test.sqlite" );
if ( TestDB ~= nil ) then
local function ShowRow ( UserData , NumCols , Values , Names )
assert ( UserData == 'UserData' );
LOG ( "New row" );
for i = 1 , NumCols do
LOG ( " " .. Names [ i ] .. " = " .. Values [ i ]);
end
return 0 ;
end
local sql = [=[
CREATE TABLE numbers(num1,num2,str);
INSERT INTO numbers VALUES(1, 11, "ABC");
INSERT INTO numbers VALUES(2, 22, "DEF");
INSERT INTO numbers VALUES(3, 33, "UVW");
INSERT INTO numbers VALUES(4, 44, "XYZ");
SELECT * FROM numbers;
]=]
local Res = TestDB : exec ( sql , ShowRow , 'UserData' );
if ( Res ~= sqlite3.OK ) then
LOG ( "TestDB:exec() failed: " .. Res .. " (" .. TestDB : errmsg () .. ")" );
end ;
TestDB : close ();
else
-- 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 .. ")" );
end
2013-05-19 15:45:03 +00:00
LOG ( "SQLite bindings test ended" );
end
2013-04-07 19:28:32 +00:00
2013-04-09 13:43:24 +00:00
2013-05-19 15:45:03 +00:00
function TestExpatBindings ()
LOG ( "Testing Expat bindings..." );
-- Debug LuaExpat bindings:
2013-04-09 13:43:24 +00:00
local count = 0
callbacks = {
StartElement = function ( parser , name )
LOG ( "+ " .. string.rep ( " " , count ) .. name );
count = count + 1 ;
end ,
EndElement = function ( parser , name )
count = count - 1 ;
LOG ( "- " .. string.rep ( " " , count ) .. name );
end
}
local p = lxp.new ( callbacks );
p : parse ( "<elem1> \n next line \n another line" );
p : parse ( "text \n " );
p : parse ( "<elem2/> \n " );
p : parse ( "more text" );
p : parse ( "</elem1>" );
p : parse ( " \n " );
2013-05-19 15:45:03 +00:00
p : parse (); -- finishes the document
p : close (); -- closes the parser
LOG ( "Expat bindings test ended" );
2012-10-16 08:20:45 +00:00
end
2013-05-25 12:03:20 +00:00
function OnUsingBlazeRod ( Player , BlockX , BlockY , BlockZ , BlockFace , CursorX , CursorY , CursorZ )
-- Magic rod of query: show block types and metas for both neighbors of the pointed face
local Type , Meta , Valid = Player : GetWorld (): GetBlockTypeMeta ( BlockX , BlockY , BlockZ , Type , Meta );
if ( Type == E_BLOCK_AIR ) then
Player : SendMessage ( cChatColor.LightGray .. "Block {" .. BlockX .. ", " .. BlockY .. ", " .. BlockZ .. "}: air:" .. Meta );
else
local TempItem = cItem ( Type , 1 , Meta );
Player : SendMessage ( cChatColor.LightGray .. "Block {" .. BlockX .. ", " .. BlockY .. ", " .. BlockZ .. "}: " .. ItemToFullString ( TempItem ) .. " (" .. Type .. ":" .. Meta .. ")" );
end
local X , Y , Z = AddFaceDirection ( BlockX , BlockY , BlockZ , BlockFace );
Valid , Type , Meta = Player : GetWorld (): GetBlockTypeMeta ( X , Y , Z , Type , Meta );
if ( Type == E_BLOCK_AIR ) then
Player : SendMessage ( cChatColor.LightGray .. "Block {" .. X .. ", " .. Y .. ", " .. Z .. "}: air:" .. Meta );
else
local TempItem = cItem ( Type , 1 , Meta );
Player : SendMessage ( cChatColor.LightGray .. "Block {" .. X .. ", " .. Y .. ", " .. Z .. "}: " .. ItemToFullString ( TempItem ) .. " (" .. Type .. ":" .. Meta .. ")" );
end
return false ;
end
function OnUsingDiamond ( Player , BlockX , BlockY , BlockZ , BlockFace , CursorX , CursorY , CursorZ )
-- Rclk with a diamond to test block area cropping and expanding
local Area = cBlockArea ();
Area : Read ( Player : GetWorld (),
BlockX - 19 , BlockX + 19 ,
BlockY - 7 , BlockY + 7 ,
BlockZ - 19 , BlockZ + 19
);
LOG ( "Size before cropping: " .. Area : GetSizeX () .. " x " .. Area : GetSizeY () .. " x " .. Area : GetSizeZ ());
Area : DumpToRawFile ( "crop0.dat" );
Area : Crop ( 2 , 3 , 0 , 0 , 0 , 0 );
LOG ( "Size after cropping 1: " .. Area : GetSizeX () .. " x " .. Area : GetSizeY () .. " x " .. Area : GetSizeZ ());
Area : DumpToRawFile ( "crop1.dat" );
Area : Crop ( 2 , 3 , 0 , 0 , 0 , 0 );
LOG ( "Size after cropping 2: " .. Area : GetSizeX () .. " x " .. Area : GetSizeY () .. " x " .. Area : GetSizeZ ());
Area : DumpToRawFile ( "crop2.dat" );
Area : Expand ( 2 , 3 , 0 , 0 , 0 , 0 );
LOG ( "Size after expanding 1: " .. Area : GetSizeX () .. " x " .. Area : GetSizeY () .. " x " .. Area : GetSizeZ ());
Area : DumpToRawFile ( "expand1.dat" );
Area : Expand ( 3 , 2 , 1 , 1 , 0 , 0 );
LOG ( "Size after expanding 2: " .. Area : GetSizeX () .. " x " .. Area : GetSizeY () .. " x " .. Area : GetSizeZ ());
Area : DumpToRawFile ( "expand2.dat" );
Area : Crop ( 0 , 0 , 0 , 0 , 3 , 2 );
LOG ( "Size after cropping 3: " .. Area : GetSizeX () .. " x " .. Area : GetSizeY () .. " x " .. Area : GetSizeZ ());
Area : DumpToRawFile ( "crop3.dat" );
Area : Crop ( 0 , 0 , 3 , 2 , 0 , 0 );
LOG ( "Size after cropping 4: " .. Area : GetSizeX () .. " x " .. Area : GetSizeY () .. " x " .. Area : GetSizeZ ());
Area : DumpToRawFile ( "crop4.dat" );
LOG ( "Crop test done" );
Player : SendMessage ( "Crop / expand test done." );
return false ;
end
function OnUsingEyeOfEnder ( Player , BlockX , BlockY , BlockZ )
-- Rclk with an eye of ender places a predefined schematic at the cursor
local Area = cBlockArea ();
if not ( Area : LoadFromSchematicFile ( "schematics/test.schematic" )) then
LOG ( "Loading failed" );
return false ;
end
LOG ( "Schematic loaded, placing now." );
Area : Write ( Player : GetWorld (), BlockX , BlockY , BlockZ );
LOG ( "Done." );
return false ;
end
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
local Area = cBlockArea ();
if not ( Area : Read ( Player : GetWorld (),
BlockX - 8 , BlockX + 8 , BlockY - 8 , BlockY + 8 , BlockZ - 8 , BlockZ + 8 )
) then
LOG ( "LUA: Area couldn't be read" );
return false ;
end
LOG ( "LUA: Area read, copying now." );
local Area2 = cBlockArea ();
Area2 : CopyFrom ( Area );
LOG ( "LUA: Copied, now saving." );
if not ( Area2 : SaveToSchematicFile ( "schematics/test.schematic" )) then
LOG ( "LUA: Cannot save schematic file." );
return false ;
end
LOG ( "LUA: Done." );
return false ;
end
function OnUsingRedstoneTorch ( Player , BlockX , BlockY , BlockZ , BlockFace , CursorX , CursorY , CursorZ )
-- Redstone torch activates a rapid dispenser / dropper discharge (at every tick):
local BlockType = Player : GetWorld (): GetBlock ( BlockX , BlockY , BlockZ );
if ( BlockType == E_BLOCK_DISPENSER ) then
2013-05-26 14:39:04 +00:00
table.insert ( g_DropSpensersToActivate , { World = Player : GetWorld (), x = BlockX , y = BlockY , z = BlockZ });
2013-05-25 12:03:20 +00:00
Player : SendMessage ( "Dispenser at {" .. BlockX .. ", " .. BlockY .. ", " .. BlockZ .. "} discharging" );
return true ;
elseif ( BlockType == E_BLOCK_DROPPER ) then
2013-05-26 14:39:04 +00:00
table.insert ( g_DropSpensersToActivate , { World = Player : GetWorld (), x = BlockX , y = BlockY , z = BlockZ });
2013-05-25 12:03:20 +00:00
Player : SendMessage ( "Dropper at {" .. BlockX .. ", " .. BlockY .. ", " .. BlockZ .. "} discharging" );
return true ;
else
Player : SendMessage ( "Neither a dispenser nor a dropper at {" .. BlockX .. ", " .. BlockY .. ", " .. BlockZ .. "}: " .. BlockType );
end
return false ;
end
2013-01-13 11:10:26 +00:00
function OnPlayerUsingItem ( Player , BlockX , BlockY , BlockZ , BlockFace , CursorX , CursorY , CursorZ )
2012-10-16 08:20:45 +00:00
-- dont check if the direction is in the air
2013-01-13 11:10:26 +00:00
if ( BlockFace == BLOCK_FACE_NONE ) then
2012-10-16 08:20:45 +00:00
return false
end
2013-01-13 11:10:26 +00:00
local HeldItem = Player : GetEquippedItem ();
2013-05-25 12:03:20 +00:00
local HeldItemType = HeldItem.m_ItemType ;
2013-01-13 11:10:26 +00:00
2013-05-25 12:03:20 +00:00
if ( HeldItemType == E_ITEM_STICK ) then
2012-10-16 08:20:45 +00:00
-- Magic sTick of ticking: set the pointed block for ticking at the next tick
Player : SendMessage ( cChatColor.LightGray .. "Setting next block tick to {" .. BlockX .. ", " .. BlockY .. ", " .. BlockZ .. "}" )
Player : GetWorld (): SetNextBlockTick ( BlockX , BlockY , BlockZ );
return true
2013-05-25 12:03:20 +00:00
elseif ( HeldItemType == E_ITEM_BLAZE_ROD ) then
return OnUsingBlazeRod ( Player , BlockX , BlockY , BlockZ , BlockFace , CursorX , CursorY , CursorZ );
elseif ( HeldItemType == E_ITEM_DIAMOND ) then
return OnUsingDiamond ( Player , BlockX , BlockY , BlockZ , BlockFace , CursorX , CursorY , CursorZ );
elseif ( HeldItemType == E_ITEM_EYE_OF_ENDER ) then
return OnUsingEyeOfEnder ( Player , BlockX , BlockY , BlockZ , BlockFace , CursorX , CursorY , CursorZ );
elseif ( HeldItemType == E_ITEM_ENDER_PEARL ) then
return OnUsingEnderPearl ( Player , BlockX , BlockY , BlockZ , BlockFace , CursorX , CursorY , CursorZ );
2012-10-16 08:20:45 +00:00
end
2013-05-25 12:03:20 +00:00
return false ;
end
2012-10-16 08:20:45 +00:00
2013-02-06 22:29:29 +00:00
2013-01-13 11:10:26 +00:00
2013-02-06 18:22:30 +00:00
2013-02-06 22:29:29 +00:00
2013-05-25 12:03:20 +00:00
function OnPlayerUsingBlock ( Player , BlockX , BlockY , BlockZ , BlockFace , CursorX , CursorY , CursorZ , BlockType , BlockMeta )
-- dont check if the direction is in the air
if ( BlockFace == BLOCK_FACE_NONE ) then
return false
2013-02-06 18:22:30 +00:00
end
2013-05-25 12:03:20 +00:00
local HeldItem = Player : GetEquippedItem ();
local HeldItemType = HeldItem.m_ItemType ;
2013-02-06 22:29:29 +00:00
2013-05-25 12:03:20 +00:00
if ( HeldItemType == E_BLOCK_REDSTONE_TORCH_ON ) then
return OnUsingRedstoneTorch ( Player , BlockX , BlockY , BlockZ , BlockFace , CursorX , CursorY , CursorZ );
2013-02-06 22:29:29 +00:00
end
2012-10-16 08:20:45 +00:00
end
2012-12-21 11:22:46 +00:00
function OnTakeDamage ( Receiver , TDI )
-- Receiver is cPawn
-- TDI is TakeDamageInfo
LOG ( Receiver : GetClass () .. " was dealt RawDamage " .. TDI.RawDamage .. ", FinalDamage " .. TDI.FinalDamage .. " (that is, " .. ( TDI.RawDamage - TDI.FinalDamage ) .. " HPs covered by armor)" );
2013-05-25 12:03:20 +00:00
return false ;
end
2013-05-30 19:34:09 +00:00
--- When set to a positive number, the following OnTick() will perform GC and decrease until 0 again
GCOnTick = 0 ;
2013-05-25 12:03:20 +00:00
function OnTick ()
2013-05-26 14:39:04 +00:00
-- Activate all dropspensers in the g_DropSpensersToActivate list:
local ActivateDrSp = function ( DropSpenser )
if ( DropSpenser : GetContents (): GetFirstUsedSlot () == - 1 ) then
2013-05-25 12:03:20 +00:00
return true ;
end
2013-05-26 14:39:04 +00:00
DropSpenser : Activate ();
2013-05-25 12:03:20 +00:00
return false ;
end
2013-05-26 14:39:04 +00:00
-- Walk the list backwards, because we're removing some items
local idx = # g_DropSpensersToActivate ;
2013-05-25 12:03:20 +00:00
for i = idx , 1 , - 1 do
2013-05-26 14:39:04 +00:00
local DrSp = g_DropSpensersToActivate [ i ];
if not ( DrSp.World : DoWithDropSpenserAt ( DrSp.x , DrSp.y , DrSp.z , ActivateDrSp )) then
table.remove ( g_DropSpensersToActivate , i );
2013-05-25 12:03:20 +00:00
end
end
2013-05-30 19:34:09 +00:00
-- If GCOnTick > 0, do a garbage-collect and decrease by one
if ( GCOnTick > 0 ) then
collectgarbage ();
GCOnTick = GCOnTick - 1 ;
end
2013-05-25 12:03:20 +00:00
return false ;
2012-12-21 11:22:46 +00:00
end
2013-02-08 20:57:42 +00:00
function OnChunkGenerated ( World , ChunkX , ChunkZ , ChunkDesc )
-- Test ChunkDesc / BlockArea interaction
local BlockArea = cBlockArea ();
ChunkDesc : ReadBlockArea ( BlockArea , 0 , 15 , 50 , 70 , 0 , 15 );
2013-02-09 11:03:22 +00:00
-- BlockArea:SaveToSchematicFile("ChunkBlocks_" .. ChunkX .. "_" .. ChunkZ .. ".schematic");
2013-02-08 20:57:42 +00:00
ChunkDesc : WriteBlockArea ( BlockArea , 5 , 115 , 5 );
return false ;
end
2013-05-19 15:45:03 +00:00
-- Function "round" copied from http://lua-users.org/wiki/SimpleRound
function round ( num , idp )
local mult = 10 ^ ( idp or 0 )
if num >= 0 then return math.floor ( num * mult + 0.5 ) / mult
else return math.ceil ( num * mult - 0.5 ) / mult end
end
function HandleListEntitiesCmd ( Split , Player )
local NumEntities = 0 ;
local ListEntity = function ( Entity )
if ( Entity : IsDestroyed ()) then
-- The entity has already been destroyed, don't list it
return false ;
end ;
Player : SendMessage ( " " .. Entity : GetUniqueID () .. ": " .. Entity : GetClass () .. " {" .. round ( Entity : GetPosX (), 2 ) .. ", " .. round ( Entity : GetPosY (), 2 ) .. ", " .. round ( Entity : GetPosZ (), 2 ) .. "}" );
NumEntities = NumEntities + 1 ;
end
Player : SendMessage ( "Listing all entities..." );
Player : GetWorld (): ForEachEntity ( ListEntity );
Player : SendMessage ( "List finished, " .. NumEntities .. " entities listed" );
return true ;
end
function HandleKillEntitiesCmd ( Split , Player )
local NumEntities = 0 ;
local KillEntity = function ( Entity )
-- kill everything except for players:
if ( Entity : GetEntityType () ~= cEntity.etPlayer ) then
Entity : Destroy ();
NumEntities = NumEntities + 1 ;
end ;
end
Player : SendMessage ( "Killing all entities..." );
Player : GetWorld (): ForEachEntity ( KillEntity );
Player : SendMessage ( "Killed " .. NumEntities .. " entities." );
return true ;
end
2013-05-19 18:37:01 +00:00
function HandleWoolCmd ( Split , Player )
local Wool = cItem ( E_BLOCK_WOOL , 1 , E_META_WOOL_BLUE );
2013-05-24 07:30:39 +00:00
Player : GetInventory (): SetArmorSlot ( 0 , Wool );
Player : GetInventory (): SetArmorSlot ( 1 , Wool );
Player : GetInventory (): SetArmorSlot ( 2 , Wool );
Player : GetInventory (): SetArmorSlot ( 3 , Wool );
2013-05-19 18:41:16 +00:00
Player : SendMessage ( "You have been bluewooled :)" );
2013-05-19 18:37:01 +00:00
return true ;
2013-05-30 19:34:09 +00:00
end
function HandleTestWndCmd ( a_Split , a_Player )
local WindowType = cWindow.Hopper ;
local WindowSizeX = 5 ;
local WindowSizeY = 1 ;
if ( # a_Split == 4 ) then
WindowType = tonumber ( a_Split [ 2 ]);
WindowSizeX = tonumber ( a_Split [ 3 ]);
WindowSizeY = tonumber ( a_Split [ 4 ]);
elseif ( # a_Split ~= 1 ) then
a_Player : SendMessage ( "Usage: /testwnd [WindowType WindowSizeX WindowSizeY]" );
return true ;
end
2013-05-30 20:40:43 +00:00
-- Test out the OnClosing callback's ability to refuse to close the window
local attempt = 1 ;
2013-06-02 21:59:25 +00:00
local OnClosing = function ( Window , Player , CanRefuse )
Player : SendMessage ( "Window closing attempt #" .. attempt .. "; CanRefuse = " .. tostring ( CanRefuse ));
2013-05-30 20:40:43 +00:00
attempt = attempt + 1 ;
2013-06-02 21:59:25 +00:00
return CanRefuse and ( attempt <= 3 ); -- refuse twice, then allow, unless CanRefuse is set to true
2013-05-30 20:40:43 +00:00
end
2013-05-31 07:16:14 +00:00
-- Log the slot changes
local OnSlotChanged = function ( Window , SlotNum )
LOG ( "Window \" " .. Window : GetWindowTitle () .. " \" slot " .. SlotNum .. " changed." );
end
2013-05-30 19:34:09 +00:00
local Window = cLuaWindow ( WindowType , WindowSizeX , WindowSizeY , "TestWnd" );
2013-06-02 21:21:32 +00:00
local Item2 = cItem ( E_ITEM_DIAMOND_SWORD , 1 , 0 , "1=1" );
local Item3 = cItem ( E_ITEM_DIAMOND_SHOVEL );
Item3.m_Enchantments : SetLevel ( cEnchantments.enchUnbreaking , 4 );
2013-06-04 11:54:44 +00:00
local Item4 = cItem ( Item3 ); -- Copy
Item4.m_Enchantments : SetLevel ( cEnchantments.enchEfficiency , 3 ); -- Add enchantment
Item4.m_Enchantments : SetLevel ( cEnchantments.enchUnbreaking , 5 ); -- Overwrite existing level
2013-06-02 21:44:24 +00:00
local Item5 = cItem ( E_ITEM_DIAMOND_CHESTPLATE , 1 , 0 , "thorns=1;unbreaking=3" );
2013-05-30 19:34:09 +00:00
Window : SetSlot ( a_Player , 0 , cItem ( E_ITEM_DIAMOND , 64 ));
2013-06-02 21:21:32 +00:00
Window : SetSlot ( a_Player , 1 , Item2 );
Window : SetSlot ( a_Player , 2 , Item3 );
Window : SetSlot ( a_Player , 3 , Item4 );
2013-06-02 21:44:24 +00:00
Window : SetSlot ( a_Player , 4 , Item5 );
2013-05-30 20:40:43 +00:00
Window : SetOnClosing ( OnClosing );
2013-05-31 07:16:14 +00:00
Window : SetOnSlotChanged ( OnSlotChanged );
2013-05-30 19:34:09 +00:00
a_Player : OpenWindow ( Window );
-- To make sure that the object has the correct life-management in Lua,
-- let's garbage-collect in the following few ticks
GCOnTick = 10 ;
return true ;
end
function HandleGCCmd ( a_Split , a_Player )
collectgarbage ();
return true ;
end