快轉到主要內容

合成台方塊自訂UI|Minecraft基岩版Add-On模組製作教學

分類   遊戲攻略 Minecraft
標籤   Minecraft Add-On Minecraft Resource Pack
🗓️ 民國110年 辛丑年
✍ 切換正體/簡體字
目錄

1. 前言
#

這篇文章介紹如何透過方塊來打開自訂UI的畫面。

基岩版不使用Scripting API的話,目前的UI都是修改原版居多,而且是透過資源包來修改。

第一個例子,Dewdimpple製作的 Custom Crafting Table加入了鍋爐的新方塊,開啟修改過的合成台UI,可以用來烤雞肉。實際上它還是九宮格,只是透過自訂UI把其他格子遮住,而且在合成表中用crating_tag來限定只能在這個合成台中操作。

再來看dakonblackrose製作的 Readable BookShelf,打開這個書櫃後可以看原神的漫畫。

這二個原作者的檔案我做了些修正,使之能共存。文章最後可以下載我修改過的版本。

2. 原理
#

透過方塊添加開啟自訂合成台的組件,接著在原版合成台的檔案中,塞入自己做的UI,並跟原版合成台UI共存。

於是就樣就給了我們一個突破口:不一定要做成合成台的介面,但一樣能用這個方法來叫出自訂UI。

在開始之前,建議看AgentMindStorm的這部影片,你會對JSON的UI有個基本概念。

3. 實作
#

這裡不做合成台,只做一個像是第二個漫畫例子的UI,這邊要做一個資訊看板。

影片版教學:

  1. 首先要在行為包新增一個叫做"Info Block"的方塊。

這裡主要在行為包中添加組件"minecraft:crafting_table",設定合成表,目前只能3x3。然後再設定UI的custom_description,就把它想成這個UI的唯一代號。

customUI_B/blocks/info_block.json內容:

//...
			"minecraft:crafting_table": {
				"custom_description": "container.newblock.info", // Name shown in GUI, you will use this name in the ui
				"grid_size": 3, // Currently only supports 3
				"crafting_tags": [
					"info"
				]
			},
//...

custom_description是字串形式,如果寫成mygui. xxx,你就可以在資源包*texts裡面給它設定多國語言。

  1. 切換到資源包

新增UI要先在_ui_defs.json聲明自製UI檔案的位置,通常是在最前面插入。

資源包/ui/_ui_defs.json內容:

{
  // Alphabetical order please :)
  "ui_defs": [
    "ui/infoui.json" //file name must be unique to avoid conflicts with other addons that also uses this
  ]
}
  1. 然後從原版Minecraft資源包複製這二個檔案:inventory_screen.jsoninventory_screen_pocket.json

一個是電腦版背包界面,一個是手機版的界面,要修改的地方大同小異。

  1. 開啟inventory_screen.json,刪除到只剩下crafting_screen,在裡面插入要開啟的UI。modification裡面用插入controls陣列的方式來加入UI。

[email protected]_panel,前面的info可以想成只是個變數,後面infoui.final_panel才是實際有功用/要呼叫的面板。

資源包/ui/inventory_screen.json內容:

{
	"namespace": "crafting",
	//Insert new UI into crafting screen "controls" array
	"[email protected]_screen_base": {
		"modifications": [
			{
				"array_name": "controls",
				"operation": "insert_back",
				"value": {
					//Your custom ui
					"[email protected]_panel": {
						//Bindings, to avoid conflicts with other custom UI Add-Ons.
						"bindings": [
							{
								"binding_name": "#crafting_label_text"
							},
							{
								"binding_type": "view",
								"source_property_name": "(#crafting_label_text = 'container.newblock.info')",
								"target_property_name": "#visible"
							}
						]
					}
				}
			},
			//Use this to make sure the vanilla crafting table will not be overwritten. However, if multiple Add-On use same names, many dulpicated crafting screens will be created :( Minecraft will show you warnings, too.
			//Therefore, "vanilla crafting table" and "crafting_screen" should be unique, too. But "crafting_screen" is required, so this problem is unsolved.
			{
				"array_name": "controls",
				"operation": "insert_back",
				"value": {
					"[email protected]_screen_base": {
						"bindings": [
							{
								"binding_name": "#crafting_label_text"
							},
							{
								"binding_type": "view",
								"source_property_name": "(#crafting_label_text = container.crafting)",
								"target_property_name": "#visible"
							}
						]
					}
				}
			}
		]
	}
}
  1. 除此之外,還要設定binding name (14~22行),填入剛剛在行為包設定的custom_description,以UI的文字當作顯示的依據,這樣它才只會在呼叫時顯示,避免跟其他Add-On以及原版的合成台重疊。

  2. 再來把原版的合成台UI加回來(28~45行),否則合成台會空白一片。

資源包/ui/inventory_screen_pocket.json檔案亦同:

/*
Similar to inventory_screen.json
*/
{
  "namespace": "crafting_pocket",
  "crafting_screen_pocket@crafting_pocket.inventory_screen_pocket_base": {
    "modifications": [
      {
        "array_name": "controls",
        "operation": "insert_back",
        "value": {
          //Your custom ui
          "[email protected]_panel": {
            //Bindings, to avoid conflicts with other custom UI Add-Ons.
            "bindings": [
              {
                "binding_name": "#crafting_label_text"
              },
              {
                "binding_type": "view",
                "source_property_name": "(#crafting_label_text = 'container.newblock.info')",
                "target_property_name": "#visible"
              }
            ]
          }
        }
      },
      {
        "array_name": "controls",
        "operation": "insert_back",
        "value": {
          "[email protected]_screen_base": {
            "$screen_content": "crafting.recipe_inventory_screen_content",
            "$screen_bg_content": "common.screen_background",
            "$top_half_variant": "crafting.crafting_panel_top_half",
            "bindings": [
              {
                "binding_name": "#crafting_label_text",
                "binding_type": "global"
              },
              {
                "binding_type": "view",
                "source_property_name": "(#crafting_label_text = container.crafting)",
                "target_property_name": "#visible"
              }
            ]
          }
        }
      }
    ]
  }
}
  1. 新增一個檔案 infoui.json,這個就是自己做的UI檔案,上面有一個專有的namespace,也是用來避免重複。

資源包/ui/infoui.json內容:

/*
 infoui.final -> main_panel -> scrolling -> homescreen
*/
{
  "namespace": "infoui", //Unique namspace
  /*
  Elements
  */
  //Background image
  "[email protected]_image": {
    "texture": "textures/ui/background",
    "alpha": 1
  },

  //UI Contents
  "homescreen": {
    "type": "stack_panel",
    "offset": [
      0,
      0
    ],
    //Headers, images and texts. Text + Image
    //Use size y to control line spacing
    "controls": [
      {
        "row0": {
          "type": "stack_panel",
          "orientation": "horizontal",
          "size": [
            "100%",
            50
          ],
          "controls": [
            {
              "header_0@how_to_play_common.header": {
                "$text": "newblock.info.header1"
              }
            }
          ]
        }
      },

      {
        "row00": {
          "type": "stack_panel",
          "orientation": "horizontal",
          "size": [
            "100%",
            50
          ],
          "controls": [
            {
              "paragraph_1@how_to_play_common.paragraph": {
                "$text": "newblock.info.text0"
              }
            }
          ]
        }
      },

      {
        "row1t": {
          "type": "stack_panel",
          "orientation": "horizontal",
          "size": [
            "100%",
            10
          ],
          "controls": [
            {
              "paragraph_1@how_to_play_common.paragraph": {
                "$text": "newblock.info.text1"
              }
            }
          ]
        }
      },
      {
        "row1": {
          "type": "stack_panel",
          "orientation": "horizontal",
          "size": [
            "100%",
            250
          ],
          "controls": [
            {
              "1": {
                "type": "image",
                "texture": "textures/ui/info1"
              }
            }
          ]
        }
      },

      {
        "row2t": {
          "type": "stack_panel",
          "orientation": "horizontal",
          "size": [
            "100%",
            10
          ],
          "controls": [
            {
              "paragraph_1@how_to_play_common.paragraph": {
                "$text": "newblock.info.text2"
              }
            }
          ]
        }
      },
      {
        "row2": {
          "type": "stack_panel",
          "orientation": "horizontal",
          "size": [
            "100%",
            250
          ],
          "controls": [
            {
              "1": {
                "type": "image",
                "texture": "textures/ui/info2"
              }
            }
          ]
        }
      },

      {
        "row3t": {
          "type": "stack_panel",
          "orientation": "horizontal",
          "size": [
            "100%",
            10
          ],
          "controls": [
            {
              "paragraph_1@how_to_play_common.paragraph": {
                "$text": "newblock.info.text3"
              }
            }
          ]
        }
      },
      {
        "row3": {
          "type": "stack_panel",
          "orientation": "horizontal",
          "size": [
            "100%",
            250
          ],
          "controls": [
            {
              "1": {
                "type": "image",
                "texture": "textures/ui/info3"
              }
            }
          ]
        }
      },

      {
        "row4t": {
          "type": "stack_panel",
          "orientation": "horizontal",
          "size": [
            "100%",
            10
          ],
          "controls": [
            {
              "paragraph_1@how_to_play_common.paragraph": {
                "$text": "newblock.info.text4"
              }
            }
          ]
        }
      },
      {
        "row4": {
          "type": "stack_panel",
          "orientation": "horizontal",
          "size": [
            "100%",
            250
          ],
          "controls": [
            {
              "1": {
                "type": "image",
                "texture": "textures/ui/info4"
              }
            }
          ]
        }
      },

      {
        "row5t": {
          "type": "stack_panel",
          "orientation": "horizontal",
          "size": [
            "100%",
            10
          ],
          "controls": [
            {
              "paragraph_1@how_to_play_common.paragraph": {
                "$text": "newblock.info.text5"
              }
            }
          ]
        }
      },
      {
        "row5": {
          "type": "stack_panel",
          "orientation": "horizontal",
          "size": [
            "100%",
            250
          ],
          "controls": [
            {
              "1": {
                "type": "image",
                "texture": "textures/ui/info5"
              }
            }
          ]
        }
      },

      {
        "row6t": {
          "type": "stack_panel",
          "orientation": "horizontal",
          "size": [
            "100%",
            10
          ],
          "controls": [
            {
              "paragraph_1@how_to_play_common.paragraph": {
                "$text": "newblock.info.text6"
              }
            }
          ]
        }
      },
      {
        "row6": {
          "type": "stack_panel",
          "orientation": "horizontal",
          "size": [
            "100%",
            250
          ],
          "controls": [
            {
              "1": {
                "type": "image",
                "texture": "textures/ui/info6"
              }
            }
          ]
        }
      },

      {
        "row7t": {
          "type": "stack_panel",
          "orientation": "horizontal",
          "size": [
            "100%",
            10
          ],
          "controls": [
            {
              "paragraph_1@how_to_play_common.paragraph": {
                "$text": "newblock.info.text7"
              }
            }
          ]
        }
      },
      {
        "row7": {
          "type": "stack_panel",
          "orientation": "horizontal",
          "size": [
            "100%",
            250
          ],
          "controls": [
            {
              "1": {
                "type": "image",
                "texture": "textures/ui/info7"
              }
            }
          ]
        }
      },

      {
        "row8t": {
          "type": "stack_panel",
          "orientation": "horizontal",
          "size": [
            "100%",
            20
          ],
          "controls": [
            {
              "paragraph_1@how_to_play_common.paragraph": {
                "$text": "newblock.info.text8"
              }
            }
          ]
        }
      },
      {
        "row8": {
          "type": "stack_panel",
          "orientation": "horizontal",
          "size": [
            "100%",
            250
          ],
          "controls": [
            {
              "1": {
                "type": "image",
                "texture": "textures/ui/info8"
              }
            }
          ]
        }
      }
      
    ]
  },
  /*
  UI
  */
  "[email protected]_panel": {
    "$scrolling_content": "infoui.homescreen",
    "$show_background": false,
    "anchor_from": "center",
    "anchor_to": "center"
  },
  "[email protected]_panel": {
    "layer": 1,
    "size": [
      "90%",
      "90%"
    ],
    "controls": [
      {
        "[email protected]_panel": {
          "offset": [
            0,
            0
          ],
          "$show_close_button": true
        }
      },
      //Background
      {
        "bg@background_image": {
          "layer": 2,
          "size": [
            "90%",
            "95%"
          ],
          "offset": [
            0,
            0
          ]
        }
      },
      //UI contents
      {
        "sg@scrolling": {
          "size": [
            "85%",
            "90%"
          ],
          "layer": 3
        }
      }
    ]
  },
  //Final panel to show
  //use lang file to change your container title
  "final_panel": {
    "type": "panel",
    "controls": [
      {
        "main@main_panel": {}
      }
    ],
    "bindings": [
      {
        "binding_name": "#crafting_label_text"
      },
      {
        "binding_type": "view",
        "source_property_name": "(#crafting_label_text = 'container.newblock.info')", //custom_description in the behavior
        "target_property_name": "#visible"
      }
    ]
  }
}
  1. 剩下的就是往UI裡面塞入元素了。

