Alright. I tried to make this work in Lua only but - as far as I know - it is not possible. I will explain everything I tried and why it did not work for future reference, and because you never know who may find the knowledge useful.
The first thing I tried, as Summ pointed out, was to recreate ProtocolGame::sendContainer in Lua:
Code:
local function sendContainer(player, container, hasParent, firstIndex)
firstIndex = firstIndex or 0
local msg = NetworkMessage()
msg:addByte(0x6E)
msg:addByte(player:getId())
msg:addItem(container)
msg:addString(container:getName())
msg:addByte(container:getCapacity())
msg:addByte(hasParent and 0x01 or 0x00)
msg:addByte(0x01) -- Unlocked
msg:addByte(0x00) -- No pagination
local containerSize = container:getSize()
msg:addU16(containerSize)
msg:addU16(firstIndex)
if(firstIndex < containerSize) then
local itemsToSend = math.min(container:getCapacity(), containerSize - firstIndex)
msg:addByte(itemsToSend)
for i = firstIndex, itemsToSend - 1 do
msg:addItem(container:getItem(i))
end
else
msg:addByte(0x00)
end
msg:sendToPlayer(player)
msg:delete()
end
It works, and what I mean by that is, the container is sent to the player. The container is opened normally and even the items are sent, however you can't make use of the items inside, actually you can't make use of the container
at all. This is because even though the container is sent, the player didn't actually open it. And since the container is not assigned an id, nothing you try to do with it will work. Then let's add the container and assign it an id, shall we?
luascript.h:
Code:
static int luaPlayerAddContainer(lua_State* L);
luascript.cpp:
Code:
registerMethod("Player", "addContainer", LuaScriptInterface::luaPlayerAddContainer);
int LuaScriptInterface::luaPlayerAddContainer(lua_State* L)
{
// player:addContainer(container)
Player* player = getUserdata<Player>(L, 1);
if (!player) {
lua_pushnil(L);
return 1;
}
Container* container = getUserdata<Container>(L, 2);
if (container) {
if (player->getContainerID(container) != -1)
{
lua_pushnil(L);
return 1;
}
uint8_t cid = 20;
for (int i = 0; i <= 0xF; i++) {
if (player->getContainerByID(i) == nullptr)
{
cid = i;
break;
}
}
if (cid != 20)
{
player->addContainer(cid, container);
player->onSendContainer(container);
lua_pushnumber(L, cid);
}
else {
lua_pushnil(L);
}
}
else {
lua_pushnil(L);
}
return 1;
}
We can now ignore the Lua function and use only this last one. Now, we can try to do this:
Code:
local bp = Game.createItem(1988, 1)
local container = Container(bp:getUniqueId())
container:addItem(2525)
player:addContainer(container)
Once again, it will apparently work. However the server will crash, because the next time it checks if the player moved away from the container (it should normally close), it will try to do so with an invalid temporary item, that has no position.
The solution is to either: give the player the container item, or place it in a position adjacent to the player, neither of which are suitable for the task at hand.
The best way I found to achieve the effect that the OP wants is to remove the tree when the player uses it (only necessary on the first use) and replace it with a custom container-tree through Game.createContainer.
Code:
--[[
actions.xml:
<action itemid="2708" script="tree.lua"/>
- 2708 is simply a tree id.
]]
function onUse(player, item, fromPosition, target, toPosition, isHotkey)
local RESTORE_TIME = 1000 * 60 -- Restore apples every minute
local treeContainer = item
if(not item:isContainer()) then
-- Remove normal tree
item:remove()
-- Replace it with a special container one
treeContainer = Game.createContainer(item:getId(), 4, fromPosition)
local function addApples()
-- Empty the container
local size = treeContainer:getSize()
for i = 1, size do
treeContainer:getItem(0):remove()
end
-- And add new apples.
treeContainer:addItem(2674, math.random(1, 4))
addEvent(addApples, RESTORE_TIME)
end
addApples(treContainer)
addEvent(addApples, RESTORE_TIME)
end
-- Automatically open the container
player:addContainer(treeContainer)
return true
end
Hope it helps,
Non Sequitur