Skip to content
xhdndmmPublic

About

一个用Go语言编写的高性能Minecraft服务器

Topics

Resources

Contributing

Security policy

Stars

5 stars

Watchers

0 watching

Forks

Latest commit

 

History

148 Commits

Folders and files

Repository files navigation

gmcs

一个用 Go 语言编写的高性能 Minecraft Java Edition 服务器实现(当前适配 1.21.11,协议 774)。

GitHub Stars GitHub Issues MIT License Go 1.27+ Latest Release Downloads

快速开始

从Github下载

你可以在Releases页面下载编译好的版本,下载适用于你的系统及架构的版本后直接运行即可。

手动编译

scripts/build.sh            # 构建当前平台(产物在 dist/)
scripts/build.sh --all      # 交叉编译全部常用平台
go run ./cmd/gmcs           # 运行;首次启动生成 gmcs.json 与 world/

构建产物为纯 Go 静态二进制(CGO_ENABLED=0、-trimpath、剥离符号)并默认启用 PGO(配置随仓库提交,scripts/genpgo.sh 可重新生成;PGO=off 可关闭)。 性能与产物体积数据见 PERFORMANCE.md。

配置(gmcs.json)

首次运行自动生成;缺失字段回退默认值;命令行 -listen 可覆盖监听地址。

字段 说明 默认值
listen_address TCP 监听地址 :25565
motd 服务器列表消息 A gmcs 1.21.11 development server
version_name 列表中显示的版本名 gmcs-1.21.11
protocol_version 协议号(同时用于拒绝不兼容客户端) 774
max_players 列表显示的最大玩家数 100
max_connections 最大并发连接数 256
view_distance 发送给客户端的视距(区块,2–32) 10
world_dir 地图数据目录 world
world_seed 地形生成种子(首次启动随机生成并固定) 随机
world_border_size 世界边界边长(方块,正方形,以 0,0 为中心;0 不限制) 0
game_mode 新玩家的游戏模式(survival/creative/adventure/spectator) survival
spawn_monsters 是否在玩家附近生成敌对生物 true
max_mobs 同时存在的生物上限(0 表示不生成) 8
autosave_seconds 自动保存间隔(秒,0 表示禁用) 300
online_mode 启用正版验证(通过会话服务器确认账号) false
enforce_secure_profile 强制安全档案(正版模式下校验聊天消息签名,缺失或非法签名按原版断开连接;离线模式忽略) true
session_server_url 会话验证服务基地址(在线模式使用) https://sessionserver.mojang.com
starting_items 新玩家初始物品(命名空间 ID;name 或 name*数量,数量上限 64;可写数组或单个字符串) ["minecraft:stone"]
ops 管理员玩家名列表(使用管理命令;项可写 name(等价 4 级)或 name:level(1–4);可写数组或单个字符串) []
permissions 细粒度命令权限节点(按玩家名,大小写不敏感;"*" 表示所有玩家;支持 gmcs.command.* 前缀通配与 * 全通配) {}
log_file 服务器日志文件(按大小轮转,空值只输出控制台) logs/gmcs.log
log_level 日志级别(debug/info/warn/error) info
log_max_size_mb 日志轮转大小(MiB;超过后当前文件重命名为 <文件>.1) 16
audit_log_file 审计日志文件(JSONL:聊天/命令/加入退出/击杀等,空值禁用) logs/audit.jsonl
pprof_address pprof 诊断监听地址(如 127.0.0.1:6060,空值表示关闭;仅本地诊断,勿暴露公网) ""

内置命令

进入世界后可在聊天栏使用(已通过 Declare Commands 向客户端声明):

命令 说明
/help 显示可用命令
/list 列出在线玩家
/spawn 传送回出生点
/seed 显示世界种子(需要权限等级 2)
/say <消息> 向所有玩家广播消息(需要权限等级 2)
/gamemode <模式> 切换游戏模式(survival/creative/adventure/spectator,等级 2)
/tp <x> <y> <z> 或 /tp <玩家> 传送到坐标或在线玩家(含其所在维度,等级 2)
/give <物品> [数量] 给予物品(带/不带 minecraft: 前缀;放不下时掉落,等级 2)
/time set <day|noon|night|midnight|tick> / /time add <tick> / /time query 查询/修改世界时间(等级 2)
/weather <clear|rain|thunder> [秒] 设置天气(省略秒数时按原版区间随机,等级 2)
/xp add <数量> 增加经验值(等级 2)
/clear [玩家] 清空物品栏(等级 2)
/kick <玩家> 踢出在线玩家(等级 3)
/kill [玩家] 击杀玩家(走正常死亡流程,等级 3)
/dimension <overworld|the_nether|the_end> 传送到目标维度出生点(等级 3)
/save-all 立即保存全部已加载世界(等级 3)

命令补全(Tab)覆盖命令名、/gamemode//time//weather//dimension 参数与 /kick//tp//clear//kill 在线玩家名,聊天输入时还会补全在线玩家名; ops 名单项支持 name(等价 4 级)或 name:level(1–4 级),命令树按玩家等级过滤并在执行时再次校验 (/say、/gamemode、/seed、/tp、/give、/time、/weather、/xp、/clear 需 2 级, /kick、/kill、/dimension、/save-all 需 3 级;/help、/list、/spawn 所有玩家可用)。 也可以不改 ops,而在 permissions 中按玩家授予权限节点(如 "permissions": {"Alice": "gmcs.command.gamemode", "*": "gmcs.command.spawn"}): 拥有节点即可使用对应命令,节点形式为 gmcs.command.<命令名>。

功能一览

点击展开查看详情

