Fabric-ify
This commit is contained in:
parent
a42bb0507e
commit
01a26a624a
29 changed files with 823 additions and 228 deletions
18
build.gradle
18
build.gradle
|
@ -10,6 +10,10 @@ version = "$project.version+${libs.versions.minecraft.get()}"
|
|||
group = project.maven_group
|
||||
|
||||
repositories {
|
||||
maven {
|
||||
name = "Fabric"
|
||||
url = "https://maven.fabricmc.net/"
|
||||
}
|
||||
maven {
|
||||
name = "TerraformersMC"
|
||||
url = "https://maven.terraformersmc.com/"
|
||||
|
@ -42,11 +46,11 @@ loom {
|
|||
}
|
||||
|
||||
dependencies {
|
||||
minecraft libs.minecraft
|
||||
mappings variantOf(libs.quilt.mappings) { classifier 'intermediary-v2' }
|
||||
modImplementation libs.quilt.loader
|
||||
minecraft "com.mojang:minecraft:${libs.versions.minecraft.get()}"
|
||||
mappings "net.fabricmc:yarn:${libs.versions.minecraft.get()}+${libs.versions.yarn.get()}:v2"
|
||||
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
|
||||
modApi "dev.emi:trinkets:${libs.versions.trinkets.get()}"
|
||||
|
@ -59,17 +63,17 @@ dependencies {
|
|||
|
||||
processResources {
|
||||
inputs.property 'version', version
|
||||
inputs.property 'group', project.group
|
||||
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 'lib39_version', libs.versions.lib39.get()
|
||||
inputs.property 'emi_version', libs.versions.emi.get()
|
||||
|
||||
filesMatching('quilt.mod.json') {
|
||||
filesMatching('fabric.mod.json') {
|
||||
expand (
|
||||
"version": version,
|
||||
"group": project.group,
|
||||
"minecraft_version": libs.versions.minecraft.get(),
|
||||
"fabric_version": libs.versions.fabric.api.get(),
|
||||
"trinkets_version": libs.versions.trinkets.get(),
|
||||
"lib39_version": libs.versions.lib39.get(),
|
||||
"emi_version": libs.versions.emi.get()
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# Gradle Properties
|
||||
org.gradle.jvmargs = -Xmx1G
|
||||
org.gradle.jvmargs = -Xmx4G
|
||||
org.gradle.parallel = true
|
||||
|
||||
# Mod Properties
|
||||
|
|
|
@ -1,28 +1,15 @@
|
|||
[versions]
|
||||
# The latest versions are available at https://lambdaurora.dev/tools/import_quilt.html
|
||||
minecraft = "1.20.1"
|
||||
loom = "1.4.1"
|
||||
loom = "1.5.7"
|
||||
|
||||
quilt_mappings = "1.20.1+build.23"
|
||||
quilt_loader = "0.21.0"
|
||||
|
||||
quilted_fabric_api = "7.4.0+0.90.0-1.20.1"
|
||||
fabric_loader = "0.15.7"
|
||||
yarn = "build.10"
|
||||
fabric_api = "0.91.0"
|
||||
|
||||
trinkets = "3.7.2"
|
||||
lib39 = "1.5.0-experimental6.1"
|
||||
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]
|
||||
quilt_loom = { id = "org.quiltmc.loom", version.ref = "loom" }
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
package pm.c7.scout;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import com.unascribed.lib39.core.api.AutoRegistry;
|
||||
|
||||
import net.fabricmc.api.ModInitializer;
|
||||
import net.fabricmc.fabric.api.itemgroup.v1.FabricItemGroup;
|
||||
import net.minecraft.item.ItemGroup;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
@ -10,27 +13,28 @@ import net.minecraft.registry.Registry;
|
|||
import net.minecraft.text.Text;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import org.quiltmc.loader.api.ModContainer;
|
||||
import org.quiltmc.qsl.base.api.entrypoint.ModInitializer;
|
||||
import pm.c7.scout.config.ScoutConfig;
|
||||
import pm.c7.scout.registry.ScoutItems;
|
||||
|
||||
public class Scout implements ModInitializer {
|
||||
public static final AutoRegistry AUTOREGISTRY = AutoRegistry.of(ScoutUtil.MOD_ID);
|
||||
public static final ItemGroup ITEM_GROUP = FabricItemGroup.builder()
|
||||
.icon(() -> new ItemStack(ScoutItems.SATCHEL))
|
||||
.name(Text.translatable("itemGroup.scout.itemgroup"))
|
||||
.displayName(Text.translatable("itemGroup.scout.itemgroup"))
|
||||
.entries((context, entries) -> {
|
||||
entries.addItem(ScoutItems.TANNED_LEATHER);
|
||||
entries.addItem(ScoutItems.SATCHEL_STRAP);
|
||||
entries.addItem(ScoutItems.SATCHEL);
|
||||
entries.addItem(ScoutItems.UPGRADED_SATCHEL);
|
||||
entries.addItem(ScoutItems.POUCH);
|
||||
entries.addItem(ScoutItems.UPGRADED_POUCH);
|
||||
entries.add(ScoutItems.TANNED_LEATHER);
|
||||
entries.add(ScoutItems.SATCHEL_STRAP);
|
||||
entries.add(ScoutItems.SATCHEL);
|
||||
entries.add(ScoutItems.UPGRADED_SATCHEL);
|
||||
entries.add(ScoutItems.POUCH);
|
||||
entries.add(ScoutItems.UPGRADED_POUCH);
|
||||
})
|
||||
.build();
|
||||
|
||||
|
||||
@Override
|
||||
public void onInitialize(ModContainer mod) {
|
||||
public void onInitialize() {
|
||||
ScoutConfig.loadConfig();
|
||||
ScoutItems.init();
|
||||
Registry.register(Registries.ITEM_GROUP, new Identifier(ScoutUtil.MOD_ID, "itemgroup"), ITEM_GROUP);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -7,7 +7,6 @@ import net.minecraft.client.MinecraftClient;
|
|||
import net.minecraft.client.gui.screen.Screen;
|
||||
import net.minecraft.client.gui.screen.ingame.BeaconScreen;
|
||||
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.entity.player.PlayerEntity;
|
||||
import net.minecraft.inventory.Inventory;
|
||||
|
@ -16,7 +15,6 @@ 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;
|
||||
|
@ -26,7 +24,6 @@ import org.slf4j.Logger;
|
|||
import org.slf4j.LoggerFactory;
|
||||
import pm.c7.scout.item.BaseBagItem;
|
||||
import pm.c7.scout.item.BaseBagItem.BagType;
|
||||
import pm.c7.scout.screen.BagSlot;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
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.TooltipComponentCallback;
|
||||
import net.minecraft.client.gui.screen.ingame.GenericContainerScreen;
|
||||
import net.minecraft.client.gui.screen.ingame.HandledScreen;
|
||||
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.screen.slot.Slot;
|
||||
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.ScoutScreenHandler;
|
||||
import pm.c7.scout.ScoutUtil;
|
||||
|
@ -28,7 +28,7 @@ import pm.c7.scout.screen.BagSlot;
|
|||
|
||||
public class ScoutClient implements ClientModInitializer {
|
||||
@Override
|
||||
public void onInitializeClient(ModContainer mod) {
|
||||
public void onInitializeClient() {
|
||||
ClientPlayNetworking.registerGlobalReceiver(ScoutNetworking.ENABLE_SLOTS, (client, handler, packet, sender) -> {
|
||||
client.execute(() -> {
|
||||
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 (ScoutUtil.isScreenBlacklisted(screen)) {
|
||||
// realistically no one is going to have a screen bigger than 2147483647 pixels
|
||||
|
|
|
@ -2,7 +2,7 @@ package pm.c7.scout.client.gui;
|
|||
|
||||
import com.google.common.math.IntMath;
|
||||
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.item.ItemStack;
|
||||
import net.minecraft.util.collection.DefaultedList;
|
||||
|
@ -31,7 +31,7 @@ public class BagTooltipComponent implements TooltipComponent {
|
|||
}
|
||||
|
||||
@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;
|
||||
|
||||
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);
|
||||
graphics.drawTexture(ScoutUtil.SLOT_TEXTURE, x, y, 0, 46, 7, 18, 18, 256, 256);
|
||||
graphics.drawItem(itemStack, x + 1, y + 1, index);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package pm.c7.scout.client.model;
|
||||
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||
import net.minecraft.client.model.*;
|
||||
import net.minecraft.client.render.VertexConsumer;
|
||||
import net.minecraft.client.render.entity.model.SinglePartEntityModel;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
|
|
|
@ -10,7 +10,7 @@ import net.minecraft.client.render.model.json.ModelTransformationMode;
|
|||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
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.item.BaseBagItem;
|
||||
|
||||
|
@ -29,8 +29,8 @@ public class PouchFeatureRenderer<T extends LivingEntity, M extends EntityModel<
|
|||
if (!leftPouch.isEmpty()) {
|
||||
matrices.push();
|
||||
((PlayerEntityModel<?>) this.getContextModel()).leftLeg.rotate(matrices);
|
||||
matrices.multiply(Axis.X_POSITIVE.rotationDegrees(180.0F));
|
||||
matrices.multiply(Axis.Y_POSITIVE.rotationDegrees(-90.0F));
|
||||
matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(180.0F));
|
||||
matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(-90.0F));
|
||||
matrices.scale(0.325F, 0.325F, 0.325F);
|
||||
matrices.translate(0F, -0.325F, -0.475F);
|
||||
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()) {
|
||||
matrices.push();
|
||||
((PlayerEntityModel<?>) this.getContextModel()).rightLeg.rotate(matrices);
|
||||
matrices.multiply(Axis.X_POSITIVE.rotationDegrees(180.0F));
|
||||
matrices.multiply(Axis.Y_POSITIVE.rotationDegrees(-90.0F));
|
||||
matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(180.0F));
|
||||
matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(-90.0F));
|
||||
matrices.scale(0.325F, 0.325F, 0.325F);
|
||||
matrices.translate(0F, -0.325F, 0.475F);
|
||||
this.heldItemRenderer.renderItem(entity, rightPouch, ModelTransformationMode.FIXED, false, matrices, vertexConsumers, light);
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
package pm.c7.scout.client.render;
|
||||
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||
import net.minecraft.client.model.TexturedModelData;
|
||||
import net.minecraft.client.render.OverlayTexture;
|
||||
import net.minecraft.client.render.RenderLayer;
|
||||
import net.minecraft.client.render.VertexConsumer;
|
||||
import net.minecraft.client.render.VertexConsumerProvider;
|
||||
import net.minecraft.client.render.entity.feature.FeatureRenderer;
|
||||
import net.minecraft.client.render.entity.feature.FeatureRendererContext;
|
||||
|
|
459
src/main/java/pm/c7/scout/config/QDCSS.java
Normal file
459
src/main/java/pm/c7/scout/config/QDCSS.java
Normal 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));
|
||||
}
|
||||
|
||||
}
|
232
src/main/java/pm/c7/scout/config/ScoutConfig.java
Normal file
232
src/main/java/pm/c7/scout/config/ScoutConfig.java
Normal 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);
|
||||
}
|
||||
// }}}
|
||||
}
|
|
@ -3,6 +3,7 @@ package pm.c7.scout.item;
|
|||
import dev.emi.trinkets.api.SlotReference;
|
||||
import dev.emi.trinkets.api.TrinketItem;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;
|
||||
import net.minecraft.client.item.TooltipContext;
|
||||
import net.minecraft.client.item.TooltipData;
|
||||
import net.minecraft.entity.Entity;
|
||||
|
@ -21,7 +22,7 @@ import net.minecraft.util.Formatting;
|
|||
import net.minecraft.util.collection.DefaultedList;
|
||||
import net.minecraft.world.World;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.quiltmc.qsl.networking.api.ServerPlayNetworking;
|
||||
|
||||
import pm.c7.scout.ScoutNetworking;
|
||||
import pm.c7.scout.ScoutScreenHandler;
|
||||
import pm.c7.scout.ScoutUtil;
|
||||
|
|
|
@ -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.ScoutConfig;
|
||||
import pm.c7.scout.config.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 (ScoutConfig.CONFIG.useArrows.value()) {
|
||||
if (ScoutConfig.useArrows) {
|
||||
boolean infinity = bl && itemStack.isOf(Items.ARROW);
|
||||
boolean hasRan = false;
|
||||
|
||||
|
|
|
@ -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.LocalCapture;
|
||||
import pm.c7.scout.ScoutUtil;
|
||||
import pm.c7.scout.ScoutConfig;
|
||||
import pm.c7.scout.config.ScoutConfig;
|
||||
import pm.c7.scout.item.BaseBagItem;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
|
||||
@Mixin(PlayerEntity.class)
|
||||
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 (ScoutConfig.CONFIG.useArrows.value()) {
|
||||
@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) {
|
||||
if (ScoutConfig.useArrows) {
|
||||
var self = (PlayerEntity) (Object) this;
|
||||
var leftPouch = ScoutUtil.findBagItem(self, BaseBagItem.BagType.POUCH, false);
|
||||
var rightPouch = ScoutUtil.findBagItem(self, BaseBagItem.BagType.POUCH, true);
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package pm.c7.scout.mixin;
|
||||
|
||||
import org.objectweb.asm.tree.*;
|
||||
import org.quiltmc.loader.api.QuiltLoader;
|
||||
|
||||
import net.fabricmc.loader.api.FabricLoader;
|
||||
import pm.c7.scout.mixinsupport.ClassNodeTransformer;
|
||||
|
||||
import static org.objectweb.asm.Opcodes.*;
|
||||
|
@ -10,7 +10,7 @@ import static org.objectweb.asm.Opcodes.*;
|
|||
public class PlayerScreenHandlerTransformer implements ClassNodeTransformer {
|
||||
@Override
|
||||
public void transform(String name, ClassNode node) {
|
||||
var resolver = QuiltLoader.getMappingResolver();
|
||||
var resolver = FabricLoader.getInstance().getMappingResolver();
|
||||
var namespace = "intermediary";
|
||||
|
||||
var LPlayerScreenHandler = L(slash(name));
|
||||
|
@ -23,7 +23,7 @@ public class PlayerScreenHandlerTransformer implements ClassNodeTransformer {
|
|||
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 :^)
|
||||
// fix slot checking for trinkets quick move mixin
|
||||
if (mn.name.endsWith("trinkets$quickMove") || mn.name.equals(quickMove)) {
|
||||
for (var insn : mn.instructions) {
|
||||
if (insn instanceof VarInsnNode vin) {
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package pm.c7.scout.mixin;
|
||||
|
||||
import org.objectweb.asm.tree.*;
|
||||
import org.quiltmc.loader.api.QuiltLoader;
|
||||
|
||||
import net.fabricmc.loader.api.FabricLoader;
|
||||
import pm.c7.scout.mixinsupport.ClassNodeTransformer;
|
||||
|
||||
import static org.objectweb.asm.Opcodes.*;
|
||||
|
@ -12,7 +12,7 @@ public class ScreenHandlerTransformer implements ClassNodeTransformer {
|
|||
|
||||
@Override
|
||||
public void transform(String name, ClassNode node) {
|
||||
var resolver = QuiltLoader.getMappingResolver();
|
||||
var resolver = FabricLoader.getInstance().getMappingResolver();
|
||||
var namespace = "intermediary";
|
||||
|
||||
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) {
|
||||
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 (prevInsn.getPrevious() instanceof MethodInsnNode prevPrevInsn && prevPrevInsn.getOpcode() == INVOKEVIRTUAL) {
|
||||
if(prevPrevInsn.owner.equals(DefaultedList)) {
|
||||
|
|
|
@ -7,7 +7,7 @@ import net.minecraft.network.PacketByteBuf;
|
|||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.util.collection.DefaultedList;
|
||||
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.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
|
@ -39,13 +39,6 @@ public class ServerPlayerEntityMixin {
|
|||
slot.setInventory(null);
|
||||
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);
|
||||
|
@ -60,13 +53,6 @@ public class ServerPlayerEntityMixin {
|
|||
slot.setInventory(null);
|
||||
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);
|
||||
|
@ -81,14 +67,10 @@ public class ServerPlayerEntityMixin {
|
|||
slot.setInventory(null);
|
||||
slot.setEnabled(false);
|
||||
}
|
||||
|
||||
PacketByteBuf packet = new PacketByteBuf(Unpooled.buffer());
|
||||
packet.writeBoolean(false);
|
||||
packet.writeInt(1);
|
||||
packet.writeItemStack(rightPouchStack);
|
||||
|
||||
ServerPlayNetworking.send(player, ScoutNetworking.ENABLE_SLOTS, packet);
|
||||
}
|
||||
|
||||
PacketByteBuf packet = new PacketByteBuf(Unpooled.buffer());
|
||||
ServerPlayNetworking.send(player, ScoutNetworking.ENABLE_SLOTS, packet);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ import net.fabricmc.api.EnvType;
|
|||
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.client.gui.screen.recipebook.RecipeBookProvider;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.screen.AbstractFurnaceScreenHandler;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
|
|
|
@ -4,11 +4,9 @@ import net.fabricmc.api.EnvType;
|
|||
import net.fabricmc.api.Environment;
|
||||
import net.minecraft.client.gui.screen.ingame.CraftingScreen;
|
||||
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.client.gui.screen.recipebook.RecipeBookProvider;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.screen.CraftingScreenHandler;
|
||||
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;
|
||||
|
|
|
@ -3,7 +3,7 @@ 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.GuiGraphics;
|
||||
import net.minecraft.client.gui.DrawContext;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
import net.minecraft.client.gui.screen.ingame.GenericContainerScreen;
|
||||
import net.minecraft.client.gui.screen.ingame.HandledScreen;
|
||||
|
@ -44,8 +44,8 @@ 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/gui/GuiGraphics;FII)V"))
|
||||
private void scout$drawSatchelRow(GuiGraphics graphics, int mouseX, int mouseY, float delta, CallbackInfo ci) {
|
||||
@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(DrawContext 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);
|
||||
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))
|
||||
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)) {
|
||||
ItemStack leftPouchStack = ScoutUtil.findBagItem(this.client.player, BaseBagItem.BagType.POUCH, false);
|
||||
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"))
|
||||
public void scout$drawOurSlots(GuiGraphics graphics, int mouseX, int mouseY, float delta, CallbackInfo ci) {
|
||||
@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(DrawContext 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);
|
||||
|
@ -309,9 +309,9 @@ public abstract class HandledScreenMixin<T extends ScreenHandler> extends Screen
|
|||
}
|
||||
|
||||
@Shadow
|
||||
private void drawSlot(GuiGraphics graphics, Slot slot) {}
|
||||
private void drawSlot(DrawContext graphics, Slot slot) {}
|
||||
@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
|
||||
private boolean isPointOverSlot(Slot slot, double pointX, double pointY) {
|
||||
return false;
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package pm.c7.scout.mixin.client;
|
||||
|
||||
import org.objectweb.asm.tree.*;
|
||||
import org.quiltmc.loader.api.QuiltLoader;
|
||||
|
||||
import net.fabricmc.loader.api.FabricLoader;
|
||||
import pm.c7.scout.mixinsupport.ClassNodeTransformer;
|
||||
|
||||
import static org.objectweb.asm.Opcodes.*;
|
||||
|
@ -10,7 +10,7 @@ import static org.objectweb.asm.Opcodes.*;
|
|||
public class HandledScreenTransformer implements ClassNodeTransformer {
|
||||
@Override
|
||||
public void transform(String name, ClassNode node) {
|
||||
var resolver = QuiltLoader.getMappingResolver();
|
||||
var resolver = FabricLoader.getInstance().getMappingResolver();
|
||||
var namespace = "intermediary";
|
||||
|
||||
var drawSlot = resolver.mapMethodName(namespace, name, "method_2385", "(Lnet/minecraft/class_332;Lnet/minecraft/class_1735;)V");
|
||||
|
|
|
@ -4,7 +4,7 @@ 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.gui.screen.recipebook.RecipeBookProvider;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.screen.PlayerScreenHandler;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
|
|
|
@ -3,7 +3,7 @@ package pm.c7.scout.mixin.client;
|
|||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
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 org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
package pm.c7.scout.registry;
|
||||
|
||||
import net.fabricmc.fabric.api.item.v1.FabricItemSettings;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.registry.Registries;
|
||||
import net.minecraft.util.Rarity;
|
||||
import org.quiltmc.qsl.item.setting.api.QuiltItemSettings;
|
||||
import pm.c7.scout.Scout;
|
||||
import pm.c7.scout.ScoutUtil;
|
||||
import pm.c7.scout.item.BaseBagItem;
|
||||
|
||||
public class ScoutItems {
|
||||
public static final Item TANNED_LEATHER = new Item(new QuiltItemSettings());
|
||||
public static final Item SATCHEL_STRAP = new Item(new QuiltItemSettings());
|
||||
public static final BaseBagItem SATCHEL = new BaseBagItem(new QuiltItemSettings().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 POUCH = new BaseBagItem(new QuiltItemSettings().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 Item TANNED_LEATHER = new Item(new FabricItemSettings());
|
||||
public static final Item SATCHEL_STRAP = new Item(new FabricItemSettings());
|
||||
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 FabricItemSettings().maxCount(1).rarity(Rarity.RARE), ScoutUtil.MAX_SATCHEL_SLOTS, BaseBagItem.BagType.SATCHEL);
|
||||
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 FabricItemSettings().maxCount(1).rarity(Rarity.RARE), ScoutUtil.MAX_POUCH_SLOTS, BaseBagItem.BagType.POUCH);
|
||||
|
||||
public static void init() {
|
||||
Scout.AUTOREGISTRY.autoRegister(Registries.ITEM, ScoutItems.class, Item.class);
|
||||
|
|
|
@ -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.ScoutConfig;
|
||||
import pm.c7.scout.config.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 enabled && inventory != null && ScoutConfig.CONFIG.allowShulkers.value();
|
||||
return enabled && inventory != null && ScoutConfig.allowShulkers;
|
||||
}
|
||||
|
||||
return enabled && inventory != null;
|
||||
|
@ -67,11 +67,6 @@ public class BagSlot extends Slot {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStackByPlayer(ItemStack stack) {
|
||||
this.setStack(stack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void markDirty() {
|
||||
if (enabled && this.inventory != null) {
|
||||
|
|
42
src/main/resources/fabric.mod.json
Normal file
42
src/main/resources/fabric.mod.json
Normal 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": "*"
|
||||
}
|
||||
}
|
|
@ -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"
|
||||
}
|
Loading…
Reference in a new issue