zinc-j
Enforces Zinc syntax and JASS migration standards.
Install
mkdir -p .claude/skills/zinc-j && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/16517" && unzip -o skill.zip -d .claude/skills/zinc-j && rm skill.zipInstalls to .claude/skills/zinc-j
Activation
This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.
本项目 .j 文件中的 Zinc(//! zinc ... //! endzinc)语法与约定:库/结构体写法、匿名函数(无闭包)最佳实践、回调参数传递、资源释放/置空、以及 JASS->Zinc 迁移要点。Key capabilities
- →Wrap Zinc code blocks with `//! zinc` and `//! endzinc`
- →Declare arrays using `type name[];` without specifying size
- →Declare local variables at the beginning of functions
- →Release handle resources using `Destroy*` or `Remove*` APIs
- →Define static methods with `static method foo(...)` syntax
- →Migrate JASS `loop/exitwhen/endloop` to Zinc `for` loops
How it works
The skill provides guidelines for writing Zinc code, covering syntax, variable declarations, function ordering, and resource management. It also details how to migrate JASS code constructs to their Zinc equivalents.
Inputs & outputs
When to use zinc-j
- →Write optimized Zinc code
- →Migrate JASS to Zinc
- →Ensure proper handle resource release
About this skill
Zinc(本项目)语法与约定
必须遵守
- 用
//! zinc///! endzinc包裹 Zinc 代码块。 - 禁用
++/--;用+= 1/-= 1。 - 禁用
break/continue;用if分支或布尔开关改写。 - 数组声明一律用
type name[];,不要写大小(例如integer a[10]是错的)。 - Zinc 的数组维度里不要写表达式(例如
arr[HERO_COUNT + 1][5]);需要先把值算成常量再使用,或直接用固定上界。 - 二维数组在底层是线性存储;只要索引映射不冲突(例如
a[6][5]下(1,5)与(2,1)映射不同),可以按项目约定安全使用,不必为了“从 1 开始”额外预留整段[1]。 - 返回类型用
-> type写在参数列表后;无返回可省略。 - 局部变量统一在函数/匿名函数开头声明:先基础类型,后句柄类型。
- 函数定义顺序不再作为日常写法的硬性约束:
vjassc会处理上方函数直接调用下方函数的场景。 - 仍需兼容
jasshelper时,如果它只因函数顺序报错而vjassc能过,优先在该调用点改成xxxx.evaluate(...),少做大范围函数重排。 - 本地场景(例如 UI 本地执行)禁止
execute,只能用evaluate,否则有 OOS 风险。 - 仅在本文件内引用的固定长文案/标签,不要另起一个只
return "..."的函数;优先按CenterUp.j的GetResumeLabel()风格用函数式#define,并在文件末尾配套#undef。
匿名函数(无闭包)
- 匿名函数内不能直接访问外层局部变量;需要显式传参。
- 传参优先用结构体/库的
static成员变量,并在回调结束后立刻清理为默认值(null/0/"")。 - 临时触发器回调用
CreateTrigger+TriggerAddCondition+TriggerEvaluate,随后DestroyTrigger并置null。
句柄生命周期(资源释放)
- 创建出来的句柄资源(
timer/trigger/group/effect/location/...):按对应Destroy*/Remove*API 释放,并在作用域末尾= null。 - 可分配结构体(通过
allocate()/create()取得实例)析构只写method onDestroy();外部必须调用实例的.destroy(),使子句柄清理与结构体回收一起执行。 - 不要把
destroy1()当作可分配结构体的析构函数:它只是普通方法,既不会自动触发onDestroy(),也不会回收结构体实例。destroy1()仅可用于struct X []这类静态管理器的内部 UI 清理流程。 - 不要自定义
destroy()。
结构体/方法写法
- 静态方法:
static method foo(...) -> type { ... } - 实例方法:
method foo(...) -> type { ... } - 纯静态“管理器”可用
struct X [] { ... }(避免create/destroy)。
跨位置调用与性能约束
execute:不带返回值(底层是TriggerExecute触发 action)。evaluate:可用于需要返回值或不需要返回值的调用场景。jasshelper会把evaluate降成 trigger/condition 包装,存在额外资源开销;vjassc通常能把这类调用智能降成直接调用。- 不要为了旧的函数顺序习惯重排大段代码;只有在需要通过
jasshelper或解决循环调用链时才引入evaluate/execute。
玩家工具与日志名
- 判断地图有效玩家或在线用户时,直接调用 War3Lib
PlayerUtils.cfg注入的IsValidPlayer(player)/IsOnlineUser(player);不要在地图模块内重复定义,也不要重复手写GetPlayerSlotState(...) == PLAYER_SLOT_STATE_PLAYING && GetPlayerController(...) == MAP_CONTROL_USER。 - Xlimon 中通过
DzWriteLog、CrainaxLogTrace/Debug/Info/Warn/Error或项目日志包装函数记录玩家名时,统一写PlayerName[GetConvertedPlayerId(p)](已有pid/index时优先直接用对应数组下标);禁止用GetPlayerName(p),避免日志出现平台前缀(如[初雪境#0])。该约束只针对日志,不要机械改动 UI 文案、权限判断、随机种子等非日志语境。
JASS -> Zinc 迁移要点
- JASS 默认
public;Zinc 默认private:需要对外可见的函数/全局变量要显式public。 loop/exitwhen/endloop优先改写为 Zinc 的范围for (a <= i <= b)或常规 for。- timer/trigger 的一次性逻辑优先改成匿名回调。
Hash 表键位
- 没有必须隔离生命周期或键空间的理由时,不要在 Xlimon 本地新建
InitHashtable();优先复用 War3Lib 的共享表(如HASH_ITEM/HASH_UNIT/HASH_BIGINT),并把新增子键跨仓定义到对应的D:/War3/Library/War3Lib/Jass/core/table/Hash_*Define.j文件,避免以后生成代码又在本地创建重复小表。 - 只有确实无法通过共享表完成的任务,才新建独立 hashtable;例如需要独立 flush 整个 child 且不能逐键清理,或键空间/生命周期必须与共享表隔离。
- 新增或迁移
HASH_UNIT/HASH_ITEM/HASH_BIGINT子键时,先检查对应D:/War3/Library/War3Lib/Jass/core/table/Hash_*Define.j内是否已有相同数值;同一个 hashtable 内数值冲突会导致完全不同系统互相覆盖。 Hash_UnitDefine.j、Hash_ItemDefine.j、Hash_BIDefine.j是不同 hashtable 的键名空间;跨表数值相同通常不是问题,但同文件内数值和宏名都必须唯一。- 修改共享键位前,先搜索旧宏名的全部
Save*/Load*/RemoveSaved*调用,确认应该移动新键还是保留既有系统键位。 - 可用以下命令快速检查三张表内重复数值和重复宏名:
$files = 'D:\War3\Library\War3Lib\Jass\core\table\Hash_UnitDefine.j','D:\War3\Library\War3Lib\Jass\core\table\Hash_ItemDefine.j','D:\War3\Library\War3Lib\Jass\core\table\Hash_BIDefine.j'; foreach ($file in $files) { Write-Host "FILE $file"; $defs = Select-String -Path $file -Pattern '^\s*#define\s+(\S+)\s+(-?\d+)\b' | ForEach-Object { [pscustomobject]@{ Line=$_.LineNumber; Name=$_.Matches[0].Groups[1].Value; Value=[int64]$_.Matches[0].Groups[2].Value; Text=$_.Line.Trim() } }; $defs | Group-Object Value | Where-Object Count -gt 1 | ForEach-Object { Write-Host " DUP VALUE $($_.Name)"; $_.Group | ForEach-Object { Write-Host (" L{0}: {1}" -f $_.Line, $_.Text) } }; $defs | Group-Object Name | Where-Object Count -gt 1 | ForEach-Object { Write-Host " DUP NAME $($_.Name)"; $_.Group | ForEach-Object { Write-Host (" L{0}: {1}" -f $_.Line, $_.Text) } } }
References(按需加载)
references/jass-to-zinc.mdreferences/anonymous-functions.mdreferences/callback-params.mdreferences/method-syntax.mdreferences/function-order-and-indirect-call.md
When not to use it
- →When using `++/--` operators
- →When using `break/continue` statements
- →When calling a lower-order function from a higher-order function without using a struct static method or `execute`/`evaluate`
Limitations
- →Anonymous functions cannot directly access outer local variables
- →Local UI scenarios prohibit `execute` due to OOS risk
- →Custom `destroy()` methods are not allowed for struct destruction
How it compares
This skill provides specific Zinc syntax and convention rules, unlike a generic linter that might not enforce project-specific patterns.
Compared to similar skills
zinc-j side by side with the closest alternatives in the catalog.
| Skill | Installs | Updated | Safety | Difficulty |
|---|---|---|---|---|
| zinc-j (this skill) | 0 | 7mo | No flags | Intermediate |
| architect-review | 109 | 5mo | No flags | Advanced |
| solid-principles | 57 | 11mo | No flags | Intermediate |
| codex | 32 | 4mo | Review | Advanced |
Try saying
Example prompts that trigger this skill in your AI assistant.
More by Crainax
View all by Crainax →You might also like
architect-review
sickn33
Master software architect specializing in modern architecture patterns, clean architecture, microservices, event-driven systems, and DDD. Reviews system designs and code changes for architectural integrity, scalability, and maintainability. Use PROACTIVELY for architectural decisions.
solid-principles
SmidigStorm
Enforce SOLID principles (Single Responsibility, Open/Closed, Liskov Substitution, Interface Segregation, Dependency Inversion) in object-oriented design. Use when writing or reviewing classes and modules.
codex
Lucklyric
Invoke Codex CLI for complex coding tasks requiring high reasoning capabilities. This skill should be invoked when users explicitly mention "Codex", request complex implementation challenges, advanced reasoning, or need high-reasoning model assistance. Automatically triggers on codex-related requests and supports session continuation for iterative development.
error-handling-patterns
wshobson
Master error handling patterns across languages including exceptions, Result types, error propagation, and graceful degradation to build resilient applications. Use when implementing error handling, designing APIs, or improving application reliability.
deepwiki-rs
sopaco
AI-powered Rust documentation generation engine for comprehensive codebase analysis, C4 architecture diagrams, and automated technical documentation. Use when Claude needs to analyze source code, understand software architecture, generate technical specs, or create professional documentation from any programming language.
senior-fullstack
davila7
Comprehensive fullstack development skill for building complete web applications with React, Next.js, Node.js, GraphQL, and PostgreSQL. Includes project scaffolding, code quality analysis, architecture patterns, and complete tech stack guidance. Use when building new projects, analyzing code quality, implementing design patterns, or setting up development workflows.