Zentutorial
  • 首页
  • Zenscript
  • 简单运用
    • 局部变量
    • 尖括号调用
    • 工作台合成
      • 添加配方
      • 移除配方
      • Metadata
      • NBT
    • 熔炉配方
    • 矿物词典(Ore Dictionaries)
    • 物品名称修改
    • tooltips
      • 样式代码
    • 物品条件
    • 物品转换器
    • 掉落物
      • 打草掉落物
      • 生物掉落物
      • Dropt - 导言
        • Dropt - 方法速查
        • Dropt - 使用示例
    • 战利品表 : 导论
      • 战利品表修改(LootTableTweaker)
      • 战利品表修改(LootTweaker-基础)
    • 循环语句(foreach循环) / 普通数组
  • 高级运用
    • 概论
      • 基本类
      • ZenGetter
      • ZenSetter
      • ZenMethod(方法)
    • 常见错误
    • 基本运算
    • 数组与集合
    • 循环与遍历
    • 全局函数
    • Math包
    • if
    • in/has 操作符
    • 战利品表修改(LootTweaker-进阶)
    • 三元操作符
    • 预处理器
    • 全局和静态变量
    • 跨脚本引用
    • 关联数组(映射)
    • IItemStack类型的重新认识
    • IIngredient接口
    • IItemDefinition & IBlockDefinition
    • IData 类型
      • DataMap
    • 穷举与遍历
    • 自定义函数
    • 配方函数与配方事件
      • 配方函数
      • 配方事件
    • 事件概论
      • 一些忠告
    • ZenClass
  • ContentTweaker
    • ContentTweaker
    • 指令
    • 原版加工厂
      • 概论
      • 物品
      • 方块
      • 流体
      • 创造标签
      • 食物
    • 材料系统
      • 基础用法
        • 材料
        • 部件
        • 注册材料部件
        • 材料部件信息
      • 高级运用
        • 自定义部件类型
        • 注册自定义部件
        • 自定义材料部件信息
    • 高级运用
    • 更多鸡联动
    • 匠魂联动
      • 材料引导
        • 材料
        • 构建材料
      • 特性引导
        • 特性
        • 构建特性
        • 特性数据
      • 高级运用
  • 实战
    • 配方
      • 数据驱动合成修改
    • 事件
      • 修改方块掉落物
      • 禁止开创造
由 GitBook 提供支持
在本页
  • !world.remote保证事件只在服务端处理
  • 将数据持久化保存
  • 写入数据
  • 读取、修改数据

这有帮助吗?

  1. 高级运用
  2. 事件概论

一些忠告

!world.remote保证事件只在服务端处理

MC分为服务端和客户端,服务端用来处理事件、存储存档,而客户端用来渲染、向服务端发送数据包。大部分事件只能在服务端内执行,客户端不能执行。单人游戏同样存在内置服务端和客户端。

IWorld的remote ZenGetter用来判断是否在服务端还是客户端。服务端这个ZenGetter会返回false,客户端为true。一旦和存档有关系,比如召唤实体、修改方块,必须使用!world.remote来保证只有服务端能执行这个事件。

val bat = VanillaFactory.createItem("forestbat");
bat.onItemUse = function(player, world, pos, hand, facing, blockHit) {
    if (!world.remote) {
        player.getHeldItem(hand).shrink(1);
        <entity:minecraft:bat>.spawnEntity(world, pos.getOffset("up", 1));
        player.sendMessage("新人请说出常用模组。");
        return ActionResult.success();
    }
    return ActionResult.pass();
};

这个是ConttentTweaker的脚本,创建一个物品,手持该物品对一个方块右键,召唤一只蝙蝠。你现在只需要注意函数内内容,这里需要使用!world.remote,否则右键执行事件后,会出现两只蝙蝠,一个正常,一个在原地不动,无法交互。

你应该用合适的Getter获取到IWorld对象。比如player.world

将数据持久化保存

读懂此条目需要有较高的水平,请确保对以下关键词已有相当了解:事件,IPlayer,IData,DataMap,NBT格式。

