User:ChampionAsh5357/Sandbox

This is the sandbox page! Everything here is just...here until I finish writing or find a place to put it.

Containers, Menus, and Screens

  • Container
    • Vanilla's Inventory System
    • Player uses an implementation called Inventory
    • Superseded by Forge's IItemHandler capabilitiy
  • Menu
    • The handler between the represented data and a user's input
    • Base implementation is AbstractContainerMenu
    • Currently used to handle two types of data
      • Slot: Holds ItemStacks
      • DataSlot: Holds integers (though only shorts of the data are actually synchronized)
      • Syncing additional data is just as simple as building an abstract holder for that type that can mutate the actual object data.
        • Send the data to the client via a packet in your network when changed and mutate it on the client container
          • Since the container contains the player it's referencing, you just need to send it to that player
    • The data handled is used as a manager for synchronization so the client doesn't need to be aware of the actual objects containing the value.
    • Both should be attached in the constructor via addSlot or addDataSlots respectively
    • Also should check passed in container size and data size to make sure they match the currently set up menu.
    • As such, all mutable components of these two data points directly modify the data that was passed in.
    • Common Methods for Implementation
      • stillValid: Checks whether the menu can remain open
      • quickMoveStack: Logic to move the stack to the correct location after shift-clicking
    • The only logic that should happen in the menu is those which can only happen in the container. Otherwise, it should happen in whatever the menu is referencing.
    • MenuType
      • The registry object representing the container
      • Holds how to construct the container on the client side
      • The client constructor on Menu should only have two parameters: windowId and playerInventory
        • In the case of extra data, a third parameter can be used with IForgeContainerType#create: FriendlyByteBuf
          • Extra data may include block position, tracked screen mode, etc.
        • The client constructor is just a reference to the server constructor with dummy containers and data slots passed in for synchronization between the server and client
      • The server constructor should only take in values that can be constructed by the client as a dummy.
    • MenuProvider
      • Used to open a menu on the server side.
      • Can be implemented anonymously, but can also be attached to another type like a BlockEntity.
      • Methods to Implement
        • getDisplayName: Just creates the component to represent the display name of the menu reference on the client.
        • createMenu: Used to create the container on the server, passes in the windowId, playerInventory, and the player the inventory belongs to (redundant but mojank).
      • Opened by using NetworkHooks#openGui
        • Takes in the ServerPlayer for which the container instance will belong to and the menu provider to open the container.
          • If needed, also consumes a FriendlyByteBuf to send additional data to the client, though this only works if the MenuType is implemented via IForgeContainerType#create
        • Usually implemented via Block#use or Item#use
          • Client side interaction is InteractionResult#SUCCESS
          • Server side interaction checks whether it can open the menu and does so if it can. Then it returns InteractionResult#CONSUME.
  • Screen
    • User view of menu on the client
    • Base implementation is Screen, though we will use AbstractContainerScreen since it has a bunch of helpers already implemented.
    • Constructor must have three parameters: The container menu, the player inventory, and the menu reference's display name.
      • Will be passed in from NetworkHooks#openGui when sent to the client.
      • This is also where you should set the imageWidth and imageHeight if they are not the default 176x166 size.
      • Data needed from the menu should be obtained from the menu itself. If the data was properly synced, you can just refer to the according slot or data slot it is using. (Easier to add a helper method here within the menu itself).
    • Broken down into three major methods.
      • init: Sets up the initial data within the screen
        • Can be used to add widgets (renderable or not), set base data such as the title/inventory label location, etc.
      • render: Renders the data on the screen
        • Some information is not implemented here so we need to add it ourselves
        • Easiest implementation: call renderBackground first, super of render second, then renderTooltip third
        • Sets up the data such that the game looks unfocused and tooltips on slot components show up
      • renderBg: Renders the background of the screen
        • Here is where you set the background texture and draw any extra components needed that is not already handled for you (slots only)
        • Set by three basic RenderSystem calls: setShader to GameRenderer#getPositionTexShader for rendering components in a location, setShaderColor to all 1 as to not tint the screen, and setShaderTexture to set the texture to pull the data for rendering from.
        • can then call the blit methods to determine what to render where
          • These are located in GuiComponent and available to all screens and widgets to use
          • Most common blit method used takes in the PoseStack, x and y position of the game window (usually calculated by ((screen_dimension - image_dimension) / 2)), x and y position of the top left pixel of the texture in the supplied image, and the image width and height.
      • Additional methods for implementation include tick, mouseClicked, keyPressed, charTyped. This is left up to the reader to figure out how to implement.
      • Container Screens can be attached to any Menu via MenuScreens#register. This can be called within FMLClientSetupEvent in the synchronous work queue since the method is not thread safe.