Cuberite Forum
Lua hooks needed! - Printable Version

+- Cuberite Forum (https://forum.cuberite.org)
+-- Forum: Cuberite (https://forum.cuberite.org/forum-4.html)
+--- Forum: Development (https://forum.cuberite.org/forum-13.html)
+--- Thread: Lua hooks needed! (/thread-464.html)

Pages: 1 2 3 4 5 6 7 8 9 10 11 12 13


Lua hooks needed! - Taugeshtu - 06-05-2012

Okay, here's the deal:

I'm getting serious and going to use MCS seriously. I mean, on a public server. Thus I got to write several plugins, for which I would like to have several new hooks. Such as:

OnCrafting( cCraftOperation )
By cCraftOperation I mean some way to get cPlayer (who's crafting) and cItem of recipe result, that was recognized by MCS. This hook should return cItem as well (the one that will be displayed as crafting result and will be grabbed by player).
What for:
For example, I would like to make "classes" - some classes could craft diamond instruments, some couldn't. With such a hook I can easily change diamond axe input into iron axe output. Or I can take into account the fact that player is standing in special "area" that allows him to craft items with full HP instead of damaged.
If plugin returns nil, then default recipe is used (such behavior could be used for "exp for crafting" plugin)

LateTick()
This one could be really handy for organizing plugin<->plugin interactions through .ini-s. Or you can add some structures for shared data access. (Oh, I just got an idea that cIniFile could be such a structure, am I right? I mean, it stores all .ini keys and values in RAM till it will be written, right?)

OnChunkPopulate( cChunk or something like that )
What for: adding new blocks, changing existing population methid (Yessss, strategic oregen!)


RE: Lua hooks needed! - xoft - 06-06-2012

OnCrafting:
- the internal C++ implementation uses an array of cItems, together with the dimensions, to describe the crafting grid. It seems easier to use than a custom object just for the callback.
- the internal C++ implementation not only provides the output item, it also "processes" the recipe - it removes the ingredients that the recipe specifies, from the crafting grid. That's the only way to specify recipes that take more items in a single slot (a currently unused feature, but still present in the code)
- I could probably write this hook, I'm not too sure on Lua interfacing yet, but I think there's enough sample code for me to manage

LateTick:
- I have no idea what you mean
- When should it be called, who should call it, what parameters?

OnChunkPopulate:
- Called only for freshly generated terrain, or for a chunk loaded from storage as well?
- If you want to change generator, you should split this callback into two - one called before the actual generator kicks in, one after. Why let it generate terrain, if you're gonna overwrite it all?
- I could probably write both of these. The post-generation is much easier; pre-generation will be more tricky, due to the data transfer.
Seems a bit more difficult than anticipated - chunks can be generated even before the plugin subsystem is fully initialized - when the world is generating the spawn for the first time. This will need some extra care.


RE: Lua hooks needed! - xoft - 06-06-2012

Wow, I'm good Smile
OnChunkGenerated hook is available in Rev 558. It is called by the chunk generator each time a new chunk is generated. At the time of calling, the chunk is already valid in cWorld, so it can be modified directly using cWorld's methods (note that they are notoriously slow, you don't want to query an entire chunk block-by-block!)

Here's a quick sample plugin that uses that hook. It logs every chunk generated and then places a glowstone block at the XZ center of each chunk in Y=40:
Code:
function Initialize( Plugin )
    PLUGIN = Plugin
    
    Plugin:SetName( "GeneLog" )
    Plugin:SetVersion(1)
    
    PluginManager = cRoot:Get():GetPluginManager()
    PluginManager:AddHook(Plugin, cPluginManager.E_PLUGIN_CHUNK_GENERATED)
    
    LOG( "Initialized " .. Plugin:GetName() .. " v." .. Plugin:GetVersion() )
    return true
end


function OnChunkGenerated(World, ChunkX, ChunkZ)

    LOG("Lua GeneLog: Generated chunk [" .. ChunkX .. ", " .. ChunkZ .. "] in world " .. World:GetName() .. ".")

    World:SetBlock(ChunkX * 16 + 8, 40, ChunkZ * 16 + 8, E_BLOCK_GLOWSTONE, 0)
end



RE: Lua hooks needed! - Taugeshtu - 06-06-2012

LateTick:
Called after all Tick() are done... I suppose, server is calling Tick(), right? So, it should call LateTick() too
Parameters - same deltaTime as in Tick()

OnChunkPopulate:
Called only for freshly generated terrain, AND for regenerated as well. Not for loaded from storage.
Quote:If you want to change generator, you should split this callback into two - one called before the actual generator kicks in, one after. Why let it generate terrain, if you're gonna overwrite it all?
Fair point. Maybe OnChunkWillPopulate() (if returned true - no generator work needed then, if false - generator continues) plus OnChunkPosPopulate() (no difference between false and true returned)

Quote:chunks can be generated even before the plugin subsystem is fully initialized
Well, then ChunkWorx can regenerate spawn area as well (because it seems to be the only zone which can be generated before plugin system initialisation)


RE: Lua hooks needed! - xoft - 06-06-2012

I still can't quite fathom why you'd need anything like LateTick() - isn't Tick() enough? And if it isn't, would one LateTick() be enough, or soon there'll be demand for LateLateTick(), LateLateLateTick(), ...

(06-06-2012, 01:29 AM)Taugeshtu Wrote: Maybe OnChunkWillPopulate() (if returned true - no generator work needed then, if false - generator continues) plus OnChunkPosPopulate() (no difference between false and true returned)
A few good frameworks use the schema "OnDoing", "OnDone", so I'm sticking to names "OnChunkGenerated" (already implemented, called after the chunk is generated) and "OnChunkGenerating" (called just before generating)
Why would you need two "OnChunkGenerating", again? One is IMHO enough - it can write all chunk data instead of the generator, and if it returns true, the generator will skip builtin generating. It also needn't modify the data and be used as a notification only; return false in that case.


RE: Lua hooks needed! - Taugeshtu - 06-06-2012

LateTick isn't needed right now, I thought that I could use this that way:
One plugin calculates some information about player, writes it into .ini. It all happens in Tick()
Another plugin reads that .ini on LateTick(), so it's sure that first plugin had done all it's logic. But then I had that thought about cIniFile classBig Grin And still had no time to check it...

As for generation:
Two example situations. In first you write your own ore distribution, and completely replaces generator work. In another you simply add some ore type (or structures!), and want to add it AFTER generator (or another plugin!) did all it's job.
I can see no way one hook can handle both situations. I mean, in one case you have to abort generator's work, in another you want to add some changes after it's done. And you can even want to add something BEFORE generator start!


RE: Lua hooks needed! - xoft - 06-06-2012

That would work, but what if the second plugin wanted to communicate something back to the first plugin? Then you'd need a third hook. And a fourth, later. Generally, this is a bad idea, we can come up with something better. At the very least, "OnPluginBroadcast()", which is triggerred whenever a plugin calls a "Broadcast()" method.

Generation: Misunderstanding. I thought you wanted two more hooks, in addition to the OnChunkGenerated(). Now I get it and we're in agreement here, except for the names Smile
This is the generator pseudo-code, as we both want it:
Code:
// received another chunk for generating
if (!CallHook("OnChunkGenerating", ChunkData))
{
  // Hook didn't generate the chunk, we need to do it ourselves:
  GenerateChunkUsingInternal(ChunkData);
}
cWorld->ChunkGenerated(ChunkData);  // Send the chunk data to cWorld
CallHook("OnChunkGenerated", ChunkCoords);



RE: Lua hooks needed! - Taugeshtu - 06-06-2012

Quote:except for the names
I would be happy even if you would call it OnCallBeetleJuice()Big Grin


RE: Lua hooks needed! - FakeTruth - 06-06-2012

Good, but I wouldn't go with the LateTick. I suggest using a more robust method of inter-plugin communication like the ones already discussed in another thread


RE: Lua hooks needed! - Taugeshtu - 06-08-2012

Trying to fill the wiki, run into problems with new hooks. I look into Bindings.cpp:
Code:
cPluginManager
    constant E_PLUGIN_CHUNK_GENERATED,                cPluginManager::E_PLUGIN_CHUNK_GENERATED
    constant E_PLUGIN_CHUNK_GENERATING,                cPluginManager::E_PLUGIN_CHUNK_GENERATING
    constant E_PLUGIN_BLOCK_TO_DROPS,                cPluginManager::E_PLUGIN_BLOCK_TO_DROPS
Everything is fine.
Now:
Code:
cPlugin
    function OnChunkGenerated                        Plugin_OnChunkGenerated00
And that's it. No OnChunkGenerating, no OnBlockToDrops. Am I missing something, or there's something wrong?
Could someone explain, please?

And, well, since it's about hooks, can someone explain how server behaves when OnCollectItem hook returns true and false?