你可能会对数据有着更多的需求,例如长久保存一些数据来使用。但即使是全局、静态变量,它们也不是长久保存的,在游戏关闭后这些变量都会被释放。

我们可以将数据保存到玩家数据中,在退出、保存游戏时,我们的数据也随着保存到硬盘上了,即使游戏关闭了也依然存在。

写入数据

import crafttweaker.events.IEventManager;
import crafttweaker.event.PlayerCraftedEvent;

events.onPlayerCrafted(function(event as PlayerCraftedEvent) {
    if(event.player.world.remote) return;// 保证仅在服务端执行
    event.player.update({custom: 1 as byte});// 向玩家数据中写入自定义数据
    print(event.player.data);// 打印出玩家数据的字符串形式
});

当玩家合成时,就会写入该自定义标签到玩家数据中,同时输出调试信息。

[SERVER_STARTED][SERVER][INFO] {custom: 1 as byte}

这个标签的位置具体在哪里呢?借用FTB Utilities模组提供的游戏内 NBT 编辑工具,在游戏内输入命令/nbtedit player打开可视化工具,在ForgeData标签下即可以看到我们的自定义标签custom了,它的值为1。

  • 需要注意的是,直接保存在ForgeData下的数据会在玩家死亡时被清空,如果你希望玩家死亡后清空或重置该数据,那么你可以将数据保存在此处。

那么要玩家死亡了也不会清空呢?你可以在ForgeData下建立PlayerPersisted这个标签,将数据保存在里面即可。

import crafttweaker.events.IEventManager;
import crafttweaker.event.PlayerCraftedEvent;

events.onPlayerCrafted(function(event as PlayerCraftedEvent) {
    if(event.player.world.remote) return;// 保证仅在服务端执行
    event.player.update({PlayerPersisted: {custom: 1}});// 向PlayerPersisted中写入子标签{custom: 1}
    print(event.player.data);// 打印出玩家数据的字符串形式
});

输出的调试信息为

[SERVER_STARTED][SERVER][INFO] {PlayerPersisted: {custom: 1}}
  • 在PlayerPersisted内部的数据即可做到真正的持久化保存,即使玩家死亡了也不会清空。

读取、修改数据

这里就要简单许多了,但是还有几点需要注意,先看代码。

import crafttweaker.events.IEventManager;
import crafttweaker.event.PlayerCraftedEvent;

events.onPlayerCrafted(function(event as PlayerCraftedEvent) {
    if(event.player.world.remote) return;// 保证仅在服务端执行
    event.player.update({PlayerPersisted: {custom: 1}});// 向PlayerPersisted中写入子标签{custom: 1}
    print(event.player.data.PlayerPersisted.custom);// 获取并输出custom标签保存的值
});
  • 尽管你可以通过event.player.data.PlayerPersisted.custom来获取custom标签保存的值,但是你不可以给它赋值,也就是说类似于event.player.data.PlayerPersisted.custom = 10;的这种写法是错误的。

想修改玩家数据,只能去覆盖它(详见DataMap)。

import crafttweaker.events.IEventManager;
import crafttweaker.event.PlayerCraftedEvent;
import crafttweaker.player.IPlayer;
import crafttweaker.data.IData;

events.onPlayerCrafted(function(event as PlayerCraftedEvent) {
    if(event.player.world.remote) return;// 保证仅在服务端执行
    var data as IData = event.player.data;// 获取玩家数据
    if(isNull(data.PlayerPersisted.custom)) return;// 防止该标签为空时出现空指针异常
    event.player.update({PlayerPersisted: {custom: 10}});// 该操作为覆盖,最终相当于修改custom标签的值
    print(event.player.data.PlayerPersisted.custom);// 获取并输出custom标签保存的值
});

当玩家合成时,就会修改他保存着的custom标签的数据,同时输出调试信息。

[SERVER_STARTED][SERVER][INFO] 10
上一页事件概论下一页ZenClass

最后更新于1年前

这有帮助吗?