Skip to content

Prevent item frame transmutation #8552

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: mc1.20.1/dev
Choose a base branch
from

Conversation

Allmoz
Copy link
Contributor

@Allmoz Allmoz commented May 25, 2025

Fixes schematicannon consuming an item frame when printing a glow item frame. didn't find a open or close issue about it.

@Allmoz Allmoz force-pushed the glow_item_frame branch 2 times, most recently from b079685 to d7c6927 Compare May 25, 2025 19:00
@VoidLeech VoidLeech added pr type: fix PR fixes a bug pr flag: simple PR has minimal changes labels May 25, 2025
@@ -141,10 +142,10 @@ public static ItemRequirement of(Entity entity) {
}

if (entity instanceof ItemFrame itemFrame) {
ItemStack frame = new ItemStack(Items.ITEM_FRAME);
ItemStack frame = new ItemStack(entity instanceof GlowItemFrame ? Items.GLOW_ITEM_FRAME : Items.ITEM_FRAME);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It may be best to use an accessor to call ItemFrame#getFrameItemStack instead. That way modded item frames are supported too

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It may be best to use an accessor to call ItemFrame#getFrameItemStack instead. That way modded item frames are supported too

IDEA didn't find it :/ i don't see a getFrameItemStack method in the ItemFrame class

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

intermediary class_1533.method_33340, which is ItemFrame#getFrameItemStack in mojmap and ItemFrameEntity.getAsItemStack in yarn

it is protected, so if you're doing itemFrame.getFrame[TAB] then autocomplete won't find it.

Copy link
Contributor Author

@Allmoz Allmoz Jun 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

then something like this?

ItemStack frame;
try{
	Method m = ItemFrame.class.getDeclaredMethod("getFrameItemStack");
	m.setAccessible(true);
	frame = (ItemStack) m.invoke(itemFrame);
}catch (Exception ignored) {
	frame = new ItemStack(entity instanceof GlowItemFrame ? Items.GLOW_ITEM_FRAME : Items.ITEM_FRAME);
}

:/ i don't remember reading something similar in the codebase

Copy link
Member

@IThundxr IThundxr Jun 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your almost there, you want a invoker instead:

@Mixin(ItemFrame.class)
public class ItemFrameAccessor {
	@Invoker("getFrameItemStack")
	ItemStack create$getFrameItemStack()
}

And then this would go in a file named ItemFrameAccessor under https://github.com/Creators-of-Create/Create/tree/mc1.20.1/dev/src/main/java/com/simibubi/create/foundation/mixin

Now to call this, you would do the following:

ItemFrame frame = [...]
ItemStack stack = ((ItemFrameAccessor) frame).create$getFrameItemStack();
More in-depth write up of accessor's and invoker's

Accessor's and Invoker's

Accessor's/Invoker's can replace AW/AT's and be faster since you don't need to wait for loom/FG/NG/MDG to recompile the Minecraft jar.

(They are also really helpful when you need to access stuff in other mods as AW/AT's only work on Minecraft's source and aren't able to be used for other mods)

Accessor

@Accessor lets you access protected/private fields.
Below is a example for a Accessor getter and setter.

@Mixin(LootPool.class)  
public interface AccessorLootPool { 
	// Gets the entries field
    @Accessor("entries")  
    LootPoolEntryContainer[] zeta$getEntries();  
	
	// Sets the entries field
    @Accessor("entries")  
    void zeta$setEntries(LootPoolEntryContainer[] entries);  
}

Usage:

// Getter
LootPool pool = ...

((AccessorLootPool) pool).zeta$getEntries();


// Setter
LootPoolEntryContainer[] entries = ...

((AccessorLootPool) pool).zeta$setEntries(entries);

Accessor for static fields

You'll want to throw a AssertionError or any other error inside of the static method, Don't be afraid however it wont actually throw a error once used, it'll be overriden by the class you are mixing into, and the get/set operation instead of the error being thrown.

@Mixin(AxeItem.class)  
public interface AccessorAxeItem {  
    @Accessor("STRIPPABLES")  
    static Map<Block, Block> zeta$getStrippables() {  
        throw new AssertionError();  
    }
}

Usage:

AccessorAxeItem.zeta$getStrippables(...)

Invoker

@Invoker lets you call protected/private methods.

@Mixin(FireBlock.class)  
public interface AccessorFireBlock {  
    @Invoker("getBurnOdds")  
    int zeta$getBurnOdds(BlockState state);
}

Usage:

((AccessorFireBlock) Blocks.FIRE).zeta$getBurnOdds(state)

Invoker for static method's

You'll want to throw a AssertionError or any other error inside of the static method, Don't be afraid however it wont actually throw a error once used, it'll be overriden by the class you are mixing into, and the method you want to call will be called instead of the error being thrown.

@Mixin(CriteriaTriggers.class)
public interface AccessorCriteriaTriggers {
    @Invoker("register")  
    static <T extends CriterionTrigger<?>> T zeta$register(T criterion) {  
        throw new AssertionError();  
    };  
}

Usage:

AccessorCriteriaTriggers.zeta$register(...)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it'd be an @Invoker, no?

Also, do they delegate to subclasses?

Copy link
Member

@IThundxr IThundxr Jun 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it'd be an @Invoker, no?

Also, do they delegate to subclasses?

Ah yeah, it'd be a invoker, i've fixed that.

And yeah they do

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your almost there, you want a invoker instead:

@Mixin(ItemFrame.class)
public class ItemFrameAccessor {
	@Invoker("getFrameItemStack")
	ItemStack create$getFrameItemStack()
}

And then this would go in a file named ItemFrameAccessor under https://github.com/Creators-of-Create/Create/tree/mc1.20.1/dev/src/main/java/com/simibubi/create/foundation/mixin

Now to call this, you would do the following:

ItemFrame frame = [...]
ItemStack stack = ((ItemFrameAccessor) frame).create$getFrameItemStack();

More in-depth write up of accessor's and invoker's

Thankiu so much, :D changes done

@Allmoz Allmoz force-pushed the glow_item_frame branch from d7c6927 to 3addfcc Compare June 16, 2025 07:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
pr flag: simple PR has minimal changes pr type: fix PR fixes a bug
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants