一个属于左半红印的Avalon
《黑神话悟空》剧情解析一

这个时间点网上已经有很多关于这个游戏的剧情解析了。我大致都看了看,有些写的挺好的,而另一些则过于夸张。比如一些过于牵强的联想,有的甚至从过场动画的人物表情上取证等等。所以就有了这篇日志,我会尽量依照时间逻辑和符合游戏文本逻辑的方式,清楚的讲一下《黑神话悟空》到底讲了个啥。这里考虑到篇幅问题,有可能会分期讲。这一篇,我们直接讲游戏结局。

先说明一下,整个游戏不算片头动画,包括最后的花果山,一共6个篇章。片头的动画我算作序章,在序章中老猴子向玩家扮演的天命人传达了整个游戏的攻略目标,即收集大圣的根器并最后复活大圣。随后游戏通过五个章节来描述天命人经历的五个故事,并最终回到花果山复活大圣。本篇日志不会涉及中间那五个章节的故事(这个我们后面再讲),而是直接来讲天命人的这趟旅途的始末。

西天取经之后,孙悟空封了斗战胜佛住在了天上。本应逍遥自在过日子,但是因为一些游戏里没有交代的事情,孙悟空决定舍弃佛位跑回了花果山。然后天庭不打算就这么放过他,于是有了游戏的开场部分。

大圣为什么离开天界?

在大圣与猪八戒的对话中,我们能猜测悟空有可能遇到了什么事情而自己又无能为力。亦或者是某些神佛做的事让大圣无法忍受。

然而,实际情况是除了在序章中我们看到的天兵天将,天界还安排了五个妖王来帮忙。分别是已经在观音那当山神的黑熊精,灵吉菩萨的徒弟黄凤鼠精,弥勒佛的徒弟黄眉,给毗蓝婆菩萨看门的蜈蚣精,皈依佛门的牛魔王。战斗的经过我们不得而知,但结果是孙悟空死了。

大圣怎么死的?

两种可能,一种是自杀,从天命人与二郎神的对话中猜测,孙悟空是杀不死的,所以孙悟空可能是自杀。并用自杀换取了二郎神没有彻底杀光花果山的猴子猴孙,为未来的天命人留下了可能。

另一种是肉身被二郎神和妖王联手杀死但是神魂不灭。二郎神知道孙悟空的六根无法杀死,于是将他们分给妖王。

孙悟空死后,遭到了二郎神和五个妖王的分尸。大圣的尸体化为六根,黑熊精获得眼,鼠精获得耳,黄眉获得鼻子,蜈蚣精获得舌头,身体则归了牛魔王。另外二郎神也取了一样东西,游戏中并未具体说是什么,但从剧情中猜测应该是大圣的记忆。六根中的意随着大圣的死亡消散了。

大圣六根中的意去哪里了?

两种理解,一种是根据游戏最后阶段老猴子的说法,大圣的意已经不存在了,天命人自己的意就可以充当大圣六根中的意。另一种是根据游戏中对根器意见欲的描述,为忆念,也就是二郎神取走的记忆。

然后就是游戏的主要内容,玩家控制的天命人依次从五个妖王那里取回了大圣的五个根器。在这个过程中,天命人在每一个妖王那里都会碰到一个奇怪的NPC。他们分别是黑风山的白衣秀士、黄风岭的黄袍员外、小西天的翠笠武师、盘丝岭的黑手道人和火焰山的皓斧力士。这些人都有着共同的特点,他们都是在大圣死后才来到这些妖王的身边,他们都是被他们自己称作大哥或者郎君的人派过来调查妖王的,他们都指引着天命人找到了这些妖王背后的隐藏信息。而从天命人与二郎神的对话中可以知道,正是在大圣死后二郎神派他们来的。

游戏的最后,天命人回到花果山,取回了大圣的战衣和金箍棒,击败了大圣最后的残留(大圣残躯)。结合了从五个妖王那里取回的大圣五根器,从二郎神那里取回的大圣记忆和天命人自己的意,成为了新的大圣。

