Skip to content

Commit a1f5e25

Browse files
committed
Add better end anvil compatibility
1 parent 2907683 commit a1f5e25

5 files changed

Lines changed: 277 additions & 2 deletions

File tree

fabric/build.gradle

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,12 @@ repositories {
4040
maven {
4141
url = "http://maven.terraformersmc.com/releases/"
4242
}
43+
maven {
44+
url "https://www.cursemaven.com"
45+
content {
46+
includeGroup "curse.maven"
47+
}
48+
}
4349
}
4450

4551
sourceCompatibility = JavaVersion.VERSION_1_8
@@ -55,6 +61,7 @@ def runAndCompile(List<String> mods, boolean run) {
5561
if (run) {
5662
modRuntime (it) {
5763
exclude(module: "modmenu")
64+
exclude(module: "fabric-api")
5865
}
5966
}
6067
}
@@ -66,9 +73,11 @@ def includeLibraries(List<String> libraries) {
6673
libraries.each {
6774
modImplementation (it) {
6875
exclude(module: "modmenu")
76+
exclude(module: "fabric-api")
6977
}
7078
include (it) {
7179
exclude(module: "modmenu")
80+
exclude(module: "fabric-api")
7281
}
7382
}
7483
}
@@ -79,6 +88,7 @@ def runAlways(List<String> mods) {
7988
mods.each {
8089
modRuntime (it) {
8190
exclude(module: "modmenu")
91+
exclude(module: "fabric-api")
8292
}
8393
}
8494
}
@@ -100,9 +110,13 @@ dependencies {
100110

101111
runAndCompile(["net.kyrptonaught:quickshulker:${project.quickshulker}",
102112
"com.github.emilyploszaj:trinkets:${project.trinkets}",
103-
"com.misterpemodder:shulkerboxtooltip:${project.shulkerboxtooltip}+"+/*${project.minecraft_version}*/"1.16.4"], false)
113+
"com.misterpemodder:shulkerboxtooltip:${project.shulkerboxtooltip}+"+/*${project.minecraft_version}*/"1.16.4",
114+
"curse.maven:betterend-413596:3168267"
115+
], true)
104116

105-
modCompile "io.github.prospector:modmenu:${project.modmenu}"
117+
modCompile("io.github.prospector:modmenu:${project.modmenu}") {
118+
exclude(module: "fabric-api")
119+
}
106120

