Skip to content

Commit a182fed

Browse files
committed
add velocity implementation
1 parent 25c9ee7 commit a182fed

File tree

14 files changed

+884
-1
lines changed

14 files changed

+884
-1
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ The Server API is organized into several modules:
1919
- `bungeecord` - The platform-specific integration for Servers running on BungeeCord.
2020
- `common` - Contains shared classes and utilities used across different server implementations to ensure consistent
2121
behavior and reduce code duplication.
22+
- `velocity` - The platform-specific integration for Servers running on Velocity.
2223

2324
## Integrations
2425

server/velocity/build.gradle.kts

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
plugins {
2+
id("java")
3+
}
4+
5+
repositories {
6+
maven("https://repo.papermc.io/repository/maven-public/")
7+
}
8+
9+
dependencies {
10+
compileOnly("com.velocitypowered:velocity-api:3.3.0-SNAPSHOT")
11+
annotationProcessor("com.velocitypowered:velocity-api:3.3.0-SNAPSHOT")
12+
}
13+
14+
var generateJavaTask = tasks.create("generateJava", Copy::class) {
15+
val properties = mapOf("version" to project.version.toString())
16+
inputs.properties(properties)
17+
18+
from("src/template/java")
19+
into("${project.layout.buildDirectory.get().asFile}/generated/java")
20+
21+
expand(properties)
22+
}
23+
24+
25+
sourceSets.findByName("main")?.apply {
26+
this.java.srcDirs("${project.buildDir}/generated/java")
27+
}
28+
29+
tasks.named("checkLicenseMain") {
30+
dependsOn(generateJavaTask)
31+
}
32+
33+
tasks.named("updateLicenseMain") {
34+
dependsOn(generateJavaTask)
35+
}
36+
37+
tasks.named("sourcesJar") {
38+
dependsOn(generateJavaTask)
39+
}
40+
41+
tasks.compileJava {
42+
dependsOn(generateJavaTask)
43+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
* MIT License
3+
*
4+
* Copyright (c) 2024 LabyMedia GmbH
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in all
14+
* copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+
* SOFTWARE.
23+
*/
24+
25+
package net.labymod.serverapi.server.velocity;
26+
27+
import com.velocitypowered.api.proxy.Player;
28+
import net.labymod.serverapi.server.common.model.player.AbstractServerLabyModPlayer;
29+
30+
import java.util.UUID;
31+
32+
public class LabyModPlayer extends AbstractServerLabyModPlayer<LabyModPlayer, Player> {
33+
34+
public LabyModPlayer(
35+
LabyModProtocolService protocolService,
36+
UUID uniqueId,
37+
Player player,
38+
String labyModVersion
39+
) {
40+
super(protocolService, uniqueId, player, labyModVersion);
41+
}
42+
}
Lines changed: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
1+
/*
2+
* MIT License
3+
*
4+
* Copyright (c) 2024 LabyMedia GmbH
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in all
14+
* copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+
* SOFTWARE.
23+
*/
24+
25+
package net.labymod.serverapi.server.velocity;
26+
27+
import com.velocitypowered.api.proxy.ProxyServer;
28+
import com.velocitypowered.api.proxy.messages.MinecraftChannelIdentifier;
29+
import net.labymod.serverapi.api.Protocol;
30+
import net.labymod.serverapi.api.logger.NoOpProtocolPlatformLogger;
31+
import net.labymod.serverapi.api.logger.ProtocolPlatformLogger;
32+
import net.labymod.serverapi.api.packet.Packet;
33+
import net.labymod.serverapi.api.payload.PayloadChannelIdentifier;
34+
import net.labymod.serverapi.api.payload.io.PayloadWriter;
35+
import net.labymod.serverapi.core.packet.serverbound.login.VersionLoginPacket;
36+
import net.labymod.serverapi.server.common.AbstractServerLabyModProtocolService;
37+
import net.labymod.serverapi.server.velocity.event.LabyModPacketReceivedEvent;
38+
import net.labymod.serverapi.server.velocity.event.LabyModPacketSentEvent;
39+
import net.labymod.serverapi.server.velocity.handler.DefaultVersionLoginPacketHandler;
40+
import net.labymod.serverapi.server.velocity.listener.DefaultDisconnectListener;
41+
import net.labymod.serverapi.server.velocity.listener.DefaultPluginMessageListener;
42+
import org.jetbrains.annotations.NotNull;
43+
import org.slf4j.Logger;
44+
45+
import java.util.Objects;
46+
import java.util.UUID;
47+
48+
public class LabyModProtocolService extends AbstractServerLabyModProtocolService<LabyModPlayer> {
49+
50+
private static final LabyModProtocolService INSTANCE = new LabyModProtocolService();
51+
private ProtocolPlatformLogger logger = NoOpProtocolPlatformLogger.get();
52+
53+
private Object plugin;
54+
private ProxyServer server;
55+
56+
private LabyModProtocolService() {
57+
// singleton
58+
}
59+
60+
/**
61+
* @return the instance of the protocol service
62+
*/
63+
public static LabyModProtocolService get() {
64+
return INSTANCE;
65+
}
66+
67+
/**
68+
* Initializes the protocol services. Can only be done once.
69+
*
70+
* @param plugin the instance of the plugin main class
71+
* @param server the proxy server instance
72+
* @param logger the logger instance
73+
* @throws IllegalStateException if the plugin is already set
74+
* @throws NullPointerException if the plugin is null
75+
*/
76+
public static void initialize(
77+
@NotNull Object plugin,
78+
@NotNull ProxyServer server,
79+
@NotNull Logger logger
80+
) {
81+
LabyModProtocolService.get().initializePlugin(plugin, server, logger);
82+
}
83+
84+
@Override
85+
public void afterPacketHandled(
86+
@NotNull Protocol protocol,
87+
@NotNull Packet packet,
88+
@NotNull UUID sender
89+
) {
90+
if (this.server != null) {
91+
this.server.getEventManager().fire(new LabyModPacketReceivedEvent(
92+
this,
93+
protocol,
94+
sender,
95+
packet
96+
));
97+
}
98+
}
99+
100+
@Override
101+
public void afterPacketSent(
102+
@NotNull Protocol protocol,
103+
@NotNull Packet packet,
104+
@NotNull UUID recipient
105+
) {
106+
if (this.server != null) {
107+
this.server.getEventManager().fire(new LabyModPacketSentEvent(
108+
this,
109+
protocol,
110+
recipient,
111+
packet
112+
));
113+
}
114+
}
115+
116+
public @NotNull MinecraftChannelIdentifier mapToVelocityChannelIdentifier(
117+
@NotNull PayloadChannelIdentifier identifier
118+
) {
119+
Objects.requireNonNull(identifier, "Identifier cannot be null");
120+
return MinecraftChannelIdentifier.create(identifier.getNamespace(), identifier.getPath());
121+
}
122+
123+
public @NotNull PayloadChannelIdentifier mapFromVelocityChannelIdentifier(
124+
@NotNull MinecraftChannelIdentifier identifier
125+
) {
126+
Objects.requireNonNull(identifier, "Identifier cannot be null");
127+
return PayloadChannelIdentifier.create(identifier.getNamespace(), identifier.getName());
128+
}
129+
130+
/**
131+
* {@inheritDoc}
132+
*/
133+
@Override
134+
public void send(
135+
@NotNull PayloadChannelIdentifier identifier,
136+
@NotNull UUID recipient,
137+
@NotNull PayloadWriter writer
138+
) {
139+
Objects.requireNonNull(identifier, "Identifier cannot be null");
140+
Objects.requireNonNull(recipient, "Recipient cannot be null");
141+
Objects.requireNonNull(writer, "Writer cannot be null");
142+
if (this.plugin == null) {
143+
throw new IllegalStateException("The plugin instance is not set yet");
144+
}
145+
146+
this.server.getPlayer(recipient).ifPresent(player -> player.sendPluginMessage(
147+
this.mapToVelocityChannelIdentifier(identifier),
148+
writer.toByteArray()
149+
));
150+
}
151+
152+
/**
153+
* {@inheritDoc}
154+
*/
155+
@Override
156+
public @NotNull ProtocolPlatformLogger logger() {
157+
return this.logger;
158+
}
159+
160+
/**
161+
* {@inheritDoc}
162+
*/
163+
@Override
164+
public boolean isInitialized() {
165+
return this.plugin != null;
166+
}
167+
168+
private void initializePlugin(
169+
@NotNull Object plugin,
170+
@NotNull ProxyServer server,
171+
@NotNull Logger logger
172+
) {
173+
Objects.requireNonNull(plugin, "Plugin cannot be null");
174+
Objects.requireNonNull(server, "Server cannot be null");
175+
Objects.requireNonNull(logger, "Logger cannot be null");
176+
if (this.plugin != null) {
177+
throw new IllegalStateException("The plugin instance is already set");
178+
}
179+
180+
this.server = server;
181+
this.plugin = plugin;
182+
this.logger = new Slf4jPlatformLogger(logger);
183+
this.registry().addRegisterListener(protocol -> {
184+
this.server.getChannelRegistrar().register(
185+
this.mapToVelocityChannelIdentifier(protocol.identifier())
186+
);
187+
188+
this.server.getEventManager().register(
189+
plugin,
190+
new DefaultPluginMessageListener(this, protocol)
191+
);
192+
}
193+
);
194+
195+
this.initializeManaged();
196+
}
197+
198+
private void initializeManaged() {
199+
this.labyModProtocol.registerHandler(
200+
VersionLoginPacket.class,
201+
new DefaultVersionLoginPacketHandler(this, this.players, this.server)
202+
);
203+
204+
this.server.getEventManager().register(
205+
this.plugin,
206+
new DefaultDisconnectListener(this.players)
207+
);
208+
}
209+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*
2+
* MIT License
3+
*
4+
* Copyright (c) 2024 LabyMedia GmbH
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in all
14+
* copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+
* SOFTWARE.
23+
*/
24+
25+
package net.labymod.serverapi.server.velocity;
26+
27+
import com.google.inject.Inject;
28+
import com.velocitypowered.api.event.Subscribe;
29+
import com.velocitypowered.api.event.proxy.ProxyInitializeEvent;
30+
import com.velocitypowered.api.plugin.Plugin;
31+
import com.velocitypowered.api.proxy.ProxyServer;
32+
import org.slf4j.Logger;
33+
34+
@Plugin(
35+
id = "labymod-server-api",
36+
name = "LabyModServerAPI",
37+
version = LabyModServerAPIBuildInfo.VERSION
38+
)
39+
public class LabyModServerAPIPlugin {
40+
41+
private final ProxyServer server;
42+
private final Logger logger;
43+
44+
@Inject
45+
public LabyModServerAPIPlugin(ProxyServer server, Logger logger) {
46+
this.server = server;
47+
this.logger = logger;
48+
}
49+
50+
@Subscribe
51+
public void onProxyInitialization(ProxyInitializeEvent event) {
52+
LabyModProtocolService.initialize(this, this.server, this.logger);
53+
}
54+
}
55+

0 commit comments

Comments
 (0)