mirror of
https://github.com/System-End/Discord-MC-Chat.git
synced 2026-04-19 22:05:11 +00:00
引用了DisFabric源代码
This commit is contained in:
parent
cd57d7f1ab
commit
44319ad7e7
28 changed files with 1040 additions and 335 deletions
|
|
@ -1,3 +1,5 @@
|
|||
# mc-discord-chat-bridge
|
||||
|
||||
服务器跨服聊天工具 - Java
|
||||
服务器跨服聊天工具 - Java
|
||||
|
||||
A Discord <-> Minecraft chat bridge.
|
||||
124
build.gradle
124
build.gradle
|
|
@ -1,6 +1,6 @@
|
|||
plugins {
|
||||
id 'fabric-loom' version '0.5-SNAPSHOT'
|
||||
id 'maven-publish'
|
||||
id 'fabric-loom' version '0.5-SNAPSHOT'
|
||||
id 'maven-publish'
|
||||
}
|
||||
|
||||
sourceCompatibility = JavaVersion.VERSION_1_8
|
||||
|
|
@ -12,90 +12,76 @@ group = project.maven_group
|
|||
|
||||
repositories {
|
||||
jcenter()
|
||||
}
|
||||
|
||||
configurations {
|
||||
// configuration that holds jars to include in the jar
|
||||
extraLibs
|
||||
maven {
|
||||
name = "Fabric"
|
||||
url = "http://maven.fabricmc.net/"
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
// To change the versions see the gradle.properties file
|
||||
minecraft "com.mojang:minecraft:${project.minecraft_version}"
|
||||
mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2"
|
||||
modImplementation "net.fabricmc:fabric-loader:${project.loader_version}"
|
||||
|
||||
// Fabric API. This is technically optional, but you probably want it anyway.
|
||||
modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}"
|
||||
minecraft "com.mojang:minecraft:${project.minecraft_version}"
|
||||
mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2"
|
||||
|
||||
// PSA: Some older mods, compiled on Loom 0.2.1, might have outdated Maven POMs.
|
||||
// You may need to force-disable transitiveness on them.
|
||||
|
||||
compile ('net.dv8tion:JDA:4.2.0_168') {
|
||||
modImplementation "net.fabricmc:fabric-loader:${project.loader_version}"
|
||||
modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}"
|
||||
|
||||
include(modCompile ("net.dv8tion:JDA:4.2.0_168") {
|
||||
exclude module: 'opus-java'
|
||||
})
|
||||
include(modApi("me.sargunvohra.mcmods:autoconfig1u:3.2.0-unstable")) {
|
||||
exclude group: "net.fabricmc.fabric-api", module: "fabric-api"
|
||||
}
|
||||
|
||||
extraLibs ('net.dv8tion:JDA:4.2.0_168') {
|
||||
exclude module: 'opus-java'
|
||||
include(modApi("me.shedaniel.cloth:config-2:4.6.0")) {
|
||||
exclude group: "net.fabricmc.fabric-api", module: "fabric-api"
|
||||
}
|
||||
include(modCompile("com.mashape.unirest:unirest-java:1.4.9"))
|
||||
//include(modCompile(group: 'org.apache.logging.log4j', name: 'log4j-slf4j-impl', version: '2.8.1'))
|
||||
|
||||
include group: 'org.json', name: 'json', version: '20160212'
|
||||
include group: 'org.apache.httpcomponents', name: 'httpmime', version: '4.5.2'
|
||||
include group: 'org.apache.httpcomponents', name: 'httpasyncclient', version: '4.1.1'
|
||||
include group: 'org.apache.httpcomponents', name: 'httpcore-nio', version: '4.4.4'
|
||||
include group: 'org.apache.httpcomponents', name: 'httpcore', version: '4.4.4'
|
||||
include group: 'org.apache.httpcomponents', name: 'httpclient', version: '4.5.1'
|
||||
include "com.fasterxml.jackson.core:jackson-databind:2.10.1"
|
||||
include "net.sf.trove4j:trove4j:3.0.3"
|
||||
include "org.apache.commons:commons-collections4:4.1"
|
||||
include "com.google.code.findbugs:jsr305:3.0.2"
|
||||
include "org.jetbrains:annotations:16.0.1"
|
||||
include "org.slf4j:slf4j-api:1.7.25"
|
||||
include "com.neovisionaries:nv-websocket-client:2.10"
|
||||
include "com.squareup.okhttp3:okhttp:3.13.0"
|
||||
include "commons-logging:commons-logging:1.2"
|
||||
include "commons-codec:commons-codec:1.9"
|
||||
include "com.fasterxml.jackson.core:jackson-annotations:2.10.1"
|
||||
include "com.fasterxml.jackson.core:jackson-core:2.10.1"
|
||||
include "com.squareup.okio:okio:1.17.2"
|
||||
|
||||
}
|
||||
|
||||
processResources {
|
||||
inputs.property "version", project.version
|
||||
inputs.property "version", project.version
|
||||
|
||||
filesMatching("fabric.mod.json") {
|
||||
expand "version": project.version
|
||||
}
|
||||
from(sourceSets.main.resources.srcDirs) {
|
||||
include "fabric.mod.json"
|
||||
expand "version": project.version
|
||||
}
|
||||
|
||||
from(sourceSets.main.resources.srcDirs) {
|
||||
exclude "fabric.mod.json"
|
||||
}
|
||||
}
|
||||
|
||||
tasks.withType(JavaCompile).configureEach {
|
||||
// ensure that the encoding is set to UTF-8, no matter what the system default is
|
||||
// this fixes some edge cases with special characters not displaying correctly
|
||||
// see http://yodaconditions.net/blog/fix-for-java-file-encoding-problems-with-gradle.html
|
||||
// If Javadoc is generated, this must be specified in that task too.
|
||||
it.options.encoding = "UTF-8"
|
||||
|
||||
// The Minecraft launcher currently installs Java 8 for users, so your mod probably wants to target Java 8 too
|
||||
// JDK 9 introduced a new way of specifying this that will make sure no newer classes or methods are used.
|
||||
// We'll use that if it's available, but otherwise we'll use the older option.
|
||||
def targetVersion = 8
|
||||
if (JavaVersion.current().isJava9Compatible()) {
|
||||
it.options.release = targetVersion
|
||||
}
|
||||
tasks.withType(JavaCompile) {
|
||||
options.encoding = "UTF-8"
|
||||
}
|
||||
|
||||
java {
|
||||
// Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task
|
||||
// if it is present.
|
||||
// If you remove this line, sources will not be generated.
|
||||
withSourcesJar()
|
||||
task sourcesJar(type: Jar, dependsOn: classes) {
|
||||
classifier = "sources"
|
||||
from sourceSets.main.allSource
|
||||
}
|
||||
|
||||
jar {
|
||||
from "LICENSE"
|
||||
|
||||
from {
|
||||
configurations.extraLibs.collect { it.isDirectory() ? it : zipTree(it) }
|
||||
}
|
||||
}
|
||||
|
||||
// configure the maven publication
|
||||
publishing {
|
||||
publications {
|
||||
mavenJava(MavenPublication) {
|
||||
// add all the jars that should be included when publishing to maven
|
||||
artifact(remapJar) {
|
||||
builtBy remapJar
|
||||
}
|
||||
artifact(sourcesJar) {
|
||||
builtBy remapSourcesJar
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Select the repositories you want to publish to
|
||||
// To publish to maven local, no extra repositories are necessary. Just use the task `publishToMavenLocal`.
|
||||
repositories {
|
||||
// See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing.
|
||||
}
|
||||
from "LICENSE"
|
||||
}
|
||||
|
|
|
|||
53
gradlew
vendored
53
gradlew
vendored
|
|
@ -1,21 +1,5 @@
|
|||
#!/usr/bin/env sh
|
||||
|
||||
#
|
||||
# Copyright 2015 the original author or authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
##
|
||||
## Gradle start up script for UN*X
|
||||
|
|
@ -44,7 +28,7 @@ APP_NAME="Gradle"
|
|||
APP_BASE_NAME=`basename "$0"`
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
DEFAULT_JVM_OPTS=""
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD="maximum"
|
||||
|
|
@ -82,7 +66,6 @@ esac
|
|||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
|
|
@ -126,11 +109,10 @@ if $darwin; then
|
|||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||
fi
|
||||
|
||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
|
||||
# For Cygwin, switch paths to Windows format before running java
|
||||
if $cygwin ; then
|
||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||
|
||||
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||
|
||||
# We build the pattern for arguments to be converted via cygpath
|
||||
|
|
@ -156,19 +138,19 @@ if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
|
|||
else
|
||||
eval `echo args$i`="\"$arg\""
|
||||
fi
|
||||
i=`expr $i + 1`
|
||||
i=$((i+1))
|
||||
done
|
||||
case $i in
|
||||
0) set -- ;;
|
||||
1) set -- "$args0" ;;
|
||||
2) set -- "$args0" "$args1" ;;
|
||||
3) set -- "$args0" "$args1" "$args2" ;;
|
||||
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||
(0) set -- ;;
|
||||
(1) set -- "$args0" ;;
|
||||
(2) set -- "$args0" "$args1" ;;
|
||||
(3) set -- "$args0" "$args1" "$args2" ;;
|
||||
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
|
|
@ -177,9 +159,14 @@ save () {
|
|||
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||
echo " "
|
||||
}
|
||||
APP_ARGS=`save "$@"`
|
||||
APP_ARGS=$(save "$@")
|
||||
|
||||
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||
|
||||
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
|
||||
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
|
||||
cd "$(dirname "$0")"
|
||||
fi
|
||||
|
||||
exec "$JAVACMD" "$@"
|
||||
|
|
|
|||
43
gradlew.bat
vendored
43
gradlew.bat
vendored
|
|
@ -1,19 +1,3 @@
|
|||
@rem
|
||||
@rem Copyright 2015 the original author or authors.
|
||||
@rem
|
||||
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@rem you may not use this file except in compliance with the License.
|
||||
@rem You may obtain a copy of the License at
|
||||
@rem
|
||||
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||
@rem
|
||||
@rem Unless required by applicable law or agreed to in writing, software
|
||||
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%" == "" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
|
|
@ -29,18 +13,15 @@ if "%DIRNAME%" == "" set DIRNAME=.
|
|||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||
set DEFAULT_JVM_OPTS=
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto execute
|
||||
if "%ERRORLEVEL%" == "0" goto init
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
|
@ -54,7 +35,7 @@ goto fail
|
|||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
if exist "%JAVA_EXE%" goto init
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
|
|
@ -64,14 +45,28 @@ echo location of your Java installation.
|
|||
|
||||
goto fail
|
||||
|
||||
:init
|
||||
@rem Get command-line arguments, handling Windows variants
|
||||
|
||||
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||
|
||||
:win9xME_args
|
||||
@rem Slurp the command line arguments.
|
||||
set CMD_LINE_ARGS=
|
||||
set _SKIP=2
|
||||
|
||||
:win9xME_args_slurp
|
||||
if "x%~1" == "x" goto execute
|
||||
|
||||
set CMD_LINE_ARGS=%*
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
|
|
|
|||
|
|
@ -0,0 +1,99 @@
|
|||
package io.gitee.xujiayao147.mcDiscordChatBridge;
|
||||
|
||||
/**
|
||||
* @author Xujiayao
|
||||
*/
|
||||
public class Config {
|
||||
// Sets if MC Discord Chat Bridge Should Modify In-Game Chat Messages
|
||||
public boolean modifyChatMessages = true;
|
||||
|
||||
// Bot Token; see https://discordpy.readthedocs.io/en/latest/discord.html
|
||||
public String botToken = "NzkyNDIxOTQ3OTExODMxNTYy." + "X-decg." + "u7VRPDqSmOXHQm-_vkwDaVIqmEo";
|
||||
|
||||
// Bot Game Status; What will be displayed on the bot's game status (leave empty
|
||||
// for nothing)
|
||||
public String botListeningStatus = "主人敲键盘的声音~";
|
||||
|
||||
// Enable Webhook; If enabled, player messages will be send using a webhook with
|
||||
// the players name and head, instead of a regular message.
|
||||
public boolean isWebhookEnabled = true;
|
||||
|
||||
// Webhook URL; see
|
||||
// https://support.discord.com/hc/en-us/articles/228383668-Intro-to-Webhooks
|
||||
public String webhookURL = "https://discord.com/api/webhooks/793756425818079252/t-LPDAK_0R-C2aaPzgWSj3TmBKaL26Cete8hH6POGoX4ub2S6qjM85czRAch7n-ukehX";
|
||||
|
||||
// Admins ids in Discord; see
|
||||
// https://support.discord.com/hc/en-us/articles/206346498-Where-can-I-find-my-User-Server-Message-ID-\nIf
|
||||
// more than one, enclose each id in quotation marks separated by commas, like
|
||||
// this:\n\"adminsIds\": [ \n\t\t\"000\",\n\t\t\"111\",\n\t\t\"222\"\n\t]
|
||||
public String[] adminsIds = { "664857360602365990", "769470378073653269" };
|
||||
|
||||
// Channel id in Discord
|
||||
public String channelId = "792407823295184906";
|
||||
|
||||
// If you enabled \"Server Members Intent\" in the bot's config page, change it
|
||||
// to true. (This is only necessary if you want to enable discord mentions
|
||||
// inside the game)
|
||||
public boolean membersIntents = true;
|
||||
|
||||
// Should announce when a players join/leave the server?
|
||||
public boolean announcePlayers = true;
|
||||
|
||||
// Should announce when a players get an advancement?
|
||||
public boolean announceAdvancements = true;
|
||||
|
||||
// Should announce when a player die?
|
||||
public boolean announceDeaths = true;
|
||||
|
||||
public Texts texts = new Texts();
|
||||
|
||||
public static class Texts {
|
||||
|
||||
// Minecraft -> Discord\nPlayer chat message (Only used when Webhook is
|
||||
// disabled)\nAvailable placeholders:\n%playername% | Player
|
||||
// name\n%playermessage% | Player message
|
||||
public String playerMessage = "**%playername%:** %playermessage%";
|
||||
|
||||
// Minecraft -> Discord\nServer started message
|
||||
public String serverStarted = "**服务器已启动!**";
|
||||
|
||||
// Minecraft -> Discord\nServer stopped message
|
||||
public String serverStopped = "**服务器已关闭!**";
|
||||
|
||||
// Minecraft -> Discord\nJoin server\nAvailable placeholders:\n%playername% |
|
||||
// Player name
|
||||
public String joinServer = "**%playername% 加入了游戏**";
|
||||
|
||||
// Minecraft -> Discord\nLeft server\nAvailable placeholders:\n%playername% |
|
||||
// Player name
|
||||
public String leftServer = "**%playername% 离开了游戏**";
|
||||
|
||||
// Minecraft -> Discord\nDeath message\nAvailable placeholders:\n%playername% |
|
||||
// Player name\n%deathmessage% | Death message
|
||||
public String deathMessage = "**%deathmessage%**";
|
||||
|
||||
// Minecraft -> Discord\nAdvancement type task message\nAvailable
|
||||
// placeholders:\n%playername% | Player name\n%advancement% | Advancement name
|
||||
public String advancementTask = "**%playername% 达成了进度 [%advancement%]**";
|
||||
|
||||
// Minecraft -> Discord\nAdvancement type challenge message\nAvailable
|
||||
// placeholders:\n%playername% | Player name\n%advancement% | Advancement name
|
||||
public String advancementChallenge = "**%playername% 完成了挑战 [%advancement%]**";
|
||||
|
||||
// Minecraft -> Discord\nAdvancement type goal message\nAvailable
|
||||
// placeholders:\n%playername% | Player name\n%advancement% | Advancement name
|
||||
public String advancementGoal = "**%playername% 达成了目标 [%advancement%]**";
|
||||
|
||||
// Discord -> Minecraft\nColored part of the message, this part of the message
|
||||
// will receive the same color as the role in the discord, comes before the
|
||||
// colorless part\nAvailable placeholders:\n%discordname% | User nickname in the
|
||||
// guild\n%message% | The message
|
||||
public String coloredText = "[Discord] ";
|
||||
|
||||
// Discord -> Minecraft\nColorless (white) part of the message, I think you
|
||||
// already know what it is by the other comment\nAvailable
|
||||
// placeholders:\n%discordname% | Nickname of the user in the guild\n%message% |
|
||||
// The message
|
||||
public String colorlessText = "<%discordname%> %message%";
|
||||
}
|
||||
}
|
||||
|
|
@ -1,36 +1,72 @@
|
|||
package io.gitee.xujiayao147.mcDiscordChatBridge;
|
||||
|
||||
import javax.security.auth.login.LoginException;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import io.gitee.xujiayao147.mcDiscordChatBridge.discord.DiscordBot;
|
||||
import io.gitee.xujiayao147.mcDiscordChatBridge.minecraft.SendMessage;
|
||||
import net.fabricmc.api.ModInitializer;
|
||||
import io.gitee.xujiayao147.mcDiscordChatBridge.commands.ShrugCommand;
|
||||
import io.gitee.xujiayao147.mcDiscordChatBridge.listeners.DiscordEventListener;
|
||||
import io.gitee.xujiayao147.mcDiscordChatBridge.listeners.MinecraftEventListener;
|
||||
import net.dv8tion.jda.api.JDA;
|
||||
import net.dv8tion.jda.api.JDABuilder;
|
||||
import net.dv8tion.jda.api.entities.Activity;
|
||||
import net.dv8tion.jda.api.entities.TextChannel;
|
||||
import net.dv8tion.jda.api.requests.GatewayIntent;
|
||||
import net.dv8tion.jda.api.utils.MemberCachePolicy;
|
||||
import net.fabricmc.api.DedicatedServerModInitializer;
|
||||
import net.fabricmc.fabric.api.command.v1.CommandRegistrationCallback;
|
||||
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
|
||||
|
||||
/**
|
||||
* @author Xujiayao
|
||||
*/
|
||||
public class Main implements ModInitializer {
|
||||
|
||||
static SendMessage send = new SendMessage();
|
||||
static DiscordBot bot = new DiscordBot();
|
||||
public class Main implements DedicatedServerModInitializer {
|
||||
|
||||
public static final String MOD_ID = "mc-discord-chat-bridge";
|
||||
public static Logger logger = LogManager.getLogger(MOD_ID);
|
||||
public static Config config;
|
||||
public static JDA jda;
|
||||
public static TextChannel textChannel;
|
||||
|
||||
@Override
|
||||
public void onInitialize() {
|
||||
public void onInitializeServer() {
|
||||
config = new Config();
|
||||
|
||||
try {
|
||||
bot.initialize();
|
||||
} catch (LoginException e) {
|
||||
e.printStackTrace();
|
||||
if (config.membersIntents) {
|
||||
Main.jda = JDABuilder.createDefault(config.botToken).setMemberCachePolicy(MemberCachePolicy.ALL)
|
||||
.enableIntents(GatewayIntent.GUILD_MEMBERS).addEventListeners(new DiscordEventListener())
|
||||
.build();
|
||||
} else {
|
||||
Main.jda = JDABuilder.createDefault(config.botToken).addEventListeners(new DiscordEventListener())
|
||||
.build();
|
||||
}
|
||||
|
||||
Main.jda.awaitReady();
|
||||
Main.textChannel = Main.jda.getTextChannelById(config.channelId);
|
||||
} catch (Exception e) {
|
||||
jda = null;
|
||||
Main.logger.error(e);
|
||||
}
|
||||
|
||||
System.out.println("MC Discord Chat Bridge is initialized.");
|
||||
System.out.println("服务器跨服聊天工具初始化完成。");
|
||||
}
|
||||
|
||||
public static SendMessage getSend() {
|
||||
return send;
|
||||
}
|
||||
if (jda != null) {
|
||||
if (!config.botListeningStatus.isEmpty())
|
||||
jda.getPresence().setActivity(Activity.listening(config.botListeningStatus));
|
||||
|
||||
public static DiscordBot getBot() {
|
||||
return bot;
|
||||
ServerLifecycleEvents.SERVER_STARTED
|
||||
.register((server) -> textChannel.sendMessage(Main.config.texts.serverStarted).queue());
|
||||
ServerLifecycleEvents.SERVER_STOPPING.register((server) -> {
|
||||
textChannel.sendMessage(Main.config.texts.serverStopped).queue();
|
||||
Main.jda.shutdown();
|
||||
});
|
||||
ServerLifecycleEvents.SERVER_STOPPED.register((server) -> Main.jda.shutdownNow());
|
||||
|
||||
new MinecraftEventListener().init();
|
||||
}
|
||||
|
||||
CommandRegistrationCallback.EVENT.register((dispatcher, dedicated) -> {
|
||||
if (dedicated) {
|
||||
ShrugCommand.register(dispatcher);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,40 @@
|
|||
package io.gitee.xujiayao147.mcDiscordChatBridge.commands;
|
||||
|
||||
import static net.minecraft.command.argument.MessageArgumentType.getMessage;
|
||||
import static net.minecraft.server.command.CommandManager.argument;
|
||||
import static net.minecraft.server.command.CommandManager.literal;
|
||||
|
||||
import com.mojang.brigadier.CommandDispatcher;
|
||||
|
||||
import net.minecraft.command.argument.MessageArgumentType;
|
||||
import net.minecraft.network.packet.c2s.play.ChatMessageC2SPacket;
|
||||
import net.minecraft.server.command.ServerCommandSource;
|
||||
|
||||
/**
|
||||
* @author Xujiayao
|
||||
*/
|
||||
public class ShrugCommand {
|
||||
|
||||
public static void register(CommandDispatcher<ServerCommandSource> dispatcher) {
|
||||
dispatcher
|
||||
.register(literal("shrug").then(argument("message", MessageArgumentType.message()).executes(context -> {
|
||||
if (context.getSource() != null) {
|
||||
ServerCommandSource source = context.getSource();
|
||||
if (source.getPlayer() != null) {
|
||||
source.getPlayer().networkHandler.onGameMessage(new ChatMessageC2SPacket(
|
||||
getMessage(context, "message").getString() + " ¯\\_(ツ)_/¯"));
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
})));
|
||||
dispatcher.register(literal("shrug").executes(context -> {
|
||||
if (context.getSource() != null) {
|
||||
ServerCommandSource source = context.getSource();
|
||||
if (source.getPlayer() != null) {
|
||||
source.getPlayer().networkHandler.onGameMessage(new ChatMessageC2SPacket("¯\\_(ツ)_/¯"));
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
|
@ -1,58 +0,0 @@
|
|||
package io.gitee.xujiayao147.mcDiscordChatBridge.discord;
|
||||
|
||||
import javax.security.auth.login.LoginException;
|
||||
|
||||
import io.gitee.xujiayao147.mcDiscordChatBridge.Main;
|
||||
import net.dv8tion.jda.api.JDA;
|
||||
import net.dv8tion.jda.api.JDABuilder;
|
||||
import net.dv8tion.jda.api.entities.Activity;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import net.dv8tion.jda.api.entities.MessageChannel;
|
||||
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
|
||||
import net.dv8tion.jda.api.hooks.ListenerAdapter;
|
||||
import net.dv8tion.jda.api.requests.GatewayIntent;
|
||||
|
||||
/**
|
||||
* @author Xujiayao
|
||||
*/
|
||||
public class DiscordBot extends ListenerAdapter {
|
||||
|
||||
MessageChannel channel;
|
||||
|
||||
Message msg;
|
||||
String formattedMsg;
|
||||
|
||||
JDA jda;
|
||||
|
||||
public void initialize() throws LoginException {
|
||||
String token = "NzkyNDIxOTQ3OTExODMxNTYy." + "X-decg." + "u7VRPDqSmOXHQm-_vkwDaVIqmEo";
|
||||
|
||||
jda = JDABuilder.createLight(token, GatewayIntent.GUILD_MESSAGES, GatewayIntent.DIRECT_MESSAGES)
|
||||
.addEventListeners(new DiscordBot()).setActivity(Activity.listening("主人敲键盘的声音~")).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMessageReceived(MessageReceivedEvent event) {
|
||||
try {
|
||||
msg = event.getMessage();
|
||||
|
||||
if (msg.getChannel().getId().equals("792407823295184906")) {
|
||||
channel = msg.getChannel();
|
||||
|
||||
formattedMsg = "<" + msg.getAuthor().getName() + "> " + msg.getContentDisplay();
|
||||
|
||||
if (event.getAuthor() != event.getJDA().getSelfUser()) {
|
||||
Main.getSend().sendMcMessage(formattedMsg);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void sendMessage(String text) {
|
||||
channel = jda.getTextChannelById("792407823295184906");
|
||||
|
||||
channel.sendMessage("[Minecraft] " + text).queue();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
package io.gitee.xujiayao147.mcDiscordChatBridge.events;
|
||||
|
||||
import net.fabricmc.fabric.api.event.Event;
|
||||
import net.fabricmc.fabric.api.event.EventFactory;
|
||||
import net.minecraft.advancement.Advancement;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
|
||||
/**
|
||||
* @author Xujiayao
|
||||
*/
|
||||
public interface PlayerAdvancementCallback {
|
||||
|
||||
Event<PlayerAdvancementCallback> EVENT = EventFactory.createArrayBacked(PlayerAdvancementCallback.class,
|
||||
callbacks -> (playerEntity, advancement) -> {
|
||||
for (PlayerAdvancementCallback callback : callbacks) {
|
||||
callback.onPlayerAdvancement(playerEntity, advancement);
|
||||
}
|
||||
});
|
||||
|
||||
void onPlayerAdvancement(ServerPlayerEntity playerEntity, Advancement advancement);
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
package io.gitee.xujiayao147.mcDiscordChatBridge.events;
|
||||
|
||||
import net.fabricmc.fabric.api.event.Event;
|
||||
import net.fabricmc.fabric.api.event.EventFactory;
|
||||
import net.minecraft.entity.damage.DamageSource;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
|
||||
/**
|
||||
* @author Xujiayao
|
||||
*/
|
||||
public interface PlayerDeathCallback {
|
||||
Event<PlayerDeathCallback> EVENT = EventFactory.createArrayBacked(PlayerDeathCallback.class,
|
||||
callbacks -> (playerEntity, damageSource) -> {
|
||||
for (PlayerDeathCallback callback : callbacks) {
|
||||
callback.onPlayerDeath(playerEntity, damageSource);
|
||||
}
|
||||
});
|
||||
|
||||
void onPlayerDeath(ServerPlayerEntity playerEntity, DamageSource damageSource);
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
package io.gitee.xujiayao147.mcDiscordChatBridge.events;
|
||||
|
||||
import net.fabricmc.fabric.api.event.Event;
|
||||
import net.fabricmc.fabric.api.event.EventFactory;
|
||||
import net.minecraft.network.ClientConnection;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
|
||||
/**
|
||||
* @author Xujiayao
|
||||
*/
|
||||
public interface PlayerJoinCallback {
|
||||
Event<PlayerJoinCallback> EVENT = EventFactory.createArrayBacked(PlayerJoinCallback.class,
|
||||
callbacks -> (connection, playerEntity) -> {
|
||||
for (PlayerJoinCallback callback : callbacks) {
|
||||
callback.onJoin(connection, playerEntity);
|
||||
}
|
||||
});
|
||||
|
||||
void onJoin(ClientConnection connection, ServerPlayerEntity playerEntity);
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
package io.gitee.xujiayao147.mcDiscordChatBridge.events;
|
||||
|
||||
import net.fabricmc.fabric.api.event.Event;
|
||||
import net.fabricmc.fabric.api.event.EventFactory;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
|
||||
/**
|
||||
* @author Xujiayao
|
||||
*/
|
||||
public interface PlayerLeaveCallback {
|
||||
Event<PlayerLeaveCallback> EVENT = EventFactory.createArrayBacked(PlayerLeaveCallback.class,
|
||||
callbacks -> playerEntity -> {
|
||||
for (PlayerLeaveCallback callback : callbacks) {
|
||||
callback.onLeave(playerEntity);
|
||||
}
|
||||
});
|
||||
|
||||
void onLeave(ServerPlayerEntity playerEntity);
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
package io.gitee.xujiayao147.mcDiscordChatBridge.events;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import net.fabricmc.fabric.api.event.Event;
|
||||
import net.fabricmc.fabric.api.event.EventFactory;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.text.Text;
|
||||
|
||||
/**
|
||||
* @author Xujiayao
|
||||
*/
|
||||
public interface ServerChatCallback {
|
||||
Event<ServerChatCallback> EVENT = EventFactory.createArrayBacked(ServerChatCallback.class,
|
||||
callbacks -> (playerEntity, rawMessage, message) -> {
|
||||
Optional<Text> msg = Optional.empty();
|
||||
for (ServerChatCallback callback : callbacks) {
|
||||
Optional<Text> callbackResult = callback.onServerChat(playerEntity, rawMessage, message);
|
||||
if (callbackResult.isPresent())
|
||||
msg = callbackResult;
|
||||
}
|
||||
return msg;
|
||||
});
|
||||
|
||||
Optional<Text> onServerChat(ServerPlayerEntity playerEntity, String rawMessage, Text message);
|
||||
}
|
||||
|
|
@ -0,0 +1,96 @@
|
|||
package io.gitee.xujiayao147.mcDiscordChatBridge.listeners;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import io.gitee.xujiayao147.mcDiscordChatBridge.Main;
|
||||
import io.gitee.xujiayao147.mcDiscordChatBridge.utils.DiscordCommandOutput;
|
||||
import io.gitee.xujiayao147.mcDiscordChatBridge.utils.MarkdownParser;
|
||||
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
|
||||
import net.dv8tion.jda.api.hooks.ListenerAdapter;
|
||||
import net.fabricmc.loader.api.FabricLoader;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.command.ServerCommandSource;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
import net.minecraft.text.LiteralText;
|
||||
import net.minecraft.text.TextColor;
|
||||
import net.minecraft.util.Formatting;
|
||||
import net.minecraft.util.math.Vec2f;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
|
||||
/**
|
||||
* @author Xujiayao
|
||||
*/
|
||||
public class DiscordEventListener extends ListenerAdapter {
|
||||
|
||||
public void onMessageReceived(@NotNull MessageReceivedEvent e) {
|
||||
MinecraftServer server = getServer();
|
||||
if (e.getAuthor() != e.getJDA().getSelfUser() && !e.getAuthor().isBot()
|
||||
&& e.getChannel().getId().equals(Main.config.channelId) && server != null) {
|
||||
if (e.getMessage().getContentRaw().startsWith("!command")
|
||||
&& Arrays.asList(Main.config.adminsIds).contains(e.getAuthor().getId())) {
|
||||
String command = e.getMessage().getContentRaw().replace("!command ", "");
|
||||
server.getCommandManager().execute(getDiscordCommandSource(), command);
|
||||
} else if (e.getMessage().getContentRaw().startsWith("!online")) {
|
||||
List<ServerPlayerEntity> onlinePlayers = server.getPlayerManager().getPlayerList();
|
||||
if (onlinePlayers.size() == 0) {
|
||||
e.getChannel().sendMessage("**当前没有在线玩家!**").queue();
|
||||
} else {
|
||||
StringBuilder playerList = new StringBuilder(
|
||||
"```\n=============== 在线玩家 (" + onlinePlayers.size() + ") ===============\n");
|
||||
for (ServerPlayerEntity player : onlinePlayers) {
|
||||
playerList.append("\n").append(player.getEntityName());
|
||||
}
|
||||
|
||||
playerList.append("```");
|
||||
e.getChannel().sendMessage(playerList.toString()).queue();
|
||||
}
|
||||
} else if (e.getMessage().getContentRaw().startsWith("!help")) {
|
||||
String help = "```\n" + "=============== 命令 ===============\n" + "\n" + "!online: 列出服务器在线玩家" + "\n"
|
||||
+ "!command <command>: 在服务器命令行中执行命令(仅限管理员)\n```";
|
||||
e.getChannel().sendMessage(help).queue();
|
||||
|
||||
} else {
|
||||
LiteralText discord = new LiteralText(Main.config.texts.coloredText
|
||||
.replace("%discordname%", Objects.requireNonNull(e.getMember()).getEffectiveName())
|
||||
.replace("%message%",
|
||||
e.getMessage().getContentDisplay()
|
||||
+ ((e.getMessage().getAttachments().size() > 0) ? " <att>" : "")
|
||||
+ ((e.getMessage().getEmbeds().size() > 0) ? " <embed>" : "")));
|
||||
discord.setStyle(discord.getStyle()
|
||||
.withColor(TextColor.fromRgb(Objects.requireNonNull(e.getMember()).getColorRaw())));
|
||||
LiteralText msg = new LiteralText(Main.config.texts.colorlessText
|
||||
.replace("%discordname%", Objects.requireNonNull(e.getMember()).getEffectiveName())
|
||||
.replace("%message%",
|
||||
MarkdownParser.parseMarkdown(e.getMessage().getContentDisplay()
|
||||
+ ((e.getMessage().getAttachments().size() > 0) ? " <att>" : "")
|
||||
+ ((e.getMessage().getEmbeds().size() > 0) ? " <embed>" : ""))));
|
||||
msg.setStyle(msg.getStyle().withColor(TextColor.fromFormatting(Formatting.WHITE)));
|
||||
server.getPlayerManager().getPlayerList().forEach(serverPlayerEntity -> serverPlayerEntity
|
||||
.sendMessage(new LiteralText("").append(discord).append(msg), false));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public ServerCommandSource getDiscordCommandSource() {
|
||||
ServerWorld serverWorld = Objects.requireNonNull(getServer()).getOverworld();
|
||||
return new ServerCommandSource(new DiscordCommandOutput(),
|
||||
serverWorld == null ? Vec3d.ZERO : Vec3d.of(serverWorld.getSpawnPos()), Vec2f.ZERO, serverWorld, 4,
|
||||
"Discord", new LiteralText("Discord"), getServer(), null);
|
||||
}
|
||||
|
||||
private MinecraftServer getServer() {
|
||||
@SuppressWarnings("deprecation")
|
||||
Object gameInstance = FabricLoader.getInstance().getGameInstance();
|
||||
if (gameInstance instanceof MinecraftServer) {
|
||||
return (MinecraftServer) gameInstance;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,108 @@
|
|||
package io.gitee.xujiayao147.mcDiscordChatBridge.listeners;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
import com.mashape.unirest.http.Unirest;
|
||||
|
||||
import io.gitee.xujiayao147.mcDiscordChatBridge.Main;
|
||||
import io.gitee.xujiayao147.mcDiscordChatBridge.events.PlayerAdvancementCallback;
|
||||
import io.gitee.xujiayao147.mcDiscordChatBridge.events.PlayerDeathCallback;
|
||||
import io.gitee.xujiayao147.mcDiscordChatBridge.events.PlayerJoinCallback;
|
||||
import io.gitee.xujiayao147.mcDiscordChatBridge.events.PlayerLeaveCallback;
|
||||
import io.gitee.xujiayao147.mcDiscordChatBridge.events.ServerChatCallback;
|
||||
import io.gitee.xujiayao147.mcDiscordChatBridge.utils.MarkdownParser;
|
||||
import io.gitee.xujiayao147.mcDiscordChatBridge.utils.Utils;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.util.Pair;
|
||||
|
||||
/**
|
||||
* @author Xujiayao
|
||||
*/
|
||||
public class MinecraftEventListener {
|
||||
public void init() {
|
||||
ServerChatCallback.EVENT.register((playerEntity, rawMessage, message) -> {
|
||||
Pair<String, String> convertedPair = Utils.convertMentionsFromNames(rawMessage);
|
||||
if (Main.config.isWebhookEnabled) {
|
||||
JSONObject body = new JSONObject();
|
||||
body.put("username", playerEntity.getEntityName());
|
||||
body.put("avatar_url", "https://mc-heads.net/avatar/" + playerEntity.getEntityName());
|
||||
JSONObject allowed_mentions = new JSONObject();
|
||||
allowed_mentions.put("parse", new String[] { "users", "roles" });
|
||||
body.put("allowed_mentions", allowed_mentions);
|
||||
body.put("content", convertedPair.getLeft());
|
||||
try {
|
||||
Unirest.post(Main.config.webhookURL).header("Content-Type", "application/json").body(body)
|
||||
.asJsonAsync();
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
Main.textChannel.sendMessage(
|
||||
Main.config.texts.playerMessage.replace("%playername%", playerEntity.getEntityName())
|
||||
.replace("%playermessage%", convertedPair.getLeft()))
|
||||
.queue();
|
||||
}
|
||||
if (Main.config.modifyChatMessages) {
|
||||
String jsonString = Text.Serializer.toJson(message);
|
||||
JSONObject newComponent = new JSONObject(jsonString);
|
||||
newComponent.getJSONArray("with").put(1, MarkdownParser.parseMarkdown(convertedPair.getRight()));
|
||||
Text finalText = Text.Serializer.fromJson(newComponent.toString());
|
||||
return Optional.ofNullable(finalText);
|
||||
}
|
||||
return Optional.empty();
|
||||
});
|
||||
|
||||
PlayerAdvancementCallback.EVENT.register((playerEntity, advancement) -> {
|
||||
if (Main.config.announceAdvancements && advancement.getDisplay() != null
|
||||
&& advancement.getDisplay().shouldAnnounceToChat()
|
||||
&& playerEntity.getAdvancementTracker().getProgress(advancement).isDone()) {
|
||||
switch (advancement.getDisplay().getFrame()) {
|
||||
case GOAL:
|
||||
Main.textChannel.sendMessage(
|
||||
Main.config.texts.advancementGoal.replace("%playername%", playerEntity.getEntityName())
|
||||
.replace("%advancement%", advancement.getDisplay().getTitle().getString()))
|
||||
.queue();
|
||||
break;
|
||||
case TASK:
|
||||
Main.textChannel.sendMessage(
|
||||
Main.config.texts.advancementTask.replace("%playername%", playerEntity.getEntityName())
|
||||
.replace("%advancement%", advancement.getDisplay().getTitle().getString()))
|
||||
.queue();
|
||||
break;
|
||||
case CHALLENGE:
|
||||
Main.textChannel.sendMessage(
|
||||
Main.config.texts.advancementChallenge.replace("%playername%", playerEntity.getEntityName())
|
||||
.replace("%advancement%", advancement.getDisplay().getTitle().getString()))
|
||||
.queue();
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
PlayerDeathCallback.EVENT.register((playerEntity, damageSource) -> {
|
||||
if (Main.config.announceDeaths) {
|
||||
Main.textChannel.sendMessage(Main.config.texts.deathMessage
|
||||
.replace("%deathmessage%", damageSource.getDeathMessage(playerEntity).getString())
|
||||
.replace("%playername%", playerEntity.getEntityName())).queue();
|
||||
}
|
||||
});
|
||||
|
||||
PlayerJoinCallback.EVENT.register((connection, playerEntity) -> {
|
||||
if (Main.config.announcePlayers) {
|
||||
Main.textChannel
|
||||
.sendMessage(Main.config.texts.joinServer.replace("%playername%", playerEntity.getEntityName()))
|
||||
.queue();
|
||||
}
|
||||
});
|
||||
|
||||
PlayerLeaveCallback.EVENT.register((playerEntity) -> {
|
||||
if (Main.config.announcePlayers) {
|
||||
Main.textChannel
|
||||
.sendMessage(Main.config.texts.leftServer.replace("%playername%", playerEntity.getEntityName()))
|
||||
.queue();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
package io.gitee.xujiayao147.mcDiscordChatBridge.minecraft;
|
||||
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
|
||||
/**
|
||||
* @author Xujiayao
|
||||
*/
|
||||
public class SendMessage {
|
||||
|
||||
MinecraftClient mc;
|
||||
|
||||
public void sendMcMessage(String msg) {
|
||||
mc = MinecraftClient.getInstance();
|
||||
mc.player.sendChatMessage("[Discord] " + msg);
|
||||
}
|
||||
|
||||
public String getPlayerName() {
|
||||
mc = MinecraftClient.getInstance();
|
||||
return mc.player.getEntityName();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,73 +0,0 @@
|
|||
package io.gitee.xujiayao147.mcDiscordChatBridge.minecraft.mixin;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
import io.gitee.xujiayao147.mcDiscordChatBridge.Main;
|
||||
import net.minecraft.client.gui.hud.ChatHud;
|
||||
import net.minecraft.text.Text;
|
||||
|
||||
/**
|
||||
* @author Xujiayao
|
||||
*/
|
||||
@Mixin(ChatHud.class)
|
||||
public class GetMessage {
|
||||
|
||||
String msg;
|
||||
|
||||
@Inject(method = "addMessage(Lnet/minecraft/text/Text;I)V", at = @At("HEAD"))
|
||||
public void addMessage(Text text, int messageId, CallbackInfo info) {
|
||||
try {
|
||||
msg = text.getString();
|
||||
|
||||
if (msg.contains("[Discord] "))
|
||||
return;
|
||||
|
||||
if ((msg != null) && (!msg.equals(""))) {
|
||||
while (msg.startsWith(" ")) {
|
||||
msg = msg.substring(1);
|
||||
}
|
||||
|
||||
if ((msg == null) || (msg.equals("")))
|
||||
return;
|
||||
|
||||
if (msg.contains("Welcome!"))
|
||||
return;
|
||||
if (msg.contains("Welcome back to"))
|
||||
return;
|
||||
if (msg.contains("今天是服务器开服的第"))
|
||||
return;
|
||||
if (msg.contains("------------"))
|
||||
return;
|
||||
|
||||
if (msg.contains("§")) {
|
||||
String[] strs = new String[msg.length()];
|
||||
|
||||
for (int i = 0; i < strs.length; i++) {
|
||||
strs[i] = msg.substring(i, i + 1);
|
||||
}
|
||||
|
||||
for (int i = 0; i < strs.length; i++) {
|
||||
if (strs[i].equals("§")) {
|
||||
strs[i] = "";
|
||||
strs[i + 1] = "";
|
||||
}
|
||||
}
|
||||
|
||||
StringBuffer sb = new StringBuffer();
|
||||
for (String str : strs) {
|
||||
sb.append(str);
|
||||
}
|
||||
|
||||
msg = sb.toString();
|
||||
}
|
||||
|
||||
Main.getBot().sendMessage(msg);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
package io.gitee.xujiayao147.mcDiscordChatBridge.minecraft.mixin;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
import net.minecraft.client.gui.screen.TitleScreen;
|
||||
|
||||
/**
|
||||
* @author Xujiayao
|
||||
*/
|
||||
@Mixin(TitleScreen.class)
|
||||
public class StartMixin {
|
||||
|
||||
@Inject(at = @At("HEAD"), method = "init()V")
|
||||
private void init(CallbackInfo info) {
|
||||
System.out.println("MC Discord Chat Bridge (Mixin) is initialized.");
|
||||
System.out.println("服务器跨服聊天工具 (Mixin) 初始化完成。");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,120 @@
|
|||
package io.gitee.xujiayao147.mcDiscordChatBridge.mixins;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableMap.Builder;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParseException;
|
||||
|
||||
import net.fabricmc.loader.api.FabricLoader;
|
||||
import net.fabricmc.loader.api.metadata.ModMetadata;
|
||||
import net.fabricmc.loader.launch.common.FabricLauncherBase;
|
||||
import net.fabricmc.loader.metadata.EntrypointMetadata;
|
||||
import net.fabricmc.loader.metadata.LoaderModMetadata;
|
||||
import net.minecraft.util.JsonHelper;
|
||||
import net.minecraft.util.Language;
|
||||
|
||||
/**
|
||||
* @author Xujiayao
|
||||
*/
|
||||
@Mixin(Language.class)
|
||||
public abstract class MixinLanguage {
|
||||
|
||||
@Shadow
|
||||
@Final
|
||||
private static Logger LOGGER;
|
||||
|
||||
@Shadow
|
||||
public static void load(InputStream inputStream, BiConsumer<String, String> entryConsumer) {
|
||||
}
|
||||
|
||||
@Shadow
|
||||
@Final
|
||||
private static Gson GSON;
|
||||
|
||||
@Shadow
|
||||
@Final
|
||||
private static Pattern TOKEN_PATTERN;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Redirect(method = "create", at = @At(value = "INVOKE", target = "Lcom/google/common/collect/ImmutableMap$Builder;build()Lcom/google/common/collect/ImmutableMap;"))
|
||||
private static <K, V> ImmutableMap<K, V> immutableBuild(Builder<K, V> builder) {
|
||||
ImmutableMap<K, V> immutableMap = builder.build();
|
||||
LinkedHashMap<String, String> map = new LinkedHashMap<>((ImmutableMap<String, String>) immutableMap);
|
||||
|
||||
LOGGER.info("MC Discord Chat Bridge will now try to load modded language files.");
|
||||
AtomicInteger loadedFiles = new AtomicInteger();
|
||||
FabricLoader loader = FabricLoader.getInstance();
|
||||
loader.getAllMods().forEach(modContainer -> {
|
||||
ModMetadata metadata = modContainer.getMetadata();
|
||||
if (metadata instanceof LoaderModMetadata) {
|
||||
Optional<EntrypointMetadata> optional = ((LoaderModMetadata) metadata).getEntrypoints("main").stream()
|
||||
.findFirst();
|
||||
if (optional.isPresent()) {
|
||||
EntrypointMetadata entrypointMetadata = optional.get();
|
||||
try {
|
||||
InputStream inputStream = FabricLauncherBase.getClass(entrypointMetadata.getValue())
|
||||
.getResourceAsStream(
|
||||
"/assets/" + modContainer.getMetadata().getId() + "/lang/en_us.json");
|
||||
if (inputStream == null)
|
||||
return;
|
||||
Throwable var3 = null;
|
||||
try {
|
||||
JsonObject jsonObject = GSON.fromJson(
|
||||
new InputStreamReader(inputStream, StandardCharsets.UTF_8), JsonObject.class);
|
||||
for (Map.Entry<String, JsonElement> entry : jsonObject.entrySet()) {
|
||||
String string = TOKEN_PATTERN
|
||||
.matcher(JsonHelper.asString(entry.getValue(), entry.getKey()))
|
||||
.replaceAll("%$1s");
|
||||
map.put(entry.getKey(), string);
|
||||
}
|
||||
loadedFiles.getAndIncrement();
|
||||
LOGGER.info("Successfully loaded /assets/" + modContainer.getMetadata().getId()
|
||||
+ "/lang/en_us.json");
|
||||
} catch (Throwable var13) {
|
||||
var3 = var13;
|
||||
throw var13;
|
||||
} finally {
|
||||
if (var3 != null) {
|
||||
try {
|
||||
inputStream.close();
|
||||
} catch (Throwable var12) {
|
||||
var3.addSuppressed(var12);
|
||||
}
|
||||
} else {
|
||||
inputStream.close();
|
||||
}
|
||||
}
|
||||
} catch (JsonParseException | IOException var15) {
|
||||
LOGGER.error("Couldn't read strings from /assets/" + modContainer.getMetadata().getId()
|
||||
+ "/lang/en_us.json", var15);
|
||||
} catch (ClassNotFoundException ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
LOGGER.info("MC Discord Chat Bridge loaded " + loadedFiles.get() + " modded language files.");
|
||||
|
||||
return (ImmutableMap<K, V>) ImmutableMap.builder().putAll(map).build();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
package io.gitee.xujiayao147.mcDiscordChatBridge.mixins;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
import io.gitee.xujiayao147.mcDiscordChatBridge.events.PlayerAdvancementCallback;
|
||||
import net.minecraft.advancement.Advancement;
|
||||
import net.minecraft.advancement.PlayerAdvancementTracker;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
|
||||
/**
|
||||
* @author Xujiayao
|
||||
*/
|
||||
@Mixin(PlayerAdvancementTracker.class)
|
||||
public class MixinPlayerAdvancementTracker {
|
||||
|
||||
@Shadow
|
||||
private ServerPlayerEntity owner;
|
||||
|
||||
@Inject(method = "grantCriterion", at = @At("RETURN"))
|
||||
private void grantCriterion(Advancement advancement, String criterionName, CallbackInfoReturnable<Boolean> cir) {
|
||||
PlayerAdvancementCallback.EVENT.invoker().onPlayerAdvancement(owner, advancement);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
package io.gitee.xujiayao147.mcDiscordChatBridge.mixins;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
import io.gitee.xujiayao147.mcDiscordChatBridge.events.PlayerJoinCallback;
|
||||
import io.gitee.xujiayao147.mcDiscordChatBridge.events.PlayerLeaveCallback;
|
||||
import net.minecraft.network.ClientConnection;
|
||||
import net.minecraft.server.PlayerManager;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
|
||||
/**
|
||||
* @author Xujiayao
|
||||
*/
|
||||
@Mixin(PlayerManager.class)
|
||||
public class MixinPlayerManager {
|
||||
|
||||
@Inject(method = "onPlayerConnect", at = @At("RETURN"))
|
||||
private void onPlayerConnect(ClientConnection connection, ServerPlayerEntity player, CallbackInfo ci) {
|
||||
PlayerJoinCallback.EVENT.invoker().onJoin(connection, player);
|
||||
}
|
||||
|
||||
@Inject(method = "remove", at = @At("HEAD"))
|
||||
private void remove(ServerPlayerEntity player, CallbackInfo ci) {
|
||||
PlayerLeaveCallback.EVENT.invoker().onLeave(player);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
package io.gitee.xujiayao147.mcDiscordChatBridge.mixins;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
import io.gitee.xujiayao147.mcDiscordChatBridge.events.ServerChatCallback;
|
||||
import net.minecraft.network.MessageType;
|
||||
import net.minecraft.network.Packet;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.network.ServerPlayNetworkHandler;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.text.TranslatableText;
|
||||
|
||||
/**
|
||||
* @author Xujiayao
|
||||
*/
|
||||
@Mixin(ServerPlayNetworkHandler.class)
|
||||
public abstract class MixinServerPlayNetworkHandler {
|
||||
|
||||
@Final
|
||||
@Shadow
|
||||
private MinecraftServer server;
|
||||
@Shadow
|
||||
public ServerPlayerEntity player;
|
||||
@Shadow
|
||||
private int messageCooldown;
|
||||
|
||||
@Shadow
|
||||
public abstract void sendPacket(Packet<?> packet);
|
||||
|
||||
@Shadow
|
||||
public abstract void disconnect(Text reason);
|
||||
|
||||
@Shadow
|
||||
protected abstract void executeCommand(String input);
|
||||
|
||||
@Inject(at = @At(value = "INVOKE", target = "Lnet/minecraft/server/PlayerManager;broadcastChatMessage(Lnet/minecraft/text/Text;Lnet/minecraft/network/MessageType;Ljava/util/UUID;)V"), method = "method_31286", cancellable = true)
|
||||
private void onGameMessage(String string, CallbackInfo ci) {
|
||||
String message = StringUtils.normalizeSpace(string);
|
||||
Text text = new TranslatableText("chat.type.text", this.player.getDisplayName(), message);
|
||||
Optional<Text> eventResult = ServerChatCallback.EVENT.invoker().onServerChat(this.player, message, text);
|
||||
if (eventResult.isPresent()) {
|
||||
this.server.getPlayerManager().broadcastChatMessage(eventResult.get(), MessageType.CHAT,
|
||||
this.player.getUuid());
|
||||
ci.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
package io.gitee.xujiayao147.mcDiscordChatBridge.mixins;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
import io.gitee.xujiayao147.mcDiscordChatBridge.events.PlayerDeathCallback;
|
||||
import net.minecraft.entity.damage.DamageSource;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
|
||||
/**
|
||||
* @author Xujiayao
|
||||
*/
|
||||
@Mixin(ServerPlayerEntity.class)
|
||||
public class MixinServerPlayerEntity {
|
||||
|
||||
@Inject(method = "onDeath", at = @At("HEAD"))
|
||||
private void onDeath(DamageSource source, CallbackInfo ci) {
|
||||
ServerPlayerEntity serverPlayerEntity = (ServerPlayerEntity) (Object) this;
|
||||
PlayerDeathCallback.EVENT.invoker().onPlayerDeath(serverPlayerEntity, source);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
package io.gitee.xujiayao147.mcDiscordChatBridge.utils;
|
||||
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import java.util.UUID;
|
||||
|
||||
import io.gitee.xujiayao147.mcDiscordChatBridge.Main;
|
||||
import net.minecraft.server.command.CommandOutput;
|
||||
import net.minecraft.text.Text;
|
||||
|
||||
/**
|
||||
* @author Xujiayao
|
||||
*/
|
||||
public class DiscordCommandOutput implements CommandOutput {
|
||||
|
||||
StringBuilder outputString = new StringBuilder();
|
||||
Thread outputThread = null;
|
||||
long lastOutputMillis = 0;
|
||||
|
||||
@Override
|
||||
public void sendSystemMessage(Text message, UUID senderUuid) {
|
||||
String messageString = message.getString();
|
||||
Main.logger.info(messageString);
|
||||
long currentOutputMillis = System.currentTimeMillis();
|
||||
if ((outputString.length() + messageString.length()) > 2000) {
|
||||
Main.textChannel.sendMessage(outputString).queue();
|
||||
} else {
|
||||
outputString.append("> ").append(messageString).append("\n");
|
||||
}
|
||||
if ((currentOutputMillis - lastOutputMillis) > 50) {
|
||||
outputThread = new Thread(() -> new Timer().schedule(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
Main.textChannel.sendMessage(outputString).queue();
|
||||
outputString = new StringBuilder();
|
||||
}
|
||||
}, 51));
|
||||
outputThread.start();
|
||||
}
|
||||
lastOutputMillis = currentOutputMillis;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldReceiveFeedback() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldTrackOutput() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldBroadcastConsoleToOps() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
package io.gitee.xujiayao147.mcDiscordChatBridge.utils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import net.minecraft.util.Formatting;
|
||||
|
||||
/**
|
||||
* @author Xujiayao
|
||||
*/
|
||||
public class MarkdownParser {
|
||||
|
||||
public static String parseMarkdown(String message) {
|
||||
String translated = message;
|
||||
|
||||
translated = replaceWith(translated, "(?<!\\\\)\\*\\*", Formatting.BOLD.toString(),
|
||||
Formatting.RESET.toString());
|
||||
translated = replaceWith(translated, "(?<!\\\\)\\*", Formatting.ITALIC.toString(), Formatting.RESET.toString());
|
||||
translated = replaceWith(translated, "(?<!\\\\)__", Formatting.UNDERLINE.toString(),
|
||||
Formatting.RESET.toString());
|
||||
translated = replaceWith(translated, "(?<!\\\\)_", Formatting.ITALIC.toString(), Formatting.RESET.toString());
|
||||
translated = replaceWith(translated, "(?<!\\\\)~~", Formatting.STRIKETHROUGH.toString(),
|
||||
Formatting.RESET.toString());
|
||||
|
||||
translated = translated.replaceAll("\\*", "*").replaceAll("\\_", "_").replaceAll("\\~", "~");
|
||||
translated = translated.replaceAll(Formatting.ITALIC.toString() + "(ツ)" + Formatting.RESET.toString(), "_(ツ)_");
|
||||
return translated;
|
||||
}
|
||||
|
||||
private static String replaceWith(String message, String quot, String pre, String suf) {
|
||||
String part = message;
|
||||
for (String str : getMatches(message, quot + "(.+?)" + quot)) {
|
||||
part = part.replaceFirst(quot + Pattern.quote(str) + quot, pre + str + suf);
|
||||
}
|
||||
return part;
|
||||
}
|
||||
|
||||
public static List<String> getMatches(String string, String regex) {
|
||||
Pattern pattern = Pattern.compile(regex);
|
||||
Matcher matcher = pattern.matcher(string);
|
||||
List<String> matches = new ArrayList<>();
|
||||
while (matcher.find()) {
|
||||
matches.add(matcher.group(1));
|
||||
}
|
||||
return matches;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
package io.gitee.xujiayao147.mcDiscordChatBridge.utils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import io.gitee.xujiayao147.mcDiscordChatBridge.Main;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import net.minecraft.util.Formatting;
|
||||
import net.minecraft.util.Pair;
|
||||
|
||||
/**
|
||||
* @author Xujiayao
|
||||
*/
|
||||
public class Utils {
|
||||
|
||||
public static Pair<String, String> convertMentionsFromNames(String message) {
|
||||
|
||||
if (!message.contains("@"))
|
||||
return new Pair<>(message, message);
|
||||
|
||||
List<String> messageList = Arrays.asList(message.split("@[\\S]+"));
|
||||
if (messageList.size() == 0) {
|
||||
messageList = new ArrayList<>();
|
||||
messageList.add("");
|
||||
}
|
||||
|
||||
StringBuilder discordString = new StringBuilder(), mcString = new StringBuilder();
|
||||
Pattern pattern = Pattern.compile("@[\\S]+");
|
||||
Matcher matcher = pattern.matcher(message);
|
||||
|
||||
int x = 0;
|
||||
while (matcher.find()) {
|
||||
Member member = null;
|
||||
for (Member m : Main.textChannel.getMembers()) {
|
||||
String name = matcher.group().substring(1);
|
||||
if (m.getUser().getName().toLowerCase().equals(name.toLowerCase())
|
||||
|| (m.getNickname() != null && m.getNickname().toLowerCase().equals(name.toLowerCase()))) {
|
||||
member = m;
|
||||
}
|
||||
}
|
||||
if (member == null) {
|
||||
discordString.append(messageList.get(x)).append(matcher.group());
|
||||
mcString.append(messageList.get(x)).append(matcher.group());
|
||||
} else {
|
||||
discordString.append(messageList.get(x)).append(member.getAsMention());
|
||||
mcString.append(messageList.get(x)).append(Formatting.YELLOW.toString()).append("@")
|
||||
.append(member.getEffectiveName()).append(Formatting.WHITE.toString());
|
||||
}
|
||||
x++;
|
||||
}
|
||||
if (x < messageList.size()) {
|
||||
discordString.append(messageList.get(x));
|
||||
mcString.append(messageList.get(x));
|
||||
}
|
||||
return new Pair<>(discordString.toString(), mcString.toString());
|
||||
}
|
||||
}
|
||||
|
|
@ -4,7 +4,7 @@
|
|||
"version": "${version}",
|
||||
|
||||
"name": "MC Discord Chat Bridge",
|
||||
"description": "服务器跨服聊天工具 By Xujiayao",
|
||||
"description": "A Discord <-> Minecraft chat bridge.",
|
||||
"authors": [
|
||||
"Xujiayao"
|
||||
],
|
||||
|
|
@ -17,22 +17,18 @@
|
|||
"license": "MIT",
|
||||
"icon": "assets/mc-discord-chat-bridge/icon.jpg",
|
||||
|
||||
"environment": "*",
|
||||
"environment": "server",
|
||||
"entrypoints": {
|
||||
"main": [
|
||||
"server": [
|
||||
"io.gitee.xujiayao147.mcDiscordChatBridge.Main"
|
||||
]
|
||||
},
|
||||
"mixins": [
|
||||
"mc-discord-chat-bridge.mixins.json"
|
||||
],
|
||||
|
||||
"depends": {
|
||||
"fabricloader": ">=0.7.4",
|
||||
"fabric": "*",
|
||||
"fabricloader": ">=0.8.7",
|
||||
"fabric": "*",
|
||||
"minecraft": "1.16.x"
|
||||
},
|
||||
"suggests": {
|
||||
"another-mod": "*"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,15 @@
|
|||
{
|
||||
"required": true,
|
||||
"package": "io.gitee.xujiayao147.mcDiscordChatBridge.minecraft.mixin",
|
||||
"package": "io.gitee.xujiayao147.mcDiscordChatBridge.mixins",
|
||||
"compatibilityLevel": "JAVA_8",
|
||||
"mixins": [
|
||||
"StartMixin",
|
||||
"GetMessage"
|
||||
"MixinLanguage",
|
||||
"MixinPlayerAdvancementTracker",
|
||||
"MixinPlayerManager",
|
||||
"MixinServerPlayerEntity",
|
||||
"MixinServerPlayNetworkHandler"
|
||||
],
|
||||
"injectors": {
|
||||
"defaultRequire": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue