Skip to content

Commit ad2e4d0

Browse files
committed
Add command /authproxy ping
1 parent 26fec36 commit ad2e4d0

20 files changed

Lines changed: 543 additions & 15 deletions

.idea/misc.xml

Lines changed: 3 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

changelog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
### General
22

3+
- ***Added*** command `/authproxy ping`
34
- Support for Minecraft 1.21.7

common.gradle

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,6 @@ repositories {
5151
// https://github.com/FabricMC/fabric-loader/issues/783
5252
configurations {
5353
modRuntimeOnly.exclude(group: "net.fabricmc", module: "fabric-loader")
54-
modCompileOnly.exclude(group: "com.github.2No2Name", module: "McTester")
55-
modImplementation.exclude(group: "com.github.2No2Name", module: "McTester")
5654
}
5755

5856
dependencies {
@@ -63,6 +61,9 @@ dependencies {
6361
// fabric
6462
modImplementation("net.fabricmc:fabric-loader:${project.loader_version}")
6563

64+
//libs
65+
include(modImplementation("me.fallenbreath:conditional-mixin-fabric:${project.conditionalmixin_version}"))
66+
6667
if (!releasing) {
6768
if (mcVersion >= 11600) {
6869
if (mcVersion < 11900) {
@@ -114,7 +115,7 @@ loom {
114115
}
115116

116117
preprocess {
117-
patternAnnotation.set("com.ayakacraft.authlibproxyforserver.utils.PreprocessPattern")
118+
patternAnnotation.set("com.ayakacraft.authlibproxyforserver.utils.preprocess.PreprocessPattern")
118119
}
119120

120121
shadowJar {

gradle.properties

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,14 @@ loader_version=0.16.14
66
# Mod Properties
77
mod_id=authlib-proxy-for-server
88
mod_name=AuthlibProxyForServer
9-
mod_version=0.1.1
9+
mod_version=0.2.0
1010
mod_version_type=release
1111
group=com.ayakacraft
1212
archives_base_name=authlib-proxy-for-server
1313
modrinth_id=L7XPJc1F
1414
curseforge_id=1282523
1515
loader_dependency=>=0.16.0
16+
# Libs
17+
conditionalmixin_version=0.6.4
1618
# Test
1719
junit_version=4.13.2

src/main/java/com/ayakacraft/authlibproxyforserver/ProxyConfig.java

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,6 @@
2020

2121
package com.ayakacraft.authlibproxyforserver;
2222

23-
import com.google.gson.annotations.SerializedName;
24-
2523
import java.net.InetAddress;
2624
import java.net.InetSocketAddress;
2725
import java.net.Proxy;
@@ -126,10 +124,8 @@ public enum InvalidReason {
126124

127125
public enum ProxyType {
128126

129-
@SerializedName("HTTP")
130127
HTTP(Proxy.Type.HTTP),
131128

132-
@SerializedName("SOCKS")
133129
SOCKS(Proxy.Type.SOCKS);
134130

135131
public final Proxy.Type real;

src/main/java/com/ayakacraft/authlibproxyforserver/commands/AuthProxyCommand.java

Lines changed: 100 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,22 @@
2222

2323
import com.ayakacraft.authlibproxyforserver.AuthlibProxyForServer;
2424
import com.ayakacraft.authlibproxyforserver.ProxyConfig;
25-
import com.ayakacraft.authlibproxyforserver.utils.PreprocessPattern;
25+
import com.ayakacraft.authlibproxyforserver.mixin.YggdrasilAuthenticationServiceAccessor;
26+
import com.ayakacraft.authlibproxyforserver.utils.NetworkUtils;
27+
import com.ayakacraft.authlibproxyforserver.utils.preprocess.PreprocessPattern;
2628
import com.mojang.brigadier.CommandDispatcher;
2729
import com.mojang.brigadier.arguments.IntegerArgumentType;
2830
import com.mojang.brigadier.arguments.StringArgumentType;
2931
import com.mojang.brigadier.context.CommandContext;
3032
import net.minecraft.server.command.ServerCommandSource;
3133
import net.minecraft.text.Text;
34+
import net.minecraft.util.Formatting;
35+
import net.minecraft.util.Pair;
3236

3337
import java.io.IOException;
38+
import java.net.URI;
39+
import java.util.LinkedList;
40+
import java.util.List;
3441

3542
import static com.ayakacraft.authlibproxyforserver.AuthlibProxyForServer.LOGGER;
3643
import static com.ayakacraft.authlibproxyforserver.AuthlibProxyForServer.config;
@@ -40,6 +47,8 @@
4047

4148
public final class AuthProxyCommand {
4249

50+
private static final int TCPING_TIMES = 5;
51+
4352
private static int display(CommandContext<ServerCommandSource> context) {
4453
sendFeedback(
4554
context.getSource(),
@@ -153,6 +162,27 @@ private static int type(CommandContext<ServerCommandSource> context, String type
153162
return 1;
154163
}
155164

165+
private static int ping(CommandContext<ServerCommandSource> context) {
166+
List<String> hosts = new LinkedList<>();
167+
//#if MC>=12006
168+
com.mojang.authlib.Environment env = YggdrasilAuthenticationServiceAccessor.determineEnvironment();
169+
hosts.add(env.sessionHost());
170+
hosts.add(env.servicesHost());
171+
//#elseif MC>=11600
172+
//$$ com.mojang.authlib.Environment env = YggdrasilAuthenticationServiceAccessor.determineEnvironment();
173+
//$$ hosts.add(env.getAuthHost());
174+
//$$ hosts.add(env.getAccountsHost());
175+
//$$ hosts.add(env.getSessionHost());
176+
//$$ hosts.add(env.getServicesHost());
177+
//#else
178+
//$$ hosts.add(com.ayakacraft.authlibproxyforserver.mixin.YggdrasilGameProfileRepositoryAccessor.getBaseUrl());
179+
//$$ hosts.add(com.ayakacraft.authlibproxyforserver.mixin.YggdrasilMinecraftSessionServiceAccessor.getBaseUrl());
180+
//$$ hosts.add(com.ayakacraft.authlibproxyforserver.mixin.YggdrasilUserAuthenticationAccessor.getBaseUrl());
181+
//#endif
182+
new TcpingThread(hosts, context.getSource()).start();
183+
return 1;
184+
}
185+
156186
/**
157187
* @return true if failed
158188
*/
@@ -211,7 +241,76 @@ public static void register(CommandDispatcher<ServerCommandSource> dispatcher) {
211241
.then(literal("http").executes(it -> AuthProxyCommand.type(it, "HTTP")))
212242
.then(literal("socks").executes(it -> AuthProxyCommand.type(it, "SOCKS")))
213243
)
244+
.then(literal("ping").executes(AuthProxyCommand::ping))
214245
);
215246
}
216247

248+
private static class TcpingThread extends Thread {
249+
250+
private static Text packetLossStatusText(int packetsReceived) {
251+
double packetLoss = 1d - (double) packetsReceived / AuthProxyCommand.TCPING_TIMES;
252+
Formatting colour;
253+
if (packetLoss >= 0.8d) {
254+
colour = Formatting.RED;
255+
} else if (packetLoss >= 0.3d) {
256+
colour = Formatting.YELLOW;
257+
} else {
258+
colour = Formatting.GREEN;
259+
}
260+
return Text.literal(String.format("%d packets transmitted, %d packets received, ", TCPING_TIMES, packetsReceived))
261+
.append(Text.literal(String.format("%.1f%%", packetLoss * 100)).formatted(colour))
262+
.append(Text.literal(" packet loss"));
263+
}
264+
265+
private static Text averagePingText(long ping) {
266+
Formatting colour;
267+
if (ping >= 800) {
268+
colour = Formatting.RED;
269+
} else if (ping >= 400) {
270+
colour = Formatting.YELLOW;
271+
} else {
272+
colour = Formatting.GREEN;
273+
}
274+
return Text.literal("Average ping: ")
275+
.append(Text.literal(ping + "ms").formatted(colour));
276+
}
277+
278+
private final List<String> hosts;
279+
280+
private final ServerCommandSource source;
281+
282+
public TcpingThread(List<String> hosts, ServerCommandSource source) {
283+
this.hosts = hosts;
284+
this.source = source;
285+
}
286+
287+
private void tcping(String host) {
288+
Pair<Long, Integer> res = NetworkUtils.tcpingMultiple(URI.create(host), proxy, TCPING_TIMES);
289+
sendFeedback(
290+
source,
291+
Text.literal(String.format("Ping for '%s':", host)),
292+
false
293+
);
294+
sendFeedback(
295+
source,
296+
packetLossStatusText(res.getRight()),
297+
false
298+
);
299+
if (res.getRight() > 0) {
300+
sendFeedback(
301+
source,
302+
averagePingText(res.getLeft() / TCPING_TIMES),
303+
false
304+
);
305+
}
306+
}
307+
308+
public void run() {
309+
sendFeedback(source, Text.literal("Ping started"), false);
310+
hosts.forEach(this::tcping);
311+
sendFeedback(source, Text.literal("Ping finished"), false);
312+
}
313+
314+
}
315+
217316
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* This file is part of the AuthlibProxyForServer project, licensed under the
3+
* GNU General Public License v3.0
4+
*
5+
* Copyright (C) 2025 Calboot and contributors
6+
*
7+
* This program is free software: you can redistribute it and/or modify
8+
* it under the terms of the GNU General Public License as published by
9+
* the Free Software Foundation, either version 3 of the License, or
10+
* (at your option) any later version.
11+
*
12+
* This program is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
* GNU General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU General Public License
18+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
19+
*/
20+
21+
package com.ayakacraft.authlibproxyforserver.mixin;
22+
23+
import com.mojang.authlib.Environment;
24+
import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService;
25+
import me.fallenbreath.conditionalmixin.api.annotation.Condition;
26+
import me.fallenbreath.conditionalmixin.api.annotation.Restriction;
27+
import org.spongepowered.asm.mixin.Mixin;
28+
import org.spongepowered.asm.mixin.gen.Invoker;
29+
30+
@Restriction(require = @Condition(value = "minecraft", versionPredicates = ">=1.16"))
31+
@Mixin(value = YggdrasilAuthenticationService.class, remap = false)
32+
public interface YggdrasilAuthenticationServiceAccessor {
33+
34+
@Invoker("determineEnvironment")
35+
static Environment determineEnvironment() {
36+
throw new AssertionError();
37+
}
38+
39+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
* This file is part of the AuthlibProxyForServer project, licensed under the
3+
* GNU General Public License v3.0
4+
*
5+
* Copyright (C) 2025 Calboot and contributors
6+
*
7+
* This program is free software: you can redistribute it and/or modify
8+
* it under the terms of the GNU General Public License as published by
9+
* the Free Software Foundation, either version 3 of the License, or
10+
* (at your option) any later version.
11+
*
12+
* This program is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
* GNU General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU General Public License
18+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
19+
*/
20+
21+
package com.ayakacraft.authlibproxyforserver.mixin;
22+
23+
import com.ayakacraft.authlibproxyforserver.utils.mixin.DummyClass;
24+
import me.fallenbreath.conditionalmixin.api.annotation.Condition;
25+
import me.fallenbreath.conditionalmixin.api.annotation.Restriction;
26+
import org.spongepowered.asm.mixin.Mixin;
27+
28+
@Restriction(require = @Condition(value = "minecraft", versionPredicates = "<1.16"))
29+
@Mixin(DummyClass.class)
30+
public interface YggdrasilGameProfileRepositoryAccessor {
31+
32+
// Implementation in 1.15.2
33+
34+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
* This file is part of the AuthlibProxyForServer project, licensed under the
3+
* GNU General Public License v3.0
4+
*
5+
* Copyright (C) 2025 Calboot and contributors
6+
*
7+
* This program is free software: you can redistribute it and/or modify
8+
* it under the terms of the GNU General Public License as published by
9+
* the Free Software Foundation, either version 3 of the License, or
10+
* (at your option) any later version.
11+
*
12+
* This program is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
* GNU General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU General Public License
18+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
19+
*/
20+
21+
package com.ayakacraft.authlibproxyforserver.mixin;
22+
23+
import com.ayakacraft.authlibproxyforserver.utils.mixin.DummyClass;
24+
import me.fallenbreath.conditionalmixin.api.annotation.Condition;
25+
import me.fallenbreath.conditionalmixin.api.annotation.Restriction;
26+
import org.spongepowered.asm.mixin.Mixin;
27+
28+
@Restriction(require = @Condition(value = "minecraft", versionPredicates = "<1.16"))
29+
@Mixin(DummyClass.class)
30+
public interface YggdrasilMinecraftSessionServiceAccessor {
31+
32+
// Implementation in 1.15.2
33+
34+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
* This file is part of the AuthlibProxyForServer project, licensed under the
3+
* GNU General Public License v3.0
4+
*
5+
* Copyright (C) 2025 Calboot and contributors
6+
*
7+
* This program is free software: you can redistribute it and/or modify
8+
* it under the terms of the GNU General Public License as published by
9+
* the Free Software Foundation, either version 3 of the License, or
10+
* (at your option) any later version.
11+
*
12+
* This program is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
* GNU General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU General Public License
18+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
19+
*/
20+
21+
package com.ayakacraft.authlibproxyforserver.mixin;
22+
23+
import com.ayakacraft.authlibproxyforserver.utils.mixin.DummyClass;
24+
import me.fallenbreath.conditionalmixin.api.annotation.Condition;
25+
import me.fallenbreath.conditionalmixin.api.annotation.Restriction;
26+
import org.spongepowered.asm.mixin.Mixin;
27+
28+
@Restriction(require = @Condition(value = "minecraft", versionPredicates = "<1.16"))
29+
@Mixin(DummyClass.class)
30+
public interface YggdrasilUserAuthenticationAccessor {
31+
32+
// Implementation in 1.15.2
33+
34+
}

0 commit comments

Comments
 (0)