107121
runAlways(["me.shedaniel:RoughlyEnoughItems:${project.rei}"])
108122

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package com.oroarmor.netherite_plus.mixin.better_end;
2+
3+
import java.util.ArrayList;
4+
import java.util.List;
5+
import java.util.Set;
6+
7+
import org.objectweb.asm.tree.ClassNode;
8+
import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin;
9+
import org.spongepowered.asm.mixin.extensibility.IMixinInfo;
10+
11+
import net.fabricmc.api.EnvType;
12+
import net.fabricmc.loader.api.FabricLoader;
13+
14+
public class BetterEndMixinCompatibility implements IMixinConfigPlugin {
15+
@Override
16+
public void onLoad(String mixinPackage) {
17+
}
18+
19+
@Override
20+
public String getRefMapperConfig() {
21+
return null;
22+
}
23+
24+
@Override
25+
public boolean shouldApplyMixin(String targetClassName, String mixinClassName) {
26+
if (mixinClassName.equals("com.oroarmor.netherite_plus.mixin.better_end.NetheriteAnvilScreenMixin")) {
27+
return FabricLoader.getInstance().getEnvironmentType() == EnvType.CLIENT;
28+
}
29+
return false;
30+
}
31+
32+
@Override
33+
public void acceptTargets(Set<String> myTargets, Set<String> otherTargets) {
34+
}
35+
36+
@Override
37+
public List<String> getMixins() {
38+
return new ArrayList<String>() {{
39+
this.add("better_end.NetheriteAnvilScreenHandlerMixin");
40+
this.add("better_end.NetheriteAnvilScreenMixin");
41+
}};
42+
}
43+
44+
@Override
45+
public void preApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) {
46+
}
47+
48+
@Override
49+
public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) {
50+
}
51+
}
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
package com.oroarmor.netherite_plus.mixin.better_end;
2+
3+
import java.util.Collections;
4+
import java.util.List;
5+
import java.util.stream.Collectors;
6+
7+
import com.oroarmor.netherite_plus.screen.NetheriteAnvilScreenHandler;
8+
import org.spongepowered.asm.mixin.Mixin;
9+
import org.spongepowered.asm.mixin.Shadow;
10+
import org.spongepowered.asm.mixin.injection.At;
11+
import org.spongepowered.asm.mixin.injection.Inject;
12+
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
13+
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
14+
15+
import net.minecraft.entity.player.PlayerEntity;
16+
import net.minecraft.entity.player.PlayerInventory;
17+
import net.minecraft.item.ItemStack;
18+
import net.minecraft.recipe.RecipeManager;
19+
import net.minecraft.screen.ForgingScreenHandler;
20+
import net.minecraft.screen.ScreenHandlerContext;
21+
import net.minecraft.screen.ScreenHandlerType;
22+
23+
import ru.betterend.interfaces.AnvilScreenHandlerExtended;
24+
import ru.betterend.recipe.builders.AnvilRecipe;
25+
26+
@Mixin(NetheriteAnvilScreenHandler.class)
27+
public abstract class NetheriteAnvilScreenHandlerMixin extends ForgingScreenHandler implements AnvilScreenHandlerExtended {
28+
29+
private List<AnvilRecipe> be_recipes = Collections.emptyList();
30+
private AnvilRecipe be_currentRecipe;
31+
32+
public NetheriteAnvilScreenHandlerMixin(ScreenHandlerType<?> type, int syncId, PlayerInventory playerInventory,
33+
ScreenHandlerContext context) {
34+
super(type, syncId, playerInventory, context);
35+
}
36+
37+
@Shadow
38+
public abstract void updateResult();
39+
40+
@Inject(method = "canTakeOutput", at = @At("HEAD"), cancellable = true)
41+
protected void be_canTakeOutput(PlayerEntity player, boolean present, CallbackInfoReturnable<Boolean> info) {
42+
if (this.be_currentRecipe != null) {
43+
ItemStack output = this.be_currentRecipe.craft(this.input, player);
44+
if (!output.isEmpty()) {
45+
info.setReturnValue(true);
46+
}
47+
}
48+
}
49+
50+
@Inject(method = "onTakeOutput", at = @At("HEAD"), cancellable = true)
51+
protected void be_onTakeOutput(PlayerEntity player, ItemStack stack, CallbackInfoReturnable<ItemStack> info) {
52+
if (this.be_currentRecipe != null) {
53+
this.input.getStack(0).decrement(1);
54+
this.onContentChanged(this.input);
55+
info.setReturnValue(stack);
56+
}
57+
}
58+
59+
@Inject(method = "updateResult", at = @At("HEAD"), cancellable = true)
60+
public void be_updateOutput(CallbackInfo info) {
61+
RecipeManager recipeManager = this.player.world.getRecipeManager();
62+
this.be_recipes = recipeManager.getAllMatches(AnvilRecipe.TYPE, this.input, this.player.world);
63+
if (this.be_recipes.size() > 0) {
64+
this.be_currentRecipe = recipeManager.getFirstMatch(AnvilRecipe.TYPE, this.input, this.player.world).get();
65+
this.be_updateResult();
66+
info.cancel();
67+
}
68+
69+
}
70+
71+
@Inject(method = "setNewItemName", at = @At("HEAD"), cancellable = true, remap = false)
72+
public void be_setNewItemName(String string, CallbackInfo info) {
73+
if (be_currentRecipe != null) {
74+
info.cancel();
75+
}
76+
}
77+
78+
@Override
79+
public boolean onButtonClick(PlayerEntity player, int id) {
80+
if (id == 0) {
81+
this.be_previousRecipe();
82+
return true;
83+
} else if (id == 1) {
84+
this.be_nextRecipe();
85+
return true;
86+
}
87+
return super.onButtonClick(player, id);
88+
}
89+
90+
private void be_updateResult() {
91+
if (be_currentRecipe == null) return;
92+
this.output.setStack(0, be_currentRecipe.craft(input));
93+
this.sendContentUpdates();
94+
}
95+
96+
@Override
97+
public void be_updateCurrentRecipe(AnvilRecipe recipe) {
98+
this.be_currentRecipe = recipe;
99+
this.be_updateResult();
100+
}
101+
102+
@Override
103+
public AnvilRecipe be_getCurrentRecipe() {
104+
return this.be_currentRecipe;
105+
}
106+
107+
@Override
108+
public List<AnvilRecipe> be_getRecipes() {
109+
return this.be_recipes;
110+
}
111+
}
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
package com.oroarmor.netherite_plus.mixin.better_end;
2+
3+
import java.util.List;
4+
5+
import com.oroarmor.netherite_plus.client.gui.screen.NetheriteAnvilScreen;
6+
import com.oroarmor.netherite_plus.screen.NetheriteAnvilScreenHandler;
7+
import org.spongepowered.asm.mixin.Mixin;
8+
import org.spongepowered.asm.mixin.Shadow;
9+
import org.spongepowered.asm.mixin.injection.At;
10+
import org.spongepowered.asm.mixin.injection.Inject;
11+
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
12+
13+
import com.google.common.collect.Lists;
14+
15+
import net.minecraft.client.gui.screen.ingame.ForgingScreen;
16+
import net.minecraft.client.gui.widget.AbstractButtonWidget;
17+
import net.minecraft.client.gui.widget.ButtonWidget;
18+
import net.minecraft.client.gui.widget.TextFieldWidget;
19+
import net.minecraft.client.util.math.MatrixStack;
20+
import net.minecraft.entity.player.PlayerInventory;
21+
import net.minecraft.item.ItemStack;
22+
import net.minecraft.screen.ScreenHandler;
23+
import net.minecraft.text.LiteralText;
24+
import net.minecraft.text.Text;
25+
import net.minecraft.util.Identifier;
26+
import ru.betterend.interfaces.AnvilScreenHandlerExtended;
27+
28+
@Mixin(NetheriteAnvilScreen.class)
29+
public class NetheriteAnvilScreenMixin extends ForgingScreen<NetheriteAnvilScreenHandler> {
30+
31+
@Shadow(remap = false)
32+
private TextFieldWidget nameField;
33+
34+
private final List<AbstractButtonWidget> be_buttons = Lists.newArrayList();
35+
private AnvilScreenHandlerExtended anvilHandler;
36+
37+
public NetheriteAnvilScreenMixin(NetheriteAnvilScreenHandler handler, PlayerInventory playerInventory, Text title,
38+
Identifier texture) {
39+
super(handler, playerInventory, title, texture);
40+
}
41+
42+
@Inject(method = "setup", at = @At("TAIL"))
43+
protected void be_setup(CallbackInfo info) {
44+
this.be_buttons.clear();
45+
int x = (width - backgroundWidth) / 2;
46+
int y = (height - backgroundHeight) / 2;
47+
this.anvilHandler = (AnvilScreenHandlerExtended) this.handler;
48+
this.be_buttons.add(new ButtonWidget(x + 8, y + 45, 15, 20, new LiteralText("<"), (b) -> be_previousRecipe()));
49+
this.be_buttons.add(new ButtonWidget(x + 154, y + 45, 15, 20, new LiteralText(">"), (b) -> be_nextRecipe()));
50+
}
51+
52+
@Inject(method = "renderForeground", at = @At("TAIL"))
53+
protected void be_renderForeground(MatrixStack matrices, int mouseX, int mouseY, float delta, CallbackInfo info) {
54+
this.be_buttons.forEach(button -> {
55+
button.render(matrices, mouseX, mouseY, delta);
56+
});
57+
}
58+
59+
@Inject(method = "onSlotUpdate", at = @At("HEAD"), cancellable = true)
60+
public void be_onSlotUpdate(ScreenHandler handler, int slotId, ItemStack stack, CallbackInfo info) {
61+
AnvilScreenHandlerExtended anvilHandler = (AnvilScreenHandlerExtended) handler;
62+
if (anvilHandler.be_getCurrentRecipe() != null) {
63+
if (anvilHandler.be_getRecipes().size() > 1) {
64+
this.be_buttons.forEach(button -> button.visible = true);
65+
} else {
66+
this.be_buttons.forEach(button -> button.visible = false);
67+
}
68+
this.nameField.setText("");
69+
info.cancel();
70+
} else {
71+
this.be_buttons.forEach(button -> button.visible = false);
72+
}
73+
}
74+
75+
private void be_nextRecipe() {
76+
this.anvilHandler.be_nextRecipe();
77+
}
78+
79+
private void be_previousRecipe() {
80+
this.anvilHandler.be_previousRecipe();
81+
}
82+
83+
@Override
84+
public boolean mouseClicked(double mouseX, double mouseY, int button) {
85+
if (client != null) {
86+
for (AbstractButtonWidget elem : be_buttons) {
87+
if (elem.visible && elem.mouseClicked(mouseX, mouseY, button)) {
88+
if (client.interactionManager != null) {
89+
int i = be_buttons.indexOf(elem);
90+
this.client.interactionManager.clickButton(handler.syncId, i);
91+
return true;
92+
}
93+
}
94+
}
95+
}
96+
return super.mouseClicked(mouseX, mouseY, button);
97+
}
98+
}

fabric/src/main/resources/netherite-plus-mod-fabric.mixins.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
],
1111
"client": [
1212
],
13+
"plugin": "com.oroarmor.netherite_plus.mixin.better_end.BetterEndMixinCompatibility",
1314
"injectors": {
1415
"defaultRequire": 1
1516
}

0 commit comments

Comments
 (0)