在Minecraft BE中使用Scripting API!第二部分:显示自定义用户界面

首先/先生/起初我想解释一下关于用棒子敲击方块后会出现3个按钮,然后按下第三个按钮就会消失的脚本。由于文件结构稍微复杂,所以建议您下载页面底部的示例包。

准备本次添加UI,与上次不同的是需要使用几个文件。需要的文件有client.js、server.js,还需要button.html、button.css、hud_screen.json。(这次给它起名为button,但名字可以随便取)

资源包和行为包的文件结构如下:
your_resource
├ manifest.json
├ ui
│ └ hud_screen.json
└ experimental_ui
└ button.html
└ button.css

您的资源包和行为包的文件结构如下:
your_resource
├ manifest.json
├ ui
│ └ hud_screen.json
└ experimental_ui
└ button.html
└ button.css

your_behavior
├ manifest.json
└ scripts
├ client
│ └ client.js
└ server
└ server.js

今回はclient.js, server.js の2つの解説をしたいと思います。

添加说明据说在win10系统中,中央的十字光标不会显示出来。一旦找到原因和解决方法,我会进行编辑。
当将ui选项的loadEventData.data.options.is_showing_menu设置为true后,即使在win10系统中也可以正常运行。(感谢信息提供者button先生)
在手机上可能会有一部分ui消失,所以请注意。

client.js编写在前一次处理的 server.js 和这里处理的内容有些不同。前一次使用的 block_Interacted_with 在这里不能使用,就像有一些可用和不可用的东西一样。(反过来,在 client.js 中也有一些只能使用的东西。)

让我们立即来查看一下代码。
下面是client.js的整个代码。

const system = client.registerSystem(0, 0);

system.initialize = function () {
   this.listenForEvent('minecraft:ui_event', (eventData) => this.onUIMessage(eventData));

   //指定イベントがブロードキャストされる毎に呼び出されるJavaScriptオブジェクトを登録
   this.listenForEvent('stick:loadui', (eventData) => this.loadui(eventData));

   //eventDataを登録

   this.registerEventData('stick:clickA', {});
   this.registerEventData('stick:clickB', {});
   this.registerEventData('stick:clickC', {});
};

system.loadui = function (eventData) {
   //uiのオプション
   var loadEventData = this.createEventData('minecraft:load_ui');
   loadEventData.data.path = 'button.html';
   loadEventData.data.options.always_accepts_input = false;
   loadEventData.data.options.is_showing_menu = false;
   loadEventData.data.options.absorbs_input = false;
   loadEventData.data.options.should_steal_mouse = true;
   loadEventData.data.options.force_render_below = true;
   loadEventData.data.options.render_only_when_topmost = true;
   loadEventData.data.options.render_game_behind = true;
   this.broadcastEvent('minecraft:load_ui', loadEventData);
};

//ボタンを押した時の処理
system.onUIMessage = function (eventData) {
   var BroadcastEventData = this.createEventData('minecraft:display_chat_event');

   if (!eventData.data) {
      return;
   }
   if (eventData.data === 'buttonAClicked') {
      //server側にブロードキャスト
      var clickEventDataA = this.createEventData('stick:clickA');
      this.broadcastEvent('stick:clickA', clickEventDataA);

      //チャットに'buttonA'と送る
      BroadcastEventData.data.message = 'buttonA';
      this.broadcastEvent('minecraft:display_chat_event', BroadcastEventData);
   }
   if (eventData.data === 'buttonBClicked') {
      //server側にブロードキャスト
      var clickEventDataB = this.createEventData('stick:clickB');
      this.broadcastEvent('stick:clickB', clickEventDataB);

      //チャットに'buttonB'と送る
      BroadcastEventData.data.message = 'buttonB';
      this.broadcastEvent('minecraft:display_chat_event', BroadcastEventData);
   }
   if (eventData.data === 'buttonCClicked') {
      //server側にブロードキャスト
      var clickEventDataC = this.createEventData('stick:clickC');
      this.broadcastEvent('stick:clickC', clickEventDataC);

      //ボタンを削除
      var unloadEventData = this.createEventData('minecraft:unload_ui');
      unloadEventData.data.path = 'button.html';
      this.broadcastEvent('minecraft:unload_ui', unloadEventData);

      //チャットに'buttonC'と送る
      BroadcastEventData.data.message = 'buttonC';
      this.broadcastEvent('minecraft:display_chat_event', BroadcastEventData);
   }
};

系统初始化
首先,在这个例子中,我们将使用一个名为minecraft:ui_event的事件来在client.js中使用。这个事件将在从html文件(这次是button.html)广播时被调用。

监听事件我在上次已经使用了这种方法来处理minecraft:ui_event并在this.onUIMessage中进行处理了,但这次我会使用另一种方法。
实际上,我们可以在第一个参数eventIdentifier中传入我们自定义的事件(例如本次是stick:loadui)。通过这种方式,我们可以注册一个JavaScript对象(例如本次是this.loadui),每当自定义事件被广播时就会被调用。

这是注册事件数据。通过使用这个,可以注册自定义事件(mcjixif:test的形式)。这次我们将注册stick:clientA, stick:clientB, stick:clientC。

系统加载用户界面这是之前在this.listenForEvent中注册的内容。当stick:loadui被广播时,将调用此内容。在这里,主要进行UI的设置。

加载活动数据的路径。这行代码指定了要读取的HTML文件。

加载EventData数据中的选项。通过这个进行UI的详细设置。总共有七个设置选项。(这次我们省略了说明。)

系统.onUIMessage在这里,我们将写下按钮被按下时的处理代码。我们将比较eventData与先前注册的事件(例如:stick:clickA),如果它们匹配,就会执行相应的处理步骤。

这个广播事件通过使用这个,将它广播到服务器端,使其正常运作。

Minecraft:卸载我想要将Button C按下时的UI隐藏的机制设置在这里,所以只需使用这个选项。
使用这个事件将先前显示的UI隐藏起来。通过指定路径进行广播来实现。

服务器.js编我想写一个使用相同的block_Interacted_with函数的处理过程,当使用棒子敲击方块时,它会产生动作。

以下是完整的代码

const system = server.registerSystem(0, 0);

var flag = false;

system.initialize = function () {
   this.listenForEvent('minecraft:block_interacted_with', (eventData) => this.onInteractedWith(eventData));

   //clientでregisterしたイベントを登録
   this.listenForEvent('stick:clickA', eventData => this.onClickA(eventData));
   this.listenForEvent('stick:clickB', eventData => this.onClickB(eventData));
   this.listenForEvent('stick:clickC', eventData => this.onClickC(eventData));
};

system.onInteractedWith = function (eventData) {
   var handContainer = this.getComponent(eventData.data.player, 'minecraft:hand_container');
   var carriedItem = handContainer.data[0].item;

   if (carriedItem == 'minecraft:stick' && !flag) {
      //clientのstick:loaduiをブロードキャスト
      this.broadcastEvent('stick:loadui', eventData);
      flag = true;
   }
};

system.onClickA = function (eventData) { 
   //処理
};

system.onClickB = function (eventData) { 
   //処理
};

system.onClickC = function (eventData) { 
   flag = false;
};

旗帜
这个标记是为了让脚本判断UI是否显示所必需的。如果没有这个标记,可能会导致多个UI堆叠显示。如果显示了UI,就将其赋值为true,否则赋值为false。

系统初始化

监听此事件首先注册block_Interacted_with。这一部分不需要解释,因为和平常一样。
然后使用listenForEvent注册之前通过client的registerEventData注册的事件。在这里注册的javascript对象(例如this.onClickA)会在client接收到stick:clickA广播时被调用。

当系统与其交互在这里,我们将创建一个if语句,就像上一次一样,如果用minecraft:stick敲击,会变成〜。我们还要确保flag为false。
当物品是棍子并且flag为false时,我们将广播客户端注册的stick:loadui。这将调用client的system.loadui并显示ui。由于ui出现了,我们将flag设置为true。

系统.点击事件因为我已经在客户端上设置了UI消失的功能,所以将flag设为false。

其他文件由于评论中已经有解释,所以我将省略。对不起,这有些敷衍。??

<!DOCTYPE html>
<html>

<head>
    <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
    <script src="../UIEngine.js"></script>
    <link rel="stylesheet" href="button.css" />
</head>

<body>
  <div class="parent">
    <button id="buttonA" class="child"></button>
    <button id="buttonB" class="child"></button>
    <button id="buttonC" class="child"></button>
  </div>
</body>
<script type="text/javascript">
let scriptInterface = null;
engine.on("facet:updated:core.scripting", function (interface) {
    scriptInterface = interface;
});

engine.trigger("facet:request", ["core.scripting"]);

//ボタンのidからエレメントオブジェクトを取得
let buttonA = document.getElementById("buttonA");
let buttonB = document.getElementById("buttonB");
let buttonC = document.getElementById("buttonC");

//clickを感知してclient側にブロードキャスト
let broadcastEvent = function (event) {
    scriptInterface.triggerEvent(event);
}
buttonA.addEventListener("click", function () {
    broadcastEvent("buttonAClicked");
});
buttonB.addEventListener("click", function () {
    broadcastEvent("buttonBClicked");
});
buttonC.addEventListener("click", function () {
    broadcastEvent("buttonCClicked");
});
</script>

</html>
@font-face {
  font-family: 'MinecraftTen';
  src: url(fonts/MinecraftTen.otf);
}
body {
  font-family: "MinecraftTen";
}
.parent {
  display: flex;
  flex-direction: row;
  justify-content: flex-end;
  height: 100%;
  width: 100%;
  opacity: 0.7;
}
.child {
  height: 6%;
  width: 6%;
}
{
  "hud_screen@common.base_screen": {
    "always_accepts_input": true
  }
}

可以参考的链接
脚本文档官方示例包

这次解说的内容是这个mcjixif样本包。

bannerAds