johnbanq

Results 8 issues of johnbanq

The Bukkit API is a well-known and long-existed plugin API that almost dictated plugin development on Java Edition for years,its longevity means that it must have got some abstraction right!...

We now have like 10 mods in this repo,and stuff like packet sending & handling,player & world events are just basically lying around in modules that uses them,so why not...

performed minor cleanup, renaming and concentration of concern in NetworkManager. This might permit some further refactoring and cleanup in network-related code.

Move TPS calculation logic into another class & renamed nextTick to nextTickTimeMillis. Not much of an addition, but is helpful in terms of slicing up the mega CloudServer object.

## 现有问题 在当前版本里,服务器是通过在main线程里执行System.exit(0)强行终止整个进程来实现停止的。 我猜想这里之所以需要强行杀掉进程,是因为Nukkit内部存在线程泄漏问题,这只是解决这个问题无可奈何的做法。但是这么做一方面不优雅(所有线程会被立刻终止,包括那些可能在执行最后一点清理逻辑的线程),另一方面会对热重启等特性的实现造成影响。 所以,我提议我们正面解决这个问题,通过好好地把尚未关闭的线程池关闭来自然地停机。 ## 修改计划 - [ ] 关闭线程池,实现优雅停机 - [*] 分析main线程结束后进程无法退出的原因,揪出那些尚未被关闭的线程池 - 目前已知的泄露有下述三个,在全部关闭后服务器是可以正常退出的: - PGZIPOutputStream内部的静态线程池 - BlockStateRegistry里的asyncStateRemover - Metrics里的scheduler - [ ] 设计逻辑关闭这些线程池 - [ ] 避免线程泄露问题复发,对可能的复发提供预案...

新特性
需要更多信息
中优先级

There should be an assertion to ensure the embedding process completes successfully

对于Allay服务端的整体设计,我的提案如下: 我认为整个东西的重点在于 网络协议/存储/游戏逻辑的划分,只要把握了这三大块的划分,剩下的都会简单的多,我认为可以这么组织: ![design-overview drawio](https://user-images.githubusercontent.com/2265049/222928202-538f7d7c-5b5b-44ab-8ccf-5af0a0453a21.png) 我们把系统分成 网络协议/存储与生成/游戏逻辑 三大块: **网络协议**:负责所有和网络协议相关的东西,例如资源包分发,登录流程等等等等。它负责处理底层协议细节,出来的是纯粹的和游戏相关的报文。 其具体可以组织成NetworkManager(顶层对象),每个玩家的连接由PlayerConnection表示,PlayerConnection知道自己玩家的UUID,负责当收发包的中转者。 **存储与生成**:顾名思义,负责存储现有地形数据,与生成新地形。这里合并了生成,其目的是为了形成“所有地形都已经实现生成好了,只是要读出来”的抽象。 具体可以组织成LevelStoreManager对象,负责向每个LevelServer提供LevelStore对象,LevelStore提供基本的存储读写API(读写Chunk,读写实体等),操作全部用Future异步化,由游戏逻辑决定要不要等。 **游戏逻辑**:负责游戏逻辑本身,每个Level由一个LevelServer负责,其内包含了一个Level应当持有的所有状态,以及一个负责运行tick loop的线程。 高层次来看,tick loop要做三件事:处理客户端发来的包,跑游戏逻辑,把变化发回给客户端。 tick loop在每个tick开始,都先从当前Level所拥有的PlayerConnection中拉取到目前为止已经收到的包,然后调用当前Level内的PacketHandler进行处理,来做命令执行/游戏世界操作/等等等等。然后调用相关对象的tick函数做ticking,最后将需要发送的区块更新信息/背包更新信息发给感兴趣的客户端。发包不一定要在最后做,也可以按需求迁移(或者提供flush功能)。 其它东西(例如命令处理,表单,NPC对话框)都可以在Level层面用Manager解决

Documentation

# 提案:使用依赖注入容器 为了提升核心的可扩展性,处理依赖与初始化问题,我们应该引入依赖注入容器(例如Guice)来帮我们对付这些问题。 ## 好处 * 可以简化插件之间的对象传递,减少耦合。例如插件A要提供一个对象作为API给插件B使用,依赖注入容器可以完成对象传递的工作,这比全局静态变量/自己实现ServiceProvider机制要干净。 * 可以简化初始化,如果对象B需要使用对象A,依赖注入可以保证在B拿到A的时候A已经被初始化完毕了。 * 可以简化发现和注册,只要向容器中提供实现特定接口的对象,核心就可以自动扫描对应实例,并将其拿来使用,而无需显式地注册 ## 坏处 * 提升debug难度,因为依赖注入容器在运行时进行装配,因为注册方式错误导致没法注册成功之类的问题会变得难以排查。

Proposal