又是一种 Minecraft 外置登录解决方案:自行实现 Yggdrasil API

最近给 Blessing Skin 写了个插件,利用皮肤站本身的账号系统实现了 Yggdrasil API(就是 Mojang 的登录 API),然后配合 authlib-agent 这个库将启动器(基于 Java 编写的支持正版登录的启动器都行)、Minecraft 游戏、Minecraft 服务端中的 Mojang Yggdrasil API 地址给替换成了自己实现的第三方 Yggdrasil API 地址(字节码替换),从而实现了与正版登录功能几乎完全相同的账户鉴权系统。

通俗地讲,就是我把 Mojang 的正版登录 API 给【劫持】成自己的啦,所以可以像登录正版那样直接用皮肤站的邮箱和密码登录游戏(还支持 Mojang 都不支持的多用户选择哦)。这种外置登录系统的实现应该可以说是比市面上的软件都要完善(毕竟可以直接利用 Minecraft 本身自带的鉴权模块),因此写一篇博文介绍一下这些实现之间的不同之处,顺带记录一下实现 Yggdrasil API 时踩到的坑,算是抛砖引玉了。

注意:本文不适合小白及问题解决能力弱的人群阅读。

感觉我明明好久没玩 MC 了,要玩也都是玩正版服务器,但是却一直在搞这些盗版服用的东西,我真是舍己为人造福大众普惠众生啊(不

一、服务器内置登录插件

相信维护过 Minecraft 服务器(当然,我这边说的是运行在离线模式下的服务器)的腐竹们或多或少都听说过 Authme、CrazyLogin 等登录插件的鼎鼎大名吧。由于这些服务器运作在离线模式(online-mode=false,即俗称的盗版模式)下,缺少 Mojang 官方账户认证系统的支持,所以必须使用这类插件来进行玩家认证(否则随便谁都可以冒名顶替别人了,换一个登录角色名就行)。

这类插件的工作原理就是在服务端维护一个数据表,表中每一条记录中存储了角色的「角色名」、「登录密码」、「注册时间」、「登录 IP 地址」等等信息,当玩家初次进入服务器时需要通过这些插件进行注册操作(e.g. /register 命令)并在表中插入一条记录,注册完毕后进入服务器则需要输入密码(e.g. /login <password> 命令)来认证。

其实这样的解决方案也没什么不好,而且现在 Authme 等登录插件在众多的服务器中都还是主流。但是,如果你的服务器已经发展到比较大型了,或许你就比较希望有这样一个东西:

阅读全文→

Laravel 动态添加 Artisan 命令的最佳实践

虽然 Laravel 官方文档提供的添加 Artisan Command 的方法是直接修改 app/Console/Kernel.php 文件并在 $commands 属性中注册要添加的 Artisan 命名的类名(Laravel 服务容器会自动解析),但是,如果我们出现需要「动态(运行时)添加 Artisan 命令」的需求的话,就会很容易吃瘪。因为,Laravel 的文档(当然,我说的是官网上的)几乎没有提到任何关于这方面的内容。

这也是我为什么总是吐槽 Laravel 文档有些地方很烂的原因 —— 很多时候你为了实现一个文档里没提到的功能,需要去翻半天 Laravel 的框架源码才能找到解决方法(我博客的 Laravel 标签 下已经有不少这样的踩坑文了)。虽然 Laravel 框架的源码很优雅,看着也不会难受,但是在一堆文件中跳来跳去寻找逻辑浪费脑细胞的行为还是能省则省吧 :(

这次要实现的功能是在运行时动态加载自定义的 Artisan Command(更详细一些的需求就是在皮肤站的一个插件中注册 Artisan 命令,Laravel 插件系统的实现可以参考我之前的 另一篇文章)。

TL;DR 太长不看

总之先上干货,毕竟不是所有人都喜欢听我废话一大堆后才拿到解决方案的。

Laravel 5.3 及以上:

Artisan::starting(function ($artisan) {
    // 传入类名字符串即可,会被服务容器自动解析
    $artisan->resolve('Example\FooCommand');
    // 批量添加
    $artisan->resolveCommands([
        'Example\FuckCommand',
        'Example\ShitCommand'
    ]);
    // 参数必须为 Symfony\Component\Console\Command\Command 的实例
    // 继承自 Illuminate\Console\Command 的类实例也可以
    $artisan->add($command);
});

Laravel 5.2:

Event::listen('Illuminate\Console\Events\ArtisanStarting', function ($event) {
    // 其他用法同上
    $event->artisan->resolve('Example\BarCommand');
});
阅读全文→

饥荒联机版独立服务器搭建踩坑记录

最近和几个同学一起联机玩饥荒(Don’t Starve Together),虽然饥荒游戏本身就可以直接创建房间让别人加入,但还是有诸多不便驱使我去开一个饥荒的独立服务端(Dedicated Server),其中最主要的就是 ——「你退了游戏其他人就玩不了了」。

本来家里还有一个用旧主板和以前换下的配件攒成的二奶机,安装的是 Elementary OS,确实可以拿来跑饥荒服务器(以前还拿它跑过 MC 服务器),但是不幸的是,由于我直接把主板硬盘之类的一股脑塞在牛奶盒子里放在窗边还不加盖儿,一个雨后的下午,我推开家门后发现那个被我当做机箱的牛奶盒子已经开始积水了……前略,天国的 Pegatron IPX31-GS (・_ゝ・)

直接在主力机上开一个服务器也不是不行,但是我的奔腾 G3258 选手实在是带不动饥荒游戏 + 游戏服务器 + 其他杂七杂八的东西了,所以只好另觅他方,去搞一台 VPS 来开服。而且这里不得不吐槽一下,饥荒联机版独立服务器的配置要求还是比较高的,几个人的小服,再多开几个 Mod,最起码就要 1G 的内存(我那台阿里云宕机好几次,还得去网页控制台强制重启),更不要想开洞穴了。

现在我拿来开服的是免费试用一个月的京东云(Xeon-E5,2G DDR4,1Mbps 的带宽),不开洞穴,目前看起来还是没什么压力的,延迟丢包率什么的也都可以接受。网上关于开服的教程也不少了,这篇文章也不会过多赘述,差不多就是记录一下主要步骤,以及提一下可能会遇到的坑。所以,想要那种很详细的教程的同学还是绕道吧,或者翻到文章最下面的「参考链接」看看。

下面的步骤在 64 位 CentOS 7.3 和 Ubuntu 16.04 上测试通过,至于 Windows……我认为实在没有啥必要特别去写,直接从 Steam 客户端就可以打开,操作方便,也没啥坑,看看网上那些教程就可以了。继续阅读之前,我希望你能有一些 Linux 的操作基础,不然会很懵。

0x01 事前准备

首先你要有一台装了 Linux 的服务器,配置要求如下(摘自 DST Wiki):

  • 上行带宽:8KBps 一个玩家;
  • 内存:差不多一个玩家 65Mbytes;
  • CPU:没太大要求

需要注意的是,饥荒联机版的服务器对内存的要求其实挺大的,亲测只开 Overworld 不开洞穴,空载 RAM 占用约 800MB,再加上差不多 65MB 一个玩家,开 Mod 还会占用更多,所以还是要衡量一下机器的配置。

阅读全文→

我 TMD 到底要怎样才能在生产环境中用上 ES6 模块化?

Python3 已经发布了九年了,Python 社区却还在用 Python 2.7;而 JavaScript 社区正好相反,大家都已经开始把还没有实现的语言特性用到生产环境中了 (´_ゝ `)

虽然这种奇妙情况的形成与 JavaScript 自身早期的设计缺陷以及浏览器平台的特殊性质都有关系,但也确实能够体现出 JavaScript 社区的技术栈迭代是有多么屌快。如果你昏迷个一年半载再去看前端圈,可能社区的主流技术栈已经变得它妈都不认识了(如果你没什么实感,可以看看《在 2016 年学习 JavaScript 是一种怎样的体验》这篇文章,你会感受到的,你会的)。

JavaScript 模块化现状

随着 JavaScript 越来越广泛的应用,朝着单页应用(SPA)方向发展的网页与代码量的愈发庞大,社区需要一种更好的代码组织形式,这就是模块化:将你的一大坨代码分装为多个不同的模块。

但是在 ES6 标准出台之前,由于标准的缺失(连 CSS 都有 @import,JavaScript 却连个毛线都没),这几年里 JavaScript 社区里冒出了各种各样的模块化解决方案(群魔乱舞),懵到一种极致。主要的几种模块化方案举例如下:

CommonJS

主要用于服务端,模块同步加载(也因此不适合在浏览器中运行,不过也有 Browserify 之类的转换工具),Node.js 的模块化实现就是基于 CommonJS 规范的,通常用法像这样:

阅读全文→

为 Hexo 博客添加页面访问计数器

一般来说,写博客的都喜欢在页面上加上一个访问计数器,来满足虚荣心显示某篇文章或者整个站点的访问量。这种需求在 WordPress 等动态博客上都是比较容易满足的,安装个插件即可(辣鸡 Ghost 除外),但是对于小部分静态博客来说就比较头疼了。

目前来看,互联网上的静态博客访问计数器解决方案大致有这么几种:

  • 使用「不蒜子」访问计数服务;
  • 利用 LeanCloud 平台搭建统计服务。

其中「不蒜子」是个自称「永久免费使用」的极简网页计数器,仅需两行代码即可为静态博客添加访问计数功能,这种简单的解决方案也受到很多静态博客作者的喜爱。但正如我之前在这篇文章(为 Ghost 博客添加页面访问计数器)中所述,不蒜子虽然提供了 site_pvsite_uvpage_pv 等多种统计,但是其并不提供这些服务的开放 API。而我的需求是在「首页」或者其他文章列表页中的每篇文章都要显示各自的访问量,并且需要一个「最受欢迎的文章」功能(按访问量倒序排序)。很可惜不蒜子无法满足我的需求,只好将其 PASS。

至于使用 LeanCloud 的方法(详情参见这篇博文),其实是利用了这个平台所提供的「数据存储」后端功能,大部分逻辑都在前端完成,而 LeanCloud 只负责存储数据。但是,这个现成的访问计数程序也不支持输出「最受欢迎的文章」功能,只能自己实现。而且,既然我已经有了 VPS,那我为啥还要去弄个 LeanCloud 呢?

综上,我决定自己写一个网页访问量计数服务。

阅读全文→

Twitter 账号被锁定是种怎样的体验

两天前(2017-06-17),我的 Twitter 账号莫名其妙被锁定了,原因是有「自动行为」。

locked

WTF? 你特么在逗我?黑人问号

我思前想后,估计那一天关于 Twitter 我干的最值得怀疑的就是「多设备异地登录」了。具体流程如下(都是发生在 6.17 那一天,其实看我那一天被封前的推文也行):

阅读全文→

博客已迁移至 Hexo

是的,我又双叒叕换博客程序了。

话是这样说,其实也没有很频繁啦,上一次从 WordPress 迁移至 Ghost 已经是一年多前的事了。这次是从 Ghost 迁移至 Hexo,一个静态博客生成器。总体来看,我对博客程序的选择是越来越轻(zhuang)(bi)化了。

目前,本博客已经完全迁移至 Hexo,包括所有的文章和主题。不过话说回来现在回头去看两年多前写的文章,真的挺尬的,行文风格完全不一样,超尬 (つд⊂) 目前我在用的这个主题(Seventeen)已经陪了我快三年了,之前我把它从 WordPress 移植到 Ghost,现在到了 Hexo 我又把它给移植过来了,我也是爱得深沉啊(笑)

既然现在迁移完成了,我打算列举一下我迁移的理由,算是个记录。

一、动态博客的优点

动态博客肯定是有一些静态博客所无法实现的优点的,不然我之前也不会一直使用动态博客,而没有考虑过使用静态博客了。

  • 动态博客功能强大,插件众多,甚至能当 CMS 用;
  • 数据存储基于数据库,灵活性强;
  • 有管理后台,发布、更新文章等操作方便;
  • 自带的附件、站内搜索、评论系统等功能。

那我为毛要选择迁移至静态博客呢?

阅读全文→

Hexo 获取特定分类或标签下的文章

今天在将博客主题移植至 Hexo 时,想要获取某个分类(Category)或者标签(Tag)下的所有文章(准确来说是想获得文章总数),在使用中文关键词搜索时,没有获得任何有用的信息(或许是我搜索姿势不对)。换用英文关键词「hexo category all posts」后搜索到了所需的信息,遂决定写一篇文章记录一下,希望能帮到后来人。

获取特定分类下的文章

let result = site.categories.findOne({name: 'example'})

同样的,你可以这样获取特定标签下的文章:

site.tags.findOne({name: 'example'})

其中 name 指定要查找分类的名称,返回值是一个 Warehouse(Hexo 作者开发的一个轻量级数据库) Document 对象。你可以直接使用 result.length 来获得该分类 / 标签下的文章总数。你也可以用 forEach 来遍历每篇文章:

阅读全文→

让 Lumen 的 dd() 与 dump() 函数输出更漂亮

做开发的,免不了要和调试打交道。单说 PHP,有的人直接 echo,有的人用 print_r(),有的人用 var_dump(),还有的人直接上 Xdebug,用啥的都有。

如果你用过 Laravel,那你应该知道 Laravel 内置了几个很方便的帮助函数(Helper)—— dd()dump()。这两个函数都能够输出变量的值,不同的是 dd() 在输出变量值后会停止脚本的执行,而 dump() 不会。它们的使用方法可参照官方文档:Helpers - Laravel Documentation

Laravel dd() 输出示例

什么?哦,上帝!真是见鬼!怎么会有人在 Laravel 中还在用 echo + die()?好家伙,我敢打赌,他一定没有好好看文档,我向圣母玛利亚保证。如果让我看到这群愚蠢的土拨鼠,看在上帝的份上,我会用靴子狠狠地踢他们的屁股,我发誓我绝对会。

阅读全文→

给 ATH-ES55 耳机更换线材

大概是几年前(总之是我的 AM800 掉在火车上之后),我从某位 dalao 手里低价收来了 ATH-IM50 和 ATH-ES55 两副耳机。当时写的记录文章在 这里,两年前的文章,现在看起来挺尬的,行文风格差了真不是一点半点。

而且好几年过去了,这俩耳机也或多或少都出了些问题。其中 IM50 原配的线已经发硬且接触不良,官方升级线又买不起(说实话也不值),于是就去某宝买了个 DIY 升级线,用着也还算不错。

某宝订单

至于 ES55,收来的时候耳机插头就是坏的,虽然当初随便买了个插头随便焊上去了事,不过后来又重新焊了一次(当时写的博文在 这里)。然而因为 ES55 不好在学校里用(太显眼,漏音也严重),放着吃灰了几个月,前几天高考结束拿出来的时候发现它的线材都已经变得黏糊糊的了。

阅读全文→