天命人获取的大圣装备是真的吗?

我个人理解是,天命人获得大圣披挂是真的。影神图中为每一个装备变化的头目都有描写,讲述为什么这件装备会变化成这个头目。所以可以认为这些披挂是真的。当然,玩家可以获得另外一批名字完全一样,品级是凡品的另一套大圣披挂。但其实仔细看一下这套凡品装备就会发现,臂甲和腿甲的样式过于简单。特别是腿甲是一双鞋子,这和游戏中其他所有腿甲都不一样。这个游戏中的所有腿甲都不是鞋子,天命人从头到尾都是光着脚,只有这套披挂中的腿甲是鞋子。所以基于以上观察,我个人推测这套凡品的大圣装备应该是游戏制作早期的版本,后来因为某些原因被弃用。而制作方又舍不得就这么扔了,尤其是这套装备还出现在了游戏的早期宣传片中,于是就作为单独一套装备被保留了下来。

至于天命人在剧情中获得的如意金箍棒是真是假,不好说,我个人偏向于认为这根棒子是假的。我这么认为的理由并不是出于什么推测和想象。首先是很多人都知道的,在花果山地图中有个柱状的石头插在山里并被大量锁链困住,游戏中也并没有交代这是什么,但有可能是金箍棒。另外还有一处是在最终BOSS战斗中,石猴变身成齐天大圣,身披金甲,召唤了如意金箍棒。可如意金箍棒不是已经在天命人手里吗?那这根如意金箍棒是哪来的?当然,最终战发生在大圣石头的意识世界内,所以也可以理解为这根召唤来的如意金箍棒是意识世界中的虚幻的。到目前为止,此案暂无解。

左半红印创作于2024.08.25th
关于CVE-2024-4577

我不太懂这方面的技术内容,所以这篇日志的主要内容是前段时间我的经历。

Security Alert: CVE-2024-4577 – PHP CGI Argument Injection Vulnerability | DEVCORE

PHP CGI Windows平台远程代码执行漏洞(CVE-2024-4577)已发现在野攻击 – 安全内参 | 决策者的网络安全知识库 (secrss.com)

首先这个漏洞的出现是在今年6月初,看内容就是windows服务器的语言编码导致PHP出现了漏洞。一些特定的字元序列,可以绕过以往的安全保护从而执行危害代码。然后在差不多的时间,我的这个小破站被攻击了……

整个服务器内的几乎所有文件都被lock,几乎每一个文件夹下都留了一个html的勒索文本。当时我那个火大啊,我一个自己的blog私人网站,没有任何商业价值,你勒索我有意义吗?!我怎么可能给你打钱?当然,也能理解的是这种攻击通常是机器人无差别全网扫描攻击,不会在乎你是谁。

然后,在折腾半天恢复了网站之后不到3个小时,服务器报警,又被黑了……再说一遍,我是这方面技术的小白。只能尽可能的自己研究和在网上费劲的搜索,然后了解到大概得攻击流程大概如下

  1. 攻击者利用漏洞在网站目录下新建一个php文件,这个文件的内容很少,就是一个包含upload的html元素的php文件
  2. 因为这个upload是攻击者新建的,所以没有任何保护机制,可以上传任何东西。
  3. 攻击者利用这个upload,上传病毒文件。上传的病毒文件会以临时文件的形式存放在tmp文件夹下
  4. 执行病毒文件,锁全盘

我会发现有几个问题即便我不是专家也觉得不合理。首先我们先不考虑系统漏洞,第一个问题是攻击者为什么可以远端执行类似这种新建文件的命令。第二,攻击者为什么有权限在网站目录下新建文件。所以目前可以想到的保护措施如下。