世界与地形

  • 种子地形(world_seed):大陆度/山脊/丘陵/细节噪声高度图(深海—平原—山地)、 河流(海平面附近的河道切口)、深板岩(y<0)、水(海平面约 Y=62)与生物群系 (雪原/针叶林/平原/森林/桦木林/深色橡木林/沼泽/沙漠/恶地/稀树草原/丛林/草甸/ 雪坡/冻峰/石峰/河流/沙滩/石岸/雪滩/海洋/深海等 24 种,按温度、湿度与海拔划分, 4×4 格分辨率随区块数据下发);群系化地表与植被(草/沙/红沙/陶瓦条带/雪/砾石、 橡树/云杉/桦木/深色橡木/丛林/金合欢/仙人掌/甘蔗/向日葵/莉花等)。 同种子同坐标结果恒定,出生点在世界边界内搜索陆地(候选列要求玩家碰撞盒 不与任何碰撞形状相交且脚下确有支撑面,栅栏/墙/箱子顶面之类的列会被跳过; 恢复存档时若位置被方块占据,会先向上推、再就近寻找可站立空位)。
  • 树叶衰减:玩家放置的树叶为 persistent=true,永不衰减;自然树叶在原木 或树叶被移除(含爆炸摧毁)时对周围 15³ 做一次“6 格内是否仍有原木”的判定, 没有则按方块战利品表掉落(树苗/木棍等)并立即消失(原版用 distance 属性 逐格扩散,最多约 14 tick,gmcs 表现为砍完即刻消失)。
  • 洞穴与矿物:3D 噪声大型洞穴(cheese caves)与随机游走隧道(worm),保留 地表密封与基岩层;8 种矿物随机游走成脉(煤/铜/铁/金/红石/钻石/青金石/绿宝石, y<0 时为深板岩变种)。观感与原版相近,但不是原版算法。
  • 多维度:主世界/下界/末地三套独立世界,按需生成与持久化(主世界使用 world/,下界/末地为 world/the_nether/、world/the_end/ 子目录):下界含 基岩地板(y=0)与天花板(y=127)、净岩、岩浆海、石英/远古残骸矿物与萤石/灵魂沙/ 玄武岩装饰;末地含主岛(末地石、黑曜石柱)、外岛与虚空。玩家所在维度随 players.json 持久化,重连恢复;跨维度切换用 /dimension 或下界/末地传送门。
  • 传送门:下界传送门(黑曜石框 2×3–21×21,打火石点燃;进入按 1:8 坐标缩放传送, 到达侧无门时自动建造出口,带冷却与音效,回程双向)与末地传送门(12 个末地传送门 框架 + 末影之眼激活后进入末地,第一次进入生成出口平台;从末地返回主世界出生点); 破坏框架会清除附近的传送门方块。
  • 区块流式加载:进入世界按由近到远发送视距内的区块;发送前用后台预生成 (8 个 worker + 请求去重)并行准备区块,预取范围比发送范围多一圈(视距+1), 跨区块移动时下一批区块已在后台就绪;跨区块移动时增量发送、超出 视距+2 卸载; 每 5 秒把距所有玩家超过 视距+4 的区块移出内存(未保存先落盘),连续超出 15 秒宽限后才真正卸载(玩家在卸载边界来回移动不会反复加载/卸载/写盘); 无玩家的已打开维度空闲 30 秒后释放全部区块(脏区块先落盘);所有玩家退出后 立即释放全部区块、区块帧缓存与区域文件句柄(未保存先落盘),跑图与空闲都 不会让内存持续增长。区块突发以 Chunk Batch Start/Finished 标记(客户端据此 调整加载速率;暂未按客户端回报速率限流)。
  • heightmap:区块数据携带 WORLD_SURFACE/MOTION_BLOCKING 高度图(方块修改 即时生效),供客户端渲染与光照使用。
  • 世界边界(world_border_size):正方形、以 (0,0) 为中心;下发官方边界包, 越界位置被拉回,生物不会生成或移动出边界。
  • 更换 world_seed 不会重建已有区块,交界处可能出现地形突变;需要全新地形时 换用新的 world_dir。

