Skip to content

Commit

Permalink
feat: 🎉 initial commit
Browse files Browse the repository at this point in the history
Co-authored-by: ZhuRuoLing <[email protected]>
  • Loading branch information
AnzhiZhang and ZhuRuoLing committed Dec 16, 2022
0 parents commit f748262
Show file tree
Hide file tree
Showing 14 changed files with 740 additions and 0 deletions.
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# idea
/.idea/

# maven
/target/
13 changes: 13 additions & 0 deletions ChatHub.iml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<module version="4">
<component name="FacetManager">
<facet type="minecraft" name="Minecraft">
<configuration>
<autoDetectTypes>
<platformType>VELOCITY</platformType>
<platformType>ADVENTURE</platformType>
</autoDetectTypes>
</configuration>
</facet>
</component>
</module>
73 changes: 73 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>com.zhanganzhi.chathub</groupId>
<artifactId>ChatHub</artifactId>
<version>1.0.0</version>

<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

<repositories>
<repository>
<id>papermc</id>
<url>https://repo.papermc.io/repository/maven-public/</url>
</repository>
</repositories>

<dependencies>
<dependency>
<groupId>com.velocitypowered</groupId>
<artifactId>velocity-api</artifactId>
<version>3.1.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>net.deechael</groupId>
<artifactId>khl</artifactId>
<version>1.09.0</version>
<scope>compile</scope>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
<exclusion>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</exclusion>
<exclusion>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
</plugins>
</build>
</project>
95 changes: 95 additions & 0 deletions src/main/java/com/zhanganzhi/chathub/ChatHub.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package com.zhanganzhi.chathub;

import java.io.File;
import java.util.HashSet;
import java.nio.file.Path;
import java.lang.reflect.Field;

import org.slf4j.Logger;
import com.google.inject.Inject;
import com.velocitypowered.api.plugin.Plugin;
import com.velocitypowered.api.event.Subscribe;
import com.velocitypowered.api.proxy.ProxyServer;
import com.velocitypowered.api.event.proxy.ProxyInitializeEvent;
import com.velocitypowered.api.event.proxy.ProxyShutdownEvent;
import com.velocitypowered.api.plugin.annotation.DataDirectory;
import net.deechael.khl.bot.KaiheilaBot;
import net.deechael.khl.bot.KaiheilaBotBuilder;
import net.deechael.khl.event.MessageHandler;

import com.zhanganzhi.chathub.core.Config;
import com.zhanganzhi.chathub.core.EventHub;
import com.zhanganzhi.chathub.command.Command;
import com.zhanganzhi.chathub.receiver.VelocityReceiver;
import com.zhanganzhi.chathub.receiver.KookReceiver;

@Plugin(
id = "chathub",
name = "ChatHub",
version = "1.0.0",
url = "https://github.com/AnzhiZhang/ChatHub",
description = "Chat hub for servers under velocity proxy",
authors = {"Andy Zhang", "ZhuRuoLing"}
)
public class ChatHub {
private final ProxyServer server;
private final Path dataDirectory;
private KaiheilaBot kaiheilaBot;

@Inject
public ChatHub(ProxyServer server, Logger logger, @DataDirectory Path dataDirectory) {
this.server = server;
this.dataDirectory = dataDirectory;
}

public ProxyServer getServer() {
return server;
}

public KaiheilaBot getKaiheilaBot() {
return kaiheilaBot;
}

@Subscribe
public void onInitialize(ProxyInitializeEvent event) {
// core
Config.getInstance().loadConfig(dataDirectory);
kaiheilaBot = (KaiheilaBot) KaiheilaBotBuilder.builder().createDefault(Config.getInstance().getKookToken()).build();
EventHub eventHub = new EventHub(this);

// command
server.getCommandManager().register(
server.getCommandManager().metaBuilder("chathub").plugin(this).build(),
new Command(server)
);

// velocity receiver
server.getEventManager().register(this, new VelocityReceiver(eventHub));

// kook receiver
if (Config.getInstance().isKookEnabled()) {
new Thread(() -> {
try {
Field messageHandlersField = ChatHub.this.kaiheilaBot.getEventManager().getClass().getDeclaredField("messageHandlers");
messageHandlersField.setAccessible(true);
messageHandlersField.set(ChatHub.this.kaiheilaBot.getEventManager(), new HashSet<MessageHandler>());
} catch (Exception exception) {
throw new RuntimeException(exception);
}
ChatHub.this.kaiheilaBot.getEventManager().registerMessageHandler(new KookReceiver(eventHub));
ChatHub.this.kaiheilaBot.start();
}).start();
}
}

@Subscribe
public void onProxyShutdown(ProxyShutdownEvent event) {
if (Config.getInstance().isKookEnabled()) {
kaiheilaBot.shutdown();
File sessionFile = new File("session.dat");
if (sessionFile.exists()) {
sessionFile.delete();
}
}
}
}
62 changes: 62 additions & 0 deletions src/main/java/com/zhanganzhi/chathub/command/Command.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package com.zhanganzhi.chathub.command;

import java.util.List;
import java.util.Optional;
import java.util.stream.Stream;

import net.kyori.adventure.text.Component;
import com.velocitypowered.api.proxy.Player;
import com.velocitypowered.api.proxy.ProxyServer;
import com.velocitypowered.api.command.CommandSource;
import com.velocitypowered.api.command.SimpleCommand;
import com.velocitypowered.api.proxy.server.RegisteredServer;

import com.zhanganzhi.chathub.core.Config;

public final class Command implements SimpleCommand {
ProxyServer server;

public Command(ProxyServer proxyServer) {
server = proxyServer;
}

@Override
public void execute(final Invocation invocation) {
CommandSource source = invocation.source();
String[] args = invocation.arguments();
Config config = Config.getInstance();

if (args.length == 1 && args[0].equals("list")) {
for (RegisteredServer registeredServer : server.getAllServers()) {
source.sendMessage(Component.text(
config.getMinecraftListMessage(
registeredServer.getServerInfo().getName(),
registeredServer.getPlayersConnected().size(),
registeredServer.getPlayersConnected().stream().map(Player::getUsername).toArray(String[]::new)
)
));
}
} else if (args.length == 3 && args[0].equals("msg")) {
Optional<Player> optionalPlayer = server.getPlayer(args[1]);
if (optionalPlayer.isPresent()) {
String senderName = source instanceof Player ? ((Player) source).getUsername() : "Server";
source.sendMessage(Component.text(config.getMinecraftMsgSenderMessage(args[1], args[2])));
optionalPlayer.get().sendMessage(Component.text(config.getMinecraftMsgTargetMessage(senderName, args[2])));
} else {
source.sendMessage(Component.text("Player \"" + args[1] + "\" does not online!"));
}
}
}

@Override
public List<String> suggest(final Invocation invocation) {
String[] args = invocation.arguments();
if (args.length <= 1) {
return Stream.of("list", "msg").filter(s -> s.startsWith(args.length > 0 ? args[0] : "")).toList();
} else if (args.length == 2 && args[0].equals("msg")) {
return server.getAllPlayers().stream().map(Player::getUsername).filter(s -> s.startsWith(args[1])).toList();
} else {
return List.of();
}
}
}
144 changes: 144 additions & 0 deletions src/main/java/com/zhanganzhi/chathub/core/Config.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
package com.zhanganzhi.chathub.core;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Objects;

import com.moandjiezana.toml.Toml;

public class Config {
private static final Config config = new Config();
private Toml configToml;

private Config() {
}

public static Config getInstance() {
return config;
}

public void loadConfig(Path dataDirectory) {
// check data directory
if (!dataDirectory.toFile().exists()) {
dataDirectory.toFile().mkdir();
}

// check file exists
File configFile = new File(dataDirectory.toAbsolutePath().toString(), "config.toml");
if (!configFile.exists()) {
try {
Files.copy(Objects.requireNonNull(getClass().getClassLoader().getResourceAsStream("config.toml")), configFile.toPath());
} catch (IOException e) {
throw new RuntimeException(e);
}
}

configToml = new Toml().read(configFile);
}

public boolean isCompleteTakeoverMode() {
return configToml.getBoolean("minecraft.completeTakeoverMode");
}

public String getServername(String server) {
String servername = configToml.getString("servername." + server);
return servername != null ? servername : server;
}

public String getPlainServername(String server) {
return getServername(server).replaceAll("§.", "");
}

public String getMinecraftChatMessage(String server, String name, String message) {
return configToml
.getString("minecraft.message.chat")
.replace("{server}", getServername(server))
.replace("{name}", name)
.replace("{message}", message);
}

public String getMinecraftJoinMessage(String server, String name) {
return configToml
.getString("minecraft.message.join")
.replace("{server}", getServername(server))
.replace("{name}", name);
}

public String getMinecraftLeaveMessage(String name) {
return configToml
.getString("minecraft.message.leave")
.replace("{name}", name);
}

public String getMinecraftSwitchMessage(String name, String serverFrom, String serverTo) {
return configToml
.getString("minecraft.message.switch")
.replace("{name}", name)
.replace("{serverFrom}", getServername(serverFrom))
.replace("{serverTo}", getServername(serverTo));
}

public String getMinecraftMsgSenderMessage(String target, String message) {
return configToml
.getString("minecraft.message.msgSender")
.replace("{target}", target)
.replace("{message}", message);
}

public String getMinecraftMsgTargetMessage(String sender, String message) {
return configToml
.getString("minecraft.message.msgTarget")
.replace("{sender}", sender)
.replace("{message}", message);
}

public String getMinecraftListMessage(String server, int count, String[] playerList) {
return configToml
.getString("minecraft.message.list")
.replace("{server}", getServername(server))
.replace("{count}", String.valueOf(count))
.replace("{playerList}", String.join(", ", playerList));
}

public boolean isKookEnabled() {
return configToml.getBoolean("kook.enable");
}

public String getKookToken() {
return configToml.getString("kook.token");
}

public String getKookChannelId() {
return configToml.getString("kook.channelId");
}

public String getKookChatMessage(String server, String name) {
return configToml
.getString("kook.message.chat")
.replace("{server}", getPlainServername(server))
.replace("{name}", name);
}

public String getKookJoinMessage(String server, String name) {
return configToml
.getString("kook.message.join")
.replace("{server}", getPlainServername(server))
.replace("{name}", name);
}

public String getKookLeaveMessage(String name) {
return configToml
.getString("kook.message.leave")
.replace("{name}", name);
}

public String getKookSwitchMessage(String name, String serverFrom, String serverTo) {
return configToml
.getString("kook.message.switch")
.replace("{name}", name)
.replace("{serverFrom}", getPlainServername(serverFrom))
.replace("{serverTo}", getPlainServername(serverTo));
}
}
Loading

0 comments on commit f748262

Please sign in to comment.