第一步,针对CVE-2024-4577。这个很简单,只要你在网上搜索就能找到答案。要么更新你的php版本,要么关闭cgi。这我没什么好说的,听人家的。

Version 8.3.8

06 Jun 2024
CGI:
Fixed buffer limit on Windows, replacing read call usage by _read.
Fixed bug GHSA-3qgc-jrrr-25jv (Bypass of CVE-2012-1823, Argument Injection in PHP-CGI). (CVE-2024-4577)

第二步,处理危险方法,禁止它们执行。

在php.ini中新增disable_functions = exec, shell_exec, passtthru, system等等

第三步,处理权限

这个有点麻烦,取决于用什么在运行php。这里我说一个简单的案例,可能很多人都是如此。对相关技术不太懂,又想简单搭建一个php环境,于是用了XAMPP。关于这个软件我有一些看法我们后面再说,这里先说的你可能不知道当你在运行xampp的时候,xampp会直接获取system权限来运行apache。于是往后你的php干任何事都是用system权限。这也是为什么攻击者有权限在你的网站目录下新建文件。

所以这里我们需要做的是在windows中另外新建一个低权限的用户(比如guset),然后配置用户权限中的“作为服务登录”添加这个用户。再将apache服务的登录选择为这个用户。这样当你再启动apache后,这个服务就会以你新建的那个低权限用户运行。

接下来开始配置你的文件和文件夹权限。如果有everyone权限,都给删了。加入新建用户,该给什么文件什么权限就看自己的了。

在完成了上述权限配置后,你可能会遇到一个问题就是wordpress的自动更新无法进行了。因为进行了权限管控,所以wordpress依赖的apache的权限无法对文件进行操作。如果出现了这种情况,要么进一步细致的配置权限,要么就自己手动更新吧。

在完成上述的操作同时,我曾经试图干脆直接更新php版本到最新。然后发现了一个关于xampp的小情况。可能很多人没有注意到,XAMPP并不是一个面向实际生产的软件。它开放了所有的安全选项,目的是为了让人们更好的利用它来测试自己的应用。实际上,xampp的最合适运行场所是一个本地的开发环境而不是一个真正面向公网的服务器。但即便如此,正如我前面所说,这玩意太好用了,特别的简单。所以实际上很多人直接把它部署在了服务器上。这意味着,如果你也这么做了,那么别人不黑你则好,一旦攻击你几乎就是一个没有任何防护的活靶子。所以,你需要自己来配置各种安全策略。

来自Apache Friends

XAMPP provides an ideal local development environment, but is not meant for production deployments. We want to make hosting PHP applications created with XAMPP as easy as possible. 

在理解了上述的内容后,我开始更新php版本,然后就发现xampp根本就没有提供最新版本php的xampp。实际上,如果你现在打开xampp网站你会发现,甚至它没有任何8.3版本的php更新。不仅如此,在它的历史版本软件库中,会发现从2022年5月以后xampp的版本更新速度明显下降。到2023年,全年仅发布两次更新。而此时,2024年都没有任何更新。xampp发生了什么吗?在他们的论坛中可以找到一个有趣的声明。发布时间是2022年6月,内容是Apache Friends项目将迁移至Github,同时他们发了一篇blog。

Apache Friends Project Moves to GitHub

从上面的内容,我似乎看出一些信息,似乎xampp和bitnami分家了。在过去10年里,bitnami为xampp进行了版本更新的工作,而现在随着bitnami的离开,xampp的更新就慢了甚至现在停滞了。在看到这些信息后,我感到一阵扼腕叹息。时代的车轮就是如此,无论你坚持多久可能最后的归宿都是虚无。

所以,朋友们,有什么好的替代xampp的软件推荐一下啊!

killgod创作于2024.06.29th
理解Sawtooth Wave Node

这也是一个Shader Graph中的一个常用节点,例如当我需要一个不断重复的0到1,就会利用这个节点。但是网上对这个节点的介绍并不全面甚至有些是错误的,所以这里我梳理了一下这个几点的内容。首先还是先看源码

