--- front: hard: 入门 time: 分钟 --- # 自定义方块实体 ## 概念 方块实体的概念详见[官方wiki](https://zh.minecraft.wiki/w/方块实体) ## 添加自定义方块实体 需要添加netease:block_entity组件才能为自定义方块添加自定义方块实体。 | 键 | 类型 | 默认值 | 解释 | | ------- | ---- | ------ | ------------------------------------------------------------ | | tick | bool | false | 为true时,当玩家进入方块tick范围时,该方块每秒会发送**20次**ServerBlockEntityTickEvent事件
为false时,该方块不会发送ServerBlockEntityTickEvent事件 | | client_tick | bool | false | 为true时,当玩家进入方块tick范围时,该方块每秒会发送**20次**ModBlockEntityTickClientEvent事件
为false时,该方块不会发送ModBlockEntityTickClientEvent事件 | | movable | bool | true | 为true时,该方块可被粘性活塞拉回
为false时,该方块不可被粘性活塞拉回 | - **对于已有方块实体的方块,如[自定义刷怪箱](./3-特殊方块/1-自定义刷怪箱.md),将无法再添加自定义方块实体。** - 添加了自定义方块实体的方块,可通过**服务端blockEntityData组件**来管理方块实体内的数据。 ## 相关组件与事件 - GetBlockEntityData接口 可用于管理方块实体内的数据。 - ServerPlaceBlockEntityEvent事件 当玩家手动放置含自定义方块实体的自定义方块时触发,此时可向该方块实体中存储数据。 - ChunkGeneratedServerEvent事件 通过自定义特征放置含自定义方块实体的自定义方块时,在区块生成完毕时触发,其中包含了该区块中自定义方块实体信息列表,此时可向该方块实体中存储数据。 - ServerBlockEntityTickEvent事件 若在netease:block_entity组件中配置tick为true,则当该自定义方块位于模拟范围内时触发。该事件触发频率为**每秒20次** ## demo解释 - 方块配置 [CustomBlocksMod](../../13-模组SDK编程/60-Demo示例.md#CustomBlocksMod)中,`customblocks:customblocks_test_block_entity`方块配置了自定义方块实体,具体配置如下: 即该方块在距离玩家不远时会每秒发送20次ServerBlockEntityTickEvent事件,且无法被粘性活塞拉回。 ![block_entity_1](./picture/customblock/block-entity-1.png) - 方块放置 customBlocksServer.py中注册了对ServerPlaceBlockEntityEvent事件的监听,在回调里通过blockEntityData组件向每个由玩家手动创建的自定义方块实体中写入数据: ```python def ServerPlaceBlockEntityEvent(self, args): print 'ServerPlaceBlockEntityEvent ', args dimension = args['dimension'] # 该自定义方块实体所在的维度 blockPos = (args['posX'], args['posY'], args['posZ']) # 该自定义方块实体所处位置 blockName = args['blockName'] # 含该自定义方块实体的方块名称 # 创建blockEntityData组件 comp = self.CreateComponent(self.levelId, "Minecraft", "blockEntityData") # 获取可操作该自定义方块实体的对象 blockEntityData = comp.GetBlockEntityData(dimension, blockPos) # 在对自定义方块实体内数据进行操作前,要先进行判空处理 if blockEntityData: # 使用与dict类似的操作方式存入键为"abc"、值为{"1":True,"2":None,"3":"123"}的数据 blockEntityData['abc'] = {"1": True, "2": None, "3": "123"} ``` - 方块交互 监听了ServerBlockUseEvent,在其中判断玩家是否在与customblocks:customblocks_test_block_entity方块进行交互。是则向其中写入数据: ```python def ServerBlockUseEvent(self, args): blockName = args['blockName'] # 方块名称 blockPos = (args['x'], args['y'], args['z']) # 方块位置 playerId = args['playerId'] # 玩家id dimensionComp = serverApi.CreateComponent(playerId, "Minecraft", "dimension") dimension = dimensionComp.GetPlayerDimensionId() # 获取玩家所在维度 # 判断交互的方块类型 if blockName == 'customblocks:customblocks_test_block_entity': comp = self.CreateComponent(self.levelId, "Minecraft", "blockEntityData") blockEntityData = comp.GetBlockEntityData(dimension, blockPos) if blockEntityData: # 向方块实体中写入键为"key"、值为[1, 2, 3]的数据 blockEntityData['key'] = [1, 2, 3] ``` - 方块实体tick ```python def OnBlockEntityTick(self, args): # 避免在Tick中频繁打印输出,易造成卡顿 # print 'blockEntityTick ', args pass ``` 监听了ServerBlockEntityTickEvent事件,netease:block_entity组件中配置tick为true的自定义方块每秒会触发20次其自定义方块实体tick事件。 - **应避免在诸如tick事件回调等高频函数中进行打印输出,易造成卡顿。** - **应避免在地图中放置过多netease:block_entity组件配置tick为true的自定义方块,频繁事件调用也可能造成卡顿** - 方块销毁 监听了ServerPlayerTryDestroyBlockEvent事件,当有玩家尝试摧毁customblocks:customblocks_test_block_entity方块时,会尝试从其自定义方块实体中读取数据并输出。 ```python def ServerPlayerTryDestroyBlockEvent(self, args): pos = (args["x"], args["y"], args["z"]) playerId = args['playerId'] dimensionComp = serverApi.CreateComponent(playerId, "Minecraft", "dimension") dimension = dimensionComp.GetPlayerDimensionId() comp = self.CreateComponent(self.levelId, "Minecraft", "blockEntityData") blockEntityData = comp.GetBlockEntityData(dimension, pos) if blockEntityData: # 根据key获取方块实体中对应的value value1 = blockEntityData['key'] value2 = blockEntityData['abc'] print 'value of "key" is', value1 print 'value of "abc" is', value2 ``` - 对于从未进行过交互的customblocks:customblocks_test_block_entity方块,当玩家尝试摧毁它时,会输出: ```python # 不存在于方块实体中的数据将返回None 'value of "key" is None' 'value of "abc" is {"1": True, "2": None, "3": "123"}' ``` - 若玩家曾经与该方块进行过交互,会输出: ```python 'value of "key" is [1, 2, 3]' 'value of "abc" is {"1": True, "2": None, "3": "123"}' ```