載入UI最先呼叫的就是404行的final_panel,同樣也給它設定binding name

順序就是:final_panel -> main_panel -> scrolling -> homescreen

因為這是一個捲動的視窗,在360~401行我設計了背景,以及將捲動的內容限縮在背景內。接著在16~350行填入文字和圖片,文字的部份還要在資源包/texts/en_US.lang設定實際顯示的文字內容。

一些已知的屬性:

  • source_property_name用於呼叫UI
  • layer用於重疊,越小越後面
  • size可用數字或100%、px來決定大小
  1. 這樣UI就完成了。

這個UI的效果主要是給玩家查詢Add-On使用方法,我把mcpedl上寫的文章放進來,UI裡面含有文字和圖片,可捲動。

這個UI有個小問題,crafting screen的插入方法,如果多個Add-On都這樣寫,會導致原版合成台的介面重複顯示。目前我還沒想到解決方法,如果有請跟我說吧。

關於UI的部分還有很多可以學習的地方,但如果你問我為什麼這樣那樣寫不行,我應該會說:

啊哈哈,佐佑理不清楚。

範本檔案下載
#

內含三個Add-On,鍋爐Custom Crafting Table UI、原神漫畫UI,以及本文的範例。

下載網址

也可於 Github檢視原始碼。

相關文章

Add-On 實體Render Controller的用法:3D武器、動態材質
分類   遊戲攻略 Minecraft
標籤   Minecraft Add-On Minecraft Resource Pack
神奇的material:為什麼只有閃電苦力怕的材質有動畫?為什麼蜘蛛眼睛晚上會發亮?
分類   遊戲攻略 Minecraft
標籤   Minecraft Resource Pack Minecraft Add-On
Minecraft模組實體模型的格式選擇 (Java、基岩版)
分類   遊戲攻略 Minecraft
標籤   Minecraft Add-On Forge Mod BlockBench Fabric Mod

留言板

此處提供二種留言板。點選按鈕,選擇您覺得方便的留言板。要討論程式碼請用Giscus,匿名討論請用Disqus。

這是Giscus留言板,需要Github帳號才能留言。支援markdown語法,若要上傳圖片請貼Imgur連結。您的留言會在Github Discussions向所有人公開。

這是Disqus留言板,您可能會看到Disqus強制投放的廣告。有時留言可能會被系統判定需審核,導致延遲顯示,請見諒。