Внедрение интерфейса

Это новый метод, представленный Loom 0.11 для добавления методов в определенный существующий класс. Более конкретно, вы можете создать интерфейс, а затем внедрить этот интерфейс в класс. В результате целевой класс получит все методы интерфейса, как если бы они у него всегда были. Внедрение интерфейса - это функция только во время компиляции, это означает, что для реализации интерфейса в целевом классе также следует использовать Миксин.

Это особенно полезно для библиотек, с помощью этого вы можете добавлять новые методы в существующие классы и использовать их без необходимости каждый раз приводить или переопределять интерфейс.

Давайте лучше объясним на примере:

Область применения этого примера состоит в том, чтобы добавить следующий метод в net.minecraft.fluid.FlowableFluid, чтобы получить звук ведра при опустошении. Обычно это невозможно, потому что net.minecraft.fluid.FlowableFluid не имеет аналогичного метода.

Optional<SoundEvent> getBucketEmptySound()

Чтобы добавить метод в класс, прежде всего вам нужно создать с ним интерфейс:

package net.fabricmc.example;
 
public interface BucketEmptySoundGetter {
	// Методы во внедренном интерфейсе ДОЛЖНЫ быть по умолчанию,
	// в противном случае код, ссылающийся на них, не будет компилироваться!
	default Optional<SoundEvent> getBucketEmptySound() {
		return Optional.empty();
	}
}

Теперь вам нужно реализовать этот интерфейс в net.minecraft.fluid.FlowableFluid с помощью миксина, реализующего интерфейс:

@Mixin(FlowableFluid.class)
public class MixinFlowableFluid implements BucketEmptySoundGetter {
	@Override
	public Optional<SoundEvent> getBucketEmptySound() {
		//Вот как получить звук по умолчанию, скопированный из класса BucketItem.
		return Optional.of(((FlowableFluid) (Object) this).isIn(FluidTags.LAVA) ? SoundEvents.ITEM_BUCKET_EMPTY_LAVA : SoundEvents.ITEM_BUCKET_EMPTY);
	}
}

Наконец, вам нужно ввести интерфейс в net.minecraft.fluid.FlowableFluid. Следующий фрагмент можно добавить в ваш файл fabric.mod.json, чтобы добавить один или несколько интерфейсов к классу net.minecraft.fluid.FlowableFluid. Обратите внимание, что все имена классов здесь должны использовать “внутренние имена”, которые используют косые черты вместо точек (example/path/to/Class).

{
	"custom": {
		"loom:injected_interfaces": {
			"net/minecraft/class_3609": ["net/fabricmc/example/BucketEmptySoundGetter"]
		}
	}
}

Теперь вы можете использовать новый метод:

Optional<SoundEvent> sound = mytestfluid.getBucketEmptySound();

Вы также можете переопределить этот метод в классах, расширяющих FlowableFluid, для реализации пользовательского поведения.