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
 | 
					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()
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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" }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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.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;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										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.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;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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)) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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");
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										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…
	
	Add table
		Add a link
		
	
		Reference in a new issue