Skip to content

Commit f7a2929

Browse files
committed
Further work on isolation: Velocity (mostly) works, initial progress on BungeeCord
1 parent afd2150 commit f7a2929

21 files changed

Lines changed: 299 additions & 144 deletions

File tree

Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,28 @@
11
plugins {
2-
id("geyser.platform-conventions")
3-
id("geyser.modrinth-uploading-conventions")
2+
id("geyser.platform-base-conventions")
43
}
54

65
dependencies {
7-
api(projects.core)
8-
6+
implementation(projects.core)
7+
implementation(libs.floodgate.bungee)
98
implementation(libs.cloud.bungee)
109
compileOnlyApi(libs.bungeecord.proxy) {
1110
isTransitive = false
1211
}
1312
compileOnlyApi(libs.bungeecord.api)
14-
implementation(libs.floodgate.bungee)
1513
}
1614

17-
platformRelocate("net.md_5.bungee.jni")
18-
platformRelocate("net.kyori")
19-
platformRelocate("org.incendo")
20-
platformRelocate("io.leangen.geantyref") // provided by cloud and Configurate, should also be relocated
21-
platformRelocate("org.yaml") // Broken as of 1.20
22-
platformRelocate("org.spongepowered")
23-
platformRelocate("org.bstats")
15+
// TODO: figure out if yaml works correctly without falling back to bungee's version
16+
// platformRelocate("org.yaml") // Broken as of 1.20
2417

2518
// These dependencies are already present on the platform
2619
provided(libs.bungeecord.proxy)
2720

2821
tasks.withType<com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar> {
29-
archiveBaseName.set("Geyser-BungeeCord")
22+
archiveBaseName.set("Geyser-BungeeCord-Base")
3023

3124
dependencies {
3225
exclude(dependency("com.google.*:.*"))
3326
exclude(dependency("io.netty.*:.*"))
3427
}
3528
}
36-
37-
modrinth {
38-
uploadFile.set(tasks.getByPath("shadowJar"))
39-
loaders.add("bungeecord")
40-
}

bootstrap/bungeecord/base/src/main/java/org/geysermc/geyser/platform/bungeecord/BungeeMetrics.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,4 +96,9 @@ private void writeFile(File file, String... lines) throws IOException {
9696
}
9797
}
9898
}
99+
100+
@Override
101+
public boolean disableRelocateCheck() {
102+
return true;
103+
}
99104
}

bootstrap/bungeecord/base/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeePlugin.java renamed to bootstrap/bungeecord/base/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeePlatform.java

Lines changed: 44 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,15 @@
2929
import net.md_5.bungee.BungeeCord;
3030
import net.md_5.bungee.Util;
3131
import net.md_5.bungee.api.CommandSender;
32+
import net.md_5.bungee.api.ProxyServer;
3233
import net.md_5.bungee.api.config.ListenerInfo;
3334
import net.md_5.bungee.api.plugin.Plugin;
3435
import net.md_5.bungee.protocol.ProtocolConstants;
3536
import org.checkerframework.checker.nullness.qual.NonNull;
3637
import org.checkerframework.checker.nullness.qual.Nullable;
3738
import org.geysermc.floodgate.core.skin.SkinApplier;
39+
import org.geysermc.floodgate.isolation.IsolatedPlatform;
40+
import org.geysermc.floodgate.isolation.library.LibraryManager;
3841
import org.geysermc.geyser.FloodgateKeyLoader;
3942
import org.geysermc.geyser.GeyserBootstrap;
4043
import org.geysermc.geyser.GeyserImpl;
@@ -66,17 +69,28 @@
6669
import java.util.Optional;
6770
import java.util.concurrent.TimeUnit;
6871

69-
public class GeyserBungeePlugin extends Plugin implements GeyserBootstrap {
72+
public class GeyserBungeePlatform implements GeyserBootstrap, IsolatedPlatform {
73+
74+
private final ProxyServer proxyServer = ProxyServer.getInstance();
75+
private final Plugin plugin;
76+
private final GeyserBungeeLogger geyserLogger;
7077

7178
private CommandRegistry commandRegistry;
7279
private GeyserPluginConfig geyserConfig;
7380
private GeyserBungeeInjector geyserInjector;
74-
private final GeyserBungeeLogger geyserLogger = new GeyserBungeeLogger(getLogger());
7581
private IGeyserPingPassthrough geyserBungeePingPassthrough;
7682
private GeyserImpl geyser;
7783

84+
final LibraryManager manager; // don't remove! We don't need it in Geyser, but in Floodgate
85+
86+
public GeyserBungeePlatform(LibraryManager manager, Plugin plugin) {
87+
this.manager = manager;
88+
this.plugin = plugin;
89+
this.geyserLogger = new GeyserBungeeLogger(plugin.getLogger());
90+
}
91+
7892
@Override
79-
public void onLoad() {
93+
public void load() {
8094
onGeyserInitialize();
8195
}
8296

@@ -90,7 +104,7 @@ public void onGeyserInitialize() {
90104
geyserLogger.error(" / \\");
91105
geyserLogger.error(" / \\");
92106
geyserLogger.error(" / | \\");
93-
geyserLogger.error(" / | \\ " + GeyserLocale.getLocaleStringLog("geyser.bootstrap.unsupported_proxy", getProxy().getName()));
107+
geyserLogger.error(" / | \\ " + GeyserLocale.getLocaleStringLog("geyser.bootstrap.unsupported_proxy", proxyServer.getName()));
94108
geyserLogger.error(" / \\ " + GeyserLocale.getLocaleStringLog("geyser.may_not_work_as_intended_all_caps"));
95109
geyserLogger.error(" / o \\");
96110
geyserLogger.error("/_____________\\");
@@ -109,27 +123,27 @@ public void onGeyserInitialize() {
109123
return;
110124
}
111125
this.geyser = GeyserImpl.load(this);
112-
this.geyserInjector = new GeyserBungeeInjector(this);
126+
this.geyserInjector = new GeyserBungeeInjector(plugin);
113127

114128
// Registration of listeners occurs only once
115-
this.getProxy().getPluginManager().registerListener(this, new GeyserBungeeUpdateListener());
129+
proxyServer.getPluginManager().registerListener(plugin, new GeyserBungeeUpdateListener());
116130
}
117131

118132
@Override
119-
public void onEnable() {
133+
public void enable() {
120134
if (geyser == null) {
121135
return; // Config did not load properly!
122136
}
123137

124138
// After Geyser initialize for parity with other platforms.
125139
var sourceConverter = new CommandSourceConverter<>(
126140
CommandSender.class,
127-
id -> getProxy().getPlayer(id),
128-
() -> getProxy().getConsole(),
141+
proxyServer::getPlayer,
142+
proxyServer::getConsole,
129143
BungeeCommandSource::new
130144
);
131145
CommandManager<GeyserCommandSource> cloud = new BungeeCommandManager<>(
132-
this,
146+
plugin,
133147
ExecutionCoordinator.simpleCoordinator(),
134148
sourceConverter
135149
);
@@ -158,7 +172,7 @@ private void awaitStartupCompletion(int tries) {
158172

159173
Collection<Channel> listeners = (Collection<Channel>) listenersField.get(BungeeCord.getInstance());
160174
if (listeners.isEmpty()) {
161-
this.getProxy().getScheduler().schedule(this, this::onGeyserEnable, tries, TimeUnit.SECONDS);
175+
proxyServer.getScheduler().schedule(plugin, this::onGeyserEnable, tries, TimeUnit.SECONDS);
162176
} else {
163177
this.awaitStartupCompletion(++tries);
164178
}
@@ -176,7 +190,7 @@ public void onGeyserEnable() {
176190
}
177191

178192
// Force-disable query if enabled, or else Geyser won't enable
179-
for (ListenerInfo info : getProxy().getConfig().getListeners()) {
193+
for (ListenerInfo info : proxyServer.getConfig().getListeners()) {
180194
if (info.isQueryEnabled() && info.getQueryPort() == geyserConfig.bedrock().port()) {
181195
try {
182196
Field queryField = ListenerInfo.class.getDeclaredField("queryEnabled");
@@ -193,20 +207,20 @@ public void onGeyserEnable() {
193207
}
194208
}
195209

196-
if (getProxy().getPluginManager().getPlugin("floodgate") != null) {
210+
if (proxyServer.getPluginManager().getPlugin("floodgate") != null) {
197211
geyserLogger.warning("WHY DO YOU HAVE FLOODGATE INSTALLED???1/");
198212
}
199213

200214
if (geyserConfig.java().authType() == AuthType.FLOODGATE) {
201-
getProxy().getPluginManager().registerListener(this, new BungeeHybridListener());
215+
proxyServer.getPluginManager().registerListener(plugin, new BungeeHybridListener());
202216
}
203217

204218
GeyserImpl.start();
205219

206220
if (!geyserConfig.motd().integratedPingPassthrough()) {
207221
this.geyserBungeePingPassthrough = GeyserLegacyPingPassthrough.init(geyser);
208222
} else {
209-
this.geyserBungeePingPassthrough = new GeyserBungeePingPassthrough(getProxy());
223+
this.geyserBungeePingPassthrough = new GeyserBungeePingPassthrough(proxyServer);
210224
}
211225

212226
// No need to re-register commands or re-init injector when reloading
@@ -235,7 +249,12 @@ public void onGeyserShutdown() {
235249
}
236250

237251
@Override
238-
public void onDisable() {
252+
public void disable() {
253+
this.onGeyserDisable();
254+
}
255+
256+
@Override
257+
public void shutdown() {
239258
this.onGeyserShutdown();
240259
}
241260

@@ -266,22 +285,22 @@ public IGeyserPingPassthrough getGeyserPingPassthrough() {
266285

267286
@Override
268287
public Path getConfigFolder() {
269-
return getDataFolder().toPath();
288+
return plugin.getDataFolder().toPath();
270289
}
271290

272291
@Override
273292
public BootstrapDumpInfo getDumpInfo() {
274-
return new GeyserBungeeDumpInfo(getProxy());
293+
return new GeyserBungeeDumpInfo(proxyServer);
275294
}
276295

277296
@Override
278297
public Path getLogsPath() {
279-
return Paths.get(getProxy().getName().equals("BungeeCord") ? "proxy.log.0" : "logs/latest.log");
298+
return Paths.get(proxyServer.getName().equals("BungeeCord") ? "proxy.log.0" : "logs/latest.log");
280299
}
281300

282301
@Override
283302
public @NonNull String getServerPlatform() {
284-
return getProxy().getName();
303+
return proxyServer.getName();
285304
}
286305

287306
@Nullable
@@ -303,13 +322,13 @@ public int getServerPort() {
303322

304323
@Override
305324
public boolean testFloodgatePluginPresent() {
306-
return getProxy().getPluginManager().getPlugin("floodgate") != null;
325+
return proxyServer.getPluginManager().getPlugin("floodgate") != null;
307326
}
308327

309328
@Override
310329
public Path getFloodgateKeyPath() {
311-
Plugin floodgate = getProxy().getPluginManager().getPlugin("floodgate");
312-
Path geyserDataFolder = getDataFolder().toPath();
330+
Plugin floodgate = proxyServer.getPluginManager().getPlugin("floodgate");
331+
Path geyserDataFolder = plugin.getDataFolder().toPath();
313332
Path floodgateDataFolder = floodgate != null ? floodgate.getDataFolder().toPath() : null;
314333

315334
return FloodgateKeyLoader.getKeyPath(geyserConfig, floodgateDataFolder, geyserDataFolder, geyserLogger);
@@ -318,7 +337,7 @@ public Path getFloodgateKeyPath() {
318337
@Override
319338
public MetricsPlatform createMetricsPlatform() {
320339
try {
321-
return new BungeeMetrics(this);
340+
return new BungeeMetrics(plugin);
322341
} catch (IOException e) {
323342
this.geyserLogger.debug("Integrated bStats support failed to load.");
324343
if (this.config().debugMode()) {
@@ -329,7 +348,7 @@ public MetricsPlatform createMetricsPlatform() {
329348
}
330349

331350
private Optional<InetSocketAddress> findCompatibleListener() {
332-
var listeners = getProxy().getConfig().getListeners();
351+
var listeners = proxyServer.getConfig().getListeners();
333352
if (listeners.size() == 1) {
334353
return listeners.stream()
335354
.filter(info -> info.getSocketAddress() instanceof InetSocketAddress)
Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,25 @@
11
plugins {
22
id("geyser.isolated-platform-conventions")
3+
id("geyser.modrinth-uploading-conventions")
34
}
45

5-
application {
6-
mainClass = "org.geysermc.geyser.platform.bungeecord.BungeeMain"
6+
dependencies {
7+
compileOnlyApi(libs.bungeecord.proxy)
8+
compileOnlyApi(libs.bungeecord.api)
79
}
810

911
tasks {
1012
jar {
13+
manifest.attributes["Main-Class"] = "org.geysermc.geyser.platform.bungeecord.BungeeMain"
14+
}
15+
16+
shadowJar {
1117
archiveBaseName.set("Geyser-BungeeCord")
1218
}
1319
}
20+
21+
modrinth {
22+
uploadFile.set(tasks.getByPath("shadowJar"))
23+
loaders.add("bungeecord")
24+
}
25+

bootstrap/bungeecord/base/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeeMain.java renamed to bootstrap/bungeecord/isolated/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeeMain.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
2+
* Copyright (c) 2019-2026 GeyserMC. http://geysermc.org
33
*
44
* Permission is hereby granted, free of charge, to any person obtaining a copy
55
* of this software and associated documentation files (the "Software"), to deal
@@ -29,7 +29,7 @@
2929

3030
public class GeyserBungeeMain extends GeyserMain {
3131

32-
public static void main(String[] args) {
32+
static void main() {
3333
new GeyserBungeeMain().displayMessage();
3434
}
3535

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/*
2+
* Copyright (c) 2026 GeyserMC. http://geysermc.org
3+
*
4+
* Permission is hereby granted, free of charge, to any person obtaining a copy
5+
* of this software and associated documentation files (the "Software"), to deal
6+
* in the Software without restriction, including without limitation the rights
7+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8+
* copies of the Software, and to permit persons to whom the Software is
9+
* furnished to do so, subject to the following conditions:
10+
*
11+
* The above copyright notice and this permission notice shall be included in
12+
* all copies or substantial portions of the Software.
13+
*
14+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20+
* THE SOFTWARE.
21+
*
22+
* @author GeyserMC
23+
* @link https://github.com/GeyserMC/Geyser
24+
*/
25+
26+
package org.geysermc.geyser.platform.bungeecord;
27+
28+
import net.md_5.bungee.api.plugin.Plugin;
29+
import org.geysermc.floodgate.isolation.loader.PlatformHolder;
30+
import org.geysermc.floodgate.isolation.loader.PlatformLoader;
31+
32+
import java.nio.file.Path;
33+
import java.util.List;
34+
35+
public final class IsolatedBungeePlugin extends Plugin {
36+
private final PlatformHolder holder;
37+
38+
public IsolatedBungeePlugin() {
39+
super();
40+
41+
try {
42+
Path libsDirectory = getDataFolder().toPath().resolve("libs");
43+
holder = PlatformLoader.loadDefault(getClass().getClassLoader(), libsDirectory);
44+
// Must match the arguments of the GeyserBungeePlatform constructor exactly
45+
holder.init(List.of(Plugin.class), List.of(this));
46+
} catch (Exception exception) {
47+
throw new RuntimeException("Failed to load Geyser", exception);
48+
}
49+
}
50+
51+
@Override
52+
public void onLoad() {
53+
holder.load();
54+
}
55+
56+
@Override
57+
public void onEnable() {
58+
holder.enable();
59+
}
60+
61+
@Override
62+
public void onDisable() {
63+
holder.shutdown();
64+
}
65+
}
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
main: org.geysermc.geyser.platform.bungeecord.GeyserBungeePlugin
1+
main: org.geysermc.geyser.platform.bungeecord.IsolatedBungeePlugin
22
name: ${name}-BungeeCord
33
author: ${author}
44
website: ${url}
5-
version: ${version}
5+
version: ${version}

0 commit comments

Comments
 (0)