Skip to content

Commit 765128c

Browse files
CamotoyKonicaionebeastchriseclipseisofflineNovampr
authored
Switch config system to Configurate (#5010)
* Start implementing Configurate config system * More development * Start migrating to Gson only * Progress * Update usage of WebUtils * Most things now use Gson for JSON * Allow tests to succeed by using new Gson version * Use slightly cleaner version for Version deserializer * Work around older Gson versions without record support * GeyserCustomSkullConfiguration uses Configurate * Fix regression in properties get * New config used in core * The configuration is gone. Long live the config. * More changes and migrations away from Jackson * Improve node ordering when updating configs * typo * Better check for ignoring non-configurate configs for considering comment moving * Ensure metrics UUID is valid * Initial advanced config * Remove Jackson; finish config value placements * Remove duplicate relocate declarations * Let annotations work * Renaming to PluginSpecific * Use global bStats config where possible * Fix test * Re-introduce asterisk behavior in configs * Remove GeyserPluginBootstrap as it's no longer necessary * Remove old config.yml file * Update Xbox achievement comment * Apply suggestions from code review Co-authored-by: chris <github@onechris.mozmail.com> * No need to remove values anymore * Fix: disable bstats relocation on platforms where it is not needed * ensure it builds * Update custom unavailable slot comment Co-authored-by: chris <github@onechris.mozmail.com> * Update cooldown image * Logger message for direct-compression still being enabled * oops * More explicit RuntimeException message Co-authored-by: Konicai <71294714+Konicai@users.noreply.github.com> * Constant for 'system' locale * Better config JSON encoding (something is broken with Cloudflare; we'll figure it out * Fix broadcast port default * Add this file too * Update configurate branch * fix build * Fix: Allow using custom config file on Standalone, add relocation comment * Move config loading to GeyserBootstrap interface * Add and rename some config options, add section notes (#5390) * Add and rename some config options, add section notes * adjust message * Update core/src/main/java/org/geysermc/geyser/command/defaults/ConnectionTestCommand.java Co-authored-by: Eclipse <eclipse@eclipseisoffline.xyz> * Update core/src/main/java/org/geysermc/geyser/configuration/GeyserConfig.java Co-authored-by: Eclipse <eclipse@eclipseisoffline.xyz> * Update ConfigLoader.java * Update AdvancedConfig.java * clarify that we're talking about the HAProxy protocol * rename config option to use-haproxy-protocol * remove ominous warning sign on xbox auth warning * adjust wording --------- Co-authored-by: Eclipse <eclipse@eclipseisoffline.xyz> * Back to one config file * Some minor touchups * Configurate: Sectionification (#5904) * Init: config sections * Start on adding tests, move migrations over to ConfigMigrations class * Get rid of auth section again, rename that one config option, fix mtu migration * Move custom skulls config options to the bottom of the gameplay settings * Add more tests * Rename and migrate proxy-protocol-whitelisted-ips to haproxy-protocol-whitelisted-ips * Add automatic downloading of the GeyserOptionalPack * Revert "Add automatic downloading of the GeyserOptionalPack" This reverts commit 65b9620. * Add more invalid config tests * Warn about emote-offhand-workaround removal * Add automatic loading of the GeyserOptionalPack (feature/configurate) (#5964) * Add automatic downloading of the GeyserOptionalPack * Warn about including the OptionalPack from extensions when Geyser is already including it instead of throwing. * Copy optional pack instead of downloading --------- Co-authored-by: onebeastchris <github@onechris.mozmail.com> * Remove unused variable * Start warning users not running Java 21 * Update tests, temporarily remove NumericRanges test * Remove duplicate advanced section from Geyser dump * Address some "reviews" * yeet md5 hash from geyser dump * Add info about number of resource packs / amount of mappings into Geyser dump * Re-enable invalid config loading test * Fix: allow-custom-skulls migration * Fix test * Add "enable-emotes" configuration option * Rename "emotes-enabled" to "show-emotes" * Only enable integrated pack when optional pack isn't present * Update integrated pack * Exclude jackson annotations, remove leftover debug print * Remove one-time config migration warnings as we don't have access to the logger at that stage * Throw more detailed descriptive error when loading resource packs from the "packs" folder, add another legacy config test * Fix NeoForge's fun module conflict * Re-add warning about moved functionality, fix Geyser-ViaProxy This reverts commit fbadfa5. * oops * Move GeyserLegacyPingPassthrough to separate thread to avoid Standalone command locking issues --------- Co-authored-by: Konicai <71294714+Konicai@users.noreply.github.com> Co-authored-by: chris <github@onechris.mozmail.com> Co-authored-by: Eclipse <eclipse@eclipseisoffline.xyz> Co-authored-by: Aurora <auroranova8756@gmail.com>
1 parent 48bf094 commit 765128c

File tree

157 files changed

+8007
-2671
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

157 files changed

+8007
-2671
lines changed

bootstrap/bungeecord/build.gradle.kts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,12 @@ dependencies {
1515
}
1616

1717
platformRelocate("net.md_5.bungee.jni")
18-
platformRelocate("com.fasterxml.jackson")
1918
platformRelocate("net.kyori")
2019
platformRelocate("org.incendo")
21-
platformRelocate("io.leangen.geantyref") // provided by cloud, should also be relocated
20+
platformRelocate("io.leangen.geantyref") // provided by cloud and Configurate, should also be relocated
2221
platformRelocate("org.yaml") // Broken as of 1.20
22+
platformRelocate("org.spongepowered")
23+
platformRelocate("org.bstats")
2324

2425
// These dependencies are already present on the platform
2526
provided(libs.bungeecord.proxy)
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
/*
2+
* Copyright (c) 2024 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 net.md_5.bungee.config.Configuration;
30+
import net.md_5.bungee.config.ConfigurationProvider;
31+
import net.md_5.bungee.config.YamlConfiguration;
32+
import org.geysermc.geyser.util.metrics.MetricsPlatform;
33+
34+
import java.io.BufferedWriter;
35+
import java.io.File;
36+
import java.io.FileWriter;
37+
import java.io.IOException;
38+
import java.util.UUID;
39+
40+
public final class BungeeMetrics implements MetricsPlatform {
41+
private final Configuration configuration;
42+
43+
public BungeeMetrics(Plugin plugin) throws IOException {
44+
// https://github.com/Bastian/bstats-metrics/blob/master/bungeecord/src/main/java/org/bstats/bungeecord/Metrics.java
45+
File bStatsFolder = new File(plugin.getDataFolder().getParentFile(), "bStats");
46+
//noinspection ResultOfMethodCallIgnored
47+
bStatsFolder.mkdirs();
48+
File configFile = new File(bStatsFolder, "config.yml");
49+
if (!configFile.exists()) {
50+
writeFile(configFile,
51+
"# bStats (https://bStats.org) collects some basic information for plugin authors, like how",
52+
"# many people use their plugin and their total player count. It's recommended to keep bStats",
53+
"# enabled, but if you're not comfortable with this, you can turn this setting off. There is no",
54+
"# performance penalty associated with having metrics enabled, and data sent to bStats is fully",
55+
"# anonymous.",
56+
"enabled: true",
57+
"serverUuid: \"" + UUID.randomUUID() + "\"",
58+
"logFailedRequests: false",
59+
"logSentData: false",
60+
"logResponseStatusText: false");
61+
}
62+
63+
this.configuration = ConfigurationProvider.getProvider(YamlConfiguration.class).load(configFile);
64+
}
65+
66+
@Override
67+
public boolean enabled() {
68+
return configuration.getBoolean("enabled", true);
69+
}
70+
71+
@Override
72+
public String serverUuid() {
73+
return configuration.getString("serverUuid");
74+
}
75+
76+
@Override
77+
public boolean logFailedRequests() {
78+
return configuration.getBoolean("logFailedRequests", false);
79+
}
80+
81+
@Override
82+
public boolean logSentData() {
83+
return configuration.getBoolean("logSentData", false);
84+
}
85+
86+
@Override
87+
public boolean logResponseStatusText() {
88+
return configuration.getBoolean("logResponseStatusText", false);
89+
}
90+
91+
private void writeFile(File file, String... lines) throws IOException {
92+
try (BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(file))) {
93+
for (String line : lines) {
94+
bufferedWriter.write(line);
95+
bufferedWriter.newLine();
96+
}
97+
}
98+
}
99+
}

bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeeInjector.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ protected IoEventLoop newChild(Executor executor, IoHandlerFactory ioHandlerFact
157157
listenerInfo.isPingPassthrough(),
158158
listenerInfo.getQueryPort(),
159159
listenerInfo.isQueryEnabled(),
160-
bootstrap.getGeyserConfig().getRemote().isUseProxyProtocol() // If Geyser is expecting HAProxy, so should the Bungee end
160+
bootstrap.config().advanced().java().useHaproxyProtocol() // If Geyser is expecting HAProxy, so should the Bungee end
161161
);
162162

163163
// The field that stores all listeners in BungeeCord
@@ -191,7 +191,7 @@ protected void initChannel(@NonNull Channel ch) throws Exception {
191191
}
192192
initChannel.invoke(channelInitializer, ch);
193193

194-
if (bootstrap.getGeyserConfig().isDisableCompression()) {
194+
if (bootstrap.config().advanced().java().disableCompression()) {
195195
ch.pipeline().addAfter(PipelineUtils.PACKET_ENCODER, "geyser-compression-disabler",
196196
new GeyserBungeeCompressionDisabler());
197197
}

bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeePingPassthrough.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ public GeyserPingInfo getPingInformation(InetSocketAddress inetSocketAddress) {
6969
try {
7070
event = future.get(100, TimeUnit.MILLISECONDS);
7171
} catch (Throwable cause) {
72-
String address = GeyserImpl.getInstance().getConfig().isLogPlayerIpAddresses() ? inetSocketAddress.toString() : "<IP address withheld>";
72+
String address = GeyserImpl.getInstance().config().logPlayerIpAddresses() ? inetSocketAddress.toString() : "<IP address withheld>";
7373
GeyserImpl.getInstance().getLogger().error("Failed to get ping information for " + address, cause);
7474
return null;
7575
}

bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeePlugin.java

Lines changed: 40 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -33,25 +33,25 @@
3333
import net.md_5.bungee.protocol.ProtocolConstants;
3434
import org.checkerframework.checker.nullness.qual.NonNull;
3535
import org.checkerframework.checker.nullness.qual.Nullable;
36+
import org.geysermc.geyser.FloodgateKeyLoader;
3637
import org.geysermc.geyser.GeyserBootstrap;
3738
import org.geysermc.geyser.GeyserImpl;
3839
import org.geysermc.geyser.api.util.PlatformType;
3940
import org.geysermc.geyser.command.CommandRegistry;
4041
import org.geysermc.geyser.command.CommandSourceConverter;
4142
import org.geysermc.geyser.command.GeyserCommandSource;
42-
import org.geysermc.geyser.configuration.GeyserConfiguration;
43+
import org.geysermc.geyser.configuration.GeyserPluginConfig;
4344
import org.geysermc.geyser.dump.BootstrapDumpInfo;
4445
import org.geysermc.geyser.network.GameProtocol;
4546
import org.geysermc.geyser.ping.GeyserLegacyPingPassthrough;
4647
import org.geysermc.geyser.ping.IGeyserPingPassthrough;
4748
import org.geysermc.geyser.platform.bungeecord.command.BungeeCommandSource;
4849
import org.geysermc.geyser.text.GeyserLocale;
49-
import org.geysermc.geyser.util.FileUtils;
50+
import org.geysermc.geyser.util.metrics.MetricsPlatform;
5051
import org.incendo.cloud.CommandManager;
5152
import org.incendo.cloud.bungee.BungeeCommandManager;
5253
import org.incendo.cloud.execution.ExecutionCoordinator;
5354

54-
import java.io.File;
5555
import java.io.IOException;
5656
import java.lang.reflect.Field;
5757
import java.net.InetSocketAddress;
@@ -61,13 +61,12 @@
6161
import java.util.Collection;
6262
import java.util.List;
6363
import java.util.Optional;
64-
import java.util.UUID;
6564
import java.util.concurrent.TimeUnit;
6665

6766
public class GeyserBungeePlugin extends Plugin implements GeyserBootstrap {
6867

6968
private CommandRegistry commandRegistry;
70-
private GeyserBungeeConfiguration geyserConfig;
69+
private GeyserPluginConfig geyserConfig;
7170
private GeyserBungeeInjector geyserInjector;
7271
private final GeyserBungeeLogger geyserLogger = new GeyserBungeeLogger(getLogger());
7372
private IGeyserPingPassthrough geyserBungeePingPassthrough;
@@ -102,12 +101,11 @@ public void onGeyserInitialize() {
102101
System.setProperty("Mcpl.io_uring", "true");
103102
}
104103

105-
if (!this.loadConfig()) {
104+
geyserConfig = loadConfig(GeyserPluginConfig.class);
105+
if (geyserConfig == null) {
106106
return;
107107
}
108-
this.geyserLogger.setDebug(geyserConfig.isDebugMode());
109-
GeyserConfiguration.checkGeyserConfiguration(geyserConfig, geyserLogger);
110-
this.geyser = GeyserImpl.load(PlatformType.BUNGEECORD, this);
108+
this.geyser = GeyserImpl.load(this);
111109
this.geyserInjector = new GeyserBungeeInjector(this);
112110

113111
// Registration of listeners occurs only once
@@ -168,16 +166,15 @@ private void awaitStartupCompletion(int tries) {
168166

169167
public void onGeyserEnable() {
170168
if (GeyserImpl.getInstance().isReloading()) {
171-
if (!loadConfig()) {
169+
geyserConfig = loadConfig(GeyserPluginConfig.class);
170+
if (geyserConfig == null) {
172171
return;
173172
}
174-
this.geyserLogger.setDebug(geyserConfig.isDebugMode());
175-
GeyserConfiguration.checkGeyserConfiguration(geyserConfig, geyserLogger);
176173
}
177174

178175
// Force-disable query if enabled, or else Geyser won't enable
179176
for (ListenerInfo info : getProxy().getConfig().getListeners()) {
180-
if (info.isQueryEnabled() && info.getQueryPort() == geyserConfig.getBedrock().port()) {
177+
if (info.isQueryEnabled() && info.getQueryPort() == geyserConfig.bedrock().port()) {
181178
try {
182179
Field queryField = ListenerInfo.class.getDeclaredField("queryEnabled");
183180
queryField.setAccessible(true);
@@ -195,7 +192,7 @@ public void onGeyserEnable() {
195192

196193
GeyserImpl.start();
197194

198-
if (geyserConfig.isLegacyPingPassthrough()) {
195+
if (!geyserConfig.motd().integratedPingPassthrough()) {
199196
this.geyserBungeePingPassthrough = GeyserLegacyPingPassthrough.init(geyser);
200197
} else {
201198
this.geyserBungeePingPassthrough = new GeyserBungeePingPassthrough(getProxy());
@@ -232,8 +229,13 @@ public void onDisable() {
232229
}
233230

234231
@Override
235-
public GeyserBungeeConfiguration getGeyserConfig() {
236-
return geyserConfig;
232+
public @NonNull PlatformType platformType() {
233+
return PlatformType.BUNGEECORD;
234+
}
235+
236+
@Override
237+
public GeyserPluginConfig config() {
238+
return this.geyserConfig;
237239
}
238240

239241
@Override
@@ -290,11 +292,29 @@ public int getServerPort() {
290292

291293
@Override
292294
public boolean testFloodgatePluginPresent() {
293-
if (getProxy().getPluginManager().getPlugin("floodgate") != null) {
294-
geyserConfig.loadFloodgate(this);
295-
return true;
295+
return getProxy().getPluginManager().getPlugin("floodgate") != null;
296+
}
297+
298+
@Override
299+
public Path getFloodgateKeyPath() {
300+
Plugin floodgate = getProxy().getPluginManager().getPlugin("floodgate");
301+
Path geyserDataFolder = getDataFolder().toPath();
302+
Path floodgateDataFolder = floodgate != null ? floodgate.getDataFolder().toPath() : null;
303+
304+
return FloodgateKeyLoader.getKeyPath(geyserConfig, floodgateDataFolder, geyserDataFolder, geyserLogger);
305+
}
306+
307+
@Override
308+
public MetricsPlatform createMetricsPlatform() {
309+
try {
310+
return new BungeeMetrics(this);
311+
} catch (IOException e) {
312+
this.geyserLogger.debug("Integrated bStats support failed to load.");
313+
if (this.config().debugMode()) {
314+
e.printStackTrace();
315+
}
316+
return null;
296317
}
297-
return false;
298318
}
299319

300320
private Optional<InetSocketAddress> findCompatibleListener() {
@@ -303,20 +323,4 @@ private Optional<InetSocketAddress> findCompatibleListener() {
303323
.map(info -> (InetSocketAddress) info.getSocketAddress())
304324
.findFirst();
305325
}
306-
307-
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
308-
private boolean loadConfig() {
309-
try {
310-
if (!getDataFolder().exists()) //noinspection ResultOfMethodCallIgnored
311-
getDataFolder().mkdir();
312-
File configFile = FileUtils.fileOrCopiedFromResource(new File(getDataFolder(), "config.yml"),
313-
"config.yml", (x) -> x.replaceAll("generateduuid", UUID.randomUUID().toString()), this);
314-
this.geyserConfig = FileUtils.loadConfig(configFile, GeyserBungeeConfiguration.class);
315-
} catch (IOException ex) {
316-
geyserLogger.error(GeyserLocale.getLocaleStringLog("geyser.config.failed"), ex);
317-
ex.printStackTrace();
318-
return false;
319-
}
320-
return true;
321-
}
322326
}

bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeeUpdateListener.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ public final class GeyserBungeeUpdateListener implements Listener {
3838

3939
@EventHandler
4040
public void onPlayerJoin(final PostLoginEvent event) {
41-
if (GeyserImpl.getInstance().getConfig().isNotifyOnNewBedrockUpdate()) {
41+
if (GeyserImpl.getInstance().config().notifyOnNewBedrockUpdate()) {
4242
final ProxiedPlayer player = event.getPlayer();
4343
if (player.hasPermission(Permissions.CHECK_UPDATE)) {
4444
VersionCheckUtils.checkForGeyserUpdate(() -> new BungeeCommandSource(player));

bootstrap/mod/fabric/build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ dependencies {
1717
shadowBundle(projects.core)
1818
includeTransitive(projects.core)
1919

20-
// These are NOT transitively included, and instead shadowed + relocated.
20+
// These are NOT transitively included, and instead shadowed (+ relocated, if not under the org.geyser namespace).
2121
// Avoids fabric complaining about non-SemVer versioning
2222
shadowBundle(libs.protocol.connection)
2323
shadowBundle(libs.protocol.common)

bootstrap/mod/fabric/src/main/java/org/geysermc/geyser/platform/fabric/GeyserFabricDumpInfo.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525

2626
package org.geysermc.geyser.platform.fabric;
2727

28+
import com.google.gson.annotations.JsonAdapter;
2829
import lombok.AllArgsConstructor;
2930
import lombok.Getter;
3031
import net.fabricmc.api.EnvType;
@@ -48,7 +49,7 @@ public class GeyserFabricDumpInfo extends BootstrapDumpInfo {
4849
private final String minecraftVersion;
4950
private final EnvType environmentType;
5051

51-
@AsteriskSerializer.Asterisk(isIp = true)
52+
@JsonAdapter(value = AsteriskSerializer.class)
5253
private final String serverIP;
5354
private final int serverPort;
5455
private final boolean onlineMode;

bootstrap/mod/fabric/src/main/java/org/geysermc/geyser/platform/fabric/GeyserFabricPlatform.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ public boolean testFloodgatePluginPresent(@NonNull GeyserModBootstrap bootstrap)
7373
Optional<ModContainer> floodgate = FabricLoader.getInstance().getModContainer("floodgate");
7474
if (floodgate.isPresent()) {
7575
Path floodgateDataFolder = FabricLoader.getInstance().getConfigDir().resolve("floodgate");
76-
bootstrap.getGeyserConfig().loadFloodgate(bootstrap, floodgateDataFolder);
76+
bootstrap.loadFloodgate(floodgateDataFolder);
7777
return true;
7878
}
7979

bootstrap/mod/neoforge/build.gradle.kts

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,6 @@ architectury {
1313
provided("org.cloudburstmc.math", "api")
1414
provided("com.google.errorprone", "error_prone_annotations")
1515

16-
// Jackson shipped by Minecraft is too old, so we shade & relocate our newer version
17-
relocate("com.fasterxml.jackson")
18-
1916
dependencies {
2017
// See https://github.com/google/guava/issues/6618
2118
modules {
@@ -30,15 +27,12 @@ dependencies {
3027
shadowBundle(project(path = ":mod", configuration = "transformProductionNeoForge"))
3128
shadowBundle(projects.core)
3229

33-
// Minecraft (1.21.2+) includes jackson. But an old version!
34-
shadowBundle(libs.jackson.core)
35-
shadowBundle(libs.jackson.databind)
36-
shadowBundle(libs.jackson.dataformat.yaml)
37-
shadowBundle(libs.jackson.annotations)
38-
3930
// Let's shade in our own api
4031
shadowBundle(projects.api)
4132

33+
// this one is particularly dumb
34+
shadowBundle(libs.configurate.`interface`)
35+
4236
// cannot be shaded, since neoforge will complain if floodgate-neoforge tries to provide this
4337
include(projects.common)
4438

@@ -61,11 +55,6 @@ tasks {
6155
remapModrinthJar {
6256
archiveBaseName.set("geyser-neoforge")
6357
}
64-
65-
shadowJar {
66-
// Without this, jackson's service files are not relocated
67-
mergeServiceFiles()
68-
}
6958
}
7059

7160
modrinth {

0 commit comments

Comments
 (0)