-
Notifications
You must be signed in to change notification settings - Fork 2
/
rss
933 lines (919 loc) · 93.1 KB
/
rss
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>Sansui's blog</title>
<link>https://sansui233.com</link>
<description>记录学习和生活的个人博客</description>
<lastBuildDate>Tue, 03 Sep 2024 01:45:09 GMT</lastBuildDate>
<docs>https://validator.w3.org/feed/docs/rss2.html</docs>
<generator>https://github.com/jpmonette/feed</generator>
<language>zh-CN</language>
<copyright>All rights reserved 2022, Sansui</copyright>
<atom:link href="https://sansui233.com/rss" rel="self" type="application/rss+xml"/>
<item>
<title><![CDATA[Windows 调整之中文字体]]></title>
<link>https://sansui233.com/posts/2023-09-29-windows-system-chinese-fonts-adjustment</link>
<guid>https://sansui233.com/posts/2023-09-29-windows-system-chinese-fonts-adjustment</guid>
<pubDate>Thu, 01 Aug 2024 18:08:00 GMT</pubDate>
<description><![CDATA[让 windows11 字体更好看的一些设置与字体浅谈]]></description>
<content:encoded><![CDATA[<blockquote>
<p>以下仅适用于低于 4k 缩放 200% 的显示器</p>
</blockquote>
<p>微软雅黑作为随着 Windows7 出现的字体,加上遥遥领先(?)的 ClearType,在当时的 1080p 显示器上十分清晰易读。</p>
<p>但如今的显示器分辨率越来越高,旧版微软雅黑的设计存在着明显的缺陷。</p>
<p>一是其字形设计并不平衡,中宫过大,有的字形可以以难看来形容;二是微软雅黑字形只在 4K 屏 200% 缩放(以上的配置)上有着较好的显示效果。</p>
<p>微软曾经设计过“另一版的微软雅黑”,即 Noble Scarlet,但并没有在正式的系统中使用。这一版字体设计依然中宫偏大,但相对老版收敛了不少,平衡了一些。</p>
<p>另外,如果你不巧像我一样用着 2K 或 2.5K 屏,</p>
<ul>
<li>在 24寸时,100% 缩放字体比较合适,但与 16 寸 1080p 显示器差不多清晰度,不过屏幕可用空间更大。</li>
<li>在 21 寸时,100% 缩放字体会偏小,比较锻炼眼睛。150% 缩放字体大小比较合适,效果更细腻,但字型会比较怪,且屏幕可用空间与 1080p 相同。</li>
<li>在 16 寸时,150% 缩放字体稍微偏小,效果比较细腻,但非整数倍缩放+ClearType 的加持下,一些像素被吞掉,笔画的间距不平衡,有种“ windows 特有的字被虫噬的美”。</li>
</ul>
<p><img src="https://img-cf.sansui233.com/imgs/2024/08/202408190158527.webp" alt="字形"/></p>
<p>可以看到,上图的 100% 200% 缩放没有字形变形问题,可以说微软雅黑小字优化是考虑的 100% 缩放。100% 缩放显得糊则是因为图片放大放大倍率过高,实际不会有糊,而是有锯齿感。</p>
<p>150% 缩放会由于 clearType 的“锐化”导致字形变化,不知道的还以为换了个字体。如果是125%、175%的缩放,字体变形更加糟糕。</p>
<p>造成缩放问题的原因大概可以用下图进行简要解释:</p>
<p><img src="https://img-cf.sansui233.com/imgs/2024/08/202408190318888.webp" alt="缩放"/></p>
<p>Mac 上的 Retina 渲染相当于 4k 200% 缩放起步。而 windows 下, 2k-2.5k 的屏幕都在 200% 以下的缩放中挣扎。如果软件没有适配高分屏,没有 clearType,强制进行双线性缩放(常见于图片UI),就会显得非常糊。想体验这样的糊,可以下载旧版的原神启动器。</p>
<h2>需要准备</h2>
<ul>
<li>
<p><strong>Noble Scarlet</strong> 替换系统的微软雅黑。由于 Noble Scarlet 是一个未完成的字体,普遍使用的是社区修正版,以下是资源参考。</p>
<ul>
<li><a href="https://bbs.pcbeta.com/viewthread-1960120-1-4.html">pcbeta</a></li>
<li><a href="https://www.bilibili.com/read/cv6059905/">bilibili</a></li>
</ul>
</li>
<li>
<p>系统字体替换工具:搜索 “<a href="https://www.fishlee.net/soft/SysFontReplacer/">字体替换工具 by 随风飘扬</a>”。替换完后重启,否则可能有缩放错误。另外,github 上有一个非侵入式的系统字体替换工具 <a href="https://github.com/Tatsu-syo/noMeiryoUI">noMeiryoUI</a>,可惜换不全 windows 11,只是作为预览不同字体在系统上的效果倒是个很不错的工具。</p>
</li>
<li>
<p><a href="https://www.mactype.net/"><strong>MacType</strong></a> 改善 ClearType 的虫噬渲染方式带来的不均匀,使用后提升非常非常大。</p>
</li>
<li>
<p><strong><a href="https://source.typekit.com/source-han-serif/cn/">思源宋体</a></strong>:推荐将浏览器的 Serif 字体设置为此字体。默认的宋体真的,不论中文英文,都很丑……只适合打印。</p>
</li>
</ul>
<h2>常用正文黑体简述</h2>
<p><img src="https://img-cf.sansui233.com/imgs/2024/07/202407260100518.webp" alt=""/></p>
<h3>苹方</h3>
<p>苹方是一款设计上很优秀的字体,其间架结构、中宫非常平衡,既兼顾了传统的汉字笔画细节又有规整而现代的几何化,间距合理,阅读起来非常舒适。</p>
<p>但是……苹方的设计缺字重。</p>
<p>在设计上,苹方没有 Heavy 字重(<a href="https://support.apple.com/en-us/103203">参考</a>)。而在<a href="https://github.com/paraself/PingFang-Fonts">流行的 github 苹方字体仓库</a>中,则是将 Bold 字重映射到了 Heavy,而将原本的Medium 映射到了 bold。虽然这个问题不是苹果设计的导致的,而是一个再次分发时的错误,但致使目前网上能搜索到的第三方仓库的苹方字体整体字重均偏细。</p>
<p>另外,苹方在 2.5K 屏上表现非常糊,苹方问世时已经进入了 Retina 屏的时代,没考虑过在低 PPI 屏幕上的表现(不是4K屏缩放200%都别用)。</p>
<p>第三,苹果设备的显示的西文字体是 <a href="https://zh.wikipedia.org/zh-hans/San_Francisco_(2014%E5%B9%B4%E7%9A%84%E5%AD%97%E4%BD%93)">San Francisco</a>,不是苹方。在 <a href="https://lrd.im/blog/2022-01-17">细数 Pingfang SC 的七宗罪</a> 中,也提到仅使用苹方导致不同设备字体 fallback 的不一致的问题。而作为系统字体里的其他问题,例如缺失本地化的字型,也是大部分字体所缺乏的,这已经不仅仅是一个字体问题,而是和字体相关的和 UI 技术标准化问题,难以仅通过字体解决。而无比例数字、冒号不垂直居中、没有垂直标点等细节,则都是因为苹果显示标点数字用的 SF 字体,苹方在此类字符上算是基本能用,但缺少多种场景下的细节。</p>
<p>其他资源: <a href="https://www.figma.com/community/file/1089832205783108371">Pingfang for windows - Figma</a></p>
<p>另外,苹方是有版权限制,以下字体除了思源黑体,和大厂的开源黑体,均不可免费商用。</p>
<h3>思源黑体系列</h3>
<p>思源黑体(Noto sans) 是 google 的开源可商用字体,用于 Android 系统,在开源可商用的的黑体其质量无可替代。</p>
<p>更纱黑体是思源黑体的衍生,修改了西文部分,相比思源黑体上更符合作为 无明显风格特征的系统字体,带 hinting 在 1080p 和 2.5k 下都能保证良好的清晰度。</p>
<p>但是,思源黑体系列设计相比于国产的商用字体并不能算好,有时间架结构比较怪异,字形的细节不太统一,比如“用”字明显矮了一截,整理风格上给人一种不稳定感。同时也不是一个大气的字体,比如口字旁处理对于黑体而言偏小,“用”字矮了一些,但是在宋体设计上,“用”字矮的这一截反而让字体看起来平衡。而一个系列的字体衬线、非衬线的统一感来源于其比例,个人理解为思源/更纱系列是优先考虑宋体的字形,和黑体的比例有一定的结合。整体而言还是宋体的设计更加优秀。</p>
<p>相对而言更纱黑体更适合作为系统字体,有着合理的 hinting。思源黑体是不太适合低 ppi 屏的,它的 Regular 字重看起来像 Bold。</p>
<h3>方正兰亭系列(微软雅黑)</h3>
<p>Noble Scarlet (社区版)常规体是新设计中宫收窄的微软雅黑,而粗体是方正兰亭黑 Pro,因此在加粗时,字体明显会变小一圈。</p>
<p>微软雅黑系列字体在标点处理上很差,最直观的就是全角引号,太像半角的处理方式,很难看出前引号与后引号的区别。其实我在写这一篇文的时候,换了 Typora 的字体,才发现前后引号全打反了……</p>
<p>方正兰亭黑 Pro 想对于两版微软雅黑都有着更小的中宫,字形设计中正。但也由于稍小了一些,在低 ppi 屏的小字上笔画更容易显得不太均匀,渲染效果不太好。另外使用此字体需要相比于其他所有字体更大的行距,因为其较小的中宫,字间距显得相对宽了。</p>
<h3>汉仪旗黑系列</h3>
<p>近年来的国产安卓厂商字体都是汉仪旗黑的衍生,代表阿里的普惠体、鸿蒙体、小米的字体、Oppo的字体。</p>
<p>这系列字体间架结构合理,但笔画上更加激进,减弱了起笔与收笔的的传统突出,以追求几何感与现代的科技感。在观感上,这样规矩的方形会使得字体相比方正系列更加圆润,多了现代感但少了汉字的人情味,用于阅读小说时尤其明显。</p>
<p>仅字形而言,作为 UI 是非常不错的。不过 Misans 渲染出来明显偏粗,我没有测试其他同系列字体是否也有这样的问题。</p>
<h2>改掉 Windows 的默认中文无衬线字体</h2>
<p>很多无法分别修改中英字体的 windows 原生应用,当只设置了英文字体时,显示的中文是新宋体(SimSun),比如 vs studio。原因在于系统里的 Microsoft Sans-serif 字体名,回落到的第一个字体就是新宋体……难以想象微软雅黑出了十多年了还有这样的问题。</p>
<p>解决办法:</p>
<ul>
<li>winkey + R, 输入 regdit,进入 windows注册表</li>
<li>进入 <code>HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\FontLink\SystemLink</code></li>
<li>把 Microsoft Sans Serif 的值中 SIMSUN.TTC 那一行去掉。这样默认的无衬线体就会往后 fallback 到系统的微软雅黑上。</li>
</ul>
<hr/>
<p>创建于 2023-09-29 02:25:44</p>
<p>更新于 2024-08-19 01:45:31</p>]]></content:encoded>
<category domain="https://sansui233.com/categories/工具">工具</category>
</item>
<item>
<title><![CDATA[Windows 命令行相关配置之 msys2+zsh+zi]]></title>
<link>https://sansui233.com/posts/windows-zsh-conf</link>
<guid>https://sansui233.com/posts/windows-zsh-conf</guid>
<pubDate>Fri, 15 Mar 2024 20:35:00 GMT</pubDate>
<content:encoded><![CDATA[<p>长久以来,遇到 bash 脚本会临时切 git-bash 中的 bash。由于用的语言都有自己的包管理器,倒也一直够用。但是最近涉及到一些 c++,由 git-bash 提供的最小化环境东西缺得太多,几乎不能当个日常 shell 用,也没有 pacman 包管理,最后决定还是单独安装 msys2。</p>
<p>git-bash 和 msys2 同时安装不会冲突。msys2 是独立的 home 目录,而 git-bash 是与 windows 当前用户通用的。我本来想卸载 git-bash,但由于我现在还是用 powershell,最终发现 git-bash 不能卸载。一是 posh-git 只支持 git-bash 的 git;其次是,astro-nvim 中的一些插件需要 <code>git.exe</code> 在环境变量下,使用 alias 链接的 git 不行,而手动加环境变量会把 git 以外的程序也加进去,造成 msys2 的工具与 powershell 本身工具的冲突。</p>
<p>想来想去,决定保留 git-bash 到最小化的状态,当成 powershell 的插件用。unix-like shell 以及相应的包管理还是 msys2。</p>
<h2>安装 msys2</h2>
<p>见 <a href="https://www.msys2.org/">https://www.msys2.org/</a> 。安装过程没什么好说的,唯一要注意的在于安装目录的权限必须是当前用户可以完全控制,否则后续各种包的安装都会有一大堆问题。如果因为强迫症安装到 Program Files 下,则需要手动添加当前用户的权限。</p>
<h3>软链接问题</h3>
<p>windows 的软链接本来也是个很麻烦的问题。到 msys2 下,还多了一个软链接方式兼容问题。msys2 默认是 <code>ln -s</code> 是复制,要用 windows 风格的软链接,可以改安装目录下的各种 <code>.ini</code> 文件中的配置。</p>
<pre><code>MSYS="winsymlinks:lnk"
</code></pre>
<h2>zsh + zi</h2>
<h3>zsh 的安装</h3>
<pre><code class="hljs language-bash">pacman -S zsh
</code></pre>
<p>老实说个人觉得和 linux 上的 zsh 相比还是差了一大截,用起来和 bash 感觉差不多。只是 zsh 插件管理的选择比较多</p>
<h3>zi 的安装</h3>
<p>关于 zsh 插件管理,之前在 git-bash 上我也安装了 oh-my-zsh,但是环境原因,遇到的 bug 着实太多,基本不用。另外,最大的问题是启动太慢,每次启动长达 10 秒。我分析了一下初始化脚本的执行时长,发现拖慢速度的罪魁祸首是初始化命令补全(就不能异步吗啊!)当然用 mac 时 omz 也有点慢,但显然没有 msys2 里这么离谱。</p>
<p>下午吐槽这个事情后,Antarx 说他换 zi 了。我试了下,确实很快,从没超过3s,令人偷税。</p>
<ul>
<li>zi 的安装:<a href="https://wiki.zshell.dev/docs/getting_started/installation">https://wiki.zshell.dev/docs/getting_started/installation</a></li>
</ul>
<p>安装过程最好在 msys2 的 GUI 终端下进行,因为需要登录的默认目录是在 home 的当前用户下。但这里又有另一个问题 —— msys2 不带 git。如果系统有另外安装 git,想复用,可以 cmd 启动 zsh,不指定启动的目录,指定继承环境变量。</p>
<pre><code class="hljs language-cmd">C:\\msys64\\msys2_shell.cmd -defterm -no-start -mingw64 -use-full-path -shell zsh
</code></pre>
<h3>zi 的配置与插件</h3>
<p><a href="https://wiki.zshell.dev/docs/getting_started/installation">安装Wiki</a> 在不断更新,检查最新版的安装方法。</p>
<p>安装好后,<code>.zshrc</code> 里添加如下,写好重启 zsh 即可。</p>
<pre><code class="hljs language-bash">$ vi ~/.zshrc
<span class="hljs-comment"># zsh</span>
<span class="hljs-built_in">setopt</span> AUTO_PUSHD
<span class="hljs-built_in">export</span> CLICOLOR=1
<span class="hljs-built_in">export</span> LSCOLORS=ExGxFxdaCxDaDahbadeche
<span class="hljs-built_in">zstyle</span> <span class="hljs-string">':completion:*'</span> list-colors <span class="hljs-string">"<span class="hljs-variable">${(@s.:.)LS_COLORS}</span>"</span>
<span class="hljs-built_in">alias</span> <span class="hljs-built_in">ls</span>=<span class="hljs-string">'ls --color=auto'</span>
<span class="hljs-built_in">alias</span> la=<span class="hljs-string">'la --color=auto'</span>
<span class="hljs-comment"># zi</span>
<span class="hljs-built_in">typeset</span> -A ZI
ZI[BIN_DIR]=<span class="hljs-string">"<span class="hljs-variable">${HOME}</span>/.zi/bin"</span>
<span class="hljs-built_in">source</span> <span class="hljs-string">"<span class="hljs-variable">${ZI[BIN_DIR]}</span>/zi.zsh"</span>
<span class="hljs-built_in">autoload</span> -Uz _zi
(( <span class="hljs-variable">${+_comps}</span> )) && _comps[zi]=_zi
<span class="hljs-comment"># source <(curl -sL init.zshell.dev); zzinit</span>
<span class="hljs-comment"># 插件</span>
<span class="hljs-comment"># 提前运行一次 zi ice pick"async.zsh" src"pure.zsh"</span>
zi light sindresorhus/pure
zi light agkozak/zsh-z <span class="hljs-comment"># 不能用 eval "$(zoxide init zsh)" 会冲突</span>
zi snippet OMZP::git
zi light zsh-users/zsh-completions
<span class="hljs-comment"># 提前运行一次 zi ice wait lucid atload'_zsh_autosuggest_start'</span>
zi light zsh-users/zsh-autosuggestions
<span class="hljs-comment"># 提前运行一次 zi ice wait lucid atinit='zpcompinit'</span>
zi light zdharma/fast-syntax-highlighting
</code></pre>
<h2>Windows Terminal 设置</h2>
<p>在设置里改 json,加相应的 profile。可以使用 <code>-use-full-path</code> 继承 windows 系统的环境变量。</p>
<pre><code class="hljs language-json"><span class="hljs-punctuation">{</span>
<span class="hljs-attr">"commandline"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"C:\\msys64\\msys2_shell.cmd -defterm -here -no-start -mingw64 -use-full-path -shell zsh"</span><span class="hljs-punctuation">,</span>
<span class="hljs-attr">"guid"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"{c420e0af-28d9-4742-a6b8-83d5fcf424e9}"</span><span class="hljs-punctuation">,</span>
<span class="hljs-attr">"icon"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"C:\\msys64\\mingw64.ico"</span><span class="hljs-punctuation">,</span>
<span class="hljs-attr">"name"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"msys2 zsh"</span><span class="hljs-punctuation">,</span>
<span class="hljs-attr">"startingDirectory"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"%USERPROFILE%"</span>
<span class="hljs-punctuation">}</span>
</code></pre>
<h2>Vscode Terminal 设置</h2>
<pre><code class="hljs language-json"><span class="hljs-attr">"terminal.integrated.profiles.windows"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
<span class="hljs-attr">"MSYS2 zsh"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
<span class="hljs-attr">"path"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"C:\\msys64\\msys2_shell.cmd"</span><span class="hljs-punctuation">,</span>
<span class="hljs-attr">"args"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span><span class="hljs-string">"-defterm"</span><span class="hljs-punctuation">,</span><span class="hljs-string">"-here"</span><span class="hljs-punctuation">,</span><span class="hljs-string">"-no-start"</span><span class="hljs-punctuation">,</span><span class="hljs-string">"-mingw64"</span><span class="hljs-punctuation">,</span><span class="hljs-string">"-use-full-path"</span><span class="hljs-punctuation">,</span><span class="hljs-string">"-shell"</span><span class="hljs-punctuation">,</span><span class="hljs-string">"zsh"</span><span class="hljs-punctuation">]</span><span class="hljs-punctuation">,</span>
<span class="hljs-attr">"env"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span> <span class="hljs-attr">"MSYSTEM"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"MINGW64"</span> <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
<span class="hljs-attr">"overrideName"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">true</span></span>
<span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
<span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
</code></pre>
<h2>Mintty 设置</h2>
<p>Mintty 是 msys2 里默认的终端 GUI,默认 shell 是 bash。修改 <code>mingw64.ini</code> 为如下内容。</p>
<pre><code>MSYS=winsymlinks:lnk
MSYS2_PATH_TYPE=inherit
MSYSTEM=MINGW64
SHELL=/usr/bin/zsh
</code></pre>
<h2>npm设置</h2>
<p>如果有使用 npm 进行包管理,继承自环境变量的 npm 补全时会报错。需要设置为</p>
<pre><code class="hljs language-shell"><span class="hljs-meta prompt_">$ </span><span class="bash">npm config edit</span>
script-shell=C:\msys64\usr\bin\bash.exe
shell=C:\msys64\msys2\usr\bin\bash.exe # 重要<span class="hljs-meta prompt_">
$ </span><span class="bash">npm config list</span>
</code></pre>
<h2>conda 设置</h2>
<p>如果有使用 conda 进行 python 开发,继承自环境变量的 conda 默认初始化脚本也有问题……从 Github 上查到的解决方法……</p>
<pre><code class="hljs language-shell"><span class="hljs-meta prompt_"># </span><span class="bash">>>> conda initialize >>></span><span class="hljs-meta prompt_">
# </span><span class="bash">!! Contents within this block are managed by <span class="hljs-string">'conda init'</span> !!</span>
if [ -f '/c/Users/me/miniconda3/Scripts/conda.exe' ]; then
#eval "$('/c/Users/me/miniconda3/Scripts/conda.exe' 'shell.zsh' 'hook')"
eval "$('/c/Users/me/miniconda3/Scripts/conda.exe' 'shell.zsh' 'hook' | sed -e 's/"$CONDA_EXE" $_CE_M $_CE_CONDA "$@"/"$CONDA_EXE" $_CE_M $_CE_CONDA "$@" | tr -d \x27\\r\x27/g')"
fi<span class="hljs-meta prompt_">
# </span><span class="bash"><<< <span class="hljs-string">conda initialize <<<</span></span>
</code></pre>
<h3>ssh配置共用</h3>
<p>如果有多个 ssh 账户的密钥,最好是软链接一下配置目录。注意需要前面的修改软链接方式,否则还是去资源管理器手动软链接吧。</p>
<pre><code class="hljs language-shell">ln -s /c/Users/me/.ssh ~/.ssh
</code></pre>
<h2>参考</h2>
<p><a href="https://hustlei.github.io/2018/11/msys2-for-win.html#%E5%AE%89%E8%A3%85git%E5%92%8Cvim">msys2-for-win</a></p>
<p><a href="https://sdl.moe/post/zsh-conf/">https://sdl.moe/post/zsh-conf/</a></p>]]></content:encoded>
<category domain="https://sansui233.com/categories/工具">工具</category>
</item>
<item>
<title><![CDATA[笔记 - 像素的一生]]></title>
<link>https://sansui233.com/posts/2024-02-29_像素的一生</link>
<guid>https://sansui233.com/posts/2024-02-29_像素的一生</guid>
<pubDate>Thu, 29 Feb 2024 23:45:00 GMT</pubDate>
<description><![CDATA[浏览器渲染原理]]></description>
<content:encoded><![CDATA[<p>内容来自于 2018 年谷歌的一个视频。原视频不长但内容很多,非常值得一看。Chrome 的渲染机制是在不断变化的。</p>
<p>笔记原存于 Logseq,如果有类似于,“见CSS/图层”一类的语句,为笔记内超链接。相关概念需自行了解。</p>
<p>📚 <strong>资料</strong></p>
<ul>
<li>
<p><a href="https://www.bilibili.com/video/av35265997/?vd_source=a94b8ba67535fb1431364b8c5fac341d">b站视频 - 2018</a></p>
</li>
<li>
<p><a href="https://docs.google.com/presentation/d/1boPxbgNrTU0ddsc144rcXayGA_WF53k96imRH8Mp34Y/edit?pli=1">英文slides</a></p>
</li>
<li>
<p><a href="https://segmentfault.com/a/1190000020102554">思否文章</a></p>
</li>
</ul>
<p><strong>渲染流程</strong>:web content → magic(rendering) → pixels</p>
<h2>1. Web content</h2>
<p>最常见的 HTML + CSS + Javascript API</p>
<p>还有图片、视频、音频、web assembly、WebGL、Canvas、PDF等等</p>
<p><img src="https://cdn.jsdelivr.net/gh/NamiLing/upic/picgo/202402292342847.webp" alt="Web Content"/></p>
<h2>2. 渲染</h2>
<p>渲染是在一个 sandbox 进行的。渲染引擎 Blink 是渲染代码的一个子集。</p>
<p>操作系统渲染 API:OpenGL,DirectX(Windows), vulkan。包含 textures shaders 等等。</p>
<h3>2.1 渲染目标</h3>
<ol>
<li>
<p>把 web content 渲染为 openGL 的调用</p>
</li>
<li>
<p>为更新渲染建立起对应的数据结构</p>
</li>
</ol>
<h3>2.2 基本渲染流程</h3>
<p><img src="https://cdn.jsdelivr.net/gh/NamiLing/upic/picgo/202402292342848.webp" alt="渲染流程"/></p>
<p>渲染流程太复杂,会被分为几个阶段进行数据结构的转换</p>
<p>不是每一次更新渲染,都要走全部的流程。相关看 浏览器/渲染原理 中的回流与重绘。</p>
<h4>HTML to DOM</h4>
<p>解析 HTML 为 DOM 树。DOM树的作用有两个,一个表示文档结构,二是暴露 API 给 Javascript,由 V8 JS引擎进行 API 绑定。</p>
<h4>CSS to ComputedStyle</h4>
<p>CSS 转换为 StyleRule 集,每个 StyleRule 包含 CSSSelector 和 CSSPropertyValue。流程如图</p>
<p><img src="https://cdn.jsdelivr.net/gh/NamiLing/upic/picgo/202402292342849.webp" alt="css parser"/></p>
<p>根据 css 样式规则,计算出每个 DOM 元素样式属性的最终值,存储于 <strong>ComputedStyle</strong> 对象模型中,是一个 style properties 与 values 的超大映射。这个过程被称为 Style Resolution。</p>
<p><img src="https://cdn.jsdelivr.net/gh/NamiLing/upic/picgo/202402292342850.webp" alt="style resolution"/></p>
<p><strong>ComputedStyle</strong> 对象已经暴露给了 JS。使用<code>getComputedStyle(element)['padding-top']</code>即可获取。在 Dev tools 的 Elements 中的 Computed 选项卡的值就是依据此 对象来的。</p>
<h4>Layout Stage</h4>
<p>例子:</p>
<ul>
<li>Web 最基础的 Block Flow 布局,需要计算出 Block 的 x、y、width、height。</li>
<li>由于 Block 自适应高度,需要根据内容的尺寸,找到文字换行的地方,以计算每个 Block 的高度。</li>
<li>每一个 Block 的矩形有多种边界(在CSS/盒模型中说得很清楚)。内容 overflow 时,需要计算两个矩形,一个是<strong>实际内容区域</strong>,一个是<strong>能显示出的内容的区域</strong>。如果内容可滚动,还要计算<strong>滚动边界</strong>和<strong>滚动条边界</strong>。</li>
</ul>
<p>Document 的根节点本身就是 overflow 且可滚动的。</p>
<p>Layout Objects 也树结构存在,几乎与 DOM 是一对一,但并非总是如此。比如伪元素、浮动元素。</p>
<p><img src="https://cdn.jsdelivr.net/gh/NamiLing/upic/picgo/202402292342851.webp" alt="layout"/></p>
<p>在 style 计算后会构建一个没有填入任何数据的 <strong>Layout Tree</strong>。</p>
<p><strong>更新布局</strong>的本质就是遍历 layout tree 并向里面填充所有数据。</p>
<p>Slides里说目前没有把 Layout Stage 的输入输出区分开,但没细说,只是说下个版本会改。放个图</p>
<p><img src="https://cdn.jsdelivr.net/gh/NamiLing/upic/picgo/202402292342852.webp" alt="Layout Stage NG"/></p>
<h4>Paint to display item lists</h4>
<p>做类似于在指定坐标内画一个红色的矩形这样的动作。代码结构上 ,是 LayoutObject 有一个 Paint 方法。去调用更底层的 Paint API。</p>
<p><strong>此阶段生成“作画步骤”,还没有真的画出像素</strong>。步骤是可以重放的。至于为什么这样做,之后再说(然而之后并没有说)。</p>
<p>Paint 是从 z-index 最大到最小进行的,而不是 DOM 的前后顺序。而两个并列的层叠上下文时,后覆盖前。在一个 CSS/层叠上下文 内,按层叠上下文的堆叠规则绘制(z轴的层叠规则),如图</p>
<p><img src="https://cdn.jsdelivr.net/gh/NamiLing/upic/picgo/202402292342853.webp" alt="image.png"/></p>
<h4>Rasterization 栅格化</h4>
<p>将 Display Item(位于 CC Layer 中,之后说)中记录的 Paint 操作转化为<strong>位图</strong>(bitmap)。</p>
<p>raster bitmap 通常保存于 GPU 内存中,被 <strong>OpenGL Texture Object</strong> 引用。GPU 不仅可以保存 bitmap,也可以生成 bitmap。叫 <strong>accelerated rasterization</strong>。</p>
<p><strong>此时像素纹理已经生成到内存,但还是没有画到屏幕上。</strong></p>
<p><img src="https://cdn.jsdelivr.net/gh/NamiLing/upic/picgo/202402292342854.webp" alt="Rasterization"/></p>
<p>栅格化通过 <strong>SKIA 库</strong>生成对 <strong>OpenGL</strong> 的调用。SKIA 提供了一系列对硬件的抽象。具体而言,PaintOps 会调用 SKIA 中的 SkCanvas 对象。</p>
<p><img src="https://cdn.jsdelivr.net/gh/NamiLing/upic/picgo/202402292342856.webp" alt="SKIA"/></p>
<p>由于渲染过程是在 sandbox 进行的, 不能产生系统调用,OpenGL 调用是通过 command buffer 塞进另一个进程 <strong>GPU Process</strong> 执行的。GPU Process 接受到绘制命令后通过 GL API 去产生真正的 GL 调用。</p>
<p>使用 GPU process 隔离渲染进程除了渲染进程有沙盒机制外,OpenGL 可能也不太稳定或者是有漏洞。GPU Process 可以做一些保护措施。</p>
<p>GL API 来源于系统动态库 <code>libGLESv2.so</code>。但是 windows 中来自于 Google 的 ANGLE 库 <code>libglesv2.dll</code>,因为 Windows 上渲染不是用的 OpenGL,而是 DirectX API。ANGLE 库可以翻译 OpenGL 调用为 DirectX 调用。</p>
<p><img src="https://cdn.jsdelivr.net/gh/NamiLing/upic/picgo/202402292342857.webp" alt="GL API"/></p>
<h2>3. 图层合成</h2>
<h3>3.1 帧与动画</h3>
<p>每一帧是当前 Web 内容的完整呈现。</p>
<p>动画是连续的帧。针对第一部分提到的 style、layout、paint、raster,浏览器都做了跟踪失效的处理,只重绘改变的部分,其他部分复用。</p>
<h3>3.2 合成线程</h3>
<p>一个单独的渲染线程,减少 JS 主线程的其他操作和渲染之间 block。</p>
<p><strong>图层</strong>给合成线程渲染。比如 video 和 gif 在单独的图层,还有 transform3D, will-change 等 css 属性也会新建图层进行处理。</p>
<p>合成线程也需要处理交互。能处理的先合成线程处理(比如滚动),处理不了的就进主线程。</p>
<p><strong>Layer Tree</strong>(CC Layer Tree)</p>
<p>图层也是以树结构存在,前序遍历。</p>
<p>有的图层的存在不是绘制,而是图层效果,比如剪贴蒙版、滤镜。</p>
<p><img src="https://cdn.jsdelivr.net/gh/NamiLing/upic/picgo/202402292342858.webp" alt="layer tree"/></p>
<p>图层的合成位于 CC (Chronium compositor) namspace, 所以代码里有很多 <code>cc::layer</code>。</p>
<p>如果一个 Layout Object 没有指定单独的 layer(比如没有 will-change 属性),就会被绘制到父 layer 的图层。</p>
<p>Paint Layer 是要被分到 CC LayerTree 的。这就是CSS/层叠上下文与CSS/图层之间的关系。</p>
<p><img src="https://cdn.jsdelivr.net/gh/NamiLing/upic/picgo/202402292342859.webp" alt="image.png"/></p>
<p><img src="https://cdn.jsdelivr.net/gh/NamiLing/upic/picgo/202402292342860.webp" alt="paint layer map"/></p>
<h3>3.3 compositioning update</h3>
<p>在上一章的流程中,没有讲到合成这步,实际要加上。因为合成不是必须的,但合成步骤能优化渲染。</p>
<p><img src="https://cdn.jsdelivr.net/gh/NamiLing/upic/picgo/202402292342861.webp" alt="更新合成"/></p>
<p>未来,创建图层的工作会放到 paint 之后(slimming paint)</p>
<p><img src="https://cdn.jsdelivr.net/gh/NamiLing/upic/picgo/202402292342862.webp" alt="commit"/></p>
<p><strong>commit</strong></p>
<p>提交一次合成。这里合成线程与主线程都存在 layer tree,需要同步合成线程与主线程的状态。</p>
<h3>3.4 Tilling</h3>
<p>在 rastering 阶段,把 CC layer 分块成 tile。</p>
<p><strong>tile 是 raster 的最小单位</strong>,在专门的 <strong>raster 线程</strong> 进行栅格化。</p>
<p>合成线程有一个 <strong>tile manager</strong> 安排 tile 优先级。</p>
<p>不同分辨率的 tile 策略是不同的。</p>
<h3>3.5 Drawing</h3>
<p>不同 tile 合成为 <strong>Quad</strong>。Quad 引用内存中的 raster output,封装在合成进程中,再提交到浏览器进程。浏览器动画帧的<strong>帧</strong>概念就是 Quad。</p>
<p><img src="https://cdn.jsdelivr.net/gh/NamiLing/upic/picgo/202402292342863.webp" alt="Quad"/></p>
<p>不同 commit 有先后顺序,需要从 pending <strong>激活</strong>再绘制。</p>
<h3>3.6 Display</h3>
<p>浏览器进程将 Quad 展示到屏幕上的过程。位于 Viz 组件中,调用 OpenGL 绘制 GPU 进程中的 Quad 资源,和 rastering 的 GL call 一样。</p>
<p>大部分平台的显示合成输出是双倍缓冲(有过游戏画面撕裂经验的应该对这有概念),quad 是在后台缓冲器(GPU的还是Viz?)中绘制的,用 swap 命令让后台的 quad 到前台展示。</p>
<h2>4. 总结</h2>
<p>Blink 引擎严格执行了主线程的步骤。但由于要实现 Web 平台化,是有一些合成线程的权限的。</p>
<p><img src="https://cdn.jsdelivr.net/gh/NamiLing/upic/picgo/202402292342864.webp" alt="总结"/></p>
<h2>其他</h2>
<p>渲染器和浏览器都用到了 GPU,都有向GPU进程的IPC通道。</p>
<p>如果想让滚动的交互产生的动画不在主线程而在合成线程执行,需要强制 will-transform 分层</p>]]></content:encoded>
<category domain="https://sansui233.com/categories/学习">学习</category>
</item>
<item>
<title><![CDATA[碎碎念001]]></title>
<link>https://sansui233.com/memos</link>
<guid>https://sansui233.com/memos?id=2024-02-29 01:28</guid>
<pubDate>Wed, 28 Feb 2024 17:28:00 GMT</pubDate>
<content:encoded><![CDATA[<h2>2024-09-03 09:31:00</h2>
<p>看到一个交互的仓库:<a href="https://veloxijs.com/">veloxijs.com</a>。瞪大了眼睛……其实 react-spring 做动画也好用但缺交互事件,交互要额外绑。而我觉得其实绑交互才是最麻烦,多平台有区分,还要干掉一些和原生交互冲突的问题……我在那手撮交互和动画算什么!!不过一看打包体积 50 多k,那还是手搓吧,按需手撮 5k 不到……</p>
<h2>2024-08-26 10:48:17</h2>
<p>推荐短篇漫画<a href="https://weibo.com/5790748645/Otq6Td0Jm">小狐狸化形记</a>。在作品要么连篇累牍的设定与废话,要么网文快节奏模板的时代,已经感觉已经好久好久,没有看过这样能写进教科书一般的,剧本了。</p>
<p>二游的剧情其实我都看不太进去,大概就 fgo 2.6 还行,1.6 已经不记得了……然后原里枫丹审判看得还行,没有逻辑 bug 已经万幸了,要有代入感就算了。二游太注重打造异世界和卖角色了,但<strong>代入感反而是要能映射现实才会有</strong>…支线有不少抄名著的但抄得很生硬,反应人性不是故意写脑子有病的家庭啊喂。</p>
<p>枫丹把矛盾归结在了“天理”上,为了解决“天理”的问题而选择牺牲自己,算是非常讨巧的做法,这是一种“虚构的矛盾”,虽然不符合现实但是非常符合异世界卖角色的二游。</p>
<p>崩铁 2.3匹诺康尼大立意很好,但小分段上也还是在卖异世界社达体验,观感上最好的是只为剧情服务的星期日……他出场不多(物理)却有非常多真实的侧写,一是和妹妹的互动,二是有领导压力和家族派系之间的压力,三是有真实的动机——想人们能快乐摸鱼。这些和异世界结合也没有违和感。大部分角色做好一个点就不错了,砂金做好童年创伤就大卖特卖…说到底还是大部分二游角色过于扁平,没有现实的复杂度支撑不住。</p>
<p>然后这也可以解释崩铁垃圾桶会塑造得很成功。首先主角独特的捡垃圾 xp 就逆天,其次“垃圾”这词在当代象征了太多。垃圾除了能指人,还有十连抽出“金色传说垃圾”嘲讽了抽卡。垃圾桶的外形和战斗机制也足够搞笑……符号比角色好出效果可太真实了。</p>
<p>然后说回 fgo 2.6,厉害的点就在于每个人都是活的,矛盾和动机是真实且鲜明的“人之间的故事”(指抽象的人)。明明都是异世界卖角色,蘑菇怎么写出来的……可能是 fgo 最不需要的就是沉浸感吧……对于看剧情的玩家,只要脱离沉浸感,纯写剧情反而结果会好…</p>
<p>古剑三也挺好的,很明显这也是不用代入主角的游戏,有沉浸感大概是本土文化滤镜吧。玩基于西方神话种族体系的就不行,代不了。</p>
<h2>2024-08-23 10:48:53</h2>
<p>屏幕调白平衡的软件 <a href="https://justgetflux.com/">https://justgetflux.com/</a> ,才发现我最适应的色温大概在 5700k。标准的 6500K sRGB 对我来说太刺眼了,看不了太长时间的蓝光+高饱和……</p>
<h2>2024-08-23 08:18:14</h2>
<p>虽然但是,ppi 小于 200,一般场景还好,但一开始涉及打印,看小说一类的,就不免会和现实的媒介比,win 这不上 4k 屏感觉真眼瞎……什么,16寸的2.5k屏 ppi 还不够吗?你好,是的,真的很明显,被虫啃了。</p>
<p>另外,把网页的字体 fallback 换成了方正兰亭黑Pro,字形真的前所未有的顺眼……微软雅黑就算改进过的也还是烂……不过 hinting 做得最好的还是更纱黑体。思源的 hinting 是一坨了。</p>
<p>关于 <span class="tag">#博客 </span>搜索,有考虑改数据库存储的方案,方案早就有想好了,客户端的接口形式也预留了,现在的 memo 就是数据获取的其中一种实现,非常的 CSR。剩下的就是看能不能找到靠谱且没那么贵的服务了,个人博客的 hosting 没什么流量,我也不是很常用。说来其实 memo 想存数据库主要是考虑搜索,目前的全文搜索真的很全文,都没有索引的……虽然写了三年的废话大小加起来连500k 也没有,长文那边 100k 也没有,完全不必担心……</p>
<p>个人一生能写的字数,大概除了写小说的,做成搜索的话用无索引全文搜索完全够了……我好像十四年的微博7000条了吧,可能 50-80 万字。memo 差不多有十万字,但搜索起来感觉就是瞬间无延迟,连 Searching 的状态指示都看不到……最大的时间消耗在第一次获取搜索数据上,也就是网络延迟……而且不是全文匹配,结果一旦符合就中断相应条目的匹配,搜不到时才是用时最久的,也用不了几秒。这么一说,个人博客废话再多也还是没有必要上数据库……实在久了就加上,只搜最近的500条所有带 tag 的条目……然后以后的处理器会越来越好,感觉远远大于,人的废话膨胀速度……</p>
<h2>2024-08-18 00:30:21</h2>
<p>跟着一梦徽州教程一步步摆做了几次后,突然就会变得会设计家园了……对于信息密度的把控与刻画细节,是可以通过重复临摹提升的,如果要走商业风格,前期多临摹很有用,真的。</p>
<p>另外谢谢谦谦……虽然自己还是很菜,但少了一些,再学什么都不会有所改变的想法。</p>
<p>真的不能总是让某些人狭窄的人生观去占据脑子,当把人考虑为一个定量的因素后,人才真的变成了一个定量的因素。但本不应如此,不应由过去的经验塑造未来,而应由当下。总是看别人、看过去,情况不会有任何改善。对未来做出承诺也是不可能的,只有看着过去决定未来的人可以对未来做出预测,想要有改变那未来必定难以预测。</p>
<p>所以请不要使用过去决定未来,会真正完全地丧失掉应有的活力。悲观的是简中的大氛围都是这样,存在着“无法赎清的罪孽”,甚至虚构的角色都不放过,比如散兵。</p>
<p>然后去了听 logseq 在 discord 的直播……全英文还是,可怕!只有在带耳机、网络好、对方没有很含糊不清的情况下比较听得懂。那个提问的有一点点印度口音的说话比管社区的人听得懂一些……很难想象这样要怎么面试啊啊啊啊!</p>
<p>我自从没什么机会说话后,又因为唱歌狂念日语歌词,中文已经说不太好了,稍微快一点舌头和口腔就会不听使唤,然后结巴……最近过剧情的时候都有意开始念台词了,像小学生一样,念不顺的词就重复念,练中文发音会用到的肌肉,特别是 ji 和 yi,舌根处用力把气流收得很窄,标准发音时会口吃,如果是说南方口音就不会口吃。才发现其实配音说话都很快,又快又清楚。天哪之前根本没觉得把话说得快而清楚是需要努力的一件事,我 18 年的视频说话就是又快又清楚的……落泪了</p>
<h2>2024-08-05 23:28:21</h2>
<p>才发现代码随想录的题解是相当个人的,废话超级多而且不说人话。KMP那里才完全感受到,一直在套名词定义,但其实直观解释两句就能让人明白,但就一直搁那里套定义,然后为了定义准确说了一堆废话。我感觉自从我做碎片化笔记后就变得不太会写教程了,我还是要努力去变得直观一些,多加一些图!</p>
<h2>2024-08-01 17:45:27</h2>
<p>解决 2024年 windows 只能设置一个字体的应用们的无衬线中文还是优先 fallback 到新宋体的问题:去注册表,<code>HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\FontLink\SystemLink</code>把 Microsoft Sans Serif 中 SIMSUN.TTC 那一行去掉……服惹 win7 就有微软雅黑了留着宋体 fallback 干嘛……还是说他们也知道微软雅黑的正文阅读体验很差劲……但宋体不搭更差劲啊!</p>]]></content:encoded>
<category>Diary</category>
</item>
<item>
<title><![CDATA[白嫖怪的经验]]></title>
<link>https://sansui233.com/posts/白嫖怪的经验</link>
<guid>https://sansui233.com/posts/白嫖怪的经验</guid>
<pubDate>Fri, 29 Dec 2023 22:09:00 GMT</pubDate>
<description><![CDATA[降本增效?嗯?]]></description>
<content:encoded><![CDATA[<p>作为一个合格的白嫖怪,列举一些个人用过的免费/低价云服务。</p>
<blockquote>
<p>注:不要滥用,白嫖在很多时候都是违反 TOS(服务条款)的。</p>
</blockquote>
<p>依据项目结构,主要分类为:</p>
<ol>
<li>免费域名购买</li>
<li>静态前端托管</li>
<li>api 服务托管</li>
<li>数据库服务托管</li>
<li>服务器购买</li>
<li>GPU 平台(AI)</li>
</ol>
<h2>域名相关</h2>
<p>由于国内存在对热门国外服务 ban 域名的情况,先持有个人域名是有必要的。有免费的,付费域名也不贵。但要注意国内域名要走备案,而备案又要求买国内的服务器,这不符合白嫖的认知。所以域名只看国外。</p>
<h3><a href="https://www.freenom.com/">Freenom</a></h3>
<p>可注册免费域名。1 个域名免费 1 年,续费要钱,1 年后想继续免费需要注册新域名。不适合长期持有。通常用于一些不想被人发现的临时服务。</p>
<h3><a href="https://www.namecheap.com/">Namecheap</a></h3>
<p>6 位纯数字 + xyz 域名,一年只要 1 刀,个人开发值得拥有。只要不抢热门,域名普遍不贵。</p>
<h3><a href="https://cloudflare.com/">Cloudflare</a></h3>
<p>著名的慈善 CDN 机构(不是)。在 CF 买域名要钱,但可以转入域名,并进行免费 DNS 解析,免费的防火墙和访问控制,免费的数据统计,免费的 SSL……</p>
<p>我个人非常喜欢 CF 的 dashboard,很直接。对域名进行管理,从输入网址开始只需要点三步,登录(切页面)=> 选域名 => 选功能,全程只切了两个页面。</p>
<p>对比一下阿里云。点登录按钮(切页面)=> 登录(切页面)=> 点控制台(切页面)=> 选域名控制台 => 选域名列表 => 选管理(切页面)。</p>
<h2>静态资源托管</h2>
<h3><a href="https://github.com">Github pages</a></h3>
<p>静态网页托管。hexo + github pages。静态博客,经典搭配,原汁原味。</p>
<p>不过被墙得厉害,即使没有墙,域名也被国内浏览器屏蔽。</p>
<h3><a href="https://www.jsdelivr.com/">Jsdelivr</a></h3>
<p>静态资源托管。Github 的加速网站。很多人拿来当图床。也容易被屏蔽。相当于把 github 当 cms 用,所以管理文件没有那么好用。</p>
<p>如果是目的不是用于开发,是明确违反了 TOS 的,只是量小的话没有人管罢了。Github 本身也不是拿来存二进制的。</p>
<h3><a href="https://vercel.com/">Vercel</a></h3>
<p>静态网页托管(其实可以不静态)。特点是国内 ping 值低,自动绑免费的 SSL。不过有一段时间 vercel 的 ip 也是被墙了的。所有没有在国内备案的服务都不保证直连的可访问性,特别是在量比较大的情况下。</p>
<h3>Cloudflare pages</h3>
<p>静态前端页面部署,类似 Vercel,优点大概是比 vercel 更难被墙。</p>
<h2>网盘,OSS</h2>
<p>嗯……网盘的资源,怎么能不算资源呢?</p>
<p>不过,要获取网盘资源的直链,至少要经过两层的 API,延迟相当高。而且国内的服务防滥用机制相当严格(国内带宽贵啊)</p>
<p>但有一个好处……现在网盘普遍在卷内容管理系统 (CMS),面向用户的产品,管理文件比 OSS 好用。主要稳定性在 API 上。</p>
<h3><a href="https://alist.nn.ci/">Alist</a> 网盘列表程序</h3>
<p>文档必看,这是一个集合了阿里云盘、百度网盘、Onedrive 等的网盘列表程序,利用各个网盘的 API,对各个网盘资源直接下载。看文档直接了解有什么服务可以白嫖,可以白嫖到什么程度。我在这照抄一下常用的不走服务器流量时的网盘:</p>
<ol>
<li>百度网盘:可直接下载 20M 以内的文件,限速。</li>
<li>阿里云盘:可下载所有文件,分享的链接限速,自己的网盘不限速。</li>
<li>Onedrive:可下载所有文件,不限速,但在国外。有 API 调用上限。</li>
</ol>
<p>当然,Alist 本身还是要有服务器的,但还有 paas 可以白嫖。</p>
<h3><a href="https://www.backblaze.com/cloud-backup/personal">BackBlaze</a></h3>
<p>对象存储,有一定的免费额度,cloudflare CDN 下行流量免费,可以说是个人白嫖图床最优选吧。知道这个是因为 rclone。</p>
<h2>API 托管</h2>
<p>主要列举 PaaS 平台。</p>
<h3><a href="https://vercel.com/">Vercel</a></h3>
<p>没错又是 Vercel。Vercel 还可以托管 Node.js 和 Python 脚本等等,拿来托管小的 API 服务是非常适合的。比如 <a href="https://waline.js.org/">Waline</a>。</p>
<blockquote>
<p>支持的语言:nodejs、php、python、ruby、go</p>
</blockquote>
<p>纯读取的 API 只用 Vercel 就可以了。如果需要上传下载动态内容,使用 Vercel + 任意数据库就可以,大部分网页应用的本质就是 CRUD。</p>
<p>Vercel 的免费版 <a href="https://vercel.com/docs/limits/overview">有限制</a>,对于个人站点来讲绰绰有余的限制。付费不便宜。</p>
<h3><a href="https://fly.io/">Fly.io</a></h3>
<p>有很小的免费额度。曾经用过,长期无访问会休眠。休眠不删数据。</p>
<h3>Heroku</h3>
<p>曾经白嫖界的王者,现在没有免费的实例了,只有 Github 学生包还有免费。会休眠,据说现在会删数据。</p>
<h3>国内平台边缘计算</h3>
<p>阿里云函数计算,腾讯云函数计算,都不是很贵。用边缘函数当服务主要是麻烦在不同平台的适配上。还有,国内走公网流量计费,也不适合大带宽的服务。</p>
<h2>数据库,BaaS</h2>
<p>BaaS 这里主要是指是数据库加上部分的后端服务,比如以 restful api 的方式访问数据库,而不是对数据库服务建立连接后写 sql。Headless CMS 也是一种 BaaS。</p>
<ol>
<li><a href="https://leancloud.cn/pricing/">LeanCloud</a> 开发版有一点免费额度。</li>
<li><a href="https://supabase.com/pricing">Supabase</a> 有 10G 免费额度。实例需要每周至少一触发,目前在用。知道的人不多,国内的薅羊毛大军没有进发到这。</li>
<li><a href="https://firebase.google.cn/pricing?hl=zh-cn">Firabase</a> 有一点点免费额度。</li>
</ol>
<p>总体用得不多,可以看文章结尾的参考。</p>
<h2>低价服务器</h2>
<p>常逛 hostloc 会知道几个被大量滥用、不保证在线率、随时可能跑路的商家。主打一个买了买不了吃亏,买了买不了上当。个人用来做实验倒是挺适合吧,多买几个,白嫖一个靠谱的 API 重定向做一下负载均衡还算也 OK。</p>
<ol>
<li><a href="https://www.racknerd.com/">racknerd</a> 12 刀 1 年的小服务器,普遍 DC 02 机房三网直连。</li>
<li><a href="https://virmach.com">virmach</a> 价格同上。有日本的机房,速度啥的挺好的。我是第一批迁过去的,传家宝系列,至今 10 刀一年。但发生过严重宕机,unavailable 了两天。</li>
<li><a href="https://greencloudvps.com/">greencloud</a> 没用过,有一年独服很便宜倒是,记得一年才 22 刀。好像日本和 virmach 是一个机房,和 virmach 一起宕机。</li>
</ol>
<h2>AI 服务</h2>
<ol>
<li><a href="http://colab.google">Colab</a> github 很多项目在这白嫖 demo,跑跑小项目用可以,实例不保存环境,大模型启动很慢。可以充钱,充钱后可能抽到 A100(我抽到过 233)</li>
<li><a href="https://www.autodl.com/">autodl</a> 收费但便宜,分钟级动态租用,环境给得非常方便,接入国内网盘符合国内环境,有时候要抢实例。</li>
<li><a href="https://huggingface.co/">huggingface</a> 有免费的 cpu space,充钱用 gpu。</li>
<li><a href="https://www.kaggle.com/">Kaggle</a> 有一点免费的 gpu 时间,体验用。</li>
</ol>
<h2>参考</h2>
<ol>
<li><a href="https://gist.github.com/imba-tjd/d73258f0817255dbe77d64d40d985e76">☁️ 一些免费的云资源</a></li>
<li><a href="https://blog.lv5.moe/p/website-hosting-and-function-computing-service-selection">Cloudflare or Vercel——网站托管与函数计算服务选择</a></li>
<li><a href="https://github.com/tzhangchi/awesome-free-saas">tzhangchi/awesome-free-saas: an awesome list of free SaaS (software as a service) for you.</a></li>
<li><a href="https://ldo.one/post/backblaze-yes/">愉快的白嫖 Backblaze 的 10G 对象存储 - Hub | ldo.one</a></li>
</ol>
<hr/>
<p>发现我的语言完全丧失了中文原有的简洁性,Sad。</p>]]></content:encoded>
<category domain="https://sansui233.com/categories/乱七八糟的分享">乱七八糟的分享</category>
</item>
<item>
<title><![CDATA[Windows 命令行相关配置]]></title>
<link>https://sansui233.com/posts/2023-11-29-windows-shell-configuration</link>
<guid>https://sansui233.com/posts/2023-11-29-windows-shell-configuration</guid>
<pubDate>Wed, 29 Nov 2023 04:07:00 GMT</pubDate>
<content:encoded><![CDATA[<h2>常用 shell</h2>
<p>一直以来 windows 的命令行方案都很多,个人感觉都有不太好用的点,怎么配置也是仁者见仁智者见智的一个事情。先总结一下常用shell 方案</p>
<ul>
<li><code>powershell</code> 官方shell,各种工具库支持最全,缺点自带的命令太长,以至于完全没有日常使用的想法。</li>
<li><code>msys2</code> windows 上的类 unix 环境,基于现代 Cygwin (POSIX兼容层) 和 MinGW-w64(工具包)。确实像 unix,一般命令可以无缝迁移。缺点是兼容性,需要手动配置很多东西,比如是否继承 windows 环境变量,不继承的话不想维护两份环境,继承了又容易冲突。</li>
<li><code>git bash</code> msys2 阉割版,无包管理,多了 git。</li>
<li><code>wsl</code> 完全的 Linux 子系统,但太占内存。</li>
</ul>
<h2>方案选择</h2>
<p>我需求</p>
<ul>
<li>常用命令必须是类 unix 命令</li>
<li>有包管理器,各类命令行工具配置友好且兼容性不错。</li>
<li>不要太占内存</li>
</ul>
<p>结果发现这就是经典的三圈相交,没有任何一个常用方案能满足以上要求。</p>
<p>最后,我决定用 powershell。除了第一条外都满足。后面两条属于难以解决的硬伤,而第一条可以编写脚本,将常用的命令模拟。</p>
<h3>powershell 配置流程</h3>
<p>包含工具包、终端美化。</p>
<ol>
<li>Install the latest Powershell Core</li>
<li>Install <a href="https://gitforwindows.org/">git-bash</a> for basic bash and git tools</li>
<li>Install <a href="https://apps.microsoft.com/store/detail/windows-terminal/9N0DX20HK701?hl=zh-cn&gl=cn&rtc=1">Windows Terminal</a> and open Powershell</li>
<li>Install <a href="https://github.com/PowerShell/PSReadLine">PSReadLine</a></li>
<li>Install <a href="https://github.com/dahlbyk/posh-git">posh-git</a></li>
<li>Install <a href="https://ohmyposh.dev/">oh-my-posh</a> for showing extra info in term.</li>
<li>Install <a href="https://github.com/gerardog/gsudo">gsudo</a> for softlink</li>
<li>open <code>$PROFILE</code> in powershell, append the contents of <a href="https://gist.github.com/Sansui233/0451b8f7c354d600c4efa74fc284d39c#file-microsoft-powershell_profile-ps1"><strong>Microsoft.PowerShell_profile.ps1</strong></a></li>
</ol>
<p>大致介绍一下用途。</p>
<ul>
<li>git-bash,一系列类 unix 工具,git 一类的</li>
<li>Windows Terminal,微软的终端。我拒绝终端用 electron 去套的……</li>
<li>PSReadLine,改变一系列 powershell 的行为。比如复制粘贴的快捷键。可惜在 vscode 里会没用,只能右键粘贴。</li>
<li>posh-git,显示 git 的状态</li>
<li>oh-my-posh,美化。具体主题可能需要会自己改一下,要么丑,要么不支持提示 conda 环境或者 npm 环境。</li>
<li>gsudo,提权,类似 unix 的 sudo。可能运行时会被杀软报毒,需要加入信任区。</li>
</ul>
<p>powershell 的用户配置文件输入 <code>$PROFILE</code> 就能找到。</p>
<p>我的配置文件上传到了 <a href="https://gist.github.com/Sansui233/0451b8f7c354d600c4efa74fc284d39c#file-microsoft-powershell_profile-ps1"><strong>Microsoft.PowerShell_profile.ps1</strong></a>。需要挂代理打开。配置文件包含 <code>ls</code> <code>ln</code> <code>open</code> <code>grep</code> <code>which</code> 等命令模拟。powershell 的缩写默认支持了 <code>mv</code> <code>cat</code> <code>rm</code> 等命令,配合起来日常基本够用。</p>
<h2>终端代理</h2>
<p>我在配置文件中设置了<code>proxy</code>和<code>unproxy</code>函数,以快速设置与取消终端的代理连接。自己改下端口就能用。因为我自己习惯上不开系统代理,都是软件内的 http 连接。</p>
<pre><code class="hljs language-powershell"># Proxy Togglers
function proxy {
$portInUse = netstat -ano | findstr "LISTENING" | findstr "7890"
$portInUse2 = netstat -ano | findstr "LISTENING" | findstr "10808"
if ($portInUse -ne $null) {
$env:HTTP_PROXY = "socks5://127.0.0.1:7890"
$env:HTTPS_PROXY = "socks5://127.0.0.1:7890"
Write-Host "Proxy set to socks port 7890"
} elseif ($portInUse2 -ne $null) {
$env:HTTP_PROXY = "socks5://127.0.0.1:10808"
$env:HTTPS_PROXY = "socks5://127.0.0.1:10808"
Write-Host "Proxy set to socks port 10808"
} else {
$env:HTTP_PROXY = "socks5://127.0.0.1:1080"
$env:HTTPS_PROXY = "socks5://127.0.0.1:1080"
Write-Host "Proxy set to socks port "
}
}
function unproxy {
$env:HTTP_PROXY = ""
$env:HTTPS_PROXY = ""
}
</code></pre>
<h2>其他常用工具</h2>
<ul>
<li>
<p>winget:自带的包管理器,命令行工具都是这个装的。部分用的 scoop,非常少。还有的直接用的官网 setup。</p>
</li>
<li>
<p>nvim:命令行编辑器,vim 的替代品。我用的是发行版 AstroNvim。之前也有自己折腾插件,太懒得维护了,算了。</p>
</li>
<li>
<p>nodejs:JS 环境,nvim 的插件要用,开发也要用</p>
</li>
<li>
<p>zoxide:快速跳转目录。最有用的功能没有之一。类似 unix 的 autojump</p>
</li>
<li>
<p>Terminal-Icons:ls 命令加 icon,还能解决 ls 不高亮的问题。但是,颜色很丑。但是,我不也想再配置了,配置真的心好累。</p>
</li>
<li>
<p>ripgrep:类似 grep 的用法。我在模拟 grep 命令时只是单纯替换成了 findstr,真的 grep 建议用 ripgrep (rg) 替代。nvim 的 telescope 一些插件也会用到。</p>
</li>
</ul>
<p>安装脚本汇总:</p>
<pre><code class="hljs language-powershell">winget install conda
winget install neovim
git clone --depth 1 https://github.com/AstroNvim/AstroNvim ~/.config/nvim
winget install gerardog.gsudo
winget install OpenJS.NodeJSLTS
Install-Module -Name Terminal-Icons -Repository PSGallery; Import-Module -Name Terminal-Icons
# z-jump
winget install zoxide # z-jump, see https://github.com/ajeetdsouza/zoxide
winget install BurntSushi.ripgrep.MSVC # grep 的完全替代品
</code></pre>
<h2>ZSH</h2>
<p>有关 zsh 相关的配置,我放在了 <a href="https://sansui233.github.io/posts/windows-zsh-conf">Windows 命令行相关配置之 msys2+zsh+zi</a> 。</p>]]></content:encoded>
<category domain="https://sansui233.com/categories/工具">工具</category>
</item>
<item>
<title><![CDATA[大概是关于五笔打字更慢的一点碎碎念?]]></title>
<link>https://sansui233.com/posts/thoughts-about-wubi-im</link>
<guid>https://sansui233.com/posts/thoughts-about-wubi-im</guid>
<pubDate>Fri, 17 Nov 2023 01:59:00 GMT</pubDate>
<content:encoded><![CDATA[<p>每次看到打字的视频,总是会有人说五笔是最快的。五笔我打了八年。突发奇想去测试了一下五笔打字的输入速度,结果在我意料之内——在不刻意飙手速(以不被室友打)的情况下,大概是 60 字/min,全拼大概是 70 字/min。</p>
<p>虽然拼音我现在已经非常不熟练了,但速度还是比五笔快。而五笔在日常使用也并没有感觉到有什么不顺畅的地方,为什么测速还是会更慢呢?</p>
<h2>五笔更慢的原因</h2>
<p>网上说五笔打得更快大多是指「看打下的极限速度」。这里有两个条件,一个是看打,一个是极限。</p>
<h3>看打和听打</h3>
<p>看打,指看着一段文字打出来,在早期没有各种扫描技术时,录文件就是这样的纯手工录入方式。</p>
<p>看打有利于五笔的拆字输入,而且不论一个人的普通话是否标准,只要认字都能使用。早期学者非常多会看字但念不准的。</p>
<p>早期输入法(智能 ABC)没有云计算,也没有词库,几乎一个字一个字蹦出来,非常非常慢。我小学拼音打冰灯用尽全力的记录也就 55 字/min,不算快的但也不算慢了。但现在五笔随意打初见就 70 字/min,途中还有好几个字不会拆的。想想在当时的那个环境,只靠打单字和少量词组,就能达到百字每分,是多么牛逼的一件事。</p>
<p>但在日常打字的时候,大部分人纯聊天,更多是使用的听打,想到什么说什么,就算口中没有真的发出声音。这明显是利于拼音打字的。另外,拼音打字的韵母键位非常固定,像 ing 这样的三字母韵母,打起来非常连贯,在这瞬间可以一秒按 8 个键,任何人打字多一点都能做到。真正意义上想说什么打什么。</p>
<p>我的名字拼音一共有 (10-15) 个字母,可以在 1.5 秒内打完全拼。拼音的输入速度完全不慢,重码问题也几乎靠技术解决了。在纠错、词库、上下文联想早就发展起来的情况下,五笔在日常使用上真的没有什么优势。</p>
<h3>极限速度?</h3>
<p>这就是一个老生常谈的问题了———学习成本。</p>
<p>如果仅仅靠日常打字,五笔要多久,拆字的顺畅程度可以达到打拼音一年的水平?</p>
<p>我的答案是:除非刻意练习,否则永远达不到。拆字顺畅,不会卡住自己的表达,是一个需要长期刻意练习的技能。</p>
<p>听起来可能有点夸张,但事实如此。</p>
<p>我在日常使用时,对于常用字,五笔输入也已经是条件反射,不太去想字形,和拼音差距也不大。但是测速文章就是另一回事了。各种领域的名词、人名等,总有你不适应的那一款(五笔大佬请无视)。不会拆时那个感觉真的难受,一分钟打一个字。</p>
<p>比如「凿个洞」「凹凸不平」「藏族」一类的词,对于拼音都非常简单且没有重码。但对于五笔,不是常用词且难拆,测速文里这类词很多。我有一个长长的清单,随时记录这类难以练到的字。</p>
<p>注意,以上的前提是「日常打字」。这里可能会有人对「日常」有一点误解,需要再澄清一下,日常不等于简单,而是「日常生活交流中的常用语言」。比如「藏族」,小学生都会念,还会写,但不日常。</p>
<p>五笔变小众的原因正在于高昂的学习成本,有没有不那么痛的学习方法吗?</p>
<p>有。我自己一向不是死记硬背型的人,基本是用什么学什么直接开干。日语没背五十音图,靠记了一首歌词入门,五笔也没有背码表,看了原理后,一个区一个区地打一级简码二级简码入门。遇到不会的就查,会的就越来越多。</p>
<p>但是不那么痛的学习方法问题就是上面所说的,仅靠日常打字,想在遇到任何情况下都拆字顺畅,永远也不可能(记忆超群的五笔大佬当我没说)。</p>
<p>那个「不熟悉的列表」,我专门打了也有七八遍了,里面的所有字能顺利拆出来了,但每个字还是要花时间反应。</p>
<p>同学妈妈打了几十年五笔工作,也只是在她的专业领域得心应手,换到不熟悉的领域同样卡壳。不要看贴子说打得越久越熟悉,这个年头没有几个人是为了打字而打字的,打字说是表达,是个有应用场景的事,有场景就有范围限定,有范围限定就有上限。你平时能练到的字,就这么多。</p>
<p>诚然,五笔的极限是很快,但为此需要付出的刻意练习,并不值得,除非你喜欢。</p>
<h3>软件问题</h3>
<p>86 版编码是经典的五笔编码,但我现在使用的 98 版五笔,因为有一天实在不能忍受 86 版那个莫名其妙的笔顺了,还有一些为了降低重码而设置的不合理末笔码。</p>
<p>但是后来我发现,有很长一段时间,我都在把 98 版的字根表和 86 版弄混——我在学 86 版五笔时从来没有去背过字根表,都是靠肌肉记忆,肌肉和脑袋打架,于是混乱了。</p>
<p>另外,对于不会拆的字,想不起来的字,我会使用拼音反查。自从 ios 有 98 五笔后我就在使用苹果的输入法,因为可以接第三方键盘,还可以输入 emoji。但我反查了很长一段时间后才发现,苹果的编码,可以说是有巨量的错误,把 86 和 98 版混到了一起,一字完全不同的两码什么的,有时候打 86 版的拆法也能出字,反查编码的时候更是灾难。我对 98 版的拆字方式长期处于一种混乱状态。</p>
<p>所以在初期</p>
<h2>输入法推荐</h2>
<p>需求</p>
<ol>
<li>基本词库+方便的自造词功能</li>
<li>精确的拼音反查</li>
<li>打重复字和 z 键特殊符号</li>
<li>良好的中英混输</li>
<li>可以方便地输入日期</li>
</ol>
<p>我觉得还不错的:</p>
<ul>
<li>windows 冰凌五笔,默认设置基本不用改,除了空码需要上屏编码用来中英混输。还有 shift + 空格的快捷键最好是关掉。加自造词非常方便</li>
<li>mac 上清歌五笔,中英之间支持加空格,加自造词非常方便</li>
<li>rime 98五笔,自己再魔改版。我觉得可以满足大部分需要,除了特殊符号不是 z 键没有提示。这个输入法现在是备用来查拆字的,是的,直接是显示的字根而不是编码。</li>
</ul>
<h2>为什么我还要用五笔</h2>
<p>话说回来,既然五笔打得没有拼音快,还费脑子,为什么我还要用五笔呢?</p>
<p>一是,当习惯了不重码后,很难再接受重码的输入法。不论是不是日常用语,99% 的情况下五笔都不需要选字,不需要翻列表。你可以轻易打出「艹」和「卄」,同时也不会影响你正常打「草」。</p>
<p>当然,拆不出字时也会很难受。</p>
<p>二是,永远不需要联网,隐私问题。</p>
<p>三是,好的输入法设计真的好。当时知道 z 键万能键打特殊符号原来这么好用时简直惊呆了。自从用了五笔,我从来都没有使用 -> 打箭头过,从来都是 →。希腊字母、带圈数字、拼音音标也非常好打。当朋友提醒我写的 logseq theme 没有连字箭头时,我才发现压根没有注意到原来 logseq 后来加入了连字字体。</p>
<hr/>
<p>好困😴 睡觉</p>]]></content:encoded>
<category domain="https://sansui233.com/categories/Diary">Diary</category>
</item>
<item>
<title><![CDATA[关于 typescript 泛型中返回值类型约束的问题]]></title>
<link>https://sansui233.com/posts/2023-11-11-typescript-generatic-type-proble-ts2322</link>
<guid>https://sansui233.com/posts/2023-11-11-typescript-generatic-type-proble-ts2322</guid>
<pubDate>Sat, 11 Nov 2023 22:26:00 GMT</pubDate>
<content:encoded><![CDATA[<p>最近遇到这么一个需求。</p>
<blockquote>
<p>定义一个函数接口,要求其返回值类型是 type A 的任意超集。</p>
</blockquote>
<p>于是我按直觉写下了:</p>
<pre><code class="hljs language-typescript"><span class="hljs-keyword">type</span> A = { <span class="hljs-attr">a</span>: <span class="hljs-built_in">string</span> }
<span class="hljs-keyword">type</span> <span class="hljs-title class_">FuncA</span> = <T <span class="hljs-keyword">extends</span> A><span class="hljs-function">() =></span> T
<span class="hljs-keyword">const</span> <span class="hljs-attr">f</span>: <span class="hljs-title class_">FuncA</span> = <span class="hljs-function">() =></span> {
<span class="hljs-keyword">return</span> { <span class="hljs-attr">a</span>: <span class="hljs-string">"ok"</span> }
}
</code></pre>
<p>人来看非常简单知道是什么意思,就是返回值包含所有 a 的属性,其他属性全是可有可无的。</p>
<p>这段代码扔给 GPT,它也看不出什么毛病。但事实上,在 return 时报了一个错:</p>
<pre><code class="hljs language-text">Type '() => A' is not assignable to type 'FuncA'.
Type 'A' is not assignable to type 'T'.
'A' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'A'.ts(2322)
</code></pre>
<p>这个报错非常的不 helpful。因为平时, typescript 可以根据返回值推测出具体函数标注。比如</p>
<pre><code class="hljs language-ts"><span class="hljs-keyword">function</span> <span class="hljs-title function_">foo</span>(<span class="hljs-params"></span>){
<span class="hljs-keyword">return</span> <span class="hljs-string">"1"</span>
} <span class="hljs-comment">// 自动推断出函数的具体签名为 () => string</span>
</code></pre>
<p>那为什么上面的报错例子,不能做这样的推断呢?</p>
<pre><code class="hljs language-ts"><span class="hljs-keyword">type</span> A = { <span class="hljs-attr">a</span>: <span class="hljs-built_in">string</span> }
<span class="hljs-keyword">type</span> <span class="hljs-title class_">FuncA</span> = <T <span class="hljs-keyword">extends</span> A><span class="hljs-function">() =></span> T
<span class="hljs-keyword">const</span> <span class="hljs-attr">f</span>: <span class="hljs-title class_">FuncA</span> = <span class="hljs-function">() =></span> {
<span class="hljs-keyword">return</span> { <span class="hljs-attr">a</span>: <span class="hljs-string">"ok"</span> }
}
<span class="hljs-comment">/* 推断出具体的签名类似于
() => {
a: string;
[name: string]: any
}
*/</span>
</code></pre>
<p>也就是说,a 是必选属性,其他属性全是 optional。</p>
<p>(先不讨论 Object 的 key 可以是 Symbol,只是为了看起来好理解,我只写了 string。要写全这里又要多写一个类型推断。)</p>
<p>当然这里又引发了另一个问题:你为什么不直接把 type A 定义附加任意可选属性?</p>
<p>好问题,这是一个正常的解决 TS2322 问题的思路。但是我就是想知道为什么泛型推断不能直接做这个……</p>
<p>我查了很多资料,没有人完美解释这个问题。但有一个相似的问题:如何让参数和返回值持有相同的泛型类型?</p>
<p>在 typescript 的 <a href="https://github.com/microsoft/TypeScript/issues/50027">github issue</a> 里有详细的案例说明,务必看看,很好懂,说是故意这么设计的。这里我将理由简短概括如下:</p>
<blockquote>
<p>如果 f 是上有一个额外的属性 prop,编译器如果推导出了返回值类型成 typeof f。之后你调用 f.prop,静态编译不会报错,但实际上有一个 runtime error,因为你的真实的返回值只是一个 <code>()=>{}</code> ,没有prop 属性。</p>
</blockquote>
<p>但个人觉得这里静态编译应该报错,并不是一个 runtime 错误。前面说了,typescript 可以对返回值进行静态的类型的检查。以上面 issue 为例,理想的报错设计是长这样:</p>
<pre><code class="hljs language-ts"><span class="hljs-keyword">type</span> A = <span class="hljs-function">() =></span> <span class="hljs-built_in">void</span>;
<span class="hljs-keyword">type</span> B = <span class="hljs-function">() =></span> <span class="hljs-built_in">void</span>;
<span class="hljs-comment">// 类型签名为 <T extends A | B>(value: T) => T 的实现</span>
<span class="hljs-keyword">function</span> f1<T <span class="hljs-keyword">extends</span> A | B>(<span class="hljs-attr">value</span>: T): T {
<span class="hljs-keyword">return</span> <span class="hljs-function">() =></span> {}; <span class="hljs-comment">// 推断出 T 此时是 typeof ()=>{},也就是 ()=>{}</span>
}
<span class="hljs-keyword">let</span> <span class="hljs-attr">f</span>: <span class="hljs-built_in">any</span>= <span class="hljs-function">()=></span>{}
f.<span class="hljs-property">prop</span> = <span class="hljs-string">"haha"</span>
<span class="hljs-title function_">f1</span>(f) <span class="hljs-comment">// 这里传参报错,因为 typeof f 和 typeof ()=>{} 不一致。本质上就是 ts2322 描述的问题,但不应该在上面报错</span>
</code></pre>
<p>当然上面的例子返回值类型已经定了是 <code>typeof ()=>{}</code>,返回值再标注 T 显得十分多此一举。但是 f1 对只是对这个函数签名的一种实现。完全可以实现对这个函数签名有不同的实现,返回不同的 subtype。</p>
<blockquote>
<p>什么是 subtype?T extends A,T 就是 A 的 subtype</p>
</blockquote>
<p>这又引发了另一个问题:这和函数重载有什么区别?</p>
<p>当然有区别啊,最大的区别就是我能定义一个统一的函数接口,只要返回值满足最基本的约束 <code>A</code>。但可以是返回不同的 subtype,实现也分开写到不同的文件里,类似于 oop 语言中返回所有某基类的派生类。这才是完全体。</p>
<p>但现在的 typescript 完全做不到这一点,返回值只能是一个非常具体的 type,要么就抛出一个毫无说服力的 ts2322 错误。</p>
<p>如果要解决开头的问题,大概是以下三个思路:</p>
<ul>
<li>定义 A 时,把所有可能要用到的属性都写到可选属性里,或直接 <code>[name: string]: any</code>。</li>
<li>考虑业务场景,其他未知属性不留下会影响到什么吗。99% 的场景是没有必要的,也就是说这个需求就是没意义的。剩下的 1% 我没有遇到/想到。</li>
<li>根据输入参数的 T 写一个类型推导,手动将返回的类型设置为 a 的具体扩展类型。类似这样</li>
</ul>
<pre><code class="hljs language-typescript"><span class="hljs-keyword">type</span> <span class="hljs-title class_">Extend</span><T <span class="hljs-keyword">extends</span> <span class="hljs-built_in">object</span>> = {
[<span class="hljs-attr">name</span>: <span class="hljs-built_in">string</span>]: <span class="hljs-built_in">any</span>
} & {
[K <span class="hljs-keyword">in</span> keyof T]: T[K]
}
<span class="hljs-keyword">type</span> A = {<span class="hljs-attr">a</span>: <span class="hljs-built_in">string</span>}
<span class="hljs-keyword">type</span> <span class="hljs-title class_">FuncA</span> = <span class="hljs-function">() =></span> <span class="hljs-title class_">Extend</span><A>
<span class="hljs-keyword">const</span> <span class="hljs-attr">f</span>: <span class="hljs-title class_">FuncA</span> = <span class="hljs-function">() =></span> {
<span class="hljs-keyword">return</span> { <span class="hljs-attr">a</span>: <span class="hljs-string">"ok"</span>, <span class="hljs-attr">b</span>:<span class="hljs-string">"extra"</span>}
}
<span class="hljs-title function_">f</span>().<span class="hljs-property">a</span> <span class="hljs-comment">// a is string</span>
<span class="hljs-title function_">f</span>().<span class="hljs-property">b</span> <span class="hljs-comment">// b is any</span>
</code></pre>
<p>总之,在目前的 typescript 中,<strong>返回值类型不能是泛型</strong>。</p>
<p>当然这样也失去了扩展的类型检查,等于是用了函数的签名来检查的,和返回值的类型一点关系也没有。</p>
<p>现在 typescript 的静态检查器其实已经做了一些运行时的功能,比如条件语句判断以排除属性。但是,这些像运行时一样的检查只在静态类型不明确时才起作用。就这个 if,我已经遇到了好几次无法判断的 bug ,清空缓存并重启才恢复。</p>
<p>说回第二点,既然你允许传了任意值,也就说明在你这个库中,你也不知道其他附加值具体是拿来干什么的,大多无非遍历一下再过滤一下。如果是静态类型检查器来遍历,诶诶扩展属性怎么全是 any。最终还得用 JS 的运行时来做这个事情……所以有拿来做什么的话早就在 A 里增加 optional 属性了。这也是为什么说 99% 的场景这个需求其实不存在。</p>
<p>还有一个更重要的原因,那就是,ts 的类型体操,实在太他妈难写了。</p>
<hr/>
<p>可能没用的参考:</p>
<ul>
<li><a href="https://stackoverflow.com/questions/56505560/how-to-fix-ts2322-could-be-instantiated-with-a-different-subtype-of-constraint">typescript - How to fix TS2322: "could be instantiated with a different subtype of constraint 'object'"? - Stack Overflow</a></li>
<li><a href="https://github.com/microsoft/TypeScript/issues/50027">Could be instantiated with a different subtype of constraint · Issue #50027 · microsoft/TypeScript</a></li>
</ul>]]></content:encoded>
<category domain="https://sansui233.com/categories/学习">学习</category>
</item>
<item>
<title><![CDATA[重读《小王子》]]></title>
<link>https://sansui233.com/posts/2023-10-09-the-little-prince-review</link>
<guid>https://sansui233.com/posts/2023-10-09-the-little-prince-review</guid>
<pubDate>Mon, 09 Oct 2023 13:56:00 GMT</pubDate>
<content:encoded><![CDATA[<p>《小王子》在不同年龄阶段都看过,中译和原著也都读过,当时只是觉得有趣。但尝试自己写故事后,才惊觉其实所有的有趣都是是作者的刻意表达。</p>
<p>仅仅以生活中的“有趣”与“想象力”写出的故事远远不够,别人看起来并没有你认为的那么有趣,内核是空洞的。</p>
<p>人在成年人后,所经历的一切容易让笔下故事的发展陷入自身所见所闻,很难写出孩子般质朴的想象,无法逃离现实的束缚。</p>
<p>举个例子,如果你的故事需要一个超现实的“天体引力”进行推动,你会用怎样的方式让这样的力产生?</p>
<p>我搜集了很多宇宙的资料,试图从中找到什么想法。但事实上我并不是想写硬科幻,也没人想在简短的剧情中读一大堆物理考据。</p>
<p>我对此一筹莫展,觉得怎样都编不出一个合理的解释……最后决定拉出上帝作为隐喻,上帝按自己心意去裁定天体引力。听起来很离谱吧,就好像是小孩子的瞎想,仅仅是“上帝裁定天体引力”不也是一具无意义空壳吗?但如果将这个设定赋予别的象征,就不再是无意义的。或者说,我其实是想象征什么,才拉出一个离谱的上帝。不过这个处理我也并不满意,但一时想不到更好的方法。</p>
<p>幻想的意义不在于幻想本身,而是幻想对故事带来的推动。感到有趣的事在深入思考后也不仅是罕见、超现实的表象,它会带来的新体验,又或者:“喜剧的内核是悲剧”。</p>
<p>今天复看《小王子》,试图从写故事的角度去理解,作者在下笔时是带着怎样的想法与心情呢?或是单纯是觉得有趣吗?怎么想出这些光怪陆离的可爱小故事?我是一个强逻辑性的Ne人,这样的思考也许能提高一下Ni的水平,带来一些不一样的启发。</p>
<h2>第1章</h2>
<p>介绍“我”与“大人”之间的区别。</p>
<p>“我”在成为大人后 ,依然有着孩子般的心灵。如果不是这样,后文的“我”将是一个很难理解小王子的大人。体现这一点是“蛇吞象”与“帽子”的故事(作者真的很会想)。大人看东西只关注现实,不现实的事情对于大人毫无意义。</p>
<h2>第2-7章</h2>
<p>介绍小王子的由来。</p>
<p>“我”困在沙漠中时遇到来自另一个星球的小王子,一个礼貌的、有点忧伤的小王子。小王子想要我画一只绵羊给他,但挑三拣四,最后对一只藏在箱子里看不见的小绵羊表示满意,还觉得小羊在箱子里睡着了。</p>
<p>为什么想到在这里安排这么一只奇怪的绵羊,如果仅仅想有趣,那安排一只会走钢丝的山羊不行吗?读到最后才隐隐有了答案——美丽的事物往往是不被看见的,这也许是“箱子里的羊”的动机。</p>
<p>第6章的写小王子星球上的猴面包树。从编剧的角度,不描写羊吃什么食物也无伤故事发展,但写了,还写的是特别具体也不常见的猴面包树,大概是有什么想法在里面的。猴面包树是会无限扩张的、不好的东西,但这和小王子的生活有什么关系呢,也就是多了一些并不让人开心的日常打扫。</p>
<p>我不认为这里是象征自私的欲望、野心,小王子的星球上没有出现这类元素的必要性,含义也并不太深刻,在后续别的星球遇到更合理。后来看知乎上感觉有一个(我认为)挺靠谱的说法:</p>
<blockquote>
<p>作者发表时正值二战期间,作者是一名法国人,国土沦丧旅居纽约。旅居纽约的法国人又分成戴高乐派和维希派,他想劝告两派捐弃前嫌共同对敌,却遭到两派的夹攻,非常无奈,这三棵灌木正是代表法西斯的德国、意大利和日本。</p>
</blockquote>
<p>破坏这份宁静的、疯长的、夺取人生存空间的猴面包树。</p>
<p>然后引出了对于小王子最重要的玫瑰花。作者是先想到绵羊再编出的玫瑰花,还是本来就想写玫瑰花与小王子的故事、再编出绵羊?如果以先写大纲让剧情先行的角度,我偏向于后者。无论以何种方式开始,绵羊和玫瑰花的情节是精妙契合的。情节的前后衔接一向不是一个简单的事情,如果先写剧情可能人物 ooc,如果先写人物可能会想不出后续,好多长篇就是这么坑掉的……</p>
<p>这部分里还有一些别的情节,比如说谈到小王子的星球叫做行星 B612 时,讽刺了大人们喜欢以衣冠取人,关注外在与代号,不关注人的本质。</p>
<p>小王子的星球上还有两座活火山一座死火山,非常有趣的脑洞,对剧情发展没什么用但并不觉得无聊,气质很符合小王子的星球(氛围渲染也是有必要的?)。小王子有一天最多看了43次日落,后文对不同星球的日落次数描写对比起来也非常有趣。至此基本表现出了小王子日常生活。</p>
<h2>第8-9章</h2>
<p>玫瑰花与小王子的相处这两章浪漫温柔,明显以人物情感先行,对话自然发生。剧情上没有太多刻意安排。有刻意安排的剧情是小王子最后一时冲动生了玫瑰花的气,离星出走。虽说是生气了,但看起来还是十分的文艺……整个文笔的基调就是这样的,very童话。</p>
<h2>第10-15章</h2>
<p>离星出走章节。不同星球上住着不同的奇怪大人,写得非常直白。后面有许多章节都会显得较为独立且直白,是娓娓道来的日常故事。</p>
<p>第10章:有理性但放不下权威架子的大人。</p>
<p>第11章:爱慕虚荣的大人。</p>
<p>第12章:永远在犯同样错误的酒鬼。非常短,像四格漫画一样,但闭环的对白好有趣。</p>
<p>第13章:除了钱和财产再脑子也容不下别的东西的商人。一些人看到什么东西就觉得是自己的,什么也不做就想据为己有,像是在讽刺资本主义的起源嗯……</p>
<p>第14章:守规矩的、不知变通的打工人。观看一千多次日落这个吐槽也很有趣,像是人物先行写出来的。</p>
<p>第15章:不出门的地理学家。看到好多模板的影子:不深入基层的高高在上的 leader、掉书袋不实践的人、把别人的成果据为己有的人、不切实际的甲方。地理学家知道地球,但连自己的星球上有没有大洋和火山都不知道,却觉得理所当然。</p>
<h2>第16-19章</h2>
<p>小王子来地球的见闻。</p>
<p>第16章介绍地球。</p>
<p>第17章小王子来到地球寻找人类,第一个遇见的毒蛇是为以后小王子回家埋下的伏笔(好残忍)。</p>
<p>第18章向花问路的写作视角很有趣。以花的视角,人没有根,所以被风送走了。</p>
<p>第19章的回声有点类似空镜的作用?我不理解,但隐约觉得好像是有用的,好可爱。</p>
<h2>第20-21章</h2>
<p>算是主线章节(?)很多玫瑰的花圃,小王子最初知道自己的玫瑰在外形上不是独一无二的后,很伤心。但小狐狸的出现又让他明白了</p>
<blockquote>
<p><strong>正是因为小王子在玫瑰身上花费的时间,才使得玫瑰变得如此珍贵。因此单她一朵,就胜过了这世间所有。</strong></p>
</blockquote>
<p>此外小狐狸还教会了他仪式感。</p>
<h2>第22-23章</h2>
<p>永远在向往别处,行色匆匆,忽视脚下风景的人。</p>
<p>永远在节省时间,追求效率的现代人。</p>
<h2>第24-25章</h2>
<p>沙漠里的井水,突出主题的两章,和星星上的玫瑰花一样。这个情节的设置和作者的自身经历有关,对于没有经历过的人而言难以复刻。</p>
<blockquote>
<p>“沙漠美丽,因为沙漠的某处隐藏着一口井。”</p>
</blockquote>
<blockquote>
<p>“房子也好,星星、沙漠也好,美化他们的东西,是肉眼看不见的。”</p>
</blockquote>
<h2>第26-27章</h2>
<p>小王子通过死亡回去了,“我”不舍。这两章人物先行,对白比较重要。</p>
<p>总体感想是,这是一本给成年人读的童话。我清楚记得我小学时看到第一章,只觉得这是一个有点可爱的怪孩子。到高中时,可以感受到文笔有童话的美好,但并不太理解作者要表达什么。大学时看原著也没有懂,纯学英文去了。直到现在才对里面的情节有所体会。小王子的“童真”是人在成长过程中需要慢慢获得的,是成年人的反思,在小时候的记忆中类似的想法我从未存在过。小时候反而会现实得多,真正的小孩子有着更原始更本能的残酷。</p>
<p>语文考试总是在问“作者在这一段想要表达什么”,小时候总觉得有时候是出题想太多。现在觉得,不是的,但也不应该有标准答案。刻意设计的剧作可以解释,很多人带着心情自然而然书写而成的东西,自己也是无法准确剖析的。剖析自己对每个人都是困难的,何况是一纸之隔的他人呢。</p>]]></content:encoded>
<category domain="https://sansui233.com/categories/书和剧">书和剧</category>
</item>
<item>
<title><![CDATA[Minecraft v1.20.1 常用设置]]></title>
<link>https://sansui233.com/posts/2023-09-26-minecraft-settings-for-v1-20</link>
<guid>https://sansui233.com/posts/2023-09-26-minecraft-settings-for-v1-20</guid>
<pubDate>Tue, 26 Sep 2023 02:38:00 GMT</pubDate>
<content:encoded><![CDATA[<p>在 Minecraft 1.20 版本光照引擎被大幅改写,使得帧数提升,模组的数量似乎又多了起来。另外在 fabric 发展起来以后,mod的社区生态有了很大的变化,有很多老牌模组有了更新的替代。现在记录一下实现常用的基本功能需要的模组与修改设置。</p>
<p>我使用的 hmcl 启动器,在其中进行模组下载可显示模组间的依赖情况。以下内容在 1.20.1 中完全兼容,且项目均在维护中。</p>
<h2>1. Mods</h2>
<p>MC 是一款肝度明显过高的游戏。mod 的选用主要是为了:</p>
<ol>
<li>使画面养眼</li>
<li>降低肝度,同时少引入额外的快捷键</li>
<li>优化细节使用体验</li>
</ol>
<p>使用以 fabric-api 构建的模组。</p>
<h3>1.1 渲染类</h3>
<ul>
<li>Sodium: 渲染优化之神,许多模组的前置</li>
<li>Sodium-extra: 渲染优化之神的扩展,相应 GUI 为reeses sodium options</li>
<li>Lithium: 原版机制的算法改进</li>
<li>Iris: Sodium 加光影</li>
<li>Custom Entity Models: 自定义实体模型,增强对 optifine 材质包的支持</li>
<li>Continuity: 无缝纹理,安装后需要启用相应的材质包</li>
<li>Indium: 许多模组的前置,提供 Fabric Rendering API的支持</li>
</ul>
<h3>1.2 功能类</h3>
<ul>
<li>modmenu: 显示所有模组和相应的设置页面(如果有的话)</li>
<li>carpet: 单人生存必备,可使用命令放置假人以常加载区块刷红石</li>
<li>tweakeroo: 一系列微调的小功能。主要使用 freecamera(灵魂出窍)以获得更好的摄影视角,zoom 开启类似 optifine 的按 c 视角放大,handrestock 可自动补货手里的工具、方块</li>
<li>JourneyMap: 小地图,降肝度必备。Xae 的小地图也不错,两者都需要设置一下显示的东西,默认会非常多,我只开启了玩家、时间、坐标。关闭了网格显示和生物显示。</li>
<li>Invertory Profile Next: 高版本的 R 键背包整理(但被我改成 Z 键整理,R 键通常是 rei 查看合成表)。自动补充工具、连续合成、捡物品时默认扔到背包中,以及在打开箱子时使用滚轮移动物品。关掉快破损时替换工具。</li>
<li>Carry on:手里没有东西时,<code>shift+右键</code> 搬运箱子,降低装饰的肝度。</li>
<li>Roughly Enough Items: 物品搜索,查看合成配方、查看方块用途,ctrl点击后快速移动到合成台。尽管原版有合成书,但一页条目显示太少,且不支持拼音搜索,不支持模组物品。REI依旧方便很多。</li>
<li>imblock: 输入法冲突修复</li>
<li>Panda's falling tree:砍树时树会倒下,降低砍树的肝度。</li>
<li>Leawind's Third Person: 更好的第三视角。这算是第一个可以日常使用的第三视角模组,挖方块瞄准都很方便。日常的垂直平滑 0.5 以上,不然爬山能晕死。</li>
<li>better combat: 动作战斗优化,攻速和攻击范围都有反馈了。</li>
<li>Litematica:投影。辅助红石机械建造,也算是一种降生存建筑的肝度。使用相当简单,一根木棍,control+滚动切换模式,快捷键进菜单。最难的其实是收集足够多的预置模型。</li>
</ul>
<h3>1.3 新物品</h3>
<ul>
<li>Gliders:类似塞尔达的滑翔伞,防摔。在空中按空格展开滑翔。使用方式和大部分游戏一致。只是要占一个盔甲位。动画做得很不错。</li>
<li>Waystones:传送石碑,后期物品,降低交通的肝度。如果用地图作弊路径点传送就不需要这个东西了,但理想的玩法还是地图只是用来看的,让传送石碑在地图上显示(需要前期多刷小黑),只能传送石碑处,禁止任意传送。传送石不是个好设计,MC背包不能放下更多东西了。除非有单纯扩容用的背包模组。</li>
<li>travelersbackpack:背包模组,终于有了 fabric 版。虽然 mojang 一直很谨慎地加入新的方块,但似乎从未考虑过方块越来越多时的背包使用问题。再者模组整合包也因为方块种类数爆炸的问题增加背包模组。在 1.12 版本时,背包容量是刚好够的。个人并不是很喜欢背包的设计。</li>
</ul>
<h2>2. 设置</h2>
<ul>
<li>画面尺寸: 1920*1080@60fps,窗口化</li>
<li>视场角: 85</li>
<li>鼠标灵敏度: 75</li>
<li>模拟距离:8</li>
<li>渲染距离:12</li>
</ul>
<h3>2.1 快捷键修改</h3>
<p>总体的键位映射图如下。深绿色为原版的功能。橘色为Mod功能,蓝色为创造模式功能。键位分为直接按键、组合键、修饰键(长按)。MC 原版只能定义直接按键,组合键与修饰键在复杂的 mod 中用得多,并且会覆盖原版的直接按键。</p>
<p><img src="https://img-cf.sansui233.com/imgs/2024/08/202408220938708.webp" alt="KeyMaps"/></p>
<h4>游戏主界面</h4>
<p>首先把 ctrl 改到 capslock 键位,方便疾跑。系统全局 powertoys 改的(吐槽一万句control的键位)</p>
<ul>
<li>长按 <code>tab</code>,滚轮切换物品栏。在tweakroo 的「工具」中开启 hotbarscroll,再在 tweakroo 的「快捷键」中把 hotbarscroll 的快捷键设置为 Tab。</li>
<li><code>v</code>: 切换第三人称视角(visual),很常用的功能。原本是f5,实在太远了</li>
<li><code>f4</code>: Leawind's Third Person 第三人称视角相机调位置。同时关掉左右切换。点按左右,长按居中</li>
<li><code>f5</code>: 灵魂出窍,在 tweakroo 的 freecamera 中设定</li>
<li><code>c</code>: 望远镜,在 tweakroo 的 zoomactivate 中设定</li>
<li><code>t</code>: 路标点传送管理(transport)。聊天改 <code>enter</code> 键</li>
<li><code>x</code>: 锦致装饰-箭袋</li>
<li><code>m</code>: 显示 jouneymap 大地图和设定。Journey map 的其他快捷键全关掉。</li>
<li><code>n</code> Litematica 投影菜单</li>
<li><code>shift+右键</code> 空手时搬运箱子,carry on 自带。</li>
</ul>
<p>特定工具下的修饰键:</p>
<ul>
<li>木棍工具
<ul>
<li><code>~</code> Litematica 木棍工具修饰键,改变区域大小</li>
<li><code>n+space</code> Litematica 木棍工具模式5下放置投影</li>
</ul>
</li>
</ul>
<p>预留键位:</p>
<ul>
<li><code>g</code> 圆盘菜单</li>
<li><code>~</code> 特定工具修饰键,比如连锁挖矿</li>
<li><code>b</code> 背包(backpack)</li>
<li><code>j</code> FTB任务书(journal)</li>
<li><code>左alt</code> 创造模式下,建筑模组 axiom 用 alt 切换专用物品栏。</li>
</ul>
<h4>合成台、箱子UI</h4>
<ul>
<li>r: REI 查看光标下物品的合成方式</li>
<li>u: REI 查看光标下物品的用途</li>
<li>ctrl + 左键点击REI的物品,移动物品到合成台</li>
<li>z: 一键整理。在 IPN 的设置中修改。</li>
<li>使用滚轮以在背包和箱子间移动物品,按shift移动整组</li>
</ul>
<h2>3. 光影</h2>
<ul>
<li>BSL v8.2.04,默认配置High,把 Camera 中的 Bloom 关闭,把 Atmosphere 中的 fog 调到 0,开启 lighting 中的handDynamicLight。抗锯齿的TAA随便开不开,取决于风扇响不响</li>
<li>Complementary Reimagined,配置 medium,high 会开启材质的反射运算量明显变大。夜晚也比较亮,适合生存。</li>
<li>itt 3.0,更适合搭配了写实系材质的建筑,风格最写实的 shader 没有之一。不适合生存。</li>
</ul>
<h2>4. 材质</h2>
<ul>
<li>任意矿物发光材质。比如 <a href="https://www.curseforge.com/minecraft/texture-packs/new-glowing-ores">New Glowing Ores</a>。主要是因为 BSL 光影没有矿物发光,所以要加一个材质以确保有 fallback。</li>
<li><a href="https://afdian.net/a/Nan2uu">彩虹像素</a>,非常优秀的免费猛男材质包,原版风但更精致。有很多更可爱的附加包。</li>
</ul>
<h2>5. 创造模式附加</h2>
<h3>5.1 Mod</h3>
<p>Axiom 高版本环境必备,可以创建实体方块随意拉伸模型,相当好用。</p>
<p>effortLess structure 快速建造几何体。原 effortless buidling。</p>
<p>lotweaks 自定义材质轮盘</p>
<p>wordedit 经典创世神</p>
<h3>快捷键</h3>
<p><code>z</code>: effortLess structure 轮盘。</p>
<p><code>x</code>: lotweaks 轮盘,和手中方块有关。会禁用丢东西(但创造模式本来就不用丢东西除了篝火灭火,何不用 Axiom 的调试棒?)</p>
<p><code>左 alt</code>: Axiom 的大菜单</p>
<p><code>r</code>: Axiom replace,其他的模组类似功能关掉。实测下来 replace 相当常用。</p>]]></content:encoded>
<category domain="https://sansui233.com/categories/游戏">游戏</category>
</item>
</channel>
</rss>