Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ org.gradle.parallel=true
#org.gradle.caching=true
#org.gradle.configuration-cache=true

versionMc=26.1.2
versionNeoForge=26.1.2.77
versionModDevGradle=2.0.141
versionMc=26.2
versionNeoForge=26.2.0.90
versionModDevGradle=2.0.148

runtimeVersion=1.0.0
4 changes: 2 additions & 2 deletions settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,5 @@ include("runtime", "test")
include("test:mc-1.21.1")
project(":test:mc-1.21.1").projectDir = file("test/mc-1.21.1")

include("test:mc-26.1.2")
project(":test:mc-26.1.2").projectDir = file("test/mc-26.1.2")
include("test:mc-26.2")
project(":test:mc-26.2").projectDir = file("test/mc-26.2")
25 changes: 25 additions & 0 deletions test/mc-26.2/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
plugins {
id("net.neoforged.moddev")
}

java {
toolchain.languageVersion = JavaLanguageVersion.of(25)
}

neoForge {
version = "26.2.0.90"

addModdingDependenciesTo(sourceSets.getByName("testClasses"))

unitTest {
enable()
}
}

dependencies {
testImplementation("org.sinytra.adapter:core") {
isTransitive = false
}

testImplementation(project(":test"))
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package org.sinytra.adapter.patch.test.mc_26_2.mixin;

import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.tree.FieldInsnNode;
import org.objectweb.asm.tree.InsnNode;
import org.objectweb.asm.tree.MethodInsnNode;
import org.objectweb.asm.tree.TypeInsnNode;
import org.sinytra.adapter.types.BytecodeFixerUpper;
import org.sinytra.adapter.types.SimpleTypeAdapter;
import org.sinytra.adapter.types.TypeAdapter;
import org.sinytra.adapter.util.provider.ClassLookup;

import java.util.List;

import static org.sinytra.adapter.util.AdapterUtil.insnList;

public class BytecodeFixerUpperTestFrontend {
private static final List<TypeAdapter> FIELD_TYPE_ADAPTERS = List.of(
new SimpleTypeAdapter(Type.getObjectType("net/minecraft/world/item/ItemStack"), Type.getObjectType("net/minecraft/world/item/Item"), (list, insn) ->
list.insert(insn, new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "net/minecraft/world/item/ItemStack", "getItem", "()Lnet/minecraft/world/item/Item;"))),
new SimpleTypeAdapter(
Type.getObjectType("java/util/function/Consumer"),
Type.getObjectType("net/neoforged/neoforge/network/bundle/PacketAndPayloadAcceptor"),
(list, insn) ->
list.insert(insn, insnList(
new TypeInsnNode(Opcodes.NEW, "net/neoforged/neoforge/network/bundle/PacketAndPayloadAcceptor"),
new InsnNode(Opcodes.DUP),
new MethodInsnNode(Opcodes.INVOKESPECIAL, "net/neoforged/neoforge/network/bundle/PacketAndPayloadAcceptor", "<init>", "(Ljava/util/function/Consumer;)V")
))),
new SimpleTypeAdapter(
Type.getObjectType("net/neoforged/neoforge/network/bundle/PacketAndPayloadAcceptor"),
Type.getObjectType("java/util/function/Consumer"),
(list, insn) ->
list.insert(insn, new FieldInsnNode(Opcodes.GETFIELD, "net/neoforged/neoforge/network/bundle/PacketAndPayloadAcceptor", "consumer", "Ljava/util/function/Consumer;")))
);

private final BytecodeFixerUpper bfu;

public BytecodeFixerUpperTestFrontend(ClassLookup cleanLookup, ClassLookup dirtyLookup) {
this.bfu = new BytecodeFixerUpper(cleanLookup, dirtyLookup, FIELD_TYPE_ADAPTERS);
}

public BytecodeFixerUpper unwrap() {
return this.bfu;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package org.sinytra.adapter.patch.test.mc_26_2.mixin;

import com.mojang.logging.LogUtils;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.objectweb.asm.tree.ClassNode;
import org.sinytra.adapter.env.ctx.PatchEnvironment;
import org.sinytra.adapter.env.ctx.RefmapHolder;
import org.sinytra.adapter.patch.DynamicPatches;
import org.sinytra.adapter.patch.Patcher;
import org.sinytra.adapter.patch.test_main.mixin.MinecraftMixinPatchTest;
import org.sinytra.adapter.types.FieldTypeUsageTransformer;
import org.sinytra.adapter.util.provider.ClassLookup;
import org.slf4j.Logger;
import org.spongepowered.asm.mixin.FabricUtil;

import java.util.List;

public class DynamicMixinPatchTest extends MinecraftMixinPatchTest {
private static final Logger LOGGER = LogUtils.getLogger();

private static Patcher patcher;
private static PatchEnvironment patchEnvironment;

@BeforeAll
static void initialize() {
ClassLookup cleanLookup = createCleanLookup();
ClassLookup dirtyLookup = createDirtyLookup();
patchEnvironment = PatchEnvironment.create(
new RefmapHolder() {
@Override
public String remap(String cls, String reference) {
return reference;
}

@Override
public void copyEntries(String from, String to) {
}
},
cleanLookup,
dirtyLookup,
new BytecodeFixerUpperTestFrontend(cleanLookup, dirtyLookup).unwrap(),
FabricUtil.COMPATIBILITY_LATEST
);
patcher = Patcher.builder(patchEnvironment)
.classTransformer(new FieldTypeUsageTransformer())
.methodTransformers(DynamicPatches.methodTransformers(List.of()))
.build();
}

@AfterAll
static void postTest() {
LOGGER.info("Complete report:\n\n{}", patchEnvironment.auditTrail().getCompleteReport());
}

@Test
void testExtractUsingCodePath() throws Exception {
assertSameCodeExtracted(
"org/sinytra/adapter/test/mc_26_2/mixin/LivingEntityMixin",
"playSoundCorrectlyForBlocks",
"org/sinytra/adapter/test/mc_26_2/mixin/adapter_generated_net_neoforged_neoforge_common_extensions_IBlockExtension",
assertTargetMethod()
);
}

@Test
void testModifyArgChangedTargetDesc() throws Exception {
assertSameCode(
"org/sinytra/adapter/test/mc_26_2/mixin/LevelRendererMixin",
"clampMaxValue",
assertTargetMethod(),
assertInjectionPoint()
);
}

@Override
protected LoadResult load(String className, List<String> allowedMethods) throws Exception {
ClassNode patched = loadClass(className);
patched.methods.removeIf(m -> !allowedMethods.contains(m.name));
patcher.process(patched);
return new LoadResult(patchEnvironment, patched, loadClass(className));
}
}
11 changes: 11 additions & 0 deletions test/mc-26.2/src/test/resources/META-INF/neoforge.mods.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
modLoader="javafml"
loaderVersion="*"
license="MIT"

[[mods]]
modId="adapter_test_26_2"
version="1.0"
displayName="Adapter Test mod"
authors="Sinytra"
description='''
'''
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package org.sinytra.adapter.test.mc_26_2.mixin;

import com.mojang.blaze3d.buffers.GpuBufferSlice;
import net.minecraft.client.renderer.LevelRenderer;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.ModifyArg;

@Mixin(LevelRenderer.class)
public class LevelRendererMixin {
@ModifyArg(
method = "render(Lcom/mojang/blaze3d/resource/GraphicsResourceAllocator;Lnet/minecraft/client/DeltaTracker;ZLnet/minecraft/client/renderer/state/level/CameraRenderState;Lorg/joml/Matrix4fc;Lcom/mojang/blaze3d/buffers/GpuBufferSlice;Lorg/joml/Vector4f;Z)V",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/client/renderer/LevelRenderer;addSkyPass(Lcom/mojang/blaze3d/framegraph/FrameGraphBuilder;Lnet/minecraft/client/renderer/state/level/CameraRenderState;Lcom/mojang/blaze3d/buffers/GpuBufferSlice;)V"
)
)
private GpuBufferSlice clampMaxValue(GpuBufferSlice fogBuffer) {
return fogBuffer;
}

@ModifyArg(
method = "render(Lcom/mojang/blaze3d/resource/GraphicsResourceAllocator;Lnet/minecraft/client/DeltaTracker;ZLnet/minecraft/client/renderer/state/level/CameraRenderState;Lorg/joml/Matrix4fc;Lcom/mojang/blaze3d/buffers/GpuBufferSlice;Lorg/joml/Vector4f;Z)V",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/client/renderer/LevelRenderer;addSkyPass(Lcom/mojang/blaze3d/framegraph/FrameGraphBuilder;Lnet/minecraft/client/renderer/state/level/CameraRenderState;Lcom/mojang/blaze3d/buffers/GpuBufferSlice;Lorg/joml/Matrix4fc;)V"
)
)
private GpuBufferSlice clampMaxValueExpected(GpuBufferSlice fogBuffer) {
return fogBuffer;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package org.sinytra.adapter.test.mc_26_2.mixin;

import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import com.llamalad7.mixinextras.sugar.Local;
import net.minecraft.sounds.SoundEvent;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.level.block.state.BlockState;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;

@Mixin(LivingEntity.class)
public class LivingEntityMixin {
public LivingEntityMixin() {
}

@WrapOperation(
method = "playBlockFallSound",
at = {@At(
value = "INVOKE",
target = "Lnet/minecraft/world/entity/LivingEntity;playSound(Lnet/minecraft/sounds/SoundEvent;FF)V"
)}
)
private void playSoundCorrectlyForBlocks(LivingEntity instance, SoundEvent sound, float volume, float pitch, Operation<Void> original, @Local BlockState state) {
original.call(instance, sound, volume, pitch);
}

@WrapOperation(
method = "playFallSound(Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/entity/LivingEntity;)V",
at = {@At(
value = "INVOKE",
target = "Lnet/minecraft/world/entity/LivingEntity;playSound(Lnet/minecraft/sounds/SoundEvent;FF)V"
)}
)
private void playSoundCorrectlyForBlocksExpected(LivingEntity instance, SoundEvent sound, float volume, float pitch, Operation<Void> original, @Local BlockState state) {
original.call(instance, sound, volume, pitch);
}
}