Skip to content

Commit f27b3ce

Browse files
Jakubk15vLuckyyyRollcziimDMK
authored
GH-119 Add Velocity support (#119)
* Add `multification-paper` module with Paper platform support and examples. * Update GitHub workflows to refine CI/CD setup * ci: make gradlew executable in CI workflows * Refactor README examples for cleaner code and update Maven repository comments. * Add Velocity support * Begin adding examples * Add Velocity platform support with configuration management and commands * re-add .gitignore * Update README.md to reflect Velocity platform support and improve code examples * Enforce JDK 21 for Velocity module * Fix example build * CR * Update multification-velocity/src/com/eternalcode/multification/velocity/VelocityViewerProvider.java Co-authored-by: DMK <81445555+imDMK@users.noreply.github.com> * Fix method name casing for getPlayer --------- Co-authored-by: Martin Sulikowski <vluckyyy.biznes@gmail.com> Co-authored-by: Rollczi <ndejlich5@gmail.com> Co-authored-by: DMK <81445555+imDMK@users.noreply.github.com>
1 parent 0380b92 commit f27b3ce

File tree

15 files changed

+470
-11
lines changed

15 files changed

+470
-11
lines changed

README.md

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,12 @@ Messages can be sent to any audience, such as players or the console.
3535

3636
## Supported Platforms
3737

38-
| Platform | Module | Java Version | Adventure API | Status |
39-
|-------------------|------------------------|--------------|-----------------------|------------------------|
40-
| **Paper** | `multification-paper` | Java 21 | Native (built-in) |Recommended |
41-
| **Bukkit/Spigot** | `multification-bukkit` | Java 8+ | External adapter | ✅ Supported |
42-
| **Velocity** | `multification-velocity` | Java 21+ | Native | ❌ Soon |
43-
| **Core** | `multification-core` | Java 8+ | Custom implementation | For custom platforms |
38+
| Platform | Module | Java Version | Adventure API | Status |
39+
|-------------------|--------------------------|--------------|-----------------------|-------------------------|
40+
| **Paper** | `multification-paper` | Java 21 | Native (built-in) |Supported |
41+
| **Bukkit/Spigot** | `multification-bukkit` | Java 8+ | External adapter | ✅ Supported |
42+
| **Velocity** | `multification-velocity` | Java 21+ | Native | ✅ Supported |
43+
| **Core** | `multification-core` | Java 8+ | Custom implementation | 🔨 For custom platforms |
4444

4545
> **💡 Recommendation:** Use `multification-paper` for Paper servers (1.19.4+) to leverage native Adventure API without
4646
> external dependencies.
@@ -172,9 +172,9 @@ public class MessagesConfig {
172172

173173
```java
174174
Cdn cdn = CdnFactory.createYamlLike()
175-
.getSettings()
176-
.withComposer(Notice.class, new MultificationNoticeCdnComposer(multification.getNoticeRegistry()))
177-
.build();
175+
.getSettings()
176+
.withComposer(Notice.class, new MultificationNoticeCdnComposer(multification.getNoticeRegistry()))
177+
.build();
178178
```
179179

180180
#### (CDN) 4. Load the configuration:
@@ -224,7 +224,10 @@ public class MessagesConfig extends OkaeriConfig {
224224
```java
225225
MessagesConfig config = (MessagesConfig) ConfigManager.create(MessagesConfig.class)
226226
.withConfigurer(new MultificationSerdesPack(multification.getNoticeRegistry()))
227-
.withConfigurer(new SerdesCommons(), new YamlBukkitConfigurer(), new SerdesBukkit()) // specify configurers for your platform
227+
.withConfigurer(
228+
new SerdesCommons(),
229+
new YamlBukkitConfigurer(),
230+
new SerdesBukkit()) // specify configurers for your platform
228231
.withBindFile(new File(dataFolder, "messages.yml"))
229232
.withRemoveOrphans(true) // automatic removal of undeclared keys
230233
.saveDefaults() // save file if does not exists

buildSrc/src/main/kotlin/Versions.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
object Versions {
32

43
const val ADVENTURE_PLATFORM_BUKKIT = "4.3.3"
@@ -11,7 +10,9 @@ object Versions {
1110
const val AWAITILITY = "4.3.0"
1211

1312
const val SPIGOT_API = "1.21.4-R0.1-SNAPSHOT"
13+
const val VELOCITY_API = "3.4.0-SNAPSHOT"
1414

1515
const val JETBRAINS_ANNOTATIONS = "26.0.2-1"
1616

17+
1718
}

examples/velocity/build.gradle.kts

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
plugins {
2+
id("java")
3+
id("com.gradleup.shadow") version "9.0.0-beta4"
4+
id("xyz.jpenilla.run-velocity") version "3.0.2"
5+
}
6+
7+
version = "1.0.0-SNAPSHOT"
8+
9+
repositories {
10+
mavenCentral()
11+
maven("https://repo.papermc.io/repository/maven-public/")
12+
maven("https://repo.panda-lang.org/releases/")
13+
}
14+
15+
dependencies {
16+
compileOnly("com.velocitypowered:velocity-api:${Versions.VELOCITY_API}")
17+
annotationProcessor("com.velocitypowered:velocity-api:${Versions.VELOCITY_API}")
18+
19+
implementation("dev.rollczi:litecommands-velocity:3.10.6")
20+
// implementation("com.eternalcode:multification-velocity:1.2.3") // <-- uncomment in your project
21+
// implementation("com.eternalcode:multification-cdn:1.2.3") // <-- uncomment in your project
22+
23+
implementation(project(":multification-velocity")) // don't use this line in your build.gradle
24+
implementation(project(":multification-cdn")) // don't use this line in your build.gradle
25+
}
26+
27+
val pluginName = "ExampleVelocityPlugin"
28+
val packageName = "com.eternalcode.example.velocity"
29+
30+
tasks.shadowJar {
31+
archiveFileName.set("$pluginName v${project.version}.jar")
32+
33+
listOf(
34+
"dev.rollczi.litecommands",
35+
"panda.std",
36+
"panda.utilities",
37+
).forEach { relocate(it, "$packageName.libs.$it") }
38+
}
39+
40+
sourceSets.test {
41+
java.setSrcDirs(emptyList<String>())
42+
resources.setSrcDirs(emptyList<String>())
43+
}
44+
45+
tasks.runVelocity {
46+
velocityVersion("${Versions.VELOCITY_API}")
47+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package com.eternalcode.example;
2+
3+
import com.eternalcode.example.command.ReloadCommand;
4+
import com.eternalcode.example.command.SwitchCommand;
5+
import com.eternalcode.example.config.ConfigurationManager;
6+
import com.eternalcode.example.config.MessagesConfig;
7+
import com.eternalcode.example.notice.ExampleMultification;
8+
import com.google.inject.Inject;
9+
import com.velocitypowered.api.command.CommandSource;
10+
import com.velocitypowered.api.event.Subscribe;
11+
import com.velocitypowered.api.event.proxy.ProxyInitializeEvent;
12+
import com.velocitypowered.api.event.proxy.ProxyShutdownEvent;
13+
import com.velocitypowered.api.plugin.Plugin;
14+
import com.velocitypowered.api.plugin.annotation.DataDirectory;
15+
import com.velocitypowered.api.proxy.ProxyServer;
16+
import dev.rollczi.litecommands.LiteCommands;
17+
import dev.rollczi.litecommands.velocity.LiteVelocityFactory;
18+
19+
import java.nio.file.Path;
20+
21+
@Plugin(
22+
id = "example-velocity-plugin",
23+
name = "Example Velocity Plugin",
24+
version = "1.0.0",
25+
description = "An example Velocity plugin demonstrating Multification usage",
26+
authors = { "EternalCode" }
27+
)
28+
public class ExampleVelocityPlugin {
29+
30+
private final ProxyServer server;
31+
private final Path dataDirectory;
32+
33+
private LiteCommands<CommandSource> liteCommands;
34+
35+
@Inject
36+
public ExampleVelocityPlugin(ProxyServer server, @DataDirectory Path dataDirectory) {
37+
this.server = server;
38+
this.dataDirectory = dataDirectory;
39+
}
40+
41+
@Subscribe
42+
void onProxyInitialize(ProxyInitializeEvent event) {
43+
MessagesConfig messagesConfig = new MessagesConfig();
44+
ExampleMultification multification = new ExampleMultification(this, this.server, messagesConfig);
45+
46+
ConfigurationManager configurationManager = new ConfigurationManager(this.dataDirectory.toFile(),
47+
multification.getNoticeRegistry());
48+
configurationManager.load(messagesConfig, "messages.yml");
49+
50+
this.liteCommands = LiteVelocityFactory.builder(this.server)
51+
.commands(
52+
new ReloadCommand(configurationManager, multification),
53+
new SwitchCommand(multification))
54+
.build();
55+
56+
this.server.getEventManager().register(this, new PlayerConnectListener(multification));
57+
}
58+
59+
@Subscribe
60+
void onProxyShutdown(ProxyShutdownEvent event) {
61+
if (this.liteCommands != null) {
62+
this.liteCommands.unregister();
63+
}
64+
}
65+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package com.eternalcode.example;
2+
3+
import com.eternalcode.example.notice.ExampleMultification;
4+
import com.velocitypowered.api.event.Subscribe;
5+
import com.velocitypowered.api.event.player.ServerConnectedEvent;
6+
7+
public class PlayerConnectListener {
8+
9+
private final ExampleMultification multification;
10+
11+
public PlayerConnectListener(ExampleMultification multification) {
12+
this.multification = multification;
13+
}
14+
15+
@Subscribe
16+
void onPlayerConnect(ServerConnectedEvent event) {
17+
this.multification.create()
18+
.all()
19+
.notice(messagesConfig -> messagesConfig.joinedTheServer)
20+
.placeholder("<server>", event.getServer().getServerInfo().getName())
21+
.send();
22+
}
23+
24+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package com.eternalcode.example.command;
2+
3+
import com.eternalcode.example.config.ConfigurationManager;
4+
import com.eternalcode.example.notice.ExampleMultification;
5+
import com.velocitypowered.api.command.CommandSource;
6+
import com.velocitypowered.api.proxy.Player;
7+
import dev.rollczi.litecommands.annotations.command.Command;
8+
import dev.rollczi.litecommands.annotations.context.Context;
9+
import dev.rollczi.litecommands.annotations.execute.Execute;
10+
11+
@Command(name = "reload-config")
12+
public class ReloadCommand {
13+
14+
private final ConfigurationManager configurationManager;
15+
private final ExampleMultification multification;
16+
17+
public ReloadCommand(ConfigurationManager configurationManager, ExampleMultification multification) {
18+
this.configurationManager = configurationManager;
19+
this.multification = multification;
20+
}
21+
22+
@Execute
23+
public void execute(@Context CommandSource sender) {
24+
this.configurationManager.reload();
25+
26+
if (sender instanceof Player player) {
27+
this.multification.create()
28+
.player(player.getUniqueId())
29+
.notice(messagesConfig -> messagesConfig.reloadMessage)
30+
.send();
31+
return;
32+
}
33+
34+
this.multification.create()
35+
.console()
36+
.notice(messagesConfig -> messagesConfig.reloadMessage)
37+
.send();
38+
}
39+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package com.eternalcode.example.command;
2+
3+
import com.eternalcode.example.notice.ExampleMultification;
4+
import com.velocitypowered.api.proxy.Player;
5+
import com.velocitypowered.api.proxy.server.RegisteredServer;
6+
import dev.rollczi.litecommands.annotations.argument.Arg;
7+
import dev.rollczi.litecommands.annotations.command.Command;
8+
import dev.rollczi.litecommands.annotations.context.Context;
9+
import dev.rollczi.litecommands.annotations.execute.Execute;
10+
11+
@Command(name = "switch")
12+
public class SwitchCommand {
13+
14+
private final ExampleMultification multification;
15+
16+
public SwitchCommand(ExampleMultification multification) {
17+
this.multification = multification;
18+
}
19+
20+
@Execute
21+
void execute(@Context Player player, @Arg RegisteredServer server) {
22+
player.createConnectionRequest(server).fireAndForget();
23+
this.multification.create()
24+
.player(player.getUniqueId())
25+
.notice(messagesConfig -> messagesConfig.switchedServer)
26+
.placeholder("<server>", server.getServerInfo().getName())
27+
.send();
28+
29+
}
30+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package com.eternalcode.example.config;
2+
3+
import com.eternalcode.multification.cdn.MultificationNoticeCdnComposer;
4+
import com.eternalcode.multification.notice.Notice;
5+
import com.eternalcode.multification.notice.resolver.NoticeResolverRegistry;
6+
import net.dzikoysk.cdn.Cdn;
7+
import net.dzikoysk.cdn.CdnFactory;
8+
import net.dzikoysk.cdn.source.Source;
9+
10+
import java.io.File;
11+
12+
public class ConfigurationManager {
13+
14+
private final File dataFolder;
15+
private final Cdn cdn;
16+
private MessagesConfig messagesConfig;
17+
18+
public ConfigurationManager(File dataFolder, NoticeResolverRegistry noticeRegistry) {
19+
this.dataFolder = dataFolder;
20+
this.cdn = CdnFactory.createYamlLike()
21+
.getSettings()
22+
.withComposer(Notice.class, new MultificationNoticeCdnComposer(noticeRegistry))
23+
.build();
24+
}
25+
26+
public void load(MessagesConfig config, String fileName) {
27+
this.messagesConfig = config;
28+
File file = new File(this.dataFolder, fileName);
29+
30+
this.cdn.load(Source.of(file), config)
31+
.orThrow(cause -> cause);
32+
33+
this.cdn.render(config, Source.of(file))
34+
.orThrow(cause -> cause);
35+
}
36+
37+
public void reload() {
38+
if (this.messagesConfig != null) {
39+
load(this.messagesConfig, "messages.yml");
40+
}
41+
}
42+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package com.eternalcode.example.config;
2+
3+
import com.eternalcode.multification.notice.Notice;
4+
import net.dzikoysk.cdn.entity.Description;
5+
import net.kyori.adventure.bossbar.BossBar;
6+
7+
import java.time.Duration;
8+
9+
public class MessagesConfig {
10+
11+
@Description("# Join message")
12+
public Notice joinedTheServer = Notice.builder()
13+
.chat("<green><player> has joined the server!")
14+
.bossBar(
15+
BossBar.Color.GREEN,
16+
BossBar.Overlay.PROGRESS,
17+
Duration.ofSeconds(5),
18+
1.0F,
19+
"<green><player> has joined the server!"
20+
)
21+
.sound("minecraft:entity.player.levelup", 1.0F, 1.0F)
22+
.build();
23+
24+
@Description("# Server switch message")
25+
public Notice switchedServer = Notice.builder()
26+
.chat("Switched to <server>!")
27+
.sound("minecraft:entity.enderman.teleport", 1.0F, 1.0F)
28+
.build();
29+
30+
public Notice reloadMessage = Notice.builder()
31+
.chat("<pride:pride>Configuration has been reloaded!")
32+
.sound("minecraft:ambient.basalt_deltas.additions", 1.0F, 1.0F)
33+
.build();
34+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package com.eternalcode.example.notice;
2+
3+
4+
import com.eternalcode.example.config.MessagesConfig;
5+
import com.eternalcode.multification.adventure.AudienceConverter;
6+
import com.eternalcode.multification.translation.TranslationProvider;
7+
import com.eternalcode.multification.velocity.VelocityMultification;
8+
import com.velocitypowered.api.command.CommandSource;
9+
import com.velocitypowered.api.proxy.ProxyServer;
10+
import net.kyori.adventure.text.Component;
11+
import net.kyori.adventure.text.minimessage.MiniMessage;
12+
import net.kyori.adventure.text.serializer.ComponentSerializer;
13+
import org.jetbrains.annotations.NotNull;
14+
15+
public class ExampleMultification extends VelocityMultification<MessagesConfig> {
16+
17+
private final MessagesConfig messagesConfig;
18+
private final MiniMessage miniMessage;
19+
20+
public ExampleMultification(Object plugin, ProxyServer server, MessagesConfig messagesConfig) {
21+
super(server, plugin);
22+
this.messagesConfig = messagesConfig;
23+
this.miniMessage = MiniMessage.miniMessage();
24+
}
25+
26+
@Override
27+
protected @NotNull TranslationProvider<MessagesConfig> translationProvider() {
28+
return locale -> this.messagesConfig;
29+
}
30+
31+
@Override
32+
protected @NotNull ComponentSerializer<Component, Component, String> serializer() {
33+
return this.miniMessage;
34+
}
35+
36+
@Override
37+
protected @NotNull AudienceConverter<CommandSource> audienceConverter() {
38+
return commandSender -> commandSender;
39+
}
40+
}

0 commit comments

Comments
 (0)