windy path

凌虚

服务器开发工程师
勤学苦练,年复一年

游戏服务器开发经验(五)应对复杂需求

技术文章 游戏服务器开发经验

什么是复杂需求? 在本文中,“复杂需求”指的是, 需求涉及到非常多的模块; 每个模块都有多层抽象重载; 状态变更逻辑复杂,边界情况众多,策划无法给出统一处理的方案; 要在已有的功能代码上进行开发,避免造轮子。需要在满足新需求的同时,保证之前的功能正常。 或者更简单的判断方式是,你看着代码思考的时候,发现脑容量上下文无法处理所有可预料的情况时,就是复杂需求。 为什么我们往往分不清复杂需求? 由于需求本身足够复杂,策划也是人,AI也有上下文限制,大家都无法将需求一次性分析完整 因此策划说的话 和 写的内容,可能是寥寥数语。因为很多细节策划在自己没有玩游戏,并且自己没看代码的情况下,确实无法思考具体的需求细节;策划那边也会每天思考,脑暴,过了一段时间又有新的想法。 程序这边收到的需求,可能只是完整需求的冰山一角。 直到需求慢慢地补全,在主玩法周围慢慢补全其他的需求的时候,才会发现这个需求的规模。 也就是说,当需求大到“脑容量上下文无法处理所有可预料的情况时”,我们就要有警报在脑袋里开始轰鸣,是复杂需求来了。 为什么复杂需求难以开发? 横跨多个模块,一个人是无法同时了解多个模块的业务逻辑的,一个模块之前的业务逻辑不一定适配当前的新业务,需要仔细评估是复用还是造轮子; 策划的需求可能只有一个预期的方向,但是这个方向上的边界情况可能非常复杂,需要程序来整理可能的边界,并且要做出取舍; 策划提出的需求可能是一个很特殊的方案,但是在大型项目中可能有不同的实现方式。如果贸然按照策划的思路实现,可能会带来副作用。因此需要耐心研读已有代码,领会之前的代码结构设计。 实现需求并不是终点,实现需求并提供一种可复用的机制,才是开发的正确标准。一旦过早“为了实现而实现”,会导致代码非常僵硬,并且与框架层代码脱节而难以处理各种情况。 如何应对复杂需求 在需求没有完全出来的时候,可以写一些“为了展示效果而临时开发”的代码,帮助策划在游戏内体验,寻找设计方向;但是这些代码自己心里一定要有数,只是临时实现。后续要争取时间进行优化; 需求慢慢完备之后,需要花时间站在更高的角度上分析需求涉及到的模块,分析需求中的主线脉络,对应于代码里的设计模式。而不是头痛医头,脚痛医脚,把大需求拆成小需求后,针对各个小需求自己实现自己的部分,到最后无法统一管理; 如果能够站在更高的角度上切分需求和涉及到的模块,就能针对各个模块去了解用到的部分的代码。我们并不需要完整领悟别的模块的代码,但是自己需求里用到的部分一定要心里有数 如果我们无法正确切分需求,则需要寻找需求涉及到的模块的负责人,询问他们相关需求的实现是什么样的。这里要记得,一定要说出完整的需求链路,而非单纯询问某个API。一定要让其他模块的负责人知道合适的上下文,让他们的判断来帮助我们更好的正确实现需求。 如果发现有一块代码怎么写都非常别扭,需要处理各种边界的时候,说明代码里有一部分逻辑是可以整理的。 如果需求真的很复杂,如果已经走了弯路,如果已经到了身心俱疲的情况,请务必向上反馈,争取时间。精神burnout带来的伤害是客观存在的,要好好保护自己的身心健康。 打好每一行日志。我们无法理解所有已有模块,但是我们可以靠日志了解运行的时序。 记得自测。一定要自测。哪怕是用GM指令自己构建一个环境也要自测。在复杂需求中,只有日志和游戏里的自测能够让我们确认自己的思路是否正确。 在策划自己也拿不准情况的时候,很多边界,如果不会带来严重后果,不用着急去问策划,而是可以自己先记下来。当功能开发差不多了,可以在游戏里体验时,再告诉策划,让策划边体验边思考这些边界应该如何处理。 如何使用AI帮忙 让AI帮忙分析你的需求。请记住,这里一定要把客观的需求告诉AI,而非把自己的方案告诉AI。在过去的很长一段时间里,AI无法完整领会需求,AI写的代码无法编译通过等。但是现在,opus4.6已经能够客观冷静分析需求。AI能翻阅整个项目的代码,去搜索其中它感兴趣的代码,它可以在代码仓库的角落里找到很多有用的功能,也会分析已有项目的设计模式。大多数情况下,它做的比人类更好。 让AI与你进行头脑风暴。AI不知道的是你的需求具体要实现什么。即使已将需求文档提交给它,也会产生误解。另外,它偶尔会选择“看起来最合适的方案”。这个时候就要与它进行多轮的头脑风暴,告诉它我们具体的需求和期望。 让AI帮你整理你不懂的代码模块。很多设计模式可能会将代码写的很松散,继承好几层,导致代码很难整体阅读。让AI整理你感兴趣的代码和已有的需求是如何实现的,可以加速我们对需求的理解。 应对复杂需求时的心态 如果需求已经复杂到你无法一次性想通所有场景和边界时,说明这个需求一定是多个模块互相组合的。在这种情况下,最大的敌人是完美主义,是希望“一次全做对”的想法。 不要害怕返工,不要觉得自己写的东西被删了是浪费时间。相反,正是因为有了这些歪路,才让我们找到了正确的方向。真正需要恪守的规则是,我们最后提交的方案一定要是我们能做到的最好的方案。 考虑不到那些需求的边界是很正常的事。不要因为没考虑到而自责,而是把它当做一件习以为常的事,就像家里的猫咪又去扒拉沙发,不小心把饭碗打翻一样,无法避免。 不要害怕bug很多的情况。当然,前提是你已经了解需求的主要脉络,在代码里做好了兜底处理,尽可能保证不要内存泄漏,要是真的崩了只崩自己的这个需求。bug多并不直接意味着人不行,也有可能是需求确实复杂,涉及模块确实众多,很多边界来不及考虑。 接受“人脑无法处理所有情况”的现实。如果你要思考需求,请你打开代码,对着已有代码进行思考。不要在没有代码的时候思考需求如何实现。 未雨绸缪 每一个正在服役的项目框架,一定有自己特有的兜底机制。在实现需求的时候,也许他们要的很急,你也应该多想想能否用得上那些兜底机制。 框架里一定有一些非常常用的模块,那些模块一定要多了解,多看代码。特别注意:放下评价代码的标尺,切换为“它这么写是为了解决什么?”“我能用这块逻辑吗?”的思考方式。验证方式是下一次看到某个已看过的模块的时候,在脑海里能回忆起粗略的细节,而非“它写的还可以”“我看不懂,好累啊” 在需求刚宣讲的那天,一般会有一小段时间,你既知道策划想要什么,又知道大概的模块有哪些,而且此时还没有定具体的实现细节。这个时候就是最佳的分析已有模块的时机。千万不要错过这个窗口期。 你的工作不等于你的价值 复杂需求让人最难过的一点是,随着需求会一点一点的明确,之前写的代码会不停地被删掉,仿佛他们之前不应该出现,与此同时,随着需求的清晰,需求的边界也慢慢清晰,我们会慢慢发现之前的思考都是错误的。 谁喜欢犯错呢?谁都不喜欢犯错。但是复杂需求就是这样,有一种让所有人不得不犯错的能力。即使你知道项目里各个模块的业务,你也很难一次两次就把功能做完善。更有可能的是,策划体验完之后,过来说,“我们对刷新/每次/减半/随机的理解好像不太一样” 如果你之前写了太多简单的增删改查、抽奖发奖,做的技能都是具体的某段逻辑,不需要考虑那些边界的话,可能很难想象一件事不断地挂在胸口,仔细一思考全是边界,看着需求截止日不断来临,而代码里还有很多临时实现。那一种绝望的感觉。 但是,这种绝望并非我们程序一人所致。要慢慢接受这种“胸口挂着事情”的感觉,接受“需求复杂到无法光靠大脑想明白”,而是要打开代码和AI大模型进行分析;在需求截止日之前提前预警,如实描述当前遇到的问题,需要什么样的帮助。最后,工作只是工作。 你的工作不等于你的价值。 ——《伯恩斯新情绪疗法》 我最近总有一种感觉,我坐在电脑前,看着显示器里的代码。我感觉我的眼睛和显示器之间,似乎有一堵无形的空气墙,或者是透明保护罩。我开始看很多项目里常用的底层框架和模块,静下心来思考当时是为了解决什么问题。 承认自己的渺小与无知 我曾以为大厂的程序员一定上知天文下通地理。但最让我惊艳的是他们的思考方式。我总是过早的希望得到一个结论,然后去实施。但是在大厂程序员和AI大模型眼里,需求是需要一遍遍确认的;已有代码是需要认真研读的;边界是肯定想不全的,但是要提前想;已有的代码是要复用的。他们很多决策都是依赖已有代码,他们是看着代码进行分析的。他们也许记不住某个具体函数名,一次性无法完全在心里想全所有业务边界,但却可以巧妙的通过合理的代码设计来管理热点内存数据,保证内存不泄露,正确申请、使用和释放。 我们本来就不可能理解所有模块的代码,就算是AI大模型也有上下文的限制。但是我们可以通过其他模块的配合,和自己的模块的干净维护,来保证需求的健壮,在不同的边界上执行已有的处理方式。(至少不会crash) 渺小和无知是我们人类的常态,渺小和无知并不可耻,可耻的是知道自己无知而放弃了学习,可耻的是不愿意选择正确的方式继续推进开发。

