# 更复杂的Mod
恭喜,你进入了进阶篇。此时你应该已经编写了大量的代码,并打算实现更复杂的逻辑和探索更底层的API了。
## 代码规范
如果你在之前的开发中很少/没有注意代码的干净整洁的话,此时你的项目中的代码可能已经变得十分混乱。此时我们有必要再次讲一下Java中的命名规范与代码格式了。
### **1. 大括号位于首行末尾**
### **2. 运算符和操作符两边应有空格**
### **3. 类的命名应使用大写驼峰式(每个单词首字母大写,没有下划线)**
### **4. 变量/字段/方法命名应使用小写驼峰式(第一个单词首字母小写,后面每个单词首字母大写,没有下划线)**
### **5. 静态常量命名全部大写,用下划线分词**
(以下为Minecraft与Forge中的特殊约定)
### **6. 所有资源文件名称都为全小写,用下划线分词**
### **7.注册名应该全小写,用下划线分词**
最后,所有编程语言都要遵循一个约定:
# **不 要 压 行**
反面例子:
~~~
// 什么? 你发现了不符合常理的new BlockState()? 不要怀疑人生,这段代码是1.14.4的......
player.world.setBlockState(new BlockPos(pos.getX(), pos.getY() + 1, pos.getZ()), new BlockState(Blocks.ENDER_CHEST, ImmutableMap<IProperty, Comparable>builder().put(EnderChestBlock.FACING, (player.getHorizontalFacing().getIndex() <= 1) ? Direction.byIndex((int)Math.random() * 4 + 1) : player.getHorizontalFacing()).build()).with(EnderChestBlock.WATERLOGGED, false));
~~~
同时如果你是写系统内核或者资深OI玩家出身的,请切记**不要把你的高级编译器原理知识运用到团队开发中**!
反面例子:**(A+B Problem)**
~~~
main(n){gets(&n);printf("%d",n%85-43);}
~~~
另外,不要忘了**使用包(Package)来分类存放你的类**。
以下为遵循了格式约定的示例代码:
~~~
package com.github.zi_jing.test;
abstract class Parent {
private static final String str = "hello";
public static String getStr() {
return str;
}
public abstract int getId();
}
interface TestInterface {
boolean someMethod(int a);
}
public class TestClass extends Parent implements TestInterface {
/**
* xxx的尺寸属性
*/
public static enum Size {
SMALL,
MEDIUM,
LARGE
}
private static int nextId = 0;
private int id;
private Size size;
/**
* 构造函数描述
* @param size 尺寸
*/
public TestClass(Size size) {
this.size = size;
this.id = getNextId();
}
private static int getNextId() {
return nextId++;
}
public Size getSize() {
return this.size;
}
@Override
public int getId() {
return this.id;
}
@Override
public boolean someMethod(int a) {
return false;
}
}
~~~
## 游戏逻辑
### 关于延时
切记:在**任何事件订阅,update方法,或者GUI的绘制方法以及与网络有关的代码**中,不要试图直接编写“延时”代码,这么做会导致**整个游戏逻辑的停止或者客户端挂起**,可能会导致严重后果。
如果你确实需要在游戏逻辑中编写延时,请使用`Timer`(`java.util.Timer`)等库来进行多线程操作。
**注意:在其他线程中操作客户端/服务端游戏对象需要使用`scheduleTask()`方法(这一点和网络线程一样)。**
### 关于tick内游戏逻辑
尽量不要在单个tick中进行大量运算或者与游戏对象频繁交互,这样做会**大幅降低TPS**。
如果确实需要偶尔进行大量运算,可以考虑**把它放到单独的线程**。
## 基础篇一些零碎的问题
### 关于日志输出
众所周知,我们只需要获取模组的`Logger`实例,然后调用它的`info`、`debug`、`warn`、`error`方法就行了。
但是如果我们想输出格式化后的文本应该怎么写呢?我们用默认的文本格式化标记(%s,%d等)并没有起作用,这是因为`Logger`的格式化标识符是`{}`,且不需要指定类型。
例子:
~~~
logger.info("Loading page {} of {}, the title is \"{}\"", cur, total, title);
~~~
如果你只想使用普通的文本格式化符号的话,就只能这样了:
~~~
logger.info(String.format("Loading page %d of %d, the title is \"%s\"", cur, total, title));
~~~
当然这种方法也不是不行,只是稍微麻烦了一点?(雾)
### 待补全
- 0.引子
- 基础篇 - 1.构建开发环境
- 基础篇 - 2.主类和代理
- 基础篇 - 3.创建一个物品
- 基础篇 - 4.创建一个方块
- 基础篇 - 4.1自定义方块模型
- 基础篇 - 5.初探事件系统
- 基础篇 - 6.Capability系统
- 基础篇 - 7.创建一个方块实体
- 基础篇 - 8.你的第一个GUI
- 基础篇 - 9.网络与通讯
- 进阶篇 - 0.更复杂的Mod
- 进阶篇 - 1.Minecraft渲染原理
- 进阶篇 - 2.更复杂的GUI
- 进阶篇 - 3.物品进阶
- 高级篇 - 1.深入探索OpenGL
- 高级篇 - 1.1OpenGL颜色渲染
- 高级篇 - 1.2OpenGL光照系统
- 高级篇 - 2.Minecraft贴图加载原理