生物与战斗

  • 敌对生物五种:僵尸(追踪 32 格、近战 2 点)、骷髅(保持 3–16 格距离射箭, 箭矢 2 点伤害)、苦力怕(靠近 3 格点燃 1.5 秒引信后爆炸:半径 3 格摧毁方块, 6 格内线性衰减最多 24 点伤害与击退)、蜘蛛(速度更快、近战 2 点)、 末影人(40 点生命,被注视或受击后仇恨并随机瞬移,末地生成,掉落末影珍珠)。 被动生物三种:牛/猪/羊(白天地表草地方生成)。僵尸/骷髅 20 点生命,蜘蛛 16 点; 敌对生物在夜晚(世界时间 13000–23000)或下界/末地生成,玩家周围 24–36 格按权重 生成,直至 max_mobs;距所有玩家超过 64 格清理(服务器无玩家时不清理); 创造/旁观不参与索敌。
  • 近战生物进入 1.9 格且视线无遮挡时先抬手 0.5 秒再造成伤害;无目标时游荡; A 寻路*(地表 4 邻接网格:绕开墙壁/地形障碍、上跳 1 格、下落最多 3 格, 每 10 tick 重算;被完全堵住时随机侧移);爆炸会摧毁半径内的方块 (基岩/黑曜石等高抗性方块除外,无掉落),并对范围内生物按距离结算伤害 (可致死并走正常掉落)、击飞范围内的掉落物。
  • 昼夜循环:24000 tick(20 分钟)一天,进入世界与每 20 tick 同步世界时间; /time set|add|query 可查询与修改。无光照引擎,因此刷怪只看时间、不看亮度 (洞穴内白天不刷怪)。
  • 天气:主世界按原版 advanceWeatherCycle 周期推进下雨与雷暴 (下雨 3600–15600 tick、放晴 12000–180000 tick,雷暴同理),强度以 0.01 步进平滑并广播 Game Event 1/2/7/8;/weather clear|rain|thunder [秒] 可手动 指定。降雨只影响主世界:浇灭火焰、阻止火焰蔓延、清除玩家与生物身上的火、 滋润耕地(isRainingAt = 下雨 + 看得到天空 + 上方无阻挡方块)。 未实现闪电、炼药锅积水与积雪、群系降水类型;天气不持久化(重启后晴朗)。
  • 数值:玩家 20 点生命;玩家攻击 4 点,下落中攻击为跳跃暴击(×1.5);受击无敌帧 0.5 秒与击退;掉落物:僵尸 0–2 腐肉与稀有铁锭/胡萝卜/土豆、骷髅骨头与箭、 苦力怕火药、蜘蛛线/蜘蛛眼、末影人末影珍珠、牛皮革/牛肉、猪猪排、羊白色羊毛/羊肉; 击杀获得的经验以经验球形式掉落(僵尸 5 点,按原版拆分表拆成 3+1+1 三个球)。
  • 饥饿系统:疾跑/跳跃/攻击/受伤积累疲劳度(每 4 点消耗 1 点饥饿值);饥饿值 ≥18 时 每 4 秒恢复 1 点生命(优先消耗饱食度),饥饿值归零后每 4 秒受 1 点饥饿伤害(最低到 1); 长按右键 1.6 秒完成进食(切换槽位/松开使用键中断),恢复饥饿与饱食度 (数值来自官方物品数据,共 44 种食物)。
  • 经验与经验球:击杀生物掉落经验球(原版拆分表 2477/1237/…/3/1;同值经验球 合并计数);经验球有重力、水中上浮、岩浆弹跳与 8 格内追踪玩家(加速度方向 归一化 × (1−√距离/8)² × 0.1),玩家靠近后自动拾取(拾取动画 + 经验条同步); 玩家死亡掉落 min(等级×7, 100) 点经验球;经验随玩家数据持久化、死亡清空(同原版)。
  • 反馈完整:挥手/受伤闪红/死亡动画、Damage Event、音效、生命/饥饿/经验同步、头部朝向广播。
  • 生物持久化到各维度世界目录的 entities.json(主世界 <世界目录>/entities.json, 下界/末地为 the_nether/、the_end/ 子目录;位置/生命/朝向、掉落物与飞行中的 箭矢(含速度/伤害)),重启后恢复。
  • 远程武器与盾牌:弓(主手/副手)蓄力 1 秒满蓄力,释放时按蓄力发射箭矢 (箭速 3 格/tick、伤害 ceil(箭速×(2+0.5×力量))),消耗箭与 1 点耐久; 力量/冲击/火矢/无限/不灭附魔生效,创造模式与无限附魔不消耗箭; 箭矢命中生物或其他玩家(跳过射手本人)并结算伤害、击退与点燃; 盾牌按住右键格挡正面、不穿透 bypasses_shield 的伤害,按 1+floor(伤害) 损耗耐久(不灭可免除),盾牌损坏自动解除格挡。
  • 护甲与附魔数值效果:护甲值与韧性来自官方物品数据,近战/弹射/爆炸/火焰/摔落 伤害按原版 CombatRules 结算(护甲吸收 + EPF 上限 20);护甲每次受非穿甲伤害 损耗 max(1, 伤害/4) 耐久;保护/火焰保护/爆炸保护/弹射保护/摔落保护、锋利/ 亡灵杀手/节肢杀手、击退、火焰附加、抢夺、效率、水下速掘、精准采集、时运、 不灭、经验修补、绑定/消失诅咒均已生效(数值展开自 1.21.11 附魔数据)。
  • 经验球随维度目录的 entities.json 保存 Value/Count/Age/速度,重启后恢复 (未拾取的经验球不再丢失)。
  • 限制:生物寻路为地表模型(不考虑头顶净空与水中游泳;末影人瞬移为随机尝试)、 爆炸无方块掉落、无光照引擎、无状态效果/药水效果;完整列表见 TODO.md。

