基于 docker-dst-server 的饥荒独立服务器部署
部署饥荒独立服务器需要大量的命令行操作,为了简化部署过程,有人开源了 docker 部署的项目:Jamesits/docker-dst-server 。即便如此,依旧需要完成一些额外工作才能正常游戏,这个教程补充官方文档中缺失的一些细节。 我喜欢循序渐进,先用最少的步骤跑通整体流程、再给出进阶的操作优化游戏体验。 WARNING:教程不适合完全的新手,需要一定的 Linux 服务器运维和 docker 知识。 基础部分1. 启动 docker-dst-server首先完成 jamesits/dst-server:latest 镜像的拉取。 官方 GitHub 项目的 readme 已经给出了启动的 docker 指令: 1docker run -v ${HOME}/.klei/DoNotStarveTogether:/data -p 10999-11000:10999-11000/udp -p 12346-12347:12346-12347/udp -it jamesits/dst-server:latest 首先需要关注的部分是 $...
iOS v.s. Android,我的小众视角
引言作为一位 iOS 的老用户,同时也是一位 Android 的开发者,我一直在寻找一个从 iOS 切换到 Android 的契机。 我经常在 iOS 和 Android 之间切换,在相同的使用场景下,总是会不自觉地对比两个系统地差异,并且随手记录下来。 关于 iOS 和 Android 有一些大家公认的优缺点: iOS: 全家桶体验更好 第三方 app 质量更好 通知更好 动画更好 录像更好 周边配件更丰富且质量更高 Android: 信号更好 充电更快、电池容量更大 DC / 高频 PWM 调光更护眼 侧滑返回更好用 拍照直出效果更好 实用小功能更多(长截图、通话录音、应用双开、应用小窗) 性价比更高 除此之外我还发现了很多相对小众、但是对我来说影响决策的点。雷同的点不再讨论,分享一下我的小众视角。 Android 的优势骚扰拦截刚开始换到 Android 的时候没想到这一块儿,但是当我看到一些”广告推销“之类的电话标注,直接挂断以后突然感觉这个真方便。顺带夸一夸曾经用过一段时间的小米 13,小爱通话这个功能也很实用。 我曾经试过在 iOS 上实现类似的功能...
相伴三年,我对 AB 实验的一些感悟
什么是 AB 实验AB 实验是一个理科概念,我们将被测试的许多个体分为两组,确保两组之间的变量唯一,那么最终这两组表现出来的差异性,就是这个变量导致的。 中国互联网一直是小步快跑的节奏,为了验证跑出的每一步是否正确,需要对部分用户生效新功能,观察这些用户的指标与其他用户的差异,来判断这个新的功能是否为产品带来了收益。 AB 实验之熵:冗余的代码既然需要新功能只对部分用户生效,那么必然需要同时保留新老功能,然后通过一些手段控制代码执行时的逻辑分叉。相当于类似的功能,项目里会有多套代码来实现。这听起来似乎没什么,但是一旦实验多起来了,项目里几乎就有数倍于单个用户所有功能的代码。 海量的实验,给项目带来了海量的逻辑分叉,在这样的项目里开发,只能说是如履薄冰。不仅仅是开发者熟悉项目的成本巨大,对于测试同学来讲,测试工作量更是巨大。 这些冗余的代码,也必然让我们的编译产物体积暴涨。这也是为什么,在单个用户的眼里,很难理解一个简单的 app 安装包体积居然如此巨大。 AB 实验之熵:难以捉摸的行为如今的互联网 app,讲究一个千人千面。这已经不仅仅体现在大数据相关的一些功能上,app 本身的...
Don't Starve Together Dedicated Server 使用问题记录
如何找到启动游戏的存档路径启动 Don’t Starve Together Dedicated Server,会弹出一个 terminal,从 terminal 中最顶部打印出来的日志就可以找到游戏存档的路径: 1234567891011121314151617181920212223242526272829System Memory: Memory Load: 52% Available Physical Memory: 7669m/16234m Available Page File: 4706m/17258m Available Virtual Memory: 134213499m/134217727m Available Extended Virtual Memory: 0m[00:00:00]:Process Memory: Peak Working Set Size: 12m Working Set Size: 12m Quota Peak Page Poo...
删代码到底有多难
引言阮老师最近一期的周刊中,聊到了技术债的问题 科技爱好者周刊(第 292 期):所有代码都是技术债 下面是相关内容的节选: 所有代码都是技术债 代码是公司的资产,公司总是鼓励大家多写代码。但是,很多人(尤其是管理层)没有意识到,代码也是负债。 代码越多,债越多,这就是程序员常说的”技术债”。 今天我想谈谈,什么是”技术债”?为什么你拥有的代码太多,不是一件好事。 “技术债”(technical debt)源自著名程序员沃德·坎宁安(Ward Cunningham)的一篇文章。他写了一句话:”交付代码就像负债累累。” 你的代码一旦进入生产环境,就像背上一笔债务,将来需要不断支付利息,除非代码不再使用。 这个比喻获得了共鸣,人们把代码带来的负担,称为”技术债”。 为什么代码好比负债累累?这有两个原因。 第一个原因是,由于各种限制,代码的实现有问题,包含了 Bug,或者选择了有问题的组件,后期需要修改或重写。 第二个原因是,即使代码是完美的,但由于技术进步,它会逐渐腐化过时,后期需要不断维护和更新,这通常比原始开发成本更高。 这意味着,无论多么小心,上线的代码总是有”技术债”。 可...
面向对象与函数式编程中的 event listener
在前端开发中,使用函数式的 JavaScript 语言,所以绝大部分的 API 设计中,都会把 event listener 设计成一个函数,在对应的时机直接调用这些函数。 12345const listener = (data) => { console.log(data);};addEventListener(listener); 在 android 开发中,最早使用面向对象的 Java 语言,后续即便换成支持函数式编程的 Kotlin 语言,绝大部分的 event listener 还是被设计成了一个对象,在对应的时机调用这些对象上的成员函数。 1234567var listener = object: Listener { override fun onChanged (data) { Log.d("data", data) }}addEventListener(listener) 两者之间其实并没有什么本质上的差异,无论是对象还是函数,其实都是一个引用而...
使用 HashMap 优化数组交集计算
在面试中,计算两个数组的交集是一个常见问题。初学者可能会想到使用两层 for 循环来解决: 123456789101112const intersection = (a, b) => { const res = new Set(); for (const itemA of a) { for (const itemB of b) { if (itemA === itemB) { res.add(itemA); break; } } } return res;}; 然而,这种方法的时间复杂度为 O(n²),效率较低。为提升效率,我们可以利用 HashMap 将复杂度降低到 O(n): 1234567891011121314const intersection2 = (a, b) => { const mapOfA = a.reduce((acc, item) => { acc[item] =...



