Skip to content

Commit 7017e42

Browse files
authored
adventure-platform-mod 6.x (#68)
* Support adventure-platform-mod 6.x, drop 5.x support for signed string parser It will always return unsigned string with 5.x. * Implement ComponentMessageThrowable conversions and fix registry aware signed string conversions * fix fabric error with 5.x and add neoforge metadata * Bump adventure-api * compile with adventure common * read server once * Remove unnecessary priority * gitignore new kotlin files
1 parent 1cbc6a7 commit 7017e42

15 files changed

Lines changed: 310 additions & 19 deletions

File tree

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,5 @@ build
77
.idea/
88

99
run/
10+
11+
.kotlin/

cloud-fabric/build.gradle.kts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ dependencies {
3838
api(libs.cloud.brigadier)
3939

4040
compileOnly(libs.cloud.minecraft.signed.arguments)
41-
modCompileOnly(libs.adventureFabric)
4241

4342
offlineLinkedJavadoc(project(":cloud-minecraft-modded-common"))
4443
localRuntime(project(":cloud-minecraft-modded-common"))
@@ -92,9 +91,16 @@ val testmod: SourceSet by sourceSets.creating {
9291
dependencies.add(implementationConfigurationName, main.output)
9392
}
9493

94+
loom {
95+
createRemapConfigurations(testmod)
96+
}
97+
9598
dependencies {
9699
localRuntime(libs.cloud.minecraft.signed.arguments)
97100
modLocalRuntime(libs.adventureFabric)
101+
"modTestmodImplementation"(libs.adventureFabric)
102+
"testmodImplementation"(libs.cloud.minecraft.extras)
103+
localRuntime(libs.cloud.minecraft.extras)
98104
}
99105

100106
val testmodJar by tasks.registering(Jar::class) {
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
//
2+
// MIT License
3+
//
4+
// Copyright (c) 2024 Incendo
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+
package org.incendo.cloud.fabric.internal;
25+
26+
import java.util.Objects;
27+
import net.fabricmc.api.EnvType;
28+
import net.fabricmc.api.ModInitializer;
29+
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
30+
import net.fabricmc.loader.api.FabricLoader;
31+
import org.apiguardian.api.API;
32+
import org.checkerframework.checker.nullness.qual.NonNull;
33+
import org.checkerframework.framework.qual.DefaultQualifier;
34+
import org.incendo.cloud.minecraft.modded.internal.AdventureSupport;
35+
36+
@API(status = API.Status.INTERNAL)
37+
@DefaultQualifier(NonNull.class)
38+
public final class CloudFabricEntrypoint implements ModInitializer {
39+
40+
@SuppressWarnings("EmptyCatch")
41+
@Override
42+
public void onInitialize() {
43+
if (FabricLoader.getInstance().isModLoaded("adventure-platform-fabric")) {
44+
try {
45+
Objects.requireNonNull(
46+
Class.forName("net.kyori.adventure.platform.modcommon.MinecraftAudiences").getName()
47+
);
48+
49+
ServerLifecycleEvents.SERVER_STARTING.register(AdventureSupport.get()::setupServer);
50+
ServerLifecycleEvents.SERVER_STOPPED.register(AdventureSupport.get()::removeServer);
51+
if (FabricLoader.getInstance().getEnvironmentType() == EnvType.CLIENT) {
52+
AdventureSupport.get().setupClient();
53+
}
54+
} catch (final ClassNotFoundException ignored) {
55+
}
56+
}
57+
}
58+
}

cloud-fabric/src/main/resources/META-INF/services/org.incendo.cloud.minecraft.modded.internal.ModdedSignedStringMapper$SignedStringFactory

Lines changed: 0 additions & 1 deletion
This file was deleted.

cloud-fabric/src/main/resources/fabric.mod.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@
1515

1616
"entrypoints": {
1717
"main": [
18-
"org.incendo.cloud.fabric.internal.LateRegistrationCatcher"
18+
"org.incendo.cloud.fabric.internal.LateRegistrationCatcher",
19+
"org.incendo.cloud.fabric.internal.CloudFabricEntrypoint"
1920
]
2021
},
2122

cloud-fabric/src/testmod/java/org/incendo/cloud/fabric/testmod/FabricExample.java

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,16 +27,18 @@
2727
import java.util.Collection;
2828
import java.util.Comparator;
2929
import java.util.List;
30+
import java.util.concurrent.atomic.AtomicReference;
3031
import java.util.stream.Collectors;
3132
import net.fabricmc.api.ModInitializer;
33+
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
3234
import net.fabricmc.loader.api.FabricLoader;
3335
import net.fabricmc.loader.api.ModContainer;
3436
import net.fabricmc.loader.api.metadata.ModMetadata;
3537
import net.fabricmc.loader.api.metadata.Person;
3638
import net.kyori.adventure.chat.ChatType;
3739
import net.kyori.adventure.identity.Identity;
38-
import net.kyori.adventure.platform.fabric.AdventureCommandSourceStack;
39-
import net.kyori.adventure.platform.fabric.FabricServerAudiences;
40+
import net.kyori.adventure.platform.modcommon.AdventureCommandSourceStack;
41+
import net.kyori.adventure.platform.modcommon.MinecraftServerAudiences;
4042
import net.kyori.adventure.text.minimessage.MiniMessage;
4143
import net.minecraft.ChatFormatting;
4244
import net.minecraft.commands.CommandSourceStack;
@@ -61,9 +63,9 @@
6163
import org.incendo.cloud.fabric.FabricServerCommandManager;
6264
import org.incendo.cloud.fabric.testmod.mixin.GiveCommandAccess;
6365
import org.incendo.cloud.key.CloudKey;
66+
import org.incendo.cloud.minecraft.extras.MinecraftExceptionHandler;
6467
import org.incendo.cloud.minecraft.modded.data.Coordinates;
6568
import org.incendo.cloud.minecraft.modded.data.Coordinates.ColumnCoordinates;
66-
import org.incendo.cloud.minecraft.modded.data.MultipleEntitySelector;
6769
import org.incendo.cloud.minecraft.modded.data.MultiplePlayerSelector;
6870
import org.incendo.cloud.minecraft.modded.parser.NamedColorParser;
6971
import org.incendo.cloud.minecraft.modded.parser.RegistryEntryParser;
@@ -89,6 +91,11 @@ public void onInitialize() {
8991
final FabricServerCommandManager<CommandSourceStack> manager =
9092
FabricServerCommandManager.createNative(ExecutionCoordinator.simpleCoordinator());
9193

94+
AtomicReference<MinecraftServerAudiences> audiences = new AtomicReference<>();
95+
ServerLifecycleEvents.SERVER_STARTING.register((server) -> audiences.set(MinecraftServerAudiences.of(server)));
96+
MinecraftExceptionHandler.<CommandSourceStack>create(stack -> audiences.get().audience(stack))
97+
.registerTo(manager);
98+
9299
final Command.Builder<CommandSourceStack> base = manager.commandBuilder("cloudtest");
93100

94101
final CloudKey<String> name = CloudKey.of("name", String.class);
@@ -224,15 +231,16 @@ public void onInitialize() {
224231
.map(Suggestion::suggestion)
225232
.collect(Collectors.toList())))
226233
.parser((commandContext, commandInput) -> {
227-
final ModMetadata meta = FabricLoader.getInstance().getModContainer(commandInput.readString())
234+
final String s = commandInput.readString();
235+
final ModMetadata meta = FabricLoader.getInstance().getModContainer(s)
228236
.map(ModContainer::getMetadata)
229237
.orElse(null);
230238
if (meta != null) {
231239
return ArgumentParseResult.success(meta);
232240
}
233241
return ArgumentParseResult.failure(new IllegalArgumentException(String.format(
234242
"No mod with id '%s'",
235-
commandInput.peek()
243+
s
236244
)));
237245
})
238246
.build();
@@ -269,7 +277,7 @@ public void onInitialize() {
269277
.required("targets", multiplePlayerSelectorParser())
270278
.required("location", vec3Parser(false))
271279
.handler(ctx -> {
272-
final MultipleEntitySelector selector = ctx.get("targets");
280+
final MultiplePlayerSelector selector = ctx.get("targets");
273281
final Vec3 location = ctx.<Coordinates>get("location").position();
274282
selector.values().forEach(target -> {
275283
target.placePortalTicket(new BlockPos(Mth.floor(location.x()), Mth.floor(location.y()), Mth.floor(location.z())));
@@ -281,7 +289,7 @@ public void onInitialize() {
281289
.required("message", signedGreedyStringParser())
282290
.handler(ctx -> {
283291
final AdventureCommandSourceStack audience =
284-
FabricServerAudiences.of(ctx.sender().getServer()).audience(ctx.sender());
292+
MinecraftServerAudiences.of(ctx.sender().getServer()).audience(ctx.sender());
285293

286294
final SignedString message = ctx.get("message");
287295

cloud-minecraft-modded-common/build.gradle.kts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,12 @@ neoForge {
1313
}
1414
}
1515

16+
dependencies {
17+
compileOnly(libs.adventureMod)
18+
19+
compileOnly(libs.cloud.minecraft.extras)
20+
}
21+
1622
tasks.withType(AbstractRemapJarTask::class).configureEach {
1723
targetNamespace = "named"
1824
}
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
//
2+
// MIT License
3+
//
4+
// Copyright (c) 2024 Incendo
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+
package org.incendo.cloud.minecraft.modded.internal;
25+
26+
import java.util.Objects;
27+
import net.kyori.adventure.platform.modcommon.MinecraftAudiences;
28+
import net.kyori.adventure.platform.modcommon.MinecraftClientAudiences;
29+
import net.kyori.adventure.platform.modcommon.MinecraftServerAudiences;
30+
import net.minecraft.server.MinecraftServer;
31+
import org.apiguardian.api.API;
32+
import org.checkerframework.checker.nullness.qual.NonNull;
33+
import org.checkerframework.checker.nullness.qual.Nullable;
34+
import org.checkerframework.framework.qual.DefaultQualifier;
35+
36+
@API(status = API.Status.INTERNAL)
37+
@DefaultQualifier(NonNull.class)
38+
public final class AdventureSupport {
39+
private static final AdventureSupport INSTANCE;
40+
41+
static {
42+
INSTANCE = new AdventureSupport();
43+
INSTANCE.setupConverter();
44+
}
45+
46+
private @Nullable MinecraftAudiences client;
47+
private @Nullable MinecraftAudiences server;
48+
49+
private AdventureSupport() {
50+
}
51+
52+
@SuppressWarnings("EmptyCatch")
53+
private void setupConverter() {
54+
try {
55+
ComponentMessageThrowableConverter.setup(this);
56+
} catch (final LinkageError ignored) {
57+
// cloud-minecraft-extras not present
58+
}
59+
}
60+
61+
/**
62+
* Set up the client audience.
63+
*/
64+
public void setupClient() {
65+
this.client = MinecraftClientAudiences.of();
66+
}
67+
68+
/**
69+
* Set up the server audience.
70+
*
71+
* @param server server
72+
*/
73+
public void setupServer(final MinecraftServer server) {
74+
this.server = MinecraftServerAudiences.of(server);
75+
}
76+
77+
/**
78+
* Shutdown the server audience.
79+
*
80+
* @param server server
81+
*/
82+
@SuppressWarnings("unused")
83+
public void removeServer(final MinecraftServer server) {
84+
this.server = null;
85+
}
86+
87+
/**
88+
* Get the MinecraftAudiences instance.
89+
*
90+
* @return audiences
91+
*/
92+
public MinecraftAudiences audiences() {
93+
final @Nullable MinecraftAudiences server = this.server;
94+
if (server == null) {
95+
return Objects.requireNonNull(this.client, "No audiences present");
96+
}
97+
return server;
98+
}
99+
100+
/**
101+
* Returns the AdventureSupport instance.
102+
*
103+
* @return the instance
104+
*/
105+
public static AdventureSupport get() {
106+
return INSTANCE;
107+
}
108+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
//
2+
// MIT License
3+
//
4+
// Copyright (c) 2024 Incendo
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+
package org.incendo.cloud.minecraft.modded.internal;
25+
26+
import com.mojang.brigadier.exceptions.CommandSyntaxException;
27+
import org.apiguardian.api.API;
28+
import org.checkerframework.checker.nullness.qual.NonNull;
29+
import org.checkerframework.framework.qual.DefaultQualifier;
30+
import org.incendo.cloud.minecraft.extras.MinecraftExceptionHandler;
31+
32+
@API(status = API.Status.INTERNAL)
33+
@DefaultQualifier(NonNull.class)
34+
final class ComponentMessageThrowableConverter implements MinecraftExceptionHandler.ComponentMessageThrowableConverter {
35+
36+
private final AdventureSupport adventureSupport;
37+
38+
ComponentMessageThrowableConverter(final AdventureSupport adventureSupport) {
39+
this.adventureSupport = adventureSupport;
40+
}
41+
42+
static void setup(final AdventureSupport adventureSupport) {
43+
MinecraftExceptionHandler.ComponentMessageThrowableConverterHolder.converter(
44+
new ComponentMessageThrowableConverter(adventureSupport)
45+
);
46+
}
47+
48+
@Override
49+
public Throwable maybeConvert(final Throwable thr) {
50+
if (thr instanceof CommandSyntaxException cse) {
51+
return (Exception) this.adventureSupport.audiences().asComponentThrowable(cse);
52+
}
53+
return thr;
54+
}
55+
}

0 commit comments

Comments
 (0)