Fabric-ify

This commit is contained in:
Cynthia Foxwell 2024-03-15 20:01:13 -06:00
parent a42bb0507e
commit 01a26a624a
29 changed files with 823 additions and 228 deletions

View file

@ -10,6 +10,10 @@ version = "$project.version+${libs.versions.minecraft.get()}"
group = project.maven_group group = project.maven_group
repositories { repositories {
maven {
name = "Fabric"
url = "https://maven.fabricmc.net/"
}
maven { maven {
name = "TerraformersMC" name = "TerraformersMC"
url = "https://maven.terraformersmc.com/" url = "https://maven.terraformersmc.com/"
@ -42,11 +46,11 @@ loom {
} }
dependencies { dependencies {
minecraft libs.minecraft minecraft "com.mojang:minecraft:${libs.versions.minecraft.get()}"
mappings variantOf(libs.quilt.mappings) { classifier 'intermediary-v2' } mappings "net.fabricmc:yarn:${libs.versions.minecraft.get()}+${libs.versions.yarn.get()}:v2"
modImplementation libs.quilt.loader modImplementation "net.fabricmc:fabric-loader:${libs.versions.fabric.loader.get()}"
modImplementation libs.quilted.fabric.api modImplementation "net.fabricmc.fabric-api:fabric-api:${libs.versions.fabric.api.get()}+${libs.versions.minecraft.get()}"
// not JiJ because it causes its mixins to fail to load // not JiJ because it causes its mixins to fail to load
modApi "dev.emi:trinkets:${libs.versions.trinkets.get()}" modApi "dev.emi:trinkets:${libs.versions.trinkets.get()}"
@ -59,17 +63,17 @@ dependencies {
processResources { processResources {
inputs.property 'version', version inputs.property 'version', version
inputs.property 'group', project.group
inputs.property 'minecraft_version', libs.versions.minecraft.get() inputs.property 'minecraft_version', libs.versions.minecraft.get()
inputs.property 'fabric_version', libs.versions.fabric.api.get()
inputs.property 'trinkets_version', libs.versions.trinkets.get() inputs.property 'trinkets_version', libs.versions.trinkets.get()
inputs.property 'lib39_version', libs.versions.lib39.get() inputs.property 'lib39_version', libs.versions.lib39.get()
inputs.property 'emi_version', libs.versions.emi.get() inputs.property 'emi_version', libs.versions.emi.get()
filesMatching('quilt.mod.json') { filesMatching('fabric.mod.json') {
expand ( expand (
"version": version, "version": version,
"group": project.group,
"minecraft_version": libs.versions.minecraft.get(), "minecraft_version": libs.versions.minecraft.get(),
"fabric_version": libs.versions.fabric.api.get(),
"trinkets_version": libs.versions.trinkets.get(), "trinkets_version": libs.versions.trinkets.get(),
"lib39_version": libs.versions.lib39.get(), "lib39_version": libs.versions.lib39.get(),
"emi_version": libs.versions.emi.get() "emi_version": libs.versions.emi.get()

View file

@ -1,5 +1,5 @@
# Gradle Properties # Gradle Properties
org.gradle.jvmargs = -Xmx1G org.gradle.jvmargs = -Xmx4G
org.gradle.parallel = true org.gradle.parallel = true
# Mod Properties # Mod Properties

View file

@ -1,28 +1,15 @@
[versions] [versions]
# The latest versions are available at https://lambdaurora.dev/tools/import_quilt.html # The latest versions are available at https://lambdaurora.dev/tools/import_quilt.html
minecraft = "1.20.1" minecraft = "1.20.1"
loom = "1.4.1" loom = "1.5.7"
quilt_mappings = "1.20.1+build.23" fabric_loader = "0.15.7"
quilt_loader = "0.21.0" yarn = "build.10"
fabric_api = "0.91.0"
quilted_fabric_api = "7.4.0+0.90.0-1.20.1"
trinkets = "3.7.2" trinkets = "3.7.2"
lib39 = "1.5.0-experimental6.1" lib39 = "1.5.0-experimental6.1"
emi = "1.1.3" emi = "1.1.3"
[libraries]
minecraft = { module = "com.mojang:minecraft", version.ref = "minecraft" }
quilt_mappings = { module = "org.quiltmc:quilt-mappings", version.ref = "quilt_mappings" }
quilt_loader = { module = "org.quiltmc:quilt-loader", version.ref = "quilt_loader" }
quilted_fabric_api = { module = "org.quiltmc.quilted-fabric-api:quilted-fabric-api", version.ref = "quilted_fabric_api" }
quilted_fabric_api_deprecated = { module = "org.quiltmc.quilted-fabric-api:quilted-fabric-api-deprecated", version.ref = "quilted_fabric_api" }
# If you have multiple similar dependencies, you can declare a dependency bundle and reference it on the build script with "libs.bundles.example".
[bundles]
quilted_fabric_api = ["quilted_fabric_api", "quilted_fabric_api_deprecated"]
[plugins] [plugins]
quilt_loom = { id = "org.quiltmc.loom", version.ref = "loom" } quilt_loom = { id = "org.quiltmc.loom", version.ref = "loom" }

View file

@ -1,7 +1,10 @@
package pm.c7.scout; package pm.c7.scout;
import java.util.Properties;
import com.unascribed.lib39.core.api.AutoRegistry; import com.unascribed.lib39.core.api.AutoRegistry;
import net.fabricmc.api.ModInitializer;
import net.fabricmc.fabric.api.itemgroup.v1.FabricItemGroup; import net.fabricmc.fabric.api.itemgroup.v1.FabricItemGroup;
import net.minecraft.item.ItemGroup; import net.minecraft.item.ItemGroup;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
@ -10,27 +13,28 @@ import net.minecraft.registry.Registry;
import net.minecraft.text.Text; import net.minecraft.text.Text;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import org.quiltmc.loader.api.ModContainer; import pm.c7.scout.config.ScoutConfig;
import org.quiltmc.qsl.base.api.entrypoint.ModInitializer;
import pm.c7.scout.registry.ScoutItems; import pm.c7.scout.registry.ScoutItems;
public class Scout implements ModInitializer { public class Scout implements ModInitializer {
public static final AutoRegistry AUTOREGISTRY = AutoRegistry.of(ScoutUtil.MOD_ID); public static final AutoRegistry AUTOREGISTRY = AutoRegistry.of(ScoutUtil.MOD_ID);
public static final ItemGroup ITEM_GROUP = FabricItemGroup.builder() public static final ItemGroup ITEM_GROUP = FabricItemGroup.builder()
.icon(() -> new ItemStack(ScoutItems.SATCHEL)) .icon(() -> new ItemStack(ScoutItems.SATCHEL))
.name(Text.translatable("itemGroup.scout.itemgroup")) .displayName(Text.translatable("itemGroup.scout.itemgroup"))
.entries((context, entries) -> { .entries((context, entries) -> {
entries.addItem(ScoutItems.TANNED_LEATHER); entries.add(ScoutItems.TANNED_LEATHER);
entries.addItem(ScoutItems.SATCHEL_STRAP); entries.add(ScoutItems.SATCHEL_STRAP);
entries.addItem(ScoutItems.SATCHEL); entries.add(ScoutItems.SATCHEL);
entries.addItem(ScoutItems.UPGRADED_SATCHEL); entries.add(ScoutItems.UPGRADED_SATCHEL);
entries.addItem(ScoutItems.POUCH); entries.add(ScoutItems.POUCH);
entries.addItem(ScoutItems.UPGRADED_POUCH); entries.add(ScoutItems.UPGRADED_POUCH);
}) })
.build(); .build();
@Override @Override
public void onInitialize(ModContainer mod) { public void onInitialize() {
ScoutConfig.loadConfig();
ScoutItems.init(); ScoutItems.init();
Registry.register(Registries.ITEM_GROUP, new Identifier(ScoutUtil.MOD_ID, "itemgroup"), ITEM_GROUP); Registry.register(Registries.ITEM_GROUP, new Identifier(ScoutUtil.MOD_ID, "itemgroup"), ITEM_GROUP);
} }

View file

@ -1,16 +0,0 @@
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);
}

View file

@ -7,7 +7,6 @@ import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.screen.ingame.BeaconScreen; import net.minecraft.client.gui.screen.ingame.BeaconScreen;
import net.minecraft.client.gui.screen.ingame.CreativeInventoryScreen; import net.minecraft.client.gui.screen.ingame.CreativeInventoryScreen;
import net.minecraft.client.gui.screen.ingame.HandledScreen;
import net.minecraft.client.gui.screen.ingame.MerchantScreen; import net.minecraft.client.gui.screen.ingame.MerchantScreen;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.inventory.Inventory; import net.minecraft.inventory.Inventory;
@ -16,7 +15,6 @@ import net.minecraft.nbt.NbtCompound;
import net.minecraft.nbt.NbtList; import net.minecraft.nbt.NbtList;
import net.minecraft.screen.PlayerScreenHandler; import net.minecraft.screen.PlayerScreenHandler;
import net.minecraft.screen.slot.Slot; import net.minecraft.screen.slot.Slot;
import net.minecraft.screen.slot.SlotActionType;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import net.minecraft.util.Pair; import net.minecraft.util.Pair;
import net.minecraft.util.collection.DefaultedList; import net.minecraft.util.collection.DefaultedList;
@ -26,7 +24,6 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import pm.c7.scout.item.BaseBagItem; import pm.c7.scout.item.BaseBagItem;
import pm.c7.scout.item.BaseBagItem.BagType; import pm.c7.scout.item.BaseBagItem.BagType;
import pm.c7.scout.screen.BagSlot;
import java.util.Optional; import java.util.Optional;

View file

@ -1,6 +1,10 @@
package pm.c7.scout.client; package pm.c7.scout.client;
import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
import net.fabricmc.fabric.api.client.screen.v1.ScreenEvents;
import net.fabricmc.fabric.api.client.rendering.v1.LivingEntityFeatureRendererRegistrationCallback; import net.fabricmc.fabric.api.client.rendering.v1.LivingEntityFeatureRendererRegistrationCallback;
import net.fabricmc.fabric.api.client.rendering.v1.TooltipComponentCallback;
import net.minecraft.client.gui.screen.ingame.GenericContainerScreen; import net.minecraft.client.gui.screen.ingame.GenericContainerScreen;
import net.minecraft.client.gui.screen.ingame.HandledScreen; import net.minecraft.client.gui.screen.ingame.HandledScreen;
import net.minecraft.client.gui.screen.ingame.ShulkerBoxScreen; import net.minecraft.client.gui.screen.ingame.ShulkerBoxScreen;
@ -9,11 +13,7 @@ import net.minecraft.inventory.Inventory;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.screen.slot.Slot; import net.minecraft.screen.slot.Slot;
import net.minecraft.util.collection.DefaultedList; import net.minecraft.util.collection.DefaultedList;
import org.quiltmc.loader.api.ModContainer;
import org.quiltmc.qsl.base.api.entrypoint.client.ClientModInitializer;
import org.quiltmc.qsl.networking.api.client.ClientPlayNetworking;
import org.quiltmc.qsl.screen.api.client.ScreenEvents;
import org.quiltmc.qsl.tooltip.api.client.TooltipComponentCallback;
import pm.c7.scout.ScoutNetworking; import pm.c7.scout.ScoutNetworking;
import pm.c7.scout.ScoutScreenHandler; import pm.c7.scout.ScoutScreenHandler;
import pm.c7.scout.ScoutUtil; import pm.c7.scout.ScoutUtil;
@ -28,7 +28,7 @@ import pm.c7.scout.screen.BagSlot;
public class ScoutClient implements ClientModInitializer { public class ScoutClient implements ClientModInitializer {
@Override @Override
public void onInitializeClient(ModContainer mod) { public void onInitializeClient() {
ClientPlayNetworking.registerGlobalReceiver(ScoutNetworking.ENABLE_SLOTS, (client, handler, packet, sender) -> { ClientPlayNetworking.registerGlobalReceiver(ScoutNetworking.ENABLE_SLOTS, (client, handler, packet, sender) -> {
client.execute(() -> { client.execute(() -> {
assert client.player != null; assert client.player != null;
@ -108,7 +108,7 @@ public class ScoutClient implements ClientModInitializer {
} }
}); });
ScreenEvents.AFTER_INIT.register((screen, client, firstInit) -> { ScreenEvents.AFTER_INIT.register((client, screen, scaledWidth, scaledHeight) -> {
if (screen instanceof HandledScreen<?> handledScreen && client.player != null) { if (screen instanceof HandledScreen<?> handledScreen && client.player != null) {
if (ScoutUtil.isScreenBlacklisted(screen)) { if (ScoutUtil.isScreenBlacklisted(screen)) {
// realistically no one is going to have a screen bigger than 2147483647 pixels // realistically no one is going to have a screen bigger than 2147483647 pixels

View file

@ -2,7 +2,7 @@ package pm.c7.scout.client.gui;
import com.google.common.math.IntMath; import com.google.common.math.IntMath;
import net.minecraft.client.font.TextRenderer; import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.tooltip.TooltipComponent; import net.minecraft.client.gui.tooltip.TooltipComponent;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.util.collection.DefaultedList; import net.minecraft.util.collection.DefaultedList;
@ -31,7 +31,7 @@ public class BagTooltipComponent implements TooltipComponent {
} }
@Override @Override
public void drawItems(TextRenderer textRenderer, int x, int y, GuiGraphics graphics) { public void drawItems(TextRenderer textRenderer, int x, int y, DrawContext graphics) {
int originalX = x; int originalX = x;
for (int i = 0; i < slotCount; i++) { for (int i = 0; i < slotCount; i++) {
@ -45,7 +45,7 @@ public class BagTooltipComponent implements TooltipComponent {
} }
} }
private void drawSlot(int x, int y, int index, GuiGraphics graphics, TextRenderer textRenderer) { private void drawSlot(int x, int y, int index, DrawContext graphics, TextRenderer textRenderer) {
ItemStack itemStack = this.inventory.get(index); ItemStack itemStack = this.inventory.get(index);
graphics.drawTexture(ScoutUtil.SLOT_TEXTURE, x, y, 0, 46, 7, 18, 18, 256, 256); graphics.drawTexture(ScoutUtil.SLOT_TEXTURE, x, y, 0, 46, 7, 18, 18, 256, 256);
graphics.drawItem(itemStack, x + 1, y + 1, index); graphics.drawItem(itemStack, x + 1, y + 1, index);

View file

@ -1,7 +1,7 @@
package pm.c7.scout.client.model; package pm.c7.scout.client.model;
import com.mojang.blaze3d.vertex.VertexConsumer;
import net.minecraft.client.model.*; import net.minecraft.client.model.*;
import net.minecraft.client.render.VertexConsumer;
import net.minecraft.client.render.entity.model.SinglePartEntityModel; import net.minecraft.client.render.entity.model.SinglePartEntityModel;
import net.minecraft.client.util.math.MatrixStack; import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.LivingEntity; import net.minecraft.entity.LivingEntity;

View file

@ -10,7 +10,7 @@ import net.minecraft.client.render.model.json.ModelTransformationMode;
import net.minecraft.client.util.math.MatrixStack; import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.LivingEntity; import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.math.Axis; import net.minecraft.util.math.RotationAxis;
import pm.c7.scout.ScoutUtil; import pm.c7.scout.ScoutUtil;
import pm.c7.scout.item.BaseBagItem; import pm.c7.scout.item.BaseBagItem;
@ -29,8 +29,8 @@ public class PouchFeatureRenderer<T extends LivingEntity, M extends EntityModel<
if (!leftPouch.isEmpty()) { if (!leftPouch.isEmpty()) {
matrices.push(); matrices.push();
((PlayerEntityModel<?>) this.getContextModel()).leftLeg.rotate(matrices); ((PlayerEntityModel<?>) this.getContextModel()).leftLeg.rotate(matrices);
matrices.multiply(Axis.X_POSITIVE.rotationDegrees(180.0F)); matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(180.0F));
matrices.multiply(Axis.Y_POSITIVE.rotationDegrees(-90.0F)); matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(-90.0F));
matrices.scale(0.325F, 0.325F, 0.325F); matrices.scale(0.325F, 0.325F, 0.325F);
matrices.translate(0F, -0.325F, -0.475F); matrices.translate(0F, -0.325F, -0.475F);
this.heldItemRenderer.renderItem(entity, leftPouch, ModelTransformationMode.FIXED, false, matrices, vertexConsumers, light); this.heldItemRenderer.renderItem(entity, leftPouch, ModelTransformationMode.FIXED, false, matrices, vertexConsumers, light);
@ -39,8 +39,8 @@ public class PouchFeatureRenderer<T extends LivingEntity, M extends EntityModel<
if (!rightPouch.isEmpty()) { if (!rightPouch.isEmpty()) {
matrices.push(); matrices.push();
((PlayerEntityModel<?>) this.getContextModel()).rightLeg.rotate(matrices); ((PlayerEntityModel<?>) this.getContextModel()).rightLeg.rotate(matrices);
matrices.multiply(Axis.X_POSITIVE.rotationDegrees(180.0F)); matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(180.0F));
matrices.multiply(Axis.Y_POSITIVE.rotationDegrees(-90.0F)); matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(-90.0F));
matrices.scale(0.325F, 0.325F, 0.325F); matrices.scale(0.325F, 0.325F, 0.325F);
matrices.translate(0F, -0.325F, 0.475F); matrices.translate(0F, -0.325F, 0.475F);
this.heldItemRenderer.renderItem(entity, rightPouch, ModelTransformationMode.FIXED, false, matrices, vertexConsumers, light); this.heldItemRenderer.renderItem(entity, rightPouch, ModelTransformationMode.FIXED, false, matrices, vertexConsumers, light);

View file

@ -1,9 +1,9 @@
package pm.c7.scout.client.render; package pm.c7.scout.client.render;
import com.mojang.blaze3d.vertex.VertexConsumer;
import net.minecraft.client.model.TexturedModelData; import net.minecraft.client.model.TexturedModelData;
import net.minecraft.client.render.OverlayTexture; import net.minecraft.client.render.OverlayTexture;
import net.minecraft.client.render.RenderLayer; import net.minecraft.client.render.RenderLayer;
import net.minecraft.client.render.VertexConsumer;
import net.minecraft.client.render.VertexConsumerProvider; import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.render.entity.feature.FeatureRenderer; import net.minecraft.client.render.entity.feature.FeatureRenderer;
import net.minecraft.client.render.entity.feature.FeatureRendererContext; import net.minecraft.client.render.entity.feature.FeatureRendererContext;

View file

@ -0,0 +1,459 @@
package pm.c7.scout.config;
//package com.unascribed.qdcss;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.AbstractList;
import java.util.AbstractMap;
import java.util.AbstractSet;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.google.common.base.Splitter;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.io.CharStreams;
/**
* A quick-and-dirty "CSS" parser.
*/
public class QDCSS {
public static class QDCSSException extends IllegalArgumentException {
public QDCSSException() {}
public QDCSSException(String message, Throwable cause) { super(message, cause); }
public QDCSSException(String s) { super(s); }
public QDCSSException(Throwable cause) { super(cause); }
}
public static class BadValueException extends QDCSSException {
public BadValueException() {}
public BadValueException(String message, Throwable cause) { super(message, cause); }
public BadValueException(String s) { super(s); }
public BadValueException(Throwable cause) { super(cause); }
}
public static class SyntaxErrorException extends QDCSSException {
public SyntaxErrorException() {}
public SyntaxErrorException(String message, Throwable cause) { super(message, cause); }
public SyntaxErrorException(String s) { super(s); }
public SyntaxErrorException(Throwable cause) { super(cause); }
}
private static class BlameString {
public final String value;
public final String file;
public final int line;
private BlameString(String value) {
this(value, null, -1);
}
private BlameString(String value, String file, int line) {
this.value = value;
this.file = file;
this.line = line;
}
public String blame() {
return line == -1 ? "<unknown>" : "line "+line+" in "+file;
}
}
private final String prelude;
private final Map<String, List<BlameString>> data;
private Consumer<String> yapLog;
private QDCSS(String prelude, Map<String, List<BlameString>> data) {
this.prelude = prelude;
this.data = data;
}
/**
* Enables "yap" mode for parse failures in this config, where rather than throwing a
* BadValueException a warning string will be sent to this Consumer and an empty Optional
* returned to the caller of get*.
* <p>
* If yapLog is null, "yap" mode is turned off.
*/
public void setYapLog(Consumer<String> yapLog) {
this.yapLog = yapLog;
}
public boolean containsKey(String key) {
return data.containsKey(key) && !data.get(key).isEmpty();
}
public void put(String key, String value) {
List<BlameString> li = new ArrayList<>();
li.add(new BlameString(value));
data.put(key, li);
}
public void put(String key, String... values) {
List<BlameString> li = new ArrayList<>();
for (String v : values) {
li.add(new BlameString(v));
}
data.put(key, li);
}
public void put(String key, Iterable<String> values) {
List<BlameString> li = new ArrayList<>();
for (String v : values) {
li.add(new BlameString(v));
}
data.put(key, li);
}
/**
* Return all defined values for the given key, or an empty list if it's not defined.
*/
public List<String> getAll(String key) {
return unwrap(data.get(key));
}
private List<BlameString> getAllBlamed(String key) {
return data.containsKey(key) ? data.get(key) : Collections.emptyList();
}
public String getBlame(String key) {
return getBlamed(key).map(BlameString::blame).orElse("<unknown>");
}
public String getBlame(String key, int index) {
if (containsKey(key)) {
return getAllBlamed(key).get(index).blame();
}
return "<unknown>";
}
private List<String> unwrap(List<BlameString> list) {
if (list == null) return Collections.emptyList();
return new AbstractList<String>() {
@Override
public String get(int index) {
return unwrap(list.get(index));
}
@Override
public int size() {
return list.size();
}
};
}
private String unwrap(BlameString bs) {
if (bs == null) return null;
return bs.value;
}
/**
* Return the last defined value for the given key.
*/
public Optional<String> get(String key) {
return Optional.ofNullable(getLast(getAll(key)));
}
private Optional<BlameString> getBlamed(String key) {
return Optional.ofNullable(getLast(getAllBlamed(key)));
}
public Optional<Integer> getInt(String key) throws BadValueException {
return getParsed(key, Integer::parseInt, () -> "a whole number");
}
public Optional<Double> getDouble(String key) throws BadValueException {
return getParsed(key, Double::parseDouble, () -> "a number");
}
public Optional<Boolean> getBoolean(String key) throws BadValueException {
return getParsed(key, this::strictParseBoolean, () -> "true/on or false/off");
}
private boolean strictParseBoolean(String s) {
switch (s.toLowerCase(Locale.ROOT)) {
case "on": case "true": return true;
case "off": case "false": return false;
default: throw new IllegalArgumentException();
}
}
public <E extends Enum<E>> Optional<E> getEnum(String key, Class<E> clazz) throws BadValueException {
return getParsed(key, s -> Enum.valueOf(clazz, s.toUpperCase(Locale.ROOT)), () -> {
StringBuilder sb = new StringBuilder("one of ");
boolean first = true;
for (E e : clazz.getEnumConstants()) {
if (first) {
first = false;
} else {
sb.append(", ");
}
sb.append(e.name().toLowerCase(Locale.ROOT));
}
return sb.toString();
});
}
private <T> Optional<T> getParsed(String key, Function<String, ? extends T> parser, Supplier<String> error) throws BadValueException {
Optional<String> s = get(key);
if (!s.isPresent()) return Optional.empty();
try {
return Optional.of(parser.apply(s.get()));
} catch (IllegalArgumentException e) {
String msg = key+" must be "+error.get()+" (got "+s.get()+") near "+getBlame(key);
if (yapLog != null) {
yapLog.accept(msg);
return Optional.empty();
} else {
throw new BadValueException(msg, e);
}
}
}
private <T> T getLast(List<T> list) {
return list == null || list.isEmpty() ? null : list.get(list.size()-1);
}
public Set<String> keySet() {
return data.keySet();
}
public Set<Map.Entry<String, List<String>>> entrySet() {
return new AbstractSet<Map.Entry<String, List<String>>>() {
@Override
public Iterator<Map.Entry<String, List<String>>> iterator() {
Iterator<Map.Entry<String, List<BlameString>>> delegate = data.entrySet().iterator();
return new Iterator<Map.Entry<String, List<String>>>() {
@Override
public boolean hasNext() {
return delegate.hasNext();
}
@Override
public Map.Entry<String, List<String>> next() {
Map.Entry<String, List<BlameString>> den = delegate.next();
return new AbstractMap.SimpleImmutableEntry<>(den.getKey(), unwrap(den.getValue()));
}
};
}
@Override
public int size() {
return size();
}
};
}
public int size() {
return data.size();
}
/**
* Lossily convert this QDCSS's data into an INI. Comments, section declarations, etc will
* be lost.
*/
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("; Loaded from ");
sb.append(prelude);
sb.append("\r\n");
for (Map.Entry<String, List<String>> en : entrySet()) {
for (String v : en.getValue()) {
sb.append(en.getKey());
sb.append("=");
sb.append(v);
sb.append("\r\n");
}
}
return sb.toString();
}
/**
* Merge the given QDCSS's data with this QDCSS's data, returning a new QDCSS object. Keys
* defined in the given QDCSS will have their values appended to this one's. For usages of
* {@link #get}, this is equivalent to an override.
*/
public QDCSS merge(QDCSS that) {
Map<String, List<BlameString>> newData = new LinkedHashMap<>(Math.max(this.size(), that.size()));
newData.putAll(data);
for (Map.Entry<String, List<BlameString>> en : that.data.entrySet()) {
if (newData.containsKey(en.getKey())) {
List<BlameString> merged = new ArrayList<>(newData.get(en.getKey()).size()+en.getValue().size());
merged.addAll(newData.get(en.getKey()));
merged.addAll(en.getValue());
newData.put(en.getKey(), Collections.unmodifiableList(merged));
} else {
newData.put(en.getKey(), en.getValue());
}
}
return new QDCSS(prelude+", merged with "+that.prelude, Collections.unmodifiableMap(newData));
}
/**
* Return a view of this QDCSS's data, dropping multivalues and collapsing to a basic key-value
* mapping that returns the last defined value for any given key.
*/
public Map<String, String> flatten() {
return new AbstractMap<String, String>() {
@Override
public String get(Object key) {
return QDCSS.this.get((String)key).orElse(null);
}
@Override
public boolean containsKey(Object key) {
return QDCSS.this.containsKey((String)key);
}
@Override
public Set<String> keySet() {
return QDCSS.this.keySet();
}
@Override
public int size() {
return QDCSS.this.size();
}
@Override
public Set<Entry<String, String>> entrySet() {
return new AbstractSet<Map.Entry<String,String>>() {
@Override
public Iterator<Entry<String, String>> iterator() {
Iterator<Entry<String, List<String>>> delegate = QDCSS.this.entrySet().iterator();
return new Iterator<Map.Entry<String,String>>() {
@Override
public boolean hasNext() {
return delegate.hasNext();
}
@Override
public Entry<String, String> next() {
Entry<String, List<String>> den = delegate.next();
return new SimpleImmutableEntry<>(den.getKey(), getLast(den.getValue()));
}
};
}
@Override
public int size() {
return size();
}
};
}
};
}
private static final Pattern JUNK_PATTERN = Pattern.compile("^(\\s*(/\\*.*?\\*/)?\\s*)*$", Pattern.DOTALL);
private static final Pattern RULESET_PATTERN = Pattern.compile("[#.]?(\\w+?)\\s*\\{(.*?)\\}", Pattern.DOTALL);
private static final Pattern RULE_PATTERN = Pattern.compile("(\\S+?)\\s*:\\s*(\\\".*?\\\"|'.*?'|.+?)\\s*(;|$)");
public static QDCSS load(String fileName, String s) throws SyntaxErrorException {
// vanilla CSS is a very simple grammar, so we can parse it using only regexes
Map<String, List<BlameString>> data = new LinkedHashMap<>();
Matcher ruleset = RULESET_PATTERN.matcher(s);
int lastEnd = 0;
while (ruleset.find()) {
String skipped = s.substring(lastEnd, ruleset.start());
if (!JUNK_PATTERN.matcher(skipped).matches()) {
throw new SyntaxErrorException("Expected a ruleset near line "+getLine(s, ruleset.start())+" in "+fileName);
}
String selector = ruleset.group(1);
String rules = ruleset.group(2);
Matcher rule = RULE_PATTERN.matcher(rules);
int lastRulesEnd = 0;
while (rule.find()) {
String skippedRule = rules.substring(lastRulesEnd, rule.start());
if (!JUNK_PATTERN.matcher(skippedRule).matches()) {
throw new SyntaxErrorException("Expected a rule near line "+getLine(s, ruleset.start(2)+rule.start())+" in "+fileName);
}
String property = rule.group(1);
String value = rule.group(2);
String key = selector+"."+property;
if (!data.containsKey(key)) {
data.put(key, Lists.newArrayList());
}
data.get(key).add(new BlameString(value, fileName, getLine(s, ruleset.start(2)+rule.start())));
lastRulesEnd = rule.end();
}
String skippedRule = rules.substring(lastRulesEnd);
if (!JUNK_PATTERN.matcher(skippedRule).matches()) {
throw new SyntaxErrorException("Expected a rule near line "+getLine(s, ruleset.start(2)+lastRulesEnd)+" in "+fileName);
}
lastEnd = ruleset.end();
}
String skipped = s.substring(lastEnd);
if (!JUNK_PATTERN.matcher(skipped).matches()) {
throw new SyntaxErrorException("Expected a ruleset or EOF near line "+getLine(s, lastEnd)+" in "+fileName);
}
return new QDCSS(fileName, data);
}
private static int getLine(String s, int start) {
int line = 1;
for (int i = 0; i < start; i++) {
if (s.charAt(i) == '\n') {
line++;
}
}
return line;
}
public static QDCSS load(File f) throws IOException {
try (InputStream in = new FileInputStream(f)) {
return load(f.getName(), in);
}
}
public static QDCSS load(Path p) throws IOException {
try (InputStream in = Files.newInputStream(p)) {
return load(p.getFileName().toString(), in);
}
}
private static final Splitter SLASH_SPLITTER = Splitter.on('/');
public static QDCSS load(URL u) throws IOException {
try (InputStream in = u.openStream()) {
return load(Iterables.getLast(SLASH_SPLITTER.split(u.getPath())), in);
}
}
public static QDCSS load(String fileName, InputStream in) throws IOException {
return load(fileName, new InputStreamReader(in, StandardCharsets.UTF_8));
}
public static QDCSS load(String fileName, Reader r) throws IOException {
return load(fileName, CharStreams.toString(r));
}
}

View file

@ -0,0 +1,232 @@
package pm.c7.scout.config;
import java.io.File;
import java.io.FileWriter;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Field;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import joptsimple.internal.Strings;
import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.client.font.TextHandler;
import net.minecraft.text.StringVisitable;
import net.minecraft.text.Style;
import pm.c7.scout.ScoutUtil;
// most of this is taken from EMI
public class ScoutConfig {
private static final Map<Class<?>, Setter> SETTERS = Maps.newHashMap();
private static final Map<Class<?>, Writer<?>> WRITERS = Maps.newHashMap();
private static final Map<String, List<String>> unparsed = Maps.newHashMap();
public static final String DEFAULT_CONFIG;
public static String startupConfig;
// {{{ config values
@Comment("Allow shulker boxes to be placed in bags. Bags are already blacklisted from shulker boxes with no toggle.")
@ConfigValue("features.allow-shulkers")
public static boolean allowShulkers = true;
@Comment("Allow bags to act as a quiver and pull arrows.")
@ConfigValue("features.use-arrows")
public static boolean useArrows = true;
// }}}
// {{{ methods
public static void loadConfig() {
try {
File config = getConfigFile();
if (config.exists() && config.isFile()) {
QDCSS css = QDCSS.load(config);
loadConfig(css);
} else {
File defaultConfig = new File(FabricLoader.getInstance().getConfigDir().getParent().toFile(), "defaultconfigs/scout.css");
if (defaultConfig.exists() && defaultConfig.isFile()) {
QDCSS css = QDCSS.load(defaultConfig);
loadConfig(css);
}
}
if (startupConfig == null) {
startupConfig = getSavedConfig();
}
writeConfig();
} catch (Exception e) {
ScoutUtil.LOGGER.error("[Scout] Error reading config");
e.printStackTrace();
}
}
public static void loadConfig(QDCSS css) {
try {
Set<String> consumed = Sets.newHashSet();
for (Field field : ScoutConfig.class.getFields()) {
ConfigValue annot = field.getAnnotation(ConfigValue.class);
if (annot != null) {
if (css.containsKey(annot.value())) {
consumed.add(annot.value());
assignField(css, annot.value(), field);
}
}
}
for (String key : css.keySet()) {
if (!consumed.contains(key)) {
unparsed.put(key, css.getAll(key));
}
}
} catch (Exception e) {
ScoutUtil.LOGGER.error("[Scout] Error reading config");
e.printStackTrace();
}
}
public static void writeConfig() {
try {
FileWriter writer = new FileWriter(getConfigFile());
writer.write(getSavedConfig());
writer.close();
} catch (Exception e) {
ScoutUtil.LOGGER.error("[Scout] Error writing config");
e.printStackTrace();
}
}
public static String getSavedConfig() {
Map<String, List<String>> unparsed = Maps.newLinkedHashMap();
TextHandler wrapper = new TextHandler((point, style) -> 1);
for (Field field : ScoutConfig.class.getFields()) {
ConfigValue annot = field.getAnnotation(ConfigValue.class);
if (annot != null) {
String[] parts = annot.value().split("\\.");
String group = parts[0];
String key = parts[1];
Comment comment = field.getAnnotation(Comment.class);
String commentText = "";
if (comment != null) {
commentText += "\t/**\n";
for (StringVisitable line : wrapper.wrapLines(comment.value(), 80, Style.EMPTY)) {
commentText += "\t * ";
commentText += line.getString();
commentText += "\n";
}
commentText += "\t */\n";
}
String text = commentText;
try {
text += writeField(key, field);
} catch (Exception e) {
ScoutUtil.LOGGER.error("[Scout] Error serializing config");
e.printStackTrace();
}
unparsed.computeIfAbsent(group, g -> Lists.newArrayList()).add(text);
}
}
for (Map.Entry<String, List<String>> entry : ScoutConfig.unparsed.entrySet()) {
String[] parts = entry.getKey().split("\\.");
String group = parts[0];
String key = parts[1];
for (String value : entry.getValue()) {
unparsed.computeIfAbsent(group, g -> Lists.newArrayList()).add("\t/** unparsed */\n\t" + key + ": "
+ value + ";\n");
}
}
String ret = "";
boolean firstCategory = true;
for (Map.Entry<String, List<String>> category : unparsed.entrySet()) {
if (!firstCategory) {
ret += "\n";
}
firstCategory = false;
ret += "#" + category.getKey() + " {\n";
ret += Strings.join(category.getValue(), "\n");
ret += "}\n";
}
return ret;
}
private static File getConfigFile() {
return new File(FabricLoader.getInstance().getConfigDir().toFile(), "scout.css");
}
private static void assignField(QDCSS css, String annot, Field field) throws IllegalAccessException {
Class<?> type = field.getType();
Setter setter = SETTERS.get(type);
if (setter != null) {
setter.setValue(css, annot, field);
} else {
throw new RuntimeException("[Scout] Unknown parsing type: " + type);
}
}
@SuppressWarnings("unchecked")
private static String writeField(String key, Field field) throws IllegalAccessException {
String text = "";
Class<?> type = field.getType();
if (WRITERS.containsKey(type)) {
text += "\t" + key + ": " + ((Writer<Object>) WRITERS.get(type)).writeValue(field.get(null)) + ";\n";
}
return text;
}
private static void defineType(Class<?> clazz, Setter setter, Writer<?> writer) {
SETTERS.put(clazz, setter);
WRITERS.put(clazz, writer);
}
private static void defineType(Class<?> clazz, Setter setter) {
defineType(clazz, setter, field -> field.toString());
}
// }}}
// {{{ static init
static {
defineType(boolean.class, (css, annot, field) -> field.setBoolean(null, css.getBoolean(annot).get()));
defineType(int.class, (css, annot, field) -> field.setInt(null, css.getInt(annot).get()));
defineType(double.class, (css, annot, field) -> field.setDouble(null, css.getDouble(annot).get()));
defineType(String.class,
(css, annot, field) -> {
String s = css.get(annot).get();
s = s.substring(1, s.length() - 1);
field.set(null, s);
},
(String field) -> "\"" + field + "\""
);
DEFAULT_CONFIG = getSavedConfig();
}
// }}}
// {{{ annotations
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public static @interface ConfigValue {
public String value();
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public static @interface Comment {
public String value();
}
// }}}
// {{{ interfaces
private static interface Setter {
void setValue(QDCSS css, String annot, Field field) throws IllegalAccessException ;
}
private static interface Writer<T> {
String writeValue(T value);
}
// }}}
}

View file

@ -3,6 +3,7 @@ package pm.c7.scout.item;
import dev.emi.trinkets.api.SlotReference; import dev.emi.trinkets.api.SlotReference;
import dev.emi.trinkets.api.TrinketItem; import dev.emi.trinkets.api.TrinketItem;
import io.netty.buffer.Unpooled; import io.netty.buffer.Unpooled;
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;
import net.minecraft.client.item.TooltipContext; import net.minecraft.client.item.TooltipContext;
import net.minecraft.client.item.TooltipData; import net.minecraft.client.item.TooltipData;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
@ -21,7 +22,7 @@ import net.minecraft.util.Formatting;
import net.minecraft.util.collection.DefaultedList; import net.minecraft.util.collection.DefaultedList;
import net.minecraft.world.World; import net.minecraft.world.World;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.quiltmc.qsl.networking.api.ServerPlayNetworking;
import pm.c7.scout.ScoutNetworking; import pm.c7.scout.ScoutNetworking;
import pm.c7.scout.ScoutScreenHandler; import pm.c7.scout.ScoutScreenHandler;
import pm.c7.scout.ScoutUtil; import pm.c7.scout.ScoutUtil;

View file

@ -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.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture; import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
import pm.c7.scout.ScoutUtil; import pm.c7.scout.ScoutUtil;
import pm.c7.scout.ScoutConfig; import pm.c7.scout.config.ScoutConfig;
import pm.c7.scout.item.BaseBagItem; import pm.c7.scout.item.BaseBagItem;
@Mixin(BowItem.class) @Mixin(BowItem.class)
public class BowItemMixin { 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) @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) { 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 (ScoutConfig.CONFIG.useArrows.value()) { if (ScoutConfig.useArrows) {
boolean infinity = bl && itemStack.isOf(Items.ARROW); boolean infinity = bl && itemStack.isOf(Items.ARROW);
boolean hasRan = false; boolean hasRan = false;

View file

@ -8,16 +8,16 @@ import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture; import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
import pm.c7.scout.ScoutUtil; import pm.c7.scout.ScoutUtil;
import pm.c7.scout.ScoutConfig; import pm.c7.scout.config.ScoutConfig;
import pm.c7.scout.item.BaseBagItem; import pm.c7.scout.item.BaseBagItem;
import java.util.function.Predicate; import java.util.function.Predicate;
@Mixin(PlayerEntity.class) @Mixin(PlayerEntity.class)
public class PlayerEntityMixin { 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) @Inject(method = "getProjectileType", 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) { public void scout$arrowsFromBags(ItemStack stack, CallbackInfoReturnable<ItemStack> cir, Predicate<ItemStack> predicate) {
if (ScoutConfig.CONFIG.useArrows.value()) { if (ScoutConfig.useArrows) {
var self = (PlayerEntity) (Object) this; var self = (PlayerEntity) (Object) this;
var leftPouch = ScoutUtil.findBagItem(self, BaseBagItem.BagType.POUCH, false); var leftPouch = ScoutUtil.findBagItem(self, BaseBagItem.BagType.POUCH, false);
var rightPouch = ScoutUtil.findBagItem(self, BaseBagItem.BagType.POUCH, true); var rightPouch = ScoutUtil.findBagItem(self, BaseBagItem.BagType.POUCH, true);

View file

@ -1,8 +1,8 @@
package pm.c7.scout.mixin; package pm.c7.scout.mixin;
import org.objectweb.asm.tree.*; import org.objectweb.asm.tree.*;
import org.quiltmc.loader.api.QuiltLoader;
import net.fabricmc.loader.api.FabricLoader;
import pm.c7.scout.mixinsupport.ClassNodeTransformer; import pm.c7.scout.mixinsupport.ClassNodeTransformer;
import static org.objectweb.asm.Opcodes.*; import static org.objectweb.asm.Opcodes.*;
@ -10,7 +10,7 @@ import static org.objectweb.asm.Opcodes.*;
public class PlayerScreenHandlerTransformer implements ClassNodeTransformer { public class PlayerScreenHandlerTransformer implements ClassNodeTransformer {
@Override @Override
public void transform(String name, ClassNode node) { public void transform(String name, ClassNode node) {
var resolver = QuiltLoader.getMappingResolver(); var resolver = FabricLoader.getInstance().getMappingResolver();
var namespace = "intermediary"; var namespace = "intermediary";
var LPlayerScreenHandler = L(slash(name)); var LPlayerScreenHandler = L(slash(name));
@ -23,7 +23,7 @@ public class PlayerScreenHandlerTransformer implements ClassNodeTransformer {
var DefaultedList = slash(resolver.mapClassName(namespace, "net.minecraft.class_2371")); var DefaultedList = slash(resolver.mapClassName(namespace, "net.minecraft.class_2371"));
for (var mn : node.methods) { for (var mn : node.methods) {
// that other comment was a half truth, you can transform mixins :^) // fix slot checking for trinkets quick move mixin
if (mn.name.endsWith("trinkets$quickMove") || mn.name.equals(quickMove)) { if (mn.name.endsWith("trinkets$quickMove") || mn.name.equals(quickMove)) {
for (var insn : mn.instructions) { for (var insn : mn.instructions) {
if (insn instanceof VarInsnNode vin) { if (insn instanceof VarInsnNode vin) {

View file

@ -1,8 +1,8 @@
package pm.c7.scout.mixin; package pm.c7.scout.mixin;
import org.objectweb.asm.tree.*; import org.objectweb.asm.tree.*;
import org.quiltmc.loader.api.QuiltLoader;
import net.fabricmc.loader.api.FabricLoader;
import pm.c7.scout.mixinsupport.ClassNodeTransformer; import pm.c7.scout.mixinsupport.ClassNodeTransformer;
import static org.objectweb.asm.Opcodes.*; import static org.objectweb.asm.Opcodes.*;
@ -12,7 +12,7 @@ public class ScreenHandlerTransformer implements ClassNodeTransformer {
@Override @Override
public void transform(String name, ClassNode node) { public void transform(String name, ClassNode node) {
var resolver = QuiltLoader.getMappingResolver(); var resolver = FabricLoader.getInstance().getMappingResolver();
var namespace = "intermediary"; var namespace = "intermediary";
var internalOnSlotClick = resolver.mapMethodName(namespace, name, "method_30010", "(IILnet/minecraft/class_1713;Lnet/minecraft/class_1657;)V"); var internalOnSlotClick = resolver.mapMethodName(namespace, name, "method_30010", "(IILnet/minecraft/class_1713;Lnet/minecraft/class_1657;)V");
@ -106,9 +106,10 @@ public class ScreenHandlerTransformer implements ClassNodeTransformer {
} }
} }
} }
} else if (mn.name.endsWith("debugify$handleCtrlQCrafting")) { // ughghghhghghghghgh } else if (mn.name.startsWith("handler$")) {
// fix getting slots for mixins
for (var insn : mn.instructions) { for (var insn : mn.instructions) {
if (insn instanceof VarInsnNode vin && vin.getOpcode() == ASTORE && vin.var == 6) { if (insn instanceof VarInsnNode vin && vin.getOpcode() == ASTORE && (vin.var == 6 || vin.var == 7)) {
if (vin.getPrevious() instanceof TypeInsnNode prevInsn && prevInsn.getOpcode() == CHECKCAST && prevInsn.desc.equals(Slot)) { if (vin.getPrevious() instanceof TypeInsnNode prevInsn && prevInsn.getOpcode() == CHECKCAST && prevInsn.desc.equals(Slot)) {
if (prevInsn.getPrevious() instanceof MethodInsnNode prevPrevInsn && prevPrevInsn.getOpcode() == INVOKEVIRTUAL) { if (prevInsn.getPrevious() instanceof MethodInsnNode prevPrevInsn && prevPrevInsn.getOpcode() == INVOKEVIRTUAL) {
if(prevPrevInsn.owner.equals(DefaultedList)) { if(prevPrevInsn.owner.equals(DefaultedList)) {

View file

@ -7,7 +7,7 @@ import net.minecraft.network.PacketByteBuf;
import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.util.collection.DefaultedList; import net.minecraft.util.collection.DefaultedList;
import net.minecraft.world.GameRules; import net.minecraft.world.GameRules;
import org.quiltmc.qsl.networking.api.ServerPlayNetworking; import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
@ -39,13 +39,6 @@ public class ServerPlayerEntityMixin {
slot.setInventory(null); slot.setInventory(null);
slot.setEnabled(false); slot.setEnabled(false);
} }
PacketByteBuf packet = new PacketByteBuf(Unpooled.buffer());
packet.writeBoolean(false);
packet.writeInt(0);
packet.writeItemStack(backStack);
ServerPlayNetworking.send(player, ScoutNetworking.ENABLE_SLOTS, packet);
} }
ItemStack leftPouchStack = ScoutUtil.findBagItem(player, BagType.POUCH, false); ItemStack leftPouchStack = ScoutUtil.findBagItem(player, BagType.POUCH, false);
@ -60,13 +53,6 @@ public class ServerPlayerEntityMixin {
slot.setInventory(null); slot.setInventory(null);
slot.setEnabled(false); slot.setEnabled(false);
} }
PacketByteBuf packet = new PacketByteBuf(Unpooled.buffer());
packet.writeBoolean(false);
packet.writeInt(0);
packet.writeItemStack(leftPouchStack);
ServerPlayNetworking.send(player, ScoutNetworking.ENABLE_SLOTS, packet);
} }
ItemStack rightPouchStack = ScoutUtil.findBagItem(player, BagType.POUCH, true); ItemStack rightPouchStack = ScoutUtil.findBagItem(player, BagType.POUCH, true);
@ -81,14 +67,10 @@ public class ServerPlayerEntityMixin {
slot.setInventory(null); slot.setInventory(null);
slot.setEnabled(false); slot.setEnabled(false);
} }
}
PacketByteBuf packet = new PacketByteBuf(Unpooled.buffer()); PacketByteBuf packet = new PacketByteBuf(Unpooled.buffer());
packet.writeBoolean(false);
packet.writeInt(1);
packet.writeItemStack(rightPouchStack);
ServerPlayNetworking.send(player, ScoutNetworking.ENABLE_SLOTS, packet); ServerPlayNetworking.send(player, ScoutNetworking.ENABLE_SLOTS, packet);
} }
} }
} }
}

View file

@ -4,7 +4,7 @@ import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment; import net.fabricmc.api.Environment;
import net.minecraft.client.gui.screen.ingame.AbstractFurnaceScreen; import net.minecraft.client.gui.screen.ingame.AbstractFurnaceScreen;
import net.minecraft.client.gui.screen.ingame.HandledScreen; import net.minecraft.client.gui.screen.ingame.HandledScreen;
import net.minecraft.client.gui.screen.recipe.book.RecipeBookProvider; import net.minecraft.client.gui.screen.recipebook.RecipeBookProvider;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.screen.AbstractFurnaceScreenHandler; import net.minecraft.screen.AbstractFurnaceScreenHandler;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;

View file

@ -4,11 +4,9 @@ import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment; import net.fabricmc.api.Environment;
import net.minecraft.client.gui.screen.ingame.CraftingScreen; import net.minecraft.client.gui.screen.ingame.CraftingScreen;
import net.minecraft.client.gui.screen.ingame.HandledScreen; import net.minecraft.client.gui.screen.ingame.HandledScreen;
import net.minecraft.client.gui.screen.recipe.book.RecipeBookProvider; import net.minecraft.client.gui.screen.recipebook.RecipeBookProvider;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.screen.CraftingScreenHandler; import net.minecraft.screen.CraftingScreenHandler;
import net.minecraft.text.Text;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;

View file

@ -3,7 +3,7 @@ package pm.c7.scout.mixin.client;
import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.systems.RenderSystem;
import net.fabricmc.api.EnvType; import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment; import net.fabricmc.api.Environment;
import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.screen.ingame.GenericContainerScreen; import net.minecraft.client.gui.screen.ingame.GenericContainerScreen;
import net.minecraft.client.gui.screen.ingame.HandledScreen; import net.minecraft.client.gui.screen.ingame.HandledScreen;
@ -44,8 +44,8 @@ public abstract class HandledScreenMixin<T extends ScreenHandler> extends Screen
@Shadow @Shadow
protected int backgroundHeight; protected int backgroundHeight;
@Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screen/ingame/HandledScreen;drawBackground(Lnet/minecraft/client/gui/GuiGraphics;FII)V")) @Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screen/ingame/HandledScreen;drawBackground(Lnet/minecraft/client/gui/DrawContext;FII)V"))
private void scout$drawSatchelRow(GuiGraphics graphics, int mouseX, int mouseY, float delta, CallbackInfo ci) { private void scout$drawSatchelRow(DrawContext graphics, int mouseX, int mouseY, float delta, CallbackInfo ci) {
if (this.client != null && this.client.player != null && !ScoutUtil.isScreenBlacklisted(this)) { if (this.client != null && this.client.player != null && !ScoutUtil.isScreenBlacklisted(this)) {
ItemStack backStack = ScoutUtil.findBagItem(this.client.player, BaseBagItem.BagType.SATCHEL, false); ItemStack backStack = ScoutUtil.findBagItem(this.client.player, BaseBagItem.BagType.SATCHEL, false);
if (!backStack.isEmpty()) { if (!backStack.isEmpty()) {
@ -96,7 +96,7 @@ public abstract class HandledScreenMixin<T extends ScreenHandler> extends Screen
} }
@Inject(method = "render", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/systems/RenderSystem;disableDepthTest()V", remap = false)) @Inject(method = "render", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/systems/RenderSystem;disableDepthTest()V", remap = false))
private void scout$drawPouchSlots(GuiGraphics graphics, int mouseX, int mouseY, float delta, CallbackInfo ci) { private void scout$drawPouchSlots(DrawContext graphics, int mouseX, int mouseY, float delta, CallbackInfo ci) {
if (this.client != null && this.client.player != null && !ScoutUtil.isScreenBlacklisted(this)) { if (this.client != null && this.client.player != null && !ScoutUtil.isScreenBlacklisted(this)) {
ItemStack leftPouchStack = ScoutUtil.findBagItem(this.client.player, BaseBagItem.BagType.POUCH, false); ItemStack leftPouchStack = ScoutUtil.findBagItem(this.client.player, BaseBagItem.BagType.POUCH, false);
if (!leftPouchStack.isEmpty()) { if (!leftPouchStack.isEmpty()) {
@ -270,8 +270,8 @@ 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/gui/GuiGraphics;II)V")) @Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screen/ingame/HandledScreen;drawForeground(Lnet/minecraft/client/gui/DrawContext;II)V"))
public void scout$drawOurSlots(GuiGraphics graphics, int mouseX, int mouseY, float delta, CallbackInfo ci) { public void scout$drawOurSlots(DrawContext graphics, int mouseX, int mouseY, float delta, CallbackInfo ci) {
if (this.client != null && this.client.player != null && !ScoutUtil.isScreenBlacklisted(this)) { if (this.client != null && this.client.player != null && !ScoutUtil.isScreenBlacklisted(this)) {
for (int i = ScoutUtil.SATCHEL_SLOT_START; i > ScoutUtil.BAG_SLOTS_END; i--) { for (int i = ScoutUtil.SATCHEL_SLOT_START; i > ScoutUtil.BAG_SLOTS_END; i--) {
BagSlot slot = (BagSlot) ScoutUtil.getBagSlot(i, this.client.player.playerScreenHandler); BagSlot slot = (BagSlot) ScoutUtil.getBagSlot(i, this.client.player.playerScreenHandler);
@ -309,9 +309,9 @@ public abstract class HandledScreenMixin<T extends ScreenHandler> extends Screen
} }
@Shadow @Shadow
private void drawSlot(GuiGraphics graphics, Slot slot) {} private void drawSlot(DrawContext graphics, Slot slot) {}
@Shadow @Shadow
public static void drawSlotHighlight(GuiGraphics graphics, int x, int y, int z) {} public static void drawSlotHighlight(DrawContext graphics, int x, int y, int z) {}
@Shadow @Shadow
private boolean isPointOverSlot(Slot slot, double pointX, double pointY) { private boolean isPointOverSlot(Slot slot, double pointX, double pointY) {
return false; return false;

View file

@ -1,8 +1,8 @@
package pm.c7.scout.mixin.client; package pm.c7.scout.mixin.client;
import org.objectweb.asm.tree.*; import org.objectweb.asm.tree.*;
import org.quiltmc.loader.api.QuiltLoader;
import net.fabricmc.loader.api.FabricLoader;
import pm.c7.scout.mixinsupport.ClassNodeTransformer; import pm.c7.scout.mixinsupport.ClassNodeTransformer;
import static org.objectweb.asm.Opcodes.*; import static org.objectweb.asm.Opcodes.*;
@ -10,7 +10,7 @@ import static org.objectweb.asm.Opcodes.*;
public class HandledScreenTransformer implements ClassNodeTransformer { public class HandledScreenTransformer implements ClassNodeTransformer {
@Override @Override
public void transform(String name, ClassNode node) { public void transform(String name, ClassNode node) {
var resolver = QuiltLoader.getMappingResolver(); var resolver = FabricLoader.getInstance().getMappingResolver();
var namespace = "intermediary"; var namespace = "intermediary";
var drawSlot = resolver.mapMethodName(namespace, name, "method_2385", "(Lnet/minecraft/class_332;Lnet/minecraft/class_1735;)V"); var drawSlot = resolver.mapMethodName(namespace, name, "method_2385", "(Lnet/minecraft/class_332;Lnet/minecraft/class_1735;)V");

View file

@ -4,7 +4,7 @@ import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment; import net.fabricmc.api.Environment;
import net.minecraft.client.gui.screen.ingame.AbstractInventoryScreen; import net.minecraft.client.gui.screen.ingame.AbstractInventoryScreen;
import net.minecraft.client.gui.screen.ingame.InventoryScreen; import net.minecraft.client.gui.screen.ingame.InventoryScreen;
import net.minecraft.client.gui.screen.recipe.book.RecipeBookProvider; import net.minecraft.client.gui.screen.recipebook.RecipeBookProvider;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.screen.PlayerScreenHandler; import net.minecraft.screen.PlayerScreenHandler;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;

View file

@ -3,7 +3,7 @@ package pm.c7.scout.mixin.client;
import net.fabricmc.api.EnvType; import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment; import net.fabricmc.api.Environment;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.recipe.book.RecipeBookWidget; import net.minecraft.client.gui.screen.recipebook.RecipeBookWidget;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;

View file

@ -1,20 +1,20 @@
package pm.c7.scout.registry; package pm.c7.scout.registry;
import net.fabricmc.fabric.api.item.v1.FabricItemSettings;
import net.minecraft.item.Item; import net.minecraft.item.Item;
import net.minecraft.registry.Registries; import net.minecraft.registry.Registries;
import net.minecraft.util.Rarity; import net.minecraft.util.Rarity;
import org.quiltmc.qsl.item.setting.api.QuiltItemSettings;
import pm.c7.scout.Scout; import pm.c7.scout.Scout;
import pm.c7.scout.ScoutUtil; import pm.c7.scout.ScoutUtil;
import pm.c7.scout.item.BaseBagItem; import pm.c7.scout.item.BaseBagItem;
public class ScoutItems { public class ScoutItems {
public static final Item TANNED_LEATHER = new Item(new QuiltItemSettings()); public static final Item TANNED_LEATHER = new Item(new FabricItemSettings());
public static final Item SATCHEL_STRAP = new Item(new QuiltItemSettings()); public static final Item SATCHEL_STRAP = new Item(new FabricItemSettings());
public static final BaseBagItem SATCHEL = new BaseBagItem(new QuiltItemSettings().maxCount(1), ScoutUtil.MAX_SATCHEL_SLOTS / 2, BaseBagItem.BagType.SATCHEL); public static final BaseBagItem SATCHEL = new BaseBagItem(new FabricItemSettings().maxCount(1), ScoutUtil.MAX_SATCHEL_SLOTS / 2, BaseBagItem.BagType.SATCHEL);
public static final BaseBagItem UPGRADED_SATCHEL = new BaseBagItem(new QuiltItemSettings().maxCount(1).rarity(Rarity.RARE), ScoutUtil.MAX_SATCHEL_SLOTS, BaseBagItem.BagType.SATCHEL); public static final BaseBagItem UPGRADED_SATCHEL = new BaseBagItem(new FabricItemSettings().maxCount(1).rarity(Rarity.RARE), ScoutUtil.MAX_SATCHEL_SLOTS, BaseBagItem.BagType.SATCHEL);
public static final BaseBagItem POUCH = new BaseBagItem(new QuiltItemSettings().maxCount(1), ScoutUtil.MAX_POUCH_SLOTS / 2, BaseBagItem.BagType.POUCH); public static final BaseBagItem POUCH = new BaseBagItem(new FabricItemSettings().maxCount(1), ScoutUtil.MAX_POUCH_SLOTS / 2, BaseBagItem.BagType.POUCH);
public static final BaseBagItem UPGRADED_POUCH = new BaseBagItem(new QuiltItemSettings().maxCount(1).rarity(Rarity.RARE), ScoutUtil.MAX_POUCH_SLOTS, BaseBagItem.BagType.POUCH); public static final BaseBagItem UPGRADED_POUCH = new BaseBagItem(new FabricItemSettings().maxCount(1).rarity(Rarity.RARE), ScoutUtil.MAX_POUCH_SLOTS, BaseBagItem.BagType.POUCH);
public static void init() { public static void init() {
Scout.AUTOREGISTRY.autoRegister(Registries.ITEM, ScoutItems.class, Item.class); Scout.AUTOREGISTRY.autoRegister(Registries.ITEM, ScoutItems.class, Item.class);

View file

@ -6,7 +6,7 @@ import net.minecraft.inventory.Inventory;
import net.minecraft.item.BlockItem; import net.minecraft.item.BlockItem;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.screen.slot.Slot; import net.minecraft.screen.slot.Slot;
import pm.c7.scout.ScoutConfig; import pm.c7.scout.config.ScoutConfig;
import pm.c7.scout.item.BaseBagItem; import pm.c7.scout.item.BaseBagItem;
public class BagSlot extends Slot { public class BagSlot extends Slot {
@ -38,7 +38,7 @@ public class BagSlot extends Slot {
if (stack.getItem() instanceof BlockItem blockItem) { if (stack.getItem() instanceof BlockItem blockItem) {
if (blockItem.getBlock() instanceof ShulkerBoxBlock) if (blockItem.getBlock() instanceof ShulkerBoxBlock)
return enabled && inventory != null && ScoutConfig.CONFIG.allowShulkers.value(); return enabled && inventory != null && ScoutConfig.allowShulkers;
} }
return enabled && inventory != null; return enabled && inventory != null;
@ -67,11 +67,6 @@ public class BagSlot extends Slot {
} }
} }
@Override
public void setStackByPlayer(ItemStack stack) {
this.setStack(stack);
}
@Override @Override
public void markDirty() { public void markDirty() {
if (enabled && this.inventory != null) { if (enabled && this.inventory != null) {

View file

@ -0,0 +1,42 @@
{
"schemaVersion": 1,
"id": "scout",
"version": "${version}",
"name": "Scout",
"description": "A mod focused on \"physically\" extending the inventory (adding slots) through wearing various types of bags.",
"authors": ["Cynosphere"],
"contact": {
"sources": "https://gitdab.com/Cynosphere-mc/Scout"
},
"license": "MIT",
"icon": "assets/scout/icon.png",
"environment": "*",
"entrypoints": {
"main": ["pm.c7.scout.Scout"],
"client": ["pm.c7.scout.client.ScoutClient"],
"emi": ["pm.c7.scout.client.compat.ScoutEmiPlugin"]
},
"mixins": ["scout.mixins.json"],
"depends": {
"fabric": ">=${fabric_version}",
"minecraft": ">=${minecraft_version}",
"trinkets": ">=${trinkets_version}",
"lib39-core": ">=${lib39_version}",
"lib39-dessicant": ">=${lib39_version}"
},
"recommends": {
"emi": ">=${emi_version}"
},
"breaks": {
"infinitory": "*",
"biginv": "*",
"extrainv": "*",
"inventory_backpack": "*",
"realistic-inventory": "*",
"inventorymod": "*"
}
}

View file

@ -1,91 +0,0 @@
{
"schema_version": 1,
"quilt_loader": {
"group": "pm.c7.scout",
"id": "scout",
"version": "${version}",
"metadata": {
"name": "Scout",
"description": "A mod focused on \"physically\" extending the inventory (adding slots) through wearing various types of bags.",
"contributors": {
"Cynosphere": "Owner, Developer",
"Kat": "Original pouch texture",
"makamys": "Original idea"
},
"contact": {
"sources": "https://gitdab.com/Cynosphere-mc/Scout"
},
"icon": "assets/scout/icon.png"
},
"intermediate_mappings": "net.fabricmc:intermediary",
"entrypoints": {
"init": "pm.c7.scout.Scout",
"client_init": "pm.c7.scout.client.ScoutClient",
"emi": "pm.c7.scout.client.compat.ScoutEmiPlugin"
},
"depends": [
{
"id": "quilt_loader",
"versions": ">=0.17.0-"
},
{
"id": "quilted_fabric_api",
"versions": ">=4.0.0-"
},
{
"id": "minecraft",
"versions": ">=${minecraft_version}"
},
{
"id": "trinkets",
"versions": ">=${trinkets_version}"
},
{
"id": "lib39-core",
"versions": ">=${lib39_version}"
},
{
"id": "lib39-dessicant",
"versions": ">=${lib39_version}"
},
{
"id": "emi",
"versions": ">=${emi_version}",
"optional": true
}
],
"breaks": [
{
"id": "infinitory",
"versions": "*",
"reason": "Infinite/Incompatible inventory mod."
},
{
"id": "biginv",
"versions": "*",
"reason": "Infinite/Incompatible inventory mod."
},
{
"id": "extrainv",
"versions": "*",
"reason": "Infinite/Incompatible inventory mod."
},
{
"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."
}
]
},
"mixin": "scout.mixins.json"
}