# 自定义方块实体
# 概念
方块实体的概念详见官方wiki
# 添加自定义方块实体
需要添加netease:block_entity组件才能为自定义方块添加自定义方块实体。
键 | 类型 | 默认值 | 解释 |
---|---|---|---|
tick | bool | false | 为true时,当玩家进入方块tick范围时,该方块每秒会发送20次ServerBlockEntityTickEvent事件 为false时,该方块不会发送ServerBlockEntityTickEvent事件 |
movable | bool | true | 为true时,该方块可被粘性活塞拉回 为false时,该方块不可被粘性活塞拉回 |
对于已有方块实体的方块,如自定义刷怪箱,将无法再添加自定义方块实体。
添加了自定义方块实体的方块,可通过服务端blockEntityData组件来管理方块实体内的数据。
# 相关组件与事件
- blockEntityData组件
可用于管理方块实体内的数据,详见blockEntityData组件
- ServerPlaceBlockEntityEvent事件
当玩家手动放置含自定义方块实体的自定义方块时,会发送ServerPlaceBlockEntityEvent事件
此时可向该方块实体中存储数据
- ChunkGeneratedServerEvent事件
通过自定义特征放置含自定义方块实体的自定义方块时,在区块创建完成时会发送ChunkGeneratedServerEvent事件,其中包含了该区块中自定义方块实体信息列表
此时可向该方块实体中存储数据
- ServerBlockEntityTickEvent事件
若在netease:block_entity组件中配置tick为true,则当该自定义方块位于tick范围内时,其自定义方块实体每秒会发送20次ServerBlockEntityTickEvent事件
# demo解释
方块配置
CustomBlocksMod中,
customblocks:customblocks_test_block_entity
方块配置了自定义方块实体,具体配置如下:即该方块在距离玩家不远时会每秒发送20次ServerBlockEntityTickEvent事件,且无法被粘性活塞拉回。
方块放置
customBlocksServer.py中注册了对ServerPlaceBlockEntityEvent事件的监听,在回调里通过blockEntityData组件向每个由玩家手动创建的自定义方块实体中写入数据:
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方块进行交互。是则向其中写入数据:
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
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方块时,会尝试从其自定义方块实体中读取数据并输出。
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方块,当玩家尝试摧毁它时,会输出:
# 不存在于方块实体中的数据将返回None 'value of "key" is None' 'value of "abc" is {"1": True, "2": None, "3": "123"}'
若玩家曾经与该方块进行过交互,会输出:
'value of "key" is [1, 2, 3]' 'value of "abc" is {"1": True, "2": None, "3": "123"}'