void Unity_SawtoothWave_float4(float4 In, out float4 Out)
{
    Out = 2 * (In - floor(0.5 + In));
}

这个方法计算非常简单,我可以带入0.1,0.2,0.3等等,就能算出结果。所以从计算结果来看,首先需要确认的是,这节点的起始点是0。说准确点就是当输入是0的时候,输出也是0。然后随着输入增大开始变化,根据这个变化我可以画出这个图形

从这个图形可以看出,这个节点的幅度是(-1, 1)。所以如果我想要一个上面所说的(0, 1)就需要把这个节点的输出加1,再除以2。但这样的结果会导致起始点不是0。

另外还有一点非常重要,实际上这个节点永远也到不了1。所以上面所说的幅度其实并不准确,从图形中也很难看出。但只要我把数字带入上面的源代码中,就可以轻易发现问题。当我把0.5,1.5,2.5等等带入源代码中,可以轻易算出结果都是-1。而如果把0.49或者0.4999带入的话,结果会无限趋近于1但永远达不到。

左半红印创作于2024.05.20th
理解Tiling And Offset Node

在Unity中的Shader Graph中的一个常用节点Tiling And Offset Node,最常用的方法是把offset和time相连,这样就可以让图案运动起来。现在,要讲的是tiling和offset的关系。首先看一下源代码。

void Unity_TilingAndOffset_float(float2 UV, float2 Tiling, float2 Offset, out float2 Out)
{
    Out = UV * Tiling + Offset;
}

让我们来快速理解这个公式。UV是变换前的坐标,Out是变换后的坐标。我用一个例子来帮助理解,我们在使用这个节点的时候通常会有一个期望,就是变换后的图案的中心点和材质的中心点重合,即图像不管是扩大还是缩小,都应该以中点为锚点。在这个需求下,上面的公式中UV=0.5,这是图案的中心。Out = 0.5,这是(缩放后)材质的中心点。于是我们得到了下面的推导公式

0.5 = 0.5 * Tiling + Offset
(1 - Tiling) / 2 = Offset

可以简单验证,比如放大Tiling是(0.3, 1),此时的Offset = (0.35, 0)

缩小Tiling是(3, 1),此时的Offset = (-1, 0)

所以使用时,可以遵循上述逻辑。用对齐的方法,图案的坐标(UV)对齐材质的图标(Out),然后代入这个公式即可。

左半红印创作于2024.05.19th
关于FixedUpdate()的进一步理解

关于Unity中FixedUpdate()的意义已经在网络上有很多了,这里不再赘述那些,只是记录一下我对它的理解。

首先,关于FixedUpdate(),能不用就不用。因为它是一个固定帧率调用的方法,默认是50帧。它额外于Update方法独立运行,尤其对于配置较低的电脑来说,游戏的帧率可能都没有50帧,再额外来个50帧的负载,对性能会有影响。另外,Unity默认50帧,这个数字其实看起来怪怪的。我们都知道游戏的最低理想帧率是60,这个默认50帧的设定我想本来就是考虑到性能消耗的结果。

