├── jitpack.yml ├── changelog.md ├── gradle.properties ├── src └── main │ ├── resources │ ├── assets │ │ └── packagedauto │ │ │ ├── models │ │ │ ├── item │ │ │ │ ├── crafter.json │ │ │ │ ├── encoder.json │ │ │ │ ├── packager.json │ │ │ │ ├── distributor.json │ │ │ │ ├── unpackager.json │ │ │ │ ├── crafting_proxy.json │ │ │ │ ├── packager_extension.json │ │ │ │ ├── packaging_provider.json │ │ │ │ ├── fluid_package_filler.json │ │ │ │ ├── guide.json │ │ │ │ ├── package.json │ │ │ │ ├── volume_package.json │ │ │ │ ├── package_component.json │ │ │ │ ├── proxy_marker_bound.json │ │ │ │ ├── me_package_component.json │ │ │ │ ├── recipe_holder_filled.json │ │ │ │ ├── settings_cloner_filled.json │ │ │ │ ├── distributor_marker_bound.json │ │ │ │ ├── proxy_marker.json │ │ │ │ ├── recipe_holder.json │ │ │ │ ├── settings_cloner.json │ │ │ │ └── distributor_marker.json │ │ │ └── block │ │ │ │ ├── crafter.json │ │ │ │ ├── encoder.json │ │ │ │ ├── packager.json │ │ │ │ ├── distributor.json │ │ │ │ ├── unpackager.json │ │ │ │ ├── crafting_proxy.json │ │ │ │ ├── packager_extension.json │ │ │ │ ├── packaging_provider.json │ │ │ │ └── fluid_package_filler.json │ │ │ ├── blockstates │ │ │ ├── crafter.json │ │ │ ├── encoder.json │ │ │ ├── packager.json │ │ │ ├── distributor.json │ │ │ ├── unpackager.json │ │ │ ├── crafting_proxy.json │ │ │ ├── packager_extension.json │ │ │ ├── packaging_provider.json │ │ │ └── fluid_package_filler.json │ │ │ ├── textures │ │ │ ├── gui │ │ │ │ ├── jei.png │ │ │ │ ├── crafter.png │ │ │ │ ├── encoder.png │ │ │ │ ├── packager.png │ │ │ │ ├── distributor.png │ │ │ │ ├── unpackager.png │ │ │ │ ├── crafting_proxy.png │ │ │ │ ├── amount_specifying.png │ │ │ │ ├── packager_extension.png │ │ │ │ ├── packaging_provider.png │ │ │ │ └── fluid_package_filler.png │ │ │ ├── item │ │ │ │ ├── guide.png │ │ │ │ ├── package.png │ │ │ │ ├── proxy_marker.png │ │ │ │ ├── recipe_holder.png │ │ │ │ ├── settings_cloner.png │ │ │ │ ├── volume_package.png │ │ │ │ ├── distributor_marker.png │ │ │ │ ├── package_component.png │ │ │ │ ├── proxy_marker_bound.png │ │ │ │ ├── me_package_component.png │ │ │ │ ├── recipe_holder_filled.png │ │ │ │ ├── settings_cloner_filled.png │ │ │ │ └── distributor_marker_bound.png │ │ │ └── block │ │ │ │ ├── crafter_side.png │ │ │ │ ├── crafter_top.png │ │ │ │ ├── encoder_side.png │ │ │ │ ├── encoder_top.png │ │ │ │ ├── packager_top.png │ │ │ │ ├── distributor_top.png │ │ │ │ ├── machine_bottom.png │ │ │ │ ├── packager_side.png │ │ │ │ ├── unpackager_side.png │ │ │ │ ├── unpackager_top.png │ │ │ │ ├── distributor_side.png │ │ │ │ ├── crafting_proxy_side.png │ │ │ │ ├── crafting_proxy_top.png │ │ │ │ ├── packager_extension_top.png │ │ │ │ ├── packaging_provider_top.png │ │ │ │ ├── fluid_package_filler_side.png │ │ │ │ ├── fluid_package_filler_top.png │ │ │ │ └── packaging_provider_side.png │ │ │ └── patchouli_books │ │ │ └── guide │ │ │ └── en_us │ │ │ ├── categories │ │ │ ├── core.json │ │ │ └── recipe.json │ │ │ ├── entries │ │ │ ├── recipe │ │ │ │ ├── processing.json │ │ │ │ ├── ordered.json │ │ │ │ ├── crafting.json │ │ │ │ └── crafting_proxy.json │ │ │ └── core │ │ │ │ ├── components.json │ │ │ │ ├── package.json │ │ │ │ ├── settings_cloner.json │ │ │ │ ├── introduction.json │ │ │ │ ├── recipe_holder.json │ │ │ │ ├── fluid_package_filler.json │ │ │ │ ├── volume_package.json │ │ │ │ ├── packaging_provider.json │ │ │ │ ├── encoder.json │ │ │ │ └── packager_extension.json │ │ │ └── templates │ │ │ └── spotlight2.json │ ├── data │ │ ├── packagedauto │ │ │ ├── recipes │ │ │ │ ├── proxy_marker_cloning.json │ │ │ │ ├── recipe_holder_cloning.json │ │ │ │ ├── distributor_marker_cloning.json │ │ │ │ ├── patchouli_guide.json │ │ │ │ ├── proxy_marker.json │ │ │ │ ├── distributor_marker.json │ │ │ │ ├── settings_cloner.json │ │ │ │ ├── package_component.json │ │ │ │ ├── recipe_holder.json │ │ │ │ ├── encoder.json │ │ │ │ ├── fluid_package_filler.json │ │ │ │ ├── distributor.json │ │ │ │ ├── crafting_proxy.json │ │ │ │ ├── crafter_ae.json │ │ │ │ ├── packager_ae.json │ │ │ │ ├── unpackager_ae.json │ │ │ │ ├── me_package_component.json │ │ │ │ ├── packaging_provider.json │ │ │ │ ├── packager_extension_ae.json │ │ │ │ ├── crafter.json │ │ │ │ ├── unpackager.json │ │ │ │ ├── packager.json │ │ │ │ └── packager_extension.json │ │ │ ├── patchouli_books │ │ │ │ └── guide │ │ │ │ │ └── book.json │ │ │ └── loot_tables │ │ │ │ └── blocks │ │ │ │ ├── crafter.json │ │ │ │ ├── encoder.json │ │ │ │ ├── packager.json │ │ │ │ ├── distributor.json │ │ │ │ ├── unpackager.json │ │ │ │ ├── crafting_proxy.json │ │ │ │ ├── packager_extension.json │ │ │ │ ├── packaging_provider.json │ │ │ │ └── fluid_package_filler.json │ │ └── minecraft │ │ │ └── tags │ │ │ └── blocks │ │ │ └── mineable │ │ │ └── pickaxe.json │ ├── pack.mcmeta │ ├── packagedauto.logo.png │ └── META-INF │ │ └── mods.toml │ └── java │ └── thelm │ └── packagedauto │ ├── api │ ├── IProxyMarkerItem.java │ ├── IDistributorMarkerItem.java │ ├── ISettingsClonerItem.java │ ├── IFluidStackWrapper.java │ ├── IRecipeSlotsViewWrapper.java │ ├── IVolumePackageItem.java │ ├── IMarkerItem.java │ ├── IPackageItem.java │ ├── IPackageRecipeListItem.java │ ├── IRecipeSlotViewWrapper.java │ ├── IPackagePattern.java │ ├── PatternType.java │ ├── IPackageRecipeList.java │ ├── IPackageCraftingMachine.java │ ├── IVolumeStackWrapper.java │ ├── DirectionalGlobalPos.java │ ├── ISettingsCloneable.java │ ├── SettingsClonerData.java │ ├── IPackageRecipeType.java │ ├── PackagedAutoApi.java │ ├── IPackageRecipeInfo.java │ └── IVolumeType.java │ ├── item │ ├── MiscItem.java │ ├── ProxyMarkerItem.java │ └── DistributorMarkerItem.java │ ├── recipe │ ├── IPositionedProcessingPackageRecipeInfo.java │ ├── ICraftingPackageRecipeInfo.java │ └── OrderedProcessingPackageRecipeType.java │ ├── slot │ ├── PreviewVolumeSlot.java │ ├── SingleStackSlot.java │ ├── RemoveOnlySlot.java │ ├── PreviewSlot.java │ ├── FalseCopySlot.java │ ├── CrafterRemoveOnlySlot.java │ └── FalseCopyVolumeSlot.java │ ├── menu │ ├── EmptyMenu.java │ ├── PackagingProviderMenu.java │ ├── VolumeAmountSpecifyingMenu.java │ ├── ItemAmountSpecifyingMenu.java │ ├── CraftingProxyMenu.java │ ├── factory │ │ └── PositionalBlockEntityMenuFactory.java │ ├── FluidPackageFillerMenu.java │ ├── DistributorMenu.java │ ├── UnpackagerMenu.java │ ├── CrafterMenu.java │ ├── PackagerMenu.java │ └── PackagerExtensionMenu.java │ ├── PackagedAuto.java │ ├── integration │ ├── jei │ │ ├── RecipeSlotsViewWrapper.java │ │ ├── RecipeSlotViewWrapper.java │ │ ├── EncoderGuiHandler.java │ │ ├── FluidVolumeGuiHandler.java │ │ ├── EncoderGhostIngredientHandler.java │ │ └── EncoderTransferHandler.java │ ├── appeng │ │ ├── AppEngEventHandler.java │ │ └── recipe │ │ │ ├── RecipeCraftingPatternDetails.java │ │ │ ├── PackageCraftingPatternDetails.java │ │ │ ├── SimpleInput.java │ │ │ ├── PackagePatternDetailsDecoder.java │ │ │ └── DirectCraftingPatternDetails.java │ └── emi │ │ ├── EmiRecipeWrapper.java │ │ ├── FluidVolumeStackProvider.java │ │ ├── EmiIngredientWrapper.java │ │ └── EncoderRecipeHandler.java │ ├── client │ ├── RenderTimer.java │ └── screen │ │ ├── DistributorScreen.java │ │ ├── CraftingProxyScreen.java │ │ ├── ItemAmountSpecifyingScreen.java │ │ ├── CrafterScreen.java │ │ └── VolumeAmountSpecifyingScreen.java │ ├── inventory │ ├── FluidPackageFillerItemHandlerWrapper.java │ ├── EncoderItemHandler.java │ ├── PackagerItemHandlerWrapper.java │ ├── CrafterItemHandlerWrapper.java │ ├── PackagerExtensionItemHandlerWrapper.java │ ├── UnpackagerItemHandlerWrapper.java │ ├── CrafterItemHandler.java │ ├── FluidPackageFillerItemHandler.java │ ├── BaseVolumeInventory.java │ ├── BaseItemHandler.java │ ├── PackagerExtensionItemHandler.java │ ├── CraftingProxyItemHandler.java │ ├── DistributorItemHandler.java │ └── SidedItemHandlerWrapper.java │ ├── network │ └── packet │ │ ├── EjectTrackerPacket.java │ │ ├── SaveRecipeListPacket.java │ │ ├── TrackerCountPacket.java │ │ ├── SetFluidAmountPacket.java │ │ ├── SetPatternIndexPacket.java │ │ ├── CycleRecipeTypePacket.java │ │ ├── LoadRecipeListPacket.java │ │ ├── ChangeProvidingPacket.java │ │ ├── ChangeBlockingPacket.java │ │ ├── ChangePackagingPacket.java │ │ ├── SetItemStackPacket.java │ │ ├── SetRecipePacket.java │ │ ├── SizedMarkerPacket.java │ │ └── SyncEnergyPacket.java │ ├── block │ ├── EncoderBlock.java │ ├── CrafterBlock.java │ ├── PackagerBlock.java │ ├── PackagerExtensionBlock.java │ ├── FluidPackageFillerBlock.java │ └── CraftingProxyBlock.java │ ├── volume │ ├── UnknownStackWrapper.java │ └── FluidStackWrapper.java │ └── util │ ├── PackageRecipeList.java │ ├── OptionalIntDataSlot.java │ └── PackagePattern.java ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── README.md ├── .gitignore ├── .gitattributes ├── settings.gradle └── LICENSE /jitpack.yml: -------------------------------------------------------------------------------- 1 | jdk: 2 | - openjdk21 3 | -------------------------------------------------------------------------------- /changelog.md: -------------------------------------------------------------------------------- 1 | Use better validity checks in core recipe handling 2 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx3G 2 | org.gradle.daemon=false 3 | loom.platform=forge 4 | -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/models/item/crafter.json: -------------------------------------------------------------------------------- 1 | { 2 | "parent": "packagedauto:block/crafter" 3 | } 4 | -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/models/item/encoder.json: -------------------------------------------------------------------------------- 1 | { 2 | "parent": "packagedauto:block/encoder" 3 | } 4 | -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/models/item/packager.json: -------------------------------------------------------------------------------- 1 | { 2 | "parent": "packagedauto:block/packager" 3 | } 4 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheLMiffy1111/PackagedAuto/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/models/item/distributor.json: -------------------------------------------------------------------------------- 1 | { 2 | "parent": "packagedauto:block/distributor" 3 | } 4 | -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/models/item/unpackager.json: -------------------------------------------------------------------------------- 1 | { 2 | "parent": "packagedauto:block/unpackager" 3 | } 4 | -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/models/item/crafting_proxy.json: -------------------------------------------------------------------------------- 1 | { 2 | "parent": "packagedauto:block/crafting_proxy" 3 | } 4 | -------------------------------------------------------------------------------- /src/main/resources/data/packagedauto/recipes/proxy_marker_cloning.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "packagedauto:proxy_marker_cloning" 3 | } 4 | -------------------------------------------------------------------------------- /src/main/resources/data/packagedauto/recipes/recipe_holder_cloning.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "packagedauto:recipe_holder_cloning" 3 | } 4 | -------------------------------------------------------------------------------- /src/main/resources/pack.mcmeta: -------------------------------------------------------------------------------- 1 | { 2 | "pack": { 3 | "pack_format": 15, 4 | "description": "PackagedAuto Resources" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/models/item/packager_extension.json: -------------------------------------------------------------------------------- 1 | { 2 | "parent": "packagedauto:block/packager_extension" 3 | } 4 | -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/models/item/packaging_provider.json: -------------------------------------------------------------------------------- 1 | { 2 | "parent": "packagedauto:block/packaging_provider" 3 | } 4 | -------------------------------------------------------------------------------- /src/main/resources/data/packagedauto/recipes/distributor_marker_cloning.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "packagedauto:distributor_marker_cloning" 3 | } 4 | -------------------------------------------------------------------------------- /src/main/resources/packagedauto.logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheLMiffy1111/PackagedAuto/HEAD/src/main/resources/packagedauto.logo.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PackagedAuto 2 | PackagedAuto is an Applied Energistics 2 addon that uses "packages" to allow autocrafting with more than 9 items. 3 | -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/models/item/fluid_package_filler.json: -------------------------------------------------------------------------------- 1 | { 2 | "parent": "packagedauto:block/fluid_package_filler" 3 | } 4 | -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/blockstates/crafter.json: -------------------------------------------------------------------------------- 1 | { 2 | "variants": { 3 | "": { "model": "packagedauto:block/crafter" } 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/blockstates/encoder.json: -------------------------------------------------------------------------------- 1 | { 2 | "variants": { 3 | "": { "model": "packagedauto:block/encoder" } 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/blockstates/packager.json: -------------------------------------------------------------------------------- 1 | { 2 | "variants": { 3 | "": { "model": "packagedauto:block/packager" } 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/blockstates/distributor.json: -------------------------------------------------------------------------------- 1 | { 2 | "variants": { 3 | "": { "model": "packagedauto:block/distributor" } 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/blockstates/unpackager.json: -------------------------------------------------------------------------------- 1 | { 2 | "variants": { 3 | "": { "model": "packagedauto:block/unpackager" } 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/api/IProxyMarkerItem.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.api; 2 | 3 | public interface IProxyMarkerItem extends IMarkerItem { 4 | } 5 | -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/blockstates/crafting_proxy.json: -------------------------------------------------------------------------------- 1 | { 2 | "variants": { 3 | "": { "model": "packagedauto:block/crafting_proxy" } 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/api/IDistributorMarkerItem.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.api; 2 | 3 | public interface IDistributorMarkerItem extends IMarkerItem { 4 | } 5 | -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/blockstates/packager_extension.json: -------------------------------------------------------------------------------- 1 | { 2 | "variants": { 3 | "": { "model": "packagedauto:block/packager_extension" } 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/blockstates/packaging_provider.json: -------------------------------------------------------------------------------- 1 | { 2 | "variants": { 3 | "": { "model": "packagedauto:block/packaging_provider" } 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/models/item/guide.json: -------------------------------------------------------------------------------- 1 | { 2 | "parent": "item/generated", 3 | "textures": { 4 | "layer0": "packagedauto:item/guide" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/models/item/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "parent": "item/generated", 3 | "textures": { 4 | "layer0": "packagedauto:item/package" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/blockstates/fluid_package_filler.json: -------------------------------------------------------------------------------- 1 | { 2 | "variants": { 3 | "": { "model": "packagedauto:block/fluid_package_filler" } 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/textures/gui/jei.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheLMiffy1111/PackagedAuto/HEAD/src/main/resources/assets/packagedauto/textures/gui/jei.png -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/textures/gui/crafter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheLMiffy1111/PackagedAuto/HEAD/src/main/resources/assets/packagedauto/textures/gui/crafter.png -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/textures/gui/encoder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheLMiffy1111/PackagedAuto/HEAD/src/main/resources/assets/packagedauto/textures/gui/encoder.png -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/textures/item/guide.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheLMiffy1111/PackagedAuto/HEAD/src/main/resources/assets/packagedauto/textures/item/guide.png -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/models/item/volume_package.json: -------------------------------------------------------------------------------- 1 | { 2 | "parent": "item/generated", 3 | "textures": { 4 | "layer0": "packagedauto:item/volume_package" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/textures/gui/packager.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheLMiffy1111/PackagedAuto/HEAD/src/main/resources/assets/packagedauto/textures/gui/packager.png -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/textures/item/package.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheLMiffy1111/PackagedAuto/HEAD/src/main/resources/assets/packagedauto/textures/item/package.png -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/models/item/package_component.json: -------------------------------------------------------------------------------- 1 | { 2 | "parent": "item/generated", 3 | "textures": { 4 | "layer0": "packagedauto:item/package_component" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/textures/gui/distributor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheLMiffy1111/PackagedAuto/HEAD/src/main/resources/assets/packagedauto/textures/gui/distributor.png -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/textures/gui/unpackager.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheLMiffy1111/PackagedAuto/HEAD/src/main/resources/assets/packagedauto/textures/gui/unpackager.png -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/models/item/proxy_marker_bound.json: -------------------------------------------------------------------------------- 1 | { 2 | "parent": "item/generated", 3 | "textures": { 4 | "layer0": "packagedauto:item/proxy_marker_bound" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/textures/block/crafter_side.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheLMiffy1111/PackagedAuto/HEAD/src/main/resources/assets/packagedauto/textures/block/crafter_side.png -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/textures/block/crafter_top.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheLMiffy1111/PackagedAuto/HEAD/src/main/resources/assets/packagedauto/textures/block/crafter_top.png -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/textures/block/encoder_side.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheLMiffy1111/PackagedAuto/HEAD/src/main/resources/assets/packagedauto/textures/block/encoder_side.png -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/textures/block/encoder_top.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheLMiffy1111/PackagedAuto/HEAD/src/main/resources/assets/packagedauto/textures/block/encoder_top.png -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/textures/block/packager_top.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheLMiffy1111/PackagedAuto/HEAD/src/main/resources/assets/packagedauto/textures/block/packager_top.png -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/textures/gui/crafting_proxy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheLMiffy1111/PackagedAuto/HEAD/src/main/resources/assets/packagedauto/textures/gui/crafting_proxy.png -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/textures/item/proxy_marker.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheLMiffy1111/PackagedAuto/HEAD/src/main/resources/assets/packagedauto/textures/item/proxy_marker.png -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/textures/item/recipe_holder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheLMiffy1111/PackagedAuto/HEAD/src/main/resources/assets/packagedauto/textures/item/recipe_holder.png -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/models/item/me_package_component.json: -------------------------------------------------------------------------------- 1 | { 2 | "parent": "item/generated", 3 | "textures": { 4 | "layer0": "packagedauto:item/me_package_component" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/models/item/recipe_holder_filled.json: -------------------------------------------------------------------------------- 1 | { 2 | "parent": "item/generated", 3 | "textures": { 4 | "layer0": "packagedauto:item/recipe_holder_filled" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/models/item/settings_cloner_filled.json: -------------------------------------------------------------------------------- 1 | { 2 | "parent": "item/generated", 3 | "textures": { 4 | "layer0": "packagedauto:item/settings_cloner_filled" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/textures/block/distributor_top.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheLMiffy1111/PackagedAuto/HEAD/src/main/resources/assets/packagedauto/textures/block/distributor_top.png -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/textures/block/machine_bottom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheLMiffy1111/PackagedAuto/HEAD/src/main/resources/assets/packagedauto/textures/block/machine_bottom.png -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/textures/block/packager_side.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheLMiffy1111/PackagedAuto/HEAD/src/main/resources/assets/packagedauto/textures/block/packager_side.png -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/textures/block/unpackager_side.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheLMiffy1111/PackagedAuto/HEAD/src/main/resources/assets/packagedauto/textures/block/unpackager_side.png -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/textures/block/unpackager_top.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheLMiffy1111/PackagedAuto/HEAD/src/main/resources/assets/packagedauto/textures/block/unpackager_top.png -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/textures/gui/amount_specifying.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheLMiffy1111/PackagedAuto/HEAD/src/main/resources/assets/packagedauto/textures/gui/amount_specifying.png -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/textures/item/settings_cloner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheLMiffy1111/PackagedAuto/HEAD/src/main/resources/assets/packagedauto/textures/item/settings_cloner.png -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/textures/item/volume_package.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheLMiffy1111/PackagedAuto/HEAD/src/main/resources/assets/packagedauto/textures/item/volume_package.png -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/models/item/distributor_marker_bound.json: -------------------------------------------------------------------------------- 1 | { 2 | "parent": "item/generated", 3 | "textures": { 4 | "layer0": "packagedauto:item/distributor_marker_bound" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/textures/block/distributor_side.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheLMiffy1111/PackagedAuto/HEAD/src/main/resources/assets/packagedauto/textures/block/distributor_side.png -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/textures/gui/packager_extension.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheLMiffy1111/PackagedAuto/HEAD/src/main/resources/assets/packagedauto/textures/gui/packager_extension.png -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/textures/gui/packaging_provider.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheLMiffy1111/PackagedAuto/HEAD/src/main/resources/assets/packagedauto/textures/gui/packaging_provider.png -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/textures/item/distributor_marker.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheLMiffy1111/PackagedAuto/HEAD/src/main/resources/assets/packagedauto/textures/item/distributor_marker.png -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/textures/item/package_component.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheLMiffy1111/PackagedAuto/HEAD/src/main/resources/assets/packagedauto/textures/item/package_component.png -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/textures/item/proxy_marker_bound.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheLMiffy1111/PackagedAuto/HEAD/src/main/resources/assets/packagedauto/textures/item/proxy_marker_bound.png -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/textures/block/crafting_proxy_side.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheLMiffy1111/PackagedAuto/HEAD/src/main/resources/assets/packagedauto/textures/block/crafting_proxy_side.png -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/textures/block/crafting_proxy_top.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheLMiffy1111/PackagedAuto/HEAD/src/main/resources/assets/packagedauto/textures/block/crafting_proxy_top.png -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/textures/gui/fluid_package_filler.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheLMiffy1111/PackagedAuto/HEAD/src/main/resources/assets/packagedauto/textures/gui/fluid_package_filler.png -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/textures/item/me_package_component.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheLMiffy1111/PackagedAuto/HEAD/src/main/resources/assets/packagedauto/textures/item/me_package_component.png -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/textures/item/recipe_holder_filled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheLMiffy1111/PackagedAuto/HEAD/src/main/resources/assets/packagedauto/textures/item/recipe_holder_filled.png -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/textures/block/packager_extension_top.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheLMiffy1111/PackagedAuto/HEAD/src/main/resources/assets/packagedauto/textures/block/packager_extension_top.png -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/textures/block/packaging_provider_top.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheLMiffy1111/PackagedAuto/HEAD/src/main/resources/assets/packagedauto/textures/block/packaging_provider_top.png -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/textures/item/settings_cloner_filled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheLMiffy1111/PackagedAuto/HEAD/src/main/resources/assets/packagedauto/textures/item/settings_cloner_filled.png -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/textures/block/fluid_package_filler_side.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheLMiffy1111/PackagedAuto/HEAD/src/main/resources/assets/packagedauto/textures/block/fluid_package_filler_side.png -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/textures/block/fluid_package_filler_top.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheLMiffy1111/PackagedAuto/HEAD/src/main/resources/assets/packagedauto/textures/block/fluid_package_filler_top.png -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/textures/block/packaging_provider_side.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheLMiffy1111/PackagedAuto/HEAD/src/main/resources/assets/packagedauto/textures/block/packaging_provider_side.png -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/textures/item/distributor_marker_bound.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheLMiffy1111/PackagedAuto/HEAD/src/main/resources/assets/packagedauto/textures/item/distributor_marker_bound.png -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/api/ISettingsClonerItem.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.api; 2 | 3 | import net.minecraft.world.item.ItemStack; 4 | 5 | public interface ISettingsClonerItem { 6 | 7 | SettingsClonerData getData(ItemStack stack); 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/api/IFluidStackWrapper.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.api; 2 | 3 | import net.minecraftforge.fluids.FluidStack; 4 | 5 | public interface IFluidStackWrapper extends IVolumeStackWrapper { 6 | 7 | FluidStack getFluid(); 8 | } 9 | -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/patchouli_books/guide/en_us/categories/core.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Core Components", 3 | "description": "Core items and machines of $(#822)PackagedAuto/$.", 4 | "icon": "packagedauto:package_component", 5 | "sortnum": 0 6 | } 7 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/api/IRecipeSlotsViewWrapper.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.api; 2 | 3 | import java.util.List; 4 | 5 | public interface IRecipeSlotsViewWrapper { 6 | 7 | Object getRecipe(); 8 | 9 | List getRecipeSlotViews(); 10 | } 11 | -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/models/block/crafter.json: -------------------------------------------------------------------------------- 1 | { 2 | "parent": "block/cube_bottom_top", 3 | "textures": { 4 | "side": "packagedauto:block/crafter_side", 5 | "top": "packagedauto:block/crafter_top", 6 | "bottom": "packagedauto:block/machine_bottom" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/models/block/encoder.json: -------------------------------------------------------------------------------- 1 | { 2 | "parent": "block/cube_bottom_top", 3 | "textures": { 4 | "side": "packagedauto:block/encoder_side", 5 | "top": "packagedauto:block/encoder_top", 6 | "bottom": "packagedauto:block/machine_bottom" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/models/block/packager.json: -------------------------------------------------------------------------------- 1 | { 2 | "parent": "block/cube_bottom_top", 3 | "textures": { 4 | "side": "packagedauto:block/packager_side", 5 | "top": "packagedauto:block/packager_top", 6 | "bottom": "packagedauto:block/machine_bottom" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/models/block/distributor.json: -------------------------------------------------------------------------------- 1 | { 2 | "parent": "block/cube_bottom_top", 3 | "textures": { 4 | "side": "packagedauto:block/distributor_side", 5 | "top": "packagedauto:block/distributor_top", 6 | "bottom": "packagedauto:block/machine_bottom" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/models/block/unpackager.json: -------------------------------------------------------------------------------- 1 | { 2 | "parent": "block/cube_bottom_top", 3 | "textures": { 4 | "side": "packagedauto:block/unpackager_side", 5 | "top": "packagedauto:block/unpackager_top", 6 | "bottom": "packagedauto:block/machine_bottom" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/models/block/crafting_proxy.json: -------------------------------------------------------------------------------- 1 | { 2 | "parent": "block/cube_bottom_top", 3 | "textures": { 4 | "side": "packagedauto:block/crafting_proxy_side", 5 | "top": "packagedauto:block/crafting_proxy_top", 6 | "bottom": "packagedauto:block/machine_bottom" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/models/block/packager_extension.json: -------------------------------------------------------------------------------- 1 | { 2 | "parent": "block/cube_bottom_top", 3 | "textures": { 4 | "side": "packagedauto:block/packager_side", 5 | "top": "packagedauto:block/packager_extension_top", 6 | "bottom": "packagedauto:block/machine_bottom" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/models/block/packaging_provider.json: -------------------------------------------------------------------------------- 1 | { 2 | "parent": "block/cube_bottom_top", 3 | "textures": { 4 | "side": "packagedauto:block/packaging_provider_side", 5 | "top": "packagedauto:block/packaging_provider_top", 6 | "bottom": "packagedauto:block/machine_bottom" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/api/IVolumePackageItem.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.api; 2 | 3 | import net.minecraft.world.item.ItemStack; 4 | 5 | public interface IVolumePackageItem { 6 | 7 | IVolumeType getVolumeType(ItemStack stack); 8 | 9 | IVolumeStackWrapper getVolumeStack(ItemStack stack); 10 | } 11 | -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/models/block/fluid_package_filler.json: -------------------------------------------------------------------------------- 1 | { 2 | "parent": "block/cube_bottom_top", 3 | "textures": { 4 | "side": "packagedauto:block/fluid_package_filler_side", 5 | "top": "packagedauto:block/fluid_package_filler_top", 6 | "bottom": "packagedauto:block/machine_bottom" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/patchouli_books/guide/en_us/categories/recipe.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Recipe Types", 3 | "description": "Recipe types selectable in the $(l:core/encoder)Package Recipe Encoder/$ and their respective specialized package crafting machines.", 4 | "icon": "packagedauto:distributor", 5 | "sortnum": 1 6 | } 7 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/api/IMarkerItem.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.api; 2 | 3 | import net.minecraft.world.item.ItemStack; 4 | 5 | public interface IMarkerItem { 6 | 7 | DirectionalGlobalPos getDirectionalGlobalPos(ItemStack stack); 8 | 9 | void setDirectionalGlobalPos(ItemStack stack, DirectionalGlobalPos pos); 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/api/IPackageItem.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.api; 2 | 3 | import net.minecraft.world.item.ItemStack; 4 | 5 | public interface IPackageItem { 6 | 7 | IPackageRecipeInfo getRecipeInfo(ItemStack stack); 8 | 9 | int getIndex(ItemStack stack); 10 | 11 | PatternType getPatternType(ItemStack stack); 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/api/IPackageRecipeListItem.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.api; 2 | 3 | import net.minecraft.world.item.ItemStack; 4 | 5 | public interface IPackageRecipeListItem { 6 | 7 | IPackageRecipeList getRecipeList(ItemStack stack); 8 | 9 | void setRecipeList(ItemStack stack, IPackageRecipeList recipeList); 10 | } 11 | -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/models/item/proxy_marker.json: -------------------------------------------------------------------------------- 1 | { 2 | "parent": "item/generated", 3 | "textures": { 4 | "layer0": "packagedauto:item/proxy_marker" 5 | }, 6 | "overrides": [ 7 | { 8 | "predicate": { 9 | "packagedauto:bound": 1 10 | }, 11 | "model": "packagedauto:item/proxy_marker_bound" 12 | } 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/models/item/recipe_holder.json: -------------------------------------------------------------------------------- 1 | { 2 | "parent": "item/generated", 3 | "textures": { 4 | "layer0": "packagedauto:item/recipe_holder" 5 | }, 6 | "overrides": [ 7 | { 8 | "predicate": { 9 | "packagedauto:filled": 1 10 | }, 11 | "model": "packagedauto:item/recipe_holder_filled" 12 | } 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/models/item/settings_cloner.json: -------------------------------------------------------------------------------- 1 | { 2 | "parent": "item/generated", 3 | "textures": { 4 | "layer0": "packagedauto:item/settings_cloner" 5 | }, 6 | "overrides": [ 7 | { 8 | "predicate": { 9 | "packagedauto:filled": 1 10 | }, 11 | "model": "packagedauto:item/settings_cloner_filled" 12 | } 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/api/IRecipeSlotViewWrapper.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.api; 2 | 3 | import java.util.List; 4 | import java.util.Optional; 5 | 6 | public interface IRecipeSlotViewWrapper { 7 | 8 | Optional getDisplayedIngredient(); 9 | 10 | List getAllIngredients(); 11 | 12 | boolean isInput(); 13 | 14 | boolean isOutput(); 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/api/IPackagePattern.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.api; 2 | 3 | import java.util.List; 4 | 5 | import net.minecraft.world.item.ItemStack; 6 | 7 | public interface IPackagePattern { 8 | 9 | IPackageRecipeInfo getRecipeInfo(); 10 | 11 | int getIndex(); 12 | 13 | List getInputs(); 14 | 15 | ItemStack getOutput(); 16 | } 17 | -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/models/item/distributor_marker.json: -------------------------------------------------------------------------------- 1 | { 2 | "parent": "item/generated", 3 | "textures": { 4 | "layer0": "packagedauto:item/distributor_marker" 5 | }, 6 | "overrides": [ 7 | { 8 | "predicate": { 9 | "packagedauto:bound": 1 10 | }, 11 | "model": "packagedauto:item/distributor_marker_bound" 12 | } 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/api/PatternType.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.api; 2 | 3 | import java.util.Arrays; 4 | 5 | public enum PatternType { 6 | PACKAGE, 7 | RECIPE, 8 | DIRECT; 9 | 10 | public static PatternType fromName(String name) { 11 | return Arrays.stream(values()).filter(t->t.name().equalsIgnoreCase(name)).findAny().orElse(null); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # eclipse 2 | bin 3 | *.launch 4 | .settings 5 | .metadata 6 | .classpath 7 | .project 8 | 9 | # idea 10 | out 11 | *.ipr 12 | *.iws 13 | *.iml 14 | .idea 15 | 16 | # vscode 17 | .vscode 18 | 19 | # gradle 20 | build 21 | .gradle 22 | 23 | # macos 24 | *.DS_Store 25 | 26 | # java 27 | hs_err_*.log 28 | replay_*.log 29 | *.hprof 30 | *.jfr 31 | 32 | # minecraft 33 | run 34 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/item/MiscItem.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.item; 2 | 3 | import net.minecraft.world.item.Item; 4 | 5 | public class MiscItem extends Item { 6 | 7 | public static final MiscItem PACKAGE_COMPONENT = new MiscItem(); 8 | public static final MiscItem ME_PACKAGE_COMPONENT = new MiscItem(); 9 | 10 | protected MiscItem() { 11 | super(new Item.Properties()); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/resources/data/packagedauto/recipes/patchouli_guide.json: -------------------------------------------------------------------------------- 1 | { 2 | "conditions": [ 3 | { 4 | "type": "forge:mod_loaded", 5 | "modid": "patchouli" 6 | } 7 | ], 8 | "type": "patchouli:shapeless_book_recipe", 9 | "book": "packagedauto:guide", 10 | "ingredients": [ 11 | { 12 | "item": "minecraft:book" 13 | }, 14 | { 15 | "item": "packagedauto:package_component" 16 | } 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/api/IPackageRecipeList.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.api; 2 | 3 | import java.util.List; 4 | 5 | import net.minecraft.nbt.CompoundTag; 6 | 7 | public interface IPackageRecipeList { 8 | 9 | void load(CompoundTag nbt); 10 | 11 | void save(CompoundTag nbt); 12 | 13 | List getRecipeList(); 14 | 15 | void setRecipeList(List recipeList); 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/recipe/IPositionedProcessingPackageRecipeInfo.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.recipe; 2 | 3 | import it.unimi.dsi.fastutil.ints.Int2ObjectMap; 4 | import net.minecraft.world.item.ItemStack; 5 | import thelm.packagedauto.api.IPackageRecipeInfo; 6 | 7 | public interface IPositionedProcessingPackageRecipeInfo extends IPackageRecipeInfo { 8 | 9 | Int2ObjectMap getMatrix(); 10 | } 11 | -------------------------------------------------------------------------------- /src/main/resources/data/packagedauto/patchouli_books/guide/book.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "item.packagedauto.guide", 3 | "landing_text": "item.packagedauto.guide.landing", 4 | "use_resource_pack": true, 5 | "model": "packagedauto:guide", 6 | "show_progress": false, 7 | "subtitle": "item.packagedauto.guide.subtitle", 8 | "creative_tab": "packagedauto:tab", 9 | "show_toasts": false, 10 | "text_overflow_mode": "overflow" 11 | } 12 | -------------------------------------------------------------------------------- /src/main/resources/data/minecraft/tags/blocks/mineable/pickaxe.json: -------------------------------------------------------------------------------- 1 | { 2 | "replace": false, 3 | "values": [ 4 | "packagedauto:encoder", 5 | "packagedauto:packager", 6 | "packagedauto:packager_extension", 7 | "packagedauto:unpackager", 8 | "packagedauto:distributor", 9 | "packagedauto:crafting_proxy", 10 | "packagedauto:crafter", 11 | "packagedauto:fluid_package_filler", 12 | "packagedauto:packaging_provider" 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/item/ProxyMarkerItem.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.item; 2 | 3 | import net.minecraft.world.item.Item; 4 | import thelm.packagedauto.api.IProxyMarkerItem; 5 | 6 | public class ProxyMarkerItem extends MarkerItem implements IProxyMarkerItem { 7 | 8 | public static final ProxyMarkerItem INSTANCE = new ProxyMarkerItem(); 9 | 10 | protected ProxyMarkerItem() { 11 | super(new Item.Properties()); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/resources/data/packagedauto/recipes/proxy_marker.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "minecraft:crafting_shapeless", 3 | "result": { 4 | "item": "packagedauto:proxy_marker", 5 | "count": 1 6 | }, 7 | "ingredients": [ 8 | { 9 | "item": "packagedauto:package_component" 10 | }, 11 | { 12 | "tag": "forge:ender_pearls" 13 | }, 14 | { 15 | "tag": "forge:obsidian" 16 | }, 17 | { 18 | "item": "minecraft:blaze_powder" 19 | } 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /src/main/resources/data/packagedauto/recipes/distributor_marker.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "minecraft:crafting_shapeless", 3 | "result": { 4 | "item": "packagedauto:distributor_marker", 5 | "count": 4 6 | }, 7 | "ingredients": [ 8 | { 9 | "tag": "forge:ender_pearls" 10 | }, 11 | { 12 | "item": "minecraft:chorus_fruit" 13 | }, 14 | { 15 | "tag": "forge:dusts/redstone" 16 | }, 17 | { 18 | "tag": "forge:ingots/gold" 19 | } 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /src/main/resources/data/packagedauto/recipes/settings_cloner.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "minecraft:crafting_shapeless", 3 | "result": { 4 | "item": "packagedauto:settings_cloner", 5 | "count": 1 6 | }, 7 | "ingredients": [ 8 | { 9 | "item": "packagedauto:package_component" 10 | }, 11 | { 12 | "tag": "forge:dusts/redstone" 13 | }, 14 | { 15 | "tag": "forge:gems/quartz" 16 | }, 17 | { 18 | "tag": "forge:gems/quartz" 19 | } 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/patchouli_books/guide/en_us/entries/recipe/processing.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Processing", 3 | "category": "packagedauto:recipe", 4 | "icon": "minecraft:furnace", 5 | "pages": [ 6 | { 7 | "type": "patchouli:text", 8 | "text": "$(thing)Processing/$ is the most basic processing recipe type.$(p)When encoded, inputs and outputs will be sorted and stacked." 9 | } 10 | ], 11 | "read_by_default": true, 12 | "sortnum": 101 13 | } 14 | -------------------------------------------------------------------------------- /src/main/resources/data/packagedauto/recipes/package_component.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "minecraft:crafting_shaped", 3 | "result": { 4 | "item": "packagedauto:package_component", 5 | "count": 1 6 | }, 7 | "pattern": [ 8 | "GWG", 9 | "WEW", 10 | "GWG" 11 | ], 12 | "key": { 13 | "E": { 14 | "item": "minecraft:ender_eye" 15 | }, 16 | "W": { 17 | "tag": "minecraft:planks" 18 | }, 19 | "G": { 20 | "tag": "forge:ingots/gold" 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/item/DistributorMarkerItem.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.item; 2 | 3 | import net.minecraft.world.item.Item; 4 | import thelm.packagedauto.api.IDistributorMarkerItem; 5 | 6 | public class DistributorMarkerItem extends MarkerItem implements IDistributorMarkerItem { 7 | 8 | public static final DistributorMarkerItem INSTANCE = new DistributorMarkerItem(); 9 | 10 | protected DistributorMarkerItem() { 11 | super(new Item.Properties()); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/slot/PreviewVolumeSlot.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.slot; 2 | 3 | import net.minecraft.world.item.ItemStack; 4 | import thelm.packagedauto.inventory.BaseVolumeInventory; 5 | 6 | public class PreviewVolumeSlot extends FalseCopyVolumeSlot { 7 | 8 | public PreviewVolumeSlot(BaseVolumeInventory fluidInventory, int index, int x, int y) { 9 | super(fluidInventory, index, x, y); 10 | } 11 | 12 | @Override 13 | public void set(ItemStack stack) {} 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/slot/SingleStackSlot.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.slot; 2 | 3 | import net.minecraftforge.items.IItemHandler; 4 | import net.minecraftforge.items.SlotItemHandler; 5 | 6 | public class SingleStackSlot extends SlotItemHandler { 7 | 8 | public SingleStackSlot(IItemHandler itemHandler, int index, int xPosition, int yPosition) { 9 | super(itemHandler, index, xPosition, yPosition); 10 | } 11 | 12 | @Override 13 | public int getMaxStackSize() { 14 | return 1; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/resources/data/packagedauto/loot_tables/blocks/crafter.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "minecraft:block", 3 | "pools": [ 4 | { 5 | "rolls": 1, 6 | "entries": [ 7 | { 8 | "type": "minecraft:item", 9 | "functions": [ 10 | { 11 | "function": "minecraft:copy_name", 12 | "source": "block_entity" 13 | } 14 | ], 15 | "name": "packagedauto:crafter" 16 | } 17 | ], 18 | "conditions": [ 19 | { 20 | "condition": "minecraft:survives_explosion" 21 | } 22 | ] 23 | } 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /src/main/resources/data/packagedauto/loot_tables/blocks/encoder.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "minecraft:block", 3 | "pools": [ 4 | { 5 | "rolls": 1, 6 | "entries": [ 7 | { 8 | "type": "minecraft:item", 9 | "functions": [ 10 | { 11 | "function": "minecraft:copy_name", 12 | "source": "block_entity" 13 | } 14 | ], 15 | "name": "packagedauto:encoder" 16 | } 17 | ], 18 | "conditions": [ 19 | { 20 | "condition": "minecraft:survives_explosion" 21 | } 22 | ] 23 | } 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /src/main/resources/data/packagedauto/loot_tables/blocks/packager.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "minecraft:block", 3 | "pools": [ 4 | { 5 | "rolls": 1, 6 | "entries": [ 7 | { 8 | "type": "minecraft:item", 9 | "functions": [ 10 | { 11 | "function": "minecraft:copy_name", 12 | "source": "block_entity" 13 | } 14 | ], 15 | "name": "packagedauto:packager" 16 | } 17 | ], 18 | "conditions": [ 19 | { 20 | "condition": "minecraft:survives_explosion" 21 | } 22 | ] 23 | } 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /src/main/resources/data/packagedauto/loot_tables/blocks/distributor.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "minecraft:block", 3 | "pools": [ 4 | { 5 | "rolls": 1, 6 | "entries": [ 7 | { 8 | "type": "minecraft:item", 9 | "functions": [ 10 | { 11 | "function": "minecraft:copy_name", 12 | "source": "block_entity" 13 | } 14 | ], 15 | "name": "packagedauto:distributor" 16 | } 17 | ], 18 | "conditions": [ 19 | { 20 | "condition": "minecraft:survives_explosion" 21 | } 22 | ] 23 | } 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /src/main/resources/data/packagedauto/loot_tables/blocks/unpackager.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "minecraft:block", 3 | "pools": [ 4 | { 5 | "rolls": 1, 6 | "entries": [ 7 | { 8 | "type": "minecraft:item", 9 | "functions": [ 10 | { 11 | "function": "minecraft:copy_name", 12 | "source": "block_entity" 13 | } 14 | ], 15 | "name": "packagedauto:unpackager" 16 | } 17 | ], 18 | "conditions": [ 19 | { 20 | "condition": "minecraft:survives_explosion" 21 | } 22 | ] 23 | } 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /src/main/resources/data/packagedauto/loot_tables/blocks/crafting_proxy.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "minecraft:block", 3 | "pools": [ 4 | { 5 | "rolls": 1, 6 | "entries": [ 7 | { 8 | "type": "minecraft:item", 9 | "functions": [ 10 | { 11 | "function": "minecraft:copy_name", 12 | "source": "block_entity" 13 | } 14 | ], 15 | "name": "packagedauto:crafting_proxy" 16 | } 17 | ], 18 | "conditions": [ 19 | { 20 | "condition": "minecraft:survives_explosion" 21 | } 22 | ] 23 | } 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/slot/RemoveOnlySlot.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.slot; 2 | 3 | import net.minecraft.world.item.ItemStack; 4 | import net.minecraftforge.items.IItemHandler; 5 | import net.minecraftforge.items.SlotItemHandler; 6 | 7 | //Code from CoFHCore 8 | public class RemoveOnlySlot extends SlotItemHandler { 9 | 10 | public RemoveOnlySlot(IItemHandler itemHandler, int index, int x, int y) { 11 | super(itemHandler, index, x, y); 12 | } 13 | 14 | @Override 15 | public boolean mayPlace(ItemStack stack) { 16 | return false; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/resources/data/packagedauto/loot_tables/blocks/packager_extension.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "minecraft:block", 3 | "pools": [ 4 | { 5 | "rolls": 1, 6 | "entries": [ 7 | { 8 | "type": "minecraft:item", 9 | "functions": [ 10 | { 11 | "function": "minecraft:copy_name", 12 | "source": "block_entity" 13 | } 14 | ], 15 | "name": "packagedauto:packager_extension" 16 | } 17 | ], 18 | "conditions": [ 19 | { 20 | "condition": "minecraft:survives_explosion" 21 | } 22 | ] 23 | } 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /src/main/resources/data/packagedauto/loot_tables/blocks/packaging_provider.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "minecraft:block", 3 | "pools": [ 4 | { 5 | "rolls": 1, 6 | "entries": [ 7 | { 8 | "type": "minecraft:item", 9 | "functions": [ 10 | { 11 | "function": "minecraft:copy_name", 12 | "source": "block_entity" 13 | } 14 | ], 15 | "name": "packagedauto:packaging_provider" 16 | } 17 | ], 18 | "conditions": [ 19 | { 20 | "condition": "minecraft:survives_explosion" 21 | } 22 | ] 23 | } 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /src/main/resources/data/packagedauto/loot_tables/blocks/fluid_package_filler.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "minecraft:block", 3 | "pools": [ 4 | { 5 | "rolls": 1, 6 | "entries": [ 7 | { 8 | "type": "minecraft:item", 9 | "functions": [ 10 | { 11 | "function": "minecraft:copy_name", 12 | "source": "block_entity" 13 | } 14 | ], 15 | "name": "packagedauto:fluid_package_filler" 16 | } 17 | ], 18 | "conditions": [ 19 | { 20 | "condition": "minecraft:survives_explosion" 21 | } 22 | ] 23 | } 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /src/main/resources/data/packagedauto/recipes/recipe_holder.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "minecraft:crafting_shaped", 3 | "result": { 4 | "item": "packagedauto:recipe_holder", 5 | "count": 2 6 | }, 7 | "pattern": [ 8 | "TRT", 9 | "RGR", 10 | "ICI" 11 | ], 12 | "key": { 13 | "C": { 14 | "item": "packagedauto:package_component" 15 | }, 16 | "G": { 17 | "item": "minecraft:glowstone" 18 | }, 19 | "T": { 20 | "tag": "forge:glass" 21 | }, 22 | "I": { 23 | "tag": "forge:ingots/copper" 24 | }, 25 | "R": { 26 | "tag": "forge:dusts/redstone" 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/resources/data/packagedauto/recipes/encoder.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "minecraft:crafting_shaped", 3 | "result": { 4 | "item": "packagedauto:encoder", 5 | "count": 1 6 | }, 7 | "pattern": [ 8 | "ICI", 9 | "TGT", 10 | "IRI" 11 | ], 12 | "key": { 13 | "C": { 14 | "item": "packagedauto:package_component" 15 | }, 16 | "G": { 17 | "item": "minecraft:glowstone" 18 | }, 19 | "R": { 20 | "item": "minecraft:comparator" 21 | }, 22 | "T": { 23 | "item": "minecraft:crafting_table" 24 | }, 25 | "I": { 26 | "tag": "forge:ingots/iron" 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/resources/data/packagedauto/recipes/fluid_package_filler.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "minecraft:crafting_shaped", 3 | "result": { 4 | "item": "packagedauto:fluid_package_filler", 5 | "count": 1 6 | }, 7 | "pattern": [ 8 | "ICI", 9 | "UBU", 10 | "IPI" 11 | ], 12 | "key": { 13 | "C": { 14 | "item": "packagedauto:package_component" 15 | }, 16 | "B": { 17 | "item": "minecraft:bucket" 18 | }, 19 | "P": { 20 | "item": "minecraft:piston" 21 | }, 22 | "I": { 23 | "tag": "forge:ingots/iron" 24 | }, 25 | "U": { 26 | "tag": "forge:ingots/copper" 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/menu/EmptyMenu.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.menu; 2 | 3 | import net.minecraft.world.entity.player.Player; 4 | import net.minecraft.world.inventory.AbstractContainerMenu; 5 | import net.minecraft.world.item.ItemStack; 6 | 7 | public class EmptyMenu extends AbstractContainerMenu { 8 | 9 | public EmptyMenu() { 10 | super(null, 0); 11 | } 12 | 13 | @Override 14 | public ItemStack quickMoveStack(Player pPlayer, int pSlot) { 15 | return ItemStack.EMPTY; 16 | } 17 | 18 | @Override 19 | public boolean stillValid(Player pPlayer) { 20 | return false; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/resources/data/packagedauto/recipes/distributor.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "minecraft:crafting_shaped", 3 | "result": { 4 | "item": "packagedauto:distributor", 5 | "count": 1 6 | }, 7 | "pattern": [ 8 | "ECE", 9 | "SMS", 10 | "EIE" 11 | ], 12 | "key": { 13 | "C": { 14 | "item": "packagedauto:package_component" 15 | }, 16 | "M": { 17 | "item": "packagedauto:distributor_marker" 18 | }, 19 | "S": { 20 | "item": "minecraft:shulker_shell" 21 | }, 22 | "E": { 23 | "tag": "forge:ender_pearls" 24 | }, 25 | "I": { 26 | "tag": "forge:storage_blocks/iron" 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/api/IPackageCraftingMachine.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.api; 2 | 3 | import java.util.List; 4 | 5 | import net.minecraft.core.Direction; 6 | import net.minecraft.world.item.ItemStack; 7 | 8 | public interface IPackageCraftingMachine { 9 | 10 | boolean acceptPackage(IPackageRecipeInfo recipeInfo, List stacks, Direction direction); 11 | 12 | default boolean acceptPackage(IPackageRecipeInfo recipeInfo, List stacks, Direction direction, boolean blocking) { 13 | return acceptPackage(recipeInfo, stacks, direction); 14 | } 15 | 16 | boolean isBusy(); 17 | } 18 | -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/patchouli_books/guide/en_us/entries/recipe/ordered.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Ordered Processing", 3 | "category": "packagedauto:recipe", 4 | "icon": "minecraft:brewing_stand", 5 | "pages": [ 6 | { 7 | "type": "patchouli:text", 8 | "text": "$(thing)Ordered Processing/$ is a processing recipe type that preserves ingredient order.$(p)When encoded, outputs will be sorted and stacked.$(p)When unpackaged, items will be inserted into adjacent inventories in the encoded order, and will only be inserted into empty slots." 9 | } 10 | ], 11 | "read_by_default": true, 12 | "sortnum": 102 13 | } 14 | -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/patchouli_books/guide/en_us/templates/spotlight2.json: -------------------------------------------------------------------------------- 1 | { 2 | "components": [ 3 | { 4 | "type": "patchouli:item", 5 | "x": 35, 6 | "y": 15, 7 | "item": "#item1", 8 | "framed": true, 9 | "link_recipe": true 10 | }, 11 | { 12 | "type": "patchouli:item", 13 | "x": 65, 14 | "y": 15, 15 | "item": "#item2", 16 | "framed": true, 17 | "link_recipe": true 18 | }, 19 | { 20 | "type": "patchouli:header", 21 | "x": -1, 22 | "y": -1, 23 | "text": "#title" 24 | }, 25 | { 26 | "type": "patchouli:text", 27 | "y": 40, 28 | "text": "#text" 29 | } 30 | ] 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/api/IVolumeStackWrapper.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.api; 2 | 3 | import java.util.List; 4 | 5 | import net.minecraft.nbt.CompoundTag; 6 | import net.minecraft.network.chat.Component; 7 | 8 | public interface IVolumeStackWrapper { 9 | 10 | IVolumeType getVolumeType(); 11 | 12 | int getAmount(); 13 | 14 | IVolumeStackWrapper copy(); 15 | 16 | void setAmount(int amount); 17 | 18 | boolean isEmpty(); 19 | 20 | CompoundTag save(CompoundTag tag); 21 | 22 | CompoundTag saveAEKey(CompoundTag tag); 23 | 24 | Component getDisplayName(); 25 | 26 | Component getAmountDesc(); 27 | 28 | List getTooltip(); 29 | } 30 | -------------------------------------------------------------------------------- /src/main/resources/data/packagedauto/recipes/crafting_proxy.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "minecraft:crafting_shaped", 3 | "result": { 4 | "item": "packagedauto:crafting_proxy", 5 | "count": 1 6 | }, 7 | "pattern": [ 8 | "ECE", 9 | "SMS", 10 | "OIO" 11 | ], 12 | "key": { 13 | "C": { 14 | "item": "packagedauto:package_component" 15 | }, 16 | "M": { 17 | "item": "packagedauto:proxy_marker" 18 | }, 19 | "S": { 20 | "item": "minecraft:shulker_shell" 21 | }, 22 | "E": { 23 | "tag": "forge:ender_pearls" 24 | }, 25 | "O": { 26 | "item": "minecraft:crying_obsidian" 27 | }, 28 | "I": { 29 | "tag": "forge:storage_blocks/iron" 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/PackagedAuto.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto; 2 | 3 | import net.minecraftforge.api.distmarker.Dist; 4 | import net.minecraftforge.fml.DistExecutor; 5 | import net.minecraftforge.fml.common.Mod; 6 | import thelm.packagedauto.client.event.ClientEventHandler; 7 | import thelm.packagedauto.event.CommonEventHandler; 8 | 9 | @Mod(PackagedAuto.MOD_ID) 10 | public class PackagedAuto { 11 | 12 | public static final String MOD_ID = "packagedauto"; 13 | 14 | public PackagedAuto() { 15 | CommonEventHandler.getInstance().onConstruct(); 16 | DistExecutor.unsafeRunWhenOn(Dist.CLIENT, ()->()->{ 17 | ClientEventHandler.getInstance().onConstruct(); 18 | }); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/resources/data/packagedauto/recipes/crafter_ae.json: -------------------------------------------------------------------------------- 1 | { 2 | "conditions": [ 3 | { 4 | "type": "forge:mod_loaded", 5 | "modid": "ae2" 6 | } 7 | ], 8 | "type": "minecraft:crafting_shaped", 9 | "result": { 10 | "item": "packagedauto:crafter", 11 | "count": 1 12 | }, 13 | "pattern": [ 14 | "ICI", 15 | "RTR", 16 | "IHI" 17 | ], 18 | "key": { 19 | "C": { 20 | "item": "packagedauto:me_package_component" 21 | }, 22 | "T": { 23 | "item": "minecraft:crafting_table" 24 | }, 25 | "H": { 26 | "item": "minecraft:hopper" 27 | }, 28 | "I": { 29 | "tag": "forge:ingots/iron" 30 | }, 31 | "R": { 32 | "tag": "forge:dusts/redstone" 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/resources/data/packagedauto/recipes/packager_ae.json: -------------------------------------------------------------------------------- 1 | { 2 | "conditions": [ 3 | { 4 | "type": "forge:mod_loaded", 5 | "modid": "ae2" 6 | } 7 | ], 8 | "type": "minecraft:crafting_shaped", 9 | "result": { 10 | "item": "packagedauto:packager", 11 | "count": 1 12 | }, 13 | "pattern": [ 14 | "ICI", 15 | "RTR", 16 | "IPI" 17 | ], 18 | "key": { 19 | "C": { 20 | "item": "packagedauto:me_package_component" 21 | }, 22 | "T": { 23 | "item": "minecraft:crafting_table" 24 | }, 25 | "P": { 26 | "item": "minecraft:piston" 27 | }, 28 | "I": { 29 | "tag": "forge:ingots/iron" 30 | }, 31 | "R": { 32 | "tag": "forge:dusts/redstone" 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/resources/data/packagedauto/recipes/unpackager_ae.json: -------------------------------------------------------------------------------- 1 | { 2 | "conditions": [ 3 | { 4 | "type": "forge:mod_loaded", 5 | "modid": "ae2" 6 | } 7 | ], 8 | "type": "minecraft:crafting_shaped", 9 | "result": { 10 | "item": "packagedauto:unpackager", 11 | "count": 1 12 | }, 13 | "pattern": [ 14 | "ICI", 15 | "RSR", 16 | "IHI" 17 | ], 18 | "key": { 19 | "C": { 20 | "item": "packagedauto:me_package_component" 21 | }, 22 | "S": { 23 | "tag": "forge:chests/wooden" 24 | }, 25 | "H": { 26 | "item": "minecraft:hopper" 27 | }, 28 | "I": { 29 | "tag": "forge:ingots/iron" 30 | }, 31 | "R": { 32 | "tag": "forge:dusts/redstone" 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/slot/PreviewSlot.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.slot; 2 | 3 | import net.minecraft.world.entity.player.Player; 4 | import net.minecraft.world.item.ItemStack; 5 | import net.minecraftforge.items.IItemHandler; 6 | import net.minecraftforge.items.SlotItemHandler; 7 | 8 | public class PreviewSlot extends SlotItemHandler { 9 | 10 | public PreviewSlot(IItemHandler itemHandler, int index, int xPosition, int yPosition) { 11 | super(itemHandler, index, xPosition, yPosition); 12 | } 13 | 14 | @Override 15 | public boolean mayPickup(Player player) { 16 | return false; 17 | } 18 | 19 | @Override 20 | public boolean mayPlace(ItemStack stack) { 21 | return false; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | 24 | # Linux start script should use lf 25 | /gradlew text eol=lf 26 | 27 | # Windows script files should use crlf 28 | *.bat text eol=crlf 29 | -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/patchouli_books/guide/en_us/entries/core/components.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Crafting Components", 3 | "category": "packagedauto:core", 4 | "icon": "packagedauto:package_component", 5 | "pages": [ 6 | { 7 | "type": "patchouli:text", 8 | "text": "Basic crafting components used by $(#822)PackagedAuto/$." 9 | }, 10 | { 11 | "type": "patchouli:crafting", 12 | "recipe": "packagedauto:package_component", 13 | "title": "Crafting" 14 | }, 15 | { 16 | "type": "patchouli:crafting", 17 | "flag": "mod:ae2", 18 | "recipe": "packagedauto:me_package_component", 19 | "title": "Crafting" 20 | } 21 | ], 22 | "read_by_default": true, 23 | "sortnum": 1 24 | } 25 | -------------------------------------------------------------------------------- /src/main/resources/data/packagedauto/recipes/me_package_component.json: -------------------------------------------------------------------------------- 1 | { 2 | "conditions": [ 3 | { 4 | "type": "forge:mod_loaded", 5 | "modid": "ae2" 6 | } 7 | ], 8 | "type": "minecraft:crafting_shaped", 9 | "result": { 10 | "item": "packagedauto:me_package_component", 11 | "count": 1 12 | }, 13 | "pattern": [ 14 | "IGI", 15 | "ACF", 16 | "IGI" 17 | ], 18 | "key": { 19 | "C": { 20 | "item": "packagedauto:package_component" 21 | }, 22 | "A": { 23 | "item": "ae2:annihilation_core" 24 | }, 25 | "F": { 26 | "item": "ae2:formation_core" 27 | }, 28 | "G": { 29 | "item": "ae2:quartz_glass" 30 | }, 31 | "I": { 32 | "tag": "forge:ingots/iron" 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/resources/data/packagedauto/recipes/packaging_provider.json: -------------------------------------------------------------------------------- 1 | { 2 | "conditions": [ 3 | { 4 | "type": "forge:mod_loaded", 5 | "modid": "ae2" 6 | } 7 | ], 8 | "type": "minecraft:crafting_shaped", 9 | "result": { 10 | "item": "packagedauto:packaging_provider", 11 | "count": 1 12 | }, 13 | "pattern": [ 14 | "FPF", 15 | "UEU", 16 | "FIF" 17 | ], 18 | "key": { 19 | "P": { 20 | "item": "packagedauto:packager" 21 | }, 22 | "U": { 23 | "item": "packagedauto:unpackager" 24 | }, 25 | "E": { 26 | "item": "ae2:engineering_processor" 27 | }, 28 | "F": { 29 | "item": "ae2:fluix_pearl" 30 | }, 31 | "I": { 32 | "tag": "forge:storage_blocks/iron" 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/resources/data/packagedauto/recipes/packager_extension_ae.json: -------------------------------------------------------------------------------- 1 | { 2 | "conditions": [ 3 | { 4 | "type": "forge:mod_loaded", 5 | "modid": "ae2" 6 | } 7 | ], 8 | "type": "minecraft:crafting_shaped", 9 | "result": { 10 | "item": "packagedauto:packager_extension", 11 | "count": 1 12 | }, 13 | "pattern": [ 14 | "ICI", 15 | "GTG", 16 | "IPI" 17 | ], 18 | "key": { 19 | "C": { 20 | "item": "packagedauto:me_package_component" 21 | }, 22 | "T": { 23 | "item": "minecraft:crafting_table" 24 | }, 25 | "P": { 26 | "item": "minecraft:piston" 27 | }, 28 | "I": { 29 | "tag": "forge:ingots/iron" 30 | }, 31 | "G": { 32 | "tag": "forge:dusts/glowstone" 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/resources/data/packagedauto/recipes/crafter.json: -------------------------------------------------------------------------------- 1 | { 2 | "conditions": [ 3 | { 4 | "type": "forge:not", 5 | "value": { 6 | "type": "forge:mod_loaded", 7 | "modid": "ae2" 8 | } 9 | } 10 | ], 11 | "type": "minecraft:crafting_shaped", 12 | "result": { 13 | "item": "packagedauto:crafter", 14 | "count": 1 15 | }, 16 | "pattern": [ 17 | "ICI", 18 | "RTR", 19 | "IHI" 20 | ], 21 | "key": { 22 | "C": { 23 | "item": "packagedauto:package_component" 24 | }, 25 | "T": { 26 | "item": "minecraft:crafting_table" 27 | }, 28 | "H": { 29 | "item": "minecraft:hopper" 30 | }, 31 | "I": { 32 | "tag": "forge:ingots/iron" 33 | }, 34 | "R": { 35 | "tag": "forge:dusts/redstone" 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/resources/data/packagedauto/recipes/unpackager.json: -------------------------------------------------------------------------------- 1 | { 2 | "conditions": [ 3 | { 4 | "type": "forge:not", 5 | "value": { 6 | "type": "forge:mod_loaded", 7 | "modid": "ae2" 8 | } 9 | } 10 | ], 11 | "type": "minecraft:crafting_shaped", 12 | "result": { 13 | "item": "packagedauto:unpackager", 14 | "count": 1 15 | }, 16 | "pattern": [ 17 | "ICI", 18 | "RSR", 19 | "IHI" 20 | ], 21 | "key": { 22 | "C": { 23 | "item": "packagedauto:package_component" 24 | }, 25 | "S": { 26 | "tag": "forge:chests/wooden" 27 | }, 28 | "H": { 29 | "item": "minecraft:hopper" 30 | }, 31 | "I": { 32 | "tag": "forge:ingots/iron" 33 | }, 34 | "R": { 35 | "tag": "forge:dusts/redstone" 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/resources/data/packagedauto/recipes/packager.json: -------------------------------------------------------------------------------- 1 | { 2 | "conditions": [ 3 | { 4 | "type": "forge:not", 5 | "value": { 6 | "type": "forge:mod_loaded", 7 | "modid": "ae2" 8 | } 9 | } 10 | ], 11 | "type": "minecraft:crafting_shaped", 12 | "result": { 13 | "item": "packagedauto:packager", 14 | "count": 1 15 | }, 16 | "pattern": [ 17 | "ICI", 18 | "RTR", 19 | "IPI" 20 | ], 21 | "key": { 22 | "C": { 23 | "item": "packagedauto:package_component" 24 | }, 25 | "T": { 26 | "item": "minecraft:crafting_table" 27 | }, 28 | "P": { 29 | "item": "minecraft:piston" 30 | }, 31 | "I": { 32 | "tag": "forge:ingots/iron" 33 | }, 34 | "R": { 35 | "tag": "forge:dusts/redstone" 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/mods.toml: -------------------------------------------------------------------------------- 1 | modLoader = "javafml" 2 | loaderVersion = "[46,)" 3 | license = "MIT" 4 | issueTrackerURL = "https://github.com/TheLMiffy1111/PackagedAuto/issues" 5 | 6 | [[mods]] 7 | modId = "packagedauto" 8 | version = "0@VERSION@" 9 | displayName = "PackagedAuto" 10 | description = "An Applied Energistics 2 addon that uses 'packages' to allow autocrafting with more than 9 items." 11 | logoFile = "packagedauto.logo.png" 12 | authors = "TheLMiffy1111" 13 | displayURL = "https://www.curseforge.com/minecraft/mc-mods/packagedauto" 14 | 15 | [[dependencies.packagedauto]] 16 | modId = "forge" 17 | versionRange = "[46,)" 18 | mandatory = true 19 | 20 | [[dependencies.packagedauto]] 21 | modId = "ae2" 22 | versionRange = "*" 23 | mandatory = false 24 | -------------------------------------------------------------------------------- /src/main/resources/data/packagedauto/recipes/packager_extension.json: -------------------------------------------------------------------------------- 1 | { 2 | "conditions": [ 3 | { 4 | "type": "forge:not", 5 | "value": { 6 | "type": "forge:mod_loaded", 7 | "modid": "ae2" 8 | } 9 | } 10 | ], 11 | "type": "minecraft:crafting_shaped", 12 | "result": { 13 | "item": "packagedauto:packager_extension", 14 | "count": 1 15 | }, 16 | "pattern": [ 17 | "ICI", 18 | "GTG", 19 | "IPI" 20 | ], 21 | "key": { 22 | "C": { 23 | "item": "packagedauto:package_component" 24 | }, 25 | "T": { 26 | "item": "minecraft:crafting_table" 27 | }, 28 | "P": { 29 | "item": "minecraft:piston" 30 | }, 31 | "I": { 32 | "tag": "forge:ingots/iron" 33 | }, 34 | "G": { 35 | "tag": "forge:dusts/glowstone" 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/integration/jei/RecipeSlotsViewWrapper.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.integration.jei; 2 | 3 | import java.util.List; 4 | 5 | import com.google.common.collect.Lists; 6 | 7 | import mezz.jei.api.gui.ingredient.IRecipeSlotsView; 8 | import thelm.packagedauto.api.IRecipeSlotViewWrapper; 9 | import thelm.packagedauto.api.IRecipeSlotsViewWrapper; 10 | 11 | public record RecipeSlotsViewWrapper(Object recipe, IRecipeSlotsView recipeSlotsView) implements IRecipeSlotsViewWrapper { 12 | 13 | @Override 14 | public Object getRecipe() { 15 | return recipe; 16 | } 17 | 18 | @Override 19 | public List getRecipeSlotViews() { 20 | return Lists.transform(recipeSlotsView.getSlotViews(), RecipeSlotViewWrapper::new); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/recipe/ICraftingPackageRecipeInfo.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.recipe; 2 | 3 | import java.util.List; 4 | 5 | import net.minecraft.world.inventory.CraftingContainer; 6 | import net.minecraft.world.item.ItemStack; 7 | import net.minecraft.world.item.crafting.CraftingRecipe; 8 | import thelm.packagedauto.api.IPackageRecipeInfo; 9 | 10 | public interface ICraftingPackageRecipeInfo extends IPackageRecipeInfo { 11 | 12 | ItemStack getOutput(); 13 | 14 | CraftingRecipe getRecipe(); 15 | 16 | CraftingContainer getMatrix(); 17 | 18 | List getRemainingItems(); 19 | 20 | @Override 21 | default List getOutputs() { 22 | ItemStack output = getOutput(); 23 | return output.isEmpty() ? List.of() : List.of(output); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/integration/appeng/AppEngEventHandler.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.integration.appeng; 2 | 3 | import appeng.api.crafting.PatternDetailsHelper; 4 | import net.minecraftforge.eventbus.api.SubscribeEvent; 5 | import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent; 6 | import thelm.packagedauto.integration.appeng.recipe.PackagePatternDetailsDecoder; 7 | 8 | public class AppEngEventHandler { 9 | 10 | public static final AppEngEventHandler INSTANCE = new AppEngEventHandler(); 11 | 12 | public static AppEngEventHandler getInstance() { 13 | return INSTANCE; 14 | } 15 | 16 | @SubscribeEvent 17 | public void onCommonSetup(FMLCommonSetupEvent event) { 18 | PatternDetailsHelper.registerDecoder(PackagePatternDetailsDecoder.INSTANCE); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | repositories { 3 | mavenCentral() 4 | gradlePluginPortal() 5 | maven { 6 | url = "https://jitpack.io/" 7 | } 8 | maven { 9 | url = "https://maven.crystaelix.com/releases/" 10 | } 11 | maven { 12 | url = "https://maven.architectury.dev/" 13 | } 14 | maven { 15 | url = "https://maven.fabricmc.net/" 16 | } 17 | maven { 18 | url = "https://maven.minecraftforge.net/" 19 | } 20 | } 21 | resolutionStrategy { 22 | eachPlugin { 23 | if(requested.id.id == "com.crystaelix.loom" && requested.version.startsWith("jitpack-")) { 24 | useModule("com.github.Crystaelix:crystaelix-loom:${requested.version.substring(8)}") 25 | } 26 | } 27 | } 28 | } 29 | 30 | plugins { 31 | id "org.gradle.toolchains.foojay-resolver-convention" version "[0,)" 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/slot/FalseCopySlot.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.slot; 2 | 3 | import net.minecraft.world.entity.player.Player; 4 | import net.minecraft.world.item.ItemStack; 5 | import net.minecraftforge.items.IItemHandler; 6 | import net.minecraftforge.items.SlotItemHandler; 7 | 8 | //Code from CoFHCore 9 | public class FalseCopySlot extends SlotItemHandler { 10 | 11 | public int slotIndex; 12 | 13 | public FalseCopySlot(IItemHandler itemHandler, int index, int x, int y) { 14 | super(itemHandler, index, x, y); 15 | slotIndex = index; 16 | } 17 | 18 | @Override 19 | public boolean mayPickup(Player player) { 20 | return false; 21 | } 22 | 23 | @Override 24 | public void set(ItemStack stack) { 25 | if(!stack.isEmpty() && !mayPlace(stack)) { 26 | return; 27 | } 28 | super.set(stack); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/client/RenderTimer.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.client; 2 | 3 | import net.minecraft.client.Minecraft; 4 | import net.minecraftforge.common.MinecraftForge; 5 | import net.minecraftforge.event.TickEvent; 6 | 7 | public class RenderTimer { 8 | 9 | public static final RenderTimer INSTANCE = new RenderTimer(); 10 | 11 | private Minecraft mc; 12 | private int ticks; 13 | 14 | private RenderTimer() { 15 | mc = Minecraft.getInstance(); 16 | MinecraftForge.EVENT_BUS.addListener(this::onClientTick); 17 | } 18 | 19 | public int getTicks() { 20 | return ticks; 21 | } 22 | 23 | public void onClientTick(TickEvent.ClientTickEvent event) { 24 | if(event.phase != TickEvent.Phase.START || mc.level == null || mc.player == null || mc.isPaused()) { 25 | return; 26 | } 27 | ticks = (ticks+1) & 0x1FFFFF; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/slot/CrafterRemoveOnlySlot.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.slot; 2 | 3 | import net.minecraft.world.entity.player.Player; 4 | import net.minecraft.world.item.ItemStack; 5 | import net.minecraftforge.items.SlotItemHandler; 6 | import thelm.packagedauto.block.entity.CrafterBlockEntity; 7 | 8 | public class CrafterRemoveOnlySlot extends SlotItemHandler { 9 | 10 | public final CrafterBlockEntity blockEntity; 11 | 12 | public CrafterRemoveOnlySlot(CrafterBlockEntity blockEntity, int index, int x, int y) { 13 | super(blockEntity.getItemHandler(), index, x, y); 14 | this.blockEntity = blockEntity; 15 | } 16 | 17 | @Override 18 | public boolean mayPickup(Player player) { 19 | return !blockEntity.isWorking; 20 | } 21 | 22 | @Override 23 | public boolean mayPlace(ItemStack stack) { 24 | return false; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/integration/emi/EmiRecipeWrapper.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.integration.emi; 2 | 3 | import java.util.List; 4 | 5 | import com.google.common.collect.Streams; 6 | 7 | import dev.emi.emi.api.recipe.EmiRecipe; 8 | import thelm.packagedauto.api.IRecipeSlotViewWrapper; 9 | import thelm.packagedauto.api.IRecipeSlotsViewWrapper; 10 | 11 | public record EmiRecipeWrapper(EmiRecipe recipe) implements IRecipeSlotsViewWrapper { 12 | 13 | @Override 14 | public Object getRecipe() { 15 | return recipe.getBackingRecipe(); 16 | } 17 | 18 | @Override 19 | public List getRecipeSlotViews() { 20 | return Streams.concat( 21 | recipe.getInputs().stream().map(EmiIngredientWrapper::input), 22 | recipe.getOutputs().stream().map(EmiIngredientWrapper::output), 23 | recipe.getCatalysts().stream().map(EmiIngredientWrapper::catalyst)). 24 | toList(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/inventory/FluidPackageFillerItemHandlerWrapper.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.inventory; 2 | 3 | import net.minecraft.core.Direction; 4 | import net.minecraft.world.item.ItemStack; 5 | 6 | public class FluidPackageFillerItemHandlerWrapper extends SidedItemHandlerWrapper { 7 | 8 | public static final int[] SLOTS = {1}; 9 | 10 | public FluidPackageFillerItemHandlerWrapper(FluidPackageFillerItemHandler itemHandler, Direction direction) { 11 | super(itemHandler, direction); 12 | } 13 | 14 | @Override 15 | public int[] getSlotsForDirection(Direction direction) { 16 | return SLOTS; 17 | } 18 | 19 | @Override 20 | public boolean canInsertItem(int slot, ItemStack stack, Direction direction) { 21 | return false; 22 | } 23 | 24 | @Override 25 | public boolean canExtractItem(int slot, Direction direction) { 26 | return slot == 1; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/inventory/EncoderItemHandler.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.inventory; 2 | 3 | import net.minecraft.core.Direction; 4 | import net.minecraft.world.item.ItemStack; 5 | import net.minecraftforge.items.IItemHandlerModifiable; 6 | import net.minecraftforge.items.wrapper.EmptyHandler; 7 | import thelm.packagedauto.api.IPackageRecipeListItem; 8 | import thelm.packagedauto.block.entity.EncoderBlockEntity; 9 | 10 | public class EncoderItemHandler extends BaseItemHandler { 11 | 12 | public EncoderItemHandler(EncoderBlockEntity blockEntity) { 13 | super(blockEntity, 1); 14 | } 15 | 16 | @Override 17 | public boolean isItemValid(int slot, ItemStack stack) { 18 | return stack.getItem() instanceof IPackageRecipeListItem; 19 | } 20 | 21 | @Override 22 | public IItemHandlerModifiable getWrapperForDirection(Direction side) { 23 | return (IItemHandlerModifiable)EmptyHandler.INSTANCE; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/api/DirectionalGlobalPos.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.api; 2 | 3 | import net.minecraft.core.BlockPos; 4 | import net.minecraft.core.Direction; 5 | import net.minecraft.core.GlobalPos; 6 | import net.minecraft.resources.ResourceKey; 7 | import net.minecraft.world.level.Level; 8 | 9 | public record DirectionalGlobalPos(GlobalPos globalPos, Direction direction) { 10 | 11 | public DirectionalGlobalPos(ResourceKey dimension, BlockPos blockPos, Direction direction) { 12 | this(GlobalPos.of(dimension, blockPos), direction); 13 | } 14 | 15 | public ResourceKey dimension() { 16 | return globalPos.dimension(); 17 | } 18 | 19 | public BlockPos blockPos() { 20 | return globalPos.pos(); 21 | } 22 | 23 | public int x() { 24 | return blockPos().getX(); 25 | } 26 | 27 | public int y() { 28 | return blockPos().getY(); 29 | } 30 | 31 | public int z() { 32 | return blockPos().getZ(); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/api/ISettingsCloneable.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.api; 2 | 3 | import net.minecraft.nbt.CompoundTag; 4 | import net.minecraft.network.chat.Component; 5 | import net.minecraft.world.entity.player.Player; 6 | 7 | public interface ISettingsCloneable { 8 | 9 | String getConfigTypeName(); 10 | 11 | Result saveConfig(CompoundTag nbt, Player player); 12 | 13 | Result loadConfig(CompoundTag nbt, Player player); 14 | 15 | record Result(ResultType type, Component message) { 16 | 17 | public static Result success() { 18 | return new Result(ResultType.SUCCESS, Component.empty()); 19 | } 20 | 21 | public static Result partial(Component message) { 22 | return new Result(ResultType.PARTIAL, message); 23 | } 24 | 25 | public static Result fail(Component message) { 26 | return new Result(ResultType.FAIL, message); 27 | } 28 | } 29 | 30 | enum ResultType { 31 | SUCCESS, PARTIAL, FAIL; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/patchouli_books/guide/en_us/entries/core/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Recipe Package", 3 | "category": "packagedauto:core", 4 | "icon": "packagedauto:package", 5 | "pages": [ 6 | { 7 | "type": "patchouli:text", 8 | "text": "$(item)Recipe Packages/$ are created by $(l:core/packager)Packagers/$, and can be unpackaged in a set in $(l:core/unpackager)Unpackagers/$.$(p)You can $(thing)$(k:sneak) + $(k:use)/$ a $(item)Recipe Packages/$ to manually unpackage it." 9 | }, 10 | { 11 | "type": "patchouli:spotlight", 12 | "item": "packagedauto:package", 13 | "link_recipe": true 14 | }, 15 | { 16 | "type": "patchouli:text", 17 | "flag": "&mod:jei,!mod:emi", 18 | "title": "JEI Integration", 19 | "text": "You can press $(thing)$(k:jei.showUses)/$ on a $(item)Recipe Package/$ to show its contents and what the package set is meant to create." 20 | } 21 | ], 22 | "read_by_default": true, 23 | "sortnum": 2 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/inventory/PackagerItemHandlerWrapper.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.inventory; 2 | 3 | import java.util.stream.IntStream; 4 | 5 | import net.minecraft.core.Direction; 6 | import net.minecraft.world.item.ItemStack; 7 | 8 | public class PackagerItemHandlerWrapper extends SidedItemHandlerWrapper { 9 | 10 | public static final int[] SLOTS = IntStream.rangeClosed(0, 9).toArray(); 11 | 12 | public PackagerItemHandlerWrapper(PackagerItemHandler itemHandler, Direction direction) { 13 | super(itemHandler, direction); 14 | } 15 | 16 | @Override 17 | public int[] getSlotsForDirection(Direction direction) { 18 | return SLOTS; 19 | } 20 | 21 | @Override 22 | public boolean canInsertItem(int slot, ItemStack stack, Direction direction) { 23 | return slot < 9; 24 | } 25 | 26 | @Override 27 | public boolean canExtractItem(int slot, Direction direction) { 28 | return slot == 9 || direction == Direction.UP; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/inventory/CrafterItemHandlerWrapper.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.inventory; 2 | 3 | import java.util.stream.IntStream; 4 | 5 | import net.minecraft.core.Direction; 6 | import net.minecraft.world.item.ItemStack; 7 | 8 | public class CrafterItemHandlerWrapper extends SidedItemHandlerWrapper { 9 | 10 | public static final int[] SLOTS = IntStream.rangeClosed(0, 9).toArray(); 11 | 12 | public CrafterItemHandlerWrapper(CrafterItemHandler itemHandler, Direction direction) { 13 | super(itemHandler, direction); 14 | } 15 | 16 | @Override 17 | public int[] getSlotsForDirection(Direction direction) { 18 | return SLOTS; 19 | } 20 | 21 | @Override 22 | public boolean canInsertItem(int index, ItemStack stack, Direction direction) { 23 | return false; 24 | } 25 | 26 | @Override 27 | public boolean canExtractItem(int index, Direction direction) { 28 | return itemHandler.blockEntity.isWorking ? index == 9 : true; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/network/packet/EjectTrackerPacket.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.network.packet; 2 | 3 | import java.util.function.Supplier; 4 | 5 | import net.minecraft.network.FriendlyByteBuf; 6 | import net.minecraft.server.level.ServerPlayer; 7 | import net.minecraftforge.network.NetworkEvent; 8 | import thelm.packagedauto.menu.UnpackagerMenu; 9 | 10 | public record EjectTrackerPacket(int index) { 11 | 12 | public void encode(FriendlyByteBuf buf) { 13 | buf.writeByte(index); 14 | } 15 | 16 | public static EjectTrackerPacket decode(FriendlyByteBuf buf) { 17 | return new EjectTrackerPacket(buf.readUnsignedByte()); 18 | } 19 | 20 | public void handle(Supplier ctx) { 21 | ServerPlayer player = ctx.get().getSender(); 22 | ctx.get().enqueueWork(()->{ 23 | if(player.containerMenu instanceof UnpackagerMenu menu) { 24 | menu.blockEntity.trackers[index].ejectItems(); 25 | } 26 | }); 27 | ctx.get().setPacketHandled(true); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/network/packet/SaveRecipeListPacket.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.network.packet; 2 | 3 | import java.util.function.Supplier; 4 | 5 | import net.minecraft.network.FriendlyByteBuf; 6 | import net.minecraft.server.level.ServerPlayer; 7 | import net.minecraftforge.network.NetworkEvent; 8 | import thelm.packagedauto.menu.EncoderMenu; 9 | 10 | public record SaveRecipeListPacket(boolean single) { 11 | 12 | public void encode(FriendlyByteBuf buf) { 13 | buf.writeBoolean(single); 14 | } 15 | 16 | public static SaveRecipeListPacket decode(FriendlyByteBuf buf) { 17 | return new SaveRecipeListPacket(buf.readBoolean()); 18 | } 19 | 20 | public void handle(Supplier ctx) { 21 | ServerPlayer player = ctx.get().getSender(); 22 | ctx.get().enqueueWork(()->{ 23 | if(player.containerMenu instanceof EncoderMenu menu) { 24 | menu.blockEntity.saveRecipeList(single); 25 | } 26 | }); 27 | ctx.get().setPacketHandled(true); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/network/packet/TrackerCountPacket.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.network.packet; 2 | 3 | import java.util.function.Supplier; 4 | 5 | import net.minecraft.network.FriendlyByteBuf; 6 | import net.minecraft.server.level.ServerPlayer; 7 | import net.minecraftforge.network.NetworkEvent; 8 | import thelm.packagedauto.menu.UnpackagerMenu; 9 | 10 | public record TrackerCountPacket(boolean decrease) { 11 | 12 | public void encode(FriendlyByteBuf buf) { 13 | buf.writeBoolean(decrease); 14 | } 15 | 16 | public static TrackerCountPacket decode(FriendlyByteBuf buf) { 17 | return new TrackerCountPacket(buf.readBoolean()); 18 | } 19 | 20 | public void handle(Supplier ctx) { 21 | ServerPlayer player = ctx.get().getSender(); 22 | ctx.get().enqueueWork(()->{ 23 | if(player.containerMenu instanceof UnpackagerMenu menu) { 24 | menu.blockEntity.changeTrackerCount(decrease); 25 | } 26 | }); 27 | ctx.get().setPacketHandled(true); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/network/packet/SetFluidAmountPacket.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.network.packet; 2 | 3 | import java.util.function.Supplier; 4 | 5 | import net.minecraft.network.FriendlyByteBuf; 6 | import net.minecraft.server.level.ServerPlayer; 7 | import net.minecraftforge.network.NetworkEvent; 8 | import thelm.packagedauto.menu.FluidPackageFillerMenu; 9 | 10 | public record SetFluidAmountPacket(int amount) { 11 | 12 | public void encode(FriendlyByteBuf buf) { 13 | buf.writeInt(amount); 14 | } 15 | 16 | public static SetFluidAmountPacket decode(FriendlyByteBuf buf) { 17 | return new SetFluidAmountPacket(buf.readInt()); 18 | } 19 | 20 | public void handle(Supplier ctx) { 21 | ServerPlayer player = ctx.get().getSender(); 22 | ctx.get().enqueueWork(()->{ 23 | if(player.containerMenu instanceof FluidPackageFillerMenu menu) { 24 | menu.blockEntity.requiredAmount = amount; 25 | } 26 | }); 27 | ctx.get().setPacketHandled(true); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/menu/PackagingProviderMenu.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.menu; 2 | 3 | import net.minecraft.world.entity.player.Inventory; 4 | import net.minecraft.world.inventory.MenuType; 5 | import net.minecraftforge.common.extensions.IForgeMenuType; 6 | import thelm.packagedauto.block.entity.PackagingProviderBlockEntity; 7 | import thelm.packagedauto.menu.factory.PositionalBlockEntityMenuFactory; 8 | import thelm.packagedauto.slot.SingleStackSlot; 9 | 10 | public class PackagingProviderMenu extends BaseMenu { 11 | 12 | public static final MenuType TYPE_INSTANCE = IForgeMenuType.create(new PositionalBlockEntityMenuFactory<>(PackagingProviderMenu::new)); 13 | 14 | public PackagingProviderMenu(int windowId, Inventory inventory, PackagingProviderBlockEntity blockEntity) { 15 | super(TYPE_INSTANCE, windowId, inventory, blockEntity); 16 | addSlot(new SingleStackSlot(itemHandler, 0, 26, 35)); 17 | setupPlayerInventory(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/inventory/PackagerExtensionItemHandlerWrapper.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.inventory; 2 | 3 | import java.util.stream.IntStream; 4 | 5 | import net.minecraft.core.Direction; 6 | import net.minecraft.world.item.ItemStack; 7 | 8 | public class PackagerExtensionItemHandlerWrapper extends SidedItemHandlerWrapper { 9 | 10 | public static final int[] SLOTS = IntStream.rangeClosed(0, 9).toArray(); 11 | 12 | public PackagerExtensionItemHandlerWrapper(PackagerExtensionItemHandler itemHandler, Direction direction) { 13 | super(itemHandler, direction); 14 | } 15 | 16 | @Override 17 | public int[] getSlotsForDirection(Direction direction) { 18 | return SLOTS; 19 | } 20 | 21 | @Override 22 | public boolean canInsertItem(int slot, ItemStack stack, Direction direction) { 23 | return slot < 9; 24 | } 25 | 26 | @Override 27 | public boolean canExtractItem(int slot, Direction direction) { 28 | return slot == 9 || direction == Direction.UP; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/network/packet/SetPatternIndexPacket.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.network.packet; 2 | 3 | import java.util.function.Supplier; 4 | 5 | import net.minecraft.network.FriendlyByteBuf; 6 | import net.minecraft.server.level.ServerPlayer; 7 | import net.minecraftforge.network.NetworkEvent; 8 | import thelm.packagedauto.menu.EncoderMenu; 9 | 10 | public record SetPatternIndexPacket(int index) { 11 | 12 | public void encode(FriendlyByteBuf buf) { 13 | buf.writeByte(index); 14 | } 15 | 16 | public static SetPatternIndexPacket decode(FriendlyByteBuf buf) { 17 | return new SetPatternIndexPacket(buf.readUnsignedByte()); 18 | } 19 | 20 | public void handle(Supplier ctx) { 21 | ServerPlayer player = ctx.get().getSender(); 22 | ctx.get().enqueueWork(()->{ 23 | if(player.containerMenu instanceof EncoderMenu menu) { 24 | menu.blockEntity.setPatternIndex(index); 25 | menu.setupSlots(); 26 | } 27 | }); 28 | ctx.get().setPacketHandled(true); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/network/packet/CycleRecipeTypePacket.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.network.packet; 2 | 3 | import java.util.function.Supplier; 4 | 5 | import net.minecraft.network.FriendlyByteBuf; 6 | import net.minecraft.server.level.ServerPlayer; 7 | import net.minecraftforge.network.NetworkEvent; 8 | import thelm.packagedauto.menu.EncoderMenu; 9 | 10 | public record CycleRecipeTypePacket(boolean reverse) { 11 | 12 | public void encode(FriendlyByteBuf buf) { 13 | buf.writeBoolean(reverse); 14 | } 15 | 16 | public static CycleRecipeTypePacket decode(FriendlyByteBuf buf) { 17 | return new CycleRecipeTypePacket(buf.readBoolean()); 18 | } 19 | 20 | public void handle(Supplier ctx) { 21 | ServerPlayer player = ctx.get().getSender(); 22 | ctx.get().enqueueWork(()->{ 23 | if(player.containerMenu instanceof EncoderMenu menu) { 24 | menu.patternItemHandler.cycleRecipeType(reverse); 25 | menu.setupSlots(); 26 | } 27 | }); 28 | ctx.get().setPacketHandled(true); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/integration/jei/RecipeSlotViewWrapper.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.integration.jei; 2 | 3 | import java.util.List; 4 | import java.util.Optional; 5 | 6 | import mezz.jei.api.gui.ingredient.IRecipeSlotView; 7 | import mezz.jei.api.recipe.RecipeIngredientRole; 8 | import thelm.packagedauto.api.IRecipeSlotViewWrapper; 9 | 10 | public record RecipeSlotViewWrapper(IRecipeSlotView recipeSlotView) implements IRecipeSlotViewWrapper { 11 | 12 | @Override 13 | public Optional getDisplayedIngredient() { 14 | return recipeSlotView.getDisplayedIngredient().map(i->i.getIngredient()); 15 | } 16 | 17 | @Override 18 | public List getAllIngredients() { 19 | return recipeSlotView.getAllIngredients().map(i->i.getIngredient()).toList(); 20 | } 21 | 22 | @Override 23 | public boolean isInput() { 24 | return recipeSlotView.getRole() == RecipeIngredientRole.INPUT; 25 | } 26 | 27 | @Override 28 | public boolean isOutput() { 29 | return recipeSlotView.getRole() == RecipeIngredientRole.OUTPUT; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/patchouli_books/guide/en_us/entries/core/settings_cloner.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Settings Cloner", 3 | "category": "packagedauto:core", 4 | "icon": "packagedauto:settings_cloner", 5 | "pages": [ 6 | { 7 | "type": "patchouli:text", 8 | "text": "The $(item)Packaging Settings Cloner/$ can copy and paste settings of certain packaging machines." 9 | }, 10 | { 11 | "type": "patchouli:spotlight", 12 | "item": "packagedauto:settings_cloner", 13 | "link_recipe": true, 14 | "title": "Usage", 15 | "text": "To use the $(item)Packaging Settings Cloner/$, $(thing)$(k:sneak) + $(k:use)/$ on a supported machine to copy its settings.$(p)You can then $(thing)$(k:use)/$ on the same type of machine to paste settings.$(p)To clear, $(thing)$(k:sneak) + $(k:use)/$ on air or blocks other than supported machines." 16 | }, 17 | { 18 | "type": "patchouli:crafting", 19 | "recipe": "packagedauto:settings_cloner", 20 | "title": "Crafting" 21 | } 22 | ], 23 | "read_by_default": true, 24 | "sortnum": 5 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/network/packet/LoadRecipeListPacket.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.network.packet; 2 | 3 | import java.util.function.Supplier; 4 | 5 | import net.minecraft.network.FriendlyByteBuf; 6 | import net.minecraft.server.level.ServerPlayer; 7 | import net.minecraftforge.network.NetworkEvent; 8 | import thelm.packagedauto.menu.EncoderMenu; 9 | 10 | public record LoadRecipeListPacket(boolean single, boolean clear) { 11 | 12 | public void encode(FriendlyByteBuf buf) { 13 | buf.writeBoolean(single); 14 | buf.writeBoolean(clear); 15 | } 16 | 17 | public static LoadRecipeListPacket decode(FriendlyByteBuf buf) { 18 | return new LoadRecipeListPacket(buf.readBoolean(), buf.readBoolean()); 19 | } 20 | 21 | public void handle(Supplier ctx) { 22 | ServerPlayer player = ctx.get().getSender(); 23 | ctx.get().enqueueWork(()->{ 24 | if(player.containerMenu instanceof EncoderMenu menu) { 25 | menu.blockEntity.loadRecipeList(single, clear); 26 | } 27 | }); 28 | ctx.get().setPacketHandled(true); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/menu/VolumeAmountSpecifyingMenu.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.menu; 2 | 3 | import net.minecraft.world.entity.player.Inventory; 4 | import thelm.packagedauto.api.IVolumeStackWrapper; 5 | import thelm.packagedauto.block.entity.BaseBlockEntity; 6 | import thelm.packagedauto.inventory.BaseVolumeInventory; 7 | import thelm.packagedauto.slot.PreviewVolumeSlot; 8 | 9 | public class VolumeAmountSpecifyingMenu extends BaseMenu { 10 | 11 | public VolumeAmountSpecifyingMenu(Inventory inventory, IVolumeStackWrapper stack) { 12 | super(null, 0, inventory, null); 13 | BaseVolumeInventory volumeInventory = new BaseVolumeInventory(stack.getVolumeType(), 1); 14 | volumeInventory.setStackInSlot(0, stack); 15 | addSlot(new PreviewVolumeSlot(volumeInventory, 0, 89, 48)); 16 | } 17 | 18 | @Override 19 | public int getPlayerInvX() { 20 | return 0; 21 | } 22 | 23 | @Override 24 | public int getPlayerInvY() { 25 | return 0; 26 | } 27 | 28 | @Override 29 | public int getSizeInventory() { 30 | return 0; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/block/EncoderBlock.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.block; 2 | 3 | import net.minecraft.core.BlockPos; 4 | import net.minecraft.world.item.BlockItem; 5 | import net.minecraft.world.item.Item; 6 | import net.minecraft.world.level.block.SoundType; 7 | import net.minecraft.world.level.block.state.BlockBehaviour; 8 | import net.minecraft.world.level.block.state.BlockState; 9 | import net.minecraft.world.level.material.MapColor; 10 | import thelm.packagedauto.block.entity.EncoderBlockEntity; 11 | 12 | public class EncoderBlock extends BaseBlock { 13 | 14 | public static final EncoderBlock INSTANCE = new EncoderBlock(); 15 | public static final Item ITEM_INSTANCE = new BlockItem(INSTANCE, new Item.Properties()); 16 | 17 | protected EncoderBlock() { 18 | super(BlockBehaviour.Properties.of().strength(10F, 15F).mapColor(MapColor.METAL).sound(SoundType.METAL)); 19 | } 20 | 21 | @Override 22 | public EncoderBlockEntity newBlockEntity(BlockPos pos, BlockState state) { 23 | return EncoderBlockEntity.TYPE_INSTANCE.create(pos, state); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/inventory/UnpackagerItemHandlerWrapper.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.inventory; 2 | 3 | import java.util.Arrays; 4 | import java.util.stream.IntStream; 5 | 6 | import net.minecraft.core.Direction; 7 | import net.minecraft.world.item.ItemStack; 8 | 9 | public class UnpackagerItemHandlerWrapper extends SidedItemHandlerWrapper { 10 | 11 | public static final int[] SLOTS = IntStream.rangeClosed(0, 8).toArray(); 12 | 13 | public UnpackagerItemHandlerWrapper(UnpackagerItemHandler itemHandler, Direction direction) { 14 | super(itemHandler, direction); 15 | } 16 | 17 | @Override 18 | public int[] getSlotsForDirection(Direction direction) { 19 | return SLOTS; 20 | } 21 | 22 | @Override 23 | public boolean canInsertItem(int slot, ItemStack stack, Direction direction) { 24 | return true; 25 | } 26 | 27 | @Override 28 | public boolean canExtractItem(int slot, Direction direction) { 29 | return direction == Direction.UP && !Arrays.stream(itemHandler.blockEntity.trackers).anyMatch(t->t.isEmpty()); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/patchouli_books/guide/en_us/entries/core/introduction.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Introduction", 3 | "category": "packagedauto:core", 4 | "icon": "packagedauto:package", 5 | "pages": [ 6 | { 7 | "type": "patchouli:text", 8 | "text": "$(#822)PackagedAuto/$ uses $(thing)packages/$ of items to ease certain crafting tasks.$(p)To start, you will need to encode $(l:core/recipe_holder)Recipe Pattern Holders/$ with a $(l:core/encoder)Package Recipe Encoder/$.$(br)You can then use the encoded holders to tell $(l:core/packager)Packagers/$ what $(l:core/package)Recipe Packages/$ they can make, and these packages can be unpackaged in the $(l:core/unpackager)Unpackager/$." 9 | }, 10 | { 11 | "type": "patchouli:text", 12 | "flag": "mod:ae2", 13 | "title": "AE2 Integration", 14 | "text": "Much of $(#822)PackagedAuto/$ are designed with AE2 integration in mind, check entries for machines to see what functionality is added when connected to $(thing)ME Networks/$." 15 | } 16 | ], 17 | "read_by_default": true, 18 | "sortnum": 0 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/menu/ItemAmountSpecifyingMenu.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.menu; 2 | 3 | import net.minecraft.world.entity.player.Inventory; 4 | import net.minecraft.world.item.ItemStack; 5 | import net.minecraftforge.items.ItemHandlerHelper; 6 | import net.minecraftforge.items.ItemStackHandler; 7 | import thelm.packagedauto.block.entity.BaseBlockEntity; 8 | import thelm.packagedauto.slot.PreviewSlot; 9 | 10 | public class ItemAmountSpecifyingMenu extends BaseMenu { 11 | 12 | public ItemAmountSpecifyingMenu(Inventory inventory, ItemStack stack) { 13 | super(null, 0, inventory, null); 14 | ItemStackHandler itemInventory = new ItemStackHandler(1); 15 | itemInventory.setStackInSlot(0, ItemHandlerHelper.copyStackWithSize(stack, 1)); 16 | addSlot(new PreviewSlot(itemInventory, 0, 89, 48)); 17 | } 18 | 19 | @Override 20 | public int getPlayerInvX() { 21 | return 0; 22 | } 23 | 24 | @Override 25 | public int getPlayerInvY() { 26 | return 0; 27 | } 28 | 29 | @Override 30 | public int getSizeInventory() { 31 | return 0; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/menu/CraftingProxyMenu.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.menu; 2 | 3 | import net.minecraft.world.entity.player.Inventory; 4 | import net.minecraft.world.inventory.MenuType; 5 | import net.minecraftforge.common.extensions.IForgeMenuType; 6 | import thelm.packagedauto.block.entity.CraftingProxyBlockEntity; 7 | import thelm.packagedauto.menu.factory.PositionalBlockEntityMenuFactory; 8 | import thelm.packagedauto.slot.SingleStackSlot; 9 | 10 | public class CraftingProxyMenu extends BaseMenu { 11 | 12 | public static final MenuType TYPE_INSTANCE = IForgeMenuType.create(new PositionalBlockEntityMenuFactory<>(CraftingProxyMenu::new)); 13 | 14 | public CraftingProxyMenu(int windowId, Inventory inventory, CraftingProxyBlockEntity blockEntity) { 15 | super(TYPE_INSTANCE, windowId, inventory, blockEntity); 16 | addSlot(new SingleStackSlot(itemHandler, 0, 80, 17)); 17 | setupPlayerInventory(); 18 | } 19 | 20 | @Override 21 | public int getPlayerInvX() { 22 | return 8; 23 | } 24 | 25 | @Override 26 | public int getPlayerInvY() { 27 | return 48; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/menu/factory/PositionalBlockEntityMenuFactory.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.menu.factory; 2 | 3 | import net.minecraft.core.BlockPos; 4 | import net.minecraft.network.FriendlyByteBuf; 5 | import net.minecraft.world.entity.player.Inventory; 6 | import net.minecraft.world.inventory.AbstractContainerMenu; 7 | import net.minecraft.world.level.block.entity.BlockEntity; 8 | import net.minecraftforge.network.IContainerFactory; 9 | 10 | public class PositionalBlockEntityMenuFactory implements IContainerFactory { 11 | 12 | public interface Factory { 13 | C create(int windowId, Inventory inv, T blockEntity); 14 | } 15 | 16 | private final Factory factory; 17 | 18 | public PositionalBlockEntityMenuFactory(Factory factory) { 19 | this.factory = factory; 20 | } 21 | 22 | @Override 23 | public C create(int windowId, Inventory inv, FriendlyByteBuf data) { 24 | BlockPos pos = data.readBlockPos(); 25 | T blockEntity = (T)inv.player.level().getBlockEntity(pos); 26 | return factory.create(windowId, inv, blockEntity); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 TheLMiffy1111 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/network/packet/ChangeProvidingPacket.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.network.packet; 2 | 3 | import java.util.function.Supplier; 4 | 5 | import net.minecraft.network.FriendlyByteBuf; 6 | import net.minecraft.server.level.ServerPlayer; 7 | import net.minecraftforge.network.NetworkEvent; 8 | import thelm.packagedauto.block.entity.PackagingProviderBlockEntity; 9 | import thelm.packagedauto.menu.PackagingProviderMenu; 10 | 11 | public record ChangeProvidingPacket(PackagingProviderBlockEntity.Type type) { 12 | 13 | public void encode(FriendlyByteBuf buf) { 14 | buf.writeEnum(type); 15 | } 16 | 17 | public static ChangeProvidingPacket decode(FriendlyByteBuf buf) { 18 | return new ChangeProvidingPacket(buf.readEnum(PackagingProviderBlockEntity.Type.class)); 19 | } 20 | 21 | public void handle(Supplier ctx) { 22 | ServerPlayer player = ctx.get().getSender(); 23 | ctx.get().enqueueWork(()->{ 24 | if(player.containerMenu instanceof PackagingProviderMenu menu) { 25 | menu.blockEntity.changeProvideType(type); 26 | } 27 | }); 28 | ctx.get().setPacketHandled(true); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/api/SettingsClonerData.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.api; 2 | 3 | import net.minecraft.core.BlockPos; 4 | import net.minecraft.core.GlobalPos; 5 | import net.minecraft.nbt.CompoundTag; 6 | import net.minecraft.resources.ResourceKey; 7 | import net.minecraft.world.level.Level; 8 | 9 | public record SettingsClonerData(String type, CompoundTag data, GlobalPos globalPos) { 10 | 11 | public SettingsClonerData(String type, CompoundTag data, ResourceKey dimension, BlockPos blockPos) { 12 | this(type, data, GlobalPos.of(dimension, blockPos)); 13 | } 14 | 15 | public String type() { 16 | return type; 17 | } 18 | 19 | public CompoundTag data() { 20 | return data; 21 | } 22 | 23 | public GlobalPos globalPos() { 24 | return globalPos; 25 | } 26 | 27 | public ResourceKey dimension() { 28 | return globalPos.dimension(); 29 | } 30 | 31 | public BlockPos blockPos() { 32 | return globalPos.pos(); 33 | } 34 | 35 | public int x() { 36 | return blockPos().getX(); 37 | } 38 | 39 | public int y() { 40 | return blockPos().getY(); 41 | } 42 | 43 | public int z() { 44 | return blockPos().getZ(); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/patchouli_books/guide/en_us/entries/core/recipe_holder.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Package Recipe Holder", 3 | "category": "packagedauto:core", 4 | "icon": "packagedauto:recipe_holder", 5 | "pages": [ 6 | { 7 | "type": "patchouli:text", 8 | "text": "$(item)Package Recipe Holders/$ hold recipe data for machines, encoded in the $(l:core/encoder)Package Recipe Encoder/$.$(p)You can $(thing)$(k:sneak) + $(k:use)/$ an encoded $(item)Package Recipe Holder/$ or place in a crafting grid to clear.$(p)You can combine an encoded $(item)Package Recipe Holder/$ with empty ones in a crafting grid to copy contents." 9 | }, 10 | { 11 | "type": "patchouli:spotlight", 12 | "flag": "&mod:jei,!mod:emi", 13 | "item": "packagedauto:recipe_holder", 14 | "title": "JEI Integration", 15 | "text": "You can press $(thing)$(k:jei.showUses)/$ on encoded $(item)Package Recipe Holders/$ to show detailed information on what recipes are encoded." 16 | }, 17 | { 18 | "type": "patchouli:crafting", 19 | "recipe": "packagedauto:recipe_holder", 20 | "title": "Crafting" 21 | } 22 | ], 23 | "read_by_default": true, 24 | "sortnum": 4 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/menu/FluidPackageFillerMenu.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.menu; 2 | 3 | import net.minecraft.world.entity.player.Inventory; 4 | import net.minecraft.world.inventory.MenuType; 5 | import net.minecraftforge.common.extensions.IForgeMenuType; 6 | import net.minecraftforge.items.SlotItemHandler; 7 | import thelm.packagedauto.block.entity.FluidPackageFillerBlockEntity; 8 | import thelm.packagedauto.menu.factory.PositionalBlockEntityMenuFactory; 9 | import thelm.packagedauto.slot.RemoveOnlySlot; 10 | 11 | public class FluidPackageFillerMenu extends BaseMenu { 12 | 13 | public static final MenuType TYPE_INSTANCE = IForgeMenuType.create(new PositionalBlockEntityMenuFactory<>(FluidPackageFillerMenu::new)); 14 | 15 | public FluidPackageFillerMenu(int windowId, Inventory inventory, FluidPackageFillerBlockEntity blockEntity) { 16 | super(TYPE_INSTANCE, windowId, inventory, blockEntity); 17 | addSlot(new SlotItemHandler(itemHandler, 2, 8, 53)); 18 | addSlot(new SlotItemHandler(itemHandler, 0, 44, 35)); 19 | addSlot(new RemoveOnlySlot(itemHandler, 1, 134, 35)); 20 | setupPlayerInventory(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/network/packet/ChangeBlockingPacket.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.network.packet; 2 | 3 | import java.util.function.Supplier; 4 | 5 | import net.minecraft.network.FriendlyByteBuf; 6 | import net.minecraft.server.level.ServerPlayer; 7 | import net.minecraftforge.network.NetworkEvent; 8 | import thelm.packagedauto.menu.PackagingProviderMenu; 9 | import thelm.packagedauto.menu.UnpackagerMenu; 10 | 11 | public record ChangeBlockingPacket() { 12 | 13 | public static final ChangeBlockingPacket INSTANCE = new ChangeBlockingPacket(); 14 | 15 | public void encode(FriendlyByteBuf buf) {} 16 | 17 | public static ChangeBlockingPacket decode(FriendlyByteBuf buf) { 18 | return INSTANCE; 19 | } 20 | 21 | public void handle(Supplier ctx) { 22 | ServerPlayer player = ctx.get().getSender(); 23 | ctx.get().enqueueWork(()->{ 24 | if(player.containerMenu instanceof UnpackagerMenu menu) { 25 | menu.blockEntity.changeBlockingMode(); 26 | } 27 | if(player.containerMenu instanceof PackagingProviderMenu menu) { 28 | menu.blockEntity.changeBlockingMode(); 29 | } 30 | }); 31 | ctx.get().setPacketHandled(true); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/network/packet/ChangePackagingPacket.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.network.packet; 2 | 3 | import java.util.function.Supplier; 4 | 5 | import net.minecraft.network.FriendlyByteBuf; 6 | import net.minecraft.server.level.ServerPlayer; 7 | import net.minecraftforge.network.NetworkEvent; 8 | import thelm.packagedauto.menu.PackagerExtensionMenu; 9 | import thelm.packagedauto.menu.PackagerMenu; 10 | 11 | public record ChangePackagingPacket() { 12 | 13 | public static final ChangePackagingPacket INSTANCE = new ChangePackagingPacket(); 14 | 15 | public void encode(FriendlyByteBuf buf) {} 16 | 17 | public static ChangePackagingPacket decode(FriendlyByteBuf buf) { 18 | return INSTANCE; 19 | } 20 | 21 | public void handle(Supplier ctx) { 22 | ServerPlayer player = ctx.get().getSender(); 23 | ctx.get().enqueueWork(()->{ 24 | if(player.containerMenu instanceof PackagerMenu menu) { 25 | menu.blockEntity.changePackagingMode(); 26 | } 27 | if(player.containerMenu instanceof PackagerExtensionMenu menu) { 28 | menu.blockEntity.changePackagingMode(); 29 | } 30 | }); 31 | ctx.get().setPacketHandled(true); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/menu/DistributorMenu.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.menu; 2 | 3 | import net.minecraft.world.entity.player.Inventory; 4 | import net.minecraft.world.inventory.MenuType; 5 | import net.minecraftforge.common.extensions.IForgeMenuType; 6 | import thelm.packagedauto.block.entity.DistributorBlockEntity; 7 | import thelm.packagedauto.menu.factory.PositionalBlockEntityMenuFactory; 8 | import thelm.packagedauto.slot.SingleStackSlot; 9 | 10 | public class DistributorMenu extends BaseMenu { 11 | 12 | public static final MenuType TYPE_INSTANCE = IForgeMenuType.create(new PositionalBlockEntityMenuFactory<>(DistributorMenu::new)); 13 | 14 | public DistributorMenu(int windowId, Inventory inventory, DistributorBlockEntity blockEntity) { 15 | super(TYPE_INSTANCE, windowId, inventory, blockEntity); 16 | for(int i = 0; i < 9; ++i) { 17 | for(int j = 0; j < 9; ++j) { 18 | addSlot(new SingleStackSlot(itemHandler, j+i*9, 8+j*18, 17+i*18)); 19 | } 20 | } 21 | setupPlayerInventory(); 22 | } 23 | 24 | @Override 25 | public int getPlayerInvX() { 26 | return 8; 27 | } 28 | 29 | @Override 30 | public int getPlayerInvY() { 31 | return 192; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/menu/UnpackagerMenu.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.menu; 2 | 3 | import net.minecraft.world.entity.player.Inventory; 4 | import net.minecraft.world.inventory.MenuType; 5 | import net.minecraftforge.common.extensions.IForgeMenuType; 6 | import net.minecraftforge.items.SlotItemHandler; 7 | import thelm.packagedauto.block.entity.UnpackagerBlockEntity; 8 | import thelm.packagedauto.menu.factory.PositionalBlockEntityMenuFactory; 9 | import thelm.packagedauto.slot.SingleStackSlot; 10 | 11 | public class UnpackagerMenu extends BaseMenu { 12 | 13 | public static final MenuType TYPE_INSTANCE = IForgeMenuType.create(new PositionalBlockEntityMenuFactory<>(UnpackagerMenu::new)); 14 | 15 | public UnpackagerMenu(int windowId, Inventory inventory, UnpackagerBlockEntity blockEntity) { 16 | super(TYPE_INSTANCE, windowId, inventory, blockEntity); 17 | addSlot(new SingleStackSlot(itemHandler, 9, 26, 17)); 18 | addSlot(new SlotItemHandler(itemHandler, 10, 8, 53)); 19 | for(int i = 0; i < 3; ++i) { 20 | for(int j = 0; j < 3; ++j) { 21 | addSlot(new SlotItemHandler(itemHandler, j+i*3, 44+j*18, 17+i*18)); 22 | } 23 | } 24 | setupPlayerInventory(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/integration/emi/FluidVolumeStackProvider.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.integration.emi; 2 | 3 | import dev.emi.emi.api.EmiStackProvider; 4 | import dev.emi.emi.api.forge.ForgeEmiStack; 5 | import dev.emi.emi.api.stack.EmiStackInteraction; 6 | import net.minecraft.client.gui.screens.Screen; 7 | import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; 8 | import thelm.packagedauto.api.IFluidStackWrapper; 9 | import thelm.packagedauto.api.IVolumeStackWrapper; 10 | import thelm.packagedauto.slot.FalseCopyVolumeSlot; 11 | 12 | public class FluidVolumeStackProvider implements EmiStackProvider { 13 | 14 | @Override 15 | public EmiStackInteraction getStackAt(Screen screen, int x, int y) { 16 | if(screen instanceof AbstractContainerScreen containerScreen && 17 | containerScreen.getSlotUnderMouse() instanceof FalseCopyVolumeSlot volumeSlot) { 18 | IVolumeStackWrapper volumeStack = volumeSlot.volumeInventory.getStackInSlot(volumeSlot.slotIndex); 19 | if(volumeStack instanceof IFluidStackWrapper fluidVolumeStack) { 20 | return new EmiStackInteraction(ForgeEmiStack.of(fluidVolumeStack.getFluid()), null, false); 21 | } 22 | } 23 | return EmiStackInteraction.EMPTY; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/menu/CrafterMenu.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.menu; 2 | 3 | import net.minecraft.world.entity.player.Inventory; 4 | import net.minecraft.world.inventory.MenuType; 5 | import net.minecraftforge.common.extensions.IForgeMenuType; 6 | import net.minecraftforge.items.SlotItemHandler; 7 | import thelm.packagedauto.block.entity.CrafterBlockEntity; 8 | import thelm.packagedauto.menu.factory.PositionalBlockEntityMenuFactory; 9 | import thelm.packagedauto.slot.CrafterRemoveOnlySlot; 10 | import thelm.packagedauto.slot.RemoveOnlySlot; 11 | 12 | public class CrafterMenu extends BaseMenu { 13 | 14 | public static final MenuType TYPE_INSTANCE = IForgeMenuType.create(new PositionalBlockEntityMenuFactory<>(CrafterMenu::new)); 15 | 16 | public CrafterMenu(int windowId, Inventory inventory, CrafterBlockEntity blockEntity) { 17 | super(TYPE_INSTANCE, windowId, inventory, blockEntity); 18 | addSlot(new SlotItemHandler(itemHandler, 10, 8, 53)); 19 | for(int i = 0; i < 3; ++i) { 20 | for(int j = 0; j < 3; ++j) { 21 | addSlot(new CrafterRemoveOnlySlot(blockEntity, i*3+j, 44+j*18, 17+i*18)); 22 | } 23 | } 24 | addSlot(new RemoveOnlySlot(itemHandler, 9, 134, 35)); 25 | setupPlayerInventory(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/patchouli_books/guide/en_us/entries/recipe/crafting.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Crafting", 3 | "category": "packagedauto:recipe", 4 | "icon": "packagedauto:crafter", 5 | "pages": [ 6 | { 7 | "type": "patchouli:text", 8 | "text": "$(thing)Crafting/$ is a crafting recipe type that uses the $(item)Package Crafter/$ to craft recipes craftable in a crafting table.$(p)Items crafted by the $(item)Package Crafter/$ will be ejected into adjacent inventories.$(p)The $(item)Package Crafter/$ requires power." 9 | }, 10 | { 11 | "type": "patchouli:spotlight", 12 | "flag": "mod:ae2", 13 | "item": "packagedauto:crafter", 14 | "link_recipe": true, 15 | "title": "AE2 Integration", 16 | "text": "The $(item)Package Crafter/$ can be connected to an $(thing)ME Network/$.$(p)It will extract power to use, and instead eject crafted items into the network." 17 | }, 18 | { 19 | "type": "patchouli:crafting", 20 | "flag": "!mod:ae2", 21 | "recipe": "packagedauto:crafter", 22 | "title": "Crafting" 23 | }, 24 | { 25 | "type": "patchouli:crafting", 26 | "flag": "mod:ae2", 27 | "recipe": "packagedauto:crafter_ae", 28 | "title": "Crafting" 29 | } 30 | ], 31 | "read_by_default": true, 32 | "sortnum": 104 33 | } 34 | -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/patchouli_books/guide/en_us/entries/core/fluid_package_filler.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Fluid Package Filler", 3 | "category": "packagedauto:core", 4 | "icon": "packagedauto:fluid_package_filler", 5 | "pages": [ 6 | { 7 | "type": "patchouli:text", 8 | "text": "The $(item)Fluid Package Filler/$ creates $(l:core/volume_package)Volume Packages/$ filled with fluids.$(p)This machine requires power." 9 | }, 10 | { 11 | "type": "patchouli:spotlight", 12 | "item": "packagedauto:fluid_package_filler", 13 | "link_recipe": true, 14 | "title": "Usage", 15 | "text": "To use the $(item)Fluid Package Filler/$, place next to a fluid container, and place a template fluid container inside.$(p)You can then specify the amount of fluid the created $(l:core/volume_package)Volume Package/$ should contain." 16 | }, 17 | { 18 | "type": "patchouli:text", 19 | "title": "Usage (cont.)", 20 | "text": "Finally, apply a redstone signal to the machine to create the package.$(p)The created package will be ejected into adjacent inventories." 21 | }, 22 | { 23 | "type": "patchouli:crafting", 24 | "recipe": "packagedauto:fluid_package_filler", 25 | "title": "Crafting" 26 | } 27 | ], 28 | "read_by_default": true, 29 | "sortnum": 11 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/menu/PackagerMenu.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.menu; 2 | 3 | import net.minecraft.world.entity.player.Inventory; 4 | import net.minecraft.world.inventory.MenuType; 5 | import net.minecraftforge.common.extensions.IForgeMenuType; 6 | import net.minecraftforge.items.SlotItemHandler; 7 | import thelm.packagedauto.block.entity.PackagerBlockEntity; 8 | import thelm.packagedauto.menu.factory.PositionalBlockEntityMenuFactory; 9 | import thelm.packagedauto.slot.RemoveOnlySlot; 10 | import thelm.packagedauto.slot.SingleStackSlot; 11 | 12 | public class PackagerMenu extends BaseMenu { 13 | 14 | public static final MenuType TYPE_INSTANCE = IForgeMenuType.create(new PositionalBlockEntityMenuFactory<>(PackagerMenu::new)); 15 | 16 | public PackagerMenu(int windowId, Inventory inventory, PackagerBlockEntity blockEntity) { 17 | super(TYPE_INSTANCE, windowId, inventory, blockEntity); 18 | addSlot(new SingleStackSlot(itemHandler, 10, 134, 17)); 19 | addSlot(new SlotItemHandler(itemHandler, 11, 8, 53)); 20 | for(int i = 0; i < 3; ++i) { 21 | for(int j = 0; j < 3; ++j) { 22 | addSlot(new SlotItemHandler(itemHandler, j+i*3, 44+j*18, 17+i*18)); 23 | } 24 | } 25 | addSlot(new RemoveOnlySlot(itemHandler, 9, 134, 53)); 26 | setupPlayerInventory(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/client/screen/DistributorScreen.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.client.screen; 2 | 3 | import net.minecraft.client.gui.GuiGraphics; 4 | import net.minecraft.network.chat.Component; 5 | import net.minecraft.resources.ResourceLocation; 6 | import net.minecraft.world.entity.player.Inventory; 7 | import thelm.packagedauto.menu.DistributorMenu; 8 | 9 | public class DistributorScreen extends BaseScreen { 10 | 11 | public static final ResourceLocation BACKGROUND = new ResourceLocation("packagedauto:textures/gui/distributor.png"); 12 | 13 | public DistributorScreen(DistributorMenu menu, Inventory inventory, Component title) { 14 | super(menu, inventory, title); 15 | imageWidth = 176; 16 | imageHeight = 274; 17 | } 18 | 19 | @Override 20 | protected ResourceLocation getBackgroundTexture() { 21 | return BACKGROUND; 22 | } 23 | 24 | @Override 25 | protected void renderLabels(GuiGraphics graphics, int mouseX, int mouseY) { 26 | String s = menu.blockEntity.getDisplayName().getString(); 27 | graphics.drawString(font, s, imageWidth/2 - font.width(s)/2, 6, 0x404040, false); 28 | graphics.drawString(font, menu.inventory.getDisplayName().getString(), menu.getPlayerInvX(), menu.getPlayerInvY()-11, 0x404040, false); 29 | super.renderLabels(graphics, mouseX, mouseY); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/client/screen/CraftingProxyScreen.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.client.screen; 2 | 3 | import net.minecraft.client.gui.GuiGraphics; 4 | import net.minecraft.network.chat.Component; 5 | import net.minecraft.resources.ResourceLocation; 6 | import net.minecraft.world.entity.player.Inventory; 7 | import thelm.packagedauto.menu.CraftingProxyMenu; 8 | 9 | public class CraftingProxyScreen extends BaseScreen { 10 | 11 | public static final ResourceLocation BACKGROUND = new ResourceLocation("packagedauto:textures/gui/crafting_proxy.png"); 12 | 13 | public CraftingProxyScreen(CraftingProxyMenu menu, Inventory inventory, Component title) { 14 | super(menu, inventory, title); 15 | imageWidth = 176; 16 | imageHeight = 130; 17 | } 18 | 19 | @Override 20 | protected ResourceLocation getBackgroundTexture() { 21 | return BACKGROUND; 22 | } 23 | 24 | @Override 25 | protected void renderLabels(GuiGraphics graphics, int mouseX, int mouseY) { 26 | String s = menu.blockEntity.getDisplayName().getString(); 27 | graphics.drawString(font, s, imageWidth/2 - font.width(s)/2, 6, 0x404040, false); 28 | graphics.drawString(font, menu.inventory.getDisplayName().getString(), menu.getPlayerInvX(), menu.getPlayerInvY()-11, 0x404040, false); 29 | super.renderLabels(graphics, mouseX, mouseY); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/menu/PackagerExtensionMenu.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.menu; 2 | 3 | import net.minecraft.world.entity.player.Inventory; 4 | import net.minecraft.world.inventory.MenuType; 5 | import net.minecraftforge.common.extensions.IForgeMenuType; 6 | import net.minecraftforge.items.SlotItemHandler; 7 | import thelm.packagedauto.block.entity.PackagerExtensionBlockEntity; 8 | import thelm.packagedauto.menu.factory.PositionalBlockEntityMenuFactory; 9 | import thelm.packagedauto.slot.PreviewSlot; 10 | import thelm.packagedauto.slot.RemoveOnlySlot; 11 | 12 | public class PackagerExtensionMenu extends BaseMenu { 13 | 14 | public static final MenuType TYPE_INSTANCE = IForgeMenuType.create(new PositionalBlockEntityMenuFactory<>(PackagerExtensionMenu::new)); 15 | 16 | public PackagerExtensionMenu(int windowId, Inventory inventory, PackagerExtensionBlockEntity blockEntity) { 17 | super(TYPE_INSTANCE, windowId, inventory, blockEntity); 18 | addSlot(new SlotItemHandler(itemHandler, 10, 8, 53)); 19 | for(int i = 0; i < 3; ++i) { 20 | for(int j = 0; j < 3; ++j) { 21 | addSlot(new SlotItemHandler(itemHandler, j+i*3, 44+j*18, 17+i*18)); 22 | } 23 | } 24 | addSlot(new RemoveOnlySlot(itemHandler, 9, 134, 53)); 25 | addSlot(new PreviewSlot(blockEntity.listStackItemHandler, 0, 134, 17)); 26 | setupPlayerInventory(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/slot/FalseCopyVolumeSlot.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.slot; 2 | 3 | import net.minecraft.world.entity.player.Player; 4 | import net.minecraft.world.item.ItemStack; 5 | import net.minecraftforge.items.ItemStackHandler; 6 | import net.minecraftforge.items.SlotItemHandler; 7 | import thelm.packagedauto.api.IVolumeStackWrapper; 8 | import thelm.packagedauto.api.IVolumeType; 9 | import thelm.packagedauto.inventory.BaseVolumeInventory; 10 | 11 | public class FalseCopyVolumeSlot extends SlotItemHandler { 12 | 13 | public int slotIndex; 14 | public BaseVolumeInventory volumeInventory; 15 | 16 | public FalseCopyVolumeSlot(BaseVolumeInventory volumeInventory, int index, int x, int y) { 17 | super(new ItemStackHandler(volumeInventory.getSlots()), index, x, y); 18 | slotIndex = index; 19 | this.volumeInventory = volumeInventory; 20 | } 21 | 22 | @Override 23 | public boolean mayPickup(Player player) { 24 | return false; 25 | } 26 | 27 | @Override 28 | public void set(ItemStack stack) { 29 | IVolumeType type = volumeInventory.type; 30 | if(stack.isEmpty()) { 31 | volumeInventory.setStackInSlot(getSlotIndex(), type.getEmptyStackInstance()); 32 | } 33 | else { 34 | IVolumeStackWrapper vStack = type.getStackContained(stack).orElse(type.getEmptyStackInstance()); 35 | if(!vStack.isEmpty()) { 36 | volumeInventory.setStackInSlot(getSlotIndex(), vStack); 37 | } 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/volume/UnknownStackWrapper.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.volume; 2 | 3 | import java.util.List; 4 | 5 | import net.minecraft.nbt.CompoundTag; 6 | import net.minecraft.network.chat.Component; 7 | import thelm.packagedauto.api.IVolumeStackWrapper; 8 | import thelm.packagedauto.api.IVolumeType; 9 | 10 | public class UnknownStackWrapper implements IVolumeStackWrapper { 11 | 12 | public static final UnknownStackWrapper INSTANCE = new UnknownStackWrapper(); 13 | 14 | @Override 15 | public IVolumeType getVolumeType() { 16 | return null; 17 | } 18 | 19 | @Override 20 | public int getAmount() { 21 | return 0; 22 | } 23 | 24 | @Override 25 | public IVolumeStackWrapper copy() { 26 | return INSTANCE; 27 | } 28 | 29 | @Override 30 | public void setAmount(int amount) {} 31 | 32 | @Override 33 | public boolean isEmpty() { 34 | return true; 35 | } 36 | 37 | @Override 38 | public CompoundTag save(CompoundTag tag) { 39 | return tag; 40 | } 41 | 42 | @Override 43 | public CompoundTag saveAEKey(CompoundTag tag) { 44 | return tag; 45 | } 46 | 47 | @Override 48 | public Component getDisplayName() { 49 | return Component.literal("Unknown"); 50 | } 51 | 52 | @Override 53 | public Component getAmountDesc() { 54 | return Component.literal(""); 55 | } 56 | 57 | @Override 58 | public List getTooltip() { 59 | return List.of(Component.literal("Unknown")); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/api/IPackageRecipeType.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.api; 2 | 3 | import java.util.List; 4 | 5 | import it.unimi.dsi.fastutil.ints.Int2ObjectMap; 6 | import it.unimi.dsi.fastutil.ints.Int2ObjectMaps; 7 | import it.unimi.dsi.fastutil.ints.IntSet; 8 | import net.minecraft.core.Vec3i; 9 | import net.minecraft.network.chat.MutableComponent; 10 | import net.minecraft.resources.ResourceLocation; 11 | import net.minecraft.world.item.ItemStack; 12 | 13 | public interface IPackageRecipeType { 14 | 15 | ResourceLocation getName(); 16 | 17 | MutableComponent getDisplayName(); 18 | 19 | MutableComponent getShortDisplayName(); 20 | 21 | IPackageRecipeInfo getNewRecipeInfo(); 22 | 23 | IntSet getEnabledSlots(); 24 | 25 | default boolean canSetOutput() { 26 | return false; 27 | } 28 | 29 | default boolean hasMachine() { 30 | return true; 31 | } 32 | 33 | default boolean isOrdered() { 34 | return false; 35 | } 36 | 37 | default boolean hasCraftingRemainingItem() { 38 | return true; 39 | } 40 | 41 | default List getJEICategories() { 42 | return List.of(); 43 | } 44 | 45 | default List getEMICategories() { 46 | return getJEICategories(); 47 | } 48 | 49 | default Int2ObjectMap getRecipeTransferMap(IRecipeSlotsViewWrapper recipeLayoutWrapper) { 50 | return Int2ObjectMaps.emptyMap(); 51 | } 52 | 53 | Object getRepresentation(); 54 | 55 | Vec3i getSlotColor(int slot); 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/util/PackageRecipeList.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.util; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Collections; 5 | import java.util.List; 6 | 7 | import net.minecraft.nbt.CompoundTag; 8 | import net.minecraft.nbt.ListTag; 9 | import thelm.packagedauto.api.IPackageRecipeInfo; 10 | import thelm.packagedauto.api.IPackageRecipeList; 11 | 12 | public class PackageRecipeList implements IPackageRecipeList { 13 | 14 | private List recipeList = new ArrayList<>(); 15 | 16 | public PackageRecipeList(CompoundTag nbt) { 17 | load(nbt); 18 | } 19 | 20 | public PackageRecipeList(List recipeList) { 21 | setRecipeList(recipeList); 22 | } 23 | 24 | @Override 25 | public List getRecipeList() { 26 | return Collections.unmodifiableList(recipeList); 27 | } 28 | 29 | @Override 30 | public void setRecipeList(List recipeList) { 31 | this.recipeList.clear(); 32 | this.recipeList.addAll(recipeList); 33 | } 34 | 35 | @Override 36 | public void load(CompoundTag nbt) { 37 | recipeList.clear(); 38 | if(nbt != null) { 39 | recipeList.addAll(MiscHelper.INSTANCE.loadRecipeList(nbt.getList("Recipes", 10))); 40 | } 41 | } 42 | 43 | @Override 44 | public void save(CompoundTag nbt) { 45 | ListTag tagList = MiscHelper.INSTANCE.saveRecipeList(new ListTag(), recipeList); 46 | if(!tagList.isEmpty()) { 47 | nbt.put("Recipes", tagList); 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/recipe/OrderedProcessingPackageRecipeType.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.recipe; 2 | 3 | import net.minecraft.network.chat.Component; 4 | import net.minecraft.network.chat.MutableComponent; 5 | import net.minecraft.resources.ResourceLocation; 6 | import net.minecraft.world.item.ItemStack; 7 | import net.minecraft.world.level.block.Blocks; 8 | import thelm.packagedauto.api.IPackageRecipeInfo; 9 | 10 | public class OrderedProcessingPackageRecipeType extends ProcessingPackageRecipeType { 11 | 12 | public static final OrderedProcessingPackageRecipeType INSTANCE = new OrderedProcessingPackageRecipeType(); 13 | public static final ResourceLocation NAME = new ResourceLocation("packagedauto:ordered_processing"); 14 | 15 | @Override 16 | public ResourceLocation getName() { 17 | return NAME; 18 | } 19 | 20 | @Override 21 | public MutableComponent getDisplayName() { 22 | return Component.translatable("recipe.packagedauto.ordered_processing"); 23 | } 24 | 25 | @Override 26 | public MutableComponent getShortDisplayName() { 27 | return Component.translatable("recipe.packagedauto.ordered_processing.short"); 28 | } 29 | 30 | @Override 31 | public IPackageRecipeInfo getNewRecipeInfo() { 32 | return new OrderedProcessingPackageRecipeInfo(); 33 | } 34 | 35 | @Override 36 | public boolean isOrdered() { 37 | return true; 38 | } 39 | 40 | @Override 41 | public Object getRepresentation() { 42 | return new ItemStack(Blocks.BREWING_STAND); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/patchouli_books/guide/en_us/entries/core/volume_package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Volume Package", 3 | "category": "packagedauto:core", 4 | "icon": "packagedauto:volume_package", 5 | "pages": [ 6 | { 7 | "type": "patchouli:text", 8 | "text": "$(item)Volume Packages/$ can contain certain bulk materials such as fluids, and can be inserted or unpackaged into corresponding containers." 9 | }, 10 | { 11 | "type": "patchouli:spotlight", 12 | "item": "packagedauto:volume_package", 13 | "link_recipe": true, 14 | "title": "Creation", 15 | "text": "$(item)Volume Packages/$ of specific materials can be created in corresponding special machines, such as in $(l:core/fluid_package_filler)Fluid Package Fillers/$ for $(item)Volume Packages/$ that contain fluids." 16 | }, 17 | { 18 | "type": "patchouli:text", 19 | "flag": "&mod:jei,!mod:emi", 20 | "item": "packagedauto:volume_package", 21 | "title": "JEI Integration", 22 | "text": "You can press $(thing)$(k:jei.showUses)/$ on a $(item)Volume Package/$ to show its contents." 23 | }, 24 | { 25 | "type": "patchouli:text", 26 | "flag": "mod:ae2", 27 | "item": "packagedauto:volume_package", 28 | "title": "AE2 Integration", 29 | "text": "Machines that provide autocrafting to $(thing)ME Networks/$ can treat $(thing)Volume Packages/$ contents as autocrafting inputs/outputs, and can directly create them." 30 | } 31 | ], 32 | "read_by_default": true, 33 | "sortnum": 3 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/integration/emi/EmiIngredientWrapper.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.integration.emi; 2 | 3 | import java.util.List; 4 | import java.util.Optional; 5 | 6 | import dev.emi.emi.api.stack.EmiIngredient; 7 | import thelm.packagedauto.api.IRecipeSlotViewWrapper; 8 | 9 | public record EmiIngredientWrapper(EmiIngredient ingredient, Type type) implements IRecipeSlotViewWrapper { 10 | 11 | public static IRecipeSlotViewWrapper input(EmiIngredient ingredient) { 12 | return new EmiIngredientWrapper(ingredient, Type.INPUT); 13 | } 14 | 15 | public static IRecipeSlotViewWrapper output(EmiIngredient ingredient) { 16 | return new EmiIngredientWrapper(ingredient, Type.OUTPUT); 17 | } 18 | 19 | public static IRecipeSlotViewWrapper catalyst(EmiIngredient ingredient) { 20 | return new EmiIngredientWrapper(ingredient, Type.CATALYST); 21 | } 22 | 23 | public static enum Type { 24 | INPUT, 25 | OUTPUT, 26 | CATALYST; 27 | } 28 | 29 | @Override 30 | public Optional getDisplayedIngredient() { 31 | return PackagedAutoEMIPlugin.toStack(PackagedAutoEMIPlugin.getTreeEmiStack(ingredient)); 32 | } 33 | 34 | @Override 35 | public List getAllIngredients() { 36 | return ingredient.getEmiStacks().stream().flatMap(i->PackagedAutoEMIPlugin.toStack(i).stream()).toList(); 37 | } 38 | 39 | @Override 40 | public boolean isInput() { 41 | return type == Type.INPUT; 42 | } 43 | 44 | @Override 45 | public boolean isOutput() { 46 | return type == Type.OUTPUT; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/util/OptionalIntDataSlot.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.util; 2 | 3 | import java.util.OptionalInt; 4 | 5 | import net.minecraft.world.inventory.ContainerData; 6 | import net.minecraft.world.inventory.DataSlot; 7 | 8 | public abstract class OptionalIntDataSlot extends DataSlot { 9 | 10 | private OptionalInt prevValue = OptionalInt.empty(); 11 | 12 | public static OptionalIntDataSlot of(ContainerData data, final int id) { 13 | return new OptionalIntDataSlot() { 14 | @Override 15 | public int get() { 16 | return data.get(id); 17 | } 18 | @Override 19 | public void set(int value) { 20 | data.set(id, value); 21 | } 22 | }; 23 | } 24 | 25 | public static OptionalIntDataSlot of(int[] data, final int id) { 26 | return new OptionalIntDataSlot() { 27 | @Override 28 | public int get() { 29 | return data[id]; 30 | } 31 | @Override 32 | public void set(int value) { 33 | data[id] = value; 34 | } 35 | }; 36 | } 37 | 38 | public static OptionalIntDataSlot of() { 39 | return new OptionalIntDataSlot() { 40 | private int value; 41 | @Override 42 | public int get() { 43 | return value; 44 | } 45 | @Override 46 | public void set(int value) { 47 | this.value = value; 48 | } 49 | }; 50 | } 51 | 52 | public boolean checkAndClearUpdateFlag() { 53 | int i = get(); 54 | boolean flag = prevValue.isEmpty() || i != prevValue.getAsInt(); 55 | prevValue = OptionalInt.of(i); 56 | return flag; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/block/CrafterBlock.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.block; 2 | 3 | import net.minecraft.core.BlockPos; 4 | import net.minecraft.world.item.BlockItem; 5 | import net.minecraft.world.item.Item; 6 | import net.minecraft.world.level.Level; 7 | import net.minecraft.world.level.block.SoundType; 8 | import net.minecraft.world.level.block.entity.BlockEntity; 9 | import net.minecraft.world.level.block.entity.BlockEntityTicker; 10 | import net.minecraft.world.level.block.entity.BlockEntityType; 11 | import net.minecraft.world.level.block.state.BlockBehaviour; 12 | import net.minecraft.world.level.block.state.BlockState; 13 | import net.minecraft.world.level.material.MapColor; 14 | import thelm.packagedauto.block.entity.BaseBlockEntity; 15 | import thelm.packagedauto.block.entity.CrafterBlockEntity; 16 | 17 | public class CrafterBlock extends BaseBlock { 18 | 19 | public static final CrafterBlock INSTANCE = new CrafterBlock(); 20 | public static final Item ITEM_INSTANCE = new BlockItem(INSTANCE, new Item.Properties()); 21 | 22 | protected CrafterBlock() { 23 | super(BlockBehaviour.Properties.of().strength(10F, 15F).mapColor(MapColor.METAL).sound(SoundType.METAL)); 24 | } 25 | 26 | @Override 27 | public CrafterBlockEntity newBlockEntity(BlockPos pos, BlockState state) { 28 | return CrafterBlockEntity.TYPE_INSTANCE.create(pos, state); 29 | } 30 | 31 | @Override 32 | public BlockEntityTicker getTicker(Level level, BlockState state, BlockEntityType blockEntityType) { 33 | return BaseBlockEntity::tick; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/integration/jei/EncoderGuiHandler.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.integration.jei; 2 | 3 | import java.util.Collection; 4 | import java.util.List; 5 | 6 | import mezz.jei.api.gui.handlers.IGuiClickableArea; 7 | import mezz.jei.api.gui.handlers.IGuiContainerHandler; 8 | import mezz.jei.api.recipe.IFocusFactory; 9 | import mezz.jei.api.recipe.RecipeType; 10 | import mezz.jei.api.runtime.IRecipesGui; 11 | import net.minecraft.client.renderer.Rect2i; 12 | import net.minecraft.resources.ResourceLocation; 13 | import thelm.packagedauto.client.screen.EncoderScreen; 14 | 15 | public class EncoderGuiHandler implements IGuiContainerHandler { 16 | 17 | @Override 18 | public Collection getGuiClickableAreas(EncoderScreen containerScreen, double mouseX, double mouseY) { 19 | Rect2i area = new Rect2i(172, 129, 22, 16); 20 | List categories = containerScreen.menu.patternItemHandler.recipeType.getJEICategories(); 21 | List> types = PackagedAutoJEIPlugin.jeiRuntime.getRecipeManager().createRecipeCategoryLookup().get(). 22 | >map(c->c.getRecipeType()).filter(t->categories.contains(t.getUid())).toList(); 23 | if(!types.isEmpty()) { 24 | return List.of(new IGuiClickableArea() { 25 | @Override 26 | public Rect2i getArea() { 27 | return area; 28 | } 29 | 30 | @Override 31 | public void onClick(IFocusFactory focusFactory, IRecipesGui recipesGui) { 32 | recipesGui.showTypes(types); 33 | } 34 | }); 35 | } 36 | return List.of(); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/api/PackagedAutoApi.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.api; 2 | 3 | import java.util.NavigableMap; 4 | 5 | import net.minecraft.resources.ResourceLocation; 6 | 7 | public abstract class PackagedAutoApi { 8 | 9 | private static PackagedAutoApi instance; 10 | 11 | public static PackagedAutoApi instance() { 12 | if(instance == null) { 13 | try { 14 | instance = PackagedAutoApi.class.cast( 15 | Class.forName("thelm.packagedauto.util.ApiImpl"). 16 | getField("INSTANCE"). 17 | get(null)); 18 | } 19 | catch(Exception e) { 20 | throw new IllegalStateException("Unable to obtain api implementation.", e); 21 | } 22 | } 23 | return instance; 24 | } 25 | 26 | public abstract boolean registerRecipeType(IPackageRecipeType type); 27 | 28 | public abstract IPackageRecipeType getRecipeType(ResourceLocation name); 29 | 30 | public abstract IPackageRecipeType getRecipeType(int id); 31 | 32 | public abstract int getId(IPackageRecipeType type); 33 | 34 | public abstract NavigableMap getRecipeTypeRegistry(); 35 | 36 | public abstract IPackageRecipeType getNextRecipeType(IPackageRecipeType type, boolean reverse); 37 | 38 | public abstract boolean registerVolumeType(IVolumeType type); 39 | 40 | public abstract IVolumeType getVolumeType(ResourceLocation name); 41 | 42 | public abstract IVolumeType getVolumeType(Class typeClass); 43 | 44 | public abstract NavigableMap getVolumeTypeRegistry(); 45 | 46 | public abstract IMiscHelper miscHelper(); 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/util/PackagePattern.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.util; 2 | 3 | import java.util.List; 4 | 5 | import net.minecraft.world.item.ItemStack; 6 | import thelm.packagedauto.api.IPackagePattern; 7 | import thelm.packagedauto.api.IPackageRecipeInfo; 8 | import thelm.packagedauto.item.PackageItem; 9 | 10 | public class PackagePattern implements IPackagePattern { 11 | 12 | public final IPackageRecipeInfo recipeInfo; 13 | public final int index; 14 | public final List inputs; 15 | public final ItemStack output; 16 | 17 | public PackagePattern(IPackageRecipeInfo recipeInfo, int index) { 18 | this(recipeInfo, index, false); 19 | } 20 | 21 | public PackagePattern(IPackageRecipeInfo recipeInfo, int index, boolean condense) { 22 | this.recipeInfo = recipeInfo; 23 | this.index = index; 24 | List recipeInputs = recipeInfo.getInputs(); 25 | recipeInputs = recipeInputs.subList(9*index, Math.min(9*index+9, recipeInputs.size())); 26 | if(condense) { 27 | inputs = List.copyOf(MiscHelper.INSTANCE.condenseStacks(recipeInputs)); 28 | } 29 | else { 30 | inputs = List.copyOf(recipeInputs); 31 | } 32 | output = PackageItem.makePackage(recipeInfo, index); 33 | } 34 | 35 | @Override 36 | public IPackageRecipeInfo getRecipeInfo() { 37 | return recipeInfo; 38 | } 39 | 40 | @Override 41 | public int getIndex() { 42 | return index; 43 | } 44 | 45 | @Override 46 | public List getInputs() { 47 | return inputs; 48 | } 49 | 50 | @Override 51 | public ItemStack getOutput() { 52 | return output.copy(); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/inventory/CrafterItemHandler.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.inventory; 2 | 3 | import net.minecraft.core.Direction; 4 | import net.minecraft.world.item.ItemStack; 5 | import net.minecraftforge.common.capabilities.ForgeCapabilities; 6 | import net.minecraftforge.items.IItemHandlerModifiable; 7 | import thelm.packagedauto.block.entity.CrafterBlockEntity; 8 | 9 | public class CrafterItemHandler extends BaseItemHandler { 10 | 11 | public CrafterItemHandler(CrafterBlockEntity blockEntity) { 12 | super(blockEntity, 11); 13 | } 14 | 15 | @Override 16 | public boolean isItemValid(int index, ItemStack stack) { 17 | if(index == 10) { 18 | return stack.getCapability(ForgeCapabilities.ENERGY).isPresent(); 19 | } 20 | return false; 21 | } 22 | 23 | @Override 24 | public IItemHandlerModifiable getWrapperForDirection(Direction side) { 25 | return wrapperMap.computeIfAbsent(side, s->new CrafterItemHandlerWrapper(this, s)); 26 | } 27 | 28 | @Override 29 | public int get(int id) { 30 | return switch(id) { 31 | case 0 -> blockEntity.remainingProgress; 32 | case 1 -> blockEntity.isWorking ? 1 : 0; 33 | case 2 -> blockEntity.getEnergyStorage().getEnergyStored(); 34 | default -> 0; 35 | }; 36 | } 37 | 38 | @Override 39 | public void set(int id, int value) { 40 | switch(id) { 41 | case 0 -> blockEntity.remainingProgress = value; 42 | case 1 -> blockEntity.isWorking = value != 0; 43 | case 2 -> blockEntity.getEnergyStorage().setEnergyStored(value); 44 | } 45 | } 46 | 47 | @Override 48 | public int getCount() { 49 | return 3; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/api/IPackageRecipeInfo.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.api; 2 | 3 | import java.util.List; 4 | 5 | import it.unimi.dsi.fastutil.ints.Int2ObjectMap; 6 | import net.minecraft.nbt.CompoundTag; 7 | import net.minecraft.world.item.ItemStack; 8 | import net.minecraft.world.level.Level; 9 | 10 | /** 11 | * Please override {@link IPackageRecipeInfo#equals(IPackageRecipeInfo)} when implementing a new recipe type. 12 | */ 13 | public interface IPackageRecipeInfo { 14 | 15 | void load(CompoundTag nbt); 16 | 17 | void save(CompoundTag nbt); 18 | 19 | IPackageRecipeType getRecipeType(); 20 | 21 | boolean isValid(); 22 | 23 | List getPatterns(); 24 | 25 | default List getExtraPatterns() { 26 | return List.of(); 27 | } 28 | 29 | List getInputs(); 30 | 31 | List getOutputs(); 32 | 33 | void generateFromStacks(List input, List output, Level level); 34 | 35 | Int2ObjectMap getEncoderStacks(); 36 | 37 | default ItemStack getCraftingRemainingItem(ItemStack stack) { 38 | if(getRecipeType().hasCraftingRemainingItem()) { 39 | return stack.getCraftingRemainingItem(); 40 | } 41 | return ItemStack.EMPTY; 42 | } 43 | 44 | default boolean validPatternIndex(int index) { 45 | return index >= 0 && index < getPatterns().size(); 46 | } 47 | 48 | default boolean isPackageable() { 49 | return isValid() && !getInputs().isEmpty(); 50 | } 51 | 52 | default boolean isCraftable() { 53 | return isPackageable() && !getOutputs().isEmpty(); 54 | } 55 | 56 | @Override 57 | boolean equals(Object obj); 58 | 59 | @Override 60 | int hashCode(); 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/network/packet/SetItemStackPacket.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.network.packet; 2 | 3 | import java.util.function.Supplier; 4 | 5 | import net.minecraft.network.FriendlyByteBuf; 6 | import net.minecraft.server.level.ServerPlayer; 7 | import net.minecraft.world.inventory.AbstractContainerMenu; 8 | import net.minecraft.world.inventory.Slot; 9 | import net.minecraft.world.item.ItemStack; 10 | import net.minecraftforge.items.ItemStackHandler; 11 | import net.minecraftforge.network.NetworkEvent; 12 | import thelm.packagedauto.slot.FalseCopySlot; 13 | import thelm.packagedauto.util.MiscHelper; 14 | 15 | public record SetItemStackPacket(int containerSlot, ItemStack stack) { 16 | 17 | public void encode(FriendlyByteBuf buf) { 18 | buf.writeShort(containerSlot); 19 | MiscHelper.INSTANCE.writeItemWithLargeCount(buf, stack); 20 | } 21 | 22 | public static SetItemStackPacket decode(FriendlyByteBuf buf) { 23 | return new SetItemStackPacket(buf.readUnsignedShort(), MiscHelper.INSTANCE.readItemWithLargeCount(buf)); 24 | } 25 | 26 | public void handle(Supplier ctx) { 27 | ServerPlayer player = ctx.get().getSender(); 28 | ctx.get().enqueueWork(()->{ 29 | AbstractContainerMenu container = player.containerMenu; 30 | if(container != null) { 31 | if(containerSlot >= 0 && containerSlot < container.slots.size()) { 32 | Slot slot = container.getSlot(containerSlot); 33 | if(slot instanceof FalseCopySlot fSlot) { 34 | ItemStackHandler handler = (ItemStackHandler)fSlot.getItemHandler(); 35 | handler.setStackInSlot(slot.getSlotIndex(), stack); 36 | } 37 | } 38 | } 39 | }); 40 | ctx.get().setPacketHandled(true); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/network/packet/SetRecipePacket.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.network.packet; 2 | 3 | import java.util.function.Supplier; 4 | 5 | import it.unimi.dsi.fastutil.ints.Int2ObjectMap; 6 | import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; 7 | import net.minecraft.network.FriendlyByteBuf; 8 | import net.minecraft.server.level.ServerPlayer; 9 | import net.minecraft.world.item.ItemStack; 10 | import net.minecraftforge.network.NetworkEvent; 11 | import thelm.packagedauto.menu.EncoderMenu; 12 | import thelm.packagedauto.util.MiscHelper; 13 | 14 | public record SetRecipePacket(Int2ObjectMap map) { 15 | 16 | public SetRecipePacket addItem(int index, ItemStack stack) { 17 | map.put(index, stack); 18 | return this; 19 | } 20 | 21 | public void encode(FriendlyByteBuf buf) { 22 | buf.writeByte(map.size()); 23 | for(Int2ObjectMap.Entry entry : map.int2ObjectEntrySet()) { 24 | buf.writeByte(entry.getIntKey()); 25 | MiscHelper.INSTANCE.writeItemWithLargeCount(buf, entry.getValue()); 26 | } 27 | } 28 | 29 | public static SetRecipePacket decode(FriendlyByteBuf buf) { 30 | int size = buf.readByte(); 31 | Int2ObjectMap map = new Int2ObjectOpenHashMap<>(size); 32 | for(int i = 0; i < size; ++i) { 33 | int index = buf.readUnsignedByte(); 34 | ItemStack stack = MiscHelper.INSTANCE.readItemWithLargeCount(buf); 35 | map.put(index, stack); 36 | } 37 | return new SetRecipePacket(map); 38 | } 39 | 40 | public void handle(Supplier ctx) { 41 | ServerPlayer player = ctx.get().getSender(); 42 | ctx.get().enqueueWork(()->{ 43 | if(player.containerMenu instanceof EncoderMenu menu) { 44 | menu.patternItemHandler.setRecipe(map); 45 | } 46 | }); 47 | ctx.get().setPacketHandled(true); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/network/packet/SizedMarkerPacket.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.network.packet; 2 | 3 | import java.util.function.Supplier; 4 | 5 | import net.minecraft.network.FriendlyByteBuf; 6 | import net.minecraft.server.level.ServerPlayer; 7 | import net.minecraft.world.phys.Vec3; 8 | import net.minecraftforge.network.NetworkEvent; 9 | import net.minecraftforge.network.PacketDistributor; 10 | import thelm.packagedauto.client.WorldOverlayRenderer; 11 | import thelm.packagedauto.network.PacketHandler; 12 | 13 | public record SizedMarkerPacket(Vec3 lowerCorner, Vec3 size, int color, int lifetime) { 14 | 15 | public void encode(FriendlyByteBuf buf) { 16 | buf.writeDouble(lowerCorner.x); 17 | buf.writeDouble(lowerCorner.y); 18 | buf.writeDouble(lowerCorner.z); 19 | buf.writeDouble(size.x); 20 | buf.writeDouble(size.y); 21 | buf.writeDouble(size.z); 22 | buf.writeMedium(color); 23 | buf.writeShort(lifetime); 24 | } 25 | 26 | public static SizedMarkerPacket decode(FriendlyByteBuf buf) { 27 | Vec3 lowerCorner = new Vec3(buf.readDouble(), buf.readDouble(), buf.readDouble()); 28 | Vec3 size = new Vec3(buf.readDouble(), buf.readDouble(), buf.readDouble()); 29 | return new SizedMarkerPacket(lowerCorner, size, buf.readUnsignedMedium(), buf.readUnsignedShort()); 30 | } 31 | 32 | public void handle(Supplier ctx) { 33 | ctx.get().enqueueWork(()->{ 34 | WorldOverlayRenderer.INSTANCE.addSizedMarker(lowerCorner, size, color, lifetime); 35 | }); 36 | ctx.get().setPacketHandled(true); 37 | } 38 | 39 | public static void sendSizedMarker(ServerPlayer player, Vec3 lowerCorner, Vec3 size, int color, int lifetime) { 40 | PacketHandler.INSTANCE.send(PacketDistributor.PLAYER.with(()->player), new SizedMarkerPacket(lowerCorner, size, color, lifetime)); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/network/packet/SyncEnergyPacket.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.network.packet; 2 | 3 | import java.util.function.Supplier; 4 | 5 | import net.minecraft.client.Minecraft; 6 | import net.minecraft.client.multiplayer.ClientLevel; 7 | import net.minecraft.core.BlockPos; 8 | import net.minecraft.network.FriendlyByteBuf; 9 | import net.minecraft.resources.ResourceKey; 10 | import net.minecraft.world.level.Level; 11 | import net.minecraft.world.level.block.entity.BlockEntity; 12 | import net.minecraftforge.network.NetworkEvent; 13 | import net.minecraftforge.network.PacketDistributor; 14 | import net.minecraftforge.network.PacketDistributor.TargetPoint; 15 | import thelm.packagedauto.block.entity.BaseBlockEntity; 16 | import thelm.packagedauto.network.PacketHandler; 17 | 18 | public record SyncEnergyPacket(BlockPos pos, int energy) { 19 | 20 | public void encode(FriendlyByteBuf buf) { 21 | buf.writeBlockPos(pos); 22 | buf.writeInt(energy); 23 | } 24 | 25 | public static SyncEnergyPacket decode(FriendlyByteBuf buf) { 26 | return new SyncEnergyPacket(buf.readBlockPos(), buf.readInt()); 27 | } 28 | 29 | public void handle(Supplier ctx) { 30 | ctx.get().enqueueWork(()->{ 31 | ClientLevel level = Minecraft.getInstance().level; 32 | if(level.isLoaded(pos)) { 33 | BlockEntity be = level.getBlockEntity(pos); 34 | if(be instanceof BaseBlockEntity bbe) { 35 | bbe.getEnergyStorage().setEnergyStored(energy); 36 | } 37 | } 38 | }); 39 | ctx.get().setPacketHandled(true); 40 | } 41 | 42 | public static void syncEnergy(BlockPos pos, int energy, ResourceKey dimension, double range) { 43 | PacketHandler.INSTANCE.send(PacketDistributor.NEAR.with(()->new TargetPoint(pos.getX()+0.5D, pos.getY()+0.5D, pos.getZ()+0.5D, range, dimension)), new SyncEnergyPacket(pos, energy)); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/block/PackagerBlock.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.block; 2 | 3 | import net.minecraft.core.BlockPos; 4 | import net.minecraft.world.item.BlockItem; 5 | import net.minecraft.world.item.Item; 6 | import net.minecraft.world.level.Level; 7 | import net.minecraft.world.level.block.Block; 8 | import net.minecraft.world.level.block.SoundType; 9 | import net.minecraft.world.level.block.entity.BlockEntity; 10 | import net.minecraft.world.level.block.entity.BlockEntityTicker; 11 | import net.minecraft.world.level.block.entity.BlockEntityType; 12 | import net.minecraft.world.level.block.state.BlockBehaviour; 13 | import net.minecraft.world.level.block.state.BlockState; 14 | import net.minecraft.world.level.material.MapColor; 15 | import thelm.packagedauto.block.entity.BaseBlockEntity; 16 | import thelm.packagedauto.block.entity.PackagerBlockEntity; 17 | 18 | public class PackagerBlock extends BaseBlock { 19 | 20 | public static final PackagerBlock INSTANCE = new PackagerBlock(); 21 | public static final Item ITEM_INSTANCE = new BlockItem(INSTANCE, new Item.Properties()); 22 | 23 | protected PackagerBlock() { 24 | super(BlockBehaviour.Properties.of().strength(10F, 15F).mapColor(MapColor.METAL).sound(SoundType.METAL)); 25 | } 26 | 27 | @Override 28 | public PackagerBlockEntity newBlockEntity(BlockPos pos, BlockState state) { 29 | return PackagerBlockEntity.TYPE_INSTANCE.create(pos, state); 30 | } 31 | 32 | @Override 33 | public BlockEntityTicker getTicker(Level level, BlockState state, BlockEntityType blockEntityType) { 34 | return BaseBlockEntity::tick; 35 | } 36 | 37 | @Override 38 | public void neighborChanged(BlockState state, Level level, BlockPos pos, Block block, BlockPos fromPos, boolean isMoving) { 39 | level.getBlockEntity(pos, PackagerBlockEntity.TYPE_INSTANCE).ifPresent(PackagerBlockEntity::updatePowered); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/client/screen/ItemAmountSpecifyingScreen.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.client.screen; 2 | 3 | import net.minecraft.network.chat.Component; 4 | import net.minecraft.util.Mth; 5 | import net.minecraft.world.entity.player.Inventory; 6 | import net.minecraft.world.item.ItemStack; 7 | import thelm.packagedauto.menu.ItemAmountSpecifyingMenu; 8 | import thelm.packagedauto.network.PacketHandler; 9 | import thelm.packagedauto.network.packet.SetItemStackPacket; 10 | 11 | public class ItemAmountSpecifyingScreen extends AmountSpecifyingScreen { 12 | 13 | private int containerSlot; 14 | private ItemStack stack; 15 | private int maxAmount; 16 | 17 | public ItemAmountSpecifyingScreen(BaseScreen parent, Inventory inventory, int containerSlot, ItemStack stack, int maxAmount) { 18 | super(parent, new ItemAmountSpecifyingMenu(inventory, stack), inventory, Component.translatable("gui.packagedauto.item_amount_specifying")); 19 | this.containerSlot = containerSlot; 20 | this.stack = stack; 21 | this.maxAmount = maxAmount; 22 | } 23 | 24 | @Override 25 | protected int getDefaultAmount() { 26 | return stack.getCount(); 27 | } 28 | 29 | @Override 30 | protected int getMaxAmount() { 31 | return maxAmount; 32 | } 33 | 34 | @Override 35 | protected int[] getIncrements() { 36 | return new int[] {1, 10, 64}; 37 | } 38 | 39 | @Override 40 | protected int[] getMultipliers() { 41 | return new int[] {2, 3, 5}; 42 | } 43 | 44 | @Override 45 | protected void onOkButtonPressed(boolean shiftDown) { 46 | try { 47 | int amount = Mth.clamp(Integer.parseInt(amountField.getValue()), 0, maxAmount); 48 | ItemStack newStack = stack.copy(); 49 | newStack.setCount(amount); 50 | PacketHandler.INSTANCE.sendToServer(new SetItemStackPacket(containerSlot, newStack)); 51 | close(); 52 | } 53 | catch(NumberFormatException e) { 54 | // NO OP 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/patchouli_books/guide/en_us/entries/core/packaging_provider.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ME Packaging Provider", 3 | "category": "packagedauto:core", 4 | "icon": "packagedauto:packaging_provider", 5 | "pages": [ 6 | { 7 | "type": "patchouli:text", 8 | "text": "The $(item)ME Packaging Provider/$ combines the function of the $(l:core/packager)Packager/$ and the $(l:core/unpackager)Unpackager/$.$(p)This machine must be connected to an $(thing)ME Network/$, requiring a channel." 9 | }, 10 | { 11 | "type": "patchouli:spotlight", 12 | "item": "packagedauto:packaging_provider", 13 | "link_recipe": true, 14 | "title": "Usage", 15 | "text": "To use the $(item)ME Packaging Provider/$, put an encoded $(l:core/recipe_holder)Package Recipe Holder/$ inside. The machine will then provide Direct, Packaging, and/or Unpackaging recipes depending on the settings." 16 | }, 17 | { 18 | "type": "patchouli:text", 19 | "title": "Settings", 20 | "text": "$(thing)Direct/$: Provide package recipes as a large processing recipe, skipping the packaging and unpackaging steps.$(p)$(thing)Packaging/$: Provide packaging recipes like a $(l:core/packager)Packager/$.$(p)$(thing)Unpackaging/$: Provide unpackaging recipes like an $(l:core/unpackager)Unpackager/$." 21 | }, 22 | { 23 | "type": "patchouli:text", 24 | "title": "Settings Cloning", 25 | "text": "Using the $(l:core/settings_cloner)Packaging Settings Cloner/$, you can copy and paste the providing settings and the current available recipes.$(p)To paste recipes, the target $(item)ME Packaging Provider/$ should not have recipes, and you must have a an $(l:core/recipe_holder)Package Recipe Holder/$ in your inventory." 26 | }, 27 | { 28 | "type": "patchouli:crafting", 29 | "recipe": "packagedauto:packaging_provider", 30 | "title": "Crafting" 31 | } 32 | ], 33 | "flag": "mod:ae2", 34 | "read_by_default": true, 35 | "sortnum": 10 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/block/PackagerExtensionBlock.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.block; 2 | 3 | import net.minecraft.core.BlockPos; 4 | import net.minecraft.world.item.BlockItem; 5 | import net.minecraft.world.item.Item; 6 | import net.minecraft.world.level.Level; 7 | import net.minecraft.world.level.block.Block; 8 | import net.minecraft.world.level.block.SoundType; 9 | import net.minecraft.world.level.block.entity.BlockEntity; 10 | import net.minecraft.world.level.block.entity.BlockEntityTicker; 11 | import net.minecraft.world.level.block.entity.BlockEntityType; 12 | import net.minecraft.world.level.block.state.BlockBehaviour; 13 | import net.minecraft.world.level.block.state.BlockState; 14 | import net.minecraft.world.level.material.MapColor; 15 | import thelm.packagedauto.block.entity.BaseBlockEntity; 16 | import thelm.packagedauto.block.entity.PackagerExtensionBlockEntity; 17 | 18 | public class PackagerExtensionBlock extends BaseBlock { 19 | 20 | public static final PackagerExtensionBlock INSTANCE = new PackagerExtensionBlock(); 21 | public static final Item ITEM_INSTANCE = new BlockItem(INSTANCE, new Item.Properties()); 22 | 23 | protected PackagerExtensionBlock() { 24 | super(BlockBehaviour.Properties.of().strength(10F, 15F).mapColor(MapColor.METAL).sound(SoundType.METAL)); 25 | } 26 | 27 | @Override 28 | public PackagerExtensionBlockEntity newBlockEntity(BlockPos pos, BlockState state) { 29 | return PackagerExtensionBlockEntity.TYPE_INSTANCE.create(pos, state); 30 | } 31 | 32 | @Override 33 | public BlockEntityTicker getTicker(Level level, BlockState state, BlockEntityType blockEntityType) { 34 | return BaseBlockEntity::tick; 35 | } 36 | 37 | @Override 38 | public void neighborChanged(BlockState state, Level level, BlockPos pos, Block block, BlockPos fromPos, boolean isMoving) { 39 | level.getBlockEntity(pos, PackagerExtensionBlockEntity.TYPE_INSTANCE).ifPresent(PackagerExtensionBlockEntity::updatePowered); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/client/screen/CrafterScreen.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.client.screen; 2 | 3 | import net.minecraft.client.gui.GuiGraphics; 4 | import net.minecraft.network.chat.Component; 5 | import net.minecraft.resources.ResourceLocation; 6 | import net.minecraft.world.entity.player.Inventory; 7 | import thelm.packagedauto.menu.CrafterMenu; 8 | 9 | public class CrafterScreen extends BaseScreen { 10 | 11 | public static final ResourceLocation BACKGROUND = new ResourceLocation("packagedauto:textures/gui/crafter.png"); 12 | 13 | public CrafterScreen(CrafterMenu menu, Inventory inventory, Component title) { 14 | super(menu, inventory, title); 15 | } 16 | 17 | @Override 18 | protected ResourceLocation getBackgroundTexture() { 19 | return BACKGROUND; 20 | } 21 | 22 | @Override 23 | protected void renderBgAdditional(GuiGraphics graphics, float partialTicks, int mouseX, int mouseY) { 24 | graphics.blit(BACKGROUND, leftPos+102, topPos+35, 176, 0, menu.blockEntity.getScaledProgress(22), 16); 25 | int scaledEnergy = menu.blockEntity.getScaledEnergy(40); 26 | graphics.blit(BACKGROUND, leftPos+10, topPos+10+40-scaledEnergy, 176, 16+40-scaledEnergy, 12, scaledEnergy); 27 | } 28 | 29 | @Override 30 | protected void renderLabels(GuiGraphics graphics, int mouseX, int mouseY) { 31 | String s = menu.blockEntity.getDisplayName().getString(); 32 | graphics.drawString(font, s, imageWidth/2 - font.width(s)/2, 6, 0x404040, false); 33 | graphics.drawString(font, menu.inventory.getDisplayName().getString(), menu.getPlayerInvX(), menu.getPlayerInvY()-11, 0x404040, false); 34 | if(mouseX-leftPos >= 10 && mouseY-topPos >= 10 && mouseX-leftPos <= 21 && mouseY-topPos <= 49) { 35 | graphics.renderTooltip(font, Component.literal(menu.blockEntity.getEnergyStorage().getEnergyStored()+" / "+menu.blockEntity.getEnergyStorage().getMaxEnergyStored()+" FE"), mouseX-leftPos, mouseY-topPos); 36 | } 37 | super.renderLabels(graphics, mouseX, mouseY); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/inventory/FluidPackageFillerItemHandler.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.inventory; 2 | 3 | import net.minecraft.core.Direction; 4 | import net.minecraft.world.item.ItemStack; 5 | import net.minecraftforge.common.capabilities.ForgeCapabilities; 6 | import net.minecraftforge.fluids.FluidUtil; 7 | import net.minecraftforge.items.IItemHandlerModifiable; 8 | import thelm.packagedauto.block.entity.FluidPackageFillerBlockEntity; 9 | 10 | public class FluidPackageFillerItemHandler extends BaseItemHandler { 11 | 12 | public FluidPackageFillerItemHandler(FluidPackageFillerBlockEntity blockEntity) { 13 | super(blockEntity, 3); 14 | } 15 | 16 | @Override 17 | public boolean isItemValid(int index, ItemStack stack) { 18 | return switch(index) { 19 | case 1 -> false; 20 | case 2 -> stack.getCapability(ForgeCapabilities.ENERGY).isPresent(); 21 | default -> FluidUtil.getFluidHandler(stack).isPresent(); 22 | }; 23 | } 24 | 25 | @Override 26 | public IItemHandlerModifiable getWrapperForDirection(Direction side) { 27 | return wrapperMap.computeIfAbsent(side, s->new FluidPackageFillerItemHandlerWrapper(this, s)); 28 | } 29 | 30 | @Override 31 | public int get(int id) { 32 | return switch(id) { 33 | case 0 -> blockEntity.requiredAmount; 34 | case 1 -> blockEntity.amount; 35 | case 2 -> blockEntity.remainingProgress; 36 | case 3 -> blockEntity.isWorking ? 1 : 0; 37 | case 4 -> blockEntity.getEnergyStorage().getEnergyStored(); 38 | default -> 0; 39 | }; 40 | } 41 | 42 | @Override 43 | public void set(int id, int value) { 44 | switch(id) { 45 | case 0 -> blockEntity.requiredAmount = value; 46 | case 1 -> blockEntity.amount = value; 47 | case 2 -> blockEntity.remainingProgress = value; 48 | case 3 -> blockEntity.isWorking = value != 0; 49 | case 4 -> blockEntity.getEnergyStorage().setEnergyStored(value); 50 | } 51 | } 52 | 53 | @Override 54 | public int getCount() { 55 | return 5; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/block/FluidPackageFillerBlock.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.block; 2 | 3 | import net.minecraft.core.BlockPos; 4 | import net.minecraft.world.item.BlockItem; 5 | import net.minecraft.world.item.Item; 6 | import net.minecraft.world.level.Level; 7 | import net.minecraft.world.level.block.Block; 8 | import net.minecraft.world.level.block.SoundType; 9 | import net.minecraft.world.level.block.entity.BlockEntity; 10 | import net.minecraft.world.level.block.entity.BlockEntityTicker; 11 | import net.minecraft.world.level.block.entity.BlockEntityType; 12 | import net.minecraft.world.level.block.state.BlockBehaviour; 13 | import net.minecraft.world.level.block.state.BlockState; 14 | import net.minecraft.world.level.material.MapColor; 15 | import thelm.packagedauto.block.entity.BaseBlockEntity; 16 | import thelm.packagedauto.block.entity.FluidPackageFillerBlockEntity; 17 | 18 | public class FluidPackageFillerBlock extends BaseBlock { 19 | 20 | public static final FluidPackageFillerBlock INSTANCE = new FluidPackageFillerBlock(); 21 | public static final Item ITEM_INSTANCE = new BlockItem(INSTANCE, new Item.Properties()); 22 | 23 | protected FluidPackageFillerBlock() { 24 | super(BlockBehaviour.Properties.of().strength(10F, 15F).mapColor(MapColor.METAL).sound(SoundType.METAL)); 25 | } 26 | 27 | @Override 28 | public FluidPackageFillerBlockEntity newBlockEntity(BlockPos pos, BlockState state) { 29 | return FluidPackageFillerBlockEntity.TYPE_INSTANCE.create(pos, state); 30 | } 31 | 32 | @Override 33 | public BlockEntityTicker getTicker(Level level, BlockState state, BlockEntityType blockEntityType) { 34 | return BaseBlockEntity::tick; 35 | } 36 | 37 | @Override 38 | public void neighborChanged(BlockState state, Level level, BlockPos pos, Block block, BlockPos fromPos, boolean isMoving) { 39 | level.getBlockEntity(pos, FluidPackageFillerBlockEntity.TYPE_INSTANCE).ifPresent(FluidPackageFillerBlockEntity::updatePowered); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/integration/appeng/recipe/RecipeCraftingPatternDetails.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.integration.appeng.recipe; 2 | 3 | import java.util.List; 4 | 5 | import appeng.api.crafting.IPatternDetails; 6 | import appeng.api.stacks.AEItemKey; 7 | import appeng.api.stacks.GenericStack; 8 | import net.minecraft.world.item.ItemStack; 9 | import thelm.packagedauto.api.IPackagePattern; 10 | import thelm.packagedauto.api.IPackageRecipeInfo; 11 | import thelm.packagedauto.integration.appeng.AppEngUtil; 12 | 13 | public class RecipeCraftingPatternDetails implements IPatternDetails { 14 | 15 | public final IPackageRecipeInfo recipe; 16 | public final AEItemKey definition; 17 | public final IInput[] inputs; 18 | public final GenericStack[] outputs; 19 | 20 | public RecipeCraftingPatternDetails(IPackageRecipeInfo recipe) { 21 | this.recipe = recipe; 22 | ItemStack definitionStack = recipe.getPatterns().get(0).getOutput(); 23 | definitionStack.getTag().putString("PatternType", "recipe"); 24 | definition = AEItemKey.of(definitionStack); 25 | List sparseInputs = recipe.getPatterns().stream().map(IPackagePattern::getOutput).map(GenericStack::fromItemStack).toList(); 26 | List sparseOutputs = recipe.getOutputs().stream().map(AppEngUtil::getGenericOutput).toList(); 27 | inputs = AppEngUtil.toInputs(sparseInputs); 28 | outputs = AppEngUtil.condenseStacks(sparseOutputs); 29 | } 30 | 31 | @Override 32 | public AEItemKey getDefinition() { 33 | return definition; 34 | } 35 | 36 | @Override 37 | public IInput[] getInputs() { 38 | return inputs; 39 | } 40 | 41 | @Override 42 | public GenericStack[] getOutputs() { 43 | return outputs; 44 | } 45 | 46 | @Override 47 | public boolean equals(Object obj) { 48 | if(obj instanceof RecipeCraftingPatternDetails other) { 49 | return recipe.equals(other.recipe); 50 | } 51 | return false; 52 | } 53 | 54 | @Override 55 | public int hashCode() { 56 | return recipe.hashCode(); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/patchouli_books/guide/en_us/entries/recipe/crafting_proxy.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Crafting Proxy", 3 | "category": "packagedauto:recipe", 4 | "icon": "packagedauto:crafting_proxy", 5 | "pages": [ 6 | { 7 | "type": "patchouli:text", 8 | "text": "The $(item)Package Crafting Machine Proxy/$ allows $(l:core/unpackager)Unpackagers/$ to send items to specialized package crafting machines at a distance." 9 | }, 10 | { 11 | "type": "packagedauto:spotlight2", 12 | "item1": "packagedauto:proxy_marker", 13 | "item2": "packagedauto:crafting_proxy", 14 | "title": "Usage", 15 | "text": "To use, bind a $(item)Proxy Marker/$ to a package crafting machine, and put the marker into the proxy." 16 | }, 17 | { 18 | "type": "patchouli:text", 19 | "title": "Usage (cont.)", 20 | "text": "You can $(thing)$(k:sneak) + $(k:use)/$ a bound $(item)Proxy Marker/$ or place in a crafting grid to unbind.$(p)You can $(thing)$(k:sneak) + $(k:use)/$ with an empty hand on a $(item)Package Crafting Machine Proxy/$ to show its current range and target.$(p)You can combine a bound $(item)Proxy Marker/$ with unbound ones in a crafting grid to copy contents." 21 | }, 22 | { 23 | "type": "patchouli:text", 24 | "title": "Settings Cloning", 25 | "text": "Using the $(l:core/settings_cloner)Packaging Settings Cloner/$, you can copy and paste current target setting of a $(item)Package Crafting Machine Proxy/$.$(p)To paste target settings, you must have an empty $(item)Proxy Marker/$ in your inventory." 26 | }, 27 | { 28 | "type": "patchouli:text", 29 | "flag": "mod:ae2", 30 | "title": "AE2 Integration", 31 | "text": "The $(item)Package Crafting Machine Proxy/$ can be connected to an $(thing)ME Network/$." 32 | }, 33 | { 34 | "type": "patchouli:crafting", 35 | "recipe": "packagedauto:proxy_marker", 36 | "recipe2": "packagedauto:crafting_proxy", 37 | "title": "Crafting" 38 | } 39 | ], 40 | "read_by_default": true, 41 | "sortnum": 100 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/integration/appeng/recipe/PackageCraftingPatternDetails.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.integration.appeng.recipe; 2 | 3 | import java.util.List; 4 | import java.util.Objects; 5 | 6 | import appeng.api.crafting.IPatternDetails; 7 | import appeng.api.stacks.AEItemKey; 8 | import appeng.api.stacks.GenericStack; 9 | import net.minecraft.world.item.ItemStack; 10 | import thelm.packagedauto.api.IPackagePattern; 11 | import thelm.packagedauto.integration.appeng.AppEngUtil; 12 | 13 | public class PackageCraftingPatternDetails implements IPatternDetails { 14 | 15 | public final IPackagePattern pattern; 16 | public final AEItemKey definition; 17 | public final IInput[] inputs; 18 | public final GenericStack[] outputs; 19 | 20 | public PackageCraftingPatternDetails(IPackagePattern pattern) { 21 | this.pattern = pattern; 22 | ItemStack definitionStack = pattern.getOutput(); 23 | definitionStack.getTag().putString("PatternType", "package"); 24 | definition = AEItemKey.of(definitionStack); 25 | List sparseInputs = pattern.getInputs().stream().map(GenericStack::fromItemStack).toList(); 26 | inputs = AppEngUtil.toInputs(pattern.getRecipeInfo(), AppEngUtil.condenseStacks(sparseInputs)); 27 | outputs = new GenericStack[] {GenericStack.fromItemStack(pattern.getOutput())}; 28 | } 29 | 30 | @Override 31 | public AEItemKey getDefinition() { 32 | return definition; 33 | } 34 | 35 | @Override 36 | public IInput[] getInputs() { 37 | return inputs; 38 | } 39 | 40 | @Override 41 | public GenericStack[] getOutputs() { 42 | return outputs; 43 | } 44 | 45 | @Override 46 | public boolean equals(Object obj) { 47 | if(obj instanceof PackageCraftingPatternDetails other) { 48 | return pattern.getIndex() == other.pattern.getIndex() && pattern.getRecipeInfo().equals(other.pattern.getRecipeInfo()); 49 | } 50 | return false; 51 | } 52 | 53 | @Override 54 | public int hashCode() { 55 | return Objects.hash(pattern.getIndex(), pattern.getRecipeInfo()); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/client/screen/VolumeAmountSpecifyingScreen.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.client.screen; 2 | 3 | import net.minecraft.network.chat.Component; 4 | import net.minecraft.util.Mth; 5 | import net.minecraft.world.entity.player.Inventory; 6 | import thelm.packagedauto.api.IVolumeStackWrapper; 7 | import thelm.packagedauto.menu.VolumeAmountSpecifyingMenu; 8 | import thelm.packagedauto.network.PacketHandler; 9 | import thelm.packagedauto.network.packet.SetItemStackPacket; 10 | import thelm.packagedauto.util.MiscHelper; 11 | 12 | public class VolumeAmountSpecifyingScreen extends AmountSpecifyingScreen { 13 | 14 | private int containerSlot; 15 | private IVolumeStackWrapper stack; 16 | private int maxAmount; 17 | 18 | public VolumeAmountSpecifyingScreen(BaseScreen parent, Inventory inventory, int containerSlot, IVolumeStackWrapper stack, int maxAmount) { 19 | super(parent, new VolumeAmountSpecifyingMenu(inventory, stack), inventory, Component.translatable("gui.packagedauto.volume_amount_specifying")); 20 | this.containerSlot = containerSlot; 21 | this.stack = stack; 22 | this.maxAmount = maxAmount; 23 | } 24 | 25 | @Override 26 | protected int getDefaultAmount() { 27 | return stack.getAmount(); 28 | } 29 | 30 | @Override 31 | protected int getMaxAmount() { 32 | return maxAmount; 33 | } 34 | 35 | @Override 36 | protected int[] getIncrements() { 37 | return stack.getVolumeType().getIncrements(); 38 | } 39 | 40 | @Override 41 | protected int[] getMultipliers() { 42 | return stack.getVolumeType().getMultipliers(); 43 | } 44 | 45 | @Override 46 | protected void onOkButtonPressed(boolean shiftDown) { 47 | try { 48 | int amount = Mth.clamp(Integer.parseInt(amountField.getValue()), 0, maxAmount); 49 | IVolumeStackWrapper newStack = stack.copy(); 50 | newStack.setAmount(amount); 51 | PacketHandler.INSTANCE.sendToServer(new SetItemStackPacket(containerSlot, MiscHelper.INSTANCE.makeVolumePackage(newStack))); 52 | close(); 53 | } 54 | catch(NumberFormatException e) { 55 | // NO OP 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/integration/appeng/recipe/SimpleInput.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.integration.appeng.recipe; 2 | 3 | import appeng.api.crafting.IPatternDetails.IInput; 4 | import appeng.api.stacks.AEItemKey; 5 | import appeng.api.stacks.AEKey; 6 | import appeng.api.stacks.GenericStack; 7 | import net.minecraft.nbt.CompoundTag; 8 | import net.minecraft.world.level.Level; 9 | import thelm.packagedauto.api.IPackageRecipeInfo; 10 | import thelm.packagedauto.api.IVolumePackageItem; 11 | import thelm.packagedauto.api.IVolumeStackWrapper; 12 | 13 | public class SimpleInput implements IInput { 14 | 15 | private final IPackageRecipeInfo recipe; 16 | private final GenericStack[] template; 17 | private final long multiplier; 18 | 19 | public SimpleInput(IPackageRecipeInfo recipe, GenericStack stack) { 20 | this.recipe = recipe; 21 | template = new GenericStack[] {getGenericInput(stack)}; 22 | multiplier = stack.amount(); 23 | } 24 | 25 | @Override 26 | public GenericStack[] getPossibleInputs() { 27 | return template; 28 | } 29 | 30 | @Override 31 | public long getMultiplier() { 32 | return multiplier; 33 | } 34 | 35 | @Override 36 | public boolean isValid(AEKey input, Level level) { 37 | return input.matches(template[0]); 38 | } 39 | 40 | @Override 41 | public AEKey getRemainingKey(AEKey template) { 42 | if(recipe != null && recipe.getRecipeType().hasCraftingRemainingItem() && template instanceof AEItemKey itemTemplate) { 43 | return AEItemKey.of(recipe.getCraftingRemainingItem(itemTemplate.toStack())); 44 | } 45 | return null; 46 | } 47 | 48 | private GenericStack getGenericInput(GenericStack stack) { 49 | if(stack.what() instanceof AEItemKey itemKey && itemKey.getItem() instanceof IVolumePackageItem vPackage) { 50 | IVolumeStackWrapper vStack = vPackage.getVolumeStack(itemKey.toStack()); 51 | if(!vStack.isEmpty() && vStack.getVolumeType().supportsAE()) { 52 | AEKey key = AEKey.fromTagGeneric(vStack.saveAEKey(new CompoundTag())); 53 | if(key != null) { 54 | return new GenericStack(key, vStack.getAmount()); 55 | } 56 | } 57 | } 58 | return new GenericStack(stack.what(), 1); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/patchouli_books/guide/en_us/entries/core/encoder.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Package Recipe Encoder", 3 | "category": "packagedauto:core", 4 | "icon": "packagedauto:encoder", 5 | "pages": [ 6 | { 7 | "type": "patchouli:text", 8 | "text": "The $(item)Package Recipe Encoder/$ encodes recipes into $(l:core/recipe_holder)Package Recipe Holders/$, which then provides recipe data for machines." 9 | }, 10 | { 11 | "type": "patchouli:spotlight", 12 | "item": "packagedauto:encoder", 13 | "link_recipe": true, 14 | "title": "Usage", 15 | "text": "To encode recipes, select a $(l:recipe)recipe type/$.$(p)Depending on the recipe type, you can then set the inputs and outputs and their counts.$(p)Finally, put $(l:core/recipe_holder)Package Recipe Holders/$ inside, and press the $(thing)save button/$ to encode recipes." 16 | }, 17 | { 18 | "type": "patchouli:text", 19 | "title": "Usage (cont.)", 20 | "text": "You can load recipes from encoded $(l:core/recipe_holder)Package Recipe Holders/$ by pressing the $(thing)load button/$.$(p)Up to 20 recipes can be encoded in $(l:core/recipe_holder)Package Recipe Holders/$ by selecting recipe slots at the top of the GUI.$(p)What $(l:core/package)Recipe Packages/$ are made can be previewed on the right." 21 | }, 22 | { 23 | "type": "patchouli:text", 24 | "flag": "&mod:jei,!mod:emi", 25 | "title": "JEI Integration", 26 | "text": "You can show all recipes applicable to the current recipe type by pressing the arrow, and you can press the $(thing)Move Items/$ button to quickly encode recipes." 27 | }, 28 | { 29 | "type": "patchouli:text", 30 | "flag": "mod:emi", 31 | "title": "EMI Integration", 32 | "text": "When viewing recipes applicable to the current recipe type, you can press the $(thing)Fill Recipe/$ button to quickly encode recipes.$(p)For recipes that accepts ingredients with multiple items, you can specify which item to use by using the recipe tree." 33 | }, 34 | { 35 | "type": "patchouli:crafting", 36 | "recipe": "packagedauto:encoder", 37 | "title": "Crafting" 38 | } 39 | ], 40 | "read_by_default": true, 41 | "sortnum": 6 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/inventory/BaseVolumeInventory.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.inventory; 2 | 3 | import java.util.Arrays; 4 | 5 | import net.minecraft.nbt.CompoundTag; 6 | import net.minecraft.nbt.ListTag; 7 | import thelm.packagedauto.api.IVolumeStackWrapper; 8 | import thelm.packagedauto.api.IVolumeType; 9 | 10 | public class BaseVolumeInventory { 11 | 12 | public final IVolumeType type; 13 | public final IVolumeStackWrapper[] stacks; 14 | 15 | public BaseVolumeInventory(IVolumeType type, int size) { 16 | this.type = type; 17 | stacks = new IVolumeStackWrapper[size]; 18 | Arrays.fill(stacks, type.getEmptyStackInstance()); 19 | } 20 | 21 | public int getSlots() { 22 | return stacks.length; 23 | } 24 | 25 | public boolean isEmpty() { 26 | for(IVolumeStackWrapper stack : stacks) { 27 | if(!stack.isEmpty()) { 28 | return false; 29 | } 30 | } 31 | return true; 32 | } 33 | 34 | public IVolumeStackWrapper getStackInSlot(int index) { 35 | return index >= 0 && index < stacks.length ? stacks[index] : type.getEmptyStackInstance(); 36 | } 37 | 38 | public void setStackInSlot(int index, IVolumeStackWrapper stack) { 39 | if(index >= 0 && index < stacks.length) { 40 | if(stack.isEmpty()) { 41 | stack = type.getEmptyStackInstance(); 42 | } 43 | stacks[index] = stack; 44 | } 45 | } 46 | 47 | public void load(CompoundTag nbt) { 48 | Arrays.fill(stacks, type.getEmptyStackInstance()); 49 | ListTag tagList = nbt.getList("Volumes", 10); 50 | for(int i = 0; i < tagList.size(); ++i) { 51 | CompoundTag tag = tagList.getCompound(i); 52 | int j = tag.getByte("Slot") & 255; 53 | if(j >= 0 && j < stacks.length) { 54 | stacks[j] = type.loadStack(tag); 55 | } 56 | } 57 | } 58 | 59 | public CompoundTag write(CompoundTag nbt) { 60 | ListTag tagList = new ListTag(); 61 | for(int i = 0; i < stacks.length; ++i) { 62 | IVolumeStackWrapper stack = stacks[i]; 63 | if(!stack.isEmpty()) { 64 | CompoundTag tag = new CompoundTag(); 65 | tag.putByte("Slot", (byte)i); 66 | stack.save(tag); 67 | tagList.add(tag); 68 | } 69 | } 70 | nbt.put("Volumes", tagList); 71 | return nbt; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/inventory/BaseItemHandler.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.inventory; 2 | 3 | import java.util.Collections; 4 | import java.util.IdentityHashMap; 5 | import java.util.List; 6 | import java.util.Map; 7 | 8 | import net.minecraft.core.Direction; 9 | import net.minecraft.nbt.CompoundTag; 10 | import net.minecraft.nbt.ListTag; 11 | import net.minecraft.world.inventory.ContainerData; 12 | import net.minecraft.world.item.ItemStack; 13 | import net.minecraftforge.items.IItemHandlerModifiable; 14 | import net.minecraftforge.items.ItemStackHandler; 15 | import thelm.packagedauto.block.entity.BaseBlockEntity; 16 | import thelm.packagedauto.util.MiscHelper; 17 | 18 | public class BaseItemHandler extends ItemStackHandler implements ContainerData { 19 | 20 | public final T blockEntity; 21 | protected Map wrapperMap = new IdentityHashMap<>(7); 22 | 23 | public BaseItemHandler(T blockEntity, int size) { 24 | super(size); 25 | this.blockEntity = blockEntity; 26 | } 27 | 28 | public List getStacks() { 29 | return Collections.unmodifiableList(stacks); 30 | } 31 | 32 | @Override 33 | protected void onContentsChanged(int slot) { 34 | if(blockEntity != null) { 35 | blockEntity.setChanged(); 36 | } 37 | } 38 | 39 | public void load(CompoundTag nbt) { 40 | stacks.clear(); 41 | MiscHelper.INSTANCE.loadAllItems(nbt.getList("Items", 10), stacks, "Slot"); 42 | } 43 | 44 | public void save(CompoundTag nbt) { 45 | nbt.put("Items", MiscHelper.INSTANCE.saveAllItems(new ListTag(), stacks, "Slot")); 46 | } 47 | 48 | public void setChanged() { 49 | if(blockEntity != null) { 50 | blockEntity.setChanged(); 51 | } 52 | } 53 | 54 | public void sync(boolean rerender) { 55 | if(blockEntity != null) { 56 | blockEntity.sync(rerender); 57 | } 58 | } 59 | 60 | public IItemHandlerModifiable getWrapperForDirection(Direction side) { 61 | return this; 62 | } 63 | 64 | @Override 65 | public int get(int index) { 66 | return 0; 67 | } 68 | 69 | @Override 70 | public void set(int index, int value) {} 71 | 72 | @Override 73 | public int getCount() { 74 | return 0; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/integration/jei/FluidVolumeGuiHandler.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.integration.jei; 2 | 3 | import java.util.Optional; 4 | 5 | import mezz.jei.api.gui.handlers.IGuiContainerHandler; 6 | import mezz.jei.api.ingredients.ITypedIngredient; 7 | import mezz.jei.api.runtime.IClickableIngredient; 8 | import mezz.jei.api.runtime.IIngredientManager; 9 | import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; 10 | import net.minecraft.client.renderer.Rect2i; 11 | import net.minecraft.world.inventory.Slot; 12 | import thelm.packagedauto.api.IFluidStackWrapper; 13 | import thelm.packagedauto.api.IVolumeStackWrapper; 14 | import thelm.packagedauto.slot.FalseCopyVolumeSlot; 15 | 16 | public class FluidVolumeGuiHandler implements IGuiContainerHandler> { 17 | 18 | private final IIngredientManager ingredientManager; 19 | 20 | public FluidVolumeGuiHandler(IIngredientManager ingredientManager) { 21 | this.ingredientManager = ingredientManager; 22 | } 23 | 24 | @Override 25 | public Optional> getClickableIngredientUnderMouse(AbstractContainerScreen containerScreen, double mouseX, double mouseY) { 26 | if(containerScreen.getSlotUnderMouse() instanceof FalseCopyVolumeSlot volumeSlot) { 27 | IVolumeStackWrapper volumeStack = volumeSlot.volumeInventory.getStackInSlot(volumeSlot.slotIndex); 28 | if(volumeStack instanceof IFluidStackWrapper fluidVolumeStack) { 29 | return ingredientManager.createTypedIngredient(fluidVolumeStack.getFluid()). 30 | map(ing->new ClickableIngredient<>(ing, getSlotArea(containerScreen, volumeSlot))); 31 | } 32 | } 33 | return Optional.empty(); 34 | } 35 | 36 | private static Rect2i getSlotArea(AbstractContainerScreen gui, Slot slot) { 37 | return new Rect2i(gui.getGuiLeft()+slot.x, gui.getGuiTop()+slot.y, 16, 16); 38 | } 39 | 40 | private static record ClickableIngredient(ITypedIngredient ingredient, Rect2i area) implements IClickableIngredient { 41 | 42 | @Override 43 | public ITypedIngredient getTypedIngredient() { 44 | return ingredient; 45 | } 46 | 47 | @Override 48 | public Rect2i getArea() { 49 | return area; 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/api/IVolumeType.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.api; 2 | 3 | import java.util.Optional; 4 | 5 | import net.minecraft.client.gui.GuiGraphics; 6 | import net.minecraft.core.Direction; 7 | import net.minecraft.nbt.CompoundTag; 8 | import net.minecraft.network.chat.MutableComponent; 9 | import net.minecraft.resources.ResourceLocation; 10 | import net.minecraft.world.item.ItemStack; 11 | import net.minecraftforge.common.capabilities.Capability; 12 | import net.minecraftforge.common.capabilities.ICapabilityProvider; 13 | 14 | public interface IVolumeType { 15 | 16 | ResourceLocation getName(); 17 | 18 | Class getTypeClass(); 19 | 20 | default Class getTypeBaseClass() { 21 | return getTypeClass(); 22 | } 23 | 24 | MutableComponent getDisplayName(); 25 | 26 | default boolean supportsAE() { 27 | return false; 28 | } 29 | 30 | default Optional makeStackFromBase(Object volumeBase, int amount, CompoundTag nbt) { 31 | return Optional.empty(); 32 | } 33 | 34 | IVolumeStackWrapper getEmptyStackInstance(); 35 | 36 | Optional wrapStack(Object volumeStack); 37 | 38 | Optional getStackContained(ItemStack container); 39 | 40 | void setStack(ItemStack stack, IVolumeStackWrapper volumeStack); 41 | 42 | IVolumeStackWrapper loadStack(CompoundTag tag); 43 | 44 | Object makeItemCapability(ItemStack volumePackage); 45 | 46 | @SuppressWarnings("rawtypes") 47 | Capability getItemCapability(); 48 | 49 | boolean hasBlockCapability(ICapabilityProvider capProvider, Direction direction); 50 | 51 | default boolean isEmpty(ICapabilityProvider capProvider, Direction direction) { 52 | return false; 53 | } 54 | 55 | int fill(ICapabilityProvider capProvider, Direction direction, IVolumeStackWrapper resource, boolean simulate); 56 | 57 | IVolumeStackWrapper drain(ICapabilityProvider capProvider, Direction direction, IVolumeStackWrapper resource, boolean simulate); 58 | 59 | void render(GuiGraphics graphics, int i, int j, IVolumeStackWrapper stack); 60 | 61 | default int[] getIncrements() { 62 | return new int[] {100, 500, 1000}; 63 | } 64 | 65 | default int[] getMultipliers() { 66 | return new int[] {2, 3, 5}; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/integration/appeng/recipe/PackagePatternDetailsDecoder.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.integration.appeng.recipe; 2 | 3 | import appeng.api.crafting.IPatternDetails; 4 | import appeng.api.crafting.IPatternDetailsDecoder; 5 | import appeng.api.stacks.AEItemKey; 6 | import net.minecraft.world.item.ItemStack; 7 | import net.minecraft.world.level.Level; 8 | import thelm.packagedauto.api.IPackageItem; 9 | import thelm.packagedauto.api.IPackageRecipeInfo; 10 | import thelm.packagedauto.api.PatternType; 11 | 12 | public class PackagePatternDetailsDecoder implements IPatternDetailsDecoder { 13 | 14 | public static final PackagePatternDetailsDecoder INSTANCE = new PackagePatternDetailsDecoder(); 15 | 16 | protected PackagePatternDetailsDecoder() {} 17 | 18 | @Override 19 | public boolean isEncodedPattern(ItemStack stack) { 20 | return stack.getItem() instanceof IPackageItem; 21 | } 22 | 23 | @Override 24 | public IPatternDetails decodePattern(AEItemKey what, Level level) { 25 | return decodePattern(what.toStack(), level, false); 26 | } 27 | 28 | @Override 29 | public IPatternDetails decodePattern(ItemStack what, Level level, boolean tryRecovery) { 30 | if(what.getItem() instanceof IPackageItem packageItem) { 31 | PatternType patternType = packageItem.getPatternType(what); 32 | if(patternType != null) { 33 | switch(packageItem.getPatternType(what)) { 34 | case PACKAGE -> { 35 | IPackageRecipeInfo recipe = packageItem.getRecipeInfo(what); 36 | int index = packageItem.getIndex(what); 37 | if(recipe != null && recipe.isPackageable() && recipe.validPatternIndex(index)) { 38 | return new PackageCraftingPatternDetails(recipe.getPatterns().get(index)); 39 | } 40 | } 41 | case RECIPE -> { 42 | IPackageRecipeInfo recipe = packageItem.getRecipeInfo(what); 43 | if(recipe != null && recipe.isCraftable()) { 44 | return new RecipeCraftingPatternDetails(recipe); 45 | } 46 | } 47 | case DIRECT -> { 48 | IPackageRecipeInfo recipe = packageItem.getRecipeInfo(what); 49 | if(recipe != null && recipe.isCraftable()) { 50 | return new DirectCraftingPatternDetails(recipe); 51 | } 52 | } 53 | } 54 | } 55 | } 56 | return null; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/inventory/PackagerExtensionItemHandler.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.inventory; 2 | 3 | import net.minecraft.core.Direction; 4 | import net.minecraft.world.item.ItemStack; 5 | import net.minecraftforge.common.capabilities.ForgeCapabilities; 6 | import net.minecraftforge.items.IItemHandlerModifiable; 7 | import thelm.packagedauto.block.entity.PackagerBlockEntity; 8 | import thelm.packagedauto.block.entity.PackagerExtensionBlockEntity; 9 | 10 | public class PackagerExtensionItemHandler extends BaseItemHandler { 11 | 12 | public PackagerExtensionItemHandler(PackagerExtensionBlockEntity blockEntity) { 13 | super(blockEntity, 11); 14 | } 15 | 16 | @Override 17 | protected void onContentsChanged(int slot) { 18 | if(slot < 9 && !blockEntity.getLevel().isClientSide) { 19 | if(blockEntity.isWorking && !getStackInSlot(slot).isEmpty() && !blockEntity.isInputValid()) { 20 | blockEntity.endProcess(); 21 | } 22 | } 23 | super.onContentsChanged(slot); 24 | } 25 | 26 | @Override 27 | public boolean isItemValid(int index, ItemStack stack) { 28 | return switch(index) { 29 | case 9 -> false; 30 | case 10 -> stack.getCapability(ForgeCapabilities.ENERGY).isPresent(); 31 | default -> blockEntity.isWorking ? !getStackInSlot(index).isEmpty() : true; 32 | }; 33 | } 34 | 35 | @Override 36 | public IItemHandlerModifiable getWrapperForDirection(Direction side) { 37 | return wrapperMap.computeIfAbsent(side, s->new PackagerExtensionItemHandlerWrapper(this, s)); 38 | } 39 | 40 | @Override 41 | public int get(int id) { 42 | return switch(id) { 43 | case 0 -> blockEntity.remainingProgress; 44 | case 1 -> blockEntity.isWorking ? 1 : 0; 45 | case 2 -> blockEntity.mode.ordinal(); 46 | case 3 -> blockEntity.getEnergyStorage().getEnergyStored(); 47 | default -> 0; 48 | }; 49 | } 50 | 51 | @Override 52 | public void set(int id, int value) { 53 | switch(id) { 54 | case 0 -> blockEntity.remainingProgress = value; 55 | case 1 -> blockEntity.isWorking = value != 0; 56 | case 2 -> blockEntity.mode = PackagerBlockEntity.Mode.values()[value]; 57 | case 3 -> blockEntity.getEnergyStorage().setEnergyStored(value); 58 | } 59 | } 60 | 61 | @Override 62 | public int getCount() { 63 | return 4; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/volume/FluidStackWrapper.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.volume; 2 | 3 | import java.util.List; 4 | 5 | import net.minecraft.nbt.CompoundTag; 6 | import net.minecraft.network.chat.Component; 7 | import net.minecraftforge.fluids.FluidStack; 8 | import net.minecraftforge.registries.ForgeRegistries; 9 | import thelm.packagedauto.api.IFluidStackWrapper; 10 | import thelm.packagedauto.api.IVolumeStackWrapper; 11 | import thelm.packagedauto.api.IVolumeType; 12 | 13 | public record FluidStackWrapper(FluidStack stack) implements IFluidStackWrapper { 14 | 15 | public static final FluidStackWrapper EMPTY = new FluidStackWrapper(FluidStack.EMPTY); 16 | 17 | @Override 18 | public IVolumeType getVolumeType() { 19 | return FluidVolumeType.INSTANCE; 20 | } 21 | 22 | @Override 23 | public FluidStack getFluid() { 24 | return stack; 25 | } 26 | 27 | @Override 28 | public int getAmount() { 29 | return stack.getAmount(); 30 | } 31 | 32 | @Override 33 | public IVolumeStackWrapper copy() { 34 | return new FluidStackWrapper(stack.copy()); 35 | } 36 | 37 | @Override 38 | public void setAmount(int amount) { 39 | stack.setAmount(amount); 40 | } 41 | 42 | @Override 43 | public boolean isEmpty() { 44 | return stack.isEmpty(); 45 | } 46 | 47 | @Override 48 | public CompoundTag save(CompoundTag tag) { 49 | return stack.writeToNBT(tag); 50 | } 51 | 52 | @Override 53 | public CompoundTag saveAEKey(CompoundTag tag) { 54 | tag.putString("#c", "ae2:f"); 55 | tag.putString("id", ForgeRegistries.FLUIDS.getKey(stack.getFluid()).toString()); 56 | if(stack.hasTag()) { 57 | tag.put("tag", stack.getTag().copy()); 58 | } 59 | return tag; 60 | } 61 | 62 | @Override 63 | public Component getDisplayName() { 64 | return stack.getDisplayName(); 65 | } 66 | 67 | @Override 68 | public Component getAmountDesc() { 69 | return Component.literal(stack.getAmount()+"mB"); 70 | } 71 | 72 | @Override 73 | public List getTooltip() { 74 | return List.of(stack.getDisplayName()); 75 | } 76 | 77 | @Override 78 | public int hashCode() { 79 | return stack.hashCode(); 80 | } 81 | 82 | @Override 83 | public boolean equals(Object obj) { 84 | if(obj instanceof FluidStackWrapper other) { 85 | return stack.equals(other.stack); 86 | } 87 | return false; 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/inventory/CraftingProxyItemHandler.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.inventory; 2 | 3 | import com.google.common.primitives.Ints; 4 | 5 | import net.minecraft.core.Direction; 6 | import net.minecraft.core.Vec3i; 7 | import net.minecraft.nbt.CompoundTag; 8 | import net.minecraft.world.item.ItemStack; 9 | import net.minecraftforge.items.IItemHandlerModifiable; 10 | import net.minecraftforge.items.wrapper.EmptyHandler; 11 | import thelm.packagedauto.api.DirectionalGlobalPos; 12 | import thelm.packagedauto.api.IProxyMarkerItem; 13 | import thelm.packagedauto.block.entity.CraftingProxyBlockEntity; 14 | 15 | public class CraftingProxyItemHandler extends BaseItemHandler { 16 | 17 | public CraftingProxyItemHandler(CraftingProxyBlockEntity blockEntity) { 18 | super(blockEntity, 1); 19 | } 20 | 21 | @Override 22 | protected void onContentsChanged(int slot) { 23 | loadMarker(); 24 | super.onContentsChanged(slot); 25 | } 26 | 27 | @Override 28 | public int getSlotLimit(int slot) { 29 | return 1; 30 | } 31 | 32 | @Override 33 | public boolean isItemValid(int slot, ItemStack stack) { 34 | return stack.getItem() instanceof IProxyMarkerItem marker && marker.getDirectionalGlobalPos(stack) != null; 35 | } 36 | 37 | @Override 38 | public IItemHandlerModifiable getWrapperForDirection(Direction side) { 39 | return (IItemHandlerModifiable)EmptyHandler.INSTANCE; 40 | } 41 | 42 | @Override 43 | public void load(CompoundTag nbt) { 44 | super.load(nbt); 45 | loadMarker(); 46 | } 47 | 48 | public void loadMarker() { 49 | ItemStack stack = getStackInSlot(0); 50 | if(stack.getItem() instanceof IProxyMarkerItem marker) { 51 | DirectionalGlobalPos pos = marker.getDirectionalGlobalPos(stack); 52 | if(pos == null) { 53 | blockEntity.target = null; 54 | } 55 | else if(blockEntity.getLevel() != null && !blockEntity.getLevel().dimension().equals(pos.dimension())) { 56 | blockEntity.target = null; 57 | } 58 | else { 59 | Vec3i dirVec = pos.blockPos().subtract(blockEntity.getBlockPos()); 60 | int dist = Ints.max(Math.abs(dirVec.getX()), Math.abs(dirVec.getY()), Math.abs(dirVec.getZ())); 61 | if(dist <= CraftingProxyBlockEntity.range) { 62 | blockEntity.target = pos; 63 | } 64 | } 65 | } 66 | else { 67 | blockEntity.target = null; 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/main/resources/assets/packagedauto/patchouli_books/guide/en_us/entries/core/packager_extension.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Packager Extension", 3 | "category": "packagedauto:core", 4 | "icon": "packagedauto:packager_extension", 5 | "pages": [ 6 | { 7 | "type": "patchouli:text", 8 | "text": "The $(item)Packager Extension/$ copies the function of a nearby $(l:core/packager)Packager/$, allowing less $(l:core/recipe_holder)Package Recipe Holders/$ to be used when parallelizing packaging.$(p)This machine requires power." 9 | }, 10 | { 11 | "type": "patchouli:spotlight", 12 | "item": "packagedauto:packager_extension", 13 | "link_recipe": true, 14 | "title": "Usage", 15 | "text": "To use the $(item)Packager Extension/$, place anywhere within a 3x3x3 area around a $(l:core/packager)Packager/$ to copy its function.$(p)If multiple $(l:core/packager)Packagers/$ are present, the machine will copy the north-west-bottommost one it can find.$(p)You may extract inputs out from the top side." 16 | }, 17 | { 18 | "type": "patchouli:text", 19 | "title": "Modes", 20 | "text": "$(thing)Require Exact/$: Make the first package that exactly matches inventory contents.$(p)$(thing)Require Disjoint/$: Checks if packages have no overlap and make the package that can be made from inventory contents, otherwise fallback to $(thing)Require Exact/$.$(p)$(thing)First Match/$: Make the first package that can be made from inventory contents." 21 | }, 22 | { 23 | "type": "patchouli:text", 24 | "title": "Settings Cloning", 25 | "text": "Using the $(l:core/settings_cloner)Packaging Settings Cloner/$, you can copy and paste the mode setting." 26 | }, 27 | { 28 | "type": "patchouli:text", 29 | "flag": "mod:ae2", 30 | "title": "AE2 Integration", 31 | "text": "The $(item)Packager Extension/$ can be connected to an $(thing)ME Network/$.$(p)It will extract power to use, provide packaging as autocrafting, and instead eject created $(l:core/package)Recipe Packages/$ into the network." 32 | }, 33 | { 34 | "type": "patchouli:crafting", 35 | "flag": "!mod:ae2", 36 | "recipe": "packagedauto:packager_extension", 37 | "title": "Crafting" 38 | }, 39 | { 40 | "type": "patchouli:crafting", 41 | "flag": "mod:ae2", 42 | "recipe": "packagedauto:packager_extension_ae", 43 | "title": "Crafting" 44 | } 45 | ], 46 | "read_by_default": true, 47 | "sortnum": 8 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/integration/jei/EncoderGhostIngredientHandler.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.integration.jei; 2 | 3 | import java.util.List; 4 | 5 | import mezz.jei.api.gui.handlers.IGhostIngredientHandler; 6 | import mezz.jei.api.ingredients.ITypedIngredient; 7 | import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; 8 | import net.minecraft.client.renderer.Rect2i; 9 | import net.minecraft.world.inventory.Slot; 10 | import net.minecraft.world.item.ItemStack; 11 | import thelm.packagedauto.api.IVolumeType; 12 | import thelm.packagedauto.client.screen.EncoderScreen; 13 | import thelm.packagedauto.network.PacketHandler; 14 | import thelm.packagedauto.network.packet.SetItemStackPacket; 15 | import thelm.packagedauto.slot.FalseCopySlot; 16 | import thelm.packagedauto.util.ApiImpl; 17 | import thelm.packagedauto.util.MiscHelper; 18 | 19 | public class EncoderGhostIngredientHandler implements IGhostIngredientHandler { 20 | 21 | @Override 22 | public List> getTargetsTyped(EncoderScreen gui, ITypedIngredient ingredient, boolean doStart) { 23 | ItemStack stack = wrapStack(ingredient.getIngredient()); 24 | if(!stack.isEmpty()) { 25 | return gui.menu.slots.stream().filter(s->s instanceof FalseCopySlot). 26 | >map(s->new SlotTarget<>(s, getSlotArea(gui, s))).toList(); 27 | } 28 | return List.of(); 29 | } 30 | 31 | @Override 32 | public void onComplete() {} 33 | 34 | private static Rect2i getSlotArea(AbstractContainerScreen gui, Slot slot) { 35 | return new Rect2i(gui.getGuiLeft()+slot.x, gui.getGuiTop()+slot.y, 16, 16); 36 | } 37 | 38 | private static ItemStack wrapStack(Object ingredient) { 39 | if(ingredient instanceof ItemStack stack) { 40 | return stack; 41 | } 42 | IVolumeType type = ApiImpl.INSTANCE.getVolumeType(ingredient.getClass()); 43 | if(type != null) { 44 | return MiscHelper.INSTANCE.tryMakeVolumePackage(ingredient); 45 | } 46 | return ItemStack.EMPTY; 47 | } 48 | 49 | private static record SlotTarget(Slot slot, Rect2i area) implements Target { 50 | 51 | @Override 52 | public Rect2i getArea() { 53 | return area; 54 | } 55 | 56 | @Override 57 | public void accept(I ingredient) { 58 | ItemStack stack = wrapStack(ingredient); 59 | if(!stack.isEmpty()) { 60 | PacketHandler.INSTANCE.sendToServer(new SetItemStackPacket(slot.index, stack)); 61 | } 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/block/CraftingProxyBlock.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.block; 2 | 3 | import net.minecraft.core.BlockPos; 4 | import net.minecraft.server.level.ServerPlayer; 5 | import net.minecraft.world.InteractionHand; 6 | import net.minecraft.world.InteractionResult; 7 | import net.minecraft.world.entity.player.Player; 8 | import net.minecraft.world.item.BlockItem; 9 | import net.minecraft.world.item.Item; 10 | import net.minecraft.world.level.Level; 11 | import net.minecraft.world.level.block.SoundType; 12 | import net.minecraft.world.level.block.entity.BlockEntity; 13 | import net.minecraft.world.level.block.entity.BlockEntityTicker; 14 | import net.minecraft.world.level.block.entity.BlockEntityType; 15 | import net.minecraft.world.level.block.state.BlockBehaviour; 16 | import net.minecraft.world.level.block.state.BlockState; 17 | import net.minecraft.world.level.material.MapColor; 18 | import net.minecraft.world.phys.BlockHitResult; 19 | import thelm.packagedauto.block.entity.BaseBlockEntity; 20 | import thelm.packagedauto.block.entity.CraftingProxyBlockEntity; 21 | 22 | public class CraftingProxyBlock extends BaseBlock { 23 | 24 | public static final CraftingProxyBlock INSTANCE = new CraftingProxyBlock(); 25 | public static final Item ITEM_INSTANCE = new BlockItem(INSTANCE, new Item.Properties()); 26 | 27 | protected CraftingProxyBlock() { 28 | super(BlockBehaviour.Properties.of().strength(10F, 15F).mapColor(MapColor.METAL).sound(SoundType.METAL)); 29 | } 30 | 31 | @Override 32 | public CraftingProxyBlockEntity newBlockEntity(BlockPos pos, BlockState state) { 33 | return CraftingProxyBlockEntity.TYPE_INSTANCE.create(pos, state); 34 | } 35 | 36 | @Override 37 | public BlockEntityTicker getTicker(Level level, BlockState state, BlockEntityType blockEntityType) { 38 | return BaseBlockEntity::tick; 39 | } 40 | 41 | @Override 42 | public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hitResult) { 43 | if(player.isShiftKeyDown()) { 44 | BlockEntity blockEntity = level.getBlockEntity(pos); 45 | if(blockEntity instanceof CraftingProxyBlockEntity proxy) { 46 | if(!level.isClientSide) { 47 | proxy.sendPreview((ServerPlayer)player); 48 | } 49 | return InteractionResult.SUCCESS; 50 | } 51 | } 52 | return super.use(state, level, pos, player, hand, hitResult); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/integration/jei/EncoderTransferHandler.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.integration.jei; 2 | 3 | 4 | import java.util.List; 5 | import java.util.Optional; 6 | 7 | import it.unimi.dsi.fastutil.ints.Int2ObjectMap; 8 | import mezz.jei.api.gui.ingredient.IRecipeSlotsView; 9 | import mezz.jei.api.recipe.transfer.IRecipeTransferError; 10 | import mezz.jei.api.recipe.transfer.IRecipeTransferHandlerHelper; 11 | import mezz.jei.api.recipe.transfer.IUniversalRecipeTransferHandler; 12 | import net.minecraft.resources.ResourceLocation; 13 | import net.minecraft.world.entity.player.Player; 14 | import net.minecraft.world.inventory.MenuType; 15 | import net.minecraft.world.item.ItemStack; 16 | import thelm.packagedauto.api.IPackageRecipeType; 17 | import thelm.packagedauto.menu.EncoderMenu; 18 | import thelm.packagedauto.network.PacketHandler; 19 | import thelm.packagedauto.network.packet.SetRecipePacket; 20 | 21 | public class EncoderTransferHandler implements IUniversalRecipeTransferHandler { 22 | 23 | private final IRecipeTransferHandlerHelper transferHelper; 24 | 25 | public EncoderTransferHandler(IRecipeTransferHandlerHelper transferHelper) { 26 | this.transferHelper = transferHelper; 27 | } 28 | 29 | @Override 30 | public Class getContainerClass() { 31 | return EncoderMenu.class; 32 | } 33 | 34 | @Override 35 | public Optional> getMenuType() { 36 | return Optional.empty(); 37 | } 38 | 39 | @Override 40 | public IRecipeTransferError transferRecipe(EncoderMenu menu, Object recipe, IRecipeSlotsView recipeSlots, Player player, boolean maxTransfer, boolean doTransfer) { 41 | List categories = PackagedAutoJEIPlugin.getRecipeCategoriesForRecipe(recipe); 42 | if(categories.isEmpty()) { 43 | return transferHelper.createInternalError(); 44 | } 45 | IPackageRecipeType recipeType = menu.patternItemHandler.recipeType; 46 | if(!categories.stream().anyMatch(recipeType.getJEICategories()::contains)) { 47 | return transferHelper.createInternalError(); 48 | } 49 | Int2ObjectMap map = recipeType.getRecipeTransferMap(new RecipeSlotsViewWrapper(recipe, recipeSlots)); 50 | if(map == null || map.isEmpty()) { 51 | return transferHelper.createInternalError(); 52 | } 53 | if(!doTransfer) { 54 | return null; 55 | } 56 | PacketHandler.INSTANCE.sendToServer(new SetRecipePacket(map)); 57 | return null; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/integration/emi/EncoderRecipeHandler.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.integration.emi; 2 | 3 | import java.util.List; 4 | 5 | import dev.emi.emi.api.recipe.EmiPlayerInventory; 6 | import dev.emi.emi.api.recipe.EmiRecipe; 7 | import dev.emi.emi.api.recipe.handler.EmiCraftContext; 8 | import dev.emi.emi.api.recipe.handler.EmiRecipeHandler; 9 | import it.unimi.dsi.fastutil.ints.Int2ObjectMap; 10 | import net.minecraft.client.Minecraft; 11 | import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; 12 | import net.minecraft.resources.ResourceLocation; 13 | import net.minecraft.world.item.ItemStack; 14 | import thelm.packagedauto.api.IPackageRecipeType; 15 | import thelm.packagedauto.menu.EncoderMenu; 16 | import thelm.packagedauto.network.PacketHandler; 17 | import thelm.packagedauto.network.packet.SetRecipePacket; 18 | 19 | public class EncoderRecipeHandler implements EmiRecipeHandler { 20 | 21 | @Override 22 | public EmiPlayerInventory getInventory(AbstractContainerScreen screen) { 23 | return new EmiPlayerInventory(List.of()); 24 | } 25 | 26 | @Override 27 | public boolean supportsRecipe(EmiRecipe recipe) { 28 | return true; 29 | } 30 | 31 | @Override 32 | public boolean canCraft(EmiRecipe recipe, EmiCraftContext context) { 33 | EncoderMenu menu = context.getScreenHandler(); 34 | IPackageRecipeType recipeType = menu.patternItemHandler.recipeType; 35 | ResourceLocation category = recipe.getCategory().getId(); 36 | if(!recipeType.getEMICategories().contains(category)) { 37 | return false; 38 | } 39 | Int2ObjectMap map = recipeType.getRecipeTransferMap(new EmiRecipeWrapper(recipe)); 40 | if(map == null || map.isEmpty()) { 41 | return false; 42 | } 43 | return true; 44 | } 45 | 46 | @Override 47 | public boolean craft(EmiRecipe recipe, EmiCraftContext context) { 48 | if(!canCraft(recipe, context)) { 49 | return false; 50 | } 51 | recipe.getDisplayHeight(); 52 | EncoderMenu menu = context.getScreenHandler(); 53 | IPackageRecipeType recipeType = menu.patternItemHandler.recipeType; 54 | Int2ObjectMap map = recipeType.getRecipeTransferMap(new EmiRecipeWrapper(recipe)); 55 | if(map == null || map.isEmpty()) { 56 | return false; 57 | } 58 | Minecraft.getInstance().setScreen(context.getScreen()); 59 | PacketHandler.INSTANCE.sendToServer(new SetRecipePacket(map)); 60 | return true; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/inventory/DistributorItemHandler.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.inventory; 2 | 3 | import com.google.common.primitives.Ints; 4 | 5 | import net.minecraft.core.Direction; 6 | import net.minecraft.core.Vec3i; 7 | import net.minecraft.nbt.CompoundTag; 8 | import net.minecraft.world.item.ItemStack; 9 | import net.minecraftforge.items.IItemHandlerModifiable; 10 | import net.minecraftforge.items.wrapper.EmptyHandler; 11 | import thelm.packagedauto.api.DirectionalGlobalPos; 12 | import thelm.packagedauto.api.IDistributorMarkerItem; 13 | import thelm.packagedauto.block.entity.DistributorBlockEntity; 14 | 15 | public class DistributorItemHandler extends BaseItemHandler { 16 | 17 | public DistributorItemHandler(DistributorBlockEntity blockEntity) { 18 | super(blockEntity, 81); 19 | } 20 | 21 | @Override 22 | protected void onContentsChanged(int slot) { 23 | loadMarker(slot); 24 | super.onContentsChanged(slot); 25 | } 26 | 27 | @Override 28 | public int getSlotLimit(int slot) { 29 | return 1; 30 | } 31 | 32 | @Override 33 | public boolean isItemValid(int slot, ItemStack stack) { 34 | return stack.getItem() instanceof IDistributorMarkerItem marker && marker.getDirectionalGlobalPos(stack) != null; 35 | } 36 | 37 | @Override 38 | public IItemHandlerModifiable getWrapperForDirection(Direction side) { 39 | return (IItemHandlerModifiable)EmptyHandler.INSTANCE; 40 | } 41 | 42 | @Override 43 | public void load(CompoundTag nbt) { 44 | super.load(nbt); 45 | for(int i = 0; i < 81; ++i) { 46 | loadMarker(i); 47 | } 48 | } 49 | 50 | public void loadMarker(int slot) { 51 | ItemStack stack = getStackInSlot(slot); 52 | if(stack.getItem() instanceof IDistributorMarkerItem marker) { 53 | DirectionalGlobalPos pos = marker.getDirectionalGlobalPos(stack); 54 | if(pos == null) { 55 | blockEntity.positions.remove(slot); 56 | } 57 | else if(blockEntity.getLevel() != null && !blockEntity.getLevel().dimension().equals(pos.dimension())) { 58 | blockEntity.positions.remove(slot); 59 | } 60 | else { 61 | Vec3i dirVec = pos.blockPos().subtract(blockEntity.getBlockPos()); 62 | int dist = Ints.max(Math.abs(dirVec.getX()), Math.abs(dirVec.getY()), Math.abs(dirVec.getZ())); 63 | if(dist <= DistributorBlockEntity.range) { 64 | blockEntity.positions.put(slot, pos); 65 | } 66 | } 67 | } 68 | else { 69 | blockEntity.positions.remove(slot); 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/integration/appeng/recipe/DirectCraftingPatternDetails.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.integration.appeng.recipe; 2 | 3 | import java.util.List; 4 | import java.util.Objects; 5 | import java.util.stream.Stream; 6 | 7 | import appeng.api.crafting.IPatternDetails; 8 | import appeng.api.stacks.AEItemKey; 9 | import appeng.api.stacks.GenericStack; 10 | import net.minecraft.world.item.ItemStack; 11 | import thelm.packagedauto.api.IPackageItem; 12 | import thelm.packagedauto.api.IPackageRecipeInfo; 13 | import thelm.packagedauto.integration.appeng.AppEngUtil; 14 | 15 | public class DirectCraftingPatternDetails implements IPatternDetails { 16 | 17 | public final IPackageRecipeInfo recipe; 18 | public final AEItemKey definition; 19 | public final IInput[] inputs; 20 | public final GenericStack[] outputs; 21 | 22 | public DirectCraftingPatternDetails(IPackageRecipeInfo recipe) { 23 | this.recipe = recipe; 24 | ItemStack definitionStack = recipe.getPatterns().get(0).getOutput(); 25 | definitionStack.getTag().putString("PatternType", "direct"); 26 | definition = AEItemKey.of(definitionStack); 27 | List sparseInputs = recipe.getInputs().stream().flatMap(stack->{ 28 | // Do one recursive packing 29 | if(stack.getItem() instanceof IPackageItem packageItem) { 30 | IPackageRecipeInfo subRecipe = packageItem.getRecipeInfo(stack); 31 | if(!subRecipe.getRecipeType().hasMachine() && subRecipe.getPatterns().size() == 1) { 32 | return subRecipe.getInputs().stream(); 33 | } 34 | } 35 | return Stream.of(stack); 36 | }).map(GenericStack::fromItemStack).toList(); 37 | List sparseOutputs = recipe.getOutputs().stream().map(AppEngUtil::getGenericOutput).toList(); 38 | inputs = AppEngUtil.toInputs(recipe, AppEngUtil.condenseStacks(sparseInputs)); 39 | outputs = AppEngUtil.condenseStacks(sparseOutputs); 40 | } 41 | 42 | @Override 43 | public AEItemKey getDefinition() { 44 | return definition; 45 | } 46 | 47 | @Override 48 | public IInput[] getInputs() { 49 | return inputs; 50 | } 51 | 52 | @Override 53 | public GenericStack[] getOutputs() { 54 | return outputs; 55 | } 56 | 57 | @Override 58 | public boolean equals(Object obj) { 59 | if(obj instanceof DirectCraftingPatternDetails other) { 60 | return recipe.equals(other.recipe); 61 | } 62 | return false; 63 | } 64 | 65 | @Override 66 | public int hashCode() { 67 | return Objects.hash(recipe, 1); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/main/java/thelm/packagedauto/inventory/SidedItemHandlerWrapper.java: -------------------------------------------------------------------------------- 1 | package thelm.packagedauto.inventory; 2 | 3 | import net.minecraft.core.Direction; 4 | import net.minecraft.world.item.ItemStack; 5 | import net.minecraftforge.items.IItemHandlerModifiable; 6 | 7 | public abstract class SidedItemHandlerWrapper implements IItemHandlerModifiable { 8 | 9 | protected H itemHandler; 10 | protected Direction direction; 11 | 12 | public SidedItemHandlerWrapper(H itemHandler, Direction direction) { 13 | this.itemHandler = itemHandler; 14 | this.direction = direction; 15 | } 16 | 17 | public int getSlot(int slot, Direction direction) { 18 | int[] slots = getSlotsForDirection(direction); 19 | if(slot < slots.length) { 20 | return slots[slot]; 21 | } 22 | return -1; 23 | } 24 | 25 | @Override 26 | public int getSlots() { 27 | return getSlotsForDirection(direction).length; 28 | } 29 | 30 | @Override 31 | public ItemStack getStackInSlot(int slot) { 32 | int i = getSlot(slot, direction); 33 | return i == -1 ? ItemStack.EMPTY : itemHandler.getStackInSlot(i); 34 | } 35 | 36 | @Override 37 | public ItemStack insertItem(int slot, ItemStack stack, boolean simulate) { 38 | int i = getSlot(slot, direction); 39 | return i == -1 || !canInsertItem(i, stack, direction) ? stack : itemHandler.insertItem(i, stack, simulate); 40 | } 41 | 42 | @Override 43 | public ItemStack extractItem(int slot, int amount, boolean simulate) { 44 | int i = getSlot(slot, direction); 45 | return i == -1 || !canExtractItem(i, direction) ? ItemStack.EMPTY : itemHandler.extractItem(i, amount, simulate); 46 | } 47 | 48 | @Override 49 | public int getSlotLimit(int slot) { 50 | int i = getSlot(slot, direction); 51 | return i == -1 ? 0 : itemHandler.getSlotLimit(i); 52 | } 53 | 54 | @Override 55 | public boolean isItemValid(int slot, ItemStack stack) { 56 | int i = getSlot(slot, direction); 57 | return i == -1 ? false : itemHandler.isItemValid(i, stack); 58 | } 59 | 60 | @Override 61 | public void setStackInSlot(int slot, ItemStack stack) { 62 | int i = getSlot(slot, direction); 63 | if(i != -1) { 64 | itemHandler.setStackInSlot(i, stack); 65 | } 66 | } 67 | 68 | public abstract int[] getSlotsForDirection(Direction direction); 69 | 70 | public abstract boolean canInsertItem(int slot, ItemStack stack, Direction direction); 71 | 72 | public abstract boolean canExtractItem(int slot, Direction direction); 73 | } 74 | --------------------------------------------------------------------------------