parent
54ce760feb
commit
75dfd94e66
55
README.md
55
README.md
|
|
@ -29,7 +29,7 @@
|
|||
|
||||
### `func getServer()`
|
||||
|
||||
- 接口描述:获取一个可用的服务器ip,并记录该对局的参与玩家。
|
||||
- 接口描述:提供模版类型,获取一个可用的服务器ip,并记录该对局的参与玩家。
|
||||
|
||||
- 返回值:
|
||||
|
||||
|
|
@ -38,7 +38,8 @@
|
|||
- Int类型的对局id
|
||||
|
||||
- 参数列表:
|
||||
- `ArrayList<Player> players`
|
||||
- `(List<Player> players)`
|
||||
-
|
||||
|
||||
### `func informEnd()`
|
||||
|
||||
|
|
@ -47,7 +48,7 @@
|
|||
- 返回值:无
|
||||
|
||||
- 参数列表:
|
||||
- int id
|
||||
- `(int id)`
|
||||
|
||||
### `func getPlayerServer()`
|
||||
|
||||
|
|
@ -60,12 +61,52 @@
|
|||
- 参数列表:
|
||||
- `(Player player)`
|
||||
|
||||
### `func containPlayer`
|
||||
### `func containPlayer()`
|
||||
|
||||
- 接口描述:查询某个玩家是否在对局中。
|
||||
|
||||
- 返回值:
|
||||
- bool
|
||||
|
||||
- 参数列表:
|
||||
- `(Player player)`
|
||||
- `(Player player)`
|
||||
|
||||
## 数据库结构
|
||||
|
||||
- `match`
|
||||
|
||||
| id(int) | start(datetime) | end(datetime) | players(text) |
|
||||
| ------- | --------------- | ------------- | ------------------------------------ |
|
||||
| 1 | 1678554776 | 1678554784 | TONY_All,Sanseyooyea,PlayerA,PlayerB |
|
||||
## API 使用
|
||||
|
||||
依赖:
|
||||
|
||||
```kotlin
|
||||
dependencies {
|
||||
compileOnly("cc.maxmc.msm:MultiServerMan-API:${version}")
|
||||
}
|
||||
```
|
||||
|
||||
使用:
|
||||
|
||||
```java
|
||||
List<ProxyPlayer> players;
|
||||
|
||||
MultiServerManAPI api = MultiServerManAPIProvider.getAPI();
|
||||
api.getServer("default", players);
|
||||
```
|
||||
|
||||
## Q&A
|
||||
|
||||
1. Q: 不同类型的服务端是怎么区分的
|
||||
|
||||
A: 每个子端保留多种模版
|
||||
|
||||
2. Q: 数据库类型
|
||||
|
||||
A: MySQL / MariaDB
|
||||
|
||||
3. Q: getServer是需要负责把玩家传到子服还是只是提供服务器并记录玩家
|
||||
|
||||
A: 只提供服务器并记录玩家
|
||||
|
||||
4. Q: 服务端是
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
plugins {
|
||||
kotlin("jvm")
|
||||
}
|
||||
|
||||
group = "cc.maxmc.msm.api"
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven("https://repo.papermc.io/repository/maven-public/")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(kotlin("stdlib"))
|
||||
@Suppress("VulnerableLibrariesLocal")
|
||||
compileOnly("io.github.waterfallmc:waterfall-api:1.19-R0.1-SNAPSHOT")
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
package cc.maxmc.msm.api;
|
||||
|
||||
import cc.maxmc.msm.api.misc.ServerInfo;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@SuppressWarnings("unused") // API
|
||||
public interface MultiServerManAPI {
|
||||
ServerInfo getServer(String type, List<ProxiedPlayer> players);
|
||||
|
||||
void informEnd(int id);
|
||||
|
||||
ServerInfo getPlayerServer(ProxiedPlayer player);
|
||||
|
||||
Boolean containPlayer(ProxiedPlayer player);
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
package cc.maxmc.msm.api;
|
||||
|
||||
@SuppressWarnings("unused") // API
|
||||
public abstract class MultiServerManAPIProvider {
|
||||
private static MultiServerManAPIProvider instance;
|
||||
|
||||
public static MultiServerManAPI getAPI() {
|
||||
if (instance == null) {
|
||||
throw new NotLoadedException();
|
||||
}
|
||||
return instance.provideAPI();
|
||||
}
|
||||
|
||||
abstract MultiServerManAPI provideAPI();
|
||||
|
||||
/**
|
||||
* 在加载 API 之前请求 API 时引发异常。
|
||||
*/
|
||||
private static final class NotLoadedException extends IllegalStateException {
|
||||
private static final String MESSAGE = "The MultiServerMan API isn't loaded yet!\n" +
|
||||
"This could be because:\n" +
|
||||
" a) the MultiServerMan plugin is not installed or it failed to enable\n" +
|
||||
" b) the plugin in the stacktrace does not declare a dependency on MultiServerMan\n" +
|
||||
" c) the plugin in the stacktrace is retrieving the API before the plugin 'enable' phase\n" +
|
||||
" (call the #get method in onEnable, not the constructor!)\n";
|
||||
|
||||
NotLoadedException() {
|
||||
super(MESSAGE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
package cc.maxmc.msm.api.misc;
|
||||
|
||||
import com.google.common.net.HostAndPort;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@SuppressWarnings("unused") // API
|
||||
public class ServerInfo {
|
||||
@Nullable
|
||||
private final HostAndPort server;
|
||||
private final int id;
|
||||
|
||||
public ServerInfo(@Nullable HostAndPort server, int id) {
|
||||
this.server = server;
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public HostAndPort getServer() {
|
||||
return server;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,27 +1,2 @@
|
|||
plugins {
|
||||
kotlin("jvm") version "1.8.0"
|
||||
application
|
||||
}
|
||||
|
||||
group = "cc.maxmc.msm"
|
||||
version = "1.0-SNAPSHOT"
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
testImplementation(kotlin("test"))
|
||||
}
|
||||
|
||||
tasks.test {
|
||||
useJUnitPlatform()
|
||||
}
|
||||
|
||||
kotlin {
|
||||
jvmToolchain(8)
|
||||
}
|
||||
|
||||
application {
|
||||
mainClass.set("MainKt")
|
||||
}
|
||||
version = "1.0-SNAPSHOT"
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
plugins {
|
||||
kotlin("jvm")
|
||||
}
|
||||
|
||||
group = "cc.maxmc.msm.child"
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven("https://repo.papermc.io/repository/maven-public/")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(kotlin("stdlib"))
|
||||
compileOnly("io.github.waterfallmc:waterfall-api:1.19-R0.1-SNAPSHOT")
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
plugins {
|
||||
kotlin("jvm")
|
||||
}
|
||||
|
||||
group = "cc.maxmc.msm.common"
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
mavenLocal()
|
||||
maven("https://repo.papermc.io/repository/maven-public/")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(kotlin("stdlib"))
|
||||
compileOnly("io.github.waterfallmc:waterfall-api:1.19-R0.1-SNAPSHOT")
|
||||
compileOnly("net.md-5:bungeecord-proxy:1.19-R0.1-SNAPSHOT") {
|
||||
isTransitive = false
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
package cc.maxmc.msm.common
|
||||
|
||||
import cc.maxmc.msm.common.network.ClusterMsgCodec
|
||||
import io.netty.channel.Channel
|
||||
import net.md_5.bungee.BungeeCord
|
||||
|
||||
object PacketInjector {
|
||||
private val bungee = BungeeCord.getInstance()
|
||||
private val field = bungee::class.java.getDeclaredField("listeners").also {
|
||||
it.isAccessible = true
|
||||
}
|
||||
|
||||
fun inject() {
|
||||
val channel = getChannel()
|
||||
channel.pipeline().addFirst("ClusterMsgCodec", ClusterMsgCodec)
|
||||
}
|
||||
|
||||
private fun getChannel(): Channel {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val channelList = field.get(bungee) as Collection<Channel>
|
||||
while (true) {
|
||||
return channelList.firstOrNull() ?: continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
package cc.maxmc.msm.common.network
|
||||
|
||||
import io.netty.buffer.ByteBuf
|
||||
|
||||
interface BungeePacket: Cloneable {
|
||||
fun encode(buf: ByteBuf)
|
||||
|
||||
fun decode(buf: ByteBuf)
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
package cc.maxmc.msm.common.network
|
||||
|
||||
import io.netty.buffer.ByteBuf
|
||||
import io.netty.channel.ChannelHandlerContext
|
||||
import io.netty.handler.codec.ByteToMessageCodec
|
||||
|
||||
object ClusterMsgCodec : ByteToMessageCodec<BungeePacket>() {
|
||||
override fun encode(ctx: ChannelHandlerContext, msg: BungeePacket, out: ByteBuf) {
|
||||
msg.encode(out)
|
||||
}
|
||||
|
||||
override fun decode(ctx: ChannelHandlerContext, `in`: ByteBuf, out: MutableList<Any>) {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
package cc.maxmc.msm.common.network
|
||||
|
||||
import com.google.common.collect.HashBiMap
|
||||
|
||||
object NetworkRegistry {
|
||||
val parentBoundMap = HashBiMap.create<Int, BungeePacket>()
|
||||
val childBoundMap = HashBiMap.create<Int, BungeePacket>()
|
||||
|
||||
fun registerPacket(packet: BungeePacket, direction: PacketDirection) {
|
||||
if (direction == PacketDirection.ParentBound) {
|
||||
parentBoundMap
|
||||
} else {
|
||||
childBoundMap
|
||||
}.let {
|
||||
it[it.size] = packet
|
||||
}
|
||||
}
|
||||
|
||||
enum class PacketDirection {
|
||||
ParentBound,
|
||||
ChildBound;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.2-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
plugins {
|
||||
kotlin("jvm")
|
||||
id("com.github.johnrengelman.shadow")
|
||||
}
|
||||
|
||||
group = "cc.maxmc.msm.parent"
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven("https://repo.papermc.io/repository/maven-public/")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(kotlin("stdlib"))
|
||||
implementation(project(":api"))
|
||||
implementation(project(":common"))
|
||||
@Suppress("VulnerableLibrariesLocal")
|
||||
compileOnly("io.github.waterfallmc:waterfall-api:1.19-R0.1-SNAPSHOT")
|
||||
}
|
||||
|
||||
tasks.shadowJar {
|
||||
relocate("kotlin", "cc.maxmc.msm.lib.kotlin")
|
||||
}
|
||||
|
||||
tasks.build {
|
||||
dependsOn(tasks.shadowJar)
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
package cc.maxmc.msm.parent
|
||||
|
||||
import cc.maxmc.msm.common.PacketInjector
|
||||
import net.md_5.bungee.api.ProxyServer
|
||||
import net.md_5.bungee.api.plugin.Plugin
|
||||
|
||||
class MultiServerMan: Plugin() {
|
||||
|
||||
override fun onEnable() {
|
||||
Thread.sleep(5000)
|
||||
ProxyServer.getInstance().scheduler.runAsync(this) {
|
||||
println("injecting")
|
||||
PacketInjector.inject()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDisable() {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
name: MultiServerMan-Parent
|
||||
main: cc.maxmc.msm.parent.MultiServerMan
|
||||
author: TONY_All
|
||||
|
|
@ -1,3 +1,9 @@
|
|||
plugins {
|
||||
id("com.github.johnrengelman.shadow") version "8.1.0" apply false
|
||||
kotlin("jvm") version "1.8.10" apply false
|
||||
}
|
||||
|
||||
rootProject.name = "MultiServerMan"
|
||||
|
||||
include("common", "parent-side", "child-side")
|
||||
include("api")
|
||||
Loading…
Reference in New Issue