当然如果你在网上搜索,会搜到FixedUpdate()其实是用于物体运动控制的方法。因为Update会受到游戏运行帧率影响,调用有快有慢,所以用调用帧率相同的FixedUpdate()来处理就会防止物体运动速度随着帧率波动。这种说法是对的,但是在实际操作过程中又有问题。首先要明确的是这里指的物体移动是利用Rigidbody组件移动,当然,你会在网上搜到类似Unity中控制物体移动不推荐使用transform.Translate这样的内容。实际上这完全依据你的实际使用情况,没有什么推荐不推荐的。这里就说Rigidbody,控制其运动的方法在于给他的velocity变量赋值即可,赋值越大跑的越快。而只要velocity不是0,物体就不会停。所以首先不用在FixedUpdate()中赋值,同样也不用在FixedUpdate()中将其置0好让物体停下来。所以除非是精确控制,可以尽量不用FixedUpdate()。那么什么是精确控制呢?比如让物体从A点移动到B点,我们给在A点的物体的RigidBody一个朝向B点的velocity,现在物体开始动了。然后,问题是什么时候停下来,如何在程序中体现物体到达B点这个状态。这里我们要物体精确停留在B点,所以有个很容易想到的方法就是在物体运动的时候不断测量自己与B点的距离,如果距离非常小了就认为到了B点。那么这个测量距离的方法就要写在FixedUpdate()中。因为Rigidbody的运行方法是依照固定频率来的,即可以这么理解,它没写在FixedUpdate()中,但是也是在FixedUpdate()中更新自己的位置。所以在FixedUpdate()检测距离,其检测的频率刚好就和Rigidbody更新自己位置的频率一致,所以控制就很准确。

除此以外,就是配合TIme.timeScale使用。我们都知道一种情况就是,如果是游戏,那么当我呼出菜单或者其他情况下,游戏是会暂停的。那么这里就会利用timeScale来完成。但是问题是,我们这个时候并不希望程序这个时候真的全部暂停。很简单就能理解,呼出菜单后游戏暂停,但是菜单本身属于UI界面,我并不希望菜单本身也暂停。再比如游戏中有一些过场演出,在演出的同时,我需要游戏内物体停止运动,但是演出本身不能停止。这时timeScale的用处就体现出来了,它只会暂停FixedUpdate()的调用,而不会暂停Update()的调用(timeScale = 0时,Time.deltaTime = 0)。这就方便了我们编写内容。

那么问题来了,如果一定要在Update()中移动物体,又不想让物体移动速度受帧率影响该咋办呢。这里方法有很多,我们先说上文提到的transform.Translate。其实只要看一下官方文档就能明白。

using UnityEngine;
using System.Collections;

public class ExampleClass : MonoBehaviour
{
    void Update()
    {
        // Move the object forward along its z axis 1 unit/second.
        transform.Translate(Vector3.forward * Time.deltaTime);

        // Move the object upward in world space 1 unit/second.
        transform.Translate(Vector3.up * Time.deltaTime, Space.World);
    }
}

官方文档中给出了上面这个例子,上面已经注释的非常清楚,物体以1 unit/second的速度移动,这个速度是固定的。其实很好理解,每一帧有长有短,但其实无论长短多少,都会体现在Time.deltaTime中。它会随着帧率下降而增加,随着帧率上升而减小。那么1秒钟内,有多少帧就会有多少次deltaTime,每次的deltaTime都是距离上一帧的时间间隔,那么所有deltaTime加起来就还是1秒。

左半红印创作于2024.04.2nd
《沙丘 PART TWO》

电影看完了,拍的不错相当震撼。网上已经有了太多关于电影的解读,所以这里我就不班门弄斧了。关于第一步的感想以前也写过了。这里只是简单说一些细枝末节的地方。

首先电影PART TWO的剧情结束点也是小说第一部的结束点。所以如果你对这部科幻作品慕名而来但又不想看小说的话,看完这两部电影也就够了。实际上沙丘系列后面还有海量的内容,但就我个人来说不太喜欢。小说第一部已经是一部完整的王子复仇记,当然如果说沙丘就是一部科幻王子复仇记显然过于狭隘。下面我谈一下我的看法。

