-
Notifications
You must be signed in to change notification settings - Fork 11
The Basics
Spinnery is a GUI library for Minecraft 1.15 to 1.16. Written to be severely abstracted to allow for quick porting and less dependency on Minecraft code, it is by all means a fairly capable framework, not directly based on existing models. Effectively, it can be subdivided as seen in the following graph:
While complicated at first, the architecture, to the end user, is simple. I'll show you some of the basics and then a complete example - sounds good to me.
In Spinnery, you may have Screen
s or ContainerScreen
s. Effectively, a Screen
is something only meant to be shown to the client - a perfect fit for annoying popups on player spawn - please don't actually do that.
A ContainerScreen
(known outside Spinnery as a HandledScreen
) is a screen meant to be displayed on the client, but that requires information from the server. That'd be Chests, Furnaces, Beacons, you know, that sort of stuff. Behind any ContainerScreen
, there's a Container
(known outside Spinnery as a ScreenHandler
), which holds the actual shared data - slots and stuff.
Whenever you're making a ContainerScreen
, you're gonna need to add shared widgets in both the ContainerScreen
and the Container
(slots, mainly), except you only need positions and sizes in the ContainerScreen
. Onto positions and sizes, then!
A Position
is an object holding x
, y
and z
coordinates. They may be fixed, anchored or supplied. For a quick summary, suppose we have a widget button
at position 8
, 8
, 0
(x
, y
, z
):
- Fixed: a position based on a raw coordinate.
Position myPosition = Position.of(64, 64, 0);
This position is always at 64
, 64
, 0
.
- Anchored: a position based on a widget's position.
Position myPosition = Position.of(button, 24, 24, 0);
Can you take a guess what that does? It means that whenever its position is requested, it'll do my X plus their X, my Y plus their Y, my Z plus their Z
, so, in this case, 8 + 24, 8 + 24, 0 + 0
-> 32, 32, 0
. This is useful for simple offsets, but sometimes you need more complex positioning. That's where our next buddy comes in:
- Supplied: a position based on coordinate suppliers.
Position myPosition = Position.of(() -> screenWidth / 2f, () -> screenHeight() / 2f, () -> 0f);
This one's a bit more complicated and means you must know how Java lambdas work. Basically, whenever the coordinates are requested, it runs that bit of code; so if it wants x
, it will return screenWidth / 2f
. Of course, actually running it every time would be bad for performance, so I've fixed that up in the backend to recalculate the coordinates only when needed.
A Size
is an object holding width
and height
numbers. In other words, it dictates the literal size of a widget, and has two options - fixed and supplied.
- Fixed: a size based on the given numbers.
Size mySize = Size.of(32, 32);
The above size will be 32
by 32
, always. Of course, again you may need a more complex way to decide siding, so our buddy appears again.
- Supplied: a size based on number suppliers.
Size mySize = Size.of(() -> parentWidth / 3f, () -> parentHeight / 3f);
As you may have guessed, this means that, whenever this size is asked about its width, it'll run that bit of code - again, that's not quite how it works in the backend, but you don't have to worry about that.