六月 3, 2026 · JonathanLin

沉浸式体验东汉末年生活 - 《真三国无双 起源》玩后感

玩后感

一直以来,我都是真三国无双系列的游戏粉丝,也是光荣的三国志系列的游戏粉丝。去年年底Steam大促时,在挑选打折游戏的我,点进《真三国无双 起源》的介绍页,听到中文配音的那一刻,鼠标自顾自的移动到了购买按钮上。 我很喜欢之前的《真三国无双7》,但我也很希望能听到中文配音的无双系列。《起源》终于是满足了我的渴望。 东汉末年分三国,到底怎么分的三国? 如果玩了太多类似《三国志》系列、《三国群英传》系列的游戏,我们很容易进入游戏,然后选一个喜欢的势力,然后开始各种内政和军事指令。而剧本这一块,通常是从184年黄巾之乱,一路到228年蜀汉北伐。当我们选择了184年,会发现曹操、刘备、孙坚已经各自拥有一支部队,有初创团队,而且都是数值怪兽(曹操的夏侯兄弟、刘关张、孙坚的程普黄盖韩当)。但184年,他们真的已经起兵了吗? 实际上他们在三国演义里,184年之前,确实是没有起兵的。大家都只是社会中的百姓,或者拥有一官半职,或者只是白身平民。 黄巾起义了,那黄巾军为什么起义? 原因是东汉末年,宦官当政,社会的正常运作出现了问题。而古时候的生产力不足,天灾人祸导致民不聊生。 在游戏里第一个剧情就是主角与关公相遇,联合黄巾军击溃收了贿赂的官军。这里也解释了“苍天已死,黄天当立”这句口号,也许一开始张角一行人是真的对社会不满,希望能有一个更好的生活。 而张角临死前对主角的提问,“接连不断的胜利而产生的贪欲,人们如何遏制这股贪念呢?”更是一个非常难解决的社会管理问题。在东汉末年,是没有正解的。 在游戏里能听到很多老百姓的闲话,从一开始的吃不饱饭抱怨朝廷,到抱怨黄巾军让大家民不聊生。这个时候大家都期待,平定黄巾之乱后,也许生活就会好起来了。 黄巾军被击败,董卓却崛起了 在黄巾军即将被击败前夕,董卓会与主角进行探讨,关于战斗是为了什么。在《真三》中,主角是肯定需要陷阵杀敌的。如果你只选择斩首,想着擒贼先擒王,那么你的累计气力会不够,经验也不够。所以主角走到这一路,刀下已经亡魂千万了。董卓问主角,你击败的那些黄巾军士兵,他们难道不是百姓吗?这个问题也是无法正面回答的问题。战场上没有退路,你死我活,这里也能深切的展示战争中的残酷。 主角会跟随曹操击败十常侍,但是董卓居然在城外等待,最后把皇帝接走,废除之前的皇帝,拥立了新的皇帝。 讨伐董卓,十八路诸侯反董卓联合军 此时,百姓会在城里抱怨董卓残暴,感叹吕布的武力强大。 这个时候作为主角,与曹、孙、刘这三个势力都合作过,并且还成为了王允王司徒的门客,自然会觉得有些五味杂陈。之前大家抱怨朝廷、然后抱怨黄巾军、现在又抱怨董卓。而反董卓联军的两场战役中,内部都有不和谐的声音,袁术会摆烂。而主角就不得不在战场中跑来跑去进行救火。真是为了战争操碎了心。 董卓被打倒,群雄却开始割据 我目前只玩到了虎牢关战役,将董卓赶出了洛阳。而孙坚无意中获得了传国玉玺。结果反董卓联军里却因为这件事,成为了解散的最后一根稻草。后面的剧情其实已经烂熟于各位三国迷的心中了。各路诸侯各自割据一方,朝廷无力管辖,汉室被架空。开始了真正的天下大乱。 切身体会当了一回东汉末年老百姓 我很喜欢在那张大地图里瞎逛。路过城池的时候会听到老百姓在闲聊,也会在酒店里收到各种书信,感觉到自己好像与这个时代交融在一起。抛开那些身世之迷,或许我只是一个会武功的老百姓,做自己觉得正确的事。早期的见义勇为认识关羽,到讨伐黄巾军,到护送王司徒,到陪着曹操暗杀董卓,自己确实也是在这个时代中随波逐流。 这是玩《三国志》系列感受不到的东西。在《三国志11》中,我只会在登庸武将和褒赏的时候关心武将的忠诚值,和他们的相性,他们在我眼里只是统治天下的工具。但是在《真三国无双 起源》里,我深切的感觉到自己有一身武功,却不得不在诸侯间奔波,为了一个美好的社会愿景而努力,却又无力抵抗天下大势。我可以在战场里骑马,一人冲进敌阵里单挑千军万马;即使在虎牢关面对吕布也毫无畏惧,我却无法改变历史的走向。朝廷无能,黄巾之乱,董卓残暴,而后面曹操也要挟天子令诸侯,最后三分天下,又有谁是赢家? 和夏侯惇背靠背蛮帅的。 她真的好美。 后来我真的有选择曹孙刘的机会 我大概不会选孙家,但是会认真感受一下曹操和刘备带给我的体验。

一月 7, 2026 · JonathanLin

怒其不争!致2025年HLTV的Top18-NiKo

杂谈 CS2 电竞评论

2025年就要过去了。野榜(HLTV)也开始干活,进行一年一度的CS2职业选手的排名。 常年Top前10,甚至排到前5的波黑步枪手NiKo,今年被排到了18名。 这无疑让人有些大跌眼镜,但是仔细想来又挺正常。今年的NiKo不再有过去的统治力。或者说他一直是这样,有他在的队伍总是起伏不定。没有起错的外号,“虾哥”这个外号绝对不是随便起的。 我只是一个关注两年CS2比赛的新人观众,太多的数据我也没有时间去HLTV翻阅,本文仅从一位普通观众视角,对NiKo作为职业选手的缺陷进行简单的观测。 本文同时也是一位NiKo粉丝的脱粉宣告。 从2024年初到2025年底,CS2的王朝更迭令人眼花缭乱。 2024年赛事回顾 NiKo在2024年上半年,哥本哈根Major依靠着运气侥幸踏过传奇组,然后四强收尾。仅在IEM达拉斯拿下一冠,且此冠军是在Hooxi不在,由雇佣兵Stewie2K临时顶替,而拿下的。 2024年G2进行人员更迭,马超和Snax的加入,让他们拿下Blast秋决和总决。秋决Bo5中结束了对NAVI的九连败,而总决更是把2024年的魔童Donk打了个3-0剃光头。 磨合得这么好的G2,在12月上海Major,有无数的中国粉丝为其呐喊,绝对的主场优势。如何? 很遗憾,NiKo带领G2倒在了上海Major的四强。 这件事最有意思的是,在上海Major开打前,社会上已经得知NiKo要离开G2,前往Falcons。 NiKo的错误:缺乏团队精神 将转会信息泄露,是一个极其错误的决定,是一个没有职业道德的选择。即使CS2赛程紧密,但每半年至少快一个月的休赛期。 对比Faze的Ropz,在上海Major前终于找到了自己世一自的状态,开出了“冲上云霄的银河战舰”,然后才完成了转会。我们不排除Ropz是否提前接触过Vitality的可能性,但是Ropz没有在赛前漏出任何转会信息,并且战斗到了上海Major的最后一回合。 对比cadian,为什么有那么多人时至今日还是喜欢cadian,正是因为他身上有一种团队精神,能够在赛前说出鼓舞人心的话。虽然后续与总监在Liquid纷纷扰扰,虽然动态防守的战术和指挥狙已经过时,但是有一段时间很多粉丝还是喜欢他,A队也还愿意再给他一次机会。 在那个NiKo锤桌子的回合,1v5最后没有完成,但显然隔壁小马受到了鼓舞,下一把马上在A1完成双杀打开局面。这就是明星选手的力量。关键局站出来,即使没有完成惊世壮举,也能给团队带来力量。 但NiKo不知因为什么原因释放了离队信号。团队的绳松了。他释放离队信号的行为,让原本拿下Major前最后一个大赛冠军的G2失去了信心。他似乎从来都不是团队里的大当家,但是又握着极高的话语权,左右着团队的战术走向。而在比赛之外,又由于他平常时华丽的瞄准,Major冠军的缺憾,悲壮英雄的故事,加上长期健身和帅气的欧洲面容,让他的粉丝越来越多。而粉丝也同时在给他和G2压力。压力、士气、战术都在影响那只好不容易磨合完毕的G2,最后过不了Faze也是情理之中。 另外,有爆料称在2023年,NiKo就已和Falcons私下进行了近半年的接触。这真的让人很难评价他是否真的愿意和G2同进共退。 2025年赛事回顾 NiKo在2025年上半年,在m0NESY还未到来时,在PGL布加勒斯特拿下了第一个冠军。参赛的队伍中没有Vitality和Spirit,但是至少也是S+赛事。但随后就再未得过冠军。 在拿下2025年首冠之后,m0NESY跟随NiKo的步伐来到了Falcons。 然后就在IEM墨尔本与Vitality大战五场,2-3惜败,而最后一张图的nuke,Falcons甚至12-6领先Vitality,最后被逆转。就算暂时把失败原因归结于磨合问题,那我们也无法解释奥斯汀Major的Falcons倒在了stage2,甚至在那个小镇B点下包5V3中被逐个击破。 黑豹Furia强势崛起,而NiKo在布达佩斯Major前最后一场大赛中,最后一局在荒漠迷城交出了糟糕的答卷,隔壁的m0NESY终于找到了自信和手感,NiKo却没法保持过去的高水平了。 NiKo的错误:对m0NESY太过宠溺 在各路媒体和自媒体的叙事中,我们总是听到所谓“NiKo看到m0NESY,仿佛看到年轻时的自己”等类似的表述。 但是这真的是一件好事吗?m0NESY真的成长了吗? 2022年的m0NESY那飘逸自信的打法,到2025年已经很少见了。这其中确实有CSGO到CS2的变革,但是ZywOo和s1mple依旧能发光发热,却没有像m0NESY那样不稳定。 NiKo在潜移默化中把自己性格中的缺陷,慢慢地转移到了m0NESY身上。 这确实是我的猜测,但是从数据上看,2024年上半年的G2唯一当人的m0NESY,和下半年失恋分手的m0NESY简直是两个人。而2025年更甚,上半年因为NiKo一句“hide”而获得隐形人的称号,然后在布达佩斯Major前终于找回状态大杀四方,网友们像失忆了一样,忘记了四个月前大家还在玩hide梗。 这就是m0NESY,在NiKo身边学会了极致的瞄准,也学会了状态波动。 NiKo在Falcons的比赛中,几乎只与m0NESY有互动。在Falcons,他不在有自己的表哥,也不再有自己最信赖的指挥Hooxi,整个队伍被切成两块。这就是为什么他们很多战术打不出来,就妄图增加火力解决问题。 NiKo的错误:来到Falcons话语权太高,但又不管赛训 2025年的比赛已全部结束,我们可以得到一个结论:Falcons的赛训组甚至不如G2。G2时期的Hooxi和Snax承担了非常多的战术任务,NiKo当时还没有那么高的话语权。但是到了Falcons,在年中居然曝出“无电脑训练”的笑话,在休赛期选择与m0NESY来中国圈米,而白白错过宝贵的团队磨合时间。当我听闻他要来参加“盐城Major”,作为粉丝真是怒其不争,奥斯汀Major stage2的耻辱收场,难道不应该回去好好反思吗?而且同时存在没有团队精神的问题,他至少可以带上kyxsan,TeSeS和kyousuke一起过来打个表演赛,一起品尝中国美食,给大家都涨涨粉丝,但是他也没有提出这个想法。 NiKo的错误:没有纪律性,打法严重落后这个时代,火力也无法保持 在Hooxi指挥时期,NiKo少见的服从Hooxi的调配,甚至你能看见Hooxi不停说教的场面。到了Hooxi火力衰弱,换上Snax,再到kyxsan,你肉眼可见能看到两位新指挥的窘迫。新来的CS2观众越来越多,所有人都在举着NiKo,m0NESY的牌子,队内地位不足的情况下,很难真正完成战术配合。s1mple和ZywOo为什么最终能有统治力?一方面是他们手握最强武器AWP,另一方面他们都选择了团队,21年的s1mple终于磨平棱角融入NAVI,而ZywOo更是对apex言听计从。但是NiKo不是这样。他表面上总是在采访中说一些会努力会加油的话,但是实际上又没有跟随队友打出非常有纪律性的配合。G2时期就已经有过多次小镇多打少被翻盘,到了Falcons更甚。而他性格中的软弱让他在重要时刻只相信自己的瞄准,偏偏他又在一个全部围绕他建队的石油佬队伍中,他能够拿到CT方的指挥权,然后发挥失常。他会在队友杀穿的时候开始虾,而现在年纪终于开始拖累他的反应,他越来越无法在团队需要的时候站出来。 然而他所在的队伍里已经很久没有打出优美的道具覆盖配合了。他们也许练过,但是到了关键时刻还是希望依靠队伍里的明星选手硬解。硬解,就意味着放弃了轻松的路,选择消耗精神力去得分,这样在长时间的比赛中必然会更加疲惫。所以你会听到NiKo在第四局说自己要睡着了。 而有意思的是,在G2完成换血之后,表格Hunter带着G2居然在强者如林的2025年也拿下了一个冠军,BLAST 伦敦公开赛 2025 决赛,甚至面对的是上半年如日中天的Vitality。G2变得纪律了起来,依靠对Vitality的针对进行得分。即使队里不再有顶尖明星选手,比NiKo更年长的Hunter还是承担了责任。 杜兰特?Uzi?抱团?软脚? 当有不看CS比赛的朋友问起NiKo类比NBA、LOL比赛的谁,我们总是在沉思之后说出两个名字,凯文杜兰特和Uzi。 但今年看完比赛之后,我认为NiKo既没有凯文杜兰特独步天下的射术和硬解能力,也没有Uzi巅峰时从S3到S9在下路的统治力。 2018年杜兰特在金州勇士拿到第二个冠军,而2018年NiKo也选择去Faze组建银河战舰。关于抱团,他们是一样的。但很可惜的是,NiKo的性格和关键时刻的硬解能力根本无法做团队里的大当家,却长期拥有大当家的粉丝数和权利。而杜兰特虽然性格也有缺陷,但是能在勇士完成硬解,甘愿当库里身后的二当家。即使杜兰特身负太多争议甚至骂名,但他最后抓住了自己的巅峰期,拿到了NBA总冠军。NiKo在2025年已经尽显老态,不得不承认他真的要离开自己的巅峰期了。 而NBA另一位著名软脚虾是詹姆斯哈登。虽然哈登也有夜店王子的称号,身材管理也一直是波动的,但是哈登近年来一直在寻找合适的团队,今年还能拿下50+的得分表演。而NiKo肉眼可见的越来越软弱,在关键时刻越来越查无此人。Vitality在下半年也有一段时期非常挣扎,但是我们肉眼可见ZywOo和Vitality从未低头放弃,整个团队虽然有噪音传出,但是大家还在咬牙努力,最后完成了Major连冠。 结语 2025年,在Falcons的NiKo最终真的成了一位大少爷,他潜移默化地影响着m0NESY职业生涯,他的能力在慢慢下滑,他不再是最顶尖的那批选手,观众们已经很久没有看见他在大赛时关键时刻的硬解能力。 由于话语权过高而队伍中的指挥无法完成现代的战术,过于依赖个人能力,而他终于到了能力下滑的时候了。 粉丝过多、石油佬的赞助,让他不需要真的拥有Major冠军就能轻松得到财富。 同时缺乏团队精神,使他即使拥有丰富的CS比赛经验,他也不愿意潜心研究各大战队战术,无法真的主动坐到团队正中央完成指挥任务。他一直以来,从头到尾都只相信自己的瞄准,正如他出道时那样,从没有变过。 关于解说玩机器说过的“NiKo最终会拿到Major冠军,只不过是以指挥的身份。”我过去也相信这句话,但我看完了布达佩斯Major,仔细回顾这两年NiKo急剧下滑的速度,各种性格缺陷和能力下滑的情况,我认为他已经无缘Major冠军。 我已无法喜欢这个没有Major冠军,屡败屡战的英雄故事。我也无法再继续关注NiKo的比赛。当卸下NiKo和他的故事滤镜,会发现NiKo的CS并不优美。而2025年的ZywOo,展现出了一位明星选手应该有的风范,他有志气,谦逊,努力,团队,并且有一颗大心脏。这才是我们大家应该喜欢的职业选手。