方块交互与玩家物理

  • 生存/创造可破坏与放置方块:修改广播附近玩家并随区块保存;生存挖掘完成后生效、 放置消耗物品;创造即时且不消耗;支持创造物品栏取放;冒险/旁观不可交互;无挖掘时间。
  • 容器交互:右键箱子/陷阱箱/木桶(27 槽)、发射器/投掷器(9 槽)、漏斗(5 槽)、 酿造台(5 槽)与潜影盒(含 16 色)打开窗口;支持取放(左/右)、Shift 快速移动、数字键交换、 创造复制、Q 丢弃、拖拽分发与双击收集;内容随区块持久化,破坏时内容掉落;潜行右键改为放置方块。 窗口在方块被破坏/替换或玩家离开交互距离时自动关闭(原版 stillValid 每 tick 校验, 含工作台/切石机/锻造台/铁砧/砂轮机/附魔台;gmcs 在每个入站数据包处理前校验, 玩家走出交互距离后的下一个包即触发关闭)。
  • 漏斗传输(对照 1.21.11 反编译的 HopperBlockEntity):每游戏刻检查一次, 把最左侧物品沿朝向推 1 个到前方容器(一次搬运后冷却 8 tick,向漏斗推送时为 目标设置 7 tick 冷却错峰);传送冷却随方块实体持久化(原版 TransferCooldown, 重启后从剩余冷却继续);上方是容器时从其抽取 1 个(按目标面规则: 熔炉上方只能进原料槽、侧面只能进燃料槽、产物槽只出不进;酿造台上方只能进材料槽、 侧面可进瓶子/燃料、下方可抽瓶子与玻璃瓶),否则收集 吸入盒(方块本格 + 上方一格,下沿 11/16)内的掉落物(整个堆叠,每 tick 最多一个); 被红石供电时锁定(enabled=false,不推不吸但仍可被其他漏斗输入或抽取); 放置朝向按点击面反方向(竖直退化为向下);内容随区块持久化,破坏时内容掉落。
  • 破坏掉落:生存模式按方块掉落表生成掉落物(石头→圆石、草方块→泥土、矿石→原矿/宝石、 黏土→黏土球、雪块→雪球、西瓜→西瓜片等);精准采集保留玻璃/冰/树叶/ 草方块/矿石/西瓜/黏土/雪块等方块本身,时运影响矿石(ore_drops)、 红石/青金石/西瓜与砂砾的燧石概率,剪刀可采集树叶/草类/枯灌木/藤蔓; 作物按成熟度掉落(小麦/甜菜根未成熟只掉种子,胡萝卜/马铃薯未成熟掉 1 个, 成熟时按原版二项分布叠加时运;下界疣/甜浆果丛/火把花/可可豆/瓜类茎/ 瓶子草与海泡菜也已按官方表实现;双格植物破坏任一半只掉落一次并移除另一半); 墙式告示牌/旗帜/火把掉落站立变体;创造模式不掉落。 掉落表尚未覆盖所有方块的完整战利品表(如生物头颅等极少见掉落; 爆炸不产生掉落),见 TODO.md。
  • 掉落物与拾取:生存/创意下 Q 丢 1 个、Ctrl+Q 丢整组(沿视线抛出);掉落物运动对照原版 ItemEntity(重力 0.04、落地反弹 ×-0.5、水平阻尼 0.98、落地摩擦取脚下方块的 slipperiness(普通方块 0.6×0.98、冰更滑)、逐轴 AABB 碰撞);水中水平 ×0.99、 缓慢上浮(5.0E-4/tick)并受水流推动;同类堆叠周期合并(跨方块边界移动时每 2 tick、 静止时每 40 tick 检查,0.5 格内、不隔墙),走近 1 格内自动拾取(含拾取动画与音效); 5 分钟消失、掉入虚空/岩浆/火/仙人掌移除;死亡掉落整个物品栏;随 world/entities.json 持久化。
  • 堆叠上限按物品数据(官方 minecraft:max_stack_size,如雪球 16、工具 1), 背包合并/容器点击/创造物品栏/掉落物都按实际上限处理。
  • 玩家装备槽(对照 1.21.11 的 InventoryMenu/ArmorSlot 与官方 minecraft:equippable 组件数据):盔甲 4 槽只接受对应部位的装备 (头颅/南瓜等可装备物品也行,槽位上限 1),副手槽不限物品; Shift 点击可装备物品在对应装备槽为空时会直接穿上,否则退回主背包 ↔ 快捷栏; 右键不同物品的槽位按原版整栈交换;绑定诅咒在生存/冒险模式阻止从装备槽取出 (创造模式可取出),消失诅咒在死亡时销毁物品;盾牌可在主手或副手格挡 (见「远程武器与盾牌」)。
  • 合成:玩家物品栏 2×2 与工作台(右键打开)3×3 合成;配方数据驱动 (官方 recipe JSON:706 有序、304 无序、116 烹饪;支持标签原料), 结果槽实时计算,取走产物消耗原料,支持 Shift 快速合成;关闭窗口合成格归还背包。
  • 切石机与锻造台:右键打开对应窗口;切石机支持全部 254 条原版切石配方 (放入原料按原版不自动选中,点击配方列表项后才计算产物,重复取走保持选择、 输入物品变化清空选择,取走产物消耗 1 个原料;选中下标经 Set Container Property 同步给客户端高亮); 锻造台支持 12 条升级配方 + 18 条纹饰配方(模板+基底+添加物→产物,取走消耗三个输入各 1): 纹饰产物为基底副本 + minecraft:trim 组件(保留耐久/附魔等组件), 相同图案与材质重复应用无产物(与原版 SmithingTrimRecipe.applyTrim 一致); 输入槽按原版属性集校验(模板槽只接受锻造模板、基底槽只接受可锻造物品、 添加物槽只接受升级材料/纹饰材质)。两者的输入槽为窗口临时状态, 关闭窗口时归还背包(放不下则掉落)。
  • 配方书:进入世界时发送原版配方属性集(Update Recipes:7 个属性集 + 254 条切石机配方;属性集是客户端锻造槽位放入校验与配方书筛选的前提) 并下发全部显示条目(Recipe Book Add,默认全部解锁); 在物品栏/工作台点击配方会向服务端发送 Place Recipe,自动把原料放入合成格 (Shift 点击为“尽可能多次合成”);切石机 UI 的配方列表由切石机配方声明驱动。
  • 熔炉家族:熔炉/高炉/烟熏炉(右键打开):原料+燃料熔炼,双进度条 (Set Container Property),高炉/烟熏炉双倍速,熔炼获得经验, 燃料槽只接受燃料(空桶例外),湿海绵烘干时空桶→水桶, 燃烧与烹饪进度随区块保存(断线/重启后继续);燃烧时方块 lit 属性置为 true 并广播方块更新(原版 setLit),熄火后复位,因此熔炉会正常发光。
  • 酿造台(对照 1.21.11 反编译的 BrewingStandBlockEntity/PotionBrewing): 3 个瓶子槽 + 材料槽 + 燃料槽(烈焰粉,1 个 = 20 次);400 tick 一轮酿造, 完成时对每个瓶子应用配方(水瓶→粗制→效果→延长/强化/腐化,火药→喷溅, 龙息→滞留)、材料消耗 1 个并播放完成音效与粒子(World Event 1035); 全部 63 条药水配方与 2 条容器配方逐条对照字节码移植;药水通过 potion_contents 组件携带(颜色/效果由客户端从药水种类推导); 瓶子槽只接受药水类/玻璃瓶且必须为空、材料槽只接受酿造材料、燃料槽只接受烈焰粉; 方块状态 has_bottle_* 随瓶子变化更新;进度随区块保存(存储格式 v5)。
  • 铁砧(对照 1.21.11 反编译的 AnvilMenu.createResult 逐字节码移植): 右键打开修复窗口(标题「Repair」),输入槽 2 个 + 结果槽 + 等级成本属性 (Set Container Property);支持材料修复(每个材料修复 min(当前损坏, 耐久上限/4)、 成本 +1/个)、同物品合并(剩余耐久 + 12% 上限奖励、成本 +2)、附魔合并与重命名 (custom_name 组件、成本 +1;名称与默认悬停名相同时不设组件;空白输入清除已有名字)。 附魔合并(对照字节码 434-726):逐个处理添加物附魔(附魔书取 stored_enchantments、 其余物品取 enchantments):同名附魔取较高等级、等级相同时 +1 并钳制到最大等级; 附魔必须可作用于输入物品(supported_items;创造模式或输入本身是附魔书时豁免), 与结果已有附魔冲突时该附魔不生效且每个冲突成本 +1,全部附魔都因冲突未生效时 结果无效;生效附魔按 anvil_cost × 目标等级计入成本(附魔书减半、至少 1; 输入堆叠数大于 1 时成本直接为 40)。 成本 = 两输入累积惩罚(repair_cost)之和 + 操作成本,达到 40 级且非创造模式时 无法取走(纯重命名封顶 39 级);取走时扣经验等级(创造模式豁免)、消耗材料、 清空输入与结果并播放音效(World Event 1030);非创造模式 12% 概率损坏铁砧 (anvil → chipped_anvil → damaged_anvil → 拆除,事件 1029/1030,朝向保留)。 物品组件(damage/custom_name/repair_cost、附魔 enchantments/附魔书 stored_enchantments 与纹饰 trim)随槽位网络编码下发并随区块与 玩家数据持久化(存储格式追加字段均向后兼容读取);输入槽为窗口临时状态, 关闭窗口归还背包(放不下则掉落);窗口有效性校验(方块仍是铁砧 + 8 格距离 近似;原版为交互距离属性 4.5 + 4.0)。 物品耐久由挖掘(按工具 damage_per_block)与护甲受伤消耗,不灭附魔按原版 概率免除;经验修补在拾取经验时以 2 点耐久/点经验修复。
  • 附魔台(对照 1.21.11 反编译的 EnchantmentMenu/EnchantmentTableBlock 逐字节码移植):右键打开附魔窗口(标题「Enchant」),输入槽(至多 1 个)+ 青金石槽 + 三个随机选项与附魔线索(10 个数据槽:成本 3、附魔线索 3、 等级线索 3、附魔种子);书架提升选项等级(32 个偏移:外圈 x/z、y∈{0,1}, 书架 + 中点透明方块(#replaceable)才计数,上限 15);随机序列与 java.util.Random(LegacyRandomSource 的 48 位 LCG,含拒绝采样)逐位一致 (用 JDK 参考值验证);附魔选取复刻 EnchantmentHelper(等级修正 ±15%、 加权随机、互斥过滤、等级减半循环、书特例);候选筛选按 supported_items 且 primary_items 命中判定(5 个附魔限定主物品池,如锋利/亡灵杀手仅剑/矛可用、 荆棘仅胸甲;铁砧与书不受 primary_items 限制);附魔注册表与物品池由 tools/genregistries 从数据包生成(ID = 文件路径字典序,已与外部数据源 交叉验证);普通书附魔为附魔书;附魔以 minecraft:enchantments 组件 (非附魔书物品用 ID 13、附魔书用 stored_enchantments 41,注册表引用为裸 ID, 经官方服务端抓包验证)随槽位发送并随区块与玩家数据持久化(存储格式追加字段 向后兼容读取);点击选项扣 id+1 级(创造豁免)并重播玩家附魔种子; 缺口音效(block.enchantment_table.use);关闭窗口归还输入。 附魔的数值效果已生效(见「生物与战斗」的护甲与附魔段落): 锋利/亡灵杀手/节肢杀手、击退/火焰附加/抢夺、效率/水下速掘、保护类、 摔落保护、呼吸、不灭、经验修补、精准采集/时运、绑定/消失诅咒。 已知限制:横扫之刃、弩/三叉戟相关附魔(无对应武器系统)、附魔统计与进度、 钓鱼等其他附魔途径未实现;弓附魔(力量/冲击/火矢/无限)已生效。
  • 砂轮机(对照 1.21.11 反编译的 GrindstoneMenu 逐字节码移植):右键打开 修复/祛魔窗口(标题「Repair & Disenchant」),输入槽 2 个 + 结果槽(39 槽); 输入槽只接受可损坏物品或带附魔物品;同物品合并(剩余耐久相加 + 5% 上限奖励, 耐久上限取两者较大值);祛魔移除全部非诅咒附魔(附魔书清空后变为普通书, 诅咒无法移除,repair_cost 重置为与剩余诅咒数对应);不可损坏的堆叠物品 要求组件完全一致(结果为 2 个);双方附魔书不可合并(原版 maxStackSize < 2); 取走时按两输入附魔的最低成本之和发放经验球(ceil(total/2) + 随机(0, ceil/2))、 播放世界事件 1042(砂轮机使用音效)、清空两个输入;输入槽为窗口临时状态, 关闭窗口归还背包;窗口有效性校验(方块仍是砂轮机 + 8 格距离近似)。
  • 堆肥桶(对照 1.21.11 反编译的 ComposterBlock 逐字节码移植): 115 种可堆肥物品与成功率(从字节码提取,见 internal/registry/compost.go); 右键填入:空桶必定成功、其余按概率掷骰,结果通过世界事件 1500 同步 (客户端播放音效与粒子),非创造模式消耗 1 个;level 7 时使用不填入不消耗; level 7 → 8 为 20 tick 定时转换(就绪音效);满桶时使用弹出 1 个骨粉掉落物、 重置为 0 并播放清空音效;level 随方块状态随区块持久化;漏斗交互按原版 容器面规则(输入容器只允许上方插入、产出容器只允许下方抽出骨粉、 level 7 无槽位)。 定时转换本身不写入区块(原版存入区块的 scheduled tick);区块加载时会 立即扫描 level 7 并重新登记,另有周期全量扫描兜底。
  • 农业(对照 1.21.11 反编译的 HoeItem/CropBlock/FarmBlock/ BoneMealItem 逐字节码移植):锄头把草方块/土径/泥土耕成耕地(砂土 → 泥土、 缠根泥土 → 泥土并掉落垂滴根须;要求点击面不是底面且目标上方是空气), 消耗 1 点耐久并播放 item.hoe.till;作物物品按原版放置规则种在耕地 (下界疣只能种在灵魂沙),非创造模式消耗 1 个;作物随机刻按原版 CropBlock.getGrowthSpeed(3×3 耕地含水量 + 行列/对角减半)与 nextInt(25/speed+1) == 0 生长,下界疣按 1/10 概率生长;耕地随机刻在附近 有水时升到湿度 7、无水时逐级衰减、湿度 0 且上方无 maintains_farmland 方块时退化为泥土;玩家落到耕地上会按 FarmBlock.fallOn 踩踏退化;骨粉按 BoneMealItem.applyBonemeal 催熟 2–5 级(满龄不消耗)并广播世界事件 1505。 已知近似:gmcs 无光照引擎,天光近似为“上方整列无方块”,因此只有露天农田 可以种植与生长;雨天会通过 isRainingAt(pos.above()) 把耕地湿度提升到 7。
  • 末影箱:右键打开按玩家独立的 27 槽空间(所有末影箱共享同一份内容), 随玩家数据(players.json 的 ender_inventory)持久化。
  • 玩家皮肤层:其他玩家可见的皮肤层(披风/外衣/袖子/裤腿/帽子)按客户端 Client Information 设置显示(实体元数据索引 16)。
  • 玩家装备同步:其他玩家可见的手持物品与盔甲(Set Equipment,0x64): 玩家实体出现在视野时下发全部 6 个装备槽(主手/副手/靴子/护腿/胸甲/头盔), 此后变更时广播给附近(64 格内)玩家;空槽也会下发(count=0)以避免观察者 保留旧物品。编码格式对照官方服务端抓包(64 <实体> 80 <主手> 05 <头盔>, 槽位字节高位表示“后面还有条目”)。生物装备(僵尸穿盔甲)未实现。
  • 方块碰撞形状:全部方块状态的碰撞盒表(半砖/台阶/栅栏/墙/栅栏门/门/活板门/ 雪层/仙人掌/蛋糕/耕地/床/箱子/压力板等,常量取自原版实现),玩家移动、摔落与 掉落物物理统一使用形状级 AABB 碰撞(相触可贴面滑动)。
  • 方块放置形态(对照 1.21.11 反编译的 StairBlock/SlabBlock/ RotatedPillarBlock/HorizontalDirectionalBlock/TrapDoorBlock/ LadderBlock/WallOrFloorItem/FaceAttachedHorizontalDirectionalBlock): 台阶按玩家朝向放置并区分上下半格; 半砖按点击面与点击高度决定上下半格,点击同种单半砖直接叠成双半砖; 原木/玄武岩/锁链等柱状方块按点击面设置轴向;箱子/熔炉/南瓜灯/木桶/潜影盒/ 织布机/切石机/蜂箱/营火/讲台等朝向方块按玩家朝向放置(木桶与潜影盒含上下 朝向);活板门按点击面决定半格并可右键开合;梯子只能贴在侧面; 火把点击侧面时放置墙式变体;拉杆与按钮按点击面决定附着面(floor/wall/ ceiling)与朝向(墙式朝向决定它给哪个方块供电);门需要上下两格空间,放置时 同时创建两半,右键开合会把另一半同步为相同的 open 值,破坏任一半会移除 另一半且只掉落 1 个门(只有下半格掉落,与原版战利品表一致),铁门不能手动 开合;栅栏门按玩家朝向放置并可右键开合;门/活板门/栅栏门都会响应邻居红石 信号(通电打开、断电关闭,门的两半同步,powered 位随之设置); 门/活板门/栅栏门开合时广播开合音效(按材质分组:木质/铁质/铜质/竹/ 樱花木/下界木,栅栏门统一 block.fence_gate.*,音量 1、音高 0.9–1.0)。 放置形态表由 tools/genregistries 生成,只保存放置会用到的属性组合(约 35 KiB 源码), 不为每个台阶展开全部 80 个状态,避免启动内存膨胀。已知近似:台阶不做 邻居形状更新(shape 恒为 straight)、含水状态一律 false。栅栏门的 in_wall (沿朝向轴两侧有墙时为 true)与门的铰链(邻居坚固面/相邻下半格门 + 点击位置 回退,对齐 DoorBlock.getHinge)均按原版在放置时计算;放置位置或上方一格有 红石信号时,门/栅栏门直接以打开(通电)状态放置。
  • 摔落伤害:下落超过 3 格落地受伤,每多 1 格 1 点(ceil(下落−3));改由服务器端 支撑面检测(脚底碰撞形状顶面)判定落地(不依赖客户端标志),落水/游泳中断下落; 落在干草堆(×0.2)/床(×0.5)/粘液块/蜂蜜块/细雪上免伤或减伤;传送/重生/回拉后重置。
  • 移动校验:拒绝 NaN/越界 Y、单包超过 100 格与逐 tick 速度超限(允许距离 ≤10×√tick 数, 与原版一致)的位移,并检测穿墙(终点嵌入方块碰撞形状时拒绝并拉回); 潜行边缘保护(潜行不会走出支撑面边缘,沿边缘滑动)与悬空上升限制 (一次腾空累计上升 ≤1.3 格,覆盖原版跳跃弧顶约 1.2522 格;生存/冒险模式的简易飞行检测); 支持走上台阶/半砖(≤1 格高差)与水中自由上游(水中不受上升限制)。
  • 环境效果:接触岩浆受到 4 点/0.5 秒伤害并着火 15 秒(每秒 1 点火焰伤害,入水熄灭); 头部浸水 15 秒后每秒 2 点溺水伤害;站在岩浆块上每 0.5 秒 1 点伤害 (着火/氧气状态随 Set Entity Data 同步)。
  • 性能与安全:多玩家共享区块/注册表压缩帧(同区域近 100% 缓存命中; 同一区块的并发请求合并为一次编码)、区块卸载/预取/宽限策略 (见上“区块流式加载”)、保存与卸载编码不阻塞世界锁、区域文件句柄缓存; 会话级令牌桶限流(聊天/命令、移动、交互、容器点击、创造模式物品操作、 Tab 补全)抵御包洪泛;max_players 满员时按原版踢出 (multiplayer.disconnect.server_full,同 UUID 重连允许替换加入)。

红石

  • 电源:拉杆(右键切换)/按钮(按下后自动弹起:石质 20 tick、木质 30 tick)/红石块/ 红石火把(点亮时);红石线在同一网络内按“电源 15、每格 -1”衰减(多电源取最大值, BFS 重算);红石灯相邻电源或 power>0 的红石线时点亮;放置/破坏方块与切换开关后 都重算相连网络并仅广播变化的方块。
  • 组件按原版语义实现(对照 1.21.11 官方 mappings 反编译的组件类): 中继器(朝向单向、右键 1–4 档延迟、每档 2 tick、侧向二极管可锁定); 比较器(比较/减法模式、右键切换、读取容器填充度与“穿过导体方块”的容器); 侦测器(面向方块变化输出 2 tick 脉冲);红石火把(支撑方块被供电时熄灭, 60 tick 内切换 8 次后熔断 160 tick);活塞/粘性活塞(结构解算器:最多推 12 格、 粘性链与分支、DESTROY 方块被破坏、BLOCK/不可推动方块阻挡、PUSH_ONLY 不可拉取、 活塞头与基座联动、准连接 QC、推动实体)。
  • 方块强充能与连接指向:推反应/非导体表由 tools/genregistries 从反编译数据生成; 中继器/比较器/拉杆/火把的 direct signal 可把导体方块强充能(“中继器 → 方块 → 上方红石线”可用);红石线的连接方向按原版 getConnectionState 计算(含直线贯通 规则与“向机构方块供电需指向”),供电与客户端渲染同源。
  • 压力板:全部 16 种原版压力板(12 种木质 + 石质/抛光黑石 + 金/铁加权)。 检测盒为方块坐标 (1/16–15/16, 0–4/16, 1/16–15/16),与原版一致; 木质检测全部实体(含掉落物与经验球),石质/抛光黑石检测生物,加权(金 15/铁 150) 检测全部实体;加权信号 = ceil(min(数量, 上限) × 15 / 上限)(金 = 实体数、铁 ≈ 每 10 个 1 级); 松开延迟:轻型 20 tick、加权 10 tick;按下/弹起播放对应木质/石质/金属点击音效。
  • 已知差异:活塞无移动动画(原版 MOVING_PISTON 移动方块实体,本实现同 tick 落位); 计划刻无优先级;比较器不读取物品展示框(无该实体);绊线/阳光传感器等 其他电源未实现。红石灯点亮立即、熄灭有 4 tick 延迟(与原版一致)。详见 TODO.md。

火焰

  • 放置:打火石/发射器按原版 BaseFireBlock.canBePlacedAt 规则放置(目标必须是 空气且能存活),下方为灵魂沙/灵魂土时放置灵魂火;每次推进重新排程 30 + rand(0..9) tick。
  • 可燃数值表:206 个方块的“鼓励值(蔓延)/燃烧速率(被烧)”机械提取自官方 1.21.11 服务端 FireBlock 反汇编(internal/registry/fire_flammables.go), 未列出的方块一概不可燃。
  • 推进与蔓延:age 每 tick 增加 0–1(上限 15);六邻域内无可燃方块时,下方顶面 完整且 age ≤ 3 才保留,否则熄灭;有可燃方块时 age 到 15 后每 tick 有 1/4 概率在 下方不是可燃方块时熄灭;对六邻域按水平 300/垂直 250 的基数做燃烧判定,命中后 点燃(age + rand(0..4)/4)或直接烧毁,命中 TNT 会点燃 TNT;以空气为目标的蔓延 概率为 (可燃度 + 40 + 难度 × 7) / (age + 30)(群系 increased_fire_burnout 减半), 越往上越难蔓延。
  • 永燃与灵魂火:下界岩/岩浆块按维度的 infiniburn_* 标签永燃(不下雨也不会熄); 灵魂火没有 tick(不推进、不蔓延、不自行熄灭),失去灵魂沙/灵魂土即消失。
  • 玩家半径:与原版 1.21.11 一致,火焰只在 128 格内存有非旁观玩家时推进 (规则 fire_spread_radius_around_player 的默认值;gmcs 无游戏规则), 区块未加载时同样只重新排程。
  • 已知差异:无难度设置(按默认 Easy)、含水方块状态未建模、 雷暴不产生闪电。详见 TODO.md。
  • 着火(玩家与生物):站在火/灵魂火方块上点燃 8 秒(玩家在火中每 tick 额外 +1…2 tick),接触岩浆点燃 15 秒并受 4 点岩浆伤害;着火每秒 1 点火焰伤害 (受受伤无敌帧限制),入水立即熄灭;着火状态通过实体共享标志(Set Entity Data 索引 0 bit0,变化时才广播)同步,并随 entities.json 持久化。火/水/岩浆的相交按 实体碰撞盒覆盖的方块判定(收缩 1e-7,与原版 Entity.checkInsideBlocks 的 AABB 处理一致),而不是只看脚部与上方一格。降雨时也会熄灭实体着火(Entity.isInRain) 以及火焰方块(FireBlock.tick 的浇灭分支)。

日志与审计

  • 服务器日志按 log_file/log_level 输出到控制台与文件,超过 log_max_size_mb 时轮转为 <文件>.1(保留一份历史)。
  • 审计日志(audit_log_file,JSONL)记录聊天/命令/加入退出/踢出/击杀等事件, 便于事后排查;空值禁用。

多人

  • 玩家以实体互相可见:加入/退出、移动与朝向在 64 格内同步;皮肤来自正版档案属性。
  • 实体跟踪:每名玩家维护“客户端当前持有的实体集合”(生物/掉落物/箭矢/TNT/ 经验球/其他玩家),实体进入 64 格时补发 Add Entity、离开 80 格时补发 Remove Entities;维度切换与死亡重生后(客户端清空世界)自动重新下发范围内实体。 加入时只发送 64 格内的既有实体。
  • 可攻击其他玩家:伤害/受伤动画/生命同步与生物战斗一致;挥空也播放挥手动画。

移动校验与诊断

  • 位置校验:拒绝 NaN/越界 Y、单包超过 100 格的位移与逐 tick 速度超限(见上文), 并把客户端拉回服务器记录的位置。
  • pprof_address:启用后在 /debug/pprof/* 提供 CPU/内存/goroutine 分析 (go tool pprof http://127.0.0.1:6060/debug/pprof/profile?seconds=20)。
  • cmd/gmcsload:离线模式负载压测客户端(登录 → 配置 → 进入世界 → 持续移动), 输出进入世界耗时、收包量、流量与包类型分布;单机 loopback 结果见 docs/PERFORMANCE.md。

玩家数据(players.json)

  • 退出/关服与每 30 秒周期保存位置、生命/饥饿/饱和、疲劳度、氧气、着火时长、 经验、游戏模式、物品栏与选中的快捷栏槽位,重连恢复且不重复发放 starting_items;进入世界/跨维度传送/重生后发送 set_held_slot 同步客户端 选中的槽位;死亡状态同样持久化(重连后保持死亡,发送重生请求后复活); 物品按命名空间 ID 存储,跨版本可读。
  • gmcs 自定义格式(非原版 playerdata);强杀或崩溃最坏丢失约 30 秒进度。

正版验证(online_mode)

  • 启用后完成 AES-128/CFB8 加密握手并通过 hasJoined 验证账号,透传签名属性; 服务器列表与游戏内标记 enforcesSecureChat=true,玩家列表携带皮肤。
  • 聊天会话(chat_session_update):服务器保存客户端上报的会话公钥,并通过 Player Info 的 Initialize Chat 动作分发给其他玩家。
  • 聊天消息签名(enforce_secure_profile):保存会话后建立消息链,按原版校验每条 聊天消息的 RSA-SHA256 签名(签名覆盖发送者 UUID、会话 UUID、链序号、盐、时间戳、 消息与确认窗口)与消息确认窗口(offset/位图/校验和);校验通过后把签名与确认列表 转发给所有玩家(安全聊天标记),失败按原版组件断开连接 (chat.disabled.invalid_signature、chat.disabled.out_of_order_chat、 multiplayer.disconnect.chat_validation_failed 等)。
  • 已知差异:gmcs 没有 Mojang 的会话服务公钥,因此不校验会话公钥的 Mojang 签名 (原版会校验 KeySignature);ServerboundChatCommandSigned 的命令参数签名也未校验。
  • 默认离线模式:UUID 按原版离线规则由用户名推导,聊天按未签名消息广播 (与原版离线服务器一致)。

测试

scripts/test.sh          # gofmt + build + vet + 单元测试 + race
scripts/test.sh --bench  # 附加 benchmark
go test -race ./...      # 仅数据竞争检测

go run ./cmd/gmcsload -addr 127.0.0.1:25565 -players 50 -duration 20s  # 负载压测

关键路径的 benchmark 方法与实测数据见 docs/PERFORMANCE.md。

数据生成(更换 Minecraft 版本时)

# 1. 用官方服务端 jar 生成数据报告(reports/registries.json、blocks.json、items.json 等)
java -DbundlerMainClass=net.minecraft.data.Main -jar server.jar --reports

# 2. 从官方客户端 jar 与报告生成本仓库的注册表/方块/物品/食物/堆叠上限数据
go run ./tools/genregistries \
  -jar <client.jar> \
  -reports generated/reports/registries.json \
  -blocks generated/reports/blocks.json \
  -items generated/reports/items.json

目录结构

cmd/gmcs            服务器入口
cmd/gmcsload        负载压测客户端(离线模式模拟并发玩家)
internal/config     配置结构与 JSON 持久化
internal/protocol   协议包编解码(握手/登录/配置/Play、NBT、Slot 等)
internal/registry   生成的注册表、方块状态与物品 ID 数据
internal/world      区块模型、地形/维度生成、区域文件存储、世界管理器
internal/item       物品堆栈与玩家物品栏
internal/logging    日志文件轮转与审计日志(JSONL)
internal/server     服务器、会话生命周期、玩家列表与广播
tools/genregistries 数据生成器
scripts             跨平台构建与测试脚本
docs                文档(贡献指南、迁移指南、TODO、性能基准)

相关文档

许可证

MIT License

About

一个用Go语言编写的高性能Minecraft服务器

Topics

Resources

Contributing

Security policy

Stars

5 stars

Watchers

0 watching

Forks

Releases

Used by

Contributors

Languages