Skip to content

Commit cf97f62

Browse files
committed
1.0.0
0 parents  commit cf97f62

21 files changed

+842
-0
lines changed

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
run
2+
.idea
3+
build
4+
.gradle

LICENSE.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Copyright (c) 2025
2+
All rights reserved.

build.gradle

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
plugins {
2+
id 'fabric-loom' version '1.10.1'
3+
id 'maven-publish'
4+
}
5+
6+
version = project.mod_version
7+
group = project.maven_group
8+
9+
base {
10+
archivesName = project.archives_base_name
11+
}
12+
13+
loom {
14+
splitEnvironmentSourceSets()
15+
16+
mods {
17+
"qqbot" {
18+
sourceSet sourceSets.main
19+
sourceSet sourceSets.client
20+
}
21+
}
22+
}
23+
24+
25+
repositories {
26+
// Add repositories to retrieve artifacts from in here.
27+
// You should only use this when depending on other mods because
28+
// Loom adds the essential maven repositories to download Minecraft and libraries from automatically.
29+
// See https://docs.gradle.org/current/userguide/declaring_repositories.html
30+
// for more information about repositories.
31+
}
32+
33+
dependencies {
34+
// To change the versions see the gradle.properties file
35+
minecraft "com.mojang:minecraft:${project.minecraft_version}"
36+
mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2"
37+
modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}"
38+
//mappings loom.officialMojangMappings()
39+
modImplementation "net.fabricmc:fabric-loader:${project.loader_version}"
40+
implementation include('org.java-websocket:Java-WebSocket:1.6.0')
41+
}
42+
43+
processResources {
44+
inputs.property "version", project.version
45+
inputs.property "minecraft_version", project.minecraft_version
46+
inputs.property "loader_version", project.loader_version
47+
filteringCharset "UTF-8"
48+
49+
filesMatching("fabric.mod.json") {
50+
expand "version": project.version,
51+
"minecraft_version": project.minecraft_version,
52+
"loader_version": project.loader_version
53+
}
54+
}
55+
56+
def targetJavaVersion = 21
57+
tasks.withType(JavaCompile).configureEach {
58+
// ensure that the encoding is set to UTF-8, no matter what the system default is
59+
// this fixes some edge cases with special characters not displaying correctly
60+
// see http://yodaconditions.net/blog/fix-for-java-file-encoding-problems-with-gradle.html
61+
// If Javadoc is generated, this must be specified in that task too.
62+
it.options.encoding = "UTF-8"
63+
if (targetJavaVersion >= 10 || JavaVersion.current().isJava10Compatible()) {
64+
it.options.release.set(targetJavaVersion)
65+
}
66+
}
67+
68+
java {
69+
def javaVersion = JavaVersion.toVersion(targetJavaVersion)
70+
if (JavaVersion.current() < javaVersion) {
71+
toolchain.languageVersion = JavaLanguageVersion.of(targetJavaVersion)
72+
}
73+
// Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task
74+
// if it is present.
75+
// If you remove this line, sources will not be generated.
76+
withSourcesJar()
77+
}
78+
79+
jar {
80+
from("LICENSE") {
81+
rename { "${it}_${project.archivesBaseName}" }
82+
}
83+
}
84+
85+
// configure the maven publication
86+
publishing {
87+
publications {
88+
create("mavenJava", MavenPublication) {
89+
artifactId = project.archives_base_name
90+
from components.java
91+
}
92+
}
93+
94+
// See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing.
95+
repositories {
96+
// Add repositories to publish to here.
97+
// Notice: This block does NOT have the same function as the block in the top level.
98+
// The repositories here will be used for publishing your artifact, not for
99+
// retrieving dependencies.
100+
}
101+
}

gradle.properties

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Done to increase the memory available to gradle.
2+
org.gradle.jvmargs=-Xmx1G
3+
# Fabric Properties
4+
# check these on https://modmuss50.me/fabric.html
5+
minecraft_version=1.21
6+
loader_version=0.16.10
7+
# Mod Properties
8+
mod_version=1.0-SNAPSHOT
9+
maven_group=org.minecralogy
10+
archives_base_name=QQBot
11+
yarn_mappings=1.21+build.4
12+
# Dependencies
13+
# check this on https://modmuss50.me/fabric.html
14+
fabric_version=0.102.0+1.21
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip

