Skip to content

Commit

Permalink
Merge pull request #30 from KyoriPowered/feature/interface-injection
Browse files Browse the repository at this point in the history
  • Loading branch information
zml2008 committed May 19, 2022
2 parents 11cbcc6 + d9ccbe3 commit d5cd0b5
Show file tree
Hide file tree
Showing 33 changed files with 547 additions and 124 deletions.
6 changes: 4 additions & 2 deletions .github/workflows/build.yml
Expand Up @@ -29,11 +29,13 @@ jobs:
with:
distribution: "temurin"
java-version: "${{ env.RUNTIME_VERSION }}"
- name: "run gradle build"
- name: "prime gradle build"
uses: "gradle/gradle-build-action@v2"
with:
cache-read-only: "${{ !startsWith(github.ref, 'refs/heads/mc/') || github.event_name == 'pull_request' }}"
arguments: "build"
arguments: "generateTemplates generateTestmodTemplates --stacktrace" # Bonk loom
- name: "run gradle build"
run: "./gradlew build --stacktrace"
- name: "Archive test results"
if: "${{ always() }}"
uses: "actions/upload-artifact@v3"
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -7,6 +7,7 @@ run/

*.iml
*.ipr
.idea/

# Eclipse
/.settings/
Expand Down
2 changes: 2 additions & 0 deletions README.md
Expand Up @@ -23,6 +23,8 @@ We appreciate contributions of any type. For any new features or typo-fix/style

All the adventure projects are built with Gradle and use a common checkstyle configuration. `adventure-platform-fabric` requires the same Java version that Minecraft itself does in the target version. Please make sure all tests pass, license headers are updated, and checkstyle passes to help us review your contribution.

An unfortunate quirk with Loom is that it resolves dependencies in the configuration phase, before any task execution can happen, so we have to run Gradle twice to generate templates, then apply our in-project interface injections. Sorry!

`adventure-platform-fabric` is released under the terms of the [MIT License](LICENSE).

[Discord]: https://discord.gg/MMfhJ8F
79 changes: 65 additions & 14 deletions build.gradle.kts
@@ -1,6 +1,10 @@
import ca.stellardrift.build.configurate.ConfigFormats
import ca.stellardrift.build.configurate.transformations.convertFormat
import net.fabricmc.loom.task.GenerateSourcesTask
import net.fabricmc.loom.task.RemapJarTask
import net.fabricmc.loom.task.RunGameTask
import org.jetbrains.gradle.ext.settings
import org.jetbrains.gradle.ext.taskTriggers

plugins {
alias(libs.plugins.loom)
Expand All @@ -10,6 +14,7 @@ plugins {
alias(libs.plugins.indra.licenseHeader)
alias(libs.plugins.indra.checkstyle)
alias(libs.plugins.indra.sonatype)
alias(libs.plugins.ideaExt)
}

repositories {
Expand All @@ -31,7 +36,7 @@ quiltflower {
preferences(
"win" to 0
)
addToRuntimeClasspath.set(true)
// addToRuntimeClasspath.set(true)
}

indra {
Expand Down Expand Up @@ -93,10 +98,6 @@ dependencies {
checkstyle(libs.stylecheck)
}

// tasks.withType(net.fabricmc.loom.task.RunGameTask::class) {
// setClasspath(files(loom.unmappedModCollection, sourceSets.main.map { it.runtimeClasspath }))
// }

sourceSets {
main {
java.srcDirs(
Expand All @@ -108,12 +109,12 @@ sourceSets {
"src/mixin/resources/"
)
}
register("testmod") {
compileClasspath += main.get().compileClasspath
runtimeClasspath += main.get().runtimeClasspath
java.srcDirs("src/testmodMixin/java")
resources.srcDirs("src/testmodMixin/resources")
}
}
val testmod = sourceSets.register("testmod") {
compileClasspath += sourceSets.main.get().compileClasspath
runtimeClasspath += sourceSets.main.get().runtimeClasspath
java.srcDirs("src/testmodMixin/java")
resources.srcDirs("src/testmodMixin/resources")
}

dependencies {
Expand All @@ -131,14 +132,42 @@ loom {
server()
}
}
mixin {
add(sourceSets.main.get(), "adventure-platform-fabric-refmap.json")
add(testmod.get(), "adventure-platform-fabric-testmod-refmap.json")
}
}

// Create a remapped testmod jar
val testmodDevJar = tasks.register("testmodJar", Jar::class) {
from(testmod.map { it.output })
archiveClassifier.set("testmod-dev")
}

val remapTestmodJar = tasks.register("remapTestmodJar", RemapJarTask::class) {
inputFile.set(testmodDevJar.flatMap { it.archiveFile })
addNestedDependencies.set(false)
classpath.from(testmod.map { it.runtimeClasspath })
archiveClassifier.set("testmod")
}

tasks.build {
dependsOn(remapTestmodJar)
}

tasks.withType(RunGameTask::class) {
javaLauncher.set(javaToolchains.launcherFor { languageVersion.set(indra.javaVersions().target().map { v -> JavaLanguageVersion.of(v) })})
}

// Convert yaml files to josn
tasks.withType(ProcessResources::class.java).configureEach {
val generatedResourcesDir = project.layout.buildDirectory.dir("generated-resources").get().asFile
fun createProcessResourceTemplates(name: String, setProvider: NamedDomainObjectProvider<SourceSet>): TaskProvider<out Task> {
val destinationDir = generatedResourcesDir.resolve(name)
val set = setProvider.get()
val task = tasks.register(name, Sync::class.java) {
this.destinationDir = destinationDir
from("src/${set.name}/resource-templates")

inputs.property("version", project.version)

// Convert data files yaml -> json
Expand All @@ -151,13 +180,35 @@ tasks.withType(ProcessResources::class.java).configureEach {
.toList()
) {
convertFormat(ConfigFormats.YAML, ConfigFormats.JSON)
if (name.startsWith("fabric.mod")) {
if (this.name.startsWith("fabric.mod")) {
expand("project" to project)
}
name = name.substringBeforeLast('.') + ".json"
this.name = this.name.substringBeforeLast('.') + ".json"
}
// Convert pack meta, without changing extension
filesMatching("pack.mcmeta") { convertFormat(ConfigFormats.YAML, ConfigFormats.JSON) }
}

tasks.named(set.processResourcesTaskName) {
dependsOn(name)
}
set.resources.srcDir(task.map { it.outputs })

// Have templates ready for IDEs
eclipse.synchronizationTasks(task)
idea.project.settings.taskTriggers {
afterSync(task)
}
idea.module.generatedSourceDirs.add(destinationDir)

return task
}

val generateTemplates = createProcessResourceTemplates("generateTemplates", sourceSets.main)
val generateTestmodTemplates = createProcessResourceTemplates("generateTestmodTemplates", testmod)

tasks.withType(GenerateSourcesTask::class).configureEach {
dependsOn(generateTemplates)
}

indra {
Expand Down
7 changes: 4 additions & 3 deletions gradle/libs.versions.toml
Expand Up @@ -27,17 +27,18 @@ jetbrainsAnnotations = "org.jetbrains:annotations:23.0.0"
minecraft = "com.mojang:minecraft:1.18.2"

# build
stylecheck = "ca.stellardrift:stylecheck:0.1"
contractValidator = "ca.stellardrift:contract-validator:1.0.1"
stylecheck = "ca.stellardrift:stylecheck:0.1"

# For Renovate, do not use directly
zQuiltflower = { module = "org.quiltmc:quiltflower", version.ref = "quiltflower" }
zCheckstyle = { module = "com.puppycrawl.tools:checkstyle", version.ref = "checkstyle" }
zQuiltflower = { module = "org.quiltmc:quiltflower", version.ref = "quiltflower" }

[plugins]
configurateTransformations = "ca.stellardrift.configurate-transformations:5.0.1"
loom = "fabric-loom:0.11.+"
loomQuiltflower = "io.github.juuxel.loom-quiltflower:1.7.1"
configurateTransformations = "ca.stellardrift.configurate-transformations:5.0.1"
ideaExt = "org.jetbrains.gradle.plugin.idea-ext:1.1.4"
indra = { id = "net.kyori.indra", version.ref = "indra" }
indra-licenseHeader = { id = "net.kyori.indra.license-header", version.ref = "indra" }
indra-checkstyle = { id = "net.kyori.indra.checkstyle", version.ref = "indra" }
Expand Down
@@ -0,0 +1,38 @@
/*
* This file is part of adventure-platform-fabric, licensed under the MIT License.
*
* Copyright (c) 2021 KyoriPowered
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package net.kyori.adventure.platform.fabric.impl.accessor;

import net.kyori.adventure.key.InvalidKeyException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Invoker;

@Mixin(InvalidKeyException.class)
public interface InvalidKeyExceptionAccess {
@Invoker("<init>")
static InvalidKeyException newInvalidKeyException(final @NotNull String keyNamespace, final @NotNull String keyValue, final @Nullable String message) {
throw new IncompatibleClassChangeError("mixin missing");
}
}
@@ -1,10 +1,11 @@
{
"required": true,
"package": "net.kyori.adventure.platform.fabric.impl.accessor",
"compatibilityLevel": "JAVA_16",
"compatibilityLevel": "JAVA_17",
"mixins": [
"ComponentSerializerAccess",
"ConnectionAccess"
"ConnectionAccess",
"InvalidKeyExceptionAccess"
],
"client": [
"client.AbstractSoundInstanceAccess"
Expand Down
Expand Up @@ -41,13 +41,17 @@ public interface AdventureCommandSourceStack extends ForwardingAudience.Single,
* @param sendToOps If this message should be sent to all ops listening
* @since 4.0.0
*/
void sendSuccess(final @NotNull Component text, final boolean sendToOps);
default void sendSuccess(final @NotNull Component text, final boolean sendToOps) {
// Implemented by Mixin
}

/**
* Send an error message to the command source.
*
* @param text The error
* @since 4.0.0
*/
void sendFailure(final @NotNull Component text);
default void sendFailure(final @NotNull Component text) {
// Implemented by Mixin
}
}
Expand Up @@ -35,6 +35,7 @@
import net.kyori.adventure.pointer.Pointered;
import net.kyori.adventure.sound.Sound;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.ComponentLike;
import net.kyori.adventure.text.flattener.ComponentFlattener;
import net.kyori.adventure.text.renderer.ComponentRenderer;
import net.kyori.adventure.text.serializer.ComponentSerializer;
Expand Down Expand Up @@ -88,18 +89,27 @@ public interface FabricAudiences {
* @param loc The Identifier to convert
* @return The equivalent data as a Key
* @since 4.0.0
* @deprecated ResourceLocation directly implements key, and all Keys are ResourceLocations since Loader 0.14.0
*/
@Deprecated(forRemoval = true, since = "5.3.0")
@Contract("null -> null; !null -> !null")
static Key toAdventure(final ResourceLocation loc) {
if (loc == null) {
return null;
}
if (loc instanceof Key) {
return loc;
}
return Key.key(loc.getNamespace(), loc.getPath());
}

/**
* Convert a Kyori {@link Key} instance to a MC ResourceLocation.
*
* <p>All {@link Key} instances created in a Fabric environment with this
* mod are implemented by {@link ResourceLocation}, as long as loader 0.14 is present,
* so this is effectively a cast.</p>
*
* @param key The Key to convert
* @return The equivalent data as an Identifier
* @since 4.0.0
Expand All @@ -109,6 +119,9 @@ static ResourceLocation toNative(final Key key) {
if (key == null) {
return null;
}
if (key instanceof ResourceLocation) {
return (ResourceLocation) key;
}
return new ResourceLocation(key.namespace(), key.value());
}

Expand All @@ -118,9 +131,11 @@ static ResourceLocation toNative(final Key key) {
* @param entity the entity to convert
* @return the entity as a sound emitter
* @since 4.0.0
* @deprecated for removal, we can use loom interface injection instead
*/
@Deprecated(forRemoval = true, since = "5.3.0")
static Sound.@NotNull Emitter asEmitter(final @NotNull Entity entity) {
return (Sound.Emitter) entity;
return entity;
}

/**
Expand All @@ -143,9 +158,11 @@ static ResourceLocation toNative(final Key key) {
* @param player the player to identify
* @return an identified representation of the player
* @since 4.0.0
* @deprecated for removal, use interface injection instead
*/
@Deprecated(forRemoval = true, since = "5.3.0")
static @NotNull Identified identified(final @NotNull Player player) {
return (Identified) player;
return player;
}

/**
Expand Down Expand Up @@ -192,6 +209,10 @@ static ResourceLocation toNative(final Key key) {
* @param vanilla the native component
* @return adventure component
* @since 4.0.0
* @deprecated Use {@link ComponentLike#asComponent()} instead, implemented on {@link net.minecraft.network.chat.Component}
*/
@NotNull Component toAdventure(final net.minecraft.network.chat.@NotNull Component vanilla);
@Deprecated(forRemoval = true)
default @NotNull Component toAdventure(final net.minecraft.network.chat.@NotNull Component vanilla) {
return vanilla.asComponent();
}
}
Expand Up @@ -66,7 +66,6 @@ private KeyArgumentType() {

@Override
public @NotNull Key parse(final @NotNull StringReader reader) throws CommandSyntaxException {
// TODO: do this without creating a ResourceLocation instance
return FabricAudiences.toAdventure(ResourceLocation.read(reader));
return ResourceLocation.read(reader);
}
}
Expand Up @@ -76,7 +76,9 @@ interface Changed {
* @param player the source of the locale
* @return player locale
* @since 4.0.0
* @deprecated Use pointer instead, {@code player.get(Identity.LOCALE).orElse(Locale.getDefault())} on a server or client player
*/
@Deprecated(forRemoval = true, since = "5.3.0")
static @NotNull Locale locale(final @NotNull Player player) {
return player instanceof LocaleHolderBridge ? ((LocaleHolderBridge) player).adventure$locale() : Locale.getDefault();
}
Expand Down
Expand Up @@ -39,7 +39,7 @@ public void serializeToNetwork(final ComponentArgumentType type, final FriendlyB
@Override
public ComponentArgumentType deserializeFromNetwork(final FriendlyByteBuf buffer) {
final ResourceLocation id = buffer.readResourceLocation();
final ComponentArgumentType.Format format = ComponentArgumentType.Format.INDEX.value(FabricAudiences.toAdventure(id));
final ComponentArgumentType.Format format = ComponentArgumentType.Format.INDEX.value(id);
if (format == null) {
throw new IllegalArgumentException("Unknown Adventure component format: " + id);
}
Expand Down

0 comments on commit d5cd0b5

Please sign in to comment.