# ExpectPlatform
# ExpectPlatform
读者应该已经对 ExpectPlatform 有了一个基本的认识,ExpectPlatform 是 Architectury Plugin 的一个重要注解,它可以根据平台的不同将一个方法映射到不同的实现上去.
Architectury 对 ExpectPlatform 修饰的方法有一些规范和要求:
- 被修饰的方法必须是公开且静态的
- 方法的实现,命名必须是原方法名 + Impl
- 方法的实现,应该存放到 forge 模块,相同包下名为 forge 的包中
- 方法的实现,应该存放到 fabric 模块,相同包下名为 fabric 的包中
在 common 模块中创建类 Storyteller, 并创建一个公开静态方法,添加 ExpectPlatform 注解
位于common: trou/arch/Storyteller.java | |
@ExpectPlatform | |
public static void tellStory() { | |
// 方法体为空,Architectury 会根据不同的模组加载器自动填充 | |
} |
在 fabric 和 forge 模块中相同位置创建类 StorytellerImpl, 为它添加实现
位于fabric: trou/arch/fabric/StorytellerImpl.java | |
public class StorytellerImpl { | |
public static void tellStory() { | |
System.out.println("I'm fabric, your new friend."); | |
} | |
} |
位于forge: trou/arch/forge/StorytellerImpl.java | |
public class StorytellerImpl { | |
public static void tellStory() { | |
System.out.println("I'm forge, your old friend."); | |
} | |
} |
在 common 包中,我们就可以按需调用 tellStory 方法,编译时 Architectury 会根据平台的不同补齐方法
位于common: trou/arch/Arch.java | |
public static void init() { | |
System.out.println("Hello Architectury!"); | |
Storyteller.tellStory(); | |
} |
此时分别运行 Forge 和 Fabric 客户端,输出的信息应该有所不同.
我们的文件结构应该是这样的:
ExpectPlatform 方法: common\src\main\java\trou\arch\Storyteller.java
Forge 平台的实现: forge\src\main\java\trou\arch**\forge\**StorytellerImpl.java
Fabric 平台的实现: fabric\src\main\java\trou\arch**\fabric\**StorytellerImpl.java
# IDEA 的 Architectury 插件
Architectury 提供了 IDEA 的插件来帮助我们补全 ExpectPlatform 的实现
创建 ExpectPlatform 方法后,可以自动在正确的位置创建 forge 和 fabric 的实现
# ArchitecturyTarget
# ArchitecturyTarget <a href="#architecturytarget" id="architecturytarget"></a>
利用 ArchitecturyTarget 类的 getCurrentTarget 方法,可以直接获取当前运行的模组加载器平台.
ArchitecturyTarget.getCurrentTarget () 需要在 common 包中被调用
- 当 forge 环境执行到该语句时,方法的返回值为 forge
- 当 fabric 环境执行到该语句时,方法的返回值为 fabric
下面我们来用 ArchitecturyTarget 修改我们上一章节编写的 Storyteller 代码.
修改 StoryTeller 类,去掉 ExpectPlatform 注解,直接基于当前运行的加载器环境进行判断
public class Storyteller { | |
public static final String FORGE_STORY = "I'm forge, your old friend."; | |
public static final String FABRIC_STORY = "I'm fabric, your new friend."; | |
public static void tellStory() { | |
final String platform = ArchitecturyTarget.getCurrentTarget(); | |
System.out.println(platform.equals("forge") ? FORGE_STORY : FABRIC_STORY); | |
} | |
} |
现在应该能得到与之前相同的效果。读者可以根据需要取舍使用 ExpectPlatform 和 ArchitecturyTarget
# PlatformOnly
# PlatformOnly
PlatformOnly 是一个用于限定某一方法只能在某一平台执行的注解.
- @PlatformOnly ("forge") 修饰的方法只能在 Forge 模块调用 (编译后不会出现在 Fabric 代码中)
- @PlatformOnly ("fabric") 修饰的方法只能在 Fabric 模块调用 (编译后不会出现在 Forge 代码中)
被 PlatformOnly 修饰的方法如果在 common 包直接调用会产生警告 (需要安装插件)
如果我们尝试在 Forge 模块中调用被 @PlatformOnly ("fabric") 修饰的方法,游戏会抛出反射异常
# Environment & OnlyIn
# Transform to Environment
在 Forge 中,为了标识某一方法只在逻辑服务端执行,我们通常会添加 @OnlyIn (Dists.DEDICATED_SERVER)
在 Fabric 中,为了标识某一方法只在逻辑服务端执行,我们通常会添加 @Environment (EnvType.SERVER)
为了统一这两个相同的需求,Architectury 为我们添加了自动处理的映射关系.
在实际代码中,我们只需要添加 Environment 注解即可,Architrctury 会对 Forge 平台进行映射处理