想和基友们联机玩mc,相比于使用各种联机平台,或搭建虚拟局域网,不如自己直接开个服务器。既不用保持至少一人在线,又能避免玩游戏时需要额外运行一个联机程序的臃肿。

本文记录博主自己的mc开服经历。

工具选择与准备

主机选择——想想在把mc服务端运行在哪里

我起初有开mc服的计划时是还在上高三,没有详细了解各方面的信息,因此当时想拉上几个基友集资购买云主机,在云主机上开服。

但高考完放假之后我去了解了一下云主机的价格,还是把原来的打算作废了。

我的需求是让我的服务器 安装一些大型模组并保证十人能同时在线不卡顿。而显然价格相对低的轻量云主机(指几百块一年)难以满足。

于是我决定在自己电脑上开服。但是用自己的主力机实在感觉不妥,一来它的高功耗会导致电费的额外支出,二来心疼它二十四小时不关机

最终,我决定再组一台低功耗主机,用来开设mc服务器的同时,还能当nas用。

但是我发现,由于洋垃圾市场炒的厉害,分别购买cpu、主板、内存、硬盘配件,还不如直接购买二手整机来的划算。于是去海鲜市场(闲鱼)买了台整机。

以T结尾的intel处理器代表低功耗,正适合作为服务器使用。

到手之后重装了Windows10 LTSC,更新少,简洁、运行稳定。

游戏版本选择——求新还是经典?

游戏版本选择是我最纠结的地方,由于学业原因,我近乎三年没有碰mc,再回过来看的时候最新版本已经是1.19了,而且fabric似乎也流行了起来,越来越多的模组和资源包开始仅支持较高版本且仅兼容fabric,就连java的最新版本居然也到了17。但我更熟悉的是forge和旧版本。本想跟联机基友们共同商量,可他们也是什么都不知道。最终抱着延续初中的玩法的态度,选择了1.12.2这个时至今日已经是远古的版本。

服务端软件选择——慎之又慎

由于我此前只有建设mc基岩版服的经验,当时基岩版只有官方服务端,所以也没有什么选择。

但je(java edition)服务端不一样,各种服务端看的我眼花缭乱,最终草率地随大流,选择了Catserver(猫端)这一使用人数众多的服务端。
慎重?先开了再说,大不了redo

开服

选择好以上这些东西之后,就有了开服的方向,接下来的事情就很简单了,只需要动手去做就完事了。

配置服务端

下载与初始化catserver服务端

先在java官网,下载最新的java8。

前往catserver官网github仓库下载所需版本的catserver。

下载的是一个.jar单文件,把它重命名为Catserver.jar放入一个空文件夹,该文件夹名与路径尽量使用纯英文,避免出现奇怪的错误。

在该空文件夹内,新建一个文本文档,并写入以下内容:

java -Xmx6G -XX:+UseG1GC -XX:+ParallelRefProcEnabled -XX:MaxGCPauseMillis=200 -XX:+UnlockExperimentalVMOptions -XX:+DisableExplicitGC -XX:+AlwaysPreTouch -XX:G1NewSizePercent=30 -XX:G1MaxNewSizePercent=40 -XX:G1HeapRegionSize=8M -XX:G1ReservePercent=20 -XX:G1HeapWastePercent=5 -XX:G1MixedGCCountTarget=4 -XX:InitiatingHeapOccupancyPercent=15 -XX:G1MixedGCLiveThresholdPercent=90 -Dfml.queryResult=confirm -jar CatServer.jar

这段内容的解释:

-Xmx6G :设定服务端最大内存为6G

-XX等参数:开启G1GC和优化GC,详见此贴

然后把该文本重命名为strat.bat,双击运行该bat。

之后,猫端会自动下载所需的文件,并释放到同目录下,这样就完成了服务端的初始化。初始化完成后的目录文件如下

修改服务端配置文件

初始化完成后,需要修改以下几个文件

  • server.properties
  • bukkit.yml
  • catserver.yml
  • spigot.yml

参考这两帖,根据需求进行修改。

[服务器应用] 【优化】服务器优化指南 | 和卡顿永远说再见

[服务器应用] Minecraft服务器优化教程 —— 让多带50%的玩家不再是梦

下面是我修改后的配置文件

  • server.properties