这部小说发行于1965年,必须承认沙丘是具有当年的局限性的,但这种局限性在现今看来也许还有好的地方。接下来我说的沙丘仅仅局限于系列的第一部。小说也好电影也好,剧情主线是一致的。主角无疑是一个名为保罗的家族少主,这里的家族相当于中国历史上春秋战国时期的诸侯。那么反方是谁呢?从电影第一部看是另一个敌对家族哈克南家族,到了第二部又似乎是后面才正式登场的帝国皇帝,还有一个从头到尾都全程谜语人的贝尼杰瑟里特姐妹会。这种多反派在电影中的表现并不好,会导致观众的迷糊。再加上主角保罗可以看见未来的描写,这加重了观众的理解门槛。我在以前的日志中就提到过,没事不要轻易用时间操控的方式来做故事叙述的方法,无论是遇见未来还是平行时空都非常容易造成阅读门槛。尽管原著中也是这样,但是显然即便搬到电影上,这种方法也表现的不好。

下面我来先说说反派们吧,剧情从始到终主角保罗的敌人其实是命运。按照小说中强烈的宿命论的特性,保罗一开始就在拒绝成为救世主,在遭受家族灭亡后也如此,其实他在反抗的就是自己命运。保罗是一个可以看到未来的主角,他在明知自己的命运的同时也在反抗它,但是显然反抗不了。于是后面保罗开始接受并利用命运。那么这里的命运具象化的表现出的敌人是谁呢?是的,无论是写小说还是拍电影都得有这么个具象化的反派,不让观众看什么呢。首先是帝国皇帝和哈克南家族的联手阴谋,阴谋的目的是消灭保罗所在的厄崔迪家族。阴谋的具体方法是传圣旨将香料星球厄拉科斯行星的管理权从哈克南家族转移到厄崔迪家族,作为地方诸侯的哈克南家族肯定不会放弃香料星球,于是势必会发生两个家族的战争。在战争中,皇帝在暗中派遣自己的军队帮助哈克南家族夺取战争的胜利并消灭厄崔迪家族。所以明面上,作为保罗的复仇对象,显然有两个对象,即哈克南家族和帝国皇帝。然而幕后还有两个势力,一个就是贝尼杰瑟里特姐妹会。这个姐妹会的势力在90代人类繁衍史上就已经开始渗透进宇宙的各个角落里,甚至包括厄拉科斯行星。弗雷曼人信仰中的救世主和圣母就是姐妹会的遗产。所以我们可以理解,姐妹会在各种政治平衡和势力平衡中始终是超然的存在。就像保罗的母亲是姐妹会成员,帝国皇帝的女儿也是姐妹会成员,从立场上讲无论谁胜利还是失败都无关姐妹会,她都会是胜利的一方。但是保罗的存在打破了姐妹会的计划。前面说了因为姐妹会的地位超然,那么姐妹会到底要什么呢?从剧情上讲似乎是打造一个完美的救世主来引领人类。其实不是,姐妹会的真正的目的是能够深度影响各方势力,她们一直也是这么做的。打造救世主只是一个幌子,打造一个受姐妹会控制的救世主才是真正目的。那么现在救世主有了,就是保罗,但是保罗不受姐妹会影响,于是姐妹会站在了保罗的对立面。剧情中的菲德罗萨哈克南,也可以是救世主或者说是未来救世主的父亲,而且受到姐妹会控制,所以姐妹会支持他。说到这里,电影中的全部反派都有了,希望能够帮助你理解剧情。

此外,还有一个小说中存在,但是在电影中着墨很少的势力,宇航公会和宇联公司。有些地方的解读说宇航公会的势力非常大,就连沙丘世界的纪元也是以公会为标准。但实际上我的理解这个势力是一个顽强中干的存在,表面上他们控制着整个宇宙航路,为所有可以在宇宙中航行的星舰提供导航。但说到底,他们只是一个没有武力的公会,他们需要各大家族供养,需要源源不断的香料。所以说到底他们只是一群有着独门绝活的人的群体,谁当权就依靠谁,谁当权就服务谁。而宇联公司本来就是各大家族共同管理的公司,用来分配宇航公会的服务。

左半红印创作于2024.03.26th

Copyright © 2008-2025
Powered by WordPress
Use theme BlackCooler
Created by Redonleft
鄂ICP备19016979号-1
川公网安备51011202000667