Chen Yulin's BlogChen Yulin's Blog
HomeArchivesCategoriesTagsAbout
Game Principle of <JustWork>
Posted 2024-05-12Updated 2025-08-15Note2 minutes read (About 363 words)

Game Principle of <JustWork>

参考

Besiege

核心功能

机械建造

需要更高的建造自由度:例如刚体零件的顶点自定义,3轴移动,3轴旋转,3轴缩放。
可视化内容更丰富:例如碰撞箱,连接点。

物理优化

目前还是使用phsX引擎,考虑一下GPU加速这块功能。
零件之间的连接考虑使用joint以外的方式,特别是某些刚性连接。

逻辑电路体系

参考我写的BesiegeModern Mod

零件材质自定义

{金属,木,玻璃}
需要自己写shader material实现该功能。

次要功能

更好的机械破坏系统

譬如撞击变形,高速击穿之类的
很难
在已有父刚体在运行中,更改碰撞箱布置是非常耗费性能的。

场景建造

自定义场景元素

教程系统

参考mc机械动力模组的“思索”
animation制作

故事模式

起部分教程作用,添加沉浸感,吸引一些非硬核玩家

三渲二

难,可能对电脑性能有较高要求。

目前需要的技术栈

unity shader
unity animation
美术相关工具
物理引擎Game Physics Engine Development
unity URP

Posted 2024-05-12Updated 2025-08-15Note4 minutes read (About 561 words)

如果哪天有幸接触乐器的话,一定要弹弹下面的曲子呀

Goal

  • 人生的旋转木马(本命)
  • 残酷天使的行动纲领
  • 使一颗心免于哀伤(请使我不再哀伤)
  • 生命的名字
  • 梦中飞行(好不容易有了爱的人,却面临失去的恐惧)
  • 人生的约束
  • Take Me Home Country Roads (From <The Best of John Denver>)
  • 跨越时空的思念(泛音好仙)
  • Five Hundred Miles
  • 春日影
  • God knows
  • Call of Silence
  • 黄金之风处刑曲
  • I really want to stay at your house
  • Fly Me to The Moon
  • One Last Kiss
  • November Rain
  • 孤独与吉他与蓝色星球

Ukulele

考虑到便携易学,放寝室里也不会占太多空间,入了尤克里里(虽然貌似ysn前不久还在wb吐槽过)。300块在闲鱼收了一架单板相思木的尤克里里。
下面就暂且记录一下尤克里里的学习过程吧。

基础

教程:https://www.bilibili.com/video/BV1st411q7yc/?spm_id_from=333.337.search-card.all.click&vd_source=45fc7197aaca220eec8fef4c2711efe3
进度:
7/18:p5

曲

使一颗心免于悲伤

https://www.bilibili.com/video/BV1d2421T7xJ/?spm_id_from=333.337.search-card.all.click&vd_source=45fc7197aaca220eec8fef4c2711efe3
进度:
7/19:11小节,前奏的速度终于可以跟上了。好好听。
7/20:17小节,后面的指弹琶音好难,横按也按不到位。
7/27:27小节,横按还是效果不好,但至少能出音了,就是不是很稳定。录了个小视频。
9/20:卡在38小节扫弦,节奏掌握不好

穿越时空的思念

泛音扫弦到底是怎么做到的。。

人生的旋转木马

easy啦

电吉他

海鲜市场在众多鲁琴中找到一把GRG220PA1 classic拾音器的电吉他,遂购入。音箱用marshell的ms2迷你音箱,方便寝室里使用,暂且不连效果器。

看到学吉他分为这么些个级别:

  • 皮毛
  • 入门
  • 吉他运动员
  • 高级吉他运动员
  • 吉他手
  • 吉他大师
  • 吉他英雄(?

我要做吉他🦸!

曲

春日影

https://www.bilibili.com/video/BV1gu41137cg/?spm_id_from=333.337.search-card.all.click&vd_source=45fc7197aaca220eec8fef4c2711efe3

God Knows

《地下室手记》读书会p4
Posted 2024-05-11Updated 2025-08-15读读噜3 minutes read (About 465 words)

《地下室手记》读书会p4

我看这本书是抱着,我希望陀子能够帮我剖析我自己,希望他能够指出我内心不曾察觉的阴暗角落。
但说实话感觉有些失望以及作呕,大概是唯一一本“想赶着马上读完以脱离阅读带来的折磨”的书。

本书开篇即表明主人公自己是有病的,是心怀歹毒。但是他所作的剖析更多时候让我感觉像是纯粹为了贬损,好似只有贬损才是唯一客观的剖析。当自夸一些优异特质时,貌似是永远无法抵达自我本质的。
当我在谈论我自己做模组时,其实我是想在“背离世俗的评价标准的倾向(说白了就是反卷)”和“展现自己的专业能力(说白了就是装逼,自我价值的实现)”两者之间找到的平衡。我承认无偿制作分享模组是一件带有“美与崇高”的事情,但是如果它无法达成前面这种平衡,那我就不会选择它。也就是说我并非出于美与崇高(要求人们尊重我)去选择它,我只是在少数可选项中选择了相对更加美与崇高的一项。在这里,自由确实是我的第一性,自由超过了美与崇高,也超过了理性。

其实我感觉我在前面记的一些博客中的自我剖析已经非常接近陀子对于主人公的剖析了,也难怪读来让人窒息。看着这本书里的独白,说实话我感到熟悉而恶心。

鹭岛旅
Posted 2024-05-07Updated 2025-03-09杂记23 minutes read (About 3473 words)

鹭岛旅

很久很久去外省市旅行过了。
疫情前,因为工作性质的原因,虽然父母无需打卡上班,看似自由支配的时间很多,但实际上也意味着不会有明确的长假安排,家里出去基本也以一日游居多。记忆里上一次出去是初中去杭州。疫情后老妈子总是担心出去要得病,而且要求我们也非必要不出游。
我从小也对于旅游不感冒,非常傲慢地认为,旅游不就是花很多钱,在难得的空闲时间里,挤到人最多的地方,然后看几个也没啥好看的景点,然后带着一身疲惫去读书吗?那时候我还不理解旅行和旅游的区别。
说来小时候出去玩印象最深的其实是行的过程。去西湖印象最深的是和麻麻骑双人自行车绕湖骑了一圈。去北京印象最深的是爬了好久长城,到顶之后还一股脑滚下来过。
慢慢长大,我在高三暑假那年明确跟家里人说我要去骑行,而且要骑个远的,要到拉萨。当时可把他们吓得够呛呀。后来因为综评等一系列事情,发现时间凑不出来,我也就作罢,宅了一个暑假。大概是这个时候,我对于出去玩这件事情的认识,第一次从旅游变成了旅行。即,出去玩不是为了游乐,为了到特定的地区场所,高效汲取同质化的快乐,而是为了行万里路,在行的过程中认识人,认识路,认识自己。我认为禅宗之意是旅途中不可分离的一部分。走马观花而心不明净,是为游而非行。行者无疆,旅行带来的便该是这种开阔,自信,昂扬。
到大二,和航模队的大家去阜新参加比赛。第一次乘绿皮,还在绿皮上学会了斗地主。绿皮上,hmt和我说,下次工训的比赛,我们一起;crz跟我说一起创立一个club。
然后便是目前处于大四春假的时候了。老爸几年前就开始嚷嚷着要去厦门玩了,但因为种种原因一直没去,我感觉他都快忘了。我提出,失恋了好痛苦呀,网上说必须要看海!老妈子自然是担心我一个人去会出事(比如找个风水好的地把自己埋了),所以就让老爸一起,完美!!

Read more
Posted 2024-04-25Updated 2025-08-15Notea minute read (About 219 words)

Graduate Project

拟题:
基于混合现实的智能体交互

具体功能:
通过hololens2获取场景数据(识别小车/其他物体的位置,网格信息)。
通过hololens2的立体空间交互能力,指挥小车进行移动,执行任务(譬如抓取柱体并移动到相应位置)。

  • 关于移动,可以是在眼镜中通过手部动作画一条路径
  • 关于执行任务,可以是眼镜识别出物体的位置后规划小车移动和动作序列(A*or强化学习)->相关信息发给小车->小车收到后执行
    通过hololens2的虚拟物体放置功能,譬如可以放置小车的车库,柱体移动到的目标位置等
    可以通过hololens2显示小车将要移动的意图
这里是一片荒原
Posted 2024-04-25Updated 2025-03-09杂记an hour read (About 9279 words)

这里是一片荒原

Here's something encrypted, password is required to continue reading.
Read more
Posted 2024-04-20Updated 2025-08-15Note2 minutes read (About 358 words)

Docusaurus

The example site: https://chen-yulin.github.io/Besiege-Modern-Docs/

Initialize the local project

node -v >= 18.0

1
npm init docusaurus@latest Besiege-Modern-Mod-docs classic
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
/developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility
✔ Which language do you want to use? › JavaScript
[INFO] Creating new Docusaurus project...
[INFO] Installing dependencies with npm...
...
[SUCCESS] Created Besiege-Modern-Mod-docs.
[INFO] Inside that directory, you can run several commands:

`npm start`
Starts the development server.

`npm run build`
Bundles your website into static files for production.

`npm run serve`
Serves the built website locally.

`npm run deploy`
Publishes the website to GitHub pages.

We recommend that you begin by typing:

`cd Besiege-Modern-Mod-docs`
`npm start`

Happy building awesome websites!

Configuration

Add a source code button

src/pages/index.js,in function HomepageHeader(), add a <div>.

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
function HomepageHeader() {
const {siteConfig} = useDocusaurusContext();
return (
<header className={clsx('hero hero--primary', styles.heroBanner)}>
<div className="container">
<Heading as="h1" className="hero__title">
{siteConfig.title}
</Heading>
<p className="hero__subtitle">{siteConfig.tagline}</p>
<div className={styles.buttons}>
<Link
className="button button--secondary button--lg"
to="/docs/intro">
Getting Started ⏱️
</Link>
</div>
// +++++++++[[
<div className={styles.buttons}>
<Link
className="button button--secondary button--lg"
to="https://github.com/Chen-Yulin/Besiege-Modern-Mod">
Source code
</Link>
</div>
// ]]+++++++++
</div>
</header>
);
}

Two button too close to each other, change the css style for button.
In src/pages/index.module.css

1
2
3
4
5
6
.buttons {
display: flex;
align-items: center;
justify-content: center;
margin-top: 1rem; // +++
}

Deployment

Add the remote repository on github.

1
git remote add origin git@github.com:Chen-Yulin/Besiege-Modern-Docs.git

Change the deployment configurations

1
2
3
4
5
6
7
8
9
10
11
12
// Set the production url of your site here
url: 'https://chen-yulin.github.io',
// Set the /<baseUrl>/ pathname under which your site is served
// For GitHub pages deployment, it is often '/<projectName>/'
baseUrl: '/Besiege-Modern-Docs/',

// GitHub pages deployment config.
// If you aren't using GitHub pages, you don't need these.
organizationName: 'Chen-Yulin', // Usually your GitHub org/user name.
projectName: 'Besiege-Modern-Docs', // Usually your repo name.
deploymentBranch: 'deploy',
trailingSlash: false,

Change the page setting in repository settings, Branch set to deploy branch.

Deploy command: yarn deploy

1
2
3
4
5
[INFO] `git commit -m "Deploy website - based on aa492c3f0934f0177ca946345c2d32940c1900c3"` code: 0
To github.com:Chen-Yulin/Besiege-Modern-Docs.git
* [new branch] deploy -> deploy
[INFO] `git push --force origin deploy` code: 0
Website is live at "https://Chen-Yulin.github.io/Besiege-Modern-Docs/".
Posted 2024-04-19Updated 2025-08-15Note11 minutes read (About 1579 words)

Automate OpenROAD testing

Purpose:

We use OpenROAD to generate timing analysis reports for each design. However, manually modifying parameters, running commands, and intercepting important information will be too arduous work. It is mainly due to the following points.

  • First of all, the report generated by OpenROAD for each design is too long, and the report file may be as large as hundreds of megabytes. It is almost impossible to open and find tns, wns data using a text editor.
  • Secondly, the locations of the configuration files running OpenROAD are very scattered. Moreover, the configuration file directory for timing modification is stored in the tcl script. Manual search and modification are too anti-human and prone to misoperation.
  • Furthermore, the amount of data we need is very large. For each design, we hope to test its performance under 7 different clock cycles and 5 different core area sizes. In other words, for each design, it is necessary to manually modify parameters, run commands, and intercept important information 35 times, which is unbearable, not to mention that we have 7 designs.
    Due to these drawbacks, I decided to use shell script to automate the process of OpenROAD testing. I have the following requirements for the script.
  • The script can modify the core_area, die_area parameter in the tcl script given the path to the tcl script and the desired scale of area.
  • The script can modify the create_clock‘s -period parameter in the sdc configuration file referred by the tcl script, given the path to the tcl script and the desired clock period.
  • The script can set all the parameters and run OpenROAD analysis one by one, given the choice set of clock period and area scale.
  • After the OpenROAD generated the report file, the script can read the report and extract the information of tns & wns for each stop point and export these data to a csv table.

Main Test Framework

The entry script is named as runit.gxy, which can receive the name of design as an argument.
For each design, the corresponding tcl script is fixed, so I decided to map the name of design to the tcl script.

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
design="$1"
if [ "${design}" = "APU" ]; then
file_path_orig="../dataset/run/greedy/APU/10n.tcl"
file_path="../dataset/run/greedy/APU/10n_bak.tcl"
elif [ "${design}" = "ppu" ]; then
file_path_orig="../dataset/run/greedy/ppu/5n.tcl"
file_path="../dataset/run/greedy/ppu/5n_bak.tcl"
elif [ "${design}" = "xtea" ]; then
file_path_orig="../dataset/run/greedy/xtea/5n.tcl"
file_path="../dataset/run/greedy/xtea/5n_bak.tcl"
elif [ "${design}" = "yhuff" ]; then
file_path_orig="../dataset/run/greedy/yh/5n.tcl"
file_path="../dataset/run/greedy/yh/5n_bak.tcl"
elif [ "${design}" = "dynamic_node" ]; then
file_path_orig="../dataset/run/greedy/dy/5n2.tcl"
file_path="../dataset/run/greedy/dy/5n2_bak.tcl"
elif [ "${design}" = "ibex" ]; then
file_path_orig="../dataset/run/ibex_tcl/C0A0.tcl"
file_path="../dataset/run/ibex_tcl/C0A0_bak.tcl"
elif [ "${design}" = "salsa20" ]; then
file_path_orig="../dataset/run/greedy/sal/5n.tcl"
file_path="../dataset/run/greedy/sal/5n_bak.tcl"
else
echo "no such design"
exit 1
fi

if [ ! -f "$file_path" ]; then
echo "File $file_path not found."
if [ ! -f "$file_path_orig" ]; then
echo "Origin file ${file_path_orig} not found."
exit 1
fi
cp $file_path_orig $file_path
fi

The reason I use _bak post-fix is that, I want to reserve the original core_area and die_area configuration in the origin tcl file, since the original configuration is needed in the following steps.

Then I use nested loop to change the configuration one by one. The choice set can be modified in the condition statement of each for loop.

1
2
3
4
5
6
7
8
9
10
11
for period in 2 4 6 8 10 12 14
do
# set clk period
for scale in 0.2 0.4 0.6 0.8 1
do
# set area scale
#run openroad
timeout 5 ../../OpenROAD-flow-scripts/tools/OpenROAD/build/src/openroad $file_path > $output_path
# collect data and export to csv
done
done

The set clk period, set area scale, export to csv function will be covered in the following steps.

Set the Period of Clock

I create a new shell script called set_clk.sh to manage the automation of changing clock period.
It takes two arguments, the path to the tcl script (string) and the desired clock period (integer).
I first preprocess the period parameter, namely, divide it by 10.

1
2
3
4
5
time="$2"
period=$(echo "scale=1; $time / 10.0" | bc)
if [[ $period =~ ^\. ]]; then
period="0$period"
fi

The clock configuration can be modified in the sdc file, while the path to the sdc file can be extracted from the tcl file, with the format of set sdc_file "PATH_TO_SDC"
I decided to use grep to locate the line of set sdc_file and extract the path to sdc file using regex substitution.

1
2
tcl_path="$1"
sdc_path=$(grep 'set sdc_file' "$tcl_path" | sed 's/.*"\(.*\)".*/\1/')

In the sdc file, the configuration has a format of create_clock ... -period 0.x.
Still, use regex substitution to replace the original period with the input period and everything is done.

1
sed -i "s/^\(create_clock.*-period \)[0-9]*\.*[0-9]\(.*\)$/\1$period\2/" "$sdc_path"

Set the core_area and die_area

The area of the design is expressed in the form of {x1 y1 x2 y2}, where x1 y1 stands for the coordinate of bottom-left corner and x2 y2 stands for the coordinate of upper-right corner.
Since the area of different design varies a lot, I need to change the area proportionately. As a result I need to reserve the original area stored in tcl script as mentioned before.

First, I read the origianl core_area and die_area from the original script.

1
2
3
4
5
6
7
8
9
file_path="$1"
orig_path="${file_path//_bak}" # remove the _bak postfix_

core_area=$(grep 'set core_area' "$orig_path" | sed -n 's/.*{\([^}]*\)}.*/\1/p')
die_area=$(grep 'set die_area' "$orig_path" | sed -n 's/.*{\([^}]*\)}.*/\1/p')

IFS=' ' read -r core1 core2 core3 core4 <<< "$core_area"

IFS=' ' read -r die1 die2 die3 die4 <<< "$die_area"

Then I calculate the desired core/die area size based on the scale and original area.

1
2
3
4
5
6
7
8
9
10
11
12
13
core_x_size=$(echo "$core3" - "$core1" | bc)
core_y_size=$(echo "$core4" - "$core2" | bc)

core1=$(echo "$core1 + $core_x_size * (1 - $2) / 2" | bc)
core3=$(echo "$core3 - $core_x_size * (1 - $2) / 2" | bc)

core2=$(echo "$core2 + $core_y_size * (1 - $2) / 2" | bc)
core4=$(echo "$core4 - $core_y_size * (1 - $2) / 2" | bc)

die1=$(echo "$core1" - "10" | bc)
die2=$(echo "$core2" - "10" | bc)
die3=$(echo "$core3" + "10" | bc)
die4=$(echo "$core4" + "10" | bc)

Finally, use regex substitution to modify the area configuration in _bak.tcl script.

1
2
sed -i "s/die_area {[^}]*}/die_area {$die1 $die2 $die3 $die4}/g" "$file_path"
sed -i "s/core_area {[^}]*}/core_area {$core1 $core2 $core3 $core4}/g" "$file_path"

Collect data and export to .csv

The key information I need from the report generated by OpenROAD is tns & wns.
By observation, the block containing the data has the following pattern.

1
2
3
4
5
***
result of: stoppoint*
tns: [number1]
wns: [number2]
***

Therefore, I use the grep and awk command to get the last word in each data block. In this case, it’s stoppoint*, [number1], [number2].

1
2
input_file="$1"
tnswns=$(grep -A 2 "result of" "$input_file" | awk '/result of/{p=3} p&&p--' | awk '{print $NF}')

Each report contains totally 6 valid stop points, so I use a loop to get the desired data.

1
2
3
4
5
6
7
8
9
csv_file="${design}.csv"
for nr in 2 5 8 11 14 17
do
stoppoint=$((stoppoint+1))
tns=$(echo "$tnswns" | awk -v nr="$nr" 'NR==nr')
nr_wns=$(echo "$nr + 1" | bc)
wns=$(echo "$tnswns" | awk -v nr="$nr_wns" 'NR==nr')
# export to csv table
done

After getting the desired tns and tws, I want to export these data to a csv table.
I decided to let the table has the following columns, period, scale, stop point number, tns and wns, one such table for each design.
This function can be achieved with the following script

1
2
3
4
design="$2"
period="$3"
scale="$4"
echo "${period},${scale},stoppoint${stoppoint},${tns},${wns}" >> $csv_file

Replace the comment in the loop and everything is done.

Result

I assemble runit_gxy.sh in a single script named runit_cyl.sh to run the analysis of all designs at once.

1
2
3
./runit_gxy.sh APU
./runit_gxy.sh ppu
...

Then redirect the output to runit_cyl.log.

Here is the content of APU.csv and runit_cyl.log

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
Period,Scale,Stoppoint,tns,wns
2,1,stoppoint1,-17.2309532166,-0.4609909952
2,1,stoppoint2,-13.7819681168,-0.4073848128
2,1,stoppoint3,-13.7819681168,-0.4073848128
2,1,stoppoint4,-14.1436796188,-0.3814869523
2,1,stoppoint5,-14.1436796188,-0.3814869523
2,1,stoppoint6,-14.1436796188,-0.3814869523
2,0.95,stoppoint1,-17.2309532166,-0.4609909952
2,0.95,stoppoint2,,
2,0.95,stoppoint3,,
2,0.95,stoppoint4,,
2,0.95,stoppoint5,,
2,0.95,stoppoint6,,
2,0.9,stoppoint1,-17.2309532166,-0.4609909952
2,0.9,stoppoint2,,
2,0.9,stoppoint3,,
2,0.9,stoppoint4,,
2,0.9,stoppoint5,,
2,0.9,stoppoint6,,
4,1,stoppoint1,-8.3930120468,-0.2609909773
4,1,stoppoint2,-4.7969579697,-0.2073848099
4,1,stoppoint3,-4.7969579697,-0.2073848099
4,1,stoppoint4,-4.5129084587,-0.1783644110
4,1,stoppoint5,-4.5129084587,-0.1783644110
4,1,stoppoint6,-4.5129084587,-0.1783644110
4,0.95,stoppoint1,-8.3930120468,-0.2609909773
4,0.95,stoppoint2,,
4,0.95,stoppoint3,,
4,0.95,stoppoint4,,
4,0.95,stoppoint5,,
4,0.95,stoppoint6,,
4,0.9,stoppoint1,-8.3930120468,-0.2609909773
4,0.9,stoppoint2,,
4,0.9,stoppoint3,,
4,0.9,stoppoint4,,
4,0.9,stoppoint5,,
4,0.9,stoppoint6,,
6,1,stoppoint1,-1.8987674713,-0.0609909929
6,1,stoppoint2,-0.0572821237,-0.0073847598
6,1,stoppoint3,-0.0572821237,-0.0073847598
6,1,stoppoint4,0.0000000000,0.0000000000
6,1,stoppoint5,0.0000000000,0.0000000000
6,1,stoppoint6,0.0000000000,0.0000000000
...

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
use design: APU
use tcl file path ../dataset/run/greedy/APU/10n_bak.tcl
get sdc path: ../dataset/run/greedy/gcd/1/gcd_nangate45.sdc
Change period to 0.2
create_clock [get_ports clk] -name core_clock -period 0.2
core area difference 60.18 59.8
set die_area {.07 1.2 80.25 81}
set core_area {10.07 11.2 70.25 71}
collecting data
core area difference 60.18 59.8
set die_area {1.07 2.2 79.25 80}
set core_area {11.07 12.2 69.25 70}
collecting data
core area difference 60.18 59.8
set die_area {3.07 3.2 77.25 79}
set core_area {13.07 13.2 67.25 69}
collecting data
get sdc path: ../dataset/run/greedy/gcd/1/gcd_nangate45.sdc
Change period to 0.4
create_clock [get_ports clk] -name core_clock -period 0.4
core area difference 60.18 59.8
set die_area {.07 1.2 80.25 81}
set core_area {10.07 11.2 70.25 71}
collecting data
core area difference 60.18 59.8
set die_area {1.07 2.2 79.25 80}
set core_area {11.07 12.2 69.25 70}
collecting data
core area difference 60.18 59.8
set die_area {3.07 3.2 77.25 79}
set core_area {13.07 13.2 67.25 69}
collecting data
get sdc path: ../dataset/run/greedy/gcd/1/gcd_nangate45.sdc
Change period to 0.6
create_clock [get_ports clk] -name core_clock -period 0.6
core area difference 60.18 59.8
set die_area {.07 1.2 80.25 81}
set core_area {10.07 11.2 70.25 71}
collecting data
...
《边城》读书会p3
Posted 2024-04-18Updated 2025-08-15读读噜2 minutes read (About 306 words)

《边城》读书会p3

将命运的苦难表现得非常纯粹
就是指这种苦难它甚至和客观条件都不那么相关,也就是说,这种苦难是哲学的,普遍的,而不是特别的,临时的,它难以被真正改变。
描写旧时代的小说中最常见的底层人民的苦难,穷,病,愚昧,被剥削,这些在《边城》中都很少,几乎没有。
《边城》中,百姓淳朴善良,邻里关系好。能管事的也慷慨正值。老船夫一家虽然不富裕,但温饱不愁。甚至关于老人的病和城中的水灾,作者也都写得很克制。
但表现上越是美好,最后的结局也就越是让人意难平。
因为即使没有“穷,病,愚昧,被剥削”,人还是得不到想要的东西。
用作者的话来说:一切充满了善,然而到处都是不凑巧。既然是不凑巧,因之朴素的善终难免产生悲剧。
这便是更残酷的生命真相。

ONI Modding
Posted 2024-04-17Updated 2025-08-15Note3 minutes read (About 490 words)

ONI Modding

Basic

Useful tools

  • Dnspy: decompile the runtime library of ONI
  • Visual Studio (though it’s too fat)
  • Poedit: read the .po file for zh-en translation

Hello world

Apply patches on the Initialize() method in Db class.

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
public class Patches
{
[HarmonyPatch(typeof(Db))]
[HarmonyPatch("Initialize")]
public class Db_Initialize_Patch
{
public static void Prefix()
{
Debug.Log("Hello! Welcome to CuppyUniverse! [before Db.Initialize]");
}

public static void Postfix()
{
Debug.Log("CuppyUniverse initialized! [after Db.Initialize]");
}
}
[HarmonyPatch(typeof(ElectrolyzerConfig))]
[HarmonyPatch("CreateBuildingDef")]
public class ElectrolyzerConfig_Patch
{
public static void Postfix(ref BuildingDef __result)
{
__result.EnergyConsumptionWhenActive = 114f;
}
}
}

Add new building

Take gold washer (just like water purifier but output small amount of gold) as an example.

  1. Find the source code for water purifier.
    i.e.
    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
    using System;
    using TUNING;
    using UnityEngine;

    // Token: 0x0200039A RID: 922
    public class WaterPurifierConfig : IBuildingConfig
    {
    // Token: 0x06001314 RID: 4884 RVA: 0x000665C4 File Offset: 0x000647C4
    public override BuildingDef CreateBuildingDef()
    {
    string id = "WaterPurifier";
    int width = 4;
    int height = 3;
    string anim = "waterpurifier_kanim";
    int hitpoints = 100;
    float construction_time = 30f;
    float[] tier = BUILDINGS.CONSTRUCTION_MASS_KG.TIER3;
    string[] all_METALS = MATERIALS.ALL_METALS;
    float melting_point = 800f;
    BuildLocationRule build_location_rule = BuildLocationRule.OnFloor;
    EffectorValues tier2 = NOISE_POLLUTION.NOISY.TIER3;
    BuildingDef buildingDef = BuildingTemplates.CreateBuildingDef(id, width, height, anim, hitpoints, construction_time, tier, all_METALS, melting_point, build_location_rule, BUILDINGS.DECOR.PENALTY.TIER2, tier2, 0.2f);
    ...
    return buildingDef;
    }

    // Token: 0x06001315 RID: 4885 RVA: 0x000666A8 File Offset: 0x000648A8
    public override void ConfigureBuildingTemplate(GameObject go, Tag prefab_tag)
    {
    ...
    }

    // Token: 0x06001316 RID: 4886 RVA: 0x0006688B File Offset: 0x00064A8B
    public override void DoPostConfigureComplete(GameObject go)
    {
    ...
    }

    // Token: 0x04000A88 RID: 2696
    public const string ID = "WaterPurifier";

    // Token: 0x04000A89 RID: 2697
    private const float FILTER_INPUT_RATE = 1f;

    // Token: 0x04000A8A RID: 2698
    private const float DIRTY_WATER_INPUT_RATE = 5f;

    // Token: 0x04000A8B RID: 2699
    private const float FILTER_CAPACITY = 1200f;

    // Token: 0x04000A8C RID: 2700
    private const float USED_FILTER_OUTPUT_RATE = 0.2f;

    // Token: 0x04000A8D RID: 2701
    private const float CLEAN_WATER_OUTPUT_RATE = 5f;

    // Token: 0x04000A8E RID: 2702
    private const float TARGET_OUTPUT_TEMPERATURE = 313.15f;
    }

Create a new csharp class file in VS and copy the content into it.
Remember to rename

  • the class name
  • id in method CreateBuildingDef()
  • ID in class
    In this example change them to GoldWasher
  1. Add GoldWasher to build menu.
    create a new patch for GeneratedBuildings
    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
    using System;
    using HarmonyLib;

    namespace ONI_CuppyUniverse_Mod
    {
    [HarmonyPatch(typeof(GeneratedBuildings), "LoadGeneratedBuildings")]
    public class GeneratedBuildings_LoadGeneratedBuildings
    {
    public static void Prefix()
    {
    Strings.Add(new string[] {
    "STRINGS.BUILDINGS.PREFABS.GOLDWASHER.NAME",
    "淘金器"
    });
    Strings.Add(new string[] {
    "STRINGS.BUILDINGS.PREFABS.GOLDWASHER.EFFECT",
    "从纯净水中淘取黄金"
    });
    Strings.Add(new string[] {
    "STRINGS.BUILDINGS.PREFABS.GOLDWASHER.DESC",
    "你是信无中生有的"
    });
    ModUtil.AddBuildingToPlanScreen("Food", "GoldWasher");
    }
    }
    }

Reference

  • Some mod src
  • ONI Mod Guidance
  • Harmony Guidance
Previous
Next
  • 1
  • …
  • 18
  • 19
  • 20
  • 21
  • 22
  • …
  • 28
Chen Yulin

Chen Yulin

SJTU student

Manchester by the Sea

Posts

276

Categories

10

Tags

194

Follow

Archives

  • August 20252
  • July 20255
  • June 20256
  • May 202510
  • April 202517
  • March 202545
  • February 202512
  • January 202513
  • December 202412
  • November 20244
  • October 202418
  • September 202416
  • August 202413
  • July 20243
  • June 20245
  • May 202413
  • April 202417
  • March 20241
  • January 20241
  • December 20231
  • May 202346
  • August 20221
  • May 20226
  • April 20229

Recents

RAG-Graph

2025-08-13

RAG-Graph

Note

LangChain and LangGraph

2025-08-13

LangChain and LangGraph

Note

KAF Training

2025-07-18

KAF Training

Note

2025-07-17

MATH6003J Project Proposal

Note

2025-07-14

Math6003 Hw5

Note

Tags

3D-Scene4
6-D3
AI12
AIGC1
API1
AR2
Academic1
Algorithm1
Aliyun1
App2
Atlas1
BS41
Beautify1
Behaviorism1
Business1
C1
CADC1
CD1
CLIP5
CNN1
CV29
Capstone10
Communication2
Contrastive-Learning3
Control2
Csharp9
Css1
Cuda3
DD1
DINO4
DT1
Dataframe1
Debate5
Debugger1
Diffusion1
Discrete-Mathematics1
Disney1
Docker1
Docs2
Dynamic-programming1
ESP322
Education1
Embeded-System9
Embodied-AI8
Emoation1
Emotion13
Ethic1
FL1
FPN2
Family1
Federated-Learning1
Foundation1
Functional programming1
GPT3
Game5
Gated-NN2
Git7
Github1
Godot3
Graph1
HPC1
HRI2
Haskell1
Health2
Hexo10
Hierarchical1
Html5
Humanism1
Hyprland2
IK1
Image-Grounding1
Image-Text5
Image-generation1
ImitationLearning3
Jolt1
Json1
LLM13
LSP2
Latex2
Life4
LinearAlgebra1
Linux22
Live2d1
Love4
Lua1
MBTI1
ML8
MR/AR3
Mason1
Math6
Meme1
Message-Passing1
Mod3
Motivation1
Movie1
Multi-Agent1
Multi-modal6
Multi-view1
Music5
NLP4
NN5
Network2
Nodejs5
Numpy1
Nvim9
Object-Detection4
Open-Vocabulary9
OpenCV1
Oral1
PHD1
PSY5
Pandas2
Panoptic1
Path1
Philosophy3
PhysX1
Physical-Scene4
Physics-engine1
Pio2
Planning1
Plugin8
PoseEstimation3
Postgraduate1
Prefab1
Probability1
Python28
Pytorch1
QML1
Quantum1
RAG1
RNN4
ROS3
Reading19
Real2Sim1
Reconstruct9
Regex2
Reinforcement-learning1
Repository5
Representation-Learning1
Research-paper86
Robot1
Robotics16
SJTU-Lecture1
SQL2
SSH3
Scene-graph29
Scene-synthesis1
Science-fiction1
Scrap1
Script2
Segmentation7
Semantic12
Shader3
Shell4
Signals and Systems1
Sim2Real1
Sklearn1
Snippets1
Society4
Star-rail1
Subgraph1
Submodule1
Supervised-learning2
Survey3
TC1
TOEFL1
Task-Planning6
Tasks4
Tech Communication1
Torch5
Transformer11
Translation-Embedding2
Travel3
Unity20
Unsupervised-learning1
VLM6
VLP2
Version-management1
ViT4
VideoEditing2
Vim1
Visual-Relation20
WSL1
Waybar1
Wayland1
Web1
Website1
Well-being1
Window-manager2
YKLL3
Zen2
🍰1
🐱2
🧀1
Chen Yulin's BlogChen Yulin's Blog

© 2025 Chen Yulin  Powered by Hexo & Icarus

×