#Minecraft server properties
#Sun Jun 19 19:24:15 CST 2022
spawn-protection=16
max-tick-time=60000
generator-settings=
force-gamemode=false
allow-nether=true
gamemode=0
broadcast-console-to-ops=true
enable-query=false
player-idle-timeout=0
difficulty=2
spawn-monsters=true
op-permission-level=4
pvp=true
snooper-enabled=true
level-type=DEFAULT
hardcore=false
enable-command-block=true
max-players=10
network-compression-threshold=-1
resource-pack-sha1=
max-world-size=29999984
server-port=25565
server-ip=0.0.0.0
spawn-npcs=true
allow-flight=true
level-name=world
view-distance=8
resource-pack=
spawn-animals=true
white-list=true #开启白名单
generate-structures=true
online-mode=flase #关闭正版验证
max-build-height=256
level-seed=
prevent-proxy-connections=false
enable-rcon=false
motd=fish world
  • bukkit.yml
settings:
  allow-end: true
  warn-on-overload: true
  permissions-file: permissions.yml
  update-folder: update
  plugin-profiling: false
  connection-throttle: 4000
  query-plugins: true
  deprecated-verbose: default
  shutdown-message: Server closed
spawn-limits:
  monsters: 50
  animals: 15
  water-animals: 5
  ambient: 3
chunk-gc:
  period-in-ticks: 400
  load-threshold: 300
ticks-per:
  animal-spawns: 400
  monster-spawns: 2
  autosave: 6000
aliases: now-in-commands.yml
  • catserver.yml
world:
  keepSpawnInMemory: false
  enableSkipEntityTick: true
  enableSkipTileEntityTick: false
  worldGenMaxTick: 15
  disableForgeGenerateWorlds:
  - ExampleCustomWorld
  preventBlockLoadChunk: false
  autoUnloadDimensions:
  - 99999999
  enableRealtime: true
  forceSaveOnWatchdog: true
  maxEntityCollision: 8
  saveBukkitWorldDimensionId: true
fakePlayer:
  permissions:
  - essentials.build
  eventPass: false
vanilla:
  fixPlayBossSoundToOtherWorld: true
  fixLessCrystalRespawnDragon: false
  preventPistonPushRail: false
  preventPistonPushSlimeBlock: false
  limitFastClickGUI: false
plugin:
  patcher:
    enableDynmapCompatible: true
    enableCoreProtectModBlockCompatible: true
    enableEssentialsNewVersionCompatible: true
    enableMythicMobsPatcherCompatible: true
    enableWorldEditCompatible: true
    enableCitizensCompatible: true
  disableHopperMoveEventWorlds: []
  defaultInstall:
    spark: true
async:
  waitForgeServerChatEvent: false
security:
  opManager: false
  gameModeManager: false
disableUpdateGameProfile: false
disableFMLHandshake: false
disableFMLStatusModInfo: false
disableAsyncCatchWarn: false
versionCheck: true
  • spigot.yml
config-version: 11
settings:
  debug: false
  attribute:
    maxHealth:
      max: 2048.0
    movementSpeed:
      max: 2048.0
    attackDamage:
      max: 2048.0
  netty-threads: 4
  timeout-time: 60
  restart-on-crash: true
  restart-script: ./start.sh
  moved-too-quickly-multiplier: 10.0
  moved-wrongly-threshold: 0.0625
  filter-creative-items: true
  bungeecord: false
  sample-count: 12
  late-bind: false
  int-cache-limit: 1024
  item-dirty-ticks: 20
  user-cache-size: 1000
  player-shuffle: 0
  save-user-cache-on-stop-only: false
messages:
  whitelist: You are not whitelisted on this server!
  unknown-command: Unknown command. Type "/help" for help.
  server-full: The server is full!
  outdated-client: Outdated client! Please use {0}
  outdated-server: Outdated server! I'm still on {0}
  restart: Server is restarting
stats:
  disable-saving: false
  forced-stats: {}
commands:
  log: true
  replace-commands:
  - setblock
  - summon
  - testforblock
  - tellraw
  spam-exclusions:
  - /skill
  silent-commandblock-console: false
  tab-complete: 0
advancements:
  disable-saving: false
  disabled:
  - minecraft:story/disabled
world-settings:
  default:
    verbose: true
    merge-radius:
      item: 2.5
      exp: 3.0
    arrow-despawn-rate: 1200
    wither-spawn-sound-radius: 0
    nerf-spawner-mobs: false
    entity-tracking-range:
      players: 48
      animals: 48
      monsters: 48
      misc: 32
      other: 64
    view-distance: 10
    enable-zombie-pigmen-portal-spawns: true
    zombie-aggressive-towards-villager: true
    item-despawn-rate: 6000
    hanging-tick-frequency: 100
    growth:
      cactus-modifier: 100
      cane-modifier: 100
      melon-modifier: 100
      mushroom-modifier: 100
      pumpkin-modifier: 100
      sapling-modifier: 100
      wheat-modifier: 100
      netherwart-modifier: 100
      vine-modifier: 100
      cocoa-modifier: 100
    entity-activation-range:
      animals: 32
      monsters: 28
      misc: 16
      tick-inactive-villagers: true
    random-light-updates: false
    ticks-per:
      hopper-transfer: 8
      hopper-check: 1
    hopper-amount: 1
    save-structure-info: true
    hunger:
      jump-walk-exhaustion: 0.05
      jump-sprint-exhaustion: 0.2
      combat-exhaustion: 0.1
      regen-exhaustion: 6.0
      swim-multiplier: 0.01
      sprint-multiplier: 0.1
      other-multiplier: 0.0
    max-tick-time:
      tile: 50
      entity: 50
    squid-spawn-range:
      min: 45.0
    max-tnt-per-tick: 100
    mob-spawn-range: 4
    dragon-death-sound-radius: 0
    seed-village: 10387312
    seed-feature: 14357617
    seed-monument: 10387313
    seed-slime: 987234911

在服务端安装模组和插件

在服务端中,有mods和plugins两个文件夹,它们分别是游戏模组和服务端插件。

游戏模组是增强和丰富游戏内容的,而服务端插件是增强服务端功能的。

需要安装的模组,都放在mods文件夹内。

在安装模组时,要看清模组是否需要在服务端安装,不需要在服务端安装的模组不要安装在服务端。(如waila高亮显示等模组)

_服务端需要装

_不要在服务端装

另外在安装模组时,还要留心查看该模组的说明,有些模组需要额外的前置模组,要一起安装(如植物魔法botania需要bauble作为前置模组,二者必须都安装)
以下是我在服务端安装的模组

而服务端插件直接放如plugins文件夹即可,可以根据需要去搜索。我曾经安装了miraimc插件,它是一个能双向同步mc服务器和qq群消息的插件,但由于性能和兼容性问题又把它移除了。目前我只安装了一个luckperm插件,用来管理玩家权限(如单独给玩家tp权限而不给op管理员身份)

设定op、添加白名单

服务端启动完成后,直接在服务端控制台窗口可运行指令(包括游戏内的指令,如 time set)

执行op <玩家名>可赋予玩家op

执行whitelist add <玩家名>可为玩家添加白名单

注意在控制台窗口输入命令时,都不带/

配置客户端、制作整合包

客户端即是玩家端,可以选择任意一款启动器,制作整合包发给发给玩家,而我选择的是HMCL这个老牌启动器,版本为3.5.3

下载游戏本体

然后把所安装的模组放入游戏目录的mods文件夹

可以使用litteskin,为游戏增加自定义皮肤支持,同时还需要安装customskinloader 模组。

然后启动游戏,在多人游戏中添加搭建的服务器,退出即可。

之后在hmcl中,选择导出整合包,导出时,勾选多人服务列表一起导出。为了以后更新方便,我还构建了服务器自动更新整合包,在hmcl启动器中和mcbbs上均有相关教程。
参考
Nginx 下配置 HMCL 自动更新整合包

由于构建步骤相对繁琐,我也会另写一篇文章记录。

把制作好的整合包发给玩家后,若使用的是云主机,就可以直接开始联机游戏了。但我用的是自己的主机,其他非内网玩家是无法访问我的服务器的,所以还需要进行端口映射和ddns配置(或内网穿透)

使外部网络可访问服务器

我的路由器支持花生壳的ddns,所以我采用了端口映射+ddns的方法。

在路由器管理页面,进行如下配置映射端口(默认端口为25565,可在服务端配置文件server.properties中更改)

然后登陆花生壳ddns账号,这样外部网络便可以访问局域网中的mc服务器了。

若路由器没有内置任何ddns的支持,还可以在服务器的主机上使用ddns-go程序。