智能食谱

智能食谱

一个扩展配方格式并加入条件的Fabric模组。

基础库

Logo

Smart Recipes

GitHub Build Status Version Modrinth CurseForge License

你觉得原版 Minecraft 的合成配方格式很无聊吗?或者你希望让游戏更偏向事件驱动,像 Terraria 那样?如果是这样,Smart Recipes 正是你需要的!用我们全新的条件配方格式,打造属于你自己的独特体验吧!


格式

如果你更喜欢看实际示例而不是解释,可以直接跳到 示例 部分。但别忘了之后回来查看 条件 和 重载条件 部分。

条件格式

Smart Recipes 模组扩展了原版配方格式。理解原版格式的工作方式至关重要,否则下面的说明可能难以理解。

此模组为配方格式引入了一个新的 smart_recipes:conditions 属性。它与战利品表中的条件有些类似。让我们仔细看看:

"smart_recipes:conditions": []

此属性决定配方加载所需的条件。如果指定了多个条件,则必须全部通过。

"smart_recipes:conditions": [
  {
    "condition": "conditionName0",
    "args": [
      // 传递给名为 `conditionName0` 的某个条件的参数。
      4,
      "2"
    ]
  },
  {
    "condition": "conditionName1",
    "args": [
      // 传递给名为 `conditionName1` 的某个条件的参数。
      "foo"
    ]
  }
]

此示例与战利品表中条件的通常写法完全相同。但我觉得它们太冗长了。让我们看看如何改进我们的条件。

// 把这样的条件声明:
{
  "condition": "conditionName1",
  "args": [
    "foo"
  ]
}

// 变成这样:
"conditionName1": ["foo"]

好多了,你不觉得吗?

"smart_recipes:conditions": [
  {
    "conditionName0": [4, "2"]
  },
  {
    "conditionName1": ["foo"]
  }
]

这比以前更好了,但仍有改进的空间。让我们把条件合并到单个对象中:

"smart_recipes:conditions": [
  {
    "conditionName0": [4, "2"],
    "conditionName1": ["foo"]
  }
]

最后,如果数组只包含一个对象,Smart Recipes 模组允许省略它的声明。以下是最终结果:

"smart_recipes:conditions": {
  "conditionName0": [4, "2"],
  "conditionName1": "foo"
}

我需要说明的是,Smart Recipes 可以解析上述每一个示例,所以你可以选择你喜欢的风格。

重载条件格式

重载条件允许在不同的时机重新评估配方条件。如果你的配方依赖于天气、时间或其他易变实体,这会很有用。

这个过程非常简单。你只需要提供配方所依赖的重载条件名称:

"smart_recipes:reload_conditions": [
  "weather_changed",
  "time_changed"
]

条件

false

不需要参数,始终返回 false。

"smart_recipes:conditions": [
  "false"
]

true

不需要参数,始终返回 true。

"smart_recipes:conditions": [
  "true"
]

or 和 any

如果指定的任一条件返回 true,则返回 true。

"smart_recipes:conditions": {
  "or": [
    { "false": {} },
    false,
    "true"
  ]
}

and 和 all

如果指定的所有条件都返回 true,则返回 true。

"smart_recipes:conditions": {
  "and": {
    "true": {},
    "false": null
  }
}

not 和 none

如果指定的所有条件都不返回 true,则返回 true。

"smart_recipes:conditions": {
  "not": {
    "false": null
  }
}

is_hardcore

不需要参数,如果服务器处于极限模式,则返回 true。

"smart_recipes:conditions": {
  "not": "is_hardcore"
}

is_peaceful_difficulty

不需要参数,如果当前难度为和平,则返回 true。

"smart_recipes:conditions": {
  "or": [
    "is_peaceful_difficulty",
    "is_hardcore"
  ]
}

is_easy_difficulty

不需要参数,如果当前难度为简单,则返回 true。

"smart_recipes:conditions": {
  "not": ["is_easy_difficulty"]
}

is_normal_difficulty

不需要参数,如果当前难度为普通,则返回 true。

"smart_recipes:conditions": "is_normal_difficulty"

is_hard_difficulty

不需要参数,如果当前难度为困难,则返回 true。

"smart_recipes:conditions": {
  "is_hard_difficulty": null
}

difficulty_check

如果指定的值之一与当前难度匹配,则返回 true。

"smart_recipes:conditions": {
  "difficulty_check": [
    0, // 和平难度的序号
    1, // 简单难度的序号
    2, // 普通难度的序号
    3, // 困难难度的序号
    "peaceful",
    "easy",
    "normal",
    "HarD" // 大小写无关
  ]
}

is_survival

不需要参数,如果默认游戏模式为生存,则返回 true。

"smart_recipes:conditions": "is_survival"

is_creative

不需要参数,如果默认游戏模式为创造,则返回 true。

"smart_recipes:conditions": ["is_creative"]

is_adventure

不需要参数,如果默认游戏模式为冒险,则返回 true。

"smart_recipes:conditions": {
  "is_adventure": {}
}

is_spectator

不需要参数,如果默认游戏模式为旁观,则返回 true。

"smart_recipes:conditions": {
  "not": "is_spectator"
}

gamemode_check

如果指定的值之一与默认游戏模式匹配,则返回 true。

"smart_recipes:conditions": {
  "gamemode_check": [
    0, // 生存游戏模式的序号
    1, // 创造游戏模式的序号
    2, // 冒险游戏模式的序号
    3, // 旁观游戏模式的序号
    "survival",
    "creative",
    "adventure",
    "SpEcTaToR" // 大小写无关
  ]
}

weather_check

如果指定的字符串之一与主世界维度中的当前天气匹配,则返回 true。

"smart_recipes:conditions": {
  "weather_check": [
    "clear",    // 天气晴朗
    "rain",     // 正在下雨或雷暴
    "thunder"   // 正在雷暴
  ]
}

time_check

如果指定的字符串之一与主世界维度中的当前时间匹配,则返回 true。

"smart_recipes:conditions": {
  "time_check": [
    "day",      // 从 1000  到 12999 tick
    "noon",     // 从 5000  到 6999  tick
    "sunset",   // 从 11000 到 12999 tick
    "midnight", // 从 17000 到 18999 tick
    "sunrise",  // 从 22000 到 23999 tick
    "night"     // 从 13000 到 23999 tick,从 0 到 999 tick
  ]
}

players_online

如果所有指定的玩家都在线,则返回 true。

"smart_recipes:conditions": {
  "players_online": [
    "Notch",
    "Dinnerbone",
    "jeb_"
  ]
}

blocks_registered

如果所有指定的方块都已注册,则返回 true。

"smart_recipes:conditions": {
  "blocks_registered": [
    "stone",
    "minecraft:dirt",
    "aether:aether_dirt"
  ]
}

items_registered

如果所有指定的物品都已注册,则返回 true。

"smart_recipes:conditions": {
  "items_registered": [
    "stone",
    "minecraft:dirt",
    "aether:aether_dirt"
  ]
}

block_entities_registered

如果所有指定的方块实体都已注册,则返回 true。

"smart_recipes:conditions": {
  "block_entities_registered": [
    "furnance",
    "minecraft:chest",
    "aether:incubator"
  ]
}

entries_registered

如果所有指定的注册表项都已注册,则返回 true。

"smart_recipes:conditions": {
  "entries_registered": [
    {
      "registry": "block",
      "entry": "stone"
    },
    "minecraft:dirt", // `registry` 的默认值为 "block",
    {
      "registry": "item",
      "entry": "aether:incubator"
    },
    {
      "entry": "air"  // `registry` 的默认值为 "block",
    }
  ]
}

fabric:mods_loaded

如果所有指定的模组都已加载,则返回 true。

"smart_recipes:conditions": {
  "fabric:mods_loaded": [
    {
      "id": "smart-recipes",
      "version": "1.0"
    },
    "fabric-transfer-api-v1",       // `version` 的默认值为 "*"
    {
      "id": "fabric-command-api-v1" // `version` 的默认值为 "*"
    }
  ]
}

重载条件

player_joined 和 player_disconnected

当玩家加入或断开与服务器的连接时重载配方。

"smart_recipes:conditions": {
  "not": {
    "players_online": "Nickname"
  }
},
"smart_recipes:reload_conditions": [
  "player_joined",
  "player_disconnected"
]

difficulty_changed

当当前难度改变时重载配方。

"smart_recipes:conditions": "is_easy_difficulty",
"smart_recipes:reload_conditions": "difficulty_changed"

gamemode_changed

当默认游戏模式改变时重载配方。

"smart_recipes:conditions": {
  "gamemode_check": [
    "survival",
    "creative"
  ]
},
"smart_recipes:reload_conditions": ["gamemode_changed"]

weather_changed

当当前天气改变时重载配方。

"smart_recipes:conditions": {
  "weather_check": "thunder"
},
"smart_recipes:reload_conditions": "weather_changed"

time_changed

当当前时间改变时重载配方。

"smart_recipes:conditions": {
  "time_check": [
    "noon",
    "midnight"
  ]
},
"smart_recipes:reload_conditions": [
  "time_changed"
]

示例

考虑一个场景:我们想添加一个简化的 TNT 配方:

{
  "type": "minecraft:crafting_shaped",
  "pattern": [
    "# X",
    "   ",
    "X #"
  ],
  "key": {
    "#": {
      "item": "minecraft:sand"
    },
    "X": {
      "item": "minecraft:gunpowder"
    }
  },
  "result": {
    "item": "minecraft:tnt"
  }
}

现在,让我们添加一些条件。以下是我们的目标:

  1. 此配方应仅在 midnight(午夜)和 sunrise(日出)时可用,因为没人在大白天制作炸药。
  2. 此配方应仅在 weather is clear(天气晴朗)时可用,以防止火药受潮。
  3. 当 Vladimir is online(Vladimir 在线)时,此配方应 not(不)可用,因为我们不放心把致命武器交给 Vladimir。
  4. 此配方应仅在 hard(困难)难度下可用,因为……为什么不呢?

是时候将我们的计划付诸行动了:

{
  // 与上面相同的部分,这里没什么有趣的
  "type": "minecraft:crafting_shaped",
  "pattern": [
    "# X",
    "   ",
    "X #"
  ],
  "key": {
    "#": {
      "item": "minecraft:sand"
    },
    "X": {
      "item": "minecraft:gunpowder"
    }
  },
  "result": {
    "item": "minecraft:tnt"
  },

  // 有趣的部分开始了。
  // 我们需要在 `conditions` 部分描述加载此配方所需的条件。
  // 如果指定了多个条件,则必须全部通过。
  "smart_recipes:conditions": {
    // #1
    "time_check": [
      "midnight",
      "sunrise"
    ],

    // #2
    // 注意 `weather_check` 通常接收一个数组(就像 `time_check` 一样),
    // 但由于我们只需要传递一个值,所以可以省略。
    "weather_check": "clear",

    // #3
    "not": {
      // 这里也可以省略数组声明,但
      // 我保留它是为了说明这并非必须。
      "players_online": ["Vladimir"]
    },

    // #4
    // 可以替换为:
    // - `"is_hard_difficulty": null`
    // - `"is_hard_difficulty"`(在数组中)
    // - `{ "condition": "is_hard_difficulty" }`(在数组中)
    // - `{ "condition": "difficulty_check", "args": ["hard"] }`(在数组中)
    "difficulty_check": "hard"
  },

  // 默认情况下,条件仅在服务器启动时评估。
  // 所以,如果我们想让配方与游戏的实际状态保持同步,
  // 就需要添加 `reload_conditions`。
  "smart_recipes:reload_conditions": [
    // #1
    // 当时间改变时重载配方。
    "time_changed",

    // #2
    // 当天气改变时重载配方。
    "weather_changed",

    // #3
    // 这些会在玩家加入或断开与服务器的连接时重载配方。
    // 我将来可能会把这两个合并为一个。
    "player_joined",
    "player_disconnected",

    // #4
    // 当难度改变时重载配方。
    // 说实话,我觉得你并不真的需要它,
    // 因为大多数服务器的难度是锁定的,
    // 所以只在服务器启动时评估基于难度的条件也没问题。
    "difficulty_changed"
  ]
}

安装

要求:

  • Minecraft >=1.17.x
  • Fabric Loader >=0.11.3
  • Fabric API >=0.35.0

你可以从以下途径下载此模组:

用作依赖项

你可以将 Smart Recipes 包含在你的模组中,以使用新的条件格式,而无需玩家单独下载它。

build.gradle:

repositories {
  maven {
    name = "Modrinth"
    url = "https://api.modrinth.com/maven"
    content {
      includeGroup "maven.modrinth"
    }
  }
}

dependencies {
  modImplementation "maven.modrinth:smart-recipes:${project.smart_recipes_version}"
}

gradle.properties:

smart_recipes_version=/* 在此填入最新版本 */

从源码构建

要求:

  • JDK 17

Linux/MacOS

git clone https://github.com/Kir-Antipov/smart-recipes.git
cd smart-recipes

chmod +x ./gradlew
./gradlew build
cd build/libs

Windows

git clone https://github.com/Kir-Antipov/smart-recipes.git
cd smart-recipes

gradlew build
cd build/libs