十二月 27, 2025 · JonathanLin

Linux家用服务器维护指南

技术文章 DIY折腾

2025年,对绝大部分普通人来说,真的没必要折腾家用服务器。除了安装好的那一刻感到的快乐之外,剩下的就只有吃灰和浪费电而已。 但是这却是一次难得的和Linux亲密接触的机会。如果你感兴趣,那么玩玩也不错。 标题中“家用服务器”指的是什么 本文中探讨的家用服务器,指的是购买的小型主机设备(Intel NUC系列等),自己安装操作系统进行使用的服务器。不包括群晖等成品NAS设备。 用户购买小型服务器,在上面安装Linux系统,然后自己安装各类服务,自己管理端口,内存,磁盘,自己进行运维。 一般人的家用服务器无非用来做两件事: 照片存储 下载4K超高清无删减电影 程序员可能会多做几件事: 部署自己的git私有仓库 定时任务执行自定义脚本 在线电子书(有些技术类电子书真的只有影印版pdf,临时想看还要下载,很麻烦) 极客玩家可能会多做几件事: 部署游戏服务器私服(幻兽帕鲁等) 养宠物的朋友可能会多做几件事: 将家用摄像头的录像上传到自己的服务器永久保存 以下是各种建议 建议一:一定要用Docker进行部署 既然选择了自己维护,那么你大概率下载到的都是开源的软件。而这些软件的开发人员的想法是不一样的。 有的程序员喜欢通过全局变量的方式控制软件,有的程序员只建议用特定的方式启动软件等等。 而且安装的方式也不一定是规范的。比如有的软件允许你用root安装,在没有经验的时候你可能会这么做,而有的软件在文档里强烈建议你为它的软件建立一个用户组和用户。你可能这个软件跟着文档安装在了/usr/local里,但是下一个软件可能放在/home/用户 下。而这会让未来的你一头雾水,毕竟这台服务器一般不会连上去使用。 而docker提供了一种更优雅的方案,每个软件都运行在自己的容器中,容器里有自己独立的变量和目录。然后你可以在docker-compose.yml中指定容器内端口对应的服务器端口,容器内目录对应的服务器目录等。另外,如果你运行的软件都需要用数据库,那么你可以用容器安装一个数据库,比如MySQL8,然后定义一个数据库的容器network。其他软件的容器可以访问这个network。 比如,我的gitea的docker-compose.yml内容如下: services: gitea: image: docker.gitea.com/gitea:1.24.0 container_name: gitea restart: always ports: - "13300:3000" - "13022:22" volumes: - /data/gitea/data:/data - /etc/timezone:/etc/timezone:ro - /etc/localtime:/etc/localtime:ro environment: - USER_UID=1000 - USER_GID=1000 - GITEA__database__DB_TYPE=mysql - GITEA__database__HOST=mysql8 - GITEA__database__PASSWD=gitea123 - GITEA__database__NAME=gitea - GITEA__database__USER=gitea networks: - mysql8_database_network networks: mysql8_database_network: external: true 而我的MySQL8容器的docker-compose.yml内容如下: services: mysql8: image: mysql:8....

十二月 6, 2025 · JonathanLin

游戏服务器开发经验(四)避免写Bug的习惯、技巧和心态

技术文章 游戏服务器开发经验

编写此文的目的,并不是教大家如何写出没有Bug的代码。 没有Bug是不可能的。 话虽如此,但是我们完全可以在开发阶段,避免一些低级的Bug。笔者在游戏上线后维护服务器的时间较长,我发现线上所谓的严重问题,真正出问题的代码就是那么几行(一般不会超过10行)。也就是说,这些容易出问题的部分,并不是系统中复杂的部分。因此,我们一定有办法在事前对其进行规避。 我认为避免Bug需要我们有良好的开发习惯,和冷静耐心的心态。于此之上,再通过经验加以一些技巧,就可以避免很多大小Bug了。其中,我认为最重要的是习惯。好的习惯不会让你多花太多时间,但是能尽早发现问题。 习惯和技巧 自测 自测,即代码编写结束后,在本地或开发环境中运行,然后通过白盒或者黑盒的方式测试自己开发的代码。 在本地开发时,务必拥有一个开发环境,这个开发环境可以测试自己正在开发的、还未合并到主干的代码。有了这个环境,你就可以快速地将自己新开发的内容运行起来。如果可以Debug查看每一行的结果就更好了。 自测的意义在于,你可以成为自己代码最早的测试人员,验证自己的思路是否真的被正确开发。自测能给你一个机会,让你执行自己的代码,并且能让以下容易遗漏和犯错的部分得到快速验证: 仔细检查if语句的逻辑判断是否正确 检查玩家数据状态是否正确改变 注销后再登录,即可检查玩家数据是否正确写入 如果你的环境不允许你打断点,或者一些情况比较复杂(多线程环境或有延时函数等),你可以在本地多打一些debug级别的日志,查看数据的处理过程。 Q&A 我等客户端同学开发完,联调的时候再一起测不行吗? 可以,但是在联调时你的工作重心已经到了其他地方,你会忽略或遗忘当时写这段代码的一些想法。而这些想法很有可能就是容易出错的地方。另外客户端同学一般只会测自己感兴趣或者担心出问题的部分,他们关注的部分不一定和你一致。 要是我都写正确了,自测不就是浪费时间吗? 不。我们人类一定会犯错,即使我们逻辑写对了,也有可能会把诸如道具产销日志等一些不影响功能,但是运营、策划需要的部分遗漏,也有可能会忘记打warning日志或者error日志,或者是发现一些变量名不合适,或者是重新回看的时候发现代码结构冗余臃肿。这些都是值得修改优化的点。如果我们不自测,那么可能未来就没有时间拿来安排自测了。 服务器开发逻辑的时候,没有现成可用的客户端包进行测试,自测很麻烦。 是的,很麻烦,但是并非毫无办法,接下来会介绍一些自测的技巧。 自测的技巧 对于简单的客户端和服务器交互的接口,可以想办法在客户端手动输入协议号及协议结构,发送指定的协议数据,然后在服务器打Debug断点进行检查。 对于玩家数据经常变化的新功能,可以在数据变化推送的时候打印debug日志,通过日志来确认玩家数据正确性。 对于情况比较复杂的功能,可以先写一些私下用的一次性gm,先模拟复杂的情况,然后再进行目标功能的测试。、 总之,只要你想测到你的功能,在环境允许的情况下,一定有办法测得到。 变量及函数命名技巧 表示某事的次数不要用Times,而是用Count。原因是Times容易和Time混淆,无法一眼区分到底是次数还是时间 表示时间长度不要用Time,而是用Duration。因为“时间”这个概念本身就有歧义,可以表示某个时刻,也可以表示某一段时间。建议用Time甚至Timestamp,TimeMillis,TimeSeconds来具体指代某个时刻的时间戳,用duration来指代时间段。 如果针对某个对象要设置某个属性的值,并且设置时还要对其有特殊逻辑,并且项目中已经装了lombok依赖,则最好不要再命名setXXX(),因为这样会重写lombok的@Setter省略的函数,并且容易让阅读者忽略这个函数内有特殊逻辑。 不要使用setXXX(),但是你可以针对这个业务逻辑,定义一个更贴合业务的逻辑,比如设置玩家积分时,同时更新排行榜上的玩家数据,则setScore()会让人误以为这个函数只是给对象里的score属性赋值,而如果是叫updateScore()或updateScoreAndRank(),则可以直观的知道,这个函数要更新积分,并且可能会更新排行榜。 代码分段 代码一定要分段写。印象中有一些书籍或者公司里的开发规范中约定,每个函数不要超过多少多少行。我想也许是担心大家把函数写得太长,可读性变差而设的规则。但是,我认为真正的问题在于可读性。在某些特定情况下,一些函数可能来不及优化,不得不写得很长,但我们至少可以通过分段和注释,对代码进行梳理。 一个好的代码分段结构,大概如下: //单行注释A:介绍接下来一小段要执行什么内容 aaaaa; bbbbb; if (c) { ddd; ..... } //单行注释B:介绍接下来一小段要执行什么内容 aaaaa; bbbbb; if (c) { ddd; ..... } //... 注意,在两段代码之间,有一个空行。这个空行很重要。他代表着上面这段代码的含义是最上面单行注释A,而下一段代码的含义是单行注释B。如此,阅读者可以很轻松地理解这两段代码到底分别执行了什么逻辑。 分段的技巧 在理清楚需求的业务逻辑后,你可以先写一个空函数,然后再函数内只写注释,不写逻辑。 public void reward() { //判断功能开启 //判断活动开启 //判断玩家传参 //判断玩家领取状态 //扣除玩家消耗 //修改状态 //发放奖励 //推送奖励弹窗 //返回成功给客户端 } 当你把这个函数需要做的事情梳理清除,简单写出注释,分段也是水到渠成的事情了。...

八月 10, 2025 · JonathanLin