Compare commits
7 commits
04b4ddd3d8
...
a42bb0507e
Author | SHA1 | Date | |
---|---|---|---|
a42bb0507e | |||
b803b794f8 | |||
8712c28b0e | |||
a5f7fd9fb0 | |||
92839c5df4 | |||
cad7263d9e | |||
6ddfa10903 |
28 changed files with 749 additions and 544 deletions
19
build.gradle
19
build.gradle
|
@ -48,7 +48,8 @@ dependencies {
|
|||
|
||||
modImplementation libs.quilted.fabric.api
|
||||
|
||||
modApi include("dev.emi:trinkets:${libs.versions.trinkets.get()}")
|
||||
// not JiJ because it causes its mixins to fail to load
|
||||
modApi "dev.emi:trinkets:${libs.versions.trinkets.get()}"
|
||||
modApi include("com.unascribed:lib39-core:${libs.versions.lib39.get()}+${libs.versions.minecraft.get()}")
|
||||
modApi include("com.unascribed:lib39-dessicant:${libs.versions.lib39.get()}+${libs.versions.minecraft.get()}")
|
||||
|
||||
|
@ -57,10 +58,22 @@ dependencies {
|
|||
}
|
||||
|
||||
processResources {
|
||||
inputs.properties 'version': version, 'group': project.group
|
||||
inputs.property 'version', version
|
||||
inputs.property 'group', project.group
|
||||
inputs.property 'minecraft_version', libs.versions.minecraft.get()
|
||||
inputs.property 'trinkets_version', libs.versions.trinkets.get()
|
||||
inputs.property 'lib39_version', libs.versions.lib39.get()
|
||||
inputs.property 'emi_version', libs.versions.emi.get()
|
||||
|
||||
filesMatching('quilt.mod.json') {
|
||||
expand 'version': version, 'group': project.group
|
||||
expand (
|
||||
"version": version,
|
||||
"group": project.group,
|
||||
"minecraft_version": libs.versions.minecraft.get(),
|
||||
"trinkets_version": libs.versions.trinkets.get(),
|
||||
"lib39_version": libs.versions.lib39.get(),
|
||||
"emi_version": libs.versions.emi.get()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,6 @@ import net.minecraft.util.Identifier;
|
|||
|
||||
import org.quiltmc.loader.api.ModContainer;
|
||||
import org.quiltmc.qsl.base.api.entrypoint.ModInitializer;
|
||||
import pm.c7.scout.config.ScoutConfigHandler;
|
||||
import pm.c7.scout.registry.ScoutItems;
|
||||
|
||||
public class Scout implements ModInitializer {
|
||||
|
@ -32,7 +31,6 @@ public class Scout implements ModInitializer {
|
|||
|
||||
@Override
|
||||
public void onInitialize(ModContainer mod) {
|
||||
new ScoutConfigHandler();
|
||||
ScoutItems.init();
|
||||
Registry.register(Registries.ITEM_GROUP, new Identifier(ScoutUtil.MOD_ID, "itemgroup"), ITEM_GROUP);
|
||||
}
|
||||
|
|
16
src/main/java/pm/c7/scout/ScoutConfig.java
Normal file
16
src/main/java/pm/c7/scout/ScoutConfig.java
Normal file
|
@ -0,0 +1,16 @@
|
|||
package pm.c7.scout;
|
||||
|
||||
import org.quiltmc.config.api.ReflectiveConfig;
|
||||
import org.quiltmc.config.api.annotations.Comment;
|
||||
import org.quiltmc.config.api.values.TrackedValue;
|
||||
import org.quiltmc.loader.api.config.v2.QuiltConfig;
|
||||
|
||||
public class ScoutConfig extends ReflectiveConfig {
|
||||
public static final ScoutConfig CONFIG = QuiltConfig.create("", ScoutUtil.MOD_ID, ScoutConfig.class);
|
||||
|
||||
@Comment("Allow shulker boxes to be placed in bags. Bags are already blacklisted from shulker boxes with no toggle.")
|
||||
public final TrackedValue<Boolean> allowShulkers = this.value(true);
|
||||
|
||||
@Comment("Allow bags to act as a quiver and pull arrows.")
|
||||
public final TrackedValue<Boolean> useArrows = this.value(true);
|
||||
}
|
|
@ -3,5 +3,5 @@ package pm.c7.scout;
|
|||
import net.minecraft.util.Identifier;
|
||||
|
||||
public class ScoutNetworking {
|
||||
public static final Identifier ENABLE_SLOTS = new Identifier(ScoutUtil.MOD_ID, "enable_slots");
|
||||
public static final Identifier ENABLE_SLOTS = new Identifier(ScoutUtil.MOD_ID, "enable_slots");
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ import net.minecraft.util.collection.DefaultedList;
|
|||
import pm.c7.scout.screen.BagSlot;
|
||||
|
||||
public interface ScoutScreenHandler {
|
||||
DefaultedList<BagSlot> scout$getSatchelSlots();
|
||||
DefaultedList<BagSlot> scout$getLeftPouchSlots();
|
||||
DefaultedList<BagSlot> scout$getRightPouchSlots();
|
||||
DefaultedList<BagSlot> scout$getSatchelSlots();
|
||||
DefaultedList<BagSlot> scout$getLeftPouchSlots();
|
||||
DefaultedList<BagSlot> scout$getRightPouchSlots();
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ import net.minecraft.nbt.NbtCompound;
|
|||
import net.minecraft.nbt.NbtList;
|
||||
import net.minecraft.screen.PlayerScreenHandler;
|
||||
import net.minecraft.screen.slot.Slot;
|
||||
import net.minecraft.screen.slot.SlotActionType;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.Pair;
|
||||
import net.minecraft.util.collection.DefaultedList;
|
||||
|
@ -44,59 +45,59 @@ public class ScoutUtil {
|
|||
public static final int BAG_SLOTS_END = RIGHT_POUCH_SLOT_START - MAX_POUCH_SLOTS;
|
||||
|
||||
public static ItemStack findBagItem(PlayerEntity player, BaseBagItem.BagType type, boolean right) {
|
||||
ItemStack targetStack = ItemStack.EMPTY;
|
||||
ItemStack targetStack = ItemStack.EMPTY;
|
||||
|
||||
boolean hasFirstPouch = false;
|
||||
Optional<TrinketComponent> _component = TrinketsApi.getTrinketComponent(player);
|
||||
if (_component.isPresent()) {
|
||||
TrinketComponent component = _component.get();
|
||||
for (Pair<SlotReference, ItemStack> pair : component.getAllEquipped()) {
|
||||
ItemStack slotStack = pair.getRight();
|
||||
boolean hasFirstPouch = false;
|
||||
Optional<TrinketComponent> _component = TrinketsApi.getTrinketComponent(player);
|
||||
if (_component.isPresent()) {
|
||||
TrinketComponent component = _component.get();
|
||||
for (Pair<SlotReference, ItemStack> pair : component.getAllEquipped()) {
|
||||
ItemStack slotStack = pair.getRight();
|
||||
|
||||
if (slotStack.getItem() instanceof BaseBagItem bagItem) {
|
||||
if (slotStack.getItem() instanceof BaseBagItem bagItem) {
|
||||
if (bagItem.getType() == type) {
|
||||
if (type == BagType.POUCH) {
|
||||
if (right && !hasFirstPouch) {
|
||||
hasFirstPouch = true;
|
||||
if (type == BagType.POUCH) {
|
||||
if (right && !hasFirstPouch) {
|
||||
hasFirstPouch = true;
|
||||
} else {
|
||||
targetStack = slotStack;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
targetStack = slotStack;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
targetStack = slotStack;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
targetStack = slotStack;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return targetStack;
|
||||
}
|
||||
return targetStack;
|
||||
}
|
||||
|
||||
public static NbtList inventoryToTag(Inventory inventory) {
|
||||
NbtList tag = new NbtList();
|
||||
public static NbtList inventoryToTag(Inventory inventory) {
|
||||
NbtList tag = new NbtList();
|
||||
|
||||
for(int i = 0; i < inventory.size(); i++) {
|
||||
NbtCompound stackTag = new NbtCompound();
|
||||
stackTag.putInt("Slot", i);
|
||||
stackTag.put("Stack", inventory.getStack(i).writeNbt(new NbtCompound()));
|
||||
tag.add(stackTag);
|
||||
}
|
||||
for(int i = 0; i < inventory.size(); i++) {
|
||||
NbtCompound stackTag = new NbtCompound();
|
||||
stackTag.putInt("Slot", i);
|
||||
stackTag.put("Stack", inventory.getStack(i).writeNbt(new NbtCompound()));
|
||||
tag.add(stackTag);
|
||||
}
|
||||
|
||||
return tag;
|
||||
}
|
||||
return tag;
|
||||
}
|
||||
|
||||
public static void inventoryFromTag(NbtList tag, Inventory inventory) {
|
||||
inventory.clear();
|
||||
public static void inventoryFromTag(NbtList tag, Inventory inventory) {
|
||||
inventory.clear();
|
||||
|
||||
tag.forEach(element -> {
|
||||
NbtCompound stackTag = (NbtCompound) element;
|
||||
int slot = stackTag.getInt("Slot");
|
||||
ItemStack stack = ItemStack.fromNbt(stackTag.getCompound("Stack"));
|
||||
inventory.setStack(slot, stack);
|
||||
});
|
||||
}
|
||||
tag.forEach(element -> {
|
||||
NbtCompound stackTag = (NbtCompound) element;
|
||||
int slot = stackTag.getInt("Slot");
|
||||
ItemStack stack = ItemStack.fromNbt(stackTag.getCompound("Stack"));
|
||||
inventory.setStack(slot, stack);
|
||||
});
|
||||
}
|
||||
|
||||
public static boolean isBagSlot(int slot) {
|
||||
return slot <= SATCHEL_SLOT_START && slot > BAG_SLOTS_END;
|
||||
|
|
|
@ -27,79 +27,79 @@ import pm.c7.scout.mixin.client.HandledScreenAccessor;
|
|||
import pm.c7.scout.screen.BagSlot;
|
||||
|
||||
public class ScoutClient implements ClientModInitializer {
|
||||
@Override
|
||||
public void onInitializeClient(ModContainer mod) {
|
||||
ClientPlayNetworking.registerGlobalReceiver(ScoutNetworking.ENABLE_SLOTS, (client, handler, packet, sender) -> {
|
||||
client.execute(() -> {
|
||||
@Override
|
||||
public void onInitializeClient(ModContainer mod) {
|
||||
ClientPlayNetworking.registerGlobalReceiver(ScoutNetworking.ENABLE_SLOTS, (client, handler, packet, sender) -> {
|
||||
client.execute(() -> {
|
||||
assert client.player != null;
|
||||
ScoutScreenHandler screenHandler = (ScoutScreenHandler) client.player.playerScreenHandler;
|
||||
|
||||
ItemStack satchelStack = ScoutUtil.findBagItem(client.player, BagType.SATCHEL, false);
|
||||
DefaultedList<BagSlot> satchelSlots = screenHandler.scout$getSatchelSlots();
|
||||
ItemStack satchelStack = ScoutUtil.findBagItem(client.player, BagType.SATCHEL, false);
|
||||
DefaultedList<BagSlot> satchelSlots = screenHandler.scout$getSatchelSlots();
|
||||
|
||||
for (int i = 0; i < ScoutUtil.MAX_SATCHEL_SLOTS; i++) {
|
||||
BagSlot slot = satchelSlots.get(i);
|
||||
slot.setInventory(null);
|
||||
slot.setEnabled(false);
|
||||
}
|
||||
if (!satchelStack.isEmpty()) {
|
||||
BaseBagItem satchelItem = (BaseBagItem) satchelStack.getItem();
|
||||
Inventory satchelInv = satchelItem.getInventory(satchelStack);
|
||||
for (int i = 0; i < ScoutUtil.MAX_SATCHEL_SLOTS; i++) {
|
||||
BagSlot slot = satchelSlots.get(i);
|
||||
slot.setInventory(null);
|
||||
slot.setEnabled(false);
|
||||
}
|
||||
if (!satchelStack.isEmpty()) {
|
||||
BaseBagItem satchelItem = (BaseBagItem) satchelStack.getItem();
|
||||
Inventory satchelInv = satchelItem.getInventory(satchelStack);
|
||||
|
||||
for (int i = 0; i < satchelItem.getSlotCount(); i++) {
|
||||
BagSlot slot = satchelSlots.get(i);
|
||||
slot.setInventory(satchelInv);
|
||||
slot.setEnabled(true);
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < satchelItem.getSlotCount(); i++) {
|
||||
BagSlot slot = satchelSlots.get(i);
|
||||
slot.setInventory(satchelInv);
|
||||
slot.setEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
ItemStack leftPouchStack = ScoutUtil.findBagItem(client.player, BagType.POUCH, false);
|
||||
DefaultedList<BagSlot> leftPouchSlots = screenHandler.scout$getLeftPouchSlots();
|
||||
ItemStack leftPouchStack = ScoutUtil.findBagItem(client.player, BagType.POUCH, false);
|
||||
DefaultedList<BagSlot> leftPouchSlots = screenHandler.scout$getLeftPouchSlots();
|
||||
|
||||
for (int i = 0; i < ScoutUtil.MAX_POUCH_SLOTS; i++) {
|
||||
BagSlot slot = leftPouchSlots.get(i);
|
||||
slot.setInventory(null);
|
||||
slot.setEnabled(false);
|
||||
}
|
||||
if (!leftPouchStack.isEmpty()) {
|
||||
BaseBagItem leftPouchItem = (BaseBagItem) leftPouchStack.getItem();
|
||||
Inventory leftPouchInv = leftPouchItem.getInventory(leftPouchStack);
|
||||
for (int i = 0; i < ScoutUtil.MAX_POUCH_SLOTS; i++) {
|
||||
BagSlot slot = leftPouchSlots.get(i);
|
||||
slot.setInventory(null);
|
||||
slot.setEnabled(false);
|
||||
}
|
||||
if (!leftPouchStack.isEmpty()) {
|
||||
BaseBagItem leftPouchItem = (BaseBagItem) leftPouchStack.getItem();
|
||||
Inventory leftPouchInv = leftPouchItem.getInventory(leftPouchStack);
|
||||
|
||||
for (int i = 0; i < leftPouchItem.getSlotCount(); i++) {
|
||||
BagSlot slot = leftPouchSlots.get(i);
|
||||
slot.setInventory(leftPouchInv);
|
||||
slot.setEnabled(true);
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < leftPouchItem.getSlotCount(); i++) {
|
||||
BagSlot slot = leftPouchSlots.get(i);
|
||||
slot.setInventory(leftPouchInv);
|
||||
slot.setEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
ItemStack rightPouchStack = ScoutUtil.findBagItem(client.player, BagType.POUCH, true);
|
||||
DefaultedList<BagSlot> rightPouchSlots = screenHandler.scout$getRightPouchSlots();
|
||||
ItemStack rightPouchStack = ScoutUtil.findBagItem(client.player, BagType.POUCH, true);
|
||||
DefaultedList<BagSlot> rightPouchSlots = screenHandler.scout$getRightPouchSlots();
|
||||
|
||||
for (int i = 0; i < ScoutUtil.MAX_POUCH_SLOTS; i++) {
|
||||
BagSlot slot = rightPouchSlots.get(i);
|
||||
slot.setInventory(null);
|
||||
slot.setEnabled(false);
|
||||
}
|
||||
if (!rightPouchStack.isEmpty()) {
|
||||
BaseBagItem rightPouchItem = (BaseBagItem) rightPouchStack.getItem();
|
||||
Inventory rightPouchInv = rightPouchItem.getInventory(rightPouchStack);
|
||||
for (int i = 0; i < ScoutUtil.MAX_POUCH_SLOTS; i++) {
|
||||
BagSlot slot = rightPouchSlots.get(i);
|
||||
slot.setInventory(null);
|
||||
slot.setEnabled(false);
|
||||
}
|
||||
if (!rightPouchStack.isEmpty()) {
|
||||
BaseBagItem rightPouchItem = (BaseBagItem) rightPouchStack.getItem();
|
||||
Inventory rightPouchInv = rightPouchItem.getInventory(rightPouchStack);
|
||||
|
||||
for (int i = 0; i < rightPouchItem.getSlotCount(); i++) {
|
||||
BagSlot slot = rightPouchSlots.get(i);
|
||||
slot.setInventory(rightPouchInv);
|
||||
slot.setEnabled(true);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
for (int i = 0; i < rightPouchItem.getSlotCount(); i++) {
|
||||
BagSlot slot = rightPouchSlots.get(i);
|
||||
slot.setInventory(rightPouchInv);
|
||||
slot.setEnabled(true);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
TooltipComponentCallback.EVENT.register(data -> {
|
||||
if (data instanceof BagTooltipData d) {
|
||||
return new BagTooltipComponent(d);
|
||||
}
|
||||
TooltipComponentCallback.EVENT.register(data -> {
|
||||
if (data instanceof BagTooltipData d) {
|
||||
return new BagTooltipComponent(d);
|
||||
}
|
||||
|
||||
return null;
|
||||
});
|
||||
return null;
|
||||
});
|
||||
|
||||
LivingEntityFeatureRendererRegistrationCallback.EVENT.register((entityType, entityRenderer, registrationHelper, context) -> {
|
||||
if (entityType == EntityType.PLAYER) {
|
||||
|
@ -200,5 +200,5 @@ public class ScoutClient implements ClientModInitializer {
|
|||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,34 +12,34 @@ import pm.c7.scout.item.BaseBagItem.BagType;
|
|||
import pm.c7.scout.mixin.client.HandledScreenAccessor;
|
||||
|
||||
public class ScoutEmiPlugin implements EmiPlugin {
|
||||
@Override
|
||||
public void register(EmiRegistry registry) {
|
||||
registry.addExclusionArea(InventoryScreen.class, (screen, consumer) -> {
|
||||
MinecraftClient client = MinecraftClient.getInstance();
|
||||
ItemStack leftPouchStack = ScoutUtil.findBagItem(client.player, BagType.POUCH, false);
|
||||
if (!leftPouchStack.isEmpty()) {
|
||||
BaseBagItem bagItem = (BaseBagItem) leftPouchStack.getItem();
|
||||
int slots = bagItem.getSlotCount();
|
||||
int columns = (int) Math.ceil(slots / 3);
|
||||
@Override
|
||||
public void register(EmiRegistry registry) {
|
||||
registry.addExclusionArea(InventoryScreen.class, (screen, consumer) -> {
|
||||
MinecraftClient client = MinecraftClient.getInstance();
|
||||
ItemStack leftPouchStack = ScoutUtil.findBagItem(client.player, BagType.POUCH, false);
|
||||
if (!leftPouchStack.isEmpty()) {
|
||||
BaseBagItem bagItem = (BaseBagItem) leftPouchStack.getItem();
|
||||
int slots = bagItem.getSlotCount();
|
||||
int columns = (int) Math.ceil(slots / 3);
|
||||
|
||||
int x = ((HandledScreenAccessor) screen).getX() - (columns * 18);
|
||||
int y = ((HandledScreenAccessor) screen).getY() + 76;
|
||||
int x = ((HandledScreenAccessor) screen).getX() - (columns * 18);
|
||||
int y = ((HandledScreenAccessor) screen).getY() + 76;
|
||||
|
||||
consumer.accept(new Bounds(x, y, columns * 18, 68));
|
||||
}
|
||||
consumer.accept(new Bounds(x, y, columns * 18, 68));
|
||||
}
|
||||
|
||||
ItemStack rightPouchStack = ScoutUtil.findBagItem(client.player, BagType.POUCH, true);
|
||||
if (!rightPouchStack.isEmpty()) {
|
||||
BaseBagItem bagItem = (BaseBagItem) rightPouchStack.getItem();
|
||||
int slots = bagItem.getSlotCount();
|
||||
int columns = (int) Math.ceil(slots / 3);
|
||||
ItemStack rightPouchStack = ScoutUtil.findBagItem(client.player, BagType.POUCH, true);
|
||||
if (!rightPouchStack.isEmpty()) {
|
||||
BaseBagItem bagItem = (BaseBagItem) rightPouchStack.getItem();
|
||||
int slots = bagItem.getSlotCount();
|
||||
int columns = (int) Math.ceil(slots / 3);
|
||||
|
||||
int x = ((HandledScreenAccessor) screen).getX() + 176;
|
||||
int y = ((HandledScreenAccessor) screen).getY() + 76;
|
||||
int x = ((HandledScreenAccessor) screen).getX() + 176;
|
||||
int y = ((HandledScreenAccessor) screen).getY() + 76;
|
||||
|
||||
consumer.accept(new Bounds(x, y, columns * 18, 68));
|
||||
}
|
||||
});
|
||||
}
|
||||
consumer.accept(new Bounds(x, y, columns * 18, 68));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
package pm.c7.scout.config;
|
||||
|
||||
import org.quiltmc.config.api.WrappedConfig;
|
||||
import org.quiltmc.config.api.annotations.Comment;
|
||||
|
||||
public class ScoutConfig extends WrappedConfig {
|
||||
@Comment("Allow shulker boxes to be placed in bags. Bags are already blacklisted from shulker boxes with no toggle.")
|
||||
public final boolean allowShulkers = true;
|
||||
|
||||
@Comment("Allow bags to act as a quiver and pull arrows.")
|
||||
public final boolean useArrows = true;
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
package pm.c7.scout.config;
|
||||
|
||||
import org.quiltmc.config.api.values.TrackedValue;
|
||||
import org.quiltmc.loader.api.config.QuiltConfig;
|
||||
import pm.c7.scout.ScoutUtil;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ScoutConfigHandler {
|
||||
public static final ScoutConfig CONFIG = QuiltConfig.create("", ScoutUtil.MOD_ID, ScoutConfig.class);
|
||||
|
||||
public ScoutConfigHandler() {}
|
||||
|
||||
public static TrackedValue<?> getConfigValue(String key) {
|
||||
return CONFIG.getValue(List.of(key));
|
||||
}
|
||||
}
|
|
@ -5,19 +5,19 @@ import net.minecraft.item.ItemStack;
|
|||
import net.minecraft.util.collection.DefaultedList;
|
||||
|
||||
public class BagTooltipData implements TooltipData {
|
||||
private final DefaultedList<ItemStack> inventory;
|
||||
private final int slotCount;
|
||||
private final DefaultedList<ItemStack> inventory;
|
||||
private final int slotCount;
|
||||
|
||||
public BagTooltipData(DefaultedList<ItemStack> inventory, int slots) {
|
||||
this.inventory = inventory;
|
||||
this.slotCount = slots;
|
||||
}
|
||||
public BagTooltipData(DefaultedList<ItemStack> inventory, int slots) {
|
||||
this.inventory = inventory;
|
||||
this.slotCount = slots;
|
||||
}
|
||||
|
||||
public DefaultedList<ItemStack> getInventory() {
|
||||
return this.inventory;
|
||||
}
|
||||
public DefaultedList<ItemStack> getInventory() {
|
||||
return this.inventory;
|
||||
}
|
||||
|
||||
public int getSlotCount() {
|
||||
return this.slotCount;
|
||||
}
|
||||
public int getSlotCount() {
|
||||
return this.slotCount;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,85 +31,85 @@ import java.util.List;
|
|||
import java.util.Optional;
|
||||
|
||||
public class BaseBagItem extends TrinketItem {
|
||||
private static final String ITEMS_KEY = "Items";
|
||||
private static final String ITEMS_KEY = "Items";
|
||||
|
||||
private final int slots;
|
||||
private final BagType type;
|
||||
private final int slots;
|
||||
private final BagType type;
|
||||
|
||||
public BaseBagItem(Settings settings, int slots, BagType type) {
|
||||
super(settings);
|
||||
public BaseBagItem(Settings settings, int slots, BagType type) {
|
||||
super(settings);
|
||||
|
||||
if (type == BagType.SATCHEL && slots > ScoutUtil.MAX_SATCHEL_SLOTS) {
|
||||
throw new IllegalArgumentException("Satchel has too many slots.");
|
||||
}
|
||||
if (type == BagType.POUCH && slots > ScoutUtil.MAX_POUCH_SLOTS) {
|
||||
throw new IllegalArgumentException("Pouch has too many slots.");
|
||||
}
|
||||
if (type == BagType.SATCHEL && slots > ScoutUtil.MAX_SATCHEL_SLOTS) {
|
||||
throw new IllegalArgumentException("Satchel has too many slots.");
|
||||
}
|
||||
if (type == BagType.POUCH && slots > ScoutUtil.MAX_POUCH_SLOTS) {
|
||||
throw new IllegalArgumentException("Pouch has too many slots.");
|
||||
}
|
||||
|
||||
this.slots = slots;
|
||||
this.type = type;
|
||||
}
|
||||
this.slots = slots;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public int getSlotCount() {
|
||||
return this.slots;
|
||||
}
|
||||
public int getSlotCount() {
|
||||
return this.slots;
|
||||
}
|
||||
|
||||
public BagType getType() {
|
||||
return this.type;
|
||||
}
|
||||
public BagType getType() {
|
||||
return this.type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void appendTooltip(ItemStack stack, @Nullable World world, List<Text> tooltip, TooltipContext context) {
|
||||
super.appendTooltip(stack, world, tooltip, context);
|
||||
tooltip.add(Text.translatable("tooltip.scout.slots", Text.literal(String.valueOf(this.slots)).formatted(Formatting.BLUE)).formatted(Formatting.GRAY));
|
||||
}
|
||||
@Override
|
||||
public void appendTooltip(ItemStack stack, @Nullable World world, List<Text> tooltip, TooltipContext context) {
|
||||
super.appendTooltip(stack, world, tooltip, context);
|
||||
tooltip.add(Text.translatable("tooltip.scout.slots", Text.literal(String.valueOf(this.slots)).formatted(Formatting.BLUE)).formatted(Formatting.GRAY));
|
||||
}
|
||||
|
||||
public Inventory getInventory(ItemStack stack) {
|
||||
SimpleInventory inventory = new SimpleInventory(this.slots) {
|
||||
@Override
|
||||
public void markDirty() {
|
||||
stack.getOrCreateNbt().put(ITEMS_KEY, ScoutUtil.inventoryToTag(this));
|
||||
super.markDirty();
|
||||
}
|
||||
};
|
||||
public Inventory getInventory(ItemStack stack) {
|
||||
SimpleInventory inventory = new SimpleInventory(this.slots) {
|
||||
@Override
|
||||
public void markDirty() {
|
||||
stack.getOrCreateNbt().put(ITEMS_KEY, ScoutUtil.inventoryToTag(this));
|
||||
super.markDirty();
|
||||
}
|
||||
};
|
||||
|
||||
NbtCompound compound = stack.getOrCreateNbt();
|
||||
if (!compound.contains(ITEMS_KEY)) {
|
||||
compound.put(ITEMS_KEY, new NbtList());
|
||||
}
|
||||
NbtCompound compound = stack.getOrCreateNbt();
|
||||
if (!compound.contains(ITEMS_KEY)) {
|
||||
compound.put(ITEMS_KEY, new NbtList());
|
||||
}
|
||||
|
||||
NbtList items = compound.getList(ITEMS_KEY, 10);
|
||||
NbtList items = compound.getList(ITEMS_KEY, 10);
|
||||
|
||||
ScoutUtil.inventoryFromTag(items, inventory);
|
||||
ScoutUtil.inventoryFromTag(items, inventory);
|
||||
|
||||
return inventory;
|
||||
}
|
||||
return inventory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<TooltipData> getTooltipData(ItemStack stack) {
|
||||
DefaultedList<ItemStack> stacks = DefaultedList.of();
|
||||
Inventory inventory = getInventory(stack);
|
||||
@Override
|
||||
public Optional<TooltipData> getTooltipData(ItemStack stack) {
|
||||
DefaultedList<ItemStack> stacks = DefaultedList.of();
|
||||
Inventory inventory = getInventory(stack);
|
||||
|
||||
for (int i = 0; i < slots; i++) {
|
||||
stacks.add(inventory.getStack(i));
|
||||
}
|
||||
for (int i = 0; i < slots; i++) {
|
||||
stacks.add(inventory.getStack(i));
|
||||
}
|
||||
|
||||
if (stacks.stream().allMatch(ItemStack::isEmpty)) return Optional.empty();
|
||||
if (stacks.stream().allMatch(ItemStack::isEmpty)) return Optional.empty();
|
||||
|
||||
return Optional.of(new BagTooltipData(stacks, slots));
|
||||
}
|
||||
return Optional.of(new BagTooltipData(stacks, slots));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEquip(ItemStack stack, SlotReference slotRef, LivingEntity entity) {
|
||||
if (entity instanceof PlayerEntity player)
|
||||
updateSlots(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUnequip(ItemStack stack, SlotReference slotRef, LivingEntity entity) {
|
||||
@Override
|
||||
public void onEquip(ItemStack stack, SlotReference slotRef, LivingEntity entity) {
|
||||
if (entity instanceof PlayerEntity player)
|
||||
updateSlots(player);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUnequip(ItemStack stack, SlotReference slotRef, LivingEntity entity) {
|
||||
if (entity instanceof PlayerEntity player)
|
||||
updateSlots(player);
|
||||
}
|
||||
|
||||
private void updateSlots(PlayerEntity player) {
|
||||
ScoutScreenHandler handler = (ScoutScreenHandler) player.playerScreenHandler;
|
||||
|
@ -177,37 +177,37 @@ public class BaseBagItem extends TrinketItem {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canEquip(ItemStack stack, SlotReference slot, LivingEntity entity) {
|
||||
Item item = stack.getItem();
|
||||
@Override
|
||||
public boolean canEquip(ItemStack stack, SlotReference slot, LivingEntity entity) {
|
||||
Item item = stack.getItem();
|
||||
|
||||
ItemStack slotStack = slot.inventory().getStack(slot.index());
|
||||
Item slotItem = slotStack.getItem();
|
||||
ItemStack slotStack = slot.inventory().getStack(slot.index());
|
||||
Item slotItem = slotStack.getItem();
|
||||
|
||||
if (slotItem instanceof BaseBagItem) {
|
||||
if (((BaseBagItem) item).getType() == BagType.SATCHEL) {
|
||||
if (((BaseBagItem) slotItem).getType() == BagType.SATCHEL) {
|
||||
return true;
|
||||
} else {
|
||||
return ScoutUtil.findBagItem((PlayerEntity) entity, BagType.SATCHEL, false).isEmpty();
|
||||
}
|
||||
} else if (((BaseBagItem) item).getType() == BagType.POUCH) {
|
||||
if (((BaseBagItem) slotItem).getType() == BagType.POUCH) {
|
||||
return true;
|
||||
} else {
|
||||
return ScoutUtil.findBagItem((PlayerEntity) entity, BagType.POUCH, true).isEmpty();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (((BaseBagItem) item).getType() == BagType.SATCHEL) {
|
||||
return ScoutUtil.findBagItem((PlayerEntity) entity, BagType.SATCHEL, false).isEmpty();
|
||||
} else if (((BaseBagItem) item).getType() == BagType.POUCH) {
|
||||
return ScoutUtil.findBagItem((PlayerEntity) entity, BagType.POUCH, true).isEmpty();
|
||||
}
|
||||
}
|
||||
if (slotItem instanceof BaseBagItem) {
|
||||
if (((BaseBagItem) item).getType() == BagType.SATCHEL) {
|
||||
if (((BaseBagItem) slotItem).getType() == BagType.SATCHEL) {
|
||||
return true;
|
||||
} else {
|
||||
return ScoutUtil.findBagItem((PlayerEntity) entity, BagType.SATCHEL, false).isEmpty();
|
||||
}
|
||||
} else if (((BaseBagItem) item).getType() == BagType.POUCH) {
|
||||
if (((BaseBagItem) slotItem).getType() == BagType.POUCH) {
|
||||
return true;
|
||||
} else {
|
||||
return ScoutUtil.findBagItem((PlayerEntity) entity, BagType.POUCH, true).isEmpty();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (((BaseBagItem) item).getType() == BagType.SATCHEL) {
|
||||
return ScoutUtil.findBagItem((PlayerEntity) entity, BagType.SATCHEL, false).isEmpty();
|
||||
} else if (((BaseBagItem) item).getType() == BagType.POUCH) {
|
||||
return ScoutUtil.findBagItem((PlayerEntity) entity, BagType.POUCH, true).isEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void inventoryTick(ItemStack stack, World world, Entity entity, int slot, boolean selected) {
|
||||
|
@ -219,8 +219,8 @@ public class BaseBagItem extends TrinketItem {
|
|||
}
|
||||
}
|
||||
|
||||
public enum BagType {
|
||||
SATCHEL,
|
||||
POUCH
|
||||
}
|
||||
public enum BagType {
|
||||
SATCHEL,
|
||||
POUCH
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,14 +12,14 @@ import org.spongepowered.asm.mixin.injection.Inject;
|
|||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
|
||||
import pm.c7.scout.ScoutUtil;
|
||||
import pm.c7.scout.config.ScoutConfigHandler;
|
||||
import pm.c7.scout.ScoutConfig;
|
||||
import pm.c7.scout.item.BaseBagItem;
|
||||
|
||||
@Mixin(BowItem.class)
|
||||
public class BowItemMixin {
|
||||
@Inject(method = "onStoppedUsing", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/World;playSound(Lnet/minecraft/entity/player/PlayerEntity;DDDLnet/minecraft/sound/SoundEvent;Lnet/minecraft/sound/SoundCategory;FF)V"), locals = LocalCapture.CAPTURE_FAILHARD)
|
||||
public void scout$arrowsFromBags(ItemStack stack, World world, LivingEntity user, int remainingUseTicks, CallbackInfo ci, PlayerEntity playerEntity, boolean bl, ItemStack itemStack, int maxTime, float f) {
|
||||
if ((boolean) ScoutConfigHandler.getConfigValue("useArrows").value()) {
|
||||
if (ScoutConfig.CONFIG.useArrows.value()) {
|
||||
boolean infinity = bl && itemStack.isOf(Items.ARROW);
|
||||
boolean hasRan = false;
|
||||
|
||||
|
|
|
@ -9,15 +9,13 @@ import pm.c7.scout.item.BaseBagItem;
|
|||
|
||||
@Mixin(ItemStack.class)
|
||||
public class ItemStackMixin {
|
||||
|
||||
// Trinkets calls areEqual to check whether it should unequip old and equip new (https://github.com/emilyploszaj/trinkets/blob/7cb63ce0/src/main/java/dev/emi/trinkets/mixin/LivingEntityMixin.java#L155-L158)
|
||||
// Excluding ourselves from this check to force unequip/equip when switching bag items fixes a duplication bug
|
||||
// Gross and hacky but oh well, can't mixin mixins.
|
||||
@Inject(method = "areEqual", at = @At("HEAD"), cancellable = true)
|
||||
private void scout$grossTrinketsEquipFix(ItemStack newStack, CallbackInfoReturnable<Boolean> callbackInfo) {
|
||||
ItemStack self = (ItemStack) (Object) this;
|
||||
if (self.getItem() instanceof BaseBagItem && newStack.getItem() instanceof BaseBagItem) {
|
||||
callbackInfo.setReturnValue(false);
|
||||
}
|
||||
}
|
||||
// Trinkets calls areEqual to check whether it should unequip old and equip new (https://github.com/emilyploszaj/trinkets/blob/7cb63ce0/src/main/java/dev/emi/trinkets/mixin/LivingEntityMixin.java#L155-L158)
|
||||
// Excluding ourselves from this check to force unequip/equip when switching bag items fixes a duplication bug
|
||||
// Gross and hacky but oh well, can't mixin mixins.
|
||||
@Inject(method = "areEqual", at = @At("HEAD"), cancellable = true)
|
||||
private static void scout$grossTrinketsEquipFix(ItemStack stack, ItemStack otherStack, CallbackInfoReturnable<Boolean> callbackInfo) {
|
||||
if (stack.getItem() instanceof BaseBagItem && otherStack.getItem() instanceof BaseBagItem) {
|
||||
callbackInfo.setReturnValue(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ import org.spongepowered.asm.mixin.injection.Inject;
|
|||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
|
||||
import pm.c7.scout.ScoutUtil;
|
||||
import pm.c7.scout.config.ScoutConfigHandler;
|
||||
import pm.c7.scout.ScoutConfig;
|
||||
import pm.c7.scout.item.BaseBagItem;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
|
@ -17,7 +17,7 @@ import java.util.function.Predicate;
|
|||
public class PlayerEntityMixin {
|
||||
@Inject(method = "getArrowType", at = @At(value = "INVOKE_ASSIGN", target = "Lnet/minecraft/item/RangedWeaponItem;getProjectiles()Ljava/util/function/Predicate;"), locals = LocalCapture.CAPTURE_FAILHARD, cancellable = true)
|
||||
public void scout$arrowsFromBags(ItemStack stack, CallbackInfoReturnable<ItemStack> cir, Predicate<ItemStack> predicate, ItemStack itemStack) {
|
||||
if ((boolean) ScoutConfigHandler.getConfigValue("useArrows").value()) {
|
||||
if (ScoutConfig.CONFIG.useArrows.value()) {
|
||||
var self = (PlayerEntity) (Object) this;
|
||||
var leftPouch = ScoutUtil.findBagItem(self, BaseBagItem.BagType.POUCH, false);
|
||||
var rightPouch = ScoutUtil.findBagItem(self, BaseBagItem.BagType.POUCH, true);
|
||||
|
|
|
@ -12,88 +12,90 @@ import org.spongepowered.asm.mixin.injection.Inject;
|
|||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import pm.c7.scout.ScoutScreenHandler;
|
||||
import pm.c7.scout.ScoutUtil;
|
||||
import pm.c7.scout.ScoutMixin.Transformer;
|
||||
import pm.c7.scout.screen.BagSlot;
|
||||
|
||||
@Mixin(value = PlayerScreenHandler.class, priority = 950)
|
||||
@Transformer(PlayerScreenHandlerTransformer.class)
|
||||
public abstract class PlayerScreenHandlerMixin extends ScreenHandler implements ScoutScreenHandler {
|
||||
protected PlayerScreenHandlerMixin() {
|
||||
super(null, 0);
|
||||
}
|
||||
protected PlayerScreenHandlerMixin() {
|
||||
super(null, 0);
|
||||
}
|
||||
|
||||
@Unique
|
||||
public final DefaultedList<BagSlot> scout$satchelSlots = DefaultedList.ofSize(ScoutUtil.MAX_SATCHEL_SLOTS);
|
||||
@Unique
|
||||
public final DefaultedList<BagSlot> scout$leftPouchSlots = DefaultedList.ofSize(ScoutUtil.MAX_POUCH_SLOTS);
|
||||
@Unique
|
||||
public final DefaultedList<BagSlot> scout$rightPouchSlots = DefaultedList.ofSize(ScoutUtil.MAX_POUCH_SLOTS);
|
||||
@Unique
|
||||
public final DefaultedList<BagSlot> scout$satchelSlots = DefaultedList.ofSize(ScoutUtil.MAX_SATCHEL_SLOTS);
|
||||
@Unique
|
||||
public final DefaultedList<BagSlot> scout$leftPouchSlots = DefaultedList.ofSize(ScoutUtil.MAX_POUCH_SLOTS);
|
||||
@Unique
|
||||
public final DefaultedList<BagSlot> scout$rightPouchSlots = DefaultedList.ofSize(ScoutUtil.MAX_POUCH_SLOTS);
|
||||
|
||||
@Inject(method = "<init>", at = @At("RETURN"))
|
||||
private void scout$addSlots(PlayerInventory inventory, boolean onServer, PlayerEntity owner, CallbackInfo callbackInfo) {
|
||||
// satchel
|
||||
int x = 8;
|
||||
int y = 168;
|
||||
@Inject(method = "<init>", at = @At("RETURN"))
|
||||
private void scout$addSlots(PlayerInventory inventory, boolean onServer, PlayerEntity owner, CallbackInfo callbackInfo) {
|
||||
// satchel
|
||||
int x = 8;
|
||||
int y = 168;
|
||||
|
||||
for (int i = 0; i < ScoutUtil.MAX_SATCHEL_SLOTS; i++) {
|
||||
if (i % 9 == 0) {
|
||||
x = 8;
|
||||
}
|
||||
for (int i = 0; i < ScoutUtil.MAX_SATCHEL_SLOTS; i++) {
|
||||
if (i % 9 == 0) {
|
||||
x = 8;
|
||||
}
|
||||
|
||||
BagSlot slot = new BagSlot(i, x, y);
|
||||
BagSlot slot = new BagSlot(i, x, y);
|
||||
slot.id = ScoutUtil.SATCHEL_SLOT_START - i;
|
||||
scout$satchelSlots.add(slot);
|
||||
|
||||
x += 18;
|
||||
x += 18;
|
||||
|
||||
if ((i + 1) % 9 == 0) {
|
||||
y += 18;
|
||||
}
|
||||
}
|
||||
if ((i + 1) % 9 == 0) {
|
||||
y += 18;
|
||||
}
|
||||
}
|
||||
|
||||
// left pouch
|
||||
x = 8;
|
||||
y = 66;
|
||||
// left pouch
|
||||
x = 8;
|
||||
y = 66;
|
||||
|
||||
for (int i = 0; i < ScoutUtil.MAX_POUCH_SLOTS; i++) {
|
||||
if (i % 3 == 0) {
|
||||
x -= 18;
|
||||
y += 54;
|
||||
}
|
||||
for (int i = 0; i < ScoutUtil.MAX_POUCH_SLOTS; i++) {
|
||||
if (i % 3 == 0) {
|
||||
x -= 18;
|
||||
y += 54;
|
||||
}
|
||||
|
||||
BagSlot slot = new BagSlot(i, x, y);
|
||||
BagSlot slot = new BagSlot(i, x, y);
|
||||
slot.id = ScoutUtil.LEFT_POUCH_SLOT_START - i;
|
||||
scout$leftPouchSlots.add(slot);
|
||||
|
||||
y -= 18;
|
||||
}
|
||||
y -= 18;
|
||||
}
|
||||
|
||||
// right pouch
|
||||
x = 152;
|
||||
y = 66;
|
||||
// right pouch
|
||||
x = 152;
|
||||
y = 66;
|
||||
|
||||
for (int i = 0; i < ScoutUtil.MAX_POUCH_SLOTS; i++) {
|
||||
if (i % 3 == 0) {
|
||||
x += 18;
|
||||
y += 54;
|
||||
}
|
||||
for (int i = 0; i < ScoutUtil.MAX_POUCH_SLOTS; i++) {
|
||||
if (i % 3 == 0) {
|
||||
x += 18;
|
||||
y += 54;
|
||||
}
|
||||
|
||||
BagSlot slot = new BagSlot(i, x, y);
|
||||
BagSlot slot = new BagSlot(i, x, y);
|
||||
slot.id = ScoutUtil.RIGHT_POUCH_SLOT_START - i;
|
||||
scout$rightPouchSlots.add(slot);
|
||||
|
||||
y -= 18;
|
||||
}
|
||||
}
|
||||
y -= 18;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final DefaultedList<BagSlot> scout$getSatchelSlots() {
|
||||
return scout$satchelSlots;
|
||||
}
|
||||
@Override
|
||||
public final DefaultedList<BagSlot> scout$getLeftPouchSlots() {
|
||||
return scout$leftPouchSlots;
|
||||
}
|
||||
@Override
|
||||
public final DefaultedList<BagSlot> scout$getRightPouchSlots() {
|
||||
return scout$rightPouchSlots;
|
||||
}
|
||||
@Override
|
||||
public final DefaultedList<BagSlot> scout$getSatchelSlots() {
|
||||
return scout$satchelSlots;
|
||||
}
|
||||
@Override
|
||||
public final DefaultedList<BagSlot> scout$getLeftPouchSlots() {
|
||||
return scout$leftPouchSlots;
|
||||
}
|
||||
@Override
|
||||
public final DefaultedList<BagSlot> scout$getRightPouchSlots() {
|
||||
return scout$rightPouchSlots;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
package pm.c7.scout.mixin;
|
||||
|
||||
import org.objectweb.asm.tree.*;
|
||||
import org.quiltmc.loader.api.QuiltLoader;
|
||||
|
||||
import pm.c7.scout.mixinsupport.ClassNodeTransformer;
|
||||
|
||||
import static org.objectweb.asm.Opcodes.*;
|
||||
|
||||
public class PlayerScreenHandlerTransformer implements ClassNodeTransformer {
|
||||
@Override
|
||||
public void transform(String name, ClassNode node) {
|
||||
var resolver = QuiltLoader.getMappingResolver();
|
||||
var namespace = "intermediary";
|
||||
|
||||
var LPlayerScreenHandler = L(slash(name));
|
||||
|
||||
var quickMove = resolver.mapMethodName(namespace, name, "method_7601", "(Lnet/minecraft/class_1657;I)Lnet/minecraft/class_1799;");
|
||||
|
||||
var Slot = slash(resolver.mapClassName(namespace, "net.minecraft.class_1735"));
|
||||
var LSlot = L(Slot);
|
||||
|
||||
var DefaultedList = slash(resolver.mapClassName(namespace, "net.minecraft.class_2371"));
|
||||
|
||||
for (var mn : node.methods) {
|
||||
// that other comment was a half truth, you can transform mixins :^)
|
||||
if (mn.name.endsWith("trinkets$quickMove") || mn.name.equals(quickMove)) {
|
||||
for (var insn : mn.instructions) {
|
||||
if (insn instanceof VarInsnNode vin) {
|
||||
if (vin.getOpcode() == ASTORE && vin.var == 4) {
|
||||
if (vin.getPrevious() instanceof TypeInsnNode prevInsn && prevInsn.getOpcode() == CHECKCAST && prevInsn.desc.equals(Slot)) {
|
||||
if (prevInsn.getPrevious() instanceof MethodInsnNode prevPrevInsn && prevPrevInsn.getOpcode() == INVOKEVIRTUAL) {
|
||||
if(prevPrevInsn.owner.equals(DefaultedList)) {
|
||||
LabelNode LnotBag = new LabelNode();
|
||||
LabelNode Lend = new LabelNode();
|
||||
mn.instructions.insertBefore(prevPrevInsn.getPrevious().getPrevious().getPrevious(), insns(
|
||||
ILOAD(2),
|
||||
INVOKESTATIC("pm/c7/scout/ScoutUtil", "isBagSlot", "(I)Z"),
|
||||
IFEQ(LnotBag),
|
||||
ILOAD(2),
|
||||
ALOAD(0),
|
||||
INVOKESTATIC("pm/c7/scout/ScoutUtil", "getBagSlot", "(I" + LPlayerScreenHandler + ")" + LSlot),
|
||||
CHECKCAST(Slot),
|
||||
ASTORE(vin.var),
|
||||
GOTO(Lend),
|
||||
LnotBag
|
||||
));
|
||||
mn.instructions.insert(vin, insns(
|
||||
Lend
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String slash(String clazz) {
|
||||
return clazz.replaceAll("\\.", "/");
|
||||
}
|
||||
|
||||
private String L(String clazz) {
|
||||
return "L" + clazz + ";";
|
||||
}
|
||||
|
||||
private InsnList insns(AbstractInsnNode... insns) {
|
||||
var li = new InsnList();
|
||||
for (var i : insns) li.add(i);
|
||||
return li;
|
||||
}
|
||||
private static VarInsnNode ILOAD(int v) {
|
||||
return new VarInsnNode(ILOAD, v);
|
||||
}
|
||||
private static MethodInsnNode INVOKESTATIC(String owner, String name, String desc) {
|
||||
return new MethodInsnNode(INVOKESTATIC, owner, name, desc);
|
||||
}
|
||||
private static JumpInsnNode IFEQ(LabelNode v) {
|
||||
return new JumpInsnNode(IFEQ, v);
|
||||
}
|
||||
private static VarInsnNode ALOAD(int v) {
|
||||
return new VarInsnNode(ALOAD, v);
|
||||
}
|
||||
private static VarInsnNode ASTORE(int v) {
|
||||
return new VarInsnNode(ASTORE, v);
|
||||
}
|
||||
private static TypeInsnNode CHECKCAST(String desc) {
|
||||
return new TypeInsnNode(CHECKCAST, desc);
|
||||
}
|
||||
private static JumpInsnNode GOTO(LabelNode v) {
|
||||
return new JumpInsnNode(GOTO, v);
|
||||
}
|
||||
}
|
|
@ -6,18 +6,21 @@ import net.minecraft.item.ItemStack;
|
|||
import net.minecraft.screen.ScreenHandler;
|
||||
import net.minecraft.screen.slot.Slot;
|
||||
import net.minecraft.screen.slot.SlotActionType;
|
||||
import net.minecraft.util.collection.DefaultedList;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
|
||||
import pm.c7.scout.ScoutMixin.Transformer;
|
||||
import pm.c7.scout.ScoutUtil;
|
||||
|
||||
@Mixin(ScreenHandler.class)
|
||||
@Mixin(value = ScreenHandler.class, priority = 950)
|
||||
@Transformer(ScreenHandlerTransformer.class)
|
||||
public abstract class ScreenHandlerMixin {
|
||||
@Inject(method = "getSlot", at = @At("HEAD"), cancellable = true)
|
||||
|
@ -55,6 +58,15 @@ public abstract class ScreenHandlerMixin {
|
|||
}
|
||||
}
|
||||
|
||||
@Redirect(method = "internalOnSlotClick", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/collection/DefaultedList;get(I)Ljava/lang/Object;", ordinal = 5))
|
||||
public Object scout$fixSlotIndexing(DefaultedList<Slot> self, int index, int slotIndex, int button, SlotActionType actionType, PlayerEntity player) {
|
||||
if (ScoutUtil.isBagSlot(index)) {
|
||||
return ScoutUtil.getBagSlot(index, player.playerScreenHandler);
|
||||
} else {
|
||||
return self.get(index);
|
||||
}
|
||||
}
|
||||
|
||||
@Shadow
|
||||
public static boolean canInsertItemIntoSlot(@Nullable Slot slot, ItemStack stack, boolean allowOverflow) {
|
||||
return false;
|
||||
|
|
|
@ -2,58 +2,91 @@ package pm.c7.scout.mixin;
|
|||
|
||||
import org.objectweb.asm.tree.*;
|
||||
import org.quiltmc.loader.api.QuiltLoader;
|
||||
|
||||
import pm.c7.scout.mixinsupport.ClassNodeTransformer;
|
||||
|
||||
import static org.objectweb.asm.Opcodes.*;
|
||||
|
||||
public class ScreenHandlerTransformer implements ClassNodeTransformer {
|
||||
//private static final Logger LOGGER = LoggerFactory.getLogger("Scout:ScreenHandlerTransformer");
|
||||
|
||||
@Override
|
||||
public void transform(String name, ClassNode node) {
|
||||
var internalOnSlotClick = "m_nqfgpzfl";
|
||||
var insertItem = "m_jpjdgbxy";
|
||||
var resolver = QuiltLoader.getMappingResolver();
|
||||
var namespace = "intermediary";
|
||||
|
||||
var PlayerEntity = "net/minecraft/unmapped/C_jzrpycqo";
|
||||
var playerScreenHandler = "f_xvlfpipb";
|
||||
|
||||
var PlayerScreenHandler = "net/minecraft/unmapped/C_wgehrbdx";
|
||||
var Slot = "net/minecraft/unmapped/C_nhvqfffd";
|
||||
var DefaultedList = "net/minecraft/unmapped/C_rnrfftze";
|
||||
|
||||
if (QuiltLoader.isDevelopmentEnvironment()) {
|
||||
internalOnSlotClick = "internalOnSlotClick";
|
||||
insertItem = "insertItem";
|
||||
|
||||
PlayerEntity = "net/minecraft/entity/player/PlayerEntity";
|
||||
playerScreenHandler = "playerScreenHandler";
|
||||
|
||||
PlayerScreenHandler = "net/minecraft/screen/PlayerScreenHandler";
|
||||
Slot = "net/minecraft/screen/slot/Slot";
|
||||
DefaultedList = "net/minecraft/util/collection/DefaultedList";
|
||||
}
|
||||
var internalOnSlotClick = resolver.mapMethodName(namespace, name, "method_30010", "(IILnet/minecraft/class_1713;Lnet/minecraft/class_1657;)V");
|
||||
|
||||
var PlayerEntity = resolver.mapClassName(namespace, "net.minecraft.class_1657");
|
||||
var PlayerScreenHandler = slash(resolver.mapClassName(namespace, "net.minecraft.class_1723"));
|
||||
var LPlayerScreenHandler = L(PlayerScreenHandler);
|
||||
String playerScreenHandler = resolver.mapFieldName(namespace, PlayerEntity, "field_7498", LPlayerScreenHandler);
|
||||
PlayerEntity = slash(PlayerEntity);
|
||||
|
||||
var Slot = slash(resolver.mapClassName(namespace, "net.minecraft.class_1735"));
|
||||
var LSlot = L(Slot);
|
||||
|
||||
var DefaultedList = slash(resolver.mapClassName(namespace, "net.minecraft.class_2371"));
|
||||
//var LDefaultedList = L(DefaultedList);
|
||||
|
||||
//var slots = resolver.mapFieldName(namespace, name, "field_7761", LDefaultedList);
|
||||
|
||||
int ordinal = 0;
|
||||
|
||||
for (var mn : node.methods) {
|
||||
if (mn.name.equals(internalOnSlotClick)) {
|
||||
for (var insn : mn.instructions) {
|
||||
if (insn instanceof VarInsnNode vin) {
|
||||
if (vin.getOpcode() == ILOAD && vin.var == 1) {
|
||||
if (insn.getNext() instanceof JumpInsnNode nextInsn && nextInsn.getOpcode() == IFGE) {
|
||||
// `if (slotIndex < 0) return` -> `if (slotIndex < 0 && !isBagSlot(slotIndex)) return`
|
||||
var jumpTo = nextInsn.label;
|
||||
mn.instructions.insert(nextInsn, insns(
|
||||
ILOAD(1),
|
||||
INVOKESTATIC("pm/c7/scout/ScoutUtil", "isBagSlot", "(I)Z"),
|
||||
IFNE(jumpTo)
|
||||
ILOAD(1),
|
||||
INVOKESTATIC("pm/c7/scout/ScoutUtil", "isBagSlot", "(I)Z"),
|
||||
IFNE(jumpTo)
|
||||
));
|
||||
} else if (insn.getPrevious() instanceof JumpInsnNode prevInsn && prevInsn.getOpcode() == IFEQ && insn.getNext() instanceof JumpInsnNode nextInsn && nextInsn.getOpcode() == IFLT) {
|
||||
// skip creative duping, it uses same signature and i dont feel like overcomplicating the check
|
||||
if (ordinal != 1) {
|
||||
ordinal++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// fix dropping from bags not working
|
||||
LabelNode Lcheck = new LabelNode();
|
||||
nextInsn.label = Lcheck;
|
||||
nextInsn.setOpcode(IFGE);
|
||||
mn.instructions.insert(nextInsn, insns(
|
||||
ILOAD(1),
|
||||
INVOKESTATIC("pm/c7/scout/ScoutUtil", "isBagSlot", "(I)Z"),
|
||||
IFNE(Lcheck),
|
||||
RETURN(),
|
||||
Lcheck
|
||||
));
|
||||
}
|
||||
} else if (vin.getOpcode() == ASTORE && (vin.var == 6 || vin.var == 7)) {
|
||||
// fix most but not all calls to `slots.get`
|
||||
if (vin.getPrevious() instanceof TypeInsnNode prevInsn && prevInsn.getOpcode() == CHECKCAST && prevInsn.desc.equals(Slot)) {
|
||||
if (prevInsn.getPrevious() instanceof MethodInsnNode prevPrevInsn && prevPrevInsn.getOpcode() == INVOKEVIRTUAL) {
|
||||
if(prevPrevInsn.owner.equals(DefaultedList)) {
|
||||
LabelNode LnotBag = new LabelNode();
|
||||
LabelNode Lend = new LabelNode();
|
||||
mn.instructions.insertBefore(prevPrevInsn.getPrevious().getPrevious().getPrevious(), insns(
|
||||
var insertPoint = prevPrevInsn.getPrevious();
|
||||
|
||||
if (insertPoint.getOpcode() == ILOAD) {
|
||||
var beforeInsert = insertPoint.getPrevious();
|
||||
|
||||
if (beforeInsert != null && beforeInsert.getPrevious() != null){
|
||||
if (beforeInsert.getOpcode() == GETFIELD && beforeInsert.getPrevious().getOpcode() == ALOAD) {
|
||||
insertPoint = beforeInsert.getPrevious();
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
LabelNode LnotBag = new LabelNode();
|
||||
LabelNode Lend = (LabelNode) vin.getNext();
|
||||
|
||||
mn.instructions.insertBefore(insertPoint, insns(
|
||||
ILOAD(1),
|
||||
INVOKESTATIC("pm/c7/scout/ScoutUtil", "isBagSlot", "(I)Z"),
|
||||
IFEQ(LnotBag),
|
||||
|
@ -65,9 +98,44 @@ public class ScreenHandlerTransformer implements ClassNodeTransformer {
|
|||
ASTORE(vin.var),
|
||||
GOTO(Lend),
|
||||
LnotBag
|
||||
));
|
||||
mn.instructions.insert(vin, insns(
|
||||
Lend
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (mn.name.endsWith("debugify$handleCtrlQCrafting")) { // ughghghhghghghghgh
|
||||
for (var insn : mn.instructions) {
|
||||
if (insn instanceof VarInsnNode vin && vin.getOpcode() == ASTORE && vin.var == 6) {
|
||||
if (vin.getPrevious() instanceof TypeInsnNode prevInsn && prevInsn.getOpcode() == CHECKCAST && prevInsn.desc.equals(Slot)) {
|
||||
if (prevInsn.getPrevious() instanceof MethodInsnNode prevPrevInsn && prevPrevInsn.getOpcode() == INVOKEVIRTUAL) {
|
||||
if(prevPrevInsn.owner.equals(DefaultedList)) {
|
||||
var insertPoint = prevPrevInsn.getPrevious();
|
||||
|
||||
if (insertPoint.getOpcode() == ILOAD) {
|
||||
var beforeInsert = insertPoint.getPrevious();
|
||||
|
||||
if (beforeInsert != null && beforeInsert.getPrevious() != null && beforeInsert.getOpcode() == GETFIELD && beforeInsert.getPrevious().getOpcode() == ALOAD) {
|
||||
insertPoint = beforeInsert.getPrevious();
|
||||
}
|
||||
|
||||
LabelNode LnotBag = new LabelNode();
|
||||
LabelNode Lend = (LabelNode) vin.getNext();
|
||||
|
||||
mn.instructions.insertBefore(insertPoint, insns(
|
||||
ILOAD(1),
|
||||
INVOKESTATIC("pm/c7/scout/ScoutUtil", "isBagSlot", "(I)Z"),
|
||||
IFEQ(LnotBag),
|
||||
ILOAD(1),
|
||||
ALOAD(4),
|
||||
GETFIELD(PlayerEntity, playerScreenHandler, LPlayerScreenHandler),
|
||||
INVOKESTATIC("pm/c7/scout/ScoutUtil", "getBagSlot", "(I" + LPlayerScreenHandler + ")" + LSlot),
|
||||
CHECKCAST(Slot),
|
||||
ASTORE(vin.var),
|
||||
GOTO(Lend),
|
||||
LnotBag
|
||||
));
|
||||
}
|
||||
}
|
||||
|
@ -75,44 +143,84 @@ public class ScreenHandlerTransformer implements ClassNodeTransformer {
|
|||
}
|
||||
}
|
||||
}
|
||||
}/* else if (mn.name.equals(insertItem)) {
|
||||
for (var insn : mn.instructions) {
|
||||
if (insn instanceof VarInsnNode vin && vin.getOpcode() == ASTORE && vin.var == 7) {
|
||||
if (vin.getPrevious() instanceof TypeInsnNode prevInsn && prevInsn.getOpcode() == CHECKCAST && prevInsn.desc.equals(Slot)) {
|
||||
if (prevInsn.getPrevious() instanceof MethodInsnNode prevPrevInsn && prevPrevInsn.getOpcode() == INVOKEVIRTUAL) {
|
||||
if(prevPrevInsn.owner.equals(DefaultedList)) {
|
||||
LabelNode LnotBag = new LabelNode();
|
||||
LabelNode LpastSlot = new LabelNode();
|
||||
mn.instructions.insertBefore(prevPrevInsn.getPrevious().getPrevious().getPrevious(), insns(
|
||||
INVOKESTATIC("pm/c7/scout/ScoutUtil", "getPlayerScreenHandler", "()" + LPlayerScreenHandler),
|
||||
ASTORE(20),
|
||||
ALOAD(20),
|
||||
IFNULL(LpastSlot),
|
||||
ILOAD(6),
|
||||
INVOKESTATIC("pm/c7/scout/ScoutUtil", "isBagSlot", "(I)Z"),
|
||||
IFEQ(LnotBag),
|
||||
ILOAD(6),
|
||||
ALOAD(20),
|
||||
INVOKESTATIC("pm/c7/scout/ScoutUtil", "getBagSlot", "(I" + LPlayerScreenHandler + ")" + LSlot),
|
||||
CHECKCAST(Slot),
|
||||
ASTORE(vin.var),
|
||||
LnotBag,
|
||||
ILOAD(6),
|
||||
INVOKESTATIC("pm/c7/scout/ScoutUtil", "isBagSlot", "(I)Z"),
|
||||
IFNE(LpastSlot)
|
||||
));
|
||||
mn.instructions.insert(vin, insns(
|
||||
LpastSlot
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// debug, keeping here for future use
|
||||
/*private static List<Field> allOpcodes = Arrays.asList(Opcodes.class.getFields());
|
||||
|
||||
private String getOpcodeName(int v) {
|
||||
Optional<Field> opcode = allOpcodes.stream()
|
||||
.filter(f -> f.getType() == int.class)
|
||||
.filter(f -> {
|
||||
if (f.getName().startsWith("F_")) {
|
||||
return f.getName().equals("F_NEW");
|
||||
} else {
|
||||
return !f.getName().startsWith("V")
|
||||
&& !f.getName().startsWith("ASM")
|
||||
&& !f.getName().startsWith("SOURCE_")
|
||||
&& !f.getName().startsWith("ACC_")
|
||||
&& !f.getName().startsWith("H_")
|
||||
&& !f.getName().startsWith("T_");
|
||||
}
|
||||
})
|
||||
.filter(f -> {
|
||||
try {
|
||||
var field = f.get(Opcodes.class);
|
||||
//LOGGER.info("{} {} | {}", f.getName(), f.getType(), field);
|
||||
return field.equals(v);
|
||||
} catch (IllegalArgumentException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
} catch (IllegalAccessException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
})
|
||||
.findFirst();
|
||||
|
||||
if (opcode.isEmpty()) {
|
||||
return "<unknown: " + String.valueOf(v) + ">";
|
||||
}
|
||||
|
||||
return opcode.get().getName();
|
||||
}
|
||||
|
||||
private void printNode(AbstractInsnNode node) {
|
||||
var name = getOpcodeName(node.getOpcode());
|
||||
String val = "";
|
||||
|
||||
if (node instanceof VarInsnNode vin) {
|
||||
val = String.valueOf(vin.var);
|
||||
} else if(node instanceof FieldInsnNode fin) {
|
||||
val = fin.owner + "." + fin.name + ":" + fin.desc;
|
||||
} else if(node instanceof MethodInsnNode min) {
|
||||
val = min.owner + "." + min.name + ":" + min.desc;
|
||||
} else if (node instanceof TypeInsnNode tin) {
|
||||
val = tin.desc;
|
||||
} else if (node instanceof JumpInsnNode jin) {
|
||||
val = jin.label.toString();
|
||||
} else if (node instanceof LabelNode label) {
|
||||
name = "L";
|
||||
val = label.toString();
|
||||
}
|
||||
|
||||
LOGGER.info("{} {}", name, val);
|
||||
}
|
||||
|
||||
private void dumpInstructions(InsnList insns, int start, int end) {
|
||||
for (var i = start; i < end + 1; i++) {
|
||||
printNode(insns.get(i));
|
||||
}
|
||||
}*/
|
||||
|
||||
private String slash(String clazz) {
|
||||
return clazz.replaceAll("\\.", "/");
|
||||
}
|
||||
|
||||
private String L(String clazz) {
|
||||
return "L" + clazz + ";";
|
||||
}
|
||||
|
@ -122,34 +230,34 @@ public class ScreenHandlerTransformer implements ClassNodeTransformer {
|
|||
for (var i : insns) li.add(i);
|
||||
return li;
|
||||
}
|
||||
private static VarInsnNode ILOAD(int var) {
|
||||
return new VarInsnNode(ILOAD, var);
|
||||
private static VarInsnNode ILOAD(int v) {
|
||||
return new VarInsnNode(ILOAD, v);
|
||||
}
|
||||
private static MethodInsnNode INVOKESTATIC(String owner, String name, String desc) {
|
||||
return new MethodInsnNode(INVOKESTATIC, owner, name, desc);
|
||||
}
|
||||
private static JumpInsnNode IFNE(LabelNode var) {
|
||||
return new JumpInsnNode(IFNE, var);
|
||||
private static JumpInsnNode IFNE(LabelNode v) {
|
||||
return new JumpInsnNode(IFNE, v);
|
||||
}
|
||||
private static JumpInsnNode IFEQ(LabelNode var) {
|
||||
return new JumpInsnNode(IFEQ, var);
|
||||
private static JumpInsnNode IFEQ(LabelNode v) {
|
||||
return new JumpInsnNode(IFEQ, v);
|
||||
}
|
||||
private static VarInsnNode ALOAD(int var) {
|
||||
return new VarInsnNode(ALOAD, var);
|
||||
private static VarInsnNode ALOAD(int v) {
|
||||
return new VarInsnNode(ALOAD, v);
|
||||
}
|
||||
private static VarInsnNode ASTORE(int var) {
|
||||
return new VarInsnNode(ASTORE, var);
|
||||
private static VarInsnNode ASTORE(int v) {
|
||||
return new VarInsnNode(ASTORE, v);
|
||||
}
|
||||
private static FieldInsnNode GETFIELD(String owner, String name, String desc) {
|
||||
return new FieldInsnNode(GETFIELD, owner, name, desc);
|
||||
}
|
||||
private static JumpInsnNode IFNULL(LabelNode var) {
|
||||
return new JumpInsnNode(IFNULL, var);
|
||||
}
|
||||
private static TypeInsnNode CHECKCAST(String desc) {
|
||||
return new TypeInsnNode(CHECKCAST, desc);
|
||||
}
|
||||
private static JumpInsnNode GOTO(LabelNode var) {
|
||||
return new JumpInsnNode(GOTO, var);
|
||||
private static JumpInsnNode GOTO(LabelNode v) {
|
||||
return new JumpInsnNode(GOTO, v);
|
||||
}
|
||||
private static InsnNode RETURN() {
|
||||
return new InsnNode(RETURN);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,10 +5,8 @@ import net.fabricmc.api.Environment;
|
|||
import net.minecraft.client.gui.screen.ingame.AbstractFurnaceScreen;
|
||||
import net.minecraft.client.gui.screen.ingame.HandledScreen;
|
||||
import net.minecraft.client.gui.screen.recipe.book.RecipeBookProvider;
|
||||
import net.minecraft.entity.player.PlayerInventory;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.screen.AbstractFurnaceScreenHandler;
|
||||
import net.minecraft.text.Text;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
|
|
|
@ -9,10 +9,10 @@ import org.spongepowered.asm.mixin.gen.Accessor;
|
|||
@Environment(EnvType.CLIENT)
|
||||
@Mixin(HandledScreen.class)
|
||||
public interface HandledScreenAccessor {
|
||||
@Accessor("x")
|
||||
int getX();
|
||||
@Accessor("y")
|
||||
int getY();
|
||||
@Accessor("x")
|
||||
int getX();
|
||||
@Accessor("y")
|
||||
int getY();
|
||||
@Accessor("backgroundWidth")
|
||||
int getBackgroundWidth();
|
||||
@Accessor("backgroundHeight")
|
||||
|
|
|
@ -3,14 +3,12 @@ package pm.c7.scout.mixin.client;
|
|||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.gui.GuiGraphics;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
import net.minecraft.client.gui.screen.ingame.GenericContainerScreen;
|
||||
import net.minecraft.client.gui.screen.ingame.HandledScreen;
|
||||
import net.minecraft.client.gui.screen.ingame.ScreenHandlerProvider;
|
||||
import net.minecraft.client.gui.screen.ingame.ShulkerBoxScreen;
|
||||
import net.minecraft.client.render.GameRenderer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.screen.ScreenHandler;
|
||||
import net.minecraft.screen.slot.Slot;
|
||||
|
@ -46,7 +44,7 @@ public abstract class HandledScreenMixin<T extends ScreenHandler> extends Screen
|
|||
@Shadow
|
||||
protected int backgroundHeight;
|
||||
|
||||
@Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screen/ingame/HandledScreen;drawBackground(Lnet/minecraft/client/util/math/MatrixStack;FII)V"))
|
||||
@Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screen/ingame/HandledScreen;drawBackground(Lnet/minecraft/client/gui/GuiGraphics;FII)V"))
|
||||
private void scout$drawSatchelRow(GuiGraphics graphics, int mouseX, int mouseY, float delta, CallbackInfo ci) {
|
||||
if (this.client != null && this.client.player != null && !ScoutUtil.isScreenBlacklisted(this)) {
|
||||
ItemStack backStack = ScoutUtil.findBagItem(this.client.player, BaseBagItem.BagType.SATCHEL, false);
|
||||
|
@ -272,13 +270,12 @@ public abstract class HandledScreenMixin<T extends ScreenHandler> extends Screen
|
|||
}
|
||||
}
|
||||
|
||||
@Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screen/ingame/HandledScreen;drawForeground(Lnet/minecraft/client/util/math/MatrixStack;II)V"))
|
||||
@Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screen/ingame/HandledScreen;drawForeground(Lnet/minecraft/client/gui/GuiGraphics;II)V"))
|
||||
public void scout$drawOurSlots(GuiGraphics graphics, int mouseX, int mouseY, float delta, CallbackInfo ci) {
|
||||
if (this.client != null && this.client.player != null && !ScoutUtil.isScreenBlacklisted(this)) {
|
||||
for (int i = ScoutUtil.SATCHEL_SLOT_START; i > ScoutUtil.BAG_SLOTS_END; i--) {
|
||||
BagSlot slot = (BagSlot) ScoutUtil.getBagSlot(i, this.client.player.playerScreenHandler);
|
||||
if (slot != null && slot.isEnabled()) {
|
||||
RenderSystem.setShader(GameRenderer::getPositionTexShader);
|
||||
this.drawSlot(graphics, slot);
|
||||
}
|
||||
|
||||
|
|
|
@ -2,25 +2,21 @@ package pm.c7.scout.mixin.client;
|
|||
|
||||
import org.objectweb.asm.tree.*;
|
||||
import org.quiltmc.loader.api.QuiltLoader;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import pm.c7.scout.mixinsupport.ClassNodeTransformer;
|
||||
|
||||
import static org.objectweb.asm.Opcodes.*;
|
||||
|
||||
public class HandledScreenTransformer implements ClassNodeTransformer {
|
||||
private static Logger LOGGER = LoggerFactory.getLogger("Scout:HandledScreenTransformer");
|
||||
@Override
|
||||
public void transform(String name, ClassNode node) {
|
||||
var drawSlot = "m_zioswvnu";
|
||||
var Slot = "net/minecraft/unmapped/C_nhvqfffd";
|
||||
var y = "f_tttqoodj";
|
||||
var resolver = QuiltLoader.getMappingResolver();
|
||||
var namespace = "intermediary";
|
||||
|
||||
if (QuiltLoader.isDevelopmentEnvironment()) {
|
||||
drawSlot = "drawSlot";
|
||||
Slot = "net/minecraft/screen/slot/Slot";
|
||||
y = "y";
|
||||
}
|
||||
var drawSlot = resolver.mapMethodName(namespace, name, "method_2385", "(Lnet/minecraft/class_332;Lnet/minecraft/class_1735;)V");
|
||||
var Slot = resolver.mapClassName(namespace, "net.minecraft.class_1735");
|
||||
var y = resolver.mapFieldName(namespace, Slot, "field_7872", "I");
|
||||
Slot = slash(Slot);
|
||||
|
||||
for (var mn : node.methods) {
|
||||
if (mn.name.equals(drawSlot)) {
|
||||
|
@ -32,19 +28,19 @@ public class HandledScreenTransformer implements ClassNodeTransformer {
|
|||
LabelNode LnotBag = new LabelNode();
|
||||
int SAFE_REGISTER = 20;
|
||||
mn.instructions.insert(vin, insns(
|
||||
ALOAD(2),
|
||||
INSTANCEOF("pm/c7/scout/screen/BagSlot"),
|
||||
IFEQ(LnotBag),
|
||||
ALOAD(2),
|
||||
CHECKCAST("pm/c7/scout/screen/BagSlot"),
|
||||
ASTORE(SAFE_REGISTER),
|
||||
ALOAD(SAFE_REGISTER),
|
||||
INVOKEVIRTUAL("pm/c7/scout/screen/BagSlot", "getX", "()I"),
|
||||
ISTORE(vin.var - 1),
|
||||
ALOAD(SAFE_REGISTER),
|
||||
INVOKEVIRTUAL("pm/c7/scout/screen/BagSlot", "getY", "()I"),
|
||||
ISTORE(vin.var),
|
||||
LnotBag
|
||||
ALOAD(2),
|
||||
INSTANCEOF("pm/c7/scout/screen/BagSlot"),
|
||||
IFEQ(LnotBag),
|
||||
ALOAD(2),
|
||||
CHECKCAST("pm/c7/scout/screen/BagSlot"),
|
||||
ASTORE(SAFE_REGISTER),
|
||||
ALOAD(SAFE_REGISTER),
|
||||
INVOKEVIRTUAL("pm/c7/scout/screen/BagSlot", "getX", "()I"),
|
||||
ISTORE(vin.var - 1),
|
||||
ALOAD(SAFE_REGISTER),
|
||||
INVOKEVIRTUAL("pm/c7/scout/screen/BagSlot", "getY", "()I"),
|
||||
ISTORE(vin.var),
|
||||
LnotBag
|
||||
));
|
||||
}
|
||||
}
|
||||
|
@ -55,19 +51,23 @@ public class HandledScreenTransformer implements ClassNodeTransformer {
|
|||
}
|
||||
}
|
||||
|
||||
private String slash(String clazz) {
|
||||
return clazz.replaceAll("\\.", "/");
|
||||
}
|
||||
|
||||
private InsnList insns(AbstractInsnNode... insns) {
|
||||
var li = new InsnList();
|
||||
for (var i : insns) li.add(i);
|
||||
return li;
|
||||
}
|
||||
private static JumpInsnNode IFEQ(LabelNode var) {
|
||||
return new JumpInsnNode(IFEQ, var);
|
||||
private static JumpInsnNode IFEQ(LabelNode v) {
|
||||
return new JumpInsnNode(IFEQ, v);
|
||||
}
|
||||
private static VarInsnNode ALOAD(int var) {
|
||||
return new VarInsnNode(ALOAD, var);
|
||||
private static VarInsnNode ALOAD(int v) {
|
||||
return new VarInsnNode(ALOAD, v);
|
||||
}
|
||||
private static VarInsnNode ASTORE(int var) {
|
||||
return new VarInsnNode(ASTORE, var);
|
||||
private static VarInsnNode ASTORE(int v) {
|
||||
return new VarInsnNode(ASTORE, v);
|
||||
}
|
||||
private static TypeInsnNode INSTANCEOF(String desc) {
|
||||
return new TypeInsnNode(INSTANCEOF, desc);
|
||||
|
@ -78,7 +78,7 @@ public class HandledScreenTransformer implements ClassNodeTransformer {
|
|||
private static MethodInsnNode INVOKEVIRTUAL(String owner, String name, String desc) {
|
||||
return new MethodInsnNode(INVOKEVIRTUAL, owner, name, desc);
|
||||
}
|
||||
private static VarInsnNode ISTORE(int var) {
|
||||
return new VarInsnNode(ISTORE, var);
|
||||
private static VarInsnNode ISTORE(int v) {
|
||||
return new VarInsnNode(ISTORE, v);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,19 +1,15 @@
|
|||
package pm.c7.scout.mixin.client;
|
||||
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.minecraft.client.gui.screen.ingame.AbstractInventoryScreen;
|
||||
import net.minecraft.client.gui.screen.ingame.InventoryScreen;
|
||||
import net.minecraft.client.gui.screen.recipe.book.RecipeBookProvider;
|
||||
import net.minecraft.client.render.GameRenderer;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.screen.PlayerScreenHandler;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
import pm.c7.scout.ScoutUtil;
|
||||
import pm.c7.scout.item.BaseBagItem;
|
||||
|
@ -22,45 +18,45 @@ import pm.c7.scout.item.BaseBagItem.BagType;
|
|||
@Environment(EnvType.CLIENT)
|
||||
@Mixin(InventoryScreen.class)
|
||||
public abstract class InventoryScreenMixin extends AbstractInventoryScreen<PlayerScreenHandler> implements RecipeBookProvider {
|
||||
private InventoryScreenMixin() {
|
||||
super(null, null, null);
|
||||
}
|
||||
private InventoryScreenMixin() {
|
||||
super(null, null, null);
|
||||
}
|
||||
|
||||
@Inject(method = "isClickOutsideBounds", at = @At("TAIL"), cancellable = true)
|
||||
private void scout$adjustOutsideBounds(double mouseX, double mouseY, int left, int top, int button, CallbackInfoReturnable<Boolean> callbackInfo) {
|
||||
if (this.client != null && this.client.player != null) {
|
||||
ItemStack backStack = ScoutUtil.findBagItem(this.client.player, BagType.SATCHEL, false);
|
||||
if (!backStack.isEmpty()) {
|
||||
BaseBagItem bagItem = (BaseBagItem) backStack.getItem();
|
||||
int slots = bagItem.getSlotCount();
|
||||
int rows = (int) Math.ceil(slots / 9);
|
||||
@Inject(method = "isClickOutsideBounds", at = @At("TAIL"), cancellable = true)
|
||||
private void scout$adjustOutsideBounds(double mouseX, double mouseY, int left, int top, int button, CallbackInfoReturnable<Boolean> callbackInfo) {
|
||||
if (this.client != null && this.client.player != null) {
|
||||
ItemStack backStack = ScoutUtil.findBagItem(this.client.player, BagType.SATCHEL, false);
|
||||
if (!backStack.isEmpty()) {
|
||||
BaseBagItem bagItem = (BaseBagItem) backStack.getItem();
|
||||
int slots = bagItem.getSlotCount();
|
||||
int rows = (int) Math.ceil(slots / 9);
|
||||
|
||||
if (mouseY < (top + this.backgroundHeight) + 8 + (18 * rows) && mouseY >= (top + this.backgroundHeight) && mouseX >= left && mouseY < (left + this.backgroundWidth)) {
|
||||
callbackInfo.setReturnValue(false);
|
||||
}
|
||||
}
|
||||
if (mouseY < (top + this.backgroundHeight) + 8 + (18 * rows) && mouseY >= (top + this.backgroundHeight) && mouseX >= left && mouseY < (left + this.backgroundWidth)) {
|
||||
callbackInfo.setReturnValue(false);
|
||||
}
|
||||
}
|
||||
|
||||
ItemStack leftPouchStack = ScoutUtil.findBagItem(this.client.player, BagType.POUCH, false);
|
||||
if (!leftPouchStack.isEmpty()) {
|
||||
BaseBagItem bagItem = (BaseBagItem) leftPouchStack.getItem();
|
||||
int slots = bagItem.getSlotCount();
|
||||
int columns = (int) Math.ceil(slots / 3);
|
||||
ItemStack leftPouchStack = ScoutUtil.findBagItem(this.client.player, BagType.POUCH, false);
|
||||
if (!leftPouchStack.isEmpty()) {
|
||||
BaseBagItem bagItem = (BaseBagItem) leftPouchStack.getItem();
|
||||
int slots = bagItem.getSlotCount();
|
||||
int columns = (int) Math.ceil(slots / 3);
|
||||
|
||||
if (mouseX >= left - (columns * 18) && mouseX < left && mouseY >= (top + this.backgroundHeight) - 90 && mouseY < (top + this.backgroundHeight) - 22) {
|
||||
callbackInfo.setReturnValue(false);
|
||||
}
|
||||
}
|
||||
if (mouseX >= left - (columns * 18) && mouseX < left && mouseY >= (top + this.backgroundHeight) - 90 && mouseY < (top + this.backgroundHeight) - 22) {
|
||||
callbackInfo.setReturnValue(false);
|
||||
}
|
||||
}
|
||||
|
||||
ItemStack rightPouchStack = ScoutUtil.findBagItem(this.client.player, BagType.POUCH, true);
|
||||
if (!rightPouchStack.isEmpty()) {
|
||||
BaseBagItem bagItem = (BaseBagItem) rightPouchStack.getItem();
|
||||
int slots = bagItem.getSlotCount();
|
||||
int columns = (int) Math.ceil(slots / 3);
|
||||
ItemStack rightPouchStack = ScoutUtil.findBagItem(this.client.player, BagType.POUCH, true);
|
||||
if (!rightPouchStack.isEmpty()) {
|
||||
BaseBagItem bagItem = (BaseBagItem) rightPouchStack.getItem();
|
||||
int slots = bagItem.getSlotCount();
|
||||
int columns = (int) Math.ceil(slots / 3);
|
||||
|
||||
if (mouseX >= (left + this.backgroundWidth) && mouseX < (left + this.backgroundWidth) + (columns * 18) && mouseY >= (top + this.backgroundHeight) - 90 && mouseY < (top + this.backgroundHeight) - 22) {
|
||||
callbackInfo.setReturnValue(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (mouseX >= (left + this.backgroundWidth) && mouseX < (left + this.backgroundWidth) + (columns * 18) && mouseY >= (top + this.backgroundHeight) - 90 && mouseY < (top + this.backgroundHeight) - 22) {
|
||||
callbackInfo.setReturnValue(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,36 +19,36 @@ import pm.c7.scout.item.BaseBagItem.BagType;
|
|||
@Environment(EnvType.CLIENT)
|
||||
@Mixin(value = RecipeBookWidget.class, priority = 950)
|
||||
public class RecipeBookWidgetMixin {
|
||||
@Shadow
|
||||
protected MinecraftClient client;
|
||||
@Shadow
|
||||
private int leftOffset;
|
||||
@Shadow
|
||||
protected MinecraftClient client;
|
||||
@Shadow
|
||||
private int leftOffset;
|
||||
|
||||
@Inject(method = "findLeftEdge", at = @At("RETURN"), locals = LocalCapture.CAPTURE_FAILHARD, cancellable = true)
|
||||
private void scout$modifyRecipeBookPosition(int width, int backgroundWidth, CallbackInfoReturnable<Integer> callbackInfo, int x) {
|
||||
if (this.client != null && this.client.player != null && this.isOpen()) {
|
||||
ItemStack leftPouchStack = ScoutUtil.findBagItem(this.client.player, BagType.POUCH, false);
|
||||
if (!leftPouchStack.isEmpty()) {
|
||||
BaseBagItem bagItem = (BaseBagItem) leftPouchStack.getItem();
|
||||
int slots = bagItem.getSlotCount();
|
||||
@Inject(method = "findLeftEdge", at = @At("RETURN"), locals = LocalCapture.CAPTURE_FAILHARD, cancellable = true)
|
||||
private void scout$modifyRecipeBookPosition(int width, int backgroundWidth, CallbackInfoReturnable<Integer> callbackInfo, int x) {
|
||||
if (this.client != null && this.client.player != null && this.isOpen()) {
|
||||
ItemStack leftPouchStack = ScoutUtil.findBagItem(this.client.player, BagType.POUCH, false);
|
||||
if (!leftPouchStack.isEmpty()) {
|
||||
BaseBagItem bagItem = (BaseBagItem) leftPouchStack.getItem();
|
||||
int slots = bagItem.getSlotCount();
|
||||
|
||||
int columns = (int) Math.ceil(slots / 3);
|
||||
int columns = (int) Math.ceil(slots / 3);
|
||||
|
||||
// Realign as best we can when "Keep crafting screens centered" is enabled in Better Recipe Book
|
||||
if (this.leftOffset != 86) {
|
||||
int diff = this.leftOffset - 86;
|
||||
x -= diff;
|
||||
}
|
||||
// Realign as best we can when "Keep crafting screens centered" is enabled in Better Recipe Book
|
||||
if (this.leftOffset != 86) {
|
||||
int diff = this.leftOffset - 86;
|
||||
x -= diff;
|
||||
}
|
||||
|
||||
x += 18 * columns;
|
||||
x += 18 * columns;
|
||||
|
||||
callbackInfo.setReturnValue(x);
|
||||
}
|
||||
}
|
||||
}
|
||||
callbackInfo.setReturnValue(x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Shadow
|
||||
public boolean isOpen() {
|
||||
return false;
|
||||
}
|
||||
@Shadow
|
||||
public boolean isOpen() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ import net.minecraft.inventory.Inventory;
|
|||
import net.minecraft.item.BlockItem;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.screen.slot.Slot;
|
||||
import pm.c7.scout.config.ScoutConfigHandler;
|
||||
import pm.c7.scout.ScoutConfig;
|
||||
import pm.c7.scout.item.BaseBagItem;
|
||||
|
||||
public class BagSlot extends Slot {
|
||||
|
@ -38,7 +38,7 @@ public class BagSlot extends Slot {
|
|||
|
||||
if (stack.getItem() instanceof BlockItem blockItem) {
|
||||
if (blockItem.getBlock() instanceof ShulkerBoxBlock)
|
||||
return (boolean) ScoutConfigHandler.getConfigValue("allowShulkers").value();
|
||||
return enabled && inventory != null && ScoutConfig.CONFIG.allowShulkers.value();
|
||||
}
|
||||
|
||||
return enabled && inventory != null;
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 229 B After Width: | Height: | Size: 225 B |
|
@ -55,16 +55,6 @@
|
|||
}
|
||||
],
|
||||
"breaks": [
|
||||
{
|
||||
"id": "roughlyenoughitems",
|
||||
"versions": "*",
|
||||
"reason": "API constantly rewritten for no reason, arrogant mod author, features stolen from EMI."
|
||||
},
|
||||
{
|
||||
"id": "inventoryprofilesnext",
|
||||
"versions": "*",
|
||||
"reason": "Crashes with no intent to fix on their end."
|
||||
},
|
||||
{
|
||||
"id": "infinitory",
|
||||
"versions": "*",
|
||||
|
@ -84,6 +74,16 @@
|
|||
"id": "inventory_backpack",
|
||||
"versions": "*",
|
||||
"reason": "Infinite/Incompatible inventory mod."
|
||||
},
|
||||
{
|
||||
"id": "realistic-inventory",
|
||||
"versions": "*",
|
||||
"reason": "Infinite/Incompatible inventory mod."
|
||||
},
|
||||
{
|
||||
"id": "inventorymod",
|
||||
"versions": "*",
|
||||
"reason": "Infinite/Incompatible inventory mod."
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
Loading…
Reference in a new issue