settings.gradle

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
pluginManagement {
2+
repositories {
3+
maven {
4+
name = 'Fabric'
5+
url = 'https://maven.fabricmc.net/'
6+
}
7+
gradlePluginPortal()
8+
}
9+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package org.minecralogy.qqbot.client;
2+
3+
import net.fabricmc.api.ClientModInitializer;
4+
5+
public class BotClient implements ClientModInitializer {
6+
7+
@Override
8+
public void onInitializeClient() {
9+
}
10+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"required": true,
3+
"minVersion": "0.8",
4+
"package": "org.minecralogy.qqbot.mixin.client",
5+
"compatibilityLevel": "JAVA_21",
6+
"client": [
7+
],
8+
"injectors": {
9+
"defaultRequire": 1
10+
}
11+
}
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
package org.minecralogy.qqbot;
2+
3+
import com.google.gson.Gson;
4+
import com.google.gson.JsonSyntaxException;
5+
import com.google.gson.TypeAdapter;
6+
import com.mojang.logging.LogUtils;
7+
import net.fabricmc.api.ModInitializer;
8+
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
9+
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
10+
import net.fabricmc.loader.api.FabricLoader;
11+
import net.minecraft.server.MinecraftServer;
12+
import org.minecralogy.qqbot.command.QQCommand;
13+
import org.minecralogy.qqbot.websocket.Listener;
14+
import org.minecralogy.qqbot.websocket.Sender;
15+
import org.slf4j.Logger;
16+
import java.io.*;
17+
import java.net.URISyntaxException;
18+
19+
public class Bot implements ModInitializer {
20+
public static Config config;
21+
public static MinecraftServer server = null;
22+
public static Listener listener;
23+
public static Sender sender;
24+
static final Logger LOGGER = LogUtils.getLogger();
25+
public static <T> boolean isValidStrictly(String json, Class<T> type) {
26+
TypeAdapter<T> strictAdapter = new Gson().getAdapter(type);
27+
try {
28+
strictAdapter.fromJson(json);
29+
} catch (JsonSyntaxException | IOException e) {
30+
return false;
31+
}
32+
return true;
33+
}
34+
@Override
35+
public void onInitialize() {
36+
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
37+
QQCommand.register(dispatcher);
38+
});
39+
ServerLifecycleEvents.SERVER_STARTED.register((minecraftServer) -> {
40+
server = minecraftServer;
41+
});
42+
String path = FabricLoader.getInstance().getConfigDir().toAbsolutePath().toString();
43+
path = path + "\\qq_bot.json";
44+
LOGGER.info("The bot config:" + path);
45+
File file = new File(path);
46+
if(!file.canRead() || file.isDirectory()) {
47+
LOGGER.error("The configuration file does not exist");
48+
try {
49+
file.createNewFile();
50+
} catch (IOException e) {
51+
LOGGER.error("Can't create configuration file");
52+
throw new RuntimeException(e);
53+
}
54+
System.exit(0);
55+
}
56+
Gson g = new Gson();
57+
InputStream inputStream;
58+
String conf;
59+
try {
60+
inputStream = new FileInputStream(file);
61+
conf = new String(inputStream.readAllBytes());
62+
} catch (IOException e) {
63+
LOGGER.error("Can't read configuration file");
64+
System.exit(0);
65+
throw new RuntimeException(e);
66+
}
67+
if(!isValidStrictly(conf, Config.class)) {
68+
LOGGER.error("Configuration file is not a json file");
69+
System.exit(0);
70+
}
71+
Gson gson = new Gson();
72+
config = gson.fromJson(conf, Config.class);
73+
if(config.uri.endsWith("/")) config.uri = config.uri.substring(0, config.uri.length() -1 );
74+
try {
75+
listener = new Listener(config.uri + "/websocket/minecraft");
76+
sender = new Sender(config.uri + "/websocket/bot");
77+
} catch (URISyntaxException e) {
78+
LOGGER.error("Wrong uri");
79+
System.exit(0);
80+
throw new RuntimeException(e);
81+
}
82+
}
83+
}
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
package org.minecralogy.qqbot;
2+
3+
import net.minecraft.command.ReturnValueConsumer;
4+
import net.minecraft.command.argument.EntityAnchorArgumentType;
5+
import net.minecraft.entity.Entity;
6+
import net.minecraft.network.message.MessageType;
7+
import net.minecraft.network.message.SentMessage;
8+
import net.minecraft.network.message.SignedCommandArguments;
9+
import net.minecraft.server.MinecraftServer;
10+
import net.minecraft.server.command.CommandOutput;
11+
import net.minecraft.server.command.ServerCommandSource;
12+
import net.minecraft.server.network.ServerPlayerEntity;
13+
import net.minecraft.server.world.ServerWorld;
14+
import net.minecraft.text.Text;
15+
import net.minecraft.util.Formatting;
16+
import net.minecraft.util.math.Vec2f;
17+
import net.minecraft.util.math.Vec3d;
18+
import net.minecraft.util.thread.FutureQueue;
19+
import net.minecraft.world.GameRules;
20+
import org.jetbrains.annotations.Nullable;
21+
import java.util.function.Supplier;
22+
23+
public class BotCommandSource extends ServerCommandSource {
24+
String result = "";
25+
26+
public String getResult() {
27+
return result.substring(0, result.length()-1);
28+
}
29+
boolean success = true;
30+
31+
public boolean isSuccess() {
32+
return success;
33+
}
34+
35+
CommandOutput commandOutput;
36+
public BotCommandSource(CommandOutput output, Vec3d pos, Vec2f rot, ServerWorld world, int level, String name, Text displayName, MinecraftServer server, @Nullable Entity entity) {
37+
super(output, pos, rot, world, level, name, displayName, server, entity);
38+
commandOutput = output;
39+
}
40+
41+
protected BotCommandSource(CommandOutput output, Vec3d pos, Vec2f rot, ServerWorld world, int level, String name, Text displayName, MinecraftServer server, @Nullable Entity entity, boolean silent, ReturnValueConsumer resultStorer, EntityAnchorArgumentType.EntityAnchor entityAnchor, SignedCommandArguments signedArguments, FutureQueue messageChainTaskQueue) {
42+
super(output, pos, rot, world, level, name, displayName, server, entity, silent, resultStorer, entityAnchor, signedArguments, messageChainTaskQueue);
43+
commandOutput = output;
44+
}
45+
46+
@Override
47+
public void sendChatMessage(SentMessage message, boolean filterMaskEnabled, MessageType.Parameters params) {
48+
if (!this.isSilent()) {
49+
ServerPlayerEntity serverPlayerEntity = this.getPlayer();
50+
if (serverPlayerEntity != null) {
51+
serverPlayerEntity.sendChatMessage(message, filterMaskEnabled, params);
52+
} else {
53+
this.getOutput().sendMessage(params.applyChatDecoration(message.content()));
54+
}
55+
}
56+
}
57+
58+
@Override
59+
public void sendMessage(Text message) {
60+
result += message.getString() + "\n";
61+
if (!this.isSilent()) {
62+
ServerPlayerEntity serverPlayerEntity = this.getPlayer();
63+
if (serverPlayerEntity != null) {
64+
serverPlayerEntity.sendMessage(message);
65+
} else {
66+
this.getOutput().sendMessage(message);
67+
}
68+
}
69+
}
70+
71+
@Override
72+
public void sendFeedback(Supplier<Text> feedbackSupplier, boolean broadcastToOps) {
73+
boolean bl = this.getOutput().shouldReceiveFeedback() && !this.isSilent();
74+
boolean bl2 = broadcastToOps && this.getOutput().shouldBroadcastConsoleToOps() && !this.isSilent();
75+
Text text = (Text)feedbackSupplier.get();
76+
result += text.getString() + "\n";
77+
if (bl || bl2) {
78+
if (bl) {
79+
this.getOutput().sendMessage(text);
80+
}
81+
82+
if (bl2) {
83+
this.sendToOp(text);
84+
}
85+
}
86+
}
87+
88+
@Override
89+
public void sendError(Text message) {
90+
success = false;
91+
result += message.getString() + "\n";
92+
if (this.getOutput().shouldTrackOutput() && !this.isSilent()) {
93+
this.getOutput().sendMessage(Text.empty().append(message).formatted(Formatting.RED));
94+
}
95+
}
96+
private void sendToOp(Text message) {
97+
Text text = Text.translatable("chat.type.admin", this.getDisplayName(), message).formatted(Formatting.GRAY, Formatting.ITALIC);
98+
if (this.getServer().getGameRules().getBoolean(GameRules.SEND_COMMAND_FEEDBACK)) {
99+
for (ServerPlayerEntity serverPlayerEntity : this.getServer().getPlayerManager().getPlayerList()) {
100+
if (serverPlayerEntity != this.getOutput() && this.getServer().getPlayerManager().isOperator(serverPlayerEntity.getGameProfile())) {
101+
serverPlayerEntity.sendMessage(text);
102+
}
103+
}
104+
}
105+
106+
if (this.getOutput() != this.getServer() && this.getServer().getGameRules().getBoolean(GameRules.LOG_ADMIN_COMMANDS)) {
107+
this.getServer().sendMessage(text);
108+
}
109+
}
110+
public CommandOutput getOutput() {
111+
return commandOutput;
112+
}
113+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package org.minecralogy.qqbot;
2+
3+
public class Config {
4+
String uri;
5+
String name;
6+
String token;
7+
int reconnect_interval;
8+
Config(String uri, String name, String token, int reconnect_interval) {
9+
this.uri = uri;
10+
this.name = name;
11+
this.token = token;
12+
this.reconnect_interval = reconnect_interval;
13+
}
14+
15+
public int getReconnect_interval() {
16+
return reconnect_interval;
17+
}
18+
19+
public String getName() {
20+
return name;
21+
}
22+
23+
public String getToken() {
24+
return token;
25+
}
26+
27+
public String getUri() {
28+
return uri;
29+
}
30+
}

0 commit comments

Comments
 (0)