19游戏网 > 游戏攻略>正文

我的世界幽灵方块详解关于幽灵方块的研究分析

来源:19游戏网编辑:网络转载更新时间:2016-12-09

  我的世界幽灵方块详解 关于幽灵方块的研究分析。那下面给大家介绍的则是我的世界游戏中的幽灵方块哦~那下面就带啊大家详细的认识一下什么是幽灵方块吧!有想要了解的玩家点我查看吧!

  游戏园我的世界官方群:325049520  256070479 欢迎各路喜爱我的世界的小伙伴们加入讨论!

  玩服务器的小伙伴们可以加入:141931866 群一起联机玩游戏哦!

  如果你是腐竹的话可以给我们投稿你的服务器哦~投稿地址点我进入

  如果你有心仪的作品或者心得分享的话,欢迎来游戏园投稿,大家可以点击>>>投稿<<<进行投稿哦~ 有奖品哦~

  一、什么是幽灵方块

  mc有两个部分,客户端和服务端。客户端和服务端共同完成了游戏的算法。服务端和客户端各有分工:服务端需要计算实体的行为,客户端需要渲染GUI。每个世界都会有一个服务端作为终端,发送Packet(包)来和客户端交流。至于Packet怎么实现,是通过网络(多人游戏)还是通过本地(单人游戏)来交流就不是游戏这个层面需要管的事情了。为了节约IO资源,mc需要尽可能地减少之间的通讯。于是客户端和服务端分别进行运算,只在必须的情况下才会传递信息,进行同步。幽灵方块就是在同一位置上,服务端和客户端不同的方块。为了节约版面,我们把幽灵方块称为 G方块,客户端称为C,服务端称为S 。幽灵方块在客户端和服务端的值分别为G方块的C值和S值。

  二、幽灵方块的产生

  G方块四处存在。在任意一个方块同步的包没有发送到C时,这都是一个G方块。不过有时,方块更新并不会产生一个方块同步。这点是程序员可控的。

  制造幽灵方块会有很多可能的方法,只是许多方法我们并不知道而已。最简单粗暴的如写mod,强制在S设置一个不同步到C的方块,或者直接在C设置一个方块,都可以完成这一点。

  利用活塞是最普遍的方法了。为了节约资源,S的活塞并不同步方块更新,而是同步一个叫做方块事件的东西,让C自己完成推出的计算。在这个计算过程中可能会发生时序等的一些差异,导致幽灵方块的产生。这也是我们将会重点分析的一个部分。

  另外,我猜想通过区块加载的某些方式可以使S认为这个方块更新不需要同步到C。不过还没有实验。

  在研究活塞的行为是如何导致G方块产生的,我们需要先理解游戏的微观时序和活塞的微观行为。

  S端每tick更新的时间轴如下:

  Next Tick Entry(NTE)

  PlayerManager Update(PMU)

  这个是我新加的项目,主要负责区块和同步的管理等,卸载区块就是在这里执行的。S端在这一tick中,每个区块(Chunk)需要进行方块同步的位置都会按照顺序添加在一个数组里,在PMU统一发送Packet给C。

  语文老师:这里的“数组”是这篇文章的一个伏笔!高!实在是高!

  注:不要在意上一句话...老实说我觉得PlayerManager这名字起的不好

  Block Event(BE)

  Entity Update 为了不要和工业mod里的电力单位(Electric Unit)搞混,就不要简称了...(雾)老实说我觉得这个成员在幽灵方块的生成中起不到影响,不过为了方便以后修改,就加上了。

  Tile Entity Update(TEU)在这里,由于我打“Tile Entity”和“Tileentity”都看着不顺眼,于是就玩个简称吧..用于方块存放特殊数据,或者在每个循环执行任务。被活塞推出的方块会变成36号方块,其中存放了一个TE。在每个TEU,应该被推动完成了的36号方块就会变成原方块。

  没错,这5个重要的成员就是我们研究G方块的生成必不可少的元素了。

  接下来是活塞的具体行为。由于不好描述,本文将由伪代码的形式形容。对于36号方块(推动中的方块),清除的意思是把它变成正在推的那个方块。

  checkForMove(当活塞收到更新时调用,只由S执行){

  判断自己是否有信号和自己的状态,如果是有信号的收回态,调用addblockevent。如果是无信号的推出态,先设置自己为收回态(更新,同步,再调用addblockevent。

  }

  addblockevent{

  在一个列表里按顺序添加方块事件,但不会重复添加相同的事件(推出和收回不算相同)

  }

  tick(S世界主循环节选){

  依次调用对应方块的onblockevent received,如果它返回了true,则把一个表示blockevent的包发送到C,让C调用onblockeventreceived

  }

  onblockevent received{

  只在S执行{

  如果要伸出但是没信号,返回false

  如果要收回但是有信号,返回false,并把状态设置为推出态(同步到C)

  }

  若要推出{

  调用domove,如果domove返回了false,则返回false

  设置为推出态(同步),再返回true

  }

  若要收回{

  清除原来活塞臂的位置的方块

  把自身设置为36号方块(同步)

  如果这是粘性活塞{

  如果将会拉回的方块是36号方块,把它清除掉

  如果前面的方块是可以移动的,调用domove

  }否则,把活塞臂的位置设为空气(同步)

  }

  返回true

  }

  domove{

  如果要收回的话,把原来的活塞臂位置设为空气(同步)

  计算将要移动的方块和将要掉落的方块。如果不能移动,返回false

  把所有将要掉落的方块设置为空气(同步),然后掉落。

  把所有将要移动的方块设为空气(同步),即将移动到的位置设为一个36号方块(不同步)

  如果要推出的话,把活塞的前方设置为一个包含活塞臂的36号方块(不同步)

  }

  既然这是一个bug,我看了半天代码也没有任何思路...于是我们转变思路,采用debug的方式,从幽灵方块生成器来入手!

  这是Logdotzip的幽灵方块生成器,是最早的,也是最直观的一个。当拉杆输出下降沿时,会把钻石块以幽灵方块的形式推出,就像这样:

  不过这个东西看上去还是有点复杂。我们可以把中间这个机器拆分成左右两个部分:

  左边是G方块生成器的核心,右面只是决定了推出哪个G方块而已。

  我们发现,当拉下左边的装置的拉杆时,一个G活塞被推了出去。

  而右面的装置所做的事情呢,就是在推出两个G后(G1:C=钻石块,S=空气,G2:C=活塞,S=钻石块)把G2收回了,用了一个方法(这个方法以后再谈)消除了G2,于是只剩下G1了。所以,我们的关注点转移到了左边的装置上。

  接下来我们就是要解析左边的这个电路

  根据前文的内容,我们梳理出了这样的S时间轴。其中把向上的普通活塞称为P1,对着粘液块的活塞称为P2,推出称为+,收回称为-

  以下是电路对于活塞的操作:

  P1退激活(NTE)

  {P1激活(NTE)

  {P2激活(NTE)

  注意,P1和P2的激活顺序是不定的,但显然这并不影响幽灵方块的产生。

  接下来我们要把这个时间轴转化为活塞的行为:

  P1:EXTENDED=false(NTE)

  P1:addBlockEvent -(NTE)

  {P2:addBlockEvent +(NTE)

  {P1:addBlockEvent +(NTE)

  P1:receiveBlockEvent(BE)

  P1:EXTENDED=true(BE)

  {P2:推出(BE)

  {P1:尝试推出自己的活塞臂,但是并未成功(搞笑)(BE)

  我们发现,addBlockEvent的唯一影响就是收到BlockEvent的顺序,所以它是不需要表示的。最后那个搞笑的P1也是没有意义的。于是,我们精简成了这样:

  P1:EXTENDED=false(NTE)

  P1:receiveBlockEvent(BE)

  P1:EXTENDED=true(BE)

  P2:推出

  可以发现,在S,P1设置EXTENDED=true的时序永远比P2的推出要早。所以在S中P1不会被推出。

  那么,C是怎么操作的呢?我们将以S的时序为主线,将它向C发送的Packet标在时间轴上:

  P1:Extended=false(NTE)

  sendPacket BlockChange:P1.Extended=false(PMU)

  P1:receiveBlockEvent(BE)

  P1:Extended=true(BE)

  P2:receiveBlockEvent(BE)(上一层楼忘写了)

  P2:推出(BE)

  sendPacket BlockEvent:P2推出(BE)

  sendPacket BlockChange:P1.Extended=true(PMU)

  可以发现,因为当P1的Extended=true时,已经过了那个tick的PMU了,只好等到下一tick发送。所以P2的推出事件就抢到了P1的前面,从而先发制人地把P1推出了。

  那么粘液块是干什么的呢?C想要让P2推出,就需要让S的P2成功完成一次推出。而能黏住P1却不会被P1阻挡的方法,只有利用史莱姆块了。

  这个时间轴就是我们制作幽灵方块生成器的指明灯。只要满足这个时间轴就可以产生幽灵方块,不需要我们实际操作才能判断它是否能产生了。比如说,这个装置就是原生成器一个小小的变体:

  关于幽灵方块的生成原理就到这里了,虽然看上去简单,不知道烧了我多少脑细胞啊...

  三.幽灵方块的清除

  G方块的清除的方法极其多样。只要是服务端在原方块坐标处发送了一个blockchange包,G方块就会被同步掉。水结冰,作物的生长都会产生同步到C的方块更新。在活塞门中,最常见的设计是水流。

  下图的内容是甘蔗替换掉了G方块。

  不过,除了放置方块产生的包,还会有一些方法来引起同步.....

  1.区块同步。杨月华发现,同时推出多个G方块会清除区块内的所有G方块。于是我被启发而做了下面的实验:通过打指令在一个区块中填充了64个石头,然后G方块消失了。

  当在每次pmu同步一个区块中的方块时,如果需要同步的方块到达64个,则会产生一次区块同步,同步所有区块内的方块。G方块就这么消失了。这也是在文章开头说"数组"的原因。这个数组的长度就是64!

  不过,仅仅是64个方块,就引起了65536个方块的巨大同步,是不是太浪费了点?所以,minecraft把每16个方块分成一份,我们习惯称其为light chunk(lc)。每次只同步这个lc里4096个方块的内容。于是,y=16产生的64个方块改变就不能影响到y=0的G方块了。

  2.右键

  满足以下条件之一的右击动作可以使右击的G方块消失

  1.玩家手上拿的不是方块

  2.玩家手上拿的方块可以放置

  这里对于“方块"的定义有些区别。因为有时候,玩家并不是因为”拿着方块右键地面“而放置了一个方块,而是”拿着物品右键地面,触发物品的右击事件,放了一个方块“。蛋糕、头颅、门、床都属于这一类。

  3.其他

  当一个区块新获得一个玩家的”关注“时,会向这个玩家更新它

  好吧...”关注“是我用的最通俗易懂的词了..会意即可,不必咬文嚼字。比如重生。

  当你更新一个被保护的方块时...(不过这没什么用)

  这就是特殊消除GB的全部了。当然,你也可以直接在客户端把GB弄掉...(比如说挖)

  四.幽灵方块的特性

  G方块在游戏里是可能创造出许多奇妙的东西的。这里举一个最简单的例子:玩家落到石头上冒出了绿宝石的粒子效果

  1.活塞的推拉

  对于活塞的推拉,我们可以问一个哲学的问题:什么是推?什么是拉?

  看上去很简单。推就是活塞在上边沿所做的运动,拉就是活塞在下边沿所做的运动。

  不过有了史莱姆方块后,我们发现了一些共通的地方。

  左边活塞的伸出对于铁块来说不更像是拉吗?右面活塞的收回对于铁块来说不更像是推吗?

  对于这个问题,我们有更好的定义:对于活塞推拉运动中的一个方块,若其本身将被一个非空气方块替换,那么这就是推;反之就是拉。这样我们可以更好地描述不可推动方块或者推动掉落方块的行为。代码里的推和拉也采用了相同的算法。把两种东西想象成一种不是一件很有趣的事情吗?

  扯远了。根据以前的研究,拉会消除gb,但推不会。实际上,问题的关键在于活塞臂。

  照样,拿时间轴说话:

  S活塞收回(BE)

  s活塞臂被设为空气(BE)

  C活塞收包,收回(BE)

  c活塞臂被设为36(BE)

  C活塞收包,把36设为空气(PMU)

  可见,收回时gb的消失是因为被s的活塞臂的同步所影响。而推出时,s因为没有方块可推,不会对gb所在位置造成任何影响,便不会导致gb消失。在gb的移动中,服务端放置方块时的同步是唯一需要考虑的因素。

  比如说,对于下图这些gb粘液块,我们可以预测它们被收回的效果。这和我们的计算是相符的。对于计算它,可以基于10楼的活塞具体算法

  2.黑科技-gb粘液块电梯

  在每次循环中,客户端会给服务端传递玩家的坐标,而不传递玩家的运动速度。所以,站在幽灵方块上,玩家会不停被设置在幽灵方块上,但是因为服务端不认为有这个方块,玩家的掉落速度就不断增加。因为玩家的坐标不停被重设,也就不会因为掉到别的方块上而停止了。

  mc中实体的掉落速度是成加速度的。对于加速度什么公式我并不清楚,反正就是从0不断加速罢了...经过测试,最快速度差不多稳定在-3.9。也就是每个gt会下落3.9m。在下图中,当速度达到足够快时,玩家就会趁着数据同步的间隙触发压力板,使红石灯亮起。

  当玩家受到伤害时,服务端会把玩家的速度同步给客户端。这时候,史莱姆把玩家反弹了上去。

  可以看出,在制造幽灵电梯时,上升的高度取决于服务端中下落的速度。所以上升的高度是有上限的,测试在65m左右。要想达到这个速度,就得提供合适的延时,让弹射时玩家的下落达到极限。比如说,用下图的压力板来检测。当红石灯亮起时,速度已经达到了-3.75。再增加一点延时的话,就可以得到最高的速度了!

  目前的研究就到这里了,以后可能会补充一些其他的内容,比如关于gb的作品。欢迎大家提出质疑、疑问、脑洞、以及建议。

  我发现对于幽灵电梯还有些意思...再来研究一下

  幽灵电梯的理论上限是60格,公式一会儿发

  某些有趣的东西

  漂浮的物品展示框

  炫富机

  这个炫富机引出了我们的下一个话题:实体同步机制。为了节省资源,mc同样在c和s端分别进行运算,只在某些特殊的时刻进行同步。比如实体的消失:当掉落沙变成方块,或者物品和另一个合并时。但实体的运作是随机的,会引起可见的差异。另一点,实体在s端是以浮点进行运算的,但在发送数据包则经过运算变成了整数,精度为1/8000。所以,脑洞上是可以用这个差做些有趣的事情的。反正这个差加剧了混沌效果,导致mc必须定时对这些实体来一次同步,以确保它们的位置。minecraft有专门的类进行它。对于不同的实体也是不同的。以下将列出一个表格:

  实体名 频率(gt)

  钓鱼钩 5

  箭 20(所以经常看见箭的位置bug)

  投掷物 10

  末影眼 4

  粒子 10

  烟花 10

  经验瓶 10

  物品 20

  矿车、生物 3

  tnt 10

  掉落沙 20

  经验球 20(每次都能看见这家伙乱转,烦死了)

  悬挂物 ∞

  魔影水晶 ∞

  可以发现,有些物品是永远不会同步某些内容的(位置)。所以,只要不退出游戏,就可以做出好玩的效果。(当然频率慢的也可以)。但悬挂物不能被移动,所以造不出来,只好打一打魔影水晶的主意

  就拿这个来说吧,这是一个魔影水晶

  然后产生了几个幽灵方块以后,在左边出现了一个幽灵实体。我点它,没有任何反应。

  我拿着雪球向原来末影水晶的位置扔了一下,它变成了冰。(为了防止破坏,我取消了爆炸)

  但是由于鼠标指针的算法,客户端不会把指着的实体传递给服务端,所以客户端进行的伤害操作都是很安全的。

  只在c存在的方块,可以正常使玩家站在上面;只在s存在的方块,碰到则会剧烈地颤抖。为什么会这样呢?

  久违的更新...这是新一代幽灵方块生成器,它适用于1.8以后的任何版本,而上文的那个只限于1.8

  1.9的改变就是,活塞在失去信号后不会立即变成收回状态了,所以没法由此不通过BlockEvent控制一个活塞能否推出。我思考了半天,但没有一个解决方案...下面这个方案要感谢RacerftCraft服务器的人给出!注意,第一幅图上面的活塞是粘性活塞。

  那么,为什么这样却可以产生幽灵方块呢?

  首先,把装置简化到不能再简化。。此时,把聚精会神地盯着那个被推动的铁块,并关闭拉杆。

  变成了这样

  但是,在变化的过程中,你是否感到有些蹊跷?

  如果没有,就继续尝试并观察。知道你发现了什么地方不对为止!

  没错!你发现这个铁块到达目的地时,好像是闪现的。而不是慢慢被推过去的。

  你据此不需要去苦恼地翻阅源码,就可以大胆猜想,在客户端里,要推动这个铁块的活塞,没有行动!这个闪现,说明它是在36号方块变成铁块时,被同步过去的!

  因为客户端的活塞没有推动,所以我们可以得知,替换了原来的铁块的位置的活塞臂,也是被方块更新同步过去的。别忘了,方块更新的同步要晚1gt。趁着这时,下方粘液块一拉,幽灵方块便产生了。

  PS:在此非常感谢我的世界玩家xiaohane2的分享。

  以上就是我的世界幽灵方块详解 关于幽灵方块的研究分析。更多精彩尽在游戏园我的世界专区。

  

19游戏网整理报道

上一篇:重要的亡语说两遍炉石传说乱斗小技巧

下一篇:炉石传说艾雅怎么样青玉橙卡不二选择

相关文章

-=Minecraft|我的世界-手把手教你开服=-:[3]

我的世界怎么换皮肤

我的世界皮肤怎么用

我的世界开服!!!

iPhone版《我的世界》评测:只属于自己的天地

《我的世界》TMI让角色恒死的方法

《我的世界》CS爆破系统原理

《我的世界》等级检测器制作方法

《我的世界》枪械系统实现方法

《我的世界》1.7.2更新内容

猜你喜欢

口袋妖怪最强进化V3.0最终版图文攻略(全)

王者荣耀最强上分英雄排名玩的好就能上王者

剑网三成就党攻略那些容易快速完成的成就

梦幻西游2奇遇任务维摩诘经变图文详细攻略

绝地求生大逃杀在哪玩?steam购买下载方法介绍

王者荣耀S5赛季露娜连招改版之后真废了吗

奴隶少女希尔薇详细攻略

魔兽世界抑魔金获取方法及用法介绍

王者荣耀赵云大型攻略出装、技能及实战全教程

剑网三最全面抓马攻略套马的汉子才威武!

我的世界相关新手卡
我的世界热门文章
一周热门文章

健康游戏忠告:抵制不良游戏 拒绝盗版游戏 注意自我保护 谨防受骗上当 适度游戏益脑 沉迷游戏伤身 合理安排时间 享受健康生活

Copyright ◎ 2019 19yxw All Rights Reserved Powered By 19yxw QQ:3618073693