小游戏服务端配置教程

来自TJUUSWiki
ChengZhiFy留言 | 贡献2025年11月30日 (日) 13:40的版本
(差异) ←上一版本 | 最后版本 (差异) | 下一版本→ (差异)

TJUUS 目前运营过的大部分小游戏均为地图 + 数据包形式,这篇教程提供这种类型的服务端配置教程,以让后续的小游戏服务端更加方便。

服务端重要构成部分 | Crucial Components

  • logs 文件夹 | 存放服务器运行产生的日志文件
  • plugins 文件夹 | 存放服务器插件
  • 三个 world 文件夹 | 服务器三个世界维度的地图存档
  • server.properties | 服务端配置信息
  • eula.txt | 开服需要遵守的最终用户许可协议
  • 服务端核心

在哪下载服务端核心 | Where to download server jar?

参考 常用服务端资源指南

配置教程 | Tutorial

请确保你的电脑拥有兼容你所需要运行的服务端的 Java 环境, (Windows) 为了方便请加入到系统环境变量中.

(我推荐本地部署完毕后再上传至面板)

获取与小游戏地图游戏版本相同的 Minecraft 服务端核心,移动至一个新文件夹里。新建一个文本文档, 写入以下内容:

java -jar server-core.jar nogui
pause

server-core.jar 为你的服务端核心, nogui 是为了禁用掉 Minecraft 在较新版本服务端核心中自带的图形化控制台.

将文件类型改为 .bat 并运行。

此时文件夹内会生成一个 eula.txt 文件,你需要将里面的 eula 布尔值改为 true

再次运行 bat 文件, 不出意外这次服务端将会正常启动.

我们找到 server.properties 文件, 将部分配置改成下列所示:

enable-command-block=true
online-mode=false

接着, 将文件夹内 world 文件夹删除, 并将你需要导入的小游戏地图文件夹名称改为 world 后导入。

语音组件和全局语音组件(可选)

我推荐前往 Modrinth 下载 Simple Voice Chat 的全类型全版本资源, 并将其加入到服务端文件夹的 mods / plugins 文件夹。

并将 voicechat-server.properties 中的 portMCSM 面板中对应。


Fabric 端可使用 Simple Voice Chat Enhanced Groups 实现全局语音 (仅 Fabric 可用)

Forge 端请尝试 Sinytra Connector 来兼容上文的 Fabric 模组


对于支持 Bukkit 插件的服务端,可以参考以下代码自行构建一个插件并放入服务端的 plugins 文件夹中。

package me.chengzhify.autoJoinVoiceGroup;

import de.maxhenkel.voicechat.api.BukkitVoicechatService;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.bukkit.Bukkit;
import org.bukkit.plugin.java.JavaPlugin;

import javax.annotation.Nullable;
import java.util.UUID;

public final class AutoJoinVoiceGroup extends JavaPlugin {
    public static UUID uuid = UUID.randomUUID();
    private static AutoJoinVoiceGroup instance;
    public static final Logger LOGGER = LogManager.getLogger("AutoJoinVoiceGroup");
    @Nullable
    private VoicechatImpl voicechatPlugin;
    @Override
    public void onEnable() {
        instance = this;
        // Plugin startup logic
        if (!getServer().getPluginManager().isPluginEnabled("voicechat")) {
            getLogger().severe("voicechat not found! Disabling...");
            getServer().getPluginManager().disablePlugin(this);
        } else {
            BukkitVoicechatService service = getServer().getServicesManager().load(BukkitVoicechatService.class);
            if (service != null) {
                voicechatPlugin = new VoicechatImpl();
                service.registerPlugin(voicechatPlugin);
                LOGGER.info("Successfully registered voicegroup plugin");
            } else {
                LOGGER.info("Failed to register voicegroup plugin");
            }
        }
        Bukkit.getPluginManager().registerEvents(new PlayerJoinListener(), this);
        Bukkit.getScheduler().runTaskLater(this, () -> {
            uuid = VoicechatImpl.createGroup("全局", "语音频道");
        }, 60L);
    }

    @Override
    public void onDisable() {
        // Plugin shutdown logic
        if (voicechatPlugin != null) {
            getServer().getServicesManager().unregister(voicechatPlugin);
        }
        instance = null;
    }

    public static AutoJoinVoiceGroup getInstance() {
        return instance;
    }
}
package me.chengzhify.autoJoinVoiceGroup;

import de.maxhenkel.voicechat.api.VoicechatConnection;
import org.bukkit.Bukkit;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;

public class PlayerJoinListener implements Listener {

    @EventHandler
    public void onPlayerJoin(PlayerJoinEvent event) {
        event.getPlayer().sendMessage("§a正在尝试将你连接至全局语音频道...");
        Bukkit.getScheduler().runTaskLaterAsynchronously(AutoJoinVoiceGroup.getInstance(), () -> {
            VoicechatConnection connection = VoicechatImpl.voiceServerApi.getConnectionOf(event.getPlayer().getUniqueId());
            if (connection == null) {
                event.getPlayer().sendMessage("§c连接失败! 请检查你的 SimpleVoiceChat 模组是否正确启用!");
                return;
            }
            connection.setGroup(VoicechatImpl.voiceServerApi.getGroup(AutoJoinVoiceGroup.uuid));
            event.getPlayer().sendMessage("§a你已成功连接至全局语音频道!");
        }, 20L * 3L); // 延迟3秒执行,确保玩家已连接到语音服务器
    }
}
package me.chengzhify.autoJoinVoiceGroup;

import de.maxhenkel.voicechat.api.Group;
import de.maxhenkel.voicechat.api.VoicechatApi;
import de.maxhenkel.voicechat.api.VoicechatPlugin;
import de.maxhenkel.voicechat.api.VoicechatServerApi;
import de.maxhenkel.voicechat.api.events.EventRegistration;
import de.maxhenkel.voicechat.api.events.JoinGroupEvent;
import de.maxhenkel.voicechat.api.events.LeaveGroupEvent;
import de.maxhenkel.voicechat.api.events.VoicechatServerStartedEvent;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.entity.Player;

import java.util.UUID;

import static org.apache.logging.log4j.LogManager.getLogger;

public class VoicechatImpl implements VoicechatPlugin {
    public static VoicechatServerApi voiceServerApi;
    private static final AutoJoinVoiceGroup instance = AutoJoinVoiceGroup.getInstance();
    private static final boolean voiceLog = instance.getConfig().getBoolean("voice-group-console-log");
    @Override
    public String getPluginId() {
        return "AutoJoinVoiceGroup";
    }

    @Override
    public void initialize(VoicechatApi api) {

    }

    @Override
    public void registerEvents(EventRegistration registration) {
        registration.registerEvent(VoicechatServerStartedEvent.class, this::onVoiceServerStart);
    }

    private void onVoiceServerStart(VoicechatServerStartedEvent event) {
        voiceServerApi = event.getVoicechat();
        System.out.println(voiceServerApi);
        getLogger().info("[VoiceChat] API 已获取,可以创建语音频道了!");
    }

    public static UUID createGroup(String name, String team) {
        Group g = voiceServerApi.groupBuilder()
                .setPersistent(true)
                .setName(name + team) // The name of the group
                .setType(Group.Type.OPEN)
                .build();
        if (voiceLog) {
            getLogger().info("[VoiceGroup] " + name + team + " 语音组已创建");
        }
        return g.getId();
    }
}

Simple Voice Chat 提供了它的 API 文档, 这方便我们基于它开发一些更有意思的拓展组件。

皮肤恢复组件(可选)

皮肤恢复插件 (SkinRestorer): (较新的 MC 版本也支持模组服,服务端侧)

皮肤恢复模组 (SkinRestorer): (服务端侧,个人客户端无需安装)