172 lines
5.7 KiB
HTML
172 lines
5.7 KiB
HTML
{{- /* SFCraft 合成配方组件
|
||
两种用法:
|
||
1) 九格直填: a1..c3 为 3x3 合成格, out 为输出格
|
||
2) pattern 别名模式(提供 pattern 时优先):
|
||
pattern="a a a\nb b b\nc c c" 行间用 \n(必须写在一行内), 也可用空格或 ; 分隔, 共 9 个 token
|
||
a="diamond" b="stick" c="" 每个 token 对应一个同名参数, 值为物品 id
|
||
token 也可以直接写物品 id, 如 pattern="diamond stick ."
|
||
"." 表示空格子
|
||
- 值为 assets/items/ 下贴图的文件名(不含 .png), 留空表示空格子
|
||
- 名称后可加 ":数量" 显示堆叠数, 例如 a1="stick:2"
|
||
- 引用的贴图不存在时, 格子内显示 ? 占位提示
|
||
- caption 参数可选, 显示在组件下方
|
||
*/ -}}
|
||
|
||
{{- $table := resources.Get "table.png" -}}
|
||
{{- $slots := slice
|
||
(dict "key" "a1" "cls" "grid" "x" "13.75%" "y" "20%")
|
||
(dict "key" "a2" "cls" "grid" "x" "25%" "y" "20%")
|
||
(dict "key" "a3" "cls" "grid" "x" "36.25%" "y" "20%")
|
||
(dict "key" "b1" "cls" "grid" "x" "13.75%" "y" "42.5%")
|
||
(dict "key" "b2" "cls" "grid" "x" "25%" "y" "42.5%")
|
||
(dict "key" "b3" "cls" "grid" "x" "36.25%" "y" "42.5%")
|
||
(dict "key" "c1" "cls" "grid" "x" "13.75%" "y" "65%")
|
||
(dict "key" "c2" "cls" "grid" "x" "25%" "y" "65%")
|
||
(dict "key" "c3" "cls" "grid" "x" "36.25%" "y" "65%")
|
||
(dict "key" "out" "cls" "out" "x" "70%" "y" "37.5%")
|
||
-}}
|
||
|
||
{{- $ctx := . -}}
|
||
{{- $pattern := $ctx.Get "pattern" -}}
|
||
{{- $tokens := slice -}}
|
||
{{- if $pattern -}}
|
||
{{- $flat := replace (replace (replace (replace $pattern "\\n" " ") ";" " ") "\n" " ") "\r" " " -}}
|
||
{{- range split (trim $flat " ") " " -}}
|
||
{{- if ne . "" -}}{{- $tokens = $tokens | append . -}}{{- end -}}
|
||
{{- end -}}
|
||
{{- end -}}
|
||
|
||
{{- $cssOnce := .Page.Store.Get "sfc_crafting_css" -}}
|
||
{{- if not $cssOnce -}}
|
||
{{- .Page.Store.Set "sfc_crafting_css" true -}}
|
||
<style>
|
||
.sfc-crafting {
|
||
position: relative;
|
||
width: 100%;
|
||
max-width: 540px;
|
||
aspect-ratio: 320 / 160;
|
||
margin: 1rem 0 1.25rem;
|
||
background-repeat: no-repeat;
|
||
background-size: 100% 100%;
|
||
container-type: inline-size;
|
||
}
|
||
.sfc-slot {
|
||
position: absolute;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
.sfc-grid { width: 10.625%; height: 21.25%; }
|
||
.sfc-out { width: 15.625%; height: 31.25%; }
|
||
.sfc-item {
|
||
width: 88%;
|
||
height: 88%;
|
||
object-fit: contain;
|
||
image-rendering: pixelated;
|
||
filter: drop-shadow(0 2px 2px rgba(0, 0, 0, 0.35));
|
||
}
|
||
.sfc-count {
|
||
position: absolute;
|
||
right: 5%;
|
||
bottom: 3%;
|
||
font-family: "Minecraft", ui-monospace, Consolas, monospace;
|
||
font-size: 12px;
|
||
font-size: 2.8cqw;
|
||
font-weight: 700;
|
||
line-height: 1;
|
||
color: #fff;
|
||
text-shadow: 0 1px 0 #3f3f3f, 1px 0 0 #3f3f3f,
|
||
0 -1px 0 #3f3f3f, -1px 0 0 #3f3f3f,
|
||
0 2px 3px rgba(0, 0, 0, 0.55);
|
||
}
|
||
.sfc-missing {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
width: 86%;
|
||
height: 86%;
|
||
font-size: 4cqw;
|
||
font-weight: 700;
|
||
color: rgba(0, 0, 0, 0.28);
|
||
border: 2px dashed rgba(0, 0, 0, 0.18);
|
||
border-radius: 4px;
|
||
background:
|
||
repeating-linear-gradient(45deg, rgba(255,255,255,0.22), rgba(255,255,255,0.22) 4px, rgba(0,0,0,0.04) 4px, rgba(0,0,0,0.04) 8px);
|
||
}
|
||
.sfc-slot[data-name]::after {
|
||
content: attr(data-name);
|
||
position: absolute;
|
||
bottom: calc(100% + 6px);
|
||
left: 50%;
|
||
transform: translateX(-50%);
|
||
padding: 3px 9px;
|
||
border: 1px solid rgba(255, 255, 255, 0.16);
|
||
border-radius: 5px;
|
||
background: rgba(18, 18, 18, 0.92);
|
||
color: #fff;
|
||
font-size: 12px;
|
||
white-space: nowrap;
|
||
box-shadow: 0 3px 8px rgba(0, 0, 0, 0.35);
|
||
opacity: 0;
|
||
pointer-events: none;
|
||
transition: opacity 0.12s ease;
|
||
z-index: 30;
|
||
}
|
||
.sfc-slot[data-name]:hover::after { opacity: 1; }
|
||
.sfc-caption {
|
||
margin: 0.35rem 0 0;
|
||
text-align: center;
|
||
font-size: 0.85rem;
|
||
color: var(--gray-600, #6c757d);
|
||
}
|
||
.sfc-error {
|
||
max-width: 540px;
|
||
margin: 1rem 0;
|
||
padding: 0.6rem 1rem;
|
||
border: 1px solid #f5c2c7;
|
||
border-radius: 6px;
|
||
background: #f8d7da;
|
||
color: #842029;
|
||
font-size: 0.9rem;
|
||
}
|
||
</style>
|
||
{{- end -}}
|
||
|
||
{{- if and $pattern (ne (len $tokens) 9) -}}
|
||
<div class="sfc-error">
|
||
crafting 的 pattern 需要恰好 9 个 token(3 行 × 3 列),当前是 {{ len $tokens }} 个。
|
||
请检查 pattern="a a a\nb b b\nc c c" 的写法。
|
||
</div>
|
||
{{- else -}}
|
||
<figure class="sfc-crafting" style="background-image: url('{{ $table.RelPermalink }}');">
|
||
{{- range $i, $slot := $slots -}}
|
||
{{- $val := "" -}}
|
||
{{- if eq $slot.key "out" -}}
|
||
{{- $val = trim ($ctx.Get "out") " " -}}
|
||
{{- else if $pattern -}}
|
||
{{- $token := "" -}}
|
||
{{- if lt $i (len $tokens) -}}{{- $token = index $tokens $i -}}{{- end -}}
|
||
{{- if and (ne $token "") (ne $token ".") -}}
|
||
{{- $v := trim ($ctx.Get $token) " " -}}
|
||
{{- if eq $v "" -}}
|
||
{{- if findRE "^[a-z0-9_]+$" $token -}}{{- $v = $token -}}{{- end -}}
|
||
{{- end -}}
|
||
{{- $val = $v -}}
|
||
{{- end -}}
|
||
{{- else -}}
|
||
{{- $val = trim ($ctx.Get $slot.key) " " -}}
|
||
{{- end -}}
|
||
{{- partial "crafting-slot.html"
|
||
(dict
|
||
"val" $val
|
||
"cls" $slot.cls
|
||
"x" $slot.x
|
||
"y" $slot.y
|
||
) -}}
|
||
{{- end -}}
|
||
{{- with $ctx.Get "caption" -}}
|
||
<figcaption class="sfc-caption">{{ . }}</figcaption>
|
||
{{- end -}}
|
||
</figure>
|
||
{{- end -}}
|