Skip to content

Commit 673b98c

Browse files
committed
feat: Initial Implementation
1 parent d03d0ad commit 673b98c

File tree

18 files changed

+496
-40
lines changed

18 files changed

+496
-40
lines changed

README.md

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
1-
# Example-Expansion
2-
Example Expansion for MiniPlaceholders
1+
# ProxyConnection Expansion
32

4-
This example contains everything you need to create a functional MiniPlaceholders v3 expansion.
3+
This expansion allows you to obtain information from your proxy, whether it be Velocity(recommended) or bungeecord.
54

6-
Don't forget to modify the “expansion-provider.properties” file with the class that provides the expansion.
5+
Supports Fabric, Sponge, and Paper.
76

7+
However, in Fabric, it must be installed together with the https://modrinth.com/mod/fabric-plugin-messaging mod.
8+
This is done to ensure a standard usage of the Bungee plugin message channel.
89

9-
To create extensions for older versions of MiniPlaceholders, review the commit history, although it is always recommended to use the latest version
10+
## Placeholders
11+
12+
`<proxyconnection_player_count>`
13+
14+
15+
`<proxyconnection_player_count:(server)>`

build.gradle.kts

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,17 @@ plugins {
22
java
33
alias(libs.plugins.idea.ext)
44
alias(libs.plugins.blossom)
5+
alias(libs.plugins.shadow)
56
}
67

78
dependencies {
89
compileOnly(libs.miniplaceholders)
9-
//compileOnly(libs.spark) Some library
1010
compileOnly(libs.adventure.api)
1111
compileOnly(libs.adventure.minimessage)
12+
implementation(projects.proxyconnectionExpansionPaper)
13+
implementation(projects.proxyconnectionExpansionFabric)
14+
implementation(projects.proxyconnectionExpansionSponge)
15+
implementation(projects.proxyconnectionExpansionCommon)
1216
}
1317

1418
java.toolchain.languageVersion.set(JavaLanguageVersion.of(21))
@@ -19,6 +23,27 @@ tasks {
1923
}
2024
}
2125

26+
subprojects {
27+
apply<JavaPlugin>()
28+
java.toolchain.languageVersion.set(JavaLanguageVersion.of(21))
29+
tasks {
30+
compileJava {
31+
options.encoding = Charsets.UTF_8.name()
32+
options.release.set(21)
33+
}
34+
}
35+
}
36+
37+
tasks {
38+
shadowJar {
39+
archiveFileName.set("ProxyConnection-Expansion-${project.version}.jar")
40+
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
41+
}
42+
build {
43+
dependsOn(shadowJar)
44+
}
45+
}
46+
2247
sourceSets {
2348
main {
2449
blossom {
@@ -27,4 +52,4 @@ sourceSets {
2752
}
2853
}
2954
}
30-
}
55+
}

common/build.gradle.kts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
dependencies {
2+
compileOnly(libs.miniplaceholders)
3+
compileOnly(libs.adventure.api)
4+
compileOnly(libs.adventure.minimessage)
5+
// implementation(libs.caffeine)
6+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package io.github.miniplaceholders.expansion.proxyconnection.common;
2+
3+
import java.util.Objects;
4+
5+
/**
6+
* GET Bungee Message Types
7+
*
8+
* @implNote Unused types have been added for possible future expansion of the project.
9+
*/
10+
public enum BungeeMessageTypes {
11+
PLAYER_COUNT("PlayerCount"),
12+
PLAYER_LIST("PlayerList"),
13+
GET_SERVERS("GetServers"),
14+
SERVER_IP("ServerIp");
15+
16+
private final String rawType;
17+
BungeeMessageTypes(String rawType) {
18+
this.rawType = rawType;
19+
}
20+
21+
public boolean compareProvided(final String o) {
22+
return Objects.equals(this.rawType, o);
23+
}
24+
25+
public String rawType() {
26+
return this.rawType;
27+
}
28+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package io.github.miniplaceholders.expansion.proxyconnection.common;
2+
3+
import org.jetbrains.annotations.NotNull;
4+
5+
import java.util.List;
6+
import java.util.concurrent.ConcurrentHashMap;
7+
import java.util.concurrent.CopyOnWriteArrayList;
8+
9+
public final class DataCache {
10+
private final ConcurrentHashMap<@NotNull String, Integer> playerCountByServer = new ConcurrentHashMap<>();
11+
private final CopyOnWriteArrayList<String> serverList = new CopyOnWriteArrayList<>();
12+
13+
public void setPlayerCount(String server, int playerCount) {
14+
this.playerCountByServer.put(server, playerCount);
15+
}
16+
17+
public int getPlayerCount(String server) {
18+
return this.playerCountByServer.getOrDefault(server, 0);
19+
}
20+
21+
public int getProxyPlayerCount() {
22+
return this.playerCountByServer.reduceValuesToInt(100, i -> i, 0, Integer::sum);
23+
}
24+
25+
public List<String> getServers() {
26+
return this.serverList;
27+
}
28+
29+
public void updateServers(List<String> newServers) {
30+
serverList.clear();
31+
serverList.addAll(newServers);
32+
}
33+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package io.github.miniplaceholders.expansion.proxyconnection.common;
2+
3+
import io.github.miniplaceholders.api.Expansion;
4+
5+
import java.util.concurrent.Executors;
6+
import java.util.concurrent.ScheduledExecutorService;
7+
import java.util.regex.Pattern;
8+
9+
public abstract class PlatformProvider<S, M> {
10+
public static final String CHANNEL = "bungeecord:main";
11+
public static final Pattern SPLIT_PATTERN = Pattern.compile(", ");
12+
protected final ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
13+
protected S platformInstance;
14+
protected M miniInstance;
15+
protected final DataCache dataCache = new DataCache();
16+
17+
protected PlatformProvider(S platformInstance, M miniInstance) {
18+
this.platformInstance = platformInstance;
19+
this.miniInstance = miniInstance;
20+
}
21+
22+
public abstract Expansion.Builder provideBuilder();
23+
}

fabric/build.gradle.kts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
plugins {
2+
id("fabric-loom")
3+
}
4+
5+
dependencies {
6+
compileOnly(libs.miniplaceholders)
7+
compileOnly(projects.proxyconnectionExpansionCommon)
8+
minecraft(libs.minecraft)
9+
mappings(loom.officialMojangMappings())
10+
modCompileOnly(libs.fabric.loader)
11+
modCompileOnly(libs.fabric.api)
12+
modCompileOnly(libs.adventure.platform.fabric)
13+
// modCompileOnly("com.pokeskies:fabricpluginmessage:1.0.0")
14+
modCompileOnly("maven.modrinth:fabric-plugin-messaging:1.0.0")
15+
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
package io.github.miniplaceholders.expansion.proxyconnection.fabric;
2+
3+
import com.google.common.io.ByteArrayDataInput;
4+
import com.google.common.io.ByteArrayDataOutput;
5+
import com.google.common.io.ByteStreams;
6+
import com.pokeskies.fabricpluginmessaging.PluginMessageEvent;
7+
import com.pokeskies.fabricpluginmessaging.PluginMessagePacket;
8+
import io.github.miniplaceholders.api.Expansion;
9+
import io.github.miniplaceholders.expansion.proxyconnection.common.BungeeMessageTypes;
10+
import io.github.miniplaceholders.expansion.proxyconnection.common.PlatformProvider;
11+
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;
12+
import net.kyori.adventure.text.minimessage.tag.Tag;
13+
import net.minecraft.server.MinecraftServer;
14+
import net.minecraft.server.level.ServerPlayer;
15+
16+
import java.util.List;
17+
import java.util.concurrent.TimeUnit;
18+
19+
public final class FabricProvider extends PlatformProvider<MinecraftServer, Object> {
20+
public FabricProvider(Object platformInstance, Object miniInstance) {
21+
super((MinecraftServer) platformInstance, miniInstance);
22+
}
23+
24+
@Override
25+
public Expansion.Builder provideBuilder() {
26+
executor.schedule(() -> {
27+
final var players = platformInstance.getPlayerList().getPlayers().iterator();
28+
if (!players.hasNext()) {
29+
return;
30+
}
31+
final ServerPlayer player = players.next();
32+
for (String server : dataCache.getServers()) {
33+
final ByteArrayDataOutput output = ByteStreams.newDataOutput();
34+
output.writeUTF(BungeeMessageTypes.PLAYER_COUNT.rawType());
35+
output.writeUTF(server);
36+
ServerPlayNetworking.send(player, new PluginMessagePacket(output.toByteArray()));
37+
}
38+
}, 5, TimeUnit.SECONDS);
39+
40+
executor.schedule(() -> {
41+
final var players = platformInstance.getPlayerList().getPlayers().iterator();
42+
if (!players.hasNext()) {
43+
return;
44+
}
45+
final ServerPlayer player = players.next();
46+
final ByteArrayDataOutput output = ByteStreams.newDataOutput();
47+
output.writeUTF(BungeeMessageTypes.GET_SERVERS.rawType());
48+
ServerPlayNetworking.send(player, new PluginMessagePacket(output.toByteArray()));
49+
}, 10, TimeUnit.MINUTES);
50+
51+
PluginMessageEvent.EVENT.register((payload, context) -> {
52+
final ByteArrayDataInput data = ByteStreams.newDataInput(payload.getData());
53+
final String subchannel = data.readUTF();
54+
if (BungeeMessageTypes.PLAYER_COUNT.compareProvided(subchannel)) {
55+
final String server = data.readUTF();
56+
final int playerCount = data.readInt();
57+
dataCache.setPlayerCount(server, playerCount);
58+
return;
59+
}
60+
61+
if (BungeeMessageTypes.GET_SERVERS.compareProvided(subchannel)) {
62+
final String serversString = data.readUTF();
63+
if (serversString.isEmpty()) {
64+
return;
65+
}
66+
String[] servers = SPLIT_PATTERN.split(serversString);
67+
dataCache.updateServers(List.of(servers));
68+
}
69+
});
70+
return Expansion.builder("proxyconnection")
71+
.globalPlaceholder("player_count", (queue, context) -> {
72+
if (queue.hasNext()) {
73+
final String server = queue.pop().value();
74+
final int serverPlayerCount = dataCache.getPlayerCount(server);
75+
return Tag.preProcessParsed(Integer.toString(serverPlayerCount));
76+
}
77+
final int proxyPlayerCount = dataCache.getProxyPlayerCount();
78+
return Tag.preProcessParsed(Integer.toString(proxyPlayerCount));
79+
});
80+
}
81+
}

gradle/libs.versions.toml

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,29 +2,44 @@ metadata.format.version = "1.1"
22

33
[versions]
44

5-
velocity = "3.3.0-SNAPSHOT"
6-
paper = "1.20.2-R0.1-SNAPSHOT"
5+
velocity = "3.4.0-SNAPSHOT"
6+
paper = "1.21.8-R0.1-SNAPSHOT"
7+
sponge = "14.0.0"
78

89
blossom = "2.1.0"
9-
shadow = "8.1.1"
10+
shadow = "9.0.2"
1011
runtask = "2.3.1"
1112

1213
miniplaceholders = "3.0.0-SNAPSHOT"
1314
adventure = "4.24.0"
14-
adventurefabric = "5.10.1"
15+
adventurefabric = "6.6.0"
16+
17+
fabric-loader = "0.17.2"
18+
fabric-api = "0.131.0+1.21.8"
19+
minecraft = "1.21.8"
1520

1621
[libraries]
1722

23+
minecraft = { group = "com.mojang", name = "minecraft", version.ref = "minecraft" }
24+
velocity = { module = "com.velocitypowered:velocity-api", version.ref = "velocity" }
25+
papermc = { module = "io.papermc.paper:paper-api", version.ref = "paper" }
26+
sponge = { module = "org.spongepowered:spongeapi", version.ref = "sponge" }
27+
28+
fabric-loader = { group = "net.fabricmc", name = "fabric-loader", version.ref = "fabric-loader" }
29+
fabric-api = { group = "net.fabricmc.fabric-api", name = "fabric-api", version.ref = "fabric-api" }
30+
1831
miniplaceholders = { group = "io.github.miniplaceholders", name = "miniplaceholders-api", version.ref = "miniplaceholders" }
1932

2033
adventure-api = { group = "net.kyori", name = "adventure-api", version.ref = "adventure" }
2134
adventure-minimessage = { group = "net.kyori", name = "adventure-text-minimessage", version.ref = "adventure" }
2235
adventure-platform-fabric = { group = "net.kyori", name = "adventure-platform-fabric", version.ref = "adventurefabric" }
2336

37+
caffeine = "com.github.ben-manes.caffeine:caffeine:3.2.2"
38+
2439
[plugins]
2540

2641
blossom = { id = "net.kyori.blossom", version.ref = "blossom" }
27-
shadow = { id = "com.github.johnrengelman.shadow", version.ref = "shadow" }
42+
shadow = { id = "com.gradleup.shadow", version.ref = "shadow" }
2843
runvelocity = { id = "xyz.jpenilla.run-velocity", version.ref = "runtask" }
2944
runpaper = { id = "xyz.jpenilla.run-velocity", version.ref = "runtask" }
30-
idea-ext = { id = "org.jetbrains.gradle.plugin.idea-ext", version = "1.2" }
45+
idea-ext = { id = "org.jetbrains.gradle.plugin.idea-ext", version = "1.2" }

paper/build.gradle.kts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
plugins {
2+
alias(libs.plugins.runpaper)
3+
}
4+
5+
dependencies {
6+
compileOnly(libs.papermc)
7+
compileOnly(libs.miniplaceholders)
8+
implementation(projects.proxyconnectionExpansionCommon)
9+
}

0 commit comments

Comments
 (0)