summaryrefslogtreecommitdiffstats
path: root/MCServer/Plugins
diff options
context:
space:
mode:
Diffstat (limited to 'MCServer/Plugins')
-rw-r--r--MCServer/Plugins/APIDump/APIDesc.lua34
-rw-r--r--MCServer/Plugins/APIDump/Classes/Network.lua1
-rw-r--r--MCServer/Plugins/APIDump/Hooks/OnEntityTeleport.lua29
-rw-r--r--MCServer/Plugins/APIDump/main_APIDump.lua110
m---------MCServer/Plugins/Core0
-rw-r--r--MCServer/Plugins/Debuggers/Debuggers.lua130
-rw-r--r--MCServer/Plugins/Debuggers/Info.lua12
-rw-r--r--MCServer/Plugins/HookNotify/HookNotify.lua17
-rw-r--r--MCServer/Plugins/NetworkTest/Info.lua6
-rw-r--r--MCServer/Plugins/NetworkTest/NetworkTest.lua13
10 files changed, 321 insertions, 31 deletions
diff --git a/MCServer/Plugins/APIDump/APIDesc.lua b/MCServer/Plugins/APIDump/APIDesc.lua
index f2ec2546a..92cdb7415 100644
--- a/MCServer/Plugins/APIDump/APIDesc.lua
+++ b/MCServer/Plugins/APIDump/APIDesc.lua
@@ -925,8 +925,8 @@ local Hash = cCryptoHash.sha1HexString("DataToHash")
{ Params = "DamageType, AttackerEntity, RawDamage, KnockbackAmount", Return = "", Notes = "Causes this entity to take damage of the specified type, from the specified attacker (may be nil). The final damage is calculated from RawDamage using the currently equipped armor." },
{ Params = "DamageType, ArrackerEntity, RawDamage, FinalDamage, KnockbackAmount", Return = "", Notes = "Causes this entity to take damage of the specified type, from the specified attacker (may be nil). The values are wrapped into a {{TakeDamageInfo}} structure and applied directly." },
},
- TeleportToCoords = { Params = "PosX, PosY, PosZ", Return = "", Notes = "Teleports the entity to the specified coords." },
- TeleportToEntity = { Params = "DestEntity", Return = "", Notes = "Teleports this entity to the specified destination entity." },
+ TeleportToCoords = { Params = "PosX, PosY, PosZ", Return = "", Notes = "Teleports the entity to the specified coords. Asks plugins if the teleport is allowed." },
+ TeleportToEntity = { Params = "DestEntity", Return = "", Notes = "Teleports this entity to the specified destination entity. Asks plugins if the teleport is allowed." },
},
Constants =
{
@@ -2871,41 +2871,18 @@ end
This class represents the tolua bridge between the Lua API and MCServer. It supports some low
level operations and queries on the objects. See also the tolua++'s documentation at
{{http://www.codenix.com/~tolua/tolua++.html#utilities}}. Normally you shouldn't use any of these
- functions except for cast() and type()
+ functions except for type()
]],
Functions =
{
- cast = { Params = "Object, TypeStr", Return = "Object", Notes = "Casts the object to the specified type through the inheritance hierarchy." },
+ cast = { Params = "Object, TypeStr", Return = "Object", Notes = "Casts the object to the specified type.<br/><b>Note:</b> This is a potentially unsafe operation and it could crash the server. There is normally no need to use this function at all, so don't use it unless you know exactly what you're doing." },
getpeer = { Params = "", Return = "", Notes = "" },
inherit = { Params = "", Return = "", Notes = "" },
releaseownership = { Params = "", Return = "", Notes = "" },
setpeer = { Params = "", Return = "", Notes = "" },
takeownership = { Params = "", Return = "", Notes = "" },
- type = { Params = "Object", Return = "TypeStr", Notes = "Returns a string representing the type of the object. This works similar to Lua's built-in type() function, but recognizes the underlying C++ types, too." },
+ type = { Params = "Object", Return = "TypeStr", Notes = "Returns a string representing the type of the object. This works similar to Lua's built-in type() function, but recognizes the underlying C++ classes, too." },
},
- AdditionalInfo =
- {
- {
- Header = "Usage example",
- Contents =
- [[
- The tolua.cast() function is normally used to cast between related types. For example in the
- hook callbacks you often receive a generic {{cEntity}} object, when in fact you know that the
- object is a {{cMonster}}. You can cast the object to access its cMonster functions:
-<pre class="prettyprint lang-lua">
-function OnTakeDamage(a_ReceiverEntity, TDI)
- if (a_ReceiverEntity.IsMob()) then
- local Mob = tolua.cast(a_ReceiverEntity, "cMonster"); -- Cast a_ReceiverEntity into a {{cMonster}} instance
- if (Mob:GetMonsterType() == cMonster.mtSheep) then
- local Sheep = tolua.cast(Mob, "cSheep"); -- Cast Mob into a {{cSheep}} instance
- -- Do something sheep-specific
- end
- end
-end
-</pre>
- ]],
- }
- } -- AdditionalInfo
}, -- tolua
Globals =
@@ -2965,6 +2942,7 @@ end
RotateBlockFaceCW = { Params = "{{Globals#BlockFaces|eBlockFace}}", Return = "{{Globals#BlockFaces|eBlockFace}}", Notes = "Returns the {{Globals#BlockFaces|eBlockFace}} that corresponds to the given {{Globals#BlockFaces|eBlockFace}} after rotating it around the Y axis 90 degrees clockwise." },
StringSplit = {Params = "string, SeperatorsString", Return = "array table of strings", Notes = "Seperates string into multiple by splitting every time any of the characters in SeperatorsString is encountered."},
StringSplitAndTrim = {Params = "string, SeperatorsString", Return = "array table of strings", Notes = "Seperates string into multiple by splitting every time any of the characters in SeperatorsString is encountered. Each of the separate strings is trimmed (whitespace removed from the beginning and end of the string)"},
+ StringSplitWithQuotes = {Params = "string, SeperatorsString", Return = "array table of strings", Notes = "Seperates string into multiple by splitting every time any of the characters in SeperatorsString is encountered. Whitespace wrapped with single or double quotes will be ignored"},
StringToBiome = {Params = "string", Return = "{{Globals#BiomeTypes|BiomeType}}", Notes = "Converts a string representation to a {{Globals#BiomeTypes|BiomeType}} enumerated value"},
StringToDamageType = {Params = "string", Return = "{{Globals#DamageType|DamageType}}", Notes = "Converts a string representation to a {{Globals#DamageType|DamageType}} enumerated value."},
StringToDimension = {Params = "string", Return = "{{Globals#WorldDimension|Dimension}}", Notes = "Converts a string representation to a {{Globals#WorldDimension|Dimension}} enumerated value"},
diff --git a/MCServer/Plugins/APIDump/Classes/Network.lua b/MCServer/Plugins/APIDump/Classes/Network.lua
index 797788661..c7626562d 100644
--- a/MCServer/Plugins/APIDump/Classes/Network.lua
+++ b/MCServer/Plugins/APIDump/Classes/Network.lua
@@ -289,6 +289,7 @@ g_Server = nil
{
Connect = { Params = "Host, Port, LinkCallbacks", Return = "bool", Notes = "(STATIC) Begins establishing a (client) TCP connection to the specified host. Uses the LinkCallbacks table to report progress, success, errors and incoming data. Returns false if it fails immediately (bad port value, bad hostname format), true otherwise. Host can be either an IP address or a hostname." },
CreateUDPEndpoint = { Params = "Port, UDPCallbacks", Return = "{{cUDPEndpoint|UDPEndpoint}}", Notes = "(STATIC) Creates a UDP endpoint that listens for incoming datagrams on the specified port, and can be used to send or broadcast datagrams. Uses the UDPCallbacks to report incoming datagrams or errors. If the endpoint cannot be created, the OnError callback is called with the error details and the returned endpoint will report IsOpen() == false. The plugin needs to store the returned endpoint object for as long as it needs the UDP port open; if the endpoint is garbage-collected by Lua, the socket will be closed and no more incoming data will be reported.<br>If the Port is zero, the OS chooses an available UDP port for the endpoint; use {{cUDPEndpoint}}:GetPort() to query the port number in such case." },
+ EnumLocalIPAddresses = { Params = "", Return = "array-table of strings", Notes = "(STATIC) Returns all local IP addresses for network interfaces currently available on the machine." },
HostnameToIP = { Params = "Host, LookupCallbacks", Return = "bool", Notes = "(STATIC) Begins a DNS lookup to find the IP address(es) for the specified host. Uses the LookupCallbacks table to report progress, success or errors. Returns false if it fails immediately (bad hostname format), true if the lookup started successfully. Host can be either a hostname or an IP address." },
IPToHostname = { Params = "Address, LookupCallbacks", Return = "bool", Notes = "(STATIC) Begins a reverse-DNS lookup to find out the hostname for the specified IP address. Uses the LookupCallbacks table to report progress, success or errors. Returns false if it fails immediately (bad address format), true if the lookup started successfully." },
Listen = { Params = "Port, ListenCallbacks", Return = "{{cServerHandle|ServerHandle}}", Notes = "(STATIC) Starts listening on the specified port. Uses the ListenCallbacks to report incoming connections or errors. Returns a {{cServerHandle}} object representing the server. If the listen operation failed, the OnError callback is called with the error details and the returned server handle will report IsListening() == false. The plugin needs to store the server handle object for as long as it needs the server running, if the server handle is garbage-collected by Lua, the listening socket will be closed and all current connections dropped." },
diff --git a/MCServer/Plugins/APIDump/Hooks/OnEntityTeleport.lua b/MCServer/Plugins/APIDump/Hooks/OnEntityTeleport.lua
new file mode 100644
index 000000000..cdeb0947f
--- /dev/null
+++ b/MCServer/Plugins/APIDump/Hooks/OnEntityTeleport.lua
@@ -0,0 +1,29 @@
+return
+{
+ HOOK_ENTITY_TELEPORT =
+ {
+ CalledWhen = "Any entity teleports. Plugin may refuse teleport.",
+ DefaultFnName = "OnEntityTeleport", -- also used as pagename
+ Desc = [[
+ This function is called in each server tick for each {{cEntity|Entity}} that has
+ teleported. Plugins may refuse the teleport.
+ ]],
+ Params =
+ {
+ { Name = "Entity", Type = "{{cEntity}}", Notes = "The entity who has teleported. New position is set in the object after successfull teleport" },
+ { Name = "OldPosition", Type = "{{Vector3d}}", Notes = "The old position." },
+ { Name = "NewPosition", Type = "{{Vector3d}}", Notes = "The new position." },
+ },
+ Returns = [[
+ If the function returns true, teleport is prohibited.</p>
+ <p>
+ If the function returns false or no value, other plugins' callbacks are called and finally the new
+ position is permanently stored in the cEntity object.</p>
+ ]],
+ }, -- HOOK_ENTITY_TELEPORT
+}
+
+
+
+
+
diff --git a/MCServer/Plugins/APIDump/main_APIDump.lua b/MCServer/Plugins/APIDump/main_APIDump.lua
index a25bab9cf..239bec69c 100644
--- a/MCServer/Plugins/APIDump/main_APIDump.lua
+++ b/MCServer/Plugins/APIDump/main_APIDump.lua
@@ -62,7 +62,7 @@ local function CreateAPITables()
Variables = {
},
Descendants = {}, -- Will be filled by ReadDescriptions(), array of class APIs (references to other member in the tree)
- }},
+ },
{
Name = "cBlockArea",
Functions = {
@@ -78,7 +78,9 @@ local function CreateAPITables()
Variables = {
},
...
- }}
+ },
+
+ cCuboid = {} -- Each array item also has the map item by its name
};
local Globals = {
Functions = {
@@ -135,7 +137,9 @@ local function CreateAPITables()
(v ~= g_APIDesc)
) then
if (type(v) == "table") then
- table.insert(API, ParseClass(i, v));
+ local cls = ParseClass(i, v)
+ table.insert(API, cls);
+ API[cls.Name] = cls
else
Add(Globals, i, v);
end
@@ -1449,6 +1453,103 @@ end
+--- Returns true if a_Descendant is declared to be a (possibly indirect) descendant of a_Base
+local function IsDeclaredDescendant(a_DescendantName, a_BaseName, a_API)
+ -- Check params:
+ assert(type(a_DescendantName) == "string")
+ assert(type(a_BaseName) == "string")
+ assert(type(a_API) == "table")
+ if not(a_API[a_BaseName]) then
+ return false
+ end
+ assert(type(a_API[a_BaseName]) == "table", "Not a class name: " .. a_BaseName)
+ assert(type(a_API[a_BaseName].Descendants) == "table")
+
+ -- Check direct inheritance:
+ for _, desc in ipairs(a_API[a_BaseName].Descendants) do
+ if (desc.Name == a_DescendantName) then
+ return true
+ end
+ end -- for desc - a_BaseName's descendants
+
+ -- Check indirect inheritance:
+ for _, desc in ipairs(a_API[a_BaseName].Descendants) do
+ if (IsDeclaredDescendant(a_DescendantName, desc.Name, a_API)) then
+ return true
+ end
+ end -- for desc - a_BaseName's descendants
+
+ return false
+end
+
+
+
+
+
+--- Checks the specified class' inheritance
+-- Reports any problems as new items in the a_Report table
+local function CheckClassInheritance(a_Class, a_API, a_Report)
+ -- Check params:
+ assert(type(a_Class) == "table")
+ assert(type(a_API) == "table")
+ assert(type(a_Report) == "table")
+
+ -- Check that the declared descendants are really descendants:
+ local registry = debug.getregistry()
+ for _, desc in ipairs(a_Class.Descendants or {}) do
+ local isParent = false
+ local parents = registry["tolua_super"][_G[desc.Name]]
+ if not(parents[a_Class.Name]) then
+ table.insert(a_Report, desc.Name .. " is not a descendant of " .. a_Class.Name)
+ end
+ end -- for desc - a_Class.Descendants[]
+
+ -- Check that all inheritance is listed for the class:
+ local parents = registry["tolua_super"][_G[a_Class.Name]] -- map of "classname" -> true for each class that a_Class inherits
+ for clsName, isParent in pairs(parents or {}) do
+ if ((clsName ~= "") and not(clsName:match("const .*"))) then
+ if not(IsDeclaredDescendant(a_Class.Name, clsName, a_API)) then
+ table.insert(a_Report, a_Class.Name .. " inherits from " .. clsName .. " but this isn't documented")
+ end
+ end
+ end
+end
+
+
+
+
+
+--- Checks each class's declared inheritance versus the actual inheritance
+local function CheckAPIDescendants(a_API)
+ -- Check each class:
+ local report = {}
+ for _, cls in ipairs(a_API) do
+ if (cls.Name ~= "Globals") then
+ CheckClassInheritance(cls, a_API, report)
+ end
+ end
+
+ -- If there's anything to report, output it to a file:
+ if (report[1] ~= nil) then
+ LOG("There are inheritance errors in the API description:")
+ for _, msg in ipairs(report) do
+ LOG(" " .. msg)
+ end
+
+ local f, err = io.open("API/_inheritance_errors.txt", "w")
+ if (f == nil) then
+ LOG("Cannot report inheritance problems to a file: " .. tostring(err))
+ return
+ end
+ f:write(table.concat(report, "\n"))
+ f:close()
+ end
+end
+
+
+
+
+
local function DumpApi()
LOG("Dumping the API...")
@@ -1501,6 +1602,9 @@ local function DumpApi()
LOG("Reading descriptions...");
ReadDescriptions(API);
+ -- Check that the API lists the inheritance properly, report any problems to a file:
+ CheckAPIDescendants(API)
+
-- Dump all available API objects in HTML format into a subfolder:
DumpAPIHtml(API);
diff --git a/MCServer/Plugins/Core b/MCServer/Plugins/Core
-Subproject 6e9d612b9eb548d888d2bf986488aad762a99be
+Subproject ee3cd9ba917baa94d6b9bfe7c9205609e0722fa
diff --git a/MCServer/Plugins/Debuggers/Debuggers.lua b/MCServer/Plugins/Debuggers/Debuggers.lua
index c8069a411..d0c362ab4 100644
--- a/MCServer/Plugins/Debuggers/Debuggers.lua
+++ b/MCServer/Plugins/Debuggers/Debuggers.lua
@@ -1643,6 +1643,81 @@ end
+--- Monitors the state of the "inh" entity-spawning hook
+-- if false, the hook is installed before the "inh" command processing
+local isInhHookInstalled = false
+
+function HandleConsoleInh(a_Split, a_FullCmd)
+ -- Check the param:
+ local kindStr = a_Split[2] or "pkArrow"
+ local kind = cProjectileEntity[kindStr]
+ if (kind == nil) then
+ return true, "There's no projectile kind '" .. kindStr .. "'."
+ end
+
+ -- Get the world to test in:
+ local world = cRoot:Get():GetDefaultWorld()
+ if (world == nil) then
+ return true, "Cannot test inheritance, no default world"
+ end
+
+ -- Install the hook, if needed:
+ if not(isInhHookInstalled) then
+ cPluginManager:AddHook(cPluginManager.HOOK_SPAWNING_ENTITY,
+ function (a_CBWorld, a_CBEntity)
+ LOG("New entity is spawning:")
+ LOG(" Lua type: '" .. type(a_CBEntity) .. "'")
+ LOG(" ToLua type: '" .. tolua.type(a_CBEntity) .. "'")
+ LOG(" GetEntityType(): '" .. a_CBEntity:GetEntityType() .. "'")
+ LOG(" GetClass(): '" .. a_CBEntity:GetClass() .. "'")
+ end
+ )
+ isInhHookInstalled = true
+ end
+
+ -- Create the projectile:
+ LOG("Creating a " .. kindStr .. " projectile in world " .. world:GetName() .. "...")
+ local msg
+ world:ChunkStay({{0, 0}},
+ nil,
+ function ()
+ -- Create a projectile at {8, 100, 8}:
+ local entityID = world:CreateProjectile(8, 100, 8, kind, nil, nil)
+ if (entityID < 0) then
+ msg = "Cannot test inheritance, projectile creation failed."
+ return
+ end
+ LOG("Entity created, ID #" .. entityID)
+
+ -- Call a function on the newly created entity:
+ local hasExecutedCallback = false
+ world:DoWithEntityByID(
+ entityID,
+ function (a_CBEntity)
+ LOG("Projectile created and found using the DoWithEntityByID() callback")
+ LOG("Lua type: '" .. type(a_CBEntity) .. "'")
+ LOG("ToLua type: '" .. tolua.type(a_CBEntity) .. "'")
+ LOG("GetEntityType(): '" .. a_CBEntity:GetEntityType() .. "'")
+ LOG("GetClass(): '" .. a_CBEntity:GetClass() .. "'")
+ hasExecutedCallback = true
+ end
+ )
+ if not(hasExecutedCallback) then
+ msg = "The callback failed to execute"
+ return
+ end
+
+ msg = "Inheritance test finished"
+ end
+ )
+
+ return true, msg
+end
+
+
+
+
+
function HandleConsoleLoadChunk(a_Split)
-- Check params:
local numParams = #a_Split
@@ -1741,3 +1816,58 @@ end
+
+function HandleConsoleBBox(a_Split)
+ local bbox = cBoundingBox(0, 10, 0, 10, 0, 10)
+ local v1 = Vector3d(1, 1, 1)
+ local v2 = Vector3d(5, 5, 5)
+ local v3 = Vector3d(11, 11, 11)
+
+ if (bbox:IsInside(v1)) then
+ LOG("v1 is inside bbox")
+ else
+ LOG("v1 is not inside bbox")
+ end
+
+ if (bbox:IsInside(v2)) then
+ LOG("v2 is inside bbox")
+ else
+ LOG("v2 is not inside bbox")
+ end
+
+ if (bbox:IsInside(v3)) then
+ LOG("v3 is inside bbox")
+ else
+ LOG("v3 is not inside bbox")
+ end
+
+ if (bbox:IsInside(v1, v2)) then
+ LOG("v1*v2 is inside bbox")
+ else
+ LOG("v1*v2 is not inside bbox")
+ end
+
+ if (bbox:IsInside(v2, v1)) then
+ LOG("v2*v1 is inside bbox")
+ else
+ LOG("v2*v1 is not inside bbox")
+ end
+
+ if (bbox:IsInside(v1, v3)) then
+ LOG("v1*v3 is inside bbox")
+ else
+ LOG("v1*v3 is not inside bbox")
+ end
+
+ if (bbox:IsInside(v2, v3)) then
+ LOG("v2*v3 is inside bbox")
+ else
+ LOG("v2*v3 is not inside bbox")
+ end
+
+ return true
+end
+
+
+
+
diff --git a/MCServer/Plugins/Debuggers/Info.lua b/MCServer/Plugins/Debuggers/Info.lua
index 63a4b9177..0370145df 100644
--- a/MCServer/Plugins/Debuggers/Info.lua
+++ b/MCServer/Plugins/Debuggers/Info.lua
@@ -200,12 +200,24 @@ g_PluginInfo =
ConsoleCommands =
{
+ ["bbox"] =
+ {
+ Handler = HandleConsoleBBox,
+ HelpString = "Performs cBoundingBox API tests",
+ },
+
["hash"] =
{
Handler = HandleConsoleHash,
HelpString = "Tests the crypto hashing functions",
},
+ ["inh"] =
+ {
+ Handler = HandleConsoleInh,
+ HelpString = "Tests the bindings of the cEntity inheritance",
+ },
+
["loadchunk"] =
{
Handler = HandleConsoleLoadChunk,
diff --git a/MCServer/Plugins/HookNotify/HookNotify.lua b/MCServer/Plugins/HookNotify/HookNotify.lua
index ed791090e..1d3d5088e 100644
--- a/MCServer/Plugins/HookNotify/HookNotify.lua
+++ b/MCServer/Plugins/HookNotify/HookNotify.lua
@@ -23,6 +23,7 @@ function Initialize(Plugin)
cPluginManager.AddHook(cPluginManager.HOOK_COLLECTING_PICKUP, OnCollectingPickup);
cPluginManager.AddHook(cPluginManager.HOOK_CRAFTING_NO_RECIPE, OnCraftingNoRecipe);
cPluginManager.AddHook(cPluginManager.HOOK_DISCONNECT, OnDisconnect);
+ cPluginManager.AddHook(cPluginManager.HOOK_ENTITY_TELEPORT, OnEntityTeleport);
cPluginManager.AddHook(cPluginManager.HOOK_EXECUTE_COMMAND, OnExecuteCommand);
cPluginManager.AddHook(cPluginManager.HOOK_HANDSHAKE, OnHandshake);
cPluginManager.AddHook(cPluginManager.HOOK_KILLING, OnKilling);
@@ -179,6 +180,22 @@ end
+function OnEntityTeleport(arg1,arg2,arg3)
+ if arg1.IsPlayer() then
+ -- if it's a player, get his name
+ LOG("OnEntityTeleport: Player: " .. arg1.GetName());
+ else
+ -- if it's a entity, get its type
+ LOG("OnEntityTeleport: EntityType: " .. arg1.GetEntityType());
+ end
+ LOG("OldPos: " .. arg2.x .. " / " .. arg2.y .. " / " .. arg2.z);
+ LOG("NewPos: " .. arg3.x .. " / " .. arg3.y .. " / " .. arg3.z);
+end
+
+
+
+
+
function OnExecuteCommand(...)
LogHook("OnExecuteCommand", unpack(arg));
diff --git a/MCServer/Plugins/NetworkTest/Info.lua b/MCServer/Plugins/NetworkTest/Info.lua
index 52422d427..d8c3095fe 100644
--- a/MCServer/Plugins/NetworkTest/Info.lua
+++ b/MCServer/Plugins/NetworkTest/Info.lua
@@ -50,6 +50,12 @@ g_PluginInfo =
}, -- ParameterCombinations
}, -- close
+ ips =
+ {
+ HelpString = "Prints all locally available IP addresses",
+ Handler = HandleConsoleNetIps,
+ }, -- ips
+
listen =
{
HelpString = "Creates a new listening socket on the specified port with the specified service attached to it",
diff --git a/MCServer/Plugins/NetworkTest/NetworkTest.lua b/MCServer/Plugins/NetworkTest/NetworkTest.lua
index daab0a4bf..22056d4e9 100644
--- a/MCServer/Plugins/NetworkTest/NetworkTest.lua
+++ b/MCServer/Plugins/NetworkTest/NetworkTest.lua
@@ -288,6 +288,19 @@ end
+function HandleConsoleNetIps(a_Split)
+ local Addresses = cNetwork:EnumLocalIPAddresses()
+ LOG("IP addresses enumerated, " .. #Addresses .. " found")
+ for idx, addr in ipairs(Addresses) do
+ LOG(" IP #" .. idx .. ": " .. addr)
+ end
+ return true
+end
+
+
+
+
+
function HandleConsoleNetLookup(a_Split)
-- Get the name to look up:
local Addr = a_Split[3] or "google.com"