
上期传送门(项目配置):https://zhuanlan.zhihu.com/p/75523823
大家好,我又回来了!本期主要讲服务端、客户端和代理(Proxy)。因为要讲的东西有点多所以物品和方块鸽到下期了,改讲一下配置。
这里是我的完整Mod项目地址,有一定基础或者迫不及待的话可以直接去读源码,顺便求Star
一、服务端、客户端
MC中很重要的一个概念就是服务端和客户端。顾名思义,服务端(Server)负责处理游戏逻辑(比如怪物的生成),而客户端(Client)负责将游戏展现给玩家(比如方块的渲染)。
在多人游戏中,区分客户端和服务端是很容易的:服务端在服务器上,客户端在玩家的电脑上。实际上,现在MC的单机游戏也使用了客户端和服务端,只不过两端都运行在玩家的机器上——可以把它看做是一个本地的单人联机游戏。所以,一定要分清物理(Physical)服务端/客户端和逻辑(Logical)服务端/逻辑客户端的区别。单机游戏就是逻辑客户端和逻辑服务端都跑在物理客户端上,并不是没有服务端的事了。
那如何区分两端呢?
我们首先了解一下MC中World这个对象。顾名思义,World掌管整个世界,可以说是最常用的对象之一。当你拥有World对象时,使用World.isRemote 就可以判断这个World是哪一端的:true即为服务端,false即为客户端。
- 一定要注意,这里区分的是逻辑的端而不是物理的端,并不是isRemote为true就一定是远程的物理服务器。亲身经历,这个很容易搞混=-= 一般情况下Mod不需要知道自己在哪个物理端,只需要管逻辑端。我后面讲客户端和服务端的如果不强调即为逻辑端。
二、代理机制
初始化的时候,也要考虑哪一端的问题,比如说只有客户端需要考虑渲染的问题。Forge给我们提供了一个方便的办法,让我们在Mod类的companion object中加入如下语句:
@JvmStatic
@SidedProxy(clientSide = "com.example.examplemod.proxy.ClientProxy", serverSide = "com.example.examplemod.proxy.ServerProxy")
lateinit var proxy: CommonProxy
这里用到的就是代理机制了。@SidedProxy会在不同的端给这个proxy属性注入不同的对象:客户端使用clientSide指定的对象,也就是ClientProxy;服务端使用serverSide指定的对象,也就是ServerProxy。而CommonProxy就是他们共同的父类。
- 参数要写这个类完整的位置,注意不要写错。
补充:All Open插件
在创建proxy类之前,我们先去build.gradle加入一个新插件。把原来的buildscript和apply plugin部分改成这样:
buildscript {
ext {
kotlin_version = "1.3.40"
// annotations_version = "16.0.3"
// cor