Cuberite Forum
Creating the Trade Window? - 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: Creating the Trade Window? (/thread-2393.html)



Creating the Trade Window? - Fighter19 - 03-02-2016

Currently I'm trying to create a class to create the trade window, especially for use with Plugins.
The Problem I'm facing is, I've made the functions available towards the LUA interpreter and I'm now wondering if that's ok,
because my Class is just like the other classes (AnvilWindow, etc.) which are not exposed to LUA (ofc, with the exception of cLuaWindow).

Also I'm wondering whether it's ok to introduce a new class called "cTrade" inside the same files used for the Window.


RE: Creating the Trade Window? - xoft - 03-02-2016

Hello, welcome to the forum.

The basic idea behind the cWindow class hierarchy was, that the cWindow and its descendants, such as cCraftingWindow, cAnvilWindow etc. were to be created internally by Cuberite whn the player interacted with the "owners" of the windows - crafting table, anvil... A Lua plugin couldn't create a new instance of such a class. On the other hand, once the window was created by Cuberite, plugins should be allowed to interact with the window. Still, all the operations needed for the interaction are implemented directly in the base class, cWindow. The derived classes mostly only specify what kinds of "Slot areas" the windows contain and how shift-clicking distributes items between the areas.
The cLuaWindow class acts as an "any type" window that can be created directly by Lua, regardless of what the player is doing - so that plugins can open a "chest" window for a player even if there's no chest around. It doesn't provide any kind of extra processing based on the window type, other than adding the armor SlotArea for the Inventory and Workbench window types.

I think you should add the trade-related functions directly into cWindow, that way even Lua plugins can use them both in the built-in windows and the Lua-created ones. It is kind hackish, but it's the easiest thing to do right now.

I believe the cTrade class will need some more interaction than just the windows - it will need storage in the world files, and will be most likely managed by the villagers themselves, so I'd say make it a standalone source file.


RE: Creating the Trade Window? - Fighter19 - 03-14-2016

Thank you!

I have added the functionality to the cWindow, however I'm not quite sure if I even need another class called cTrade, as it basically just does the same functionality like cItems (except that it has a strange structure at the moment).
So I was wondering whether I should just completely remove the cTrade class and replace it with cItems (which would have a size of 3 items, the first one is the first left item, the second the right, the last is the second left item).
You can take a small peek in my github repo. (I know it's very dirty, but I'm also quite new to C++, I hope that doesn't scare you too much.) I also think that the sending and composing of the string which is going to send the items later should be done inside Protocol/ClientHandle.
https://github.com/Fighter19/cuberite/commit/00f044b8e448fd994fb0d52721cd3807cd28a45e

I hope that I'm not wasting your time, either way you'd have a small (but dirty) example of how trading could work ^^.


RE: Creating the Trade Window? - xoft - 03-14-2016

I think you should approach this from a different perspective.

All UI Windows in Cuberite are basically containers of cItem objects, organized into cSlotArea instances that provide the behavior. So I think the trade window needs a special new cSlotArea descendant that will handle the actual trade. The trade template itself should be stored in an array within the cVillager object for the villager who is offering the trade; the player should have a link to the villager with whom they are interacting, together with an index into the trade array. The trade template should be a simple container of three items and possibly some flags, as needed for the protocol currently: http://wiki.vg/Plugin_channel#MC.7CTrList
As for the actual data being sent to the client, this is protocol-specific and should be handled in the protocol handlers, I would personally edit cProtocol180::SendWholeWindow() - if the window being sent is a trade window, send the Tr|List plugin message as well (call a new virtual function cProtocol180::SendTradeList()).

It would be great to actually abstract the trading away from the cVillager class and instead create a cMerchant abstract class that declares the interface for "trading" - stores trade templates and actually processes the trade ("you give me X and Y, I give you Z and like you more and possibly have another trade for you"), each as a virtual function that is implemented by descendants.


RE: Creating the Trade Window? - Fighter19 - 03-08-2017

I meant that cItems might be enough to serve for the purpose of storing the trading template.
However deriving an extra class out of it could add more readability to the code.
(e.g having a functions like "AddSellItems AddResultItem" makes it easier to read understand and also would provide a better interface to use for the LUA interpreter).
By cTrade I was referring to the class that is meant to store the template.
EDIT: I think this is necessary because it's possible for multiple trades to be selected in one Window. So cTrade would be a container of multiple cItems which represent the trades.
Maybe it should be named cTradeList, then.

My current plan goes as follows:
Derive cSlotArea to cSlotAreaTrade, add functionality.

However for this to work, cSlotAreaTrade needs to be provided an instance of cTrade.
Normally I'd think I should retrieve this from the parent window.
This would however mean that the parent window is a container of the trade object.
So I'd add a pointer to a cTrade instance into cLuaWindows as a member. I'd move it over to cWindow as soon as it can be retrieved from a villager.
(Or optionally a own class could be made for TradingWindows regardless of if LUA or normal).
Also functionality like SetTradeList would be added to cLuaWindows and SendTradeList to the protocol interface as well as the implementations.
Then when there is an interaction with the slots, cSlotAreaTrade would try to cast it to a LuaWindow, if it worked and it has wtNPCTrade then it will use the Trading List from there, to see if the items provided are the correct ones. If they are, the item will be set into the result slot, and can be dragged.

EDIT2:
I just started implementing it and I ran into following problem:
cLuaWindow allows any size to be accepted.
But a simple trade window actually doesn't hold any items itself (Unlike chests or furnaces for example).
So creating the window with size will shift the inventory on the client but not on the server (and thus cause the inventory states to differ).
It might be easier to just use a seperate class for Lua Trade Windows.
Also none of the other similar window (e.g Anvil) provide functionality when used with LUA.

EDIT3:
I think there should be at least two LUA classes, one that provides functionality and one that leaves everything up to the scripter (as it's currently the case).