Skip to content

Add GroundCraft plugin#1170

Merged
ACaiCat merged 2 commits into
UnrealMultiple:masterfrom
loguhan:codex/add-groundcraft
Jun 29, 2026
Merged

Add GroundCraft plugin#1170
ACaiCat merged 2 commits into
UnrealMultiple:masterfrom
loguhan:codex/add-groundcraft

Conversation

@loguhan

@loguhan loguhan commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Summary

  • add GroundCraft dropped-item crafting plugin
  • support JSON recipes and condition checks for layer, biome, liquids, and boss progress
  • include Chinese and English README plus example JSON files

Validation

  • dotnet build src/GroundCraft/GroundCraft.csproj -c Release

Summary by Sourcery

引入 GroundCraft Terraria/TShock 插件,用于基于 JSON 配方以及环境/首领条件的掉落物品合成。

New Features:

  • 添加 GroundCraft 服务器插件,定期扫描世界掉落物,并在满足已配置的配方和环境条件时自动合成物品。
  • 提供可配置的、基于 JSON 的配方和条件文件(含示例),支持图层、生物群系、液体及首领进度等条件。
  • 暴露玩家和管理员聊天命令,用于查看插件状态、配方、环境标签,审计配方安全性,以及热重载配置/配方。

Documentation:

  • 为 GroundCraft 的使用方法、配置、配方格式和安全规则添加中文和英文 README 文档。

Chores:

  • 通过清单文件和项目脚手架在插件元数据中注册 GroundCraft,包括示例 JSON 配置和配方文件。
Original summary in English

Summary by Sourcery

Introduce the GroundCraft Terraria/TShock plugin for dropped-item crafting driven by JSON recipes and environment/boss conditions.

New Features:

  • Add a GroundCraft server plugin that periodically scans world drops and auto-crafts items when configured recipes and environment conditions are met.
  • Provide configurable JSON-based recipe and condition files, including examples, with support for layers, biomes, liquids and boss progression.
  • Expose player and admin chat commands for viewing plugin status, recipes, environment tags, auditing recipe safety and hot-reloading config/recipes.

Documentation:

  • Add Chinese and English README documentation for GroundCraft usage, configuration, recipe format and safety rules.

Chores:

  • Register GroundCraft in plugin metadata via a manifest file and project scaffolding, including example JSON config and recipe files.

@loguhan loguhan requested a review from a team as a code owner June 29, 2026 10:26

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - 我发现了 1 个问题,并提供了一些整体反馈:

  • GroundCraft.cs 已经变成了一个非常庞大、包含多种职责的类(插件生命周期、扫描、环境探测、配方导入/审计、配置/规格类型);建议将其中的支撑类型和逻辑拆分到单独的文件或辅助类中,以保持核心插件类更小、更易维护。
  • ReloadFiles 会修改 _config、_recipes 和 _audit,而 OnGameUpdate/ScanDrops 可能会读取它们;在重载和扫描路径上加一个简单的锁,可以避免潜在的竞争条件以及被观察到的部分更新状态。
  • TryCraftCluster 在找到集群的第一个匹配配方后就停止;如果希望在一次扫描中为同一个集群合成多条配方,可能需要在某个配方成功后继续迭代,而不是立即返回。
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- GroundCraft.cs has grown into a very large, multi-responsibility class (plugin lifecycle, scanning, environment probing, recipe import/audit, config/spec types); consider splitting supporting types and logic into separate files or helper classes to keep the core plugin class smaller and easier to maintain.
- ReloadFiles modifies _config, _recipes and _audit while OnGameUpdate/ScanDrops can read them; adding a simple lock around reload and scan paths would avoid potential race conditions and partially-updated state being observed.
- TryCraftCluster stops after the first matching recipe for a cluster; if multiple recipes per cluster are intended to be craftable in one scan, you may want to continue iterating rather than returning immediately once a recipe succeeds.

## Individual Comments

### Comment 1
<location path="src/GroundCraft/GroundCraft.cs" line_range="1259-1262" />
<code_context>
+        return $"{recipe.Id}: {ingredients} => {ItemName(recipe.OutputType)} x{recipe.OutputStack} @ {StationName(recipe.RequiredTiles)} {ConditionName(recipe.Conditions)}";
+    }
+
+    private static string StationName(IReadOnlyCollection<int> tileTypes)
+    {
+        if (tileTypes.Count == 0)
+            return "任意地点";
+
+        return string.Join("/", tileTypes.Select(tileType => tileType switch
+        {
+            TileID.WorkBenches => "工作台",
+            TileID.Furnaces => "熔炉",
+            TileID.Hellforge => "地狱熔炉",
+            TileID.Anvils => "铁砧/铅砧",
+            TileID.Sawmill => "锯木机",
+            TileID.Loom => "织布机",
+            TileID.Kegs => "酒桶",
+            TileID.Bottles => "瓶子/炼药桌",
+            TileID.CookingPots => "烹饪锅",
+            TileID.TinkerersWorkbench => "工匠作坊",
+            TileID.Extractinator => "提炼机",
+            TileID.MythrilAnvil => "秘银砧/山铜砧",
+            _ => $"图格 {tileType}"
+        }));
+    }
</code_context>
<issue_to_address>
**nitpick (typo):** 默认的工作台名称使用了“图格”,这看起来像是一个拼写错误。

回退标签目前是 `$"图格 {tileType}"`,在中文中读起来像是笔误。请更新这个字符串(比如改为“图块”或其他合适的术语),以便在向管理员展示未知的 tile ID 时,回退的工作台名称更加清晰易读。

```suggestion
            TileID.MythrilAnvil => "秘银砧/山铜砧",
            _ => $"图块 {tileType}"
        }));
    }
```
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
帮我变得更有用!请在每条评论上点击 👍 或 👎,我会根据这些反馈改进后续的代码审查。
Original comment in English

Hey - I've found 1 issue, and left some high level feedback:

  • GroundCraft.cs has grown into a very large, multi-responsibility class (plugin lifecycle, scanning, environment probing, recipe import/audit, config/spec types); consider splitting supporting types and logic into separate files or helper classes to keep the core plugin class smaller and easier to maintain.
  • ReloadFiles modifies _config, _recipes and _audit while OnGameUpdate/ScanDrops can read them; adding a simple lock around reload and scan paths would avoid potential race conditions and partially-updated state being observed.
  • TryCraftCluster stops after the first matching recipe for a cluster; if multiple recipes per cluster are intended to be craftable in one scan, you may want to continue iterating rather than returning immediately once a recipe succeeds.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- GroundCraft.cs has grown into a very large, multi-responsibility class (plugin lifecycle, scanning, environment probing, recipe import/audit, config/spec types); consider splitting supporting types and logic into separate files or helper classes to keep the core plugin class smaller and easier to maintain.
- ReloadFiles modifies _config, _recipes and _audit while OnGameUpdate/ScanDrops can read them; adding a simple lock around reload and scan paths would avoid potential race conditions and partially-updated state being observed.
- TryCraftCluster stops after the first matching recipe for a cluster; if multiple recipes per cluster are intended to be craftable in one scan, you may want to continue iterating rather than returning immediately once a recipe succeeds.

## Individual Comments

### Comment 1
<location path="src/GroundCraft/GroundCraft.cs" line_range="1259-1262" />
<code_context>
+        return $"{recipe.Id}: {ingredients} => {ItemName(recipe.OutputType)} x{recipe.OutputStack} @ {StationName(recipe.RequiredTiles)} {ConditionName(recipe.Conditions)}";
+    }
+
+    private static string StationName(IReadOnlyCollection<int> tileTypes)
+    {
+        if (tileTypes.Count == 0)
+            return "任意地点";
+
+        return string.Join("/", tileTypes.Select(tileType => tileType switch
+        {
+            TileID.WorkBenches => "工作台",
+            TileID.Furnaces => "熔炉",
+            TileID.Hellforge => "地狱熔炉",
+            TileID.Anvils => "铁砧/铅砧",
+            TileID.Sawmill => "锯木机",
+            TileID.Loom => "织布机",
+            TileID.Kegs => "酒桶",
+            TileID.Bottles => "瓶子/炼药桌",
+            TileID.CookingPots => "烹饪锅",
+            TileID.TinkerersWorkbench => "工匠作坊",
+            TileID.Extractinator => "提炼机",
+            TileID.MythrilAnvil => "秘银砧/山铜砧",
+            _ => $"图格 {tileType}"
+        }));
+    }
</code_context>
<issue_to_address>
**nitpick (typo):** The default station name uses "图格", which appears to be a typo.

The fallback label is currently `$"图格 {tileType}"`, which reads as a typo in Chinese. Please update this string (e.g., to "图块" or another appropriate term) so fallback station names are clear and readable when an unknown tile ID is shown to admins.

```suggestion
            TileID.MythrilAnvil => "秘银砧/山铜砧",
            _ => $"图块 {tileType}"
        }));
    }
```
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread src/GroundCraft/GroundCraft.cs Outdated
Comment thread src/GroundCraft/GroundCraft.cs
Comment thread src/GroundCraft/GroundCraft.cs Outdated

@ACaiCat ACaiCat left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@loguhan

loguhan commented Jun 29, 2026

Copy link
Copy Markdown
Contributor Author

已按 review 重新提交 GroundCraft 优化:

  • 将原先过大的 GroundCraft.cs 拆成 lifecycle/commands/crafting/environment/models/recipes/utilities 等 partial 文件。
  • 为配置、配方、审核结果和运行时扫描加 _stateLock,避免 /gcreload 与扫描并发读取/更新时出现部分状态。
  • 调整同一掉落簇合成逻辑,单次扫描里配方成功后可继续尝试其他可用配方,同时避免同一配方签名重复触发。
  • 修正消耗掉落物的处理方式,剩余数量会更新原物品堆,避免清掉再生成导致后续同簇合成/客户端同步混乱。
  • 将未知图块回退文案从“图格”改为“图块”,并补了一批可见文本的 GetString 包裹。

本地验证:dotnet build .\src\GroundCraft\GroundCraft.csproj -c Release 通过,0 warnings / 0 errors。

@ACaiCat ACaiCat added this pull request to the merge queue Jun 29, 2026
Merged via the queue into UnrealMultiple:master with commit 13b5806 Jun 29, 2026
2 checks passed
@loguhan

loguhan commented Jun 29, 2026

Copy link
Copy Markdown
Contributor Author

补充了合成成功时的客户端粒子效果:

  • 新增 GroundCraft.Effects.cs,合成成功后发送 Terraria 客户端特效包。
  • config.json 新增 craftEffect:支持 FairySmokeBoth,可调 burstCountradiusTilesfairyColor
  • 避开了专用服务器里 Dust.NewDust 不生成客户端粒子的问题,使用 MessageID.SpecialFX / MessageID.PoofOfSmoke 让客户端播放真实粒子。
  • 示例配置和中英文 README 已同步。

验证:dotnet build .\src\GroundCraft\GroundCraft.csproj -c Release 通过,0 warnings / 0 errors。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants