attempt #1 to backport 1.16 to 1.15
1
.gitignore
vendored
|
@ -12,6 +12,7 @@
|
|||
/classes
|
||||
/bin/
|
||||
/run/
|
||||
/logs
|
||||
|
||||
*.classpath
|
||||
*.project
|
||||
|
|
2
Jenkinsfile
vendored
|
@ -22,7 +22,7 @@ pipeline {
|
|||
|
||||
stage('Publish') {
|
||||
when {
|
||||
branch 'master'
|
||||
branch 'main'
|
||||
}
|
||||
steps {
|
||||
sh './gradlew publish --no-daemon'
|
||||
|
|
13
build.gradle
|
@ -13,7 +13,7 @@ apply plugin: 'net.minecraftforge.gradle'
|
|||
apply plugin: 'eclipse'
|
||||
apply plugin: 'maven-publish'
|
||||
|
||||
version = '1.5.5'
|
||||
version = '1.8.2'
|
||||
group = 'de.ellpeck.prettypipes' // http://maven.apache.org/guides/mini/guide-naming-conventions.html
|
||||
archivesBaseName = 'PrettyPipes'
|
||||
|
||||
|
@ -23,7 +23,7 @@ if (System.getenv('BUILD_NUMBER') != null) {
|
|||
sourceCompatibility = targetCompatibility = compileJava.sourceCompatibility = compileJava.targetCompatibility = '1.8' // Need this here so eclipse task generates correctly.
|
||||
|
||||
minecraft {
|
||||
mappings channel: 'snapshot', version: '20200128-1.15.1'
|
||||
mappings channel: 'snapshot', version: '20200514-1.15.1'
|
||||
|
||||
runs {
|
||||
client {
|
||||
|
@ -87,6 +87,9 @@ repositories {
|
|||
maven {
|
||||
url = "https://dvs1.progwml6.com/files/maven"
|
||||
}
|
||||
maven {
|
||||
url = "https://www.cursemaven.com"
|
||||
}
|
||||
}
|
||||
|
||||
configurations {
|
||||
|
@ -95,11 +98,15 @@ configurations {
|
|||
}
|
||||
|
||||
dependencies {
|
||||
minecraft 'net.minecraftforge:forge:1.15.2-31.1.19'
|
||||
minecraft 'net.minecraftforge:forge:1.15.2-31.2.45'
|
||||
embed "org.jgrapht:jgrapht-core:1.4.0"
|
||||
|
||||
compileOnly fg.deobf("mezz.jei:jei-1.15.2:6.0.0.2:api")
|
||||
runtimeOnly fg.deobf("mezz.jei:jei-1.15.2:6.0.0.2")
|
||||
|
||||
// to test the rf requiring stuff
|
||||
runtimeOnly fg.deobf("curse.maven:powah:3057732")
|
||||
runtimeOnly fg.deobf("curse.maven:lollipop:3057731")
|
||||
}
|
||||
|
||||
// Example for how to get properties into the manifest for reading by the runtime..
|
||||
|
|
BIN
media/2020-10-17_00.58.03.png
Normal file
After Width: | Height: | Size: 850 KiB |
|
@ -4,17 +4,25 @@ import de.ellpeck.prettypipes.entities.PipeFrameEntity;
|
|||
import de.ellpeck.prettypipes.entities.PipeFrameRenderer;
|
||||
import de.ellpeck.prettypipes.items.*;
|
||||
import de.ellpeck.prettypipes.misc.ItemEqualityType;
|
||||
import de.ellpeck.prettypipes.pipe.modules.FilterModifierModule;
|
||||
import de.ellpeck.prettypipes.pipe.modules.LowPriorityModuleItem;
|
||||
import de.ellpeck.prettypipes.pipe.modules.RedstoneModuleItem;
|
||||
import de.ellpeck.prettypipes.pipe.modules.SpeedModuleItem;
|
||||
import de.ellpeck.prettypipes.network.PipeNetwork;
|
||||
import de.ellpeck.prettypipes.packets.PacketHandler;
|
||||
import de.ellpeck.prettypipes.pipe.IPipeConnectable;
|
||||
import de.ellpeck.prettypipes.pipe.PipeBlock;
|
||||
import de.ellpeck.prettypipes.pipe.PipeRenderer;
|
||||
import de.ellpeck.prettypipes.pipe.PipeTileEntity;
|
||||
import de.ellpeck.prettypipes.pipe.containers.AbstractPipeContainer;
|
||||
import de.ellpeck.prettypipes.pipe.containers.MainPipeContainer;
|
||||
import de.ellpeck.prettypipes.pipe.containers.MainPipeGui;
|
||||
import de.ellpeck.prettypipes.pipe.modules.*;
|
||||
import de.ellpeck.prettypipes.pipe.modules.craft.CraftingModuleContainer;
|
||||
import de.ellpeck.prettypipes.pipe.modules.craft.CraftingModuleGui;
|
||||
import de.ellpeck.prettypipes.pipe.modules.craft.CraftingModuleItem;
|
||||
import de.ellpeck.prettypipes.pipe.modules.extraction.ExtractionModuleContainer;
|
||||
import de.ellpeck.prettypipes.pipe.modules.extraction.ExtractionModuleGui;
|
||||
import de.ellpeck.prettypipes.pipe.modules.extraction.ExtractionModuleItem;
|
||||
import de.ellpeck.prettypipes.network.PipeNetwork;
|
||||
import de.ellpeck.prettypipes.packets.PacketHandler;
|
||||
import de.ellpeck.prettypipes.pipe.*;
|
||||
import de.ellpeck.prettypipes.pipe.containers.*;
|
||||
import de.ellpeck.prettypipes.pipe.modules.filter.FilterIncreaseModuleContainer;
|
||||
import de.ellpeck.prettypipes.pipe.modules.filter.FilterIncreaseModuleGui;
|
||||
import de.ellpeck.prettypipes.pipe.modules.filter.FilterIncreaseModuleItem;
|
||||
import de.ellpeck.prettypipes.pipe.modules.insertion.FilterModuleContainer;
|
||||
import de.ellpeck.prettypipes.pipe.modules.insertion.FilterModuleGui;
|
||||
import de.ellpeck.prettypipes.pipe.modules.insertion.FilterModuleItem;
|
||||
|
@ -24,6 +32,10 @@ import de.ellpeck.prettypipes.pipe.modules.retrieval.RetrievalModuleItem;
|
|||
import de.ellpeck.prettypipes.pipe.modules.stacksize.StackSizeModuleContainer;
|
||||
import de.ellpeck.prettypipes.pipe.modules.stacksize.StackSizeModuleGui;
|
||||
import de.ellpeck.prettypipes.pipe.modules.stacksize.StackSizeModuleItem;
|
||||
import de.ellpeck.prettypipes.pressurizer.PressurizerBlock;
|
||||
import de.ellpeck.prettypipes.pressurizer.PressurizerContainer;
|
||||
import de.ellpeck.prettypipes.pressurizer.PressurizerGui;
|
||||
import de.ellpeck.prettypipes.pressurizer.PressurizerTileEntity;
|
||||
import de.ellpeck.prettypipes.terminal.CraftingTerminalBlock;
|
||||
import de.ellpeck.prettypipes.terminal.CraftingTerminalTileEntity;
|
||||
import de.ellpeck.prettypipes.terminal.ItemTerminalBlock;
|
||||
|
@ -80,6 +92,8 @@ public final class Registry {
|
|||
|
||||
@CapabilityInject(PipeNetwork.class)
|
||||
public static Capability<PipeNetwork> pipeNetworkCapability;
|
||||
@CapabilityInject(IPipeConnectable.class)
|
||||
public static Capability<IPipeConnectable> pipeConnectableCapability;
|
||||
|
||||
public static Item wrenchItem;
|
||||
public static Item pipeFrameItem;
|
||||
|
@ -98,17 +112,24 @@ public final class Registry {
|
|||
|
||||
public static EntityType<PipeFrameEntity> pipeFrameEntity;
|
||||
|
||||
public static Block pressurizerBlock;
|
||||
public static TileEntityType<PressurizerTileEntity> pressurizerTileEntity;
|
||||
public static ContainerType<PressurizerContainer> pressurizerContainer;
|
||||
|
||||
public static ContainerType<ExtractionModuleContainer> extractionModuleContainer;
|
||||
public static ContainerType<FilterModuleContainer> filterModuleContainer;
|
||||
public static ContainerType<RetrievalModuleContainer> retrievalModuleContainer;
|
||||
public static ContainerType<StackSizeModuleContainer> stackSizeModuleContainer;
|
||||
public static ContainerType<FilterIncreaseModuleContainer> filterIncreaseModuleContainer;
|
||||
public static ContainerType<CraftingModuleContainer> craftingModuleContainer;
|
||||
|
||||
@SubscribeEvent
|
||||
public static void registerBlocks(RegistryEvent.Register<Block> event) {
|
||||
event.getRegistry().registerAll(
|
||||
pipeBlock = new PipeBlock().setRegistryName("pipe"),
|
||||
itemTerminalBlock = new ItemTerminalBlock().setRegistryName("item_terminal"),
|
||||
craftingTerminalBlock = new CraftingTerminalBlock().setRegistryName("crafting_terminal")
|
||||
craftingTerminalBlock = new CraftingTerminalBlock().setRegistryName("crafting_terminal"),
|
||||
pressurizerBlock = new PressurizerBlock().setRegistryName("pressurizer")
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -124,10 +145,13 @@ public final class Registry {
|
|||
registry.registerAll(createTieredModule("filter_module", FilterModuleItem::new));
|
||||
registry.registerAll(createTieredModule("speed_module", SpeedModuleItem::new));
|
||||
registry.registerAll(createTieredModule("low_priority_module", LowPriorityModuleItem::new));
|
||||
registry.registerAll(createTieredModule("high_priority_module", HighPriorityModuleItem::new));
|
||||
registry.registerAll(createTieredModule("retrieval_module", RetrievalModuleItem::new));
|
||||
registry.register(new StackSizeModuleItem("stack_size_module"));
|
||||
registry.registerAll(Arrays.stream(ItemEqualityType.values()).map(t -> new FilterModifierModule(t.name().toLowerCase(Locale.ROOT) + "_filter_modifier", t)).toArray(Item[]::new));
|
||||
registry.registerAll(Arrays.stream(ItemEqualityType.values()).map(t -> new FilterModifierModuleItem(t.name().toLowerCase(Locale.ROOT) + "_filter_modifier", t)).toArray(Item[]::new));
|
||||
registry.register(new RedstoneModuleItem("redstone_module"));
|
||||
registry.register(new FilterIncreaseModuleItem("filter_increase_modifier"));
|
||||
registry.registerAll(createTieredModule("crafting_module", CraftingModuleItem::new));
|
||||
|
||||
ForgeRegistries.BLOCKS.getValues().stream()
|
||||
.filter(b -> b.getRegistryName().getNamespace().equals(PrettyPipes.ID))
|
||||
|
@ -139,7 +163,8 @@ public final class Registry {
|
|||
event.getRegistry().registerAll(
|
||||
pipeTileEntity = (TileEntityType<PipeTileEntity>) TileEntityType.Builder.create(PipeTileEntity::new, pipeBlock).build(null).setRegistryName("pipe"),
|
||||
itemTerminalTileEntity = (TileEntityType<ItemTerminalTileEntity>) TileEntityType.Builder.create(ItemTerminalTileEntity::new, itemTerminalBlock).build(null).setRegistryName("item_terminal"),
|
||||
craftingTerminalTileEntity = (TileEntityType<CraftingTerminalTileEntity>) TileEntityType.Builder.create(CraftingTerminalTileEntity::new, craftingTerminalBlock).build(null).setRegistryName("crafting_terminal")
|
||||
craftingTerminalTileEntity = (TileEntityType<CraftingTerminalTileEntity>) TileEntityType.Builder.create(CraftingTerminalTileEntity::new, craftingTerminalBlock).build(null).setRegistryName("crafting_terminal"),
|
||||
pressurizerTileEntity = (TileEntityType<PressurizerTileEntity>) TileEntityType.Builder.create(PressurizerTileEntity::new, pressurizerBlock).build(null).setRegistryName("pressurizer")
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -156,10 +181,13 @@ public final class Registry {
|
|||
pipeContainer = (ContainerType<MainPipeContainer>) IForgeContainerType.create((windowId, inv, data) -> new MainPipeContainer(pipeContainer, windowId, inv.player, data.readBlockPos())).setRegistryName("pipe"),
|
||||
itemTerminalContainer = (ContainerType<ItemTerminalContainer>) IForgeContainerType.create((windowId, inv, data) -> new ItemTerminalContainer(itemTerminalContainer, windowId, inv.player, data.readBlockPos())).setRegistryName("item_terminal"),
|
||||
craftingTerminalContainer = (ContainerType<CraftingTerminalContainer>) IForgeContainerType.create((windowId, inv, data) -> new CraftingTerminalContainer(craftingTerminalContainer, windowId, inv.player, data.readBlockPos())).setRegistryName("crafting_terminal"),
|
||||
pressurizerContainer = (ContainerType<PressurizerContainer>) IForgeContainerType.create((windowId, inv, data) -> new PressurizerContainer(pressurizerContainer, windowId, inv.player, data.readBlockPos())).setRegistryName("pressurizer"),
|
||||
extractionModuleContainer = createPipeContainer("extraction_module"),
|
||||
filterModuleContainer = createPipeContainer("filter_module"),
|
||||
retrievalModuleContainer = createPipeContainer("retrieval_module"),
|
||||
stackSizeModuleContainer = createPipeContainer("stack_size_module")
|
||||
stackSizeModuleContainer = createPipeContainer("stack_size_module"),
|
||||
filterIncreaseModuleContainer = createPipeContainer("filter_increase_module"),
|
||||
craftingModuleContainer = createPipeContainer("crafting_module")
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -180,34 +208,42 @@ public final class Registry {
|
|||
}
|
||||
|
||||
public static void setup(FMLCommonSetupEvent event) {
|
||||
CapabilityManager.INSTANCE.register(PipeNetwork.class, new Capability.IStorage<PipeNetwork>() {
|
||||
@Nullable
|
||||
@Override
|
||||
public INBT writeNBT(Capability<PipeNetwork> capability, PipeNetwork instance, Direction side) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readNBT(Capability<PipeNetwork> capability, PipeNetwork instance, Direction side, INBT nbt) {
|
||||
|
||||
}
|
||||
}, () -> null);
|
||||
registerCap(PipeNetwork.class);
|
||||
registerCap(IPipeConnectable.class);
|
||||
PacketHandler.setup();
|
||||
}
|
||||
|
||||
public static final class Client {
|
||||
public static void setup(FMLClientSetupEvent event) {
|
||||
RenderTypeLookup.setRenderLayer(pipeBlock, RenderType.cutout());
|
||||
RenderTypeLookup.setRenderLayer(pipeBlock, RenderType.getCutout());
|
||||
ClientRegistry.bindTileEntityRenderer(pipeTileEntity, PipeRenderer::new);
|
||||
RenderingRegistry.registerEntityRenderingHandler(pipeFrameEntity, PipeFrameRenderer::new);
|
||||
|
||||
ScreenManager.registerFactory(pipeContainer, MainPipeGui::new);
|
||||
ScreenManager.registerFactory(itemTerminalContainer, ItemTerminalGui::new);
|
||||
ScreenManager.registerFactory(pressurizerContainer, PressurizerGui::new);
|
||||
ScreenManager.registerFactory(craftingTerminalContainer, CraftingTerminalGui::new);
|
||||
ScreenManager.registerFactory(extractionModuleContainer, ExtractionModuleGui::new);
|
||||
ScreenManager.registerFactory(filterModuleContainer, FilterModuleGui::new);
|
||||
ScreenManager.registerFactory(retrievalModuleContainer, RetrievalModuleGui::new);
|
||||
ScreenManager.registerFactory(stackSizeModuleContainer, StackSizeModuleGui::new);
|
||||
ScreenManager.registerFactory(filterIncreaseModuleContainer, FilterIncreaseModuleGui::new);
|
||||
ScreenManager.registerFactory(craftingModuleContainer, CraftingModuleGui::new);
|
||||
}
|
||||
}
|
||||
|
||||
private static <T> void registerCap(Class<T> capClass) {
|
||||
CapabilityManager.INSTANCE.register(capClass, new Capability.IStorage<T>() {
|
||||
@Nullable
|
||||
@Override
|
||||
public INBT writeNBT(Capability<T> capability, T instance, Direction side) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readNBT(Capability<T> capability, T instance, Direction side, INBT nbt) {
|
||||
|
||||
}
|
||||
}, () -> null);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,22 +2,32 @@ package de.ellpeck.prettypipes;
|
|||
|
||||
import de.ellpeck.prettypipes.items.IModule;
|
||||
import de.ellpeck.prettypipes.network.PipeItem;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.entity.player.ServerPlayerEntity;
|
||||
import net.minecraft.inventory.ISidedInventory;
|
||||
import net.minecraft.inventory.ISidedInventoryProvider;
|
||||
import net.minecraft.inventory.InventoryHelper;
|
||||
import net.minecraft.inventory.container.Container;
|
||||
import net.minecraft.inventory.container.Slot;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraft.nbt.ListNBT;
|
||||
import net.minecraft.network.play.server.SUpdateTileEntityPacket;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.ChunkPos;
|
||||
import net.minecraft.util.text.*;
|
||||
import net.minecraft.world.IBlockReader;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.server.ServerWorld;
|
||||
import net.minecraftforge.common.util.INBTSerializable;
|
||||
import net.minecraftforge.items.IItemHandler;
|
||||
import net.minecraftforge.items.wrapper.SidedInvWrapper;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
@ -25,10 +35,11 @@ import java.util.Collection;
|
|||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.IntStream;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public final class Utility {
|
||||
|
||||
public static <T extends TileEntity> T getTileEntity(Class<T> type, World world, BlockPos pos) {
|
||||
public static <T extends TileEntity> T getTileEntity(Class<T> type, IBlockReader world, BlockPos pos) {
|
||||
TileEntity tile = world.getTileEntity(pos);
|
||||
return type.isInstance(tile) ? (T) tile : null;
|
||||
}
|
||||
|
@ -107,13 +118,34 @@ public final class Utility {
|
|||
return list;
|
||||
}
|
||||
|
||||
public static void sendTileEntityToClients(TileEntity tile) {
|
||||
ServerWorld world = (ServerWorld) tile.getWorld();
|
||||
Stream<ServerPlayerEntity> entities = world.getChunkProvider().chunkManager.getTrackingPlayers(new ChunkPos(tile.getPos()), false);
|
||||
SUpdateTileEntityPacket packet = new SUpdateTileEntityPacket(tile.getPos(), -1, tile.write(new CompoundNBT()));
|
||||
entities.forEach(e -> e.connection.sendPacket(packet));
|
||||
}
|
||||
|
||||
public static <T extends INBTSerializable<CompoundNBT>> List<T> deserializeAll(ListNBT list, Function<CompoundNBT, T> supplier) {
|
||||
List<T> items = new ArrayList<>();
|
||||
for (int i = 0; i < list.size(); i++)
|
||||
items.add(supplier.apply(list.getCompound(i)));
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
T item = supplier.apply(list.getCompound(i));
|
||||
if (item != null)
|
||||
items.add(item);
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
public static IItemHandler getBlockItemHandler(World world, BlockPos pos, Direction direction) {
|
||||
BlockState state = world.getBlockState(pos);
|
||||
Block block = state.getBlock();
|
||||
if (!(block instanceof ISidedInventoryProvider))
|
||||
return null;
|
||||
ISidedInventory inventory = ((ISidedInventoryProvider) block).createInventory(state, world, pos);
|
||||
if (inventory == null)
|
||||
return null;
|
||||
return new SidedInvWrapper(inventory, direction);
|
||||
}
|
||||
|
||||
public interface IMergeItemStack {
|
||||
boolean mergeItemStack(ItemStack stack, int startIndex, int endIndex, boolean reverseDirection);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
package de.ellpeck.prettypipes.compat.jei;
|
||||
|
||||
import de.ellpeck.prettypipes.misc.ItemEqualityType;
|
||||
import de.ellpeck.prettypipes.packets.PacketCraftingModuleTransfer;
|
||||
import de.ellpeck.prettypipes.packets.PacketHandler;
|
||||
import de.ellpeck.prettypipes.pipe.modules.craft.CraftingModuleContainer;
|
||||
import mezz.jei.api.gui.IRecipeLayout;
|
||||
import mezz.jei.api.gui.ingredient.IGuiIngredient;
|
||||
import mezz.jei.api.recipe.transfer.IRecipeTransferError;
|
||||
import mezz.jei.api.recipe.transfer.IRecipeTransferHandler;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class CraftingModuleTransferHandler implements IRecipeTransferHandler<CraftingModuleContainer> {
|
||||
@Override
|
||||
public Class<CraftingModuleContainer> getContainerClass() {
|
||||
return CraftingModuleContainer.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IRecipeTransferError transferRecipe(CraftingModuleContainer container, IRecipeLayout recipeLayout, PlayerEntity player, boolean maxTransfer, boolean doTransfer) {
|
||||
if (!doTransfer)
|
||||
return null;
|
||||
Map<Integer, ? extends IGuiIngredient<ItemStack>> ings = recipeLayout.getItemStacks().getGuiIngredients();
|
||||
List<ItemStack> inputs = new ArrayList<>();
|
||||
List<ItemStack> outputs = new ArrayList<>();
|
||||
for (Map.Entry<Integer, ? extends IGuiIngredient<ItemStack>> entry : ings.entrySet()) {
|
||||
List<ItemStack> allIngredients = entry.getValue().getAllIngredients();
|
||||
if (allIngredients.isEmpty())
|
||||
continue;
|
||||
ItemStack remain = allIngredients.get(0).copy();
|
||||
List<ItemStack> toAdd = entry.getValue().isInput() ? inputs : outputs;
|
||||
for (ItemStack stack : toAdd) {
|
||||
if (ItemEqualityType.compareItems(stack, remain)) {
|
||||
int fits = Math.min(stack.getMaxStackSize() - stack.getCount(), remain.getCount());
|
||||
stack.grow(fits);
|
||||
remain.shrink(fits);
|
||||
if (remain.isEmpty())
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!remain.isEmpty())
|
||||
toAdd.add(remain);
|
||||
}
|
||||
PacketHandler.sendToServer(new PacketCraftingModuleTransfer(inputs, outputs));
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -2,19 +2,25 @@ package de.ellpeck.prettypipes.compat.jei;
|
|||
|
||||
import de.ellpeck.prettypipes.PrettyPipes;
|
||||
import de.ellpeck.prettypipes.misc.PlayerPrefs;
|
||||
import de.ellpeck.prettypipes.terminal.containers.CraftingTerminalGui;
|
||||
import de.ellpeck.prettypipes.terminal.containers.ItemTerminalGui;
|
||||
import mezz.jei.api.IModPlugin;
|
||||
import mezz.jei.api.JeiPlugin;
|
||||
import mezz.jei.api.constants.VanillaRecipeCategoryUid;
|
||||
import mezz.jei.api.gui.handlers.IGuiContainerHandler;
|
||||
import mezz.jei.api.registration.IGuiHandlerRegistration;
|
||||
import mezz.jei.api.registration.IRecipeTransferRegistration;
|
||||
import mezz.jei.api.runtime.IIngredientFilter;
|
||||
import mezz.jei.api.runtime.IJeiRuntime;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
import net.minecraft.client.gui.widget.button.Button;
|
||||
import net.minecraft.client.renderer.Rectangle2d;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.text.StringTextComponent;
|
||||
import net.minecraft.util.text.TextFormatting;
|
||||
import net.minecraft.util.text.TranslationTextComponent;
|
||||
import net.minecraftforge.client.event.GuiScreenEvent;
|
||||
import net.minecraftforge.client.event.GuiScreenEvent.DrawScreenEvent;
|
||||
import net.minecraftforge.client.event.GuiScreenEvent.InitGuiEvent;
|
||||
|
@ -24,6 +30,9 @@ import net.minecraftforge.event.TickEvent.ClientTickEvent;
|
|||
import net.minecraftforge.event.world.PistonEvent;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
@JeiPlugin
|
||||
|
@ -51,6 +60,23 @@ public class JEIPrettyPipesPlugin implements IModPlugin {
|
|||
@Override
|
||||
public void registerRecipeTransferHandlers(IRecipeTransferRegistration registration) {
|
||||
registration.addRecipeTransferHandler(new CraftingTerminalTransferHandler(), VanillaRecipeCategoryUid.CRAFTING);
|
||||
registration.addUniversalRecipeTransferHandler(new CraftingModuleTransferHandler());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerGuiHandlers(IGuiHandlerRegistration registration) {
|
||||
registration.addGuiContainerHandler(ItemTerminalGui.class, new IGuiContainerHandler<ItemTerminalGui>() {
|
||||
@Override
|
||||
public List<Rectangle2d> getGuiExtraAreas(ItemTerminalGui containerScreen) {
|
||||
List<Rectangle2d> ret = new ArrayList<>();
|
||||
// sorting buttons
|
||||
ret.add(new Rectangle2d(containerScreen.getGuiLeft() - 22, containerScreen.getGuiTop(), 22, 64));
|
||||
// crafting hud
|
||||
if (containerScreen.currentlyCrafting != null && !containerScreen.currentlyCrafting.isEmpty())
|
||||
ret.add(new Rectangle2d(containerScreen.getGuiLeft() + containerScreen.getXSize(), containerScreen.getGuiTop() + 4, 65, 89));
|
||||
return ret;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
|
|
|
@ -18,10 +18,7 @@ import net.minecraft.network.PacketBuffer;
|
|||
import net.minecraft.network.datasync.DataParameter;
|
||||
import net.minecraft.network.datasync.DataSerializers;
|
||||
import net.minecraft.network.datasync.EntityDataManager;
|
||||
import net.minecraft.util.DamageSource;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.SoundEvents;
|
||||
import net.minecraft.util.*;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.RayTraceResult;
|
||||
import net.minecraft.world.GameRules;
|
||||
|
|
|
@ -31,12 +31,12 @@ public class PipeFrameRenderer extends ItemFrameRenderer {
|
|||
|
||||
FontRenderer font = this.getFontRendererFromRenderManager();
|
||||
int amount = ((PipeFrameEntity) entityIn).getAmount();
|
||||
String ammountStrg = amount < 0 ? "?" : String.valueOf(amount);
|
||||
float x = 0.5F - font.getStringWidth(ammountStrg) / 2F;
|
||||
Matrix4f matrix4f = matrixStackIn.getLast().getPositionMatrix();
|
||||
String amountStr = amount < 0 ? "?" : String.valueOf(amount);
|
||||
float x = 0.5F - font.getStringWidth(amountStr) / 2F;
|
||||
Matrix4f matrix4f = matrixStackIn.getLast().getMatrix();
|
||||
matrixStackIn.translate(0, 0.285F, 0.415F);
|
||||
matrixStackIn.scale(-0.02F, -0.02F, 0.02F);
|
||||
font.renderString(ammountStrg, x, 0, 0xFFFFFF, true, matrix4f, bufferIn, false, 0, packedLightIn);
|
||||
font.renderString(amountStr, x, 0, 0xFFFFFF, true, matrix4f, bufferIn, false, 0, packedLightIn);
|
||||
|
||||
matrixStackIn.pop();
|
||||
}
|
||||
|
|
|
@ -1,12 +1,16 @@
|
|||
package de.ellpeck.prettypipes.items;
|
||||
|
||||
import de.ellpeck.prettypipes.pipe.containers.AbstractPipeContainer;
|
||||
import de.ellpeck.prettypipes.pipe.PipeTileEntity;
|
||||
import de.ellpeck.prettypipes.pipe.containers.AbstractPipeContainer;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.entity.player.PlayerInventory;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraftforge.items.IItemHandler;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public interface IModule {
|
||||
|
||||
void tick(ItemStack module, PipeTileEntity tile);
|
||||
|
@ -28,4 +32,10 @@ public interface IModule {
|
|||
float getItemSpeedIncrease(ItemStack module, PipeTileEntity tile);
|
||||
|
||||
boolean canPipeWork(ItemStack module, PipeTileEntity tile);
|
||||
|
||||
List<ItemStack> getAllCraftables(ItemStack module, PipeTileEntity tile);
|
||||
|
||||
int getCraftableAmount(ItemStack module, PipeTileEntity tile, Consumer<ItemStack> unavailableConsumer, ItemStack stack);
|
||||
|
||||
ItemStack craft(ItemStack module, PipeTileEntity tile, BlockPos destPipe, Consumer<ItemStack> unavailableConsumer, ItemStack stack);
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package de.ellpeck.prettypipes.items;
|
|||
|
||||
import de.ellpeck.prettypipes.Registry;
|
||||
import de.ellpeck.prettypipes.Utility;
|
||||
import de.ellpeck.prettypipes.misc.ItemEqualityType;
|
||||
import de.ellpeck.prettypipes.pipe.containers.AbstractPipeContainer;
|
||||
import de.ellpeck.prettypipes.pipe.PipeTileEntity;
|
||||
import net.minecraft.client.util.ITooltipFlag;
|
||||
|
@ -9,6 +10,7 @@ import net.minecraft.entity.player.PlayerEntity;
|
|||
import net.minecraft.entity.player.PlayerInventory;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.text.*;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
|
@ -16,7 +18,9 @@ import net.minecraftforge.api.distmarker.OnlyIn;
|
|||
import net.minecraftforge.items.IItemHandler;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public abstract class ModuleItem extends Item implements IModule {
|
||||
|
||||
|
@ -73,4 +77,19 @@ public abstract class ModuleItem extends Item implements IModule {
|
|||
public boolean canPipeWork(ItemStack module, PipeTileEntity tile) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ItemStack> getAllCraftables(ItemStack module, PipeTileEntity tile) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCraftableAmount(ItemStack module, PipeTileEntity tile, Consumer<ItemStack> unavailableConsumer, ItemStack stack) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack craft(ItemStack module, PipeTileEntity tile, BlockPos destPipe, Consumer<ItemStack> unavailableConsumer, ItemStack stack) {
|
||||
return stack;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,13 +1,17 @@
|
|||
package de.ellpeck.prettypipes.items;
|
||||
|
||||
import de.ellpeck.prettypipes.Registry;
|
||||
import de.ellpeck.prettypipes.pipe.PipeBlock;
|
||||
import de.ellpeck.prettypipes.Utility;
|
||||
import de.ellpeck.prettypipes.pipe.ConnectionType;
|
||||
import de.ellpeck.prettypipes.pipe.PipeBlock;
|
||||
import de.ellpeck.prettypipes.pipe.PipeTileEntity;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.ItemUseContext;
|
||||
import net.minecraft.client.util.ITooltipFlag;
|
||||
import net.minecraft.enchantment.Enchantment;
|
||||
import net.minecraft.enchantment.Enchantments;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.*;
|
||||
import net.minecraft.state.EnumProperty;
|
||||
import net.minecraft.util.ActionResultType;
|
||||
import net.minecraft.util.Direction;
|
||||
|
@ -16,11 +20,14 @@ import net.minecraft.util.SoundEvents;
|
|||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.shapes.VoxelShape;
|
||||
import net.minecraft.util.text.ITextComponent;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class WrenchItem extends Item {
|
||||
|
||||
public WrenchItem() {
|
||||
super(new Item.Properties().maxStackSize(1).group(Registry.GROUP));
|
||||
}
|
||||
|
@ -29,20 +36,56 @@ public class WrenchItem extends Item {
|
|||
public ActionResultType onItemUse(ItemUseContext context) {
|
||||
World world = context.getWorld();
|
||||
BlockPos pos = context.getPos();
|
||||
PlayerEntity player = context.getPlayer();
|
||||
BlockState state = world.getBlockState(pos);
|
||||
if (!(state.getBlock() instanceof PipeBlock))
|
||||
return ActionResultType.PASS;
|
||||
PipeTileEntity tile = Utility.getTileEntity(PipeTileEntity.class, world, pos);
|
||||
if (tile == null)
|
||||
return ActionResultType.FAIL;
|
||||
if (player == null)
|
||||
return ActionResultType.FAIL;
|
||||
|
||||
if (context.getPlayer().isShiftKeyDown()) {
|
||||
if (player.isSneaking()) {
|
||||
if (!world.isRemote) {
|
||||
Block.spawnDrops(state, world, pos, world.getTileEntity(pos), null, ItemStack.EMPTY);
|
||||
if (tile.cover != null) {
|
||||
// remove the cover
|
||||
tile.removeCover(player, context.getHand());
|
||||
Utility.sendTileEntityToClients(tile);
|
||||
} else {
|
||||
// remove the pipe
|
||||
Block.spawnDrops(state, world, pos, tile, null, ItemStack.EMPTY);
|
||||
world.removeBlock(pos, false);
|
||||
}
|
||||
world.playSound(null, pos, SoundEvents.ENTITY_ITEM_FRAME_REMOVE_ITEM, SoundCategory.PLAYERS, 1, 1);
|
||||
world.removeBlock(pos, false);
|
||||
return ActionResultType.CONSUME;
|
||||
} else {
|
||||
return ActionResultType.SUCCESS;
|
||||
}
|
||||
return ActionResultType.SUCCESS;
|
||||
}
|
||||
|
||||
// Blocking
|
||||
// placing covers
|
||||
if (tile.cover == null) {
|
||||
ItemStack offhand = player.getHeldItemOffhand();
|
||||
if (offhand.getItem() instanceof BlockItem) {
|
||||
if (!world.isRemote) {
|
||||
BlockItemUseContext blockContext = new BlockItemUseContext(context);
|
||||
Block block = ((BlockItem) offhand.getItem()).getBlock();
|
||||
BlockState cover = block.getStateForPlacement(blockContext);
|
||||
if (cover != null && !block.hasTileEntity(cover)) {
|
||||
tile.cover = cover;
|
||||
Utility.sendTileEntityToClients(tile);
|
||||
offhand.shrink(1);
|
||||
world.playSound(null, pos, SoundEvents.ENTITY_ITEM_FRAME_ADD_ITEM, SoundCategory.PLAYERS, 1, 1);
|
||||
}
|
||||
return ActionResultType.CONSUME;
|
||||
} else {
|
||||
return ActionResultType.SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// disabling directions
|
||||
for (Map.Entry<Direction, VoxelShape> entry : PipeBlock.DIR_SHAPES.entrySet()) {
|
||||
AxisAlignedBB box = entry.getValue().getBoundingBox().offset(pos).grow(0.001F);
|
||||
if (!box.contains(context.getHitVec()))
|
||||
|
@ -65,9 +108,31 @@ public class WrenchItem extends Item {
|
|||
world.setBlockState(pos, newState);
|
||||
PipeBlock.onStateChanged(world, pos, newState);
|
||||
world.playSound(null, pos, SoundEvents.ENTITY_ITEM_FRAME_ROTATE_ITEM, SoundCategory.PLAYERS, 1, 1);
|
||||
return ActionResultType.CONSUME;
|
||||
} else {
|
||||
return ActionResultType.SUCCESS;
|
||||
}
|
||||
return ActionResultType.SUCCESS;
|
||||
}
|
||||
return ActionResultType.PASS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addInformation(ItemStack stack, World worldIn, List<ITextComponent> tooltip, ITooltipFlag flagIn) {
|
||||
Utility.addTooltip(this.getRegistryName().getPath(), tooltip);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnchantable(ItemStack stack) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemEnchantability(ItemStack stack) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canApplyAtEnchantingTable(ItemStack stack, Enchantment enchantment) {
|
||||
return enchantment == Enchantments.SILK_TOUCH;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,8 +8,12 @@ import net.minecraftforge.items.IItemHandler;
|
|||
import net.minecraftforge.items.SlotItemHandler;
|
||||
|
||||
public class FilterSlot extends SlotItemHandler {
|
||||
public FilterSlot(IItemHandler itemHandler, int index, int xPosition, int yPosition) {
|
||||
|
||||
private final boolean onlyOneItem;
|
||||
|
||||
public FilterSlot(IItemHandler itemHandler, int index, int xPosition, int yPosition, boolean onlyOneItem) {
|
||||
super(itemHandler, index, xPosition, yPosition);
|
||||
this.onlyOneItem = onlyOneItem;
|
||||
}
|
||||
|
||||
public static boolean checkFilter(Container container, int slotId, PlayerEntity player) {
|
||||
|
@ -31,7 +35,8 @@ public class FilterSlot extends SlotItemHandler {
|
|||
this.putStack(ItemStack.EMPTY);
|
||||
} else if (!heldStack.isEmpty()) {
|
||||
ItemStack s = heldStack.copy();
|
||||
s.setCount(1);
|
||||
if (this.onlyOneItem)
|
||||
s.setCount(1);
|
||||
this.putStack(s);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,8 @@ public enum ItemEqualityType {
|
|||
if (filterTags.isEmpty())
|
||||
return false;
|
||||
return stackTags.containsAll(filterTags);
|
||||
}, true);
|
||||
}, true),
|
||||
MOD((stack, filter) -> stack.getItem().getCreatorModId(stack).equals(filter.getItem().getCreatorModId(filter)), true);
|
||||
|
||||
public final BiFunction<ItemStack, ItemStack, Boolean> filter;
|
||||
public final boolean ignoreItemEquality;
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
package de.ellpeck.prettypipes.misc;
|
||||
|
||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||
import de.ellpeck.prettypipes.PrettyPipes;
|
||||
import de.ellpeck.prettypipes.packets.PacketButton;
|
||||
import de.ellpeck.prettypipes.pipe.PipeTileEntity;
|
||||
import de.ellpeck.prettypipes.pipe.modules.FilterModifierModule;
|
||||
import de.ellpeck.prettypipes.pipe.modules.FilterModifierModuleItem;
|
||||
import de.ellpeck.prettypipes.pipe.modules.filter.FilterIncreaseModuleItem;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
import net.minecraft.client.gui.widget.Widget;
|
||||
import net.minecraft.client.gui.widget.button.Button;
|
||||
|
@ -13,6 +15,7 @@ import net.minecraft.item.ItemStack;
|
|||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.text.TextFormatting;
|
||||
import net.minecraft.util.text.TranslationTextComponent;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
import net.minecraftforge.items.IItemHandler;
|
||||
|
@ -46,7 +49,7 @@ public class ItemFilter extends ItemStackHandler {
|
|||
public List<Slot> getSlots(int x, int y) {
|
||||
List<Slot> slots = new ArrayList<>();
|
||||
for (int i = 0; i < this.getSlots(); i++)
|
||||
slots.add(new FilterSlot(this, i, x + i % 9 * 18, y + i / 9 * 18));
|
||||
slots.add(new FilterSlot(this, i, x + i % 9 * 18, y + i / 9 * 18, true));
|
||||
return slots;
|
||||
}
|
||||
|
||||
|
@ -75,10 +78,12 @@ public class ItemFilter extends ItemStackHandler {
|
|||
if (id == 0 && this.canModifyWhitelist) {
|
||||
this.isWhitelist = !this.isWhitelist;
|
||||
this.modified = true;
|
||||
this.save();
|
||||
} else if (id == 1 && this.canPopulateFromInventories) {
|
||||
// populate filter from inventories
|
||||
List<ItemFilter> filters = this.getAllFilters();
|
||||
for (Direction direction : Direction.values()) {
|
||||
IItemHandler handler = this.pipe.getItemHandler(direction, null);
|
||||
IItemHandler handler = this.pipe.getItemHandler(direction);
|
||||
if (handler == null)
|
||||
continue;
|
||||
for (int i = 0; i < handler.getSlots(); i++) {
|
||||
|
@ -87,12 +92,16 @@ public class ItemFilter extends ItemStackHandler {
|
|||
continue;
|
||||
ItemStack copy = stack.copy();
|
||||
copy.setCount(1);
|
||||
ItemHandlerHelper.insertItem(this, copy, false);
|
||||
// try inserting into ourselves and any filter increase modifiers
|
||||
for (ItemFilter filter : filters) {
|
||||
if (ItemHandlerHelper.insertItem(filter, copy, false).isEmpty()) {
|
||||
filter.save();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
this.modified = true;
|
||||
}
|
||||
this.save();
|
||||
}
|
||||
|
||||
public boolean isAllowed(ItemStack stack) {
|
||||
|
@ -100,23 +109,28 @@ public class ItemFilter extends ItemStackHandler {
|
|||
}
|
||||
|
||||
private boolean isFiltered(ItemStack stack) {
|
||||
ItemEqualityType[] types = this.getEqualityTypes();
|
||||
for (int i = 0; i < this.getSlots(); i++) {
|
||||
ItemStack filter = this.getStackInSlot(i);
|
||||
if (filter.isEmpty())
|
||||
continue;
|
||||
if (ItemEqualityType.compareItems(stack, filter, types))
|
||||
return true;
|
||||
ItemEqualityType[] types = getEqualityTypes(this.pipe);
|
||||
// also check if any filter increase modules have the item we need
|
||||
for (ItemStackHandler handler : this.getAllFilters()) {
|
||||
for (int i = 0; i < handler.getSlots(); i++) {
|
||||
ItemStack filter = handler.getStackInSlot(i);
|
||||
if (filter.isEmpty())
|
||||
continue;
|
||||
if (ItemEqualityType.compareItems(stack, filter, types))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public ItemEqualityType[] getEqualityTypes() {
|
||||
return this.pipe.streamModules()
|
||||
.map(Pair::getRight)
|
||||
.filter(m -> m instanceof FilterModifierModule)
|
||||
.map(m -> ((FilterModifierModule) m).type)
|
||||
.toArray(ItemEqualityType[]::new);
|
||||
private List<ItemFilter> getAllFilters() {
|
||||
List<ItemFilter> filters = this.pipe.streamModules()
|
||||
.filter(p -> p.getRight() instanceof FilterIncreaseModuleItem)
|
||||
.map(p -> new ItemFilter(18, p.getLeft(), this.pipe))
|
||||
.collect(Collectors.toList());
|
||||
// add ourselves to the front
|
||||
filters.add(0, this);
|
||||
return filters;
|
||||
}
|
||||
|
||||
public void save() {
|
||||
|
@ -129,14 +143,16 @@ public class ItemFilter extends ItemStackHandler {
|
|||
@Override
|
||||
public CompoundNBT serializeNBT() {
|
||||
CompoundNBT nbt = super.serializeNBT();
|
||||
nbt.putBoolean("whitelist", this.isWhitelist);
|
||||
if (this.canModifyWhitelist)
|
||||
nbt.putBoolean("whitelist", this.isWhitelist);
|
||||
return nbt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserializeNBT(CompoundNBT nbt) {
|
||||
super.deserializeNBT(nbt);
|
||||
this.isWhitelist = nbt.getBoolean("whitelist");
|
||||
if (this.canModifyWhitelist)
|
||||
this.isWhitelist = nbt.getBoolean("whitelist");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -144,6 +160,14 @@ public class ItemFilter extends ItemStackHandler {
|
|||
this.modified = true;
|
||||
}
|
||||
|
||||
public static ItemEqualityType[] getEqualityTypes(PipeTileEntity pipe) {
|
||||
return pipe.streamModules()
|
||||
.map(Pair::getRight)
|
||||
.filter(m -> m instanceof FilterModifierModuleItem)
|
||||
.map(m -> ((FilterModifierModuleItem) m).type)
|
||||
.toArray(ItemEqualityType[]::new);
|
||||
}
|
||||
|
||||
public interface IFilteredContainer {
|
||||
ItemFilter getFilter();
|
||||
}
|
||||
|
|
|
@ -6,8 +6,8 @@ import java.util.Comparator;
|
|||
|
||||
public enum ItemOrder {
|
||||
AMOUNT(Comparator.comparingInt(ItemStack::getCount)),
|
||||
NAME(Comparator.comparing(s -> s.getDisplayName().getFormattedText())),
|
||||
MOD(Comparator.comparing(s -> s.getItem().getRegistryName().getNamespace()));
|
||||
NAME(Comparator.comparing(s -> s.getDisplayName().getString())),
|
||||
MOD(Comparator.comparing(s -> s.getItem().getCreatorModId(s)));
|
||||
|
||||
public final Comparator<ItemStack> comparator;
|
||||
|
||||
|
|
|
@ -10,8 +10,12 @@ import net.minecraft.client.gui.widget.Widget;
|
|||
import net.minecraft.client.renderer.ItemRenderer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.text.ITextComponent;
|
||||
import net.minecraft.util.text.StringTextComponent;
|
||||
import net.minecraft.util.text.TextComponent;
|
||||
import net.minecraft.util.text.TextFormatting;
|
||||
import net.minecraftforge.fml.client.gui.GuiUtils;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
@ -23,6 +27,7 @@ public class ItemTerminalWidget extends Widget {
|
|||
public final int gridY;
|
||||
public boolean selected;
|
||||
public ItemStack stack = ItemStack.EMPTY;
|
||||
public boolean craftable;
|
||||
|
||||
public ItemTerminalWidget(int xIn, int yIn, int gridX, int gridY, ItemTerminalGui screen) {
|
||||
super(xIn, yIn, 16, 16, "");
|
||||
|
@ -48,10 +53,12 @@ public class ItemTerminalWidget extends Widget {
|
|||
fill(this.x, this.y, this.x + 16, this.y + 16, -2130706433);
|
||||
RenderSystem.enableDepthTest();
|
||||
renderer.renderItemAndEffectIntoGUI(mc.player, this.stack, this.x, this.y);
|
||||
int amount = this.stack.getCount();
|
||||
int amount = !this.craftable ? this.stack.getCount() : 0;
|
||||
String amountStrg = this.stack.getCount() >= 1000 ? amount / 1000 + "k" : String.valueOf(amount);
|
||||
FontRenderer font = mc.getFontResourceManager().getFontRenderer(FONT);
|
||||
renderer.renderItemOverlayIntoGUI(font, this.stack, this.x, this.y, amountStrg);
|
||||
RenderSystem.pushMatrix();
|
||||
RenderSystem.scalef(0.8F, 0.8F, 1);
|
||||
renderer.renderItemOverlayIntoGUI(mc.fontRenderer, this.stack, (int) (this.x / 0.8F) + 4, (int) (this.y / 0.8F) + 4, amountStrg);
|
||||
RenderSystem.popMatrix();
|
||||
renderer.zLevel = 0;
|
||||
this.setBlitOffset(0);
|
||||
|
||||
|
|
|
@ -55,12 +55,13 @@ public class NetworkLocation implements INBTSerializable<CompoundNBT> {
|
|||
IItemHandler handler = this.getItemHandler(world);
|
||||
if (handler != null) {
|
||||
for (int i = 0; i < handler.getSlots(); i++) {
|
||||
ItemStack found = handler.extractItem(i, Integer.MAX_VALUE, true);
|
||||
if (found.isEmpty())
|
||||
// check if the slot is accessible to us
|
||||
if (handler.extractItem(i, 1, true).isEmpty())
|
||||
continue;
|
||||
if (this.itemCache == null)
|
||||
this.itemCache = new HashMap<>();
|
||||
this.itemCache.put(i, found);
|
||||
// use getStackInSlot since there might be more than 64 items in there
|
||||
this.itemCache.put(i, handler.getStackInSlot(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -71,7 +72,7 @@ public class NetworkLocation implements INBTSerializable<CompoundNBT> {
|
|||
if (this.handlerCache == null) {
|
||||
PipeNetwork network = PipeNetwork.get(world);
|
||||
PipeTileEntity pipe = network.getPipe(this.pipePos);
|
||||
this.handlerCache = pipe.getItemHandler(this.direction, null);
|
||||
this.handlerCache = pipe.getItemHandler(this.direction);
|
||||
}
|
||||
return this.handlerCache;
|
||||
}
|
||||
|
|
|
@ -1,25 +1,37 @@
|
|||
package de.ellpeck.prettypipes.network;
|
||||
|
||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||
import de.ellpeck.prettypipes.PrettyPipes;
|
||||
import de.ellpeck.prettypipes.Utility;
|
||||
import de.ellpeck.prettypipes.pipe.IPipeConnectable;
|
||||
import de.ellpeck.prettypipes.pipe.IPipeItem;
|
||||
import de.ellpeck.prettypipes.pipe.PipeTileEntity;
|
||||
import joptsimple.internal.Strings;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.ILiquidContainer;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.IRenderTypeBuffer;
|
||||
import net.minecraft.client.renderer.model.ItemCameraTransforms;
|
||||
import net.minecraft.entity.item.ItemEntity;
|
||||
import net.minecraft.fluid.Fluid;
|
||||
import net.minecraft.fluid.IFluidState;
|
||||
import net.minecraft.fluid.FluidState;
|
||||
import net.minecraft.item.BlockItem;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraft.nbt.ListNBT;
|
||||
import net.minecraft.nbt.NBTUtil;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.IBlockReader;
|
||||
import net.minecraft.world.IWorld;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
import net.minecraftforge.common.util.Constants;
|
||||
import net.minecraftforge.common.util.INBTSerializable;
|
||||
import net.minecraftforge.items.CapabilityItemHandler;
|
||||
|
@ -28,12 +40,13 @@ import net.minecraftforge.items.ItemHandlerHelper;
|
|||
import org.jgrapht.Graph;
|
||||
import org.jgrapht.GraphPath;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class PipeItem implements INBTSerializable<CompoundNBT>, ILiquidContainer {
|
||||
public class PipeItem implements IPipeItem {
|
||||
|
||||
public static final ResourceLocation TYPE = new ResourceLocation(PrettyPipes.ID, "pipe_item");
|
||||
|
||||
public ItemStack stack;
|
||||
public float speed;
|
||||
|
@ -51,17 +64,30 @@ public class PipeItem implements INBTSerializable<CompoundNBT>, ILiquidContainer
|
|||
protected int currentTile;
|
||||
protected boolean retryOnObstruction;
|
||||
protected long lastWorldTick;
|
||||
protected ResourceLocation type;
|
||||
|
||||
public PipeItem(ItemStack stack, float speed) {
|
||||
public PipeItem(ResourceLocation type, ItemStack stack, float speed) {
|
||||
this.type = type;
|
||||
this.stack = stack;
|
||||
this.speed = speed;
|
||||
}
|
||||
|
||||
public PipeItem(CompoundNBT nbt) {
|
||||
public PipeItem(ItemStack stack, float speed) {
|
||||
this(TYPE, stack, speed);
|
||||
}
|
||||
|
||||
public PipeItem(ResourceLocation type, CompoundNBT nbt) {
|
||||
this.type = type;
|
||||
this.path = new ArrayList<>();
|
||||
this.deserializeNBT(nbt);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getContent() {
|
||||
return this.stack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDestination(BlockPos startInventory, BlockPos destInventory, GraphPath<BlockPos, NetworkEdge> path) {
|
||||
this.startInventory = startInventory;
|
||||
this.destInventory = destInventory;
|
||||
|
@ -77,6 +103,7 @@ public class PipeItem implements INBTSerializable<CompoundNBT>, ILiquidContainer
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateInPipe(PipeTileEntity currPipe) {
|
||||
// this prevents pipes being updated after one another
|
||||
// causing an item that just switched to tick twice
|
||||
|
@ -85,72 +112,78 @@ public class PipeItem implements INBTSerializable<CompoundNBT>, ILiquidContainer
|
|||
return;
|
||||
this.lastWorldTick = worldTick;
|
||||
|
||||
float currSpeed = this.speed;
|
||||
BlockPos myPos = new BlockPos(this.x, this.y, this.z);
|
||||
if (!myPos.equals(currPipe.getPos()) && (currPipe.getPos().equals(this.getDestPipe()) || !myPos.equals(this.startInventory))) {
|
||||
// we're done with the current pipe, so switch to the next one
|
||||
currPipe.getItems().remove(this);
|
||||
PipeTileEntity next = this.getNextTile(currPipe, true);
|
||||
if (next == null) {
|
||||
if (!currPipe.getWorld().isRemote) {
|
||||
if (currPipe.getPos().equals(this.getDestPipe())) {
|
||||
// ..or store in our destination container if we reached our destination
|
||||
this.stack = this.store(currPipe);
|
||||
if (!this.stack.isEmpty())
|
||||
this.onPathObstructed(currPipe, true);
|
||||
} else {
|
||||
this.onPathObstructed(currPipe, false);
|
||||
}
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
next.getItems().add(this);
|
||||
}
|
||||
} else {
|
||||
double dist = new Vec3d(this.currGoalPos).squareDistanceTo(this.x - 0.5F, this.y - 0.5F, this.z - 0.5F);
|
||||
if (dist < this.speed * this.speed) {
|
||||
// we're past the start of the pipe, so move to the center of the next pipe
|
||||
BlockPos nextPos;
|
||||
PipeTileEntity next = this.getNextTile(currPipe, false);
|
||||
float motionLeft = this.speed;
|
||||
while (motionLeft > 0) {
|
||||
float currSpeed = Math.min(0.25F, motionLeft);
|
||||
motionLeft -= currSpeed;
|
||||
|
||||
BlockPos myPos = new BlockPos(this.x, this.y, this.z);
|
||||
if (!myPos.equals(currPipe.getPos()) && (currPipe.getPos().equals(this.getDestPipe()) || !myPos.equals(this.startInventory))) {
|
||||
// we're done with the current pipe, so switch to the next one
|
||||
currPipe.getItems().remove(this);
|
||||
PipeTileEntity next = this.getNextTile(currPipe, true);
|
||||
if (next == null) {
|
||||
if (currPipe.getPos().equals(this.getDestPipe())) {
|
||||
nextPos = this.destInventory;
|
||||
} else {
|
||||
currPipe.getItems().remove(this);
|
||||
if (!currPipe.getWorld().isRemote)
|
||||
if (!currPipe.getWorld().isRemote) {
|
||||
if (currPipe.getPos().equals(this.getDestPipe())) {
|
||||
// ..or store in our destination container if we reached our destination
|
||||
this.stack = this.store(currPipe);
|
||||
if (!this.stack.isEmpty())
|
||||
this.onPathObstructed(currPipe, true);
|
||||
} else {
|
||||
this.onPathObstructed(currPipe, false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
nextPos = next.getPos();
|
||||
next.getItems().add(this);
|
||||
currPipe = next;
|
||||
}
|
||||
float tolerance = 0.001F;
|
||||
if (dist >= tolerance * tolerance) {
|
||||
// when going around corners, we want to move right up to the corner
|
||||
Vec3d motion = new Vec3d(this.x - this.lastX, this.y - this.lastY, this.z - this.lastZ);
|
||||
Vec3d diff = new Vec3d(nextPos.getX() + 0.5F - this.x, nextPos.getY() + 0.5F - this.y, nextPos.getZ() + 0.5F - this.z);
|
||||
if (motion.crossProduct(diff).length() >= tolerance) {
|
||||
currSpeed = (float) Math.sqrt(dist);
|
||||
} else {
|
||||
double dist = new Vec3d(this.currGoalPos).squareDistanceTo(this.x - 0.5F, this.y - 0.5F, this.z - 0.5F);
|
||||
if (dist < currSpeed * currSpeed) {
|
||||
// we're past the start of the pipe, so move to the center of the next pipe
|
||||
BlockPos nextPos;
|
||||
PipeTileEntity next = this.getNextTile(currPipe, false);
|
||||
if (next == null) {
|
||||
if (currPipe.getPos().equals(this.getDestPipe())) {
|
||||
nextPos = this.destInventory;
|
||||
} else {
|
||||
currPipe.getItems().remove(this);
|
||||
if (!currPipe.getWorld().isRemote)
|
||||
this.onPathObstructed(currPipe, false);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// we're not going around a corner, so continue
|
||||
nextPos = next.getPos();
|
||||
}
|
||||
float tolerance = 0.001F;
|
||||
if (dist >= tolerance * tolerance) {
|
||||
// when going around corners, we want to move right up to the corner
|
||||
Vec3d motion = new Vec3d(this.x - this.lastX, this.y - this.lastY, this.z - this.lastZ);
|
||||
Vec3d diff = new Vec3d(nextPos.getX() + 0.5F - this.x, nextPos.getY() + 0.5F - this.y, nextPos.getZ() + 0.5F - this.z);
|
||||
if (motion.crossProduct(diff).length() >= tolerance) {
|
||||
currSpeed = (float) Math.sqrt(dist);
|
||||
} else {
|
||||
// we're not going around a corner, so continue
|
||||
this.currGoalPos = nextPos;
|
||||
}
|
||||
} else {
|
||||
// distance is very small, so continue
|
||||
this.currGoalPos = nextPos;
|
||||
}
|
||||
} else {
|
||||
// distance is very small, so continue
|
||||
this.currGoalPos = nextPos;
|
||||
}
|
||||
}
|
||||
|
||||
this.lastX = this.x;
|
||||
this.lastY = this.y;
|
||||
this.lastZ = this.z;
|
||||
|
||||
Vec3d dist = new Vec3d(this.currGoalPos.getX() + 0.5F - this.x, this.currGoalPos.getY() + 0.5F - this.y, this.currGoalPos.getZ() + 0.5F - this.z);
|
||||
dist = dist.normalize();
|
||||
this.x += dist.x * currSpeed;
|
||||
this.y += dist.y * currSpeed;
|
||||
this.z += dist.z * currSpeed;
|
||||
}
|
||||
|
||||
this.lastX = this.x;
|
||||
this.lastY = this.y;
|
||||
this.lastZ = this.z;
|
||||
|
||||
Vec3d dist = new Vec3d(this.currGoalPos.getX() + 0.5F - this.x, this.currGoalPos.getY() + 0.5F - this.y, this.currGoalPos.getZ() + 0.5F - this.z);
|
||||
dist = dist.normalize();
|
||||
this.x += dist.x * currSpeed;
|
||||
this.y += dist.y * currSpeed;
|
||||
this.z += dist.z * currSpeed;
|
||||
}
|
||||
|
||||
protected void onPathObstructed(PipeTileEntity currPipe, boolean tryReturn) {
|
||||
|
@ -159,22 +192,23 @@ public class PipeItem implements INBTSerializable<CompoundNBT>, ILiquidContainer
|
|||
PipeNetwork network = PipeNetwork.get(currPipe.getWorld());
|
||||
if (tryReturn) {
|
||||
// first time: we try to return to our input chest
|
||||
if (!this.retryOnObstruction && network.routeItemToLocation(currPipe.getPos(), this.destInventory, this.getStartPipe(), this.startInventory, speed -> this)) {
|
||||
if (!this.retryOnObstruction && network.routeItemToLocation(currPipe.getPos(), this.destInventory, this.getStartPipe(), this.startInventory, this.stack, speed -> this)) {
|
||||
this.retryOnObstruction = true;
|
||||
return;
|
||||
}
|
||||
// second time: we arrived at our input chest, it is full, so we try to find a different goal location
|
||||
ItemStack remain = network.routeItem(currPipe.getPos(), this.destInventory, this.stack, (stack, speed) -> this, false);
|
||||
if (remain.isEmpty())
|
||||
return;
|
||||
this.stack = remain;
|
||||
if (!remain.isEmpty())
|
||||
this.drop(currPipe.getWorld(), remain.copy());
|
||||
} else {
|
||||
// if all re-routing attempts fail, we drop
|
||||
this.drop(currPipe.getWorld(), this.stack);
|
||||
}
|
||||
// if all re-routing attempts fail, we drop
|
||||
this.drop(currPipe.getWorld());
|
||||
}
|
||||
|
||||
public void drop(World world) {
|
||||
ItemEntity item = new ItemEntity(world, this.x, this.y, this.z, this.stack.copy());
|
||||
@Override
|
||||
public void drop(World world, ItemStack stack) {
|
||||
ItemEntity item = new ItemEntity(world, this.x, this.y, this.z, stack.copy());
|
||||
item.world.addEntity(item);
|
||||
}
|
||||
|
||||
|
@ -182,8 +216,8 @@ public class PipeItem implements INBTSerializable<CompoundNBT>, ILiquidContainer
|
|||
Direction dir = Utility.getDirectionFromOffset(this.destInventory, this.getDestPipe());
|
||||
IPipeConnectable connectable = currPipe.getPipeConnectable(dir);
|
||||
if (connectable != null)
|
||||
return connectable.insertItem(currPipe.getWorld(), currPipe.getPos(), dir, this);
|
||||
IItemHandler handler = currPipe.getItemHandler(dir, this);
|
||||
return connectable.insertItem(currPipe.getPos(), dir, this.stack, false);
|
||||
IItemHandler handler = currPipe.getItemHandler(dir);
|
||||
if (handler != null)
|
||||
return ItemHandlerHelper.insertItemStacked(handler, this.stack, false);
|
||||
return this.stack;
|
||||
|
@ -203,14 +237,17 @@ public class PipeItem implements INBTSerializable<CompoundNBT>, ILiquidContainer
|
|||
return this.path.get(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockPos getDestPipe() {
|
||||
return this.path.get(this.path.size() - 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockPos getCurrentPipe() {
|
||||
return this.path.get(this.currentTile);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockPos getDestInventory() {
|
||||
return this.destInventory;
|
||||
}
|
||||
|
@ -218,6 +255,7 @@ public class PipeItem implements INBTSerializable<CompoundNBT>, ILiquidContainer
|
|||
@Override
|
||||
public CompoundNBT serializeNBT() {
|
||||
CompoundNBT nbt = new CompoundNBT();
|
||||
nbt.putString("type", this.type.toString());
|
||||
nbt.put("stack", this.stack.serializeNBT());
|
||||
nbt.putFloat("speed", this.speed);
|
||||
nbt.put("start_inv", NBTUtil.writeBlockPos(this.startInventory));
|
||||
|
@ -253,6 +291,59 @@ public class PipeItem implements INBTSerializable<CompoundNBT>, ILiquidContainer
|
|||
this.path.add(NBTUtil.readBlockPos(list.getCompound(i)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemsOnTheWay(BlockPos goalInv) {
|
||||
return this.stack.getCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public void render(PipeTileEntity tile, MatrixStack matrixStack, Random random, float partialTicks, int light, int overlay, IRenderTypeBuffer buffer) {
|
||||
matrixStack.translate(
|
||||
MathHelper.lerp(partialTicks, this.lastX, this.x),
|
||||
MathHelper.lerp(partialTicks, this.lastY, this.y),
|
||||
MathHelper.lerp(partialTicks, this.lastZ, this.z));
|
||||
|
||||
if (this.stack.getItem() instanceof BlockItem) {
|
||||
float scale = 0.7F;
|
||||
matrixStack.scale(scale, scale, scale);
|
||||
matrixStack.translate(0, -0.2F, 0);
|
||||
} else {
|
||||
float scale = 0.45F;
|
||||
matrixStack.scale(scale, scale, scale);
|
||||
matrixStack.translate(0, -0.1F, 0);
|
||||
}
|
||||
|
||||
random.setSeed(Item.getIdFromItem(this.stack.getItem()) + this.stack.getDamage());
|
||||
int amount = this.getModelCount();
|
||||
|
||||
for (int i = 0; i < amount; i++) {
|
||||
matrixStack.push();
|
||||
if (amount > 1) {
|
||||
matrixStack.translate(
|
||||
(random.nextFloat() * 2.0F - 1.0F) * 0.25F * 0.5F,
|
||||
(random.nextFloat() * 2.0F - 1.0F) * 0.25F * 0.5F,
|
||||
(random.nextFloat() * 2.0F - 1.0F) * 0.25F * 0.5F);
|
||||
}
|
||||
Minecraft.getInstance().getItemRenderer().renderItem(this.stack, ItemCameraTransforms.TransformType.GROUND, light, overlay, matrixStack, buffer);
|
||||
matrixStack.pop();
|
||||
}
|
||||
}
|
||||
|
||||
protected int getModelCount() {
|
||||
int i = 1;
|
||||
if (this.stack.getCount() > 48) {
|
||||
i = 5;
|
||||
} else if (this.stack.getCount() > 32) {
|
||||
i = 4;
|
||||
} else if (this.stack.getCount() > 16) {
|
||||
i = 3;
|
||||
} else if (this.stack.getCount() > 1) {
|
||||
i = 2;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
protected static List<BlockPos> compilePath(GraphPath<BlockPos, NetworkEdge> path) {
|
||||
Graph<BlockPos, NetworkEdge> graph = path.getGraph();
|
||||
List<BlockPos> ret = new ArrayList<>();
|
||||
|
@ -285,14 +376,4 @@ public class PipeItem implements INBTSerializable<CompoundNBT>, ILiquidContainer
|
|||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canContainFluid(IBlockReader worldIn, BlockPos pos, BlockState state, Fluid fluidIn) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean receiveFluid(IWorld worldIn, BlockPos pos, BlockState state, IFluidState fluidStateIn) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import de.ellpeck.prettypipes.PrettyPipes;
|
|||
import de.ellpeck.prettypipes.Registry;
|
||||
import de.ellpeck.prettypipes.Utility;
|
||||
import de.ellpeck.prettypipes.misc.ItemEqualityType;
|
||||
import de.ellpeck.prettypipes.pipe.IPipeItem;
|
||||
import de.ellpeck.prettypipes.pipe.PipeBlock;
|
||||
import de.ellpeck.prettypipes.pipe.PipeTileEntity;
|
||||
import de.ellpeck.prettypipes.packets.PacketHandler;
|
||||
|
@ -17,16 +18,13 @@ import net.minecraft.nbt.CompoundNBT;
|
|||
import net.minecraft.nbt.ListNBT;
|
||||
import net.minecraft.nbt.NBTUtil;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.Util;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.common.capabilities.Capability;
|
||||
import net.minecraftforge.common.capabilities.ICapabilitySerializable;
|
||||
import net.minecraftforge.common.util.Constants;
|
||||
import net.minecraftforge.common.util.Constants.NBT;
|
||||
import net.minecraftforge.common.util.LazyOptional;
|
||||
import net.minecraftforge.items.IItemHandler;
|
||||
import net.minecraftforge.items.ItemHandlerHelper;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.jgrapht.GraphPath;
|
||||
import org.jgrapht.ListenableGraph;
|
||||
|
@ -43,6 +41,7 @@ import javax.annotation.Nonnull;
|
|||
import javax.annotation.Nullable;
|
||||
import java.util.*;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
@ -53,9 +52,10 @@ public class PipeNetwork implements ICapabilitySerializable<CompoundNBT>, GraphL
|
|||
private final DijkstraShortestPath<BlockPos, NetworkEdge> dijkstra;
|
||||
private final Map<BlockPos, List<BlockPos>> nodeToConnectedNodes = new HashMap<>();
|
||||
private final Map<BlockPos, PipeTileEntity> tileCache = new HashMap<>();
|
||||
private final ListMultimap<BlockPos, PipeItem> pipeItems = ArrayListMultimap.create();
|
||||
private final ListMultimap<BlockPos, IPipeItem> pipeItems = ArrayListMultimap.create();
|
||||
private final ListMultimap<BlockPos, NetworkLock> networkLocks = ArrayListMultimap.create();
|
||||
private final World world;
|
||||
private final LazyOptional<PipeNetwork> lazyThis = LazyOptional.of(() -> this);
|
||||
|
||||
public PipeNetwork(World world) {
|
||||
this.world = world;
|
||||
|
@ -67,7 +67,7 @@ public class PipeNetwork implements ICapabilitySerializable<CompoundNBT>, GraphL
|
|||
@Nonnull
|
||||
@Override
|
||||
public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> cap, @Nullable Direction side) {
|
||||
return cap == Registry.pipeNetworkCapability ? LazyOptional.of(() -> (T) this) : LazyOptional.empty();
|
||||
return cap == Registry.pipeNetworkCapability ? this.lazyThis.cast() : LazyOptional.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -98,7 +98,7 @@ public class PipeNetwork implements ICapabilitySerializable<CompoundNBT>, GraphL
|
|||
ListNBT edges = nbt.getList("edges", NBT.TAG_COMPOUND);
|
||||
for (int i = 0; i < edges.size(); i++)
|
||||
this.addEdge(new NetworkEdge(edges.getCompound(i)));
|
||||
for (PipeItem item : Utility.deserializeAll(nbt.getList("items", NBT.TAG_COMPOUND), PipeItem::new))
|
||||
for (IPipeItem item : Utility.deserializeAll(nbt.getList("items", NBT.TAG_COMPOUND), IPipeItem::load))
|
||||
this.pipeItems.put(item.getCurrentPipe(), item);
|
||||
for (NetworkLock lock : Utility.deserializeAll(nbt.getList("locks", NBT.TAG_COMPOUND), NetworkLock::new))
|
||||
this.createNetworkLock(lock);
|
||||
|
@ -131,11 +131,11 @@ public class PipeNetwork implements ICapabilitySerializable<CompoundNBT>, GraphL
|
|||
}
|
||||
}
|
||||
|
||||
public ItemStack tryInsertItem(BlockPos startPipePos, BlockPos startInventory, ItemStack stack, boolean preventOversending) {
|
||||
public ItemStack routeItem(BlockPos startPipePos, BlockPos startInventory, ItemStack stack, boolean preventOversending) {
|
||||
return this.routeItem(startPipePos, startInventory, stack, PipeItem::new, preventOversending);
|
||||
}
|
||||
|
||||
public ItemStack routeItem(BlockPos startPipePos, BlockPos startInventory, ItemStack stack, BiFunction<ItemStack, Float, PipeItem> itemSupplier, boolean preventOversending) {
|
||||
public ItemStack routeItem(BlockPos startPipePos, BlockPos startInventory, ItemStack stack, BiFunction<ItemStack, Float, IPipeItem> itemSupplier, boolean preventOversending) {
|
||||
if (!this.isNode(startPipePos))
|
||||
return stack;
|
||||
if (!this.world.isBlockLoaded(startPipePos))
|
||||
|
@ -151,8 +151,8 @@ public class PipeNetwork implements ICapabilitySerializable<CompoundNBT>, GraphL
|
|||
Pair<BlockPos, ItemStack> dest = pipe.getAvailableDestination(stack, false, preventOversending);
|
||||
if (dest == null || dest.getLeft().equals(startInventory))
|
||||
continue;
|
||||
Function<Float, PipeItem> sup = speed -> itemSupplier.apply(dest.getRight(), speed);
|
||||
if (this.routeItemToLocation(startPipePos, startInventory, pipe.getPos(), dest.getLeft(), sup)) {
|
||||
Function<Float, IPipeItem> sup = speed -> itemSupplier.apply(dest.getRight(), speed);
|
||||
if (this.routeItemToLocation(startPipePos, startInventory, pipe.getPos(), dest.getLeft(), dest.getRight(), sup)) {
|
||||
ItemStack remain = stack.copy();
|
||||
remain.shrink(dest.getRight().getCount());
|
||||
this.endProfile();
|
||||
|
@ -163,7 +163,7 @@ public class PipeNetwork implements ICapabilitySerializable<CompoundNBT>, GraphL
|
|||
return stack;
|
||||
}
|
||||
|
||||
public boolean routeItemToLocation(BlockPos startPipePos, BlockPos startInventory, BlockPos destPipePos, BlockPos destInventory, Function<Float, PipeItem> itemSupplier) {
|
||||
public boolean routeItemToLocation(BlockPos startPipePos, BlockPos startInventory, BlockPos destPipePos, BlockPos destInventory, ItemStack stack, Function<Float, IPipeItem> itemSupplier) {
|
||||
if (!this.isNode(startPipePos) || !this.isNode(destPipePos))
|
||||
return false;
|
||||
if (!this.world.isBlockLoaded(startPipePos) || !this.world.isBlockLoaded(destPipePos))
|
||||
|
@ -176,39 +176,66 @@ public class PipeNetwork implements ICapabilitySerializable<CompoundNBT>, GraphL
|
|||
this.endProfile();
|
||||
if (path == null)
|
||||
return false;
|
||||
PipeItem item = itemSupplier.apply(startPipe.getItemSpeed());
|
||||
IPipeItem item = itemSupplier.apply(startPipe.getItemSpeed(stack));
|
||||
item.setDestination(startInventory, destInventory, path);
|
||||
if (!startPipe.getItems().contains(item))
|
||||
startPipe.getItems().add(item);
|
||||
startPipe.addNewItem(item);
|
||||
PacketHandler.sendToAllLoaded(this.world, startPipePos, new PacketItemEnterPipe(startPipePos, item));
|
||||
return true;
|
||||
}
|
||||
|
||||
public ItemStack requestItem(BlockPos destPipe, BlockPos destInventory, ItemStack stack, ItemEqualityType... equalityTypes) {
|
||||
List<NetworkLocation> locations = this.getOrderedNetworkItems(destPipe);
|
||||
if (locations.isEmpty())
|
||||
return stack;
|
||||
ItemStack remain = stack.copy();
|
||||
for (NetworkLocation location : locations) {
|
||||
remain = this.requestItem(location, destPipe, destInventory, remain, equalityTypes);
|
||||
// check existing items
|
||||
for (NetworkLocation location : this.getOrderedNetworkItems(destPipe)) {
|
||||
remain = this.requestExistingItem(location, destPipe, destInventory, null, remain, equalityTypes);
|
||||
if (remain.isEmpty())
|
||||
break;
|
||||
return remain;
|
||||
}
|
||||
return remain;
|
||||
// check craftable items
|
||||
return this.requestCraftedItem(destPipe, null, remain, equalityTypes);
|
||||
}
|
||||
|
||||
public ItemStack requestItem(NetworkLocation location, BlockPos destPipe, BlockPos destInventory, ItemStack stack, ItemEqualityType... equalityTypes) {
|
||||
public ItemStack requestCraftedItem(BlockPos destPipe, Consumer<ItemStack> unavailableConsumer, ItemStack stack, ItemEqualityType... equalityTypes) {
|
||||
for (Pair<BlockPos, ItemStack> craftable : this.getAllCraftables(destPipe)) {
|
||||
if (!ItemEqualityType.compareItems(stack, craftable.getRight(), equalityTypes))
|
||||
continue;
|
||||
PipeTileEntity pipe = this.getPipe(craftable.getLeft());
|
||||
if (pipe == null)
|
||||
continue;
|
||||
stack = pipe.craft(destPipe, unavailableConsumer, stack);
|
||||
if (stack.isEmpty())
|
||||
break;
|
||||
}
|
||||
return stack;
|
||||
}
|
||||
|
||||
public ItemStack requestExistingItem(NetworkLocation location, BlockPos destPipe, BlockPos destInventory, NetworkLock ignoredLock, ItemStack stack, ItemEqualityType... equalityTypes) {
|
||||
return this.requestExistingItem(location, destPipe, destInventory, ignoredLock, PipeItem::new, stack, equalityTypes);
|
||||
}
|
||||
|
||||
public ItemStack requestExistingItem(NetworkLocation location, BlockPos destPipe, BlockPos destInventory, NetworkLock ignoredLock, BiFunction<ItemStack, Float, IPipeItem> itemSupplier, ItemStack stack, ItemEqualityType... equalityTypes) {
|
||||
if (location.getPos().equals(destInventory))
|
||||
return stack;
|
||||
// make sure we don't pull any locked items
|
||||
int amount = location.getItemAmount(this.world, stack, equalityTypes);
|
||||
if (amount <= 0)
|
||||
return stack;
|
||||
amount -= this.getLockedAmount(location.getPos(), stack, ignoredLock, equalityTypes);
|
||||
if (amount <= 0)
|
||||
return stack;
|
||||
ItemStack remain = stack.copy();
|
||||
// make sure we only extract less than or equal to the requested amount
|
||||
if (remain.getCount() < amount)
|
||||
amount = remain.getCount();
|
||||
remain.shrink(amount);
|
||||
for (int slot : location.getStackSlots(this.world, stack, equalityTypes)) {
|
||||
// try to extract from that location's inventory and send the item
|
||||
IItemHandler handler = location.getItemHandler(this.world);
|
||||
ItemStack extracted = handler.extractItem(slot, remain.getCount(), true);
|
||||
if (this.routeItemToLocation(location.pipePos, location.getPos(), destPipe, destInventory, speed -> new PipeItem(extracted, speed))) {
|
||||
ItemStack extracted = handler.extractItem(slot, amount, true);
|
||||
if (this.routeItemToLocation(location.pipePos, location.getPos(), destPipe, destInventory, extracted, speed -> itemSupplier.apply(extracted, speed))) {
|
||||
handler.extractItem(slot, extracted.getCount(), false);
|
||||
remain.shrink(extracted.getCount());
|
||||
if (remain.isEmpty())
|
||||
amount -= extracted.getCount();
|
||||
if (amount <= 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -224,6 +251,67 @@ public class PipeNetwork implements ICapabilitySerializable<CompoundNBT>, GraphL
|
|||
return tile;
|
||||
}
|
||||
|
||||
public List<Pair<BlockPos, ItemStack>> getCurrentlyCrafting(BlockPos node) {
|
||||
this.startProfile("get_currently_crafting");
|
||||
List<Pair<BlockPos, ItemStack>> items = new ArrayList<>();
|
||||
for (Pair<BlockPos, ItemStack> craftable : this.getAllCraftables(node)) {
|
||||
PipeTileEntity pipe = this.getPipe(craftable.getLeft());
|
||||
if (pipe == null)
|
||||
continue;
|
||||
for (Pair<BlockPos, ItemStack> request : pipe.craftResultRequests) {
|
||||
BlockPos dest = request.getLeft();
|
||||
ItemStack stack = request.getRight();
|
||||
// add up all the items that should go to the same location
|
||||
Optional<Pair<BlockPos, ItemStack>> existing = items.stream()
|
||||
.filter(s -> s.getLeft().equals(dest) && ItemEqualityType.compareItems(s.getRight(), stack, ItemEqualityType.NBT))
|
||||
.findFirst();
|
||||
if (existing.isPresent()) {
|
||||
existing.get().getRight().grow(stack.getCount());
|
||||
} else {
|
||||
items.add(Pair.of(dest, stack.copy()));
|
||||
}
|
||||
}
|
||||
}
|
||||
this.endProfile();
|
||||
return items;
|
||||
}
|
||||
|
||||
public int getCurrentlyCraftingAmount(BlockPos destNode, ItemStack stack, ItemEqualityType... equalityTypes) {
|
||||
return this.getCurrentlyCrafting(destNode).stream()
|
||||
.filter(p -> p.getLeft().equals(destNode) && ItemEqualityType.compareItems(p.getRight(), stack, equalityTypes))
|
||||
.mapToInt(p -> p.getRight().getCount()).sum();
|
||||
}
|
||||
|
||||
public List<Pair<BlockPos, ItemStack>> getAllCraftables(BlockPos node) {
|
||||
if (!this.isNode(node))
|
||||
return Collections.emptyList();
|
||||
this.startProfile("get_all_craftables");
|
||||
List<Pair<BlockPos, ItemStack>> craftables = new ArrayList<>();
|
||||
for (BlockPos dest : this.getOrderedNetworkNodes(node)) {
|
||||
if (!this.world.isBlockLoaded(dest))
|
||||
continue;
|
||||
PipeTileEntity pipe = this.getPipe(dest);
|
||||
for (ItemStack stack : pipe.getAllCraftables())
|
||||
craftables.add(Pair.of(pipe.getPos(), stack));
|
||||
}
|
||||
this.endProfile();
|
||||
return craftables;
|
||||
}
|
||||
|
||||
public int getCraftableAmount(BlockPos node, Consumer<ItemStack> unavailableConsumer, ItemStack stack, ItemEqualityType... equalityTypes) {
|
||||
int total = 0;
|
||||
for (Pair<BlockPos, ItemStack> pair : this.getAllCraftables(node)) {
|
||||
if (!ItemEqualityType.compareItems(pair.getRight(), stack, equalityTypes))
|
||||
continue;
|
||||
if (!this.world.isBlockLoaded(pair.getLeft()))
|
||||
continue;
|
||||
PipeTileEntity pipe = this.getPipe(pair.getLeft());
|
||||
if (pipe != null)
|
||||
total += pipe.getCraftableAmount(unavailableConsumer, stack);
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
public List<NetworkLocation> getOrderedNetworkItems(BlockPos node) {
|
||||
if (!this.isNode(node))
|
||||
return Collections.emptyList();
|
||||
|
@ -236,11 +324,11 @@ public class PipeNetwork implements ICapabilitySerializable<CompoundNBT>, GraphL
|
|||
if (!pipe.canNetworkSee())
|
||||
continue;
|
||||
for (Direction dir : Direction.values()) {
|
||||
IItemHandler handler = pipe.getItemHandler(dir, null);
|
||||
IItemHandler handler = pipe.getItemHandler(dir);
|
||||
if (handler == null)
|
||||
continue;
|
||||
// check if this handler already exists (double-connected pipes, double chests etc.)
|
||||
if (info.stream().anyMatch(l -> l.getItemHandler(this.world) == handler))
|
||||
if (info.stream().anyMatch(l -> handler.equals(l.getItemHandler(this.world))))
|
||||
continue;
|
||||
NetworkLocation location = new NetworkLocation(dest, dir);
|
||||
if (!location.isEmpty(this.world))
|
||||
|
@ -263,9 +351,9 @@ public class PipeNetwork implements ICapabilitySerializable<CompoundNBT>, GraphL
|
|||
return this.networkLocks.get(pos);
|
||||
}
|
||||
|
||||
public int getLockedAmount(BlockPos pos, ItemStack stack, ItemEqualityType... equalityTypes) {
|
||||
public int getLockedAmount(BlockPos pos, ItemStack stack, NetworkLock ignoredLock, ItemEqualityType... equalityTypes) {
|
||||
return this.getNetworkLocks(pos).stream()
|
||||
.filter(l -> ItemEqualityType.compareItems(l.stack, stack, equalityTypes))
|
||||
.filter(l -> !l.equals(ignoredLock) && ItemEqualityType.compareItems(l.stack, stack, equalityTypes))
|
||||
.mapToInt(l -> l.stack.getCount()).sum();
|
||||
}
|
||||
|
||||
|
@ -352,7 +440,9 @@ public class PipeNetwork implements ICapabilitySerializable<CompoundNBT>, GraphL
|
|||
return null;
|
||||
}
|
||||
|
||||
private List<BlockPos> getOrderedNetworkNodes(BlockPos node) {
|
||||
public List<BlockPos> getOrderedNetworkNodes(BlockPos node) {
|
||||
if (!this.isNode(node))
|
||||
return Collections.emptyList();
|
||||
List<BlockPos> ret = this.nodeToConnectedNodes.get(node);
|
||||
if (ret == null) {
|
||||
this.startProfile("compile_connected_nodes");
|
||||
|
@ -360,6 +450,7 @@ public class PipeNetwork implements ICapabilitySerializable<CompoundNBT>, GraphL
|
|||
// sort destinations first by their priority (eg trash pipes should be last)
|
||||
// and then by their distance from the specified node
|
||||
ret = Streams.stream(new BreadthFirstIterator<>(this.graph, node))
|
||||
.filter(p -> this.getPipe(p) != null)
|
||||
.sorted(Comparator.<BlockPos>comparingInt(p -> this.getPipe(p).getPriority()).reversed().thenComparing(paths::getWeight))
|
||||
.collect(Collectors.toList());
|
||||
this.nodeToConnectedNodes.put(node, ret);
|
||||
|
@ -378,22 +469,21 @@ public class PipeNetwork implements ICapabilitySerializable<CompoundNBT>, GraphL
|
|||
this.endProfile();
|
||||
}
|
||||
|
||||
public List<PipeItem> getItemsInPipe(BlockPos pos) {
|
||||
public List<IPipeItem> getItemsInPipe(BlockPos pos) {
|
||||
return this.pipeItems.get(pos);
|
||||
}
|
||||
|
||||
private Stream<PipeItem> getPipeItemsOnTheWay(BlockPos goalInv) {
|
||||
public Stream<IPipeItem> getPipeItemsOnTheWay(BlockPos goalInv) {
|
||||
this.startProfile("get_pipe_items_on_the_way");
|
||||
Stream<PipeItem> ret = this.pipeItems.values().stream().filter(i -> i.getDestInventory().equals(goalInv));
|
||||
Stream<IPipeItem> ret = this.pipeItems.values().stream().filter(i -> i.getDestInventory().equals(goalInv));
|
||||
this.endProfile();
|
||||
return ret;
|
||||
}
|
||||
|
||||
public int getItemsOnTheWay(BlockPos goalInv, ItemStack type, ItemEqualityType... equalityTypes) {
|
||||
// TODO pending auto-crafting requests should be marked as "on the way" here to allow over-sending prevention
|
||||
return this.getPipeItemsOnTheWay(goalInv)
|
||||
.filter(i -> type == null || ItemEqualityType.compareItems(i.stack, type, equalityTypes))
|
||||
.mapToInt(i -> i.stack.getCount()).sum();
|
||||
.filter(i -> type == null || ItemEqualityType.compareItems(i.getContent(), type, equalityTypes))
|
||||
.mapToInt(i -> i.getItemsOnTheWay(goalInv)).sum();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -113,8 +113,11 @@ public class PacketButton {
|
|||
}),
|
||||
CRAFT_TERMINAL_REQUEST((pos, data, player) -> {
|
||||
CraftingTerminalTileEntity tile = Utility.getTileEntity(CraftingTerminalTileEntity.class, player.world, pos);
|
||||
boolean all = data[0] > 0;
|
||||
tile.requestCraftingItems(player, all);
|
||||
tile.requestCraftingItems(player, data[0]);
|
||||
}),
|
||||
CANCEL_CRAFTING((pos, data, player) -> {
|
||||
ItemTerminalTileEntity tile = Utility.getTileEntity(ItemTerminalTileEntity.class, player.world, pos);
|
||||
tile.cancelCrafting();
|
||||
});
|
||||
|
||||
public final TriConsumer<BlockPos, int[], PlayerEntity> action;
|
||||
|
|
|
@ -0,0 +1,88 @@
|
|||
package de.ellpeck.prettypipes.packets;
|
||||
|
||||
import com.google.common.collect.ArrayListMultimap;
|
||||
import com.google.common.collect.ListMultimap;
|
||||
import de.ellpeck.prettypipes.Utility;
|
||||
import de.ellpeck.prettypipes.misc.FilterSlot;
|
||||
import de.ellpeck.prettypipes.misc.ItemEqualityType;
|
||||
import de.ellpeck.prettypipes.pipe.PipeTileEntity;
|
||||
import de.ellpeck.prettypipes.pipe.modules.craft.CraftingModuleContainer;
|
||||
import de.ellpeck.prettypipes.pipe.modules.craft.CraftingModuleItem;
|
||||
import de.ellpeck.prettypipes.terminal.CraftingTerminalTileEntity;
|
||||
import de.ellpeck.prettypipes.terminal.ItemTerminalTileEntity;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.inventory.container.Slot;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.network.PacketBuffer;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraftforge.fml.network.NetworkEvent;
|
||||
import net.minecraftforge.items.IItemHandler;
|
||||
import net.minecraftforge.items.ItemHandlerHelper;
|
||||
import net.minecraftforge.items.ItemStackHandler;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class PacketCraftingModuleTransfer {
|
||||
|
||||
private List<ItemStack> inputs;
|
||||
private List<ItemStack> outputs;
|
||||
|
||||
public PacketCraftingModuleTransfer(List<ItemStack> inputs, List<ItemStack> outputs) {
|
||||
this.inputs = inputs;
|
||||
this.outputs = outputs;
|
||||
}
|
||||
|
||||
private PacketCraftingModuleTransfer() {
|
||||
|
||||
}
|
||||
|
||||
public static PacketCraftingModuleTransfer fromBytes(PacketBuffer buf) {
|
||||
PacketCraftingModuleTransfer packet = new PacketCraftingModuleTransfer();
|
||||
packet.inputs = new ArrayList<>();
|
||||
for (int i = buf.readInt(); i > 0; i--)
|
||||
packet.inputs.add(buf.readItemStack());
|
||||
packet.outputs = new ArrayList<>();
|
||||
for (int i = buf.readInt(); i > 0; i--)
|
||||
packet.outputs.add(buf.readItemStack());
|
||||
return packet;
|
||||
}
|
||||
|
||||
public static void toBytes(PacketCraftingModuleTransfer packet, PacketBuffer buf) {
|
||||
buf.writeInt(packet.inputs.size());
|
||||
for (ItemStack stack : packet.inputs)
|
||||
buf.writeItemStack(stack);
|
||||
buf.writeInt(packet.outputs.size());
|
||||
for (ItemStack stack : packet.outputs)
|
||||
buf.writeItemStack(stack);
|
||||
}
|
||||
|
||||
@SuppressWarnings("Convert2Lambda")
|
||||
public static void onMessage(PacketCraftingModuleTransfer message, Supplier<NetworkEvent.Context> ctx) {
|
||||
ctx.get().enqueueWork(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
PlayerEntity player = ctx.get().getSender();
|
||||
if (player != null && player.openContainer instanceof CraftingModuleContainer) {
|
||||
CraftingModuleContainer container = (CraftingModuleContainer) player.openContainer;
|
||||
copy(container.input, message.inputs);
|
||||
copy(container.output, message.outputs);
|
||||
container.modified = true;
|
||||
container.detectAndSendChanges();
|
||||
}
|
||||
}
|
||||
});
|
||||
ctx.get().setPacketHandled(true);
|
||||
}
|
||||
|
||||
private static void copy(ItemStackHandler container, List<ItemStack> contents) {
|
||||
for (int i = 0; i < container.getSlots(); i++)
|
||||
container.setStackInSlot(i, ItemStack.EMPTY);
|
||||
for (ItemStack stack : contents)
|
||||
ItemHandlerHelper.insertItem(container, stack, false);
|
||||
}
|
||||
}
|
|
@ -23,6 +23,7 @@ public final class PacketHandler {
|
|||
network.registerMessage(2, PacketNetworkItems.class, PacketNetworkItems::toBytes, PacketNetworkItems::fromBytes, PacketNetworkItems::onMessage);
|
||||
network.registerMessage(3, PacketRequest.class, PacketRequest::toBytes, PacketRequest::fromBytes, PacketRequest::onMessage);
|
||||
network.registerMessage(4, PacketGhostSlot.class, PacketGhostSlot::toBytes, PacketGhostSlot::fromBytes, PacketGhostSlot::onMessage);
|
||||
network.registerMessage(5, PacketCraftingModuleTransfer.class, PacketCraftingModuleTransfer::toBytes, PacketCraftingModuleTransfer::fromBytes, PacketCraftingModuleTransfer::onMessage);
|
||||
}
|
||||
|
||||
public static void sendToAllLoaded(World world, BlockPos pos, Object message) {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package de.ellpeck.prettypipes.packets;
|
||||
|
||||
import de.ellpeck.prettypipes.Utility;
|
||||
import de.ellpeck.prettypipes.pipe.IPipeItem;
|
||||
import de.ellpeck.prettypipes.pipe.PipeTileEntity;
|
||||
import de.ellpeck.prettypipes.network.PipeItem;
|
||||
import net.minecraft.client.Minecraft;
|
||||
|
@ -16,7 +17,7 @@ public class PacketItemEnterPipe {
|
|||
private BlockPos tilePos;
|
||||
private CompoundNBT item;
|
||||
|
||||
public PacketItemEnterPipe(BlockPos tilePos, PipeItem item) {
|
||||
public PacketItemEnterPipe(BlockPos tilePos, IPipeItem item) {
|
||||
this.tilePos = tilePos;
|
||||
this.item = item.serializeNBT();
|
||||
}
|
||||
|
@ -45,7 +46,7 @@ public class PacketItemEnterPipe {
|
|||
Minecraft mc = Minecraft.getInstance();
|
||||
if (mc.world == null)
|
||||
return;
|
||||
PipeItem item = new PipeItem(message.item);
|
||||
IPipeItem item = IPipeItem.load(message.item);
|
||||
PipeTileEntity pipe = Utility.getTileEntity(PipeTileEntity.class, mc.world, message.tilePos);
|
||||
if (pipe != null)
|
||||
pipe.getItems().add(item);
|
||||
|
|
|
@ -22,9 +22,13 @@ import java.util.function.Supplier;
|
|||
public class PacketNetworkItems {
|
||||
|
||||
private List<ItemStack> items;
|
||||
private List<ItemStack> craftables;
|
||||
private List<ItemStack> currentlyCrafting;
|
||||
|
||||
public PacketNetworkItems(List<ItemStack> items) {
|
||||
public PacketNetworkItems(List<ItemStack> items, List<ItemStack> craftables, List<ItemStack> currentlyCrafting) {
|
||||
this.items = items;
|
||||
this.craftables = craftables;
|
||||
this.currentlyCrafting = currentlyCrafting;
|
||||
}
|
||||
|
||||
private PacketNetworkItems() {
|
||||
|
@ -39,6 +43,12 @@ public class PacketNetworkItems {
|
|||
stack.setCount(buf.readVarInt());
|
||||
client.items.add(stack);
|
||||
}
|
||||
client.craftables = new ArrayList<>();
|
||||
for (int i = buf.readVarInt(); i > 0; i--)
|
||||
client.craftables.add(buf.readItemStack());
|
||||
client.currentlyCrafting = new ArrayList<>();
|
||||
for (int i = buf.readVarInt(); i > 0; i--)
|
||||
client.currentlyCrafting.add(buf.readItemStack());
|
||||
return client;
|
||||
}
|
||||
|
||||
|
@ -50,6 +60,12 @@ public class PacketNetworkItems {
|
|||
buf.writeItemStack(copy);
|
||||
buf.writeVarInt(stack.getCount());
|
||||
}
|
||||
buf.writeVarInt(packet.craftables.size());
|
||||
for (ItemStack stack : packet.craftables)
|
||||
buf.writeItemStack(stack);
|
||||
buf.writeVarInt(packet.currentlyCrafting.size());
|
||||
for (ItemStack stack : packet.currentlyCrafting)
|
||||
buf.writeItemStack(stack);
|
||||
}
|
||||
|
||||
@SuppressWarnings("Convert2Lambda")
|
||||
|
@ -59,7 +75,7 @@ public class PacketNetworkItems {
|
|||
public void run() {
|
||||
Minecraft mc = Minecraft.getInstance();
|
||||
if (mc.currentScreen instanceof ItemTerminalGui)
|
||||
((ItemTerminalGui) mc.currentScreen).updateItemList(message.items);
|
||||
((ItemTerminalGui) mc.currentScreen).updateItemList(message.items, message.craftables, message.currentlyCrafting);
|
||||
}
|
||||
});
|
||||
ctx.get().setPacketHandled(true);
|
||||
|
|
|
@ -1,26 +1,18 @@
|
|||
package de.ellpeck.prettypipes.pipe;
|
||||
|
||||
import de.ellpeck.prettypipes.network.PipeItem;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.items.IItemHandler;
|
||||
|
||||
public interface IPipeConnectable {
|
||||
|
||||
ConnectionType getConnectionType(World world, BlockPos pipePos, Direction direction);
|
||||
ConnectionType getConnectionType(BlockPos pipePos, Direction direction);
|
||||
|
||||
default IItemHandler getItemHandler(World world, BlockPos pipePos, Direction direction, PipeItem item) {
|
||||
return null;
|
||||
default ItemStack insertItem(BlockPos pipePos, Direction direction, ItemStack stack, boolean simulate) {
|
||||
return stack;
|
||||
}
|
||||
|
||||
default ItemStack insertItem(World world, BlockPos pipePos, Direction direction, PipeItem item) {
|
||||
return item.stack;
|
||||
}
|
||||
|
||||
default boolean allowsModules(World world, BlockPos pipePos, Direction direction) {
|
||||
default boolean allowsModules(BlockPos pipePos, Direction direction) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
58
src/main/java/de/ellpeck/prettypipes/pipe/IPipeItem.java
Normal file
|
@ -0,0 +1,58 @@
|
|||
package de.ellpeck.prettypipes.pipe;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||
import de.ellpeck.prettypipes.network.NetworkEdge;
|
||||
import de.ellpeck.prettypipes.network.PipeItem;
|
||||
import net.minecraft.client.renderer.IRenderTypeBuffer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
import net.minecraftforge.common.util.INBTSerializable;
|
||||
import org.jgrapht.GraphPath;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
public interface IPipeItem extends INBTSerializable<CompoundNBT> {
|
||||
|
||||
Map<ResourceLocation, BiFunction<ResourceLocation, CompoundNBT, IPipeItem>> TYPES = new HashMap<>(
|
||||
Collections.singletonMap(PipeItem.TYPE, PipeItem::new));
|
||||
|
||||
ItemStack getContent();
|
||||
|
||||
void setDestination(BlockPos startInventory, BlockPos destInventory, GraphPath<BlockPos, NetworkEdge> path);
|
||||
|
||||
void updateInPipe(PipeTileEntity currPipe);
|
||||
|
||||
void drop(World world, ItemStack stack);
|
||||
|
||||
BlockPos getDestPipe();
|
||||
|
||||
BlockPos getCurrentPipe();
|
||||
|
||||
BlockPos getDestInventory();
|
||||
|
||||
int getItemsOnTheWay(BlockPos goalInv);
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
void render(PipeTileEntity tile, MatrixStack matrixStack, Random random, float partialTicks, int light, int overlay, IRenderTypeBuffer buffer);
|
||||
|
||||
static IPipeItem load(CompoundNBT nbt) {
|
||||
// TODO legacy compat, remove eventually
|
||||
if (!nbt.contains("type"))
|
||||
nbt.putString("type", PipeItem.TYPE.toString());
|
||||
|
||||
ResourceLocation type = new ResourceLocation(nbt.getString("type"));
|
||||
BiFunction<ResourceLocation, CompoundNBT, IPipeItem> func = TYPES.get(type);
|
||||
return func != null ? func.apply(type, nbt) : null;
|
||||
}
|
||||
}
|
|
@ -1,6 +1,8 @@
|
|||
package de.ellpeck.prettypipes.pipe;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.mojang.datafixers.types.Func;
|
||||
import de.ellpeck.prettypipes.Registry;
|
||||
import de.ellpeck.prettypipes.Utility;
|
||||
import de.ellpeck.prettypipes.items.IModule;
|
||||
import de.ellpeck.prettypipes.network.PipeItem;
|
||||
|
@ -10,6 +12,7 @@ import net.minecraft.block.material.Material;
|
|||
import net.minecraft.entity.LivingEntity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.entity.player.ServerPlayerEntity;
|
||||
import net.minecraft.fluid.FluidState;
|
||||
import net.minecraft.fluid.Fluids;
|
||||
import net.minecraft.fluid.IFluidState;
|
||||
import net.minecraft.item.BlockItemUseContext;
|
||||
|
@ -24,6 +27,7 @@ import net.minecraft.util.Direction;
|
|||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.BlockRayTraceResult;
|
||||
import net.minecraft.util.math.shapes.IBooleanFunction;
|
||||
import net.minecraft.util.math.shapes.ISelectionContext;
|
||||
import net.minecraft.util.math.shapes.VoxelShape;
|
||||
import net.minecraft.util.math.shapes.VoxelShapes;
|
||||
|
@ -34,15 +38,19 @@ import net.minecraftforge.fml.network.NetworkHooks;
|
|||
import net.minecraftforge.items.CapabilityItemHandler;
|
||||
import net.minecraftforge.items.IItemHandler;
|
||||
import net.minecraftforge.items.ItemHandlerHelper;
|
||||
import org.apache.commons.lang3.mutable.MutableObject;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class PipeBlock extends ContainerBlock implements IPipeConnectable {
|
||||
public class PipeBlock extends ContainerBlock {
|
||||
|
||||
public static final Map<Direction, EnumProperty<ConnectionType>> DIRECTIONS = new HashMap<>();
|
||||
private static final Map<BlockState, VoxelShape> SHAPE_CACHE = new HashMap<>();
|
||||
private static final Map<Pair<BlockState, BlockState>, VoxelShape> SHAPE_CACHE = new HashMap<>();
|
||||
private static final Map<Pair<BlockState, BlockState>, VoxelShape> COLL_SHAPE_CACHE = new HashMap<>();
|
||||
private static final VoxelShape CENTER_SHAPE = makeCuboidShape(5, 5, 5, 11, 11, 11);
|
||||
public static final Map<Direction, VoxelShape> DIR_SHAPES = ImmutableMap.<Direction, VoxelShape>builder()
|
||||
.put(Direction.UP, makeCuboidShape(5, 10, 5, 11, 16, 11))
|
||||
|
@ -55,7 +63,7 @@ public class PipeBlock extends ContainerBlock implements IPipeConnectable {
|
|||
|
||||
static {
|
||||
for (Direction dir : Direction.values())
|
||||
DIRECTIONS.put(dir, EnumProperty.create(dir.getName(), ConnectionType.class));
|
||||
DIRECTIONS.put(dir, EnumProperty.create(dir.getName2(), ConnectionType.class));
|
||||
}
|
||||
|
||||
public PipeBlock() {
|
||||
|
@ -130,22 +138,46 @@ public class PipeBlock extends ContainerBlock implements IPipeConnectable {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isNormalCube(BlockState state, IBlockReader worldIn, BlockPos pos) {
|
||||
return false;
|
||||
public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) {
|
||||
return this.cacheAndGetShape(state, worldIn, pos, s -> s.getShape(worldIn, pos, context), SHAPE_CACHE, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) {
|
||||
VoxelShape shape = SHAPE_CACHE.get(state);
|
||||
if (shape != null)
|
||||
return shape;
|
||||
public VoxelShape getCollisionShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) {
|
||||
return this.cacheAndGetShape(state, worldIn, pos, s -> s.getCollisionShape(worldIn, pos, context), COLL_SHAPE_CACHE, s -> {
|
||||
// make the shape a bit higher so we can jump up onto a higher block
|
||||
MutableObject<VoxelShape> newShape = new MutableObject<>(VoxelShapes.empty());
|
||||
s.forEachBox((x1, y1, z1, x2, y2, z2) -> newShape.setValue(VoxelShapes.combine(VoxelShapes.create(x1, y1, z1, x2, y2 + 3 / 16F, z2), newShape.getValue(), IBooleanFunction.OR)));
|
||||
return newShape.getValue().simplify();
|
||||
});
|
||||
}
|
||||
|
||||
shape = CENTER_SHAPE;
|
||||
for (Map.Entry<Direction, EnumProperty<ConnectionType>> entry : DIRECTIONS.entrySet()) {
|
||||
if (state.get(entry.getValue()).isConnected())
|
||||
shape = VoxelShapes.or(shape, DIR_SHAPES.get(entry.getKey()));
|
||||
private VoxelShape cacheAndGetShape(BlockState state, IBlockReader worldIn, BlockPos pos, Function<BlockState, VoxelShape> coverShapeSelector, Map<Pair<BlockState, BlockState>, VoxelShape> cache, Function<VoxelShape, VoxelShape> shapeModifier) {
|
||||
VoxelShape coverShape = null;
|
||||
BlockState cover = null;
|
||||
PipeTileEntity tile = Utility.getTileEntity(PipeTileEntity.class, worldIn, pos);
|
||||
if (tile != null && tile.cover != null) {
|
||||
cover = tile.cover;
|
||||
// try catch since the block might expect to find itself at the position
|
||||
try {
|
||||
coverShape = coverShapeSelector.apply(cover);
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
Pair<BlockState, BlockState> key = Pair.of(state, cover);
|
||||
VoxelShape shape = cache.get(key);
|
||||
if (shape == null) {
|
||||
shape = CENTER_SHAPE;
|
||||
for (Map.Entry<Direction, EnumProperty<ConnectionType>> entry : DIRECTIONS.entrySet()) {
|
||||
if (state.get(entry.getValue()).isConnected())
|
||||
shape = VoxelShapes.or(shape, DIR_SHAPES.get(entry.getKey()));
|
||||
}
|
||||
if (shapeModifier != null)
|
||||
shape = shapeModifier.apply(shape);
|
||||
if (coverShape != null)
|
||||
shape = VoxelShapes.or(shape, coverShape);
|
||||
cache.put(key, shape);
|
||||
}
|
||||
SHAPE_CACHE.put(state, shape);
|
||||
return shape;
|
||||
}
|
||||
|
||||
|
@ -170,16 +202,20 @@ public class PipeBlock extends ContainerBlock implements IPipeConnectable {
|
|||
BlockPos offset = pos.offset(direction);
|
||||
if (!world.isBlockLoaded(offset))
|
||||
return ConnectionType.DISCONNECTED;
|
||||
BlockState offState = world.getBlockState(offset);
|
||||
Block block = offState.getBlock();
|
||||
if (block instanceof IPipeConnectable)
|
||||
return ((IPipeConnectable) block).getConnectionType(world, pos, direction);
|
||||
Direction opposite = direction.getOpposite();
|
||||
TileEntity tile = world.getTileEntity(offset);
|
||||
if (tile != null) {
|
||||
IItemHandler handler = tile.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, direction.getOpposite()).orElse(null);
|
||||
IPipeConnectable connectable = tile.getCapability(Registry.pipeConnectableCapability, opposite).orElse(null);
|
||||
if (connectable != null)
|
||||
return connectable.getConnectionType(pos, direction);
|
||||
IItemHandler handler = tile.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, opposite).orElse(null);
|
||||
if (handler != null)
|
||||
return ConnectionType.CONNECTED;
|
||||
}
|
||||
IItemHandler blockHandler = Utility.getBlockItemHandler(world, offset, opposite);
|
||||
if (blockHandler != null)
|
||||
return ConnectionType.CONNECTED;
|
||||
BlockState offState = world.getBlockState(offset);
|
||||
if (hasLegsTo(world, offState, offset, direction)) {
|
||||
if (DIRECTIONS.values().stream().noneMatch(d -> state.get(d) == ConnectionType.LEGS))
|
||||
return ConnectionType.LEGS;
|
||||
|
@ -191,14 +227,15 @@ public class PipeBlock extends ContainerBlock implements IPipeConnectable {
|
|||
if (state.getBlock() instanceof WallBlock || state.getBlock() instanceof FenceBlock)
|
||||
return direction == Direction.DOWN;
|
||||
if (state.getMaterial() == Material.ROCK || state.getMaterial() == Material.IRON)
|
||||
return hasSolidSide(state, world, pos, direction.getOpposite());
|
||||
return hasEnoughSolidSide(world, pos, direction.getOpposite());
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void onStateChanged(World world, BlockPos pos, BlockState newState) {
|
||||
// wait a few ticks before checking if we have to drop our modules, so that things like iron -> gold chest work
|
||||
PipeTileEntity tile = Utility.getTileEntity(PipeTileEntity.class, world, pos);
|
||||
if (tile != null && !tile.canHaveModules())
|
||||
Utility.dropInventory(tile, tile.modules);
|
||||
if (tile != null)
|
||||
tile.moduleDropCheck = 5;
|
||||
|
||||
PipeNetwork network = PipeNetwork.get(world);
|
||||
int connections = 0;
|
||||
|
@ -226,12 +263,6 @@ public class PipeBlock extends ContainerBlock implements IPipeConnectable {
|
|||
@Override
|
||||
public void onReplaced(BlockState state, World worldIn, BlockPos pos, BlockState newState, boolean isMoving) {
|
||||
if (state.getBlock() != newState.getBlock()) {
|
||||
PipeTileEntity tile = Utility.getTileEntity(PipeTileEntity.class, worldIn, pos);
|
||||
if (tile != null) {
|
||||
Utility.dropInventory(tile, tile.modules);
|
||||
for (PipeItem item : tile.getItems())
|
||||
item.drop(worldIn);
|
||||
}
|
||||
PipeNetwork network = PipeNetwork.get(worldIn);
|
||||
network.removeNode(pos);
|
||||
network.onPipeChanged(pos, state);
|
||||
|
@ -239,6 +270,19 @@ public class PipeBlock extends ContainerBlock implements IPipeConnectable {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBlockHarvested(World worldIn, BlockPos pos, BlockState state, PlayerEntity player) {
|
||||
PipeTileEntity tile = Utility.getTileEntity(PipeTileEntity.class, worldIn, pos);
|
||||
if (tile != null) {
|
||||
Utility.dropInventory(tile, tile.modules);
|
||||
for (IPipeItem item : tile.getItems())
|
||||
item.drop(worldIn, item.getContent());
|
||||
if (tile.cover != null)
|
||||
tile.removeCover(player, Hand.MAIN_HAND);
|
||||
}
|
||||
super.onBlockHarvested(worldIn, pos, state, player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasComparatorInputOverride(BlockState state) {
|
||||
return true;
|
||||
|
@ -262,12 +306,4 @@ public class PipeBlock extends ContainerBlock implements IPipeConnectable {
|
|||
public BlockRenderType getRenderType(BlockState state) {
|
||||
return BlockRenderType.MODEL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConnectionType getConnectionType(World world, BlockPos pipePos, Direction direction) {
|
||||
BlockState state = world.getBlockState(pipePos.offset(direction));
|
||||
if (state.get(DIRECTIONS.get(direction.getOpposite())) == ConnectionType.BLOCKED)
|
||||
return ConnectionType.BLOCKED;
|
||||
return ConnectionType.CONNECTED;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,17 +1,22 @@
|
|||
package de.ellpeck.prettypipes.pipe;
|
||||
|
||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||
import com.mojang.blaze3d.platform.GlStateManager;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.mojang.blaze3d.vertex.IVertexBuilder;
|
||||
import de.ellpeck.prettypipes.Registry;
|
||||
import de.ellpeck.prettypipes.network.PipeItem;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.BlockModelRenderer;
|
||||
import net.minecraft.client.renderer.IRenderTypeBuffer;
|
||||
import net.minecraft.client.renderer.model.ItemCameraTransforms;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.client.renderer.RenderTypeLookup;
|
||||
import net.minecraft.client.renderer.tileentity.TileEntityRenderer;
|
||||
import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher;
|
||||
import net.minecraft.item.BlockItem;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraftforge.client.ForgeHooksClient;
|
||||
import net.minecraftforge.client.model.data.EmptyModelData;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
|
@ -24,59 +29,30 @@ public class PipeRenderer extends TileEntityRenderer<PipeTileEntity> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void render(PipeTileEntity tile, float v, MatrixStack matrixStack, IRenderTypeBuffer iRenderTypeBuffer, int k, int i1) {
|
||||
if (tile.getItems().isEmpty())
|
||||
return;
|
||||
matrixStack.push();
|
||||
BlockPos tilePos = tile.getPos();
|
||||
matrixStack.translate(-tilePos.getX(), -tilePos.getY(), -tilePos.getZ());
|
||||
for (PipeItem item : tile.getItems()) {
|
||||
public void render(PipeTileEntity tile, float partialTicks, MatrixStack matrixStack, IRenderTypeBuffer buffer, int light, int overlay) {
|
||||
if (!tile.getItems().isEmpty()) {
|
||||
matrixStack.push();
|
||||
matrixStack.translate(
|
||||
MathHelper.lerp(v, item.lastX, item.x),
|
||||
MathHelper.lerp(v, item.lastY, item.y),
|
||||
MathHelper.lerp(v, item.lastZ, item.z));
|
||||
|
||||
if (item.stack.getItem() instanceof BlockItem) {
|
||||
float scale = 0.7F;
|
||||
matrixStack.scale(scale, scale, scale);
|
||||
matrixStack.translate(0, -0.2F, 0);
|
||||
} else {
|
||||
float scale = 0.45F;
|
||||
matrixStack.scale(scale, scale, scale);
|
||||
matrixStack.translate(0, -0.1F, 0);
|
||||
}
|
||||
|
||||
this.random.setSeed(Item.getIdFromItem(item.stack.getItem()) + item.stack.getDamage());
|
||||
int amount = this.getModelCount(item.stack);
|
||||
|
||||
for (int i = 0; i < amount; i++) {
|
||||
BlockPos tilePos = tile.getPos();
|
||||
matrixStack.translate(-tilePos.getX(), -tilePos.getY(), -tilePos.getZ());
|
||||
for (IPipeItem item : tile.getItems()) {
|
||||
matrixStack.push();
|
||||
if (amount > 1) {
|
||||
matrixStack.translate(
|
||||
(this.random.nextFloat() * 2.0F - 1.0F) * 0.25F * 0.5F,
|
||||
(this.random.nextFloat() * 2.0F - 1.0F) * 0.25F * 0.5F,
|
||||
(this.random.nextFloat() * 2.0F - 1.0F) * 0.25F * 0.5F);
|
||||
}
|
||||
Minecraft.getInstance().getItemRenderer().renderItem(item.stack, ItemCameraTransforms.TransformType.GROUND, k, i1, matrixStack, iRenderTypeBuffer);
|
||||
item.render(tile, matrixStack, this.random, partialTicks, light, overlay, buffer);
|
||||
matrixStack.pop();
|
||||
}
|
||||
matrixStack.pop();
|
||||
}
|
||||
matrixStack.pop();
|
||||
}
|
||||
|
||||
protected int getModelCount(ItemStack stack) {
|
||||
int i = 1;
|
||||
if (stack.getCount() > 48) {
|
||||
i = 5;
|
||||
} else if (stack.getCount() > 32) {
|
||||
i = 4;
|
||||
} else if (stack.getCount() > 16) {
|
||||
i = 3;
|
||||
} else if (stack.getCount() > 1) {
|
||||
i = 2;
|
||||
if (tile.cover != null) {
|
||||
matrixStack.push();
|
||||
BlockModelRenderer.enableCache();
|
||||
for (RenderType layer : RenderType.getBlockRenderTypes()) {
|
||||
if (!RenderTypeLookup.canRenderInLayer(tile.cover, layer))
|
||||
continue;
|
||||
ForgeHooksClient.setRenderLayer(layer);
|
||||
Minecraft.getInstance().getBlockRendererDispatcher().renderBlock(tile.cover, matrixStack, buffer, light, overlay, EmptyModelData.INSTANCE);
|
||||
}
|
||||
ForgeHooksClient.setRenderLayer(null);
|
||||
BlockModelRenderer.disableCache();
|
||||
matrixStack.pop();
|
||||
}
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,11 +4,12 @@ import de.ellpeck.prettypipes.PrettyPipes;
|
|||
import de.ellpeck.prettypipes.Registry;
|
||||
import de.ellpeck.prettypipes.Utility;
|
||||
import de.ellpeck.prettypipes.items.IModule;
|
||||
import de.ellpeck.prettypipes.network.PipeItem;
|
||||
import de.ellpeck.prettypipes.network.NetworkLock;
|
||||
import de.ellpeck.prettypipes.network.PipeNetwork;
|
||||
import de.ellpeck.prettypipes.pipe.containers.MainPipeContainer;
|
||||
import de.ellpeck.prettypipes.pressurizer.PressurizerTileEntity;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.ChestBlock;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.entity.player.PlayerInventory;
|
||||
import net.minecraft.inventory.container.Container;
|
||||
|
@ -16,30 +17,40 @@ import net.minecraft.inventory.container.INamedContainerProvider;
|
|||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraft.nbt.ListNBT;
|
||||
import net.minecraft.nbt.NBTUtil;
|
||||
import net.minecraft.network.NetworkManager;
|
||||
import net.minecraft.network.play.server.SUpdateTileEntityPacket;
|
||||
import net.minecraft.profiler.IProfiler;
|
||||
import net.minecraft.tileentity.ChestTileEntity;
|
||||
import net.minecraft.tileentity.ITickableTileEntity;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.tileentity.TileEntityType;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.text.ITextComponent;
|
||||
import net.minecraft.util.text.TranslationTextComponent;
|
||||
import net.minecraftforge.common.util.Constants;
|
||||
import net.minecraft.world.server.ServerWorld;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
import net.minecraftforge.common.capabilities.Capability;
|
||||
import net.minecraftforge.common.util.Constants.NBT;
|
||||
import net.minecraftforge.common.util.LazyOptional;
|
||||
import net.minecraftforge.items.CapabilityItemHandler;
|
||||
import net.minecraftforge.items.IItemHandler;
|
||||
import net.minecraftforge.items.ItemHandlerHelper;
|
||||
import net.minecraftforge.items.ItemStackHandler;
|
||||
import net.minecraftforge.items.wrapper.InvWrapper;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.*;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class PipeTileEntity extends TileEntity implements INamedContainerProvider, ITickableTileEntity {
|
||||
public class PipeTileEntity extends TileEntity implements INamedContainerProvider, ITickableTileEntity, IPipeConnectable {
|
||||
|
||||
public final ItemStackHandler modules = new ItemStackHandler(3) {
|
||||
@Override
|
||||
|
@ -56,9 +67,15 @@ public class PipeTileEntity extends TileEntity implements INamedContainerProvide
|
|||
return 1;
|
||||
}
|
||||
};
|
||||
protected List<PipeItem> items;
|
||||
public final Queue<NetworkLock> craftIngredientRequests = new LinkedList<>();
|
||||
public final List<Pair<BlockPos, ItemStack>> craftResultRequests = new ArrayList<>();
|
||||
public PressurizerTileEntity pressurizer;
|
||||
public BlockState cover;
|
||||
public int moduleDropCheck;
|
||||
protected List<IPipeItem> items;
|
||||
private int lastItemAmount;
|
||||
private int priority;
|
||||
private final LazyOptional<PipeTileEntity> lazyThis = LazyOptional.of(() -> this);
|
||||
|
||||
public PipeTileEntity() {
|
||||
this(Registry.pipeTileEntity);
|
||||
|
@ -71,12 +88,36 @@ public class PipeTileEntity extends TileEntity implements INamedContainerProvide
|
|||
@Override
|
||||
public CompoundNBT write(CompoundNBT compound) {
|
||||
compound.put("modules", this.modules.serializeNBT());
|
||||
compound.putInt("module_drop_check", this.moduleDropCheck);
|
||||
compound.put("requests", Utility.serializeAll(this.craftIngredientRequests));
|
||||
if (this.cover != null)
|
||||
compound.put("cover", NBTUtil.writeBlockState(this.cover));
|
||||
ListNBT results = new ListNBT();
|
||||
for (Pair<BlockPos, ItemStack> triple : this.craftResultRequests) {
|
||||
CompoundNBT nbt = new CompoundNBT();
|
||||
nbt.putLong("dest_pipe", triple.getLeft().toLong());
|
||||
nbt.put("item", triple.getRight().serializeNBT());
|
||||
results.add(nbt);
|
||||
}
|
||||
compound.put("craft_results", results);
|
||||
return super.write(compound);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(CompoundNBT compound) {
|
||||
this.modules.deserializeNBT(compound.getCompound("modules"));
|
||||
this.moduleDropCheck = compound.getInt("module_drop_check");
|
||||
this.cover = compound.contains("cover") ? NBTUtil.readBlockState(compound.getCompound("cover")) : null;
|
||||
this.craftIngredientRequests.clear();
|
||||
this.craftIngredientRequests.addAll(Utility.deserializeAll(compound.getList("requests", NBT.TAG_COMPOUND), NetworkLock::new));
|
||||
this.craftResultRequests.clear();
|
||||
ListNBT results = compound.getList("craft_results", NBT.TAG_COMPOUND);
|
||||
for (int i = 0; i < results.size(); i++) {
|
||||
CompoundNBT nbt = results.getCompound(i);
|
||||
this.craftResultRequests.add(Pair.of(
|
||||
BlockPos.fromLong(nbt.getLong("dest_pipe")),
|
||||
ItemStack.read(nbt.getCompound("item"))));
|
||||
}
|
||||
super.read(compound);
|
||||
}
|
||||
|
||||
|
@ -91,18 +132,34 @@ public class PipeTileEntity extends TileEntity implements INamedContainerProvide
|
|||
@Override
|
||||
public void handleUpdateTag(CompoundNBT nbt) {
|
||||
this.read(nbt);
|
||||
List<PipeItem> items = this.getItems();
|
||||
List<IPipeItem> items = this.getItems();
|
||||
items.clear();
|
||||
items.addAll(Utility.deserializeAll(nbt.getList("items", NBT.TAG_COMPOUND), PipeItem::new));
|
||||
items.addAll(Utility.deserializeAll(nbt.getList("items", NBT.TAG_COMPOUND), IPipeItem::load));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDataPacket(NetworkManager net, SUpdateTileEntityPacket pkt) {
|
||||
this.read(pkt.getNbtCompound());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
// invalidate our pressurizer reference if it was removed
|
||||
if (this.pressurizer != null && this.pressurizer.isRemoved())
|
||||
this.pressurizer = null;
|
||||
|
||||
if (!this.world.isAreaLoaded(this.pos, 1))
|
||||
return;
|
||||
IProfiler profiler = this.world.getProfiler();
|
||||
|
||||
if (!this.world.isRemote) {
|
||||
// drop modules here to give a bit of time for blocks to update (iron -> gold chest etc.)
|
||||
if (this.moduleDropCheck > 0) {
|
||||
this.moduleDropCheck--;
|
||||
if (this.moduleDropCheck <= 0 && !this.canHaveModules())
|
||||
Utility.dropInventory(this, this.modules);
|
||||
}
|
||||
|
||||
profiler.startSection("ticking_modules");
|
||||
int prio = 0;
|
||||
Iterator<Pair<ItemStack, IModule>> modules = this.streamModules().iterator();
|
||||
|
@ -120,7 +177,7 @@ public class PipeTileEntity extends TileEntity implements INamedContainerProvide
|
|||
}
|
||||
|
||||
profiler.startSection("ticking_items");
|
||||
List<PipeItem> items = this.getItems();
|
||||
List<IPipeItem> items = this.getItems();
|
||||
for (int i = items.size() - 1; i >= 0; i--)
|
||||
items.get(i).updateInPipe(this);
|
||||
if (items.size() != this.lastItemAmount) {
|
||||
|
@ -130,23 +187,50 @@ public class PipeTileEntity extends TileEntity implements INamedContainerProvide
|
|||
profiler.endSection();
|
||||
}
|
||||
|
||||
public List<PipeItem> getItems() {
|
||||
public List<IPipeItem> getItems() {
|
||||
if (this.items == null)
|
||||
this.items = PipeNetwork.get(this.world).getItemsInPipe(this.pos);
|
||||
return this.items;
|
||||
}
|
||||
|
||||
public void addNewItem(IPipeItem item) {
|
||||
// an item might be re-routed from a previous location, but it should still count as a new item then
|
||||
if (!this.getItems().contains(item))
|
||||
this.getItems().add(item);
|
||||
if (this.pressurizer != null)
|
||||
this.pressurizer.pressurizeItem(item.getContent(), false);
|
||||
}
|
||||
|
||||
public boolean isConnected(Direction dir) {
|
||||
return this.getBlockState().get(PipeBlock.DIRECTIONS.get(dir)).isConnected();
|
||||
}
|
||||
|
||||
public Pair<BlockPos, ItemStack> getAvailableDestinationOrConnectable(ItemStack stack, boolean force, boolean preventOversending) {
|
||||
Pair<BlockPos, ItemStack> dest = this.getAvailableDestination(stack, force, preventOversending);
|
||||
if (dest != null)
|
||||
return dest;
|
||||
// if there's no available destination, try inserting into terminals etc.
|
||||
for (Direction dir : Direction.values()) {
|
||||
IPipeConnectable connectable = this.getPipeConnectable(dir);
|
||||
if (connectable == null)
|
||||
continue;
|
||||
ItemStack connectableRemain = connectable.insertItem(this.getPos(), dir, stack, true);
|
||||
if (connectableRemain.getCount() != stack.getCount()) {
|
||||
ItemStack inserted = stack.copy();
|
||||
inserted.shrink(connectableRemain.getCount());
|
||||
return Pair.of(this.getPos().offset(dir), inserted);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Pair<BlockPos, ItemStack> getAvailableDestination(ItemStack stack, boolean force, boolean preventOversending) {
|
||||
if (!this.canWork())
|
||||
return null;
|
||||
if (!force && this.streamModules().anyMatch(m -> !m.getRight().canAcceptItem(m.getLeft(), this, stack)))
|
||||
return null;
|
||||
for (Direction dir : Direction.values()) {
|
||||
IItemHandler handler = this.getItemHandler(dir, null);
|
||||
IItemHandler handler = this.getItemHandler(dir);
|
||||
if (handler == null)
|
||||
continue;
|
||||
ItemStack remain = ItemHandlerHelper.insertItem(handler, stack, true);
|
||||
|
@ -172,15 +256,21 @@ public class PipeTileEntity extends TileEntity implements INamedContainerProvide
|
|||
if (toInsert.getCount() + onTheWaySame > maxAmount)
|
||||
toInsert.setCount(maxAmount - onTheWaySame);
|
||||
}
|
||||
ItemStack copy = stack.copy();
|
||||
copy.setCount(copy.getMaxStackSize());
|
||||
// totalSpace will be the amount of items that fit into the attached container
|
||||
int totalSpace = 0;
|
||||
for (int i = 0; i < handler.getSlots(); i++) {
|
||||
ItemStack copy = stack.copy();
|
||||
int maxStackSize = copy.getMaxStackSize();
|
||||
// if the container can store more than 64 items in this slot, then it's likely
|
||||
// a barrel or similar, meaning that the slot limit matters more than the max stack size
|
||||
int limit = handler.getSlotLimit(i);
|
||||
if (limit > 64)
|
||||
maxStackSize = limit;
|
||||
copy.setCount(maxStackSize);
|
||||
// this is an inaccurate check since it ignores the fact that some slots might
|
||||
// have space for items of other types, but it'll be good enough for us
|
||||
ItemStack left = handler.insertItem(i, copy, true);
|
||||
totalSpace += copy.getMaxStackSize() - left.getCount();
|
||||
totalSpace += maxStackSize - left.getCount();
|
||||
}
|
||||
// if the items on the way plus the items we're trying to move are too much, reduce
|
||||
if (onTheWay + toInsert.getCount() > totalSpace)
|
||||
|
@ -198,46 +288,65 @@ public class PipeTileEntity extends TileEntity implements INamedContainerProvide
|
|||
return this.priority;
|
||||
}
|
||||
|
||||
public float getItemSpeed() {
|
||||
float speed = (float) this.streamModules().mapToDouble(m -> m.getRight().getItemSpeedIncrease(m.getLeft(), this)).sum();
|
||||
return 0.05F + speed;
|
||||
public float getItemSpeed(ItemStack stack) {
|
||||
float moduleSpeed = (float) this.streamModules().mapToDouble(m -> m.getRight().getItemSpeedIncrease(m.getLeft(), this)).sum();
|
||||
float pressureSpeed = this.pressurizer != null && this.pressurizer.pressurizeItem(stack, true) ? 0.45F : 0;
|
||||
return 0.05F + moduleSpeed + pressureSpeed;
|
||||
}
|
||||
|
||||
public boolean canWork() {
|
||||
return this.streamModules().allMatch(m -> m.getRight().canPipeWork(m.getLeft(), this));
|
||||
}
|
||||
|
||||
public IItemHandler getItemHandler(Direction dir, PipeItem item) {
|
||||
public List<ItemStack> getAllCraftables() {
|
||||
return this.streamModules()
|
||||
.flatMap(m -> m.getRight().getAllCraftables(m.getLeft(), this).stream())
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public int getCraftableAmount(Consumer<ItemStack> unavailableConsumer, ItemStack stack) {
|
||||
return this.streamModules()
|
||||
.mapToInt(m -> m.getRight().getCraftableAmount(m.getLeft(), this, unavailableConsumer, stack))
|
||||
.sum();
|
||||
}
|
||||
|
||||
public ItemStack craft(BlockPos destPipe, Consumer<ItemStack> unavailableConsumer, ItemStack stack) {
|
||||
Iterator<Pair<ItemStack, IModule>> modules = this.streamModules().iterator();
|
||||
while (modules.hasNext()) {
|
||||
Pair<ItemStack, IModule> module = modules.next();
|
||||
stack = module.getRight().craft(module.getLeft(), this, destPipe, unavailableConsumer, stack);
|
||||
if (stack.isEmpty())
|
||||
break;
|
||||
}
|
||||
return stack;
|
||||
}
|
||||
|
||||
public IItemHandler getItemHandler(Direction dir) {
|
||||
IItemHandler handler = this.getNeighborCap(dir, CapabilityItemHandler.ITEM_HANDLER_CAPABILITY);
|
||||
if (handler != null)
|
||||
return handler;
|
||||
return Utility.getBlockItemHandler(this.world, this.pos.offset(dir), dir.getOpposite());
|
||||
}
|
||||
|
||||
public <T> T getNeighborCap(Direction dir, Capability<T> cap) {
|
||||
if (!this.isConnected(dir))
|
||||
return null;
|
||||
BlockPos pos = this.pos.offset(dir);
|
||||
TileEntity tile = this.world.getTileEntity(pos);
|
||||
if (tile != null) {
|
||||
// if we don't do this, then chests get really weird
|
||||
if (tile instanceof ChestTileEntity) {
|
||||
BlockState state = this.world.getBlockState(tile.getPos());
|
||||
if (state.getBlock() instanceof ChestBlock)
|
||||
return new InvWrapper(ChestBlock.func_226916_a_((ChestBlock) state.getBlock(), state, this.world, tile.getPos(), true));
|
||||
}
|
||||
IItemHandler handler = tile.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, dir.getOpposite()).orElse(null);
|
||||
if (handler != null)
|
||||
return handler;
|
||||
}
|
||||
IPipeConnectable connectable = this.getPipeConnectable(dir);
|
||||
if (connectable != null)
|
||||
return connectable.getItemHandler(this.world, this.pos, dir, item);
|
||||
if (tile != null)
|
||||
return tile.getCapability(cap, dir.getOpposite()).orElse(null);
|
||||
return null;
|
||||
}
|
||||
|
||||
public IPipeConnectable getPipeConnectable(Direction dir) {
|
||||
BlockState state = this.world.getBlockState(this.pos.offset(dir));
|
||||
if (state.getBlock() instanceof IPipeConnectable)
|
||||
return (IPipeConnectable) state.getBlock();
|
||||
TileEntity tile = this.world.getTileEntity(this.pos.offset(dir));
|
||||
if (tile != null)
|
||||
return tile.getCapability(Registry.pipeConnectableCapability, dir.getOpposite()).orElse(null);
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean isConnectedInventory(Direction dir) {
|
||||
return this.getItemHandler(dir, null) != null;
|
||||
return this.getItemHandler(dir) != null;
|
||||
}
|
||||
|
||||
public boolean canHaveModules() {
|
||||
|
@ -245,7 +354,7 @@ public class PipeTileEntity extends TileEntity implements INamedContainerProvide
|
|||
if (this.isConnectedInventory(dir))
|
||||
return true;
|
||||
IPipeConnectable connectable = this.getPipeConnectable(dir);
|
||||
if (connectable != null && connectable.allowsModules(this.world, this.pos, dir))
|
||||
if (connectable != null && connectable.allowsModules(this.pos, dir))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -266,10 +375,23 @@ public class PipeTileEntity extends TileEntity implements INamedContainerProvide
|
|||
return builder.build();
|
||||
}
|
||||
|
||||
public void removeCover(PlayerEntity player, Hand hand) {
|
||||
if (this.world.isRemote)
|
||||
return;
|
||||
List<ItemStack> drops = Block.getDrops(this.cover, (ServerWorld) this.world, this.pos, null, player, player.getHeldItem(hand));
|
||||
for (ItemStack drop : drops)
|
||||
Block.spawnAsEntity(this.world, this.pos, drop);
|
||||
this.cover = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
super.remove();
|
||||
this.getItems().clear();
|
||||
PipeNetwork network = PipeNetwork.get(this.world);
|
||||
for (NetworkLock lock : this.craftIngredientRequests)
|
||||
network.resolveNetworkLock(lock);
|
||||
this.lazyThis.invalidate();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -282,4 +404,26 @@ public class PipeTileEntity extends TileEntity implements INamedContainerProvide
|
|||
public Container createMenu(int window, PlayerInventory inv, PlayerEntity player) {
|
||||
return new MainPipeContainer(Registry.pipeContainer, window, player, PipeTileEntity.this.pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public AxisAlignedBB getRenderBoundingBox() {
|
||||
// our render bounding box should always be the full block in case we're covered
|
||||
return new AxisAlignedBB(this.pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> LazyOptional<T> getCapability(Capability<T> cap, Direction side) {
|
||||
if (cap == Registry.pipeConnectableCapability)
|
||||
return this.lazyThis.cast();
|
||||
return LazyOptional.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConnectionType getConnectionType(BlockPos pipePos, Direction direction) {
|
||||
BlockState state = this.world.getBlockState(pipePos.offset(direction));
|
||||
if (state.get(PipeBlock.DIRECTIONS.get(direction.getOpposite())) == ConnectionType.BLOCKED)
|
||||
return ConnectionType.BLOCKED;
|
||||
return ConnectionType.CONNECTED;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ public abstract class AbstractPipeContainer<T extends IModule> extends Container
|
|||
|
||||
public final PipeTileEntity tile;
|
||||
public final T module;
|
||||
public final int moduleIndex;
|
||||
public final ItemStack moduleStack;
|
||||
|
||||
public AbstractPipeContainer(@Nullable ContainerType<?> type, int id, PlayerEntity player, BlockPos pos, int moduleIndex) {
|
||||
|
@ -26,6 +27,7 @@ public abstract class AbstractPipeContainer<T extends IModule> extends Container
|
|||
this.tile = Utility.getTileEntity(PipeTileEntity.class, player.world, pos);
|
||||
this.moduleStack = moduleIndex < 0 ? null : this.tile.modules.getStackInSlot(moduleIndex);
|
||||
this.module = moduleIndex < 0 ? null : (T) this.moduleStack.getItem();
|
||||
this.moduleIndex = moduleIndex;
|
||||
|
||||
// needs to be done here so transferStackInSlot works correctly, bleh
|
||||
this.addSlots();
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package de.ellpeck.prettypipes.pipe.containers;
|
||||
|
||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||
import de.ellpeck.prettypipes.PrettyPipes;
|
||||
import de.ellpeck.prettypipes.Registry;
|
||||
import de.ellpeck.prettypipes.items.IModule;
|
||||
|
@ -20,7 +21,7 @@ import java.util.List;
|
|||
|
||||
public abstract class AbstractPipeGui<T extends AbstractPipeContainer<?>> extends ContainerScreen<T> {
|
||||
|
||||
private static final ResourceLocation TEXTURE = new ResourceLocation(PrettyPipes.ID, "textures/gui/pipe.png");
|
||||
protected static final ResourceLocation TEXTURE = new ResourceLocation(PrettyPipes.ID, "textures/gui/pipe.png");
|
||||
private final List<Tab> tabs = new ArrayList<>();
|
||||
private final ItemStack[] lastItems = new ItemStack[this.container.tile.modules.getSlots()];
|
||||
|
||||
|
@ -98,27 +99,25 @@ public abstract class AbstractPipeGui<T extends AbstractPipeContainer<?>> extend
|
|||
|
||||
private void initTabs() {
|
||||
this.tabs.clear();
|
||||
this.tabs.add(new Tab(new ItemStack(Registry.pipeBlock), null, 0, -1));
|
||||
this.tabs.add(new Tab(new ItemStack(Registry.pipeBlock), 0, -1));
|
||||
for (int i = 0; i < this.container.tile.modules.getSlots(); i++) {
|
||||
ItemStack stack = this.container.tile.modules.getStackInSlot(i);
|
||||
if (stack.isEmpty())
|
||||
continue;
|
||||
IModule module = (IModule) stack.getItem();
|
||||
if (module.hasContainer(stack, this.container.tile))
|
||||
this.tabs.add(new Tab(stack, module, this.tabs.size(), i));
|
||||
this.tabs.add(new Tab(stack, this.tabs.size(), i));
|
||||
}
|
||||
}
|
||||
|
||||
private class Tab {
|
||||
private final ItemStack moduleStack;
|
||||
private final IModule module;
|
||||
private final int index;
|
||||
private final int x;
|
||||
private final int y;
|
||||
|
||||
public Tab(ItemStack moduleStack, IModule module, int tabIndex, int index) {
|
||||
public Tab(ItemStack moduleStack, int tabIndex, int index) {
|
||||
this.moduleStack = moduleStack;
|
||||
this.module = module;
|
||||
this.index = index;
|
||||
this.x = AbstractPipeGui.this.guiLeft + 5 + tabIndex * 28;
|
||||
this.y = AbstractPipeGui.this.guiTop;
|
||||
|
@ -129,7 +128,7 @@ public abstract class AbstractPipeGui<T extends AbstractPipeContainer<?>> extend
|
|||
int v = 0;
|
||||
int height = 30;
|
||||
int itemOffset = 9;
|
||||
if (this.module == AbstractPipeGui.this.container.module) {
|
||||
if (this.index == AbstractPipeGui.this.container.moduleIndex) {
|
||||
y = 0;
|
||||
v = 30;
|
||||
height = 32;
|
||||
|
@ -148,7 +147,7 @@ public abstract class AbstractPipeGui<T extends AbstractPipeContainer<?>> extend
|
|||
}
|
||||
|
||||
private boolean onClicked(double mouseX, double mouseY, int button) {
|
||||
if (this.module == AbstractPipeGui.this.container.module)
|
||||
if (this.index == AbstractPipeGui.this.container.moduleIndex)
|
||||
return false;
|
||||
if (button != 0)
|
||||
return false;
|
||||
|
|
|
@ -15,11 +15,11 @@ import java.util.List;
|
|||
import java.util.Set;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
public class FilterModifierModule extends ModuleItem {
|
||||
public class FilterModifierModuleItem extends ModuleItem {
|
||||
|
||||
public final ItemEqualityType type;
|
||||
|
||||
public FilterModifierModule(String name, ItemEqualityType type) {
|
||||
public FilterModifierModuleItem(String name, ItemEqualityType type) {
|
||||
super(name);
|
||||
this.type = type;
|
||||
this.setRegistryName(name);
|
|
@ -0,0 +1,31 @@
|
|||
package de.ellpeck.prettypipes.pipe.modules;
|
||||
|
||||
import de.ellpeck.prettypipes.items.IModule;
|
||||
import de.ellpeck.prettypipes.items.ModuleItem;
|
||||
import de.ellpeck.prettypipes.items.ModuleTier;
|
||||
import de.ellpeck.prettypipes.pipe.PipeTileEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
public class HighPriorityModuleItem extends ModuleItem {
|
||||
private final int priority;
|
||||
|
||||
public HighPriorityModuleItem(String name, ModuleTier tier) {
|
||||
super(name);
|
||||
this.priority = tier.forTier(50, 100, 200);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPriority(ItemStack module, PipeTileEntity tile) {
|
||||
return this.priority;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCompatible(ItemStack module, PipeTileEntity tile, IModule other) {
|
||||
return !(other instanceof HighPriorityModuleItem) && !(other instanceof LowPriorityModuleItem);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasContainer(ItemStack module, PipeTileEntity tile) {
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -21,7 +21,7 @@ public class LowPriorityModuleItem extends ModuleItem {
|
|||
|
||||
@Override
|
||||
public boolean isCompatible(ItemStack module, PipeTileEntity tile, IModule other) {
|
||||
return !(other instanceof LowPriorityModuleItem);
|
||||
return !(other instanceof LowPriorityModuleItem) && !(other instanceof HighPriorityModuleItem);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
package de.ellpeck.prettypipes.pipe.modules.craft;
|
||||
|
||||
import de.ellpeck.prettypipes.misc.FilterSlot;
|
||||
import de.ellpeck.prettypipes.pipe.containers.AbstractPipeContainer;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.inventory.container.ContainerType;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraftforge.items.ItemStackHandler;
|
||||
|
||||
public class CraftingModuleContainer extends AbstractPipeContainer<CraftingModuleItem> {
|
||||
|
||||
public ItemStackHandler input;
|
||||
public ItemStackHandler output;
|
||||
public boolean modified;
|
||||
|
||||
public CraftingModuleContainer(ContainerType<?> type, int id, PlayerEntity player, BlockPos pos, int moduleIndex) {
|
||||
super(type, id, player, pos, moduleIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addSlots() {
|
||||
this.input = this.module.getInput(this.moduleStack);
|
||||
for (int i = 0; i < this.input.getSlots(); i++) {
|
||||
this.addSlot(new FilterSlot(this.input, i, (176 - this.module.inputSlots * 18) / 2 + 1 + i % 9 * 18, 17 + 32 + i / 9 * 18, false) {
|
||||
@Override
|
||||
public void onSlotChanged() {
|
||||
super.onSlotChanged();
|
||||
CraftingModuleContainer.this.modified = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
this.output = this.module.getOutput(this.moduleStack);
|
||||
for (int i = 0; i < this.output.getSlots(); i++) {
|
||||
this.addSlot(new FilterSlot(this.output, i, (176 - this.module.outputSlots * 18) / 2 + 1 + i % 9 * 18, 85 + i / 9 * 18, false) {
|
||||
@Override
|
||||
public void onSlotChanged() {
|
||||
super.onSlotChanged();
|
||||
CraftingModuleContainer.this.modified = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onContainerClosed(PlayerEntity playerIn) {
|
||||
super.onContainerClosed(playerIn);
|
||||
if (this.modified)
|
||||
this.module.save(this.input, this.output, this.moduleStack);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package de.ellpeck.prettypipes.pipe.modules.craft;
|
||||
|
||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||
import de.ellpeck.prettypipes.pipe.containers.AbstractPipeGui;
|
||||
import net.minecraft.entity.player.PlayerInventory;
|
||||
import net.minecraft.util.text.ITextComponent;
|
||||
|
||||
public class CraftingModuleGui extends AbstractPipeGui<CraftingModuleContainer> {
|
||||
public CraftingModuleGui(CraftingModuleContainer screenContainer, PlayerInventory inv, ITextComponent titleIn) {
|
||||
super(screenContainer, inv, titleIn);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void drawGuiContainerBackgroundLayer(float partialTicks, int mouseX, int mouseY) {
|
||||
super.drawGuiContainerBackgroundLayer(partialTicks, mouseX, mouseY);
|
||||
this.getMinecraft().getTextureManager().bindTexture(TEXTURE);
|
||||
this.blit(this.guiLeft + 176 / 2 - 16 / 2, this.guiTop + 32 + 18 * 2, 176, 80, 16, 16);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,227 @@
|
|||
package de.ellpeck.prettypipes.pipe.modules.craft;
|
||||
|
||||
import de.ellpeck.prettypipes.Registry;
|
||||
import de.ellpeck.prettypipes.items.IModule;
|
||||
import de.ellpeck.prettypipes.items.ModuleItem;
|
||||
import de.ellpeck.prettypipes.items.ModuleTier;
|
||||
import de.ellpeck.prettypipes.misc.ItemEqualityType;
|
||||
import de.ellpeck.prettypipes.misc.ItemFilter;
|
||||
import de.ellpeck.prettypipes.network.NetworkLocation;
|
||||
import de.ellpeck.prettypipes.network.NetworkLock;
|
||||
import de.ellpeck.prettypipes.network.PipeNetwork;
|
||||
import de.ellpeck.prettypipes.pipe.PipeTileEntity;
|
||||
import de.ellpeck.prettypipes.pipe.containers.AbstractPipeContainer;
|
||||
import de.ellpeck.prettypipes.terminal.CraftingTerminalTileEntity;
|
||||
import de.ellpeck.prettypipes.terminal.ItemTerminalTileEntity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.entity.player.PlayerInventory;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraftforge.items.ItemStackHandler;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class CraftingModuleItem extends ModuleItem {
|
||||
|
||||
public final int inputSlots;
|
||||
public final int outputSlots;
|
||||
private final int speed;
|
||||
|
||||
public CraftingModuleItem(String name, ModuleTier tier) {
|
||||
super(name);
|
||||
this.inputSlots = tier.forTier(1, 4, 9);
|
||||
this.outputSlots = tier.forTier(1, 2, 4);
|
||||
this.speed = tier.forTier(20, 10, 5);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCompatible(ItemStack module, PipeTileEntity tile, IModule other) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasContainer(ItemStack module, PipeTileEntity tile) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractPipeContainer<?> getContainer(ItemStack module, PipeTileEntity tile, int windowId, PlayerInventory inv, PlayerEntity player, int moduleIndex) {
|
||||
return new CraftingModuleContainer(Registry.craftingModuleContainer, windowId, player, tile.getPos(), moduleIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canNetworkSee(ItemStack module, PipeTileEntity tile) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canAcceptItem(ItemStack module, PipeTileEntity tile, ItemStack stack) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick(ItemStack module, PipeTileEntity tile) {
|
||||
if (tile.getWorld().getGameTime() % this.speed != 0 || !tile.canWork())
|
||||
return;
|
||||
PipeNetwork network = PipeNetwork.get(tile.getWorld());
|
||||
// process crafting ingredient requests
|
||||
if (!tile.craftIngredientRequests.isEmpty()) {
|
||||
network.startProfile("crafting_ingredients");
|
||||
NetworkLock request = tile.craftIngredientRequests.peek();
|
||||
ItemEqualityType[] equalityTypes = ItemFilter.getEqualityTypes(tile);
|
||||
Pair<BlockPos, ItemStack> dest = tile.getAvailableDestination(request.stack, true, true);
|
||||
if (dest != null) {
|
||||
ItemStack requestRemain = network.requestExistingItem(request.location, tile.getPos(), dest.getLeft(), request, dest.getRight(), equalityTypes);
|
||||
network.resolveNetworkLock(request);
|
||||
tile.craftIngredientRequests.remove();
|
||||
|
||||
// if we couldn't fit all items into the destination, create another request for the rest
|
||||
ItemStack remain = request.stack.copy();
|
||||
remain.shrink(dest.getRight().getCount() - requestRemain.getCount());
|
||||
if (!remain.isEmpty()) {
|
||||
NetworkLock remainRequest = new NetworkLock(request.location, remain);
|
||||
tile.craftIngredientRequests.add(remainRequest);
|
||||
network.createNetworkLock(remainRequest);
|
||||
}
|
||||
}
|
||||
network.endProfile();
|
||||
}
|
||||
// pull requested crafting results from the network once they are stored
|
||||
if (!tile.craftResultRequests.isEmpty()) {
|
||||
network.startProfile("crafting_results");
|
||||
List<NetworkLocation> items = network.getOrderedNetworkItems(tile.getPos());
|
||||
ItemEqualityType[] equalityTypes = ItemFilter.getEqualityTypes(tile);
|
||||
for (Pair<BlockPos, ItemStack> request : tile.craftResultRequests) {
|
||||
ItemStack remain = request.getRight().copy();
|
||||
PipeTileEntity destPipe = network.getPipe(request.getLeft());
|
||||
if (destPipe != null) {
|
||||
Pair<BlockPos, ItemStack> dest = destPipe.getAvailableDestinationOrConnectable(remain, true, true);
|
||||
if (dest == null)
|
||||
continue;
|
||||
for (NetworkLocation item : items) {
|
||||
ItemStack requestRemain = network.requestExistingItem(item, request.getLeft(), dest.getLeft(), null, dest.getRight(), equalityTypes);
|
||||
remain.shrink(dest.getRight().getCount() - requestRemain.getCount());
|
||||
if (remain.isEmpty())
|
||||
break;
|
||||
}
|
||||
if (remain.getCount() != request.getRight().getCount()) {
|
||||
tile.craftResultRequests.remove(request);
|
||||
// if we couldn't pull everything, log a new request
|
||||
if (!remain.isEmpty())
|
||||
tile.craftResultRequests.add(Pair.of(request.getLeft(), remain));
|
||||
network.endProfile();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
network.endProfile();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ItemStack> getAllCraftables(ItemStack module, PipeTileEntity tile) {
|
||||
List<ItemStack> ret = new ArrayList<>();
|
||||
ItemStackHandler output = this.getOutput(module);
|
||||
for (int i = 0; i < output.getSlots(); i++) {
|
||||
ItemStack stack = output.getStackInSlot(i);
|
||||
if (!stack.isEmpty())
|
||||
ret.add(stack);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCraftableAmount(ItemStack module, PipeTileEntity tile, Consumer<ItemStack> unavailableConsumer, ItemStack stack) {
|
||||
PipeNetwork network = PipeNetwork.get(tile.getWorld());
|
||||
List<NetworkLocation> items = network.getOrderedNetworkItems(tile.getPos());
|
||||
ItemEqualityType[] equalityTypes = ItemFilter.getEqualityTypes(tile);
|
||||
ItemStackHandler input = this.getInput(module);
|
||||
|
||||
int craftable = 0;
|
||||
ItemStackHandler output = this.getOutput(module);
|
||||
for (int i = 0; i < output.getSlots(); i++) {
|
||||
ItemStack out = output.getStackInSlot(i);
|
||||
if (!out.isEmpty() && ItemEqualityType.compareItems(out, stack, equalityTypes)) {
|
||||
// figure out how many crafting operations we can actually do with the input items we have in the network
|
||||
int availableCrafts = CraftingTerminalTileEntity.getAvailableCrafts(tile, input.getSlots(), input::getStackInSlot, k -> true, s -> items, unavailableConsumer, equalityTypes);
|
||||
if (availableCrafts > 0)
|
||||
craftable += out.getCount() * availableCrafts;
|
||||
}
|
||||
}
|
||||
return craftable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack craft(ItemStack module, PipeTileEntity tile, BlockPos destPipe, Consumer<ItemStack> unavailableConsumer, ItemStack stack) {
|
||||
// check if we can craft the required amount of items
|
||||
int craftableAmount = this.getCraftableAmount(module, tile, unavailableConsumer, stack);
|
||||
if (craftableAmount <= 0)
|
||||
return stack;
|
||||
|
||||
PipeNetwork network = PipeNetwork.get(tile.getWorld());
|
||||
List<NetworkLocation> items = network.getOrderedNetworkItems(tile.getPos());
|
||||
|
||||
ItemEqualityType[] equalityTypes = ItemFilter.getEqualityTypes(tile);
|
||||
int resultAmount = this.getResultAmountPerCraft(module, stack, equalityTypes);
|
||||
int requiredCrafts = MathHelper.ceil(stack.getCount() / (float) resultAmount);
|
||||
int toCraft = Math.min(craftableAmount, requiredCrafts);
|
||||
|
||||
ItemStackHandler input = this.getInput(module);
|
||||
for (int i = 0; i < input.getSlots(); i++) {
|
||||
ItemStack in = input.getStackInSlot(i);
|
||||
if (in.isEmpty())
|
||||
continue;
|
||||
ItemStack copy = in.copy();
|
||||
copy.setCount(in.getCount() * toCraft);
|
||||
Pair<List<NetworkLock>, ItemStack> ret = ItemTerminalTileEntity.requestItemLater(tile.getWorld(), tile.getPos(), items, unavailableConsumer, copy, equalityTypes);
|
||||
tile.craftIngredientRequests.addAll(ret.getLeft());
|
||||
}
|
||||
|
||||
ItemStack remain = stack.copy();
|
||||
remain.shrink(resultAmount * toCraft);
|
||||
|
||||
ItemStack result = stack.copy();
|
||||
result.shrink(remain.getCount());
|
||||
tile.craftResultRequests.add(Pair.of(destPipe, result));
|
||||
|
||||
return remain;
|
||||
}
|
||||
|
||||
public ItemStackHandler getInput(ItemStack module) {
|
||||
ItemStackHandler handler = new ItemStackHandler(this.inputSlots);
|
||||
if (module.hasTag())
|
||||
handler.deserializeNBT(module.getTag().getCompound("input"));
|
||||
return handler;
|
||||
}
|
||||
|
||||
public ItemStackHandler getOutput(ItemStack module) {
|
||||
ItemStackHandler handler = new ItemStackHandler(this.outputSlots);
|
||||
if (module.hasTag())
|
||||
handler.deserializeNBT(module.getTag().getCompound("output"));
|
||||
return handler;
|
||||
}
|
||||
|
||||
public void save(ItemStackHandler input, ItemStackHandler output, ItemStack module) {
|
||||
CompoundNBT tag = module.getOrCreateTag();
|
||||
if (input != null)
|
||||
tag.put("input", input.serializeNBT());
|
||||
if (output != null)
|
||||
tag.put("output", output.serializeNBT());
|
||||
}
|
||||
|
||||
private int getResultAmountPerCraft(ItemStack module, ItemStack stack, ItemEqualityType... equalityTypes) {
|
||||
ItemStackHandler output = this.getOutput(module);
|
||||
int resultAmount = 0;
|
||||
for (int i = 0; i < output.getSlots(); i++) {
|
||||
ItemStack out = output.getStackInSlot(i);
|
||||
if (ItemEqualityType.compareItems(stack, out, equalityTypes))
|
||||
resultAmount += out.getCount();
|
||||
}
|
||||
return resultAmount;
|
||||
}
|
||||
}
|
|
@ -39,7 +39,7 @@ public class ExtractionModuleItem extends ModuleItem {
|
|||
|
||||
PipeNetwork network = PipeNetwork.get(tile.getWorld());
|
||||
for (Direction dir : Direction.values()) {
|
||||
IItemHandler handler = tile.getItemHandler(dir, null);
|
||||
IItemHandler handler = tile.getItemHandler(dir);
|
||||
if (handler == null)
|
||||
continue;
|
||||
for (int j = 0; j < handler.getSlots(); j++) {
|
||||
|
@ -48,7 +48,7 @@ public class ExtractionModuleItem extends ModuleItem {
|
|||
continue;
|
||||
if (!filter.isAllowed(stack))
|
||||
continue;
|
||||
ItemStack remain = network.tryInsertItem(tile.getPos(), tile.getPos().offset(dir), stack, this.preventOversending);
|
||||
ItemStack remain = network.routeItem(tile.getPos(), tile.getPos().offset(dir), stack, this.preventOversending);
|
||||
if (remain.getCount() != stack.getCount()) {
|
||||
handler.extractItem(j, stack.getCount() - remain.getCount(), false);
|
||||
return;
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
package de.ellpeck.prettypipes.pipe.modules.filter;
|
||||
|
||||
import de.ellpeck.prettypipes.misc.FilterSlot;
|
||||
import de.ellpeck.prettypipes.misc.ItemFilter;
|
||||
import de.ellpeck.prettypipes.pipe.containers.AbstractPipeContainer;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.inventory.container.ContainerType;
|
||||
import net.minecraft.inventory.container.Slot;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraftforge.items.ItemStackHandler;
|
||||
|
||||
public class FilterIncreaseModuleContainer extends AbstractPipeContainer<FilterIncreaseModuleItem> implements ItemFilter.IFilteredContainer {
|
||||
|
||||
public ItemFilter filter;
|
||||
|
||||
public FilterIncreaseModuleContainer(ContainerType<?> type, int id, PlayerEntity player, BlockPos pos, int moduleIndex) {
|
||||
super(type, id, player, pos, moduleIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addSlots() {
|
||||
this.filter = new ItemFilter(18, this.moduleStack, this.tile);
|
||||
this.filter.canModifyWhitelist = false;
|
||||
for (Slot slot : this.filter.getSlots(8, 49))
|
||||
this.addSlot(slot);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onContainerClosed(PlayerEntity playerIn) {
|
||||
super.onContainerClosed(playerIn);
|
||||
this.filter.save();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemFilter getFilter() {
|
||||
return this.filter;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package de.ellpeck.prettypipes.pipe.modules.filter;
|
||||
|
||||
import de.ellpeck.prettypipes.pipe.containers.AbstractPipeGui;
|
||||
import net.minecraft.entity.player.PlayerInventory;
|
||||
import net.minecraft.util.text.ITextComponent;
|
||||
|
||||
public class FilterIncreaseModuleGui extends AbstractPipeGui<FilterIncreaseModuleContainer> {
|
||||
public FilterIncreaseModuleGui(FilterIncreaseModuleContainer screenContainer, PlayerInventory inv, ITextComponent titleIn) {
|
||||
super(screenContainer, inv, titleIn);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
package de.ellpeck.prettypipes.pipe.modules.filter;
|
||||
|
||||
import de.ellpeck.prettypipes.Registry;
|
||||
import de.ellpeck.prettypipes.items.IModule;
|
||||
import de.ellpeck.prettypipes.items.ModuleItem;
|
||||
import de.ellpeck.prettypipes.misc.ItemFilter;
|
||||
import de.ellpeck.prettypipes.pipe.PipeTileEntity;
|
||||
import de.ellpeck.prettypipes.pipe.containers.AbstractPipeContainer;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.entity.player.PlayerInventory;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraftforge.items.ItemStackHandler;
|
||||
|
||||
public class FilterIncreaseModuleItem extends ModuleItem {
|
||||
|
||||
public FilterIncreaseModuleItem(String name) {
|
||||
super(name);
|
||||
this.setRegistryName(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCompatible(ItemStack module, PipeTileEntity tile, IModule other) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasContainer(ItemStack module, PipeTileEntity tile) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractPipeContainer<?> getContainer(ItemStack module, PipeTileEntity tile, int windowId, PlayerInventory inv, PlayerEntity player, int moduleIndex) {
|
||||
return new FilterIncreaseModuleContainer(Registry.filterIncreaseModuleContainer, windowId, player, tile.getPos(), moduleIndex);
|
||||
}
|
||||
}
|
|
@ -43,6 +43,7 @@ public class RetrievalModuleItem extends ModuleItem {
|
|||
PipeNetwork network = PipeNetwork.get(tile.getWorld());
|
||||
|
||||
ItemFilter filter = new ItemFilter(this.filterSlots, module, tile);
|
||||
ItemEqualityType[] equalityTypes = ItemFilter.getEqualityTypes(tile);
|
||||
filter.isWhitelist = true;
|
||||
// loop through filter to see which items to pull
|
||||
for (int f = 0; f < filter.getSlots(); f++) {
|
||||
|
@ -54,7 +55,10 @@ public class RetrievalModuleItem extends ModuleItem {
|
|||
Pair<BlockPos, ItemStack> dest = tile.getAvailableDestination(copy, true, this.preventOversending);
|
||||
if (dest == null)
|
||||
continue;
|
||||
if (network.requestItem(tile.getPos(), dest.getLeft(), dest.getRight(), filter.getEqualityTypes()).isEmpty())
|
||||
ItemStack remain = dest.getRight().copy();
|
||||
// are we already waiting for crafting results? If so, don't request those again
|
||||
remain.shrink(network.getCurrentlyCraftingAmount(tile.getPos(), copy, equalityTypes));
|
||||
if (network.requestItem(tile.getPos(), dest.getLeft(), remain, equalityTypes).isEmpty())
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
package de.ellpeck.prettypipes.pressurizer;
|
||||
|
||||
import de.ellpeck.prettypipes.Utility;
|
||||
import de.ellpeck.prettypipes.pipe.ConnectionType;
|
||||
import de.ellpeck.prettypipes.pipe.IPipeConnectable;
|
||||
import de.ellpeck.prettypipes.terminal.ItemTerminalTileEntity;
|
||||
import net.minecraft.block.BlockRenderType;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.ContainerBlock;
|
||||
import net.minecraft.block.SoundType;
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.client.util.ITooltipFlag;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.entity.player.ServerPlayerEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.ActionResultType;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.BlockRayTraceResult;
|
||||
import net.minecraft.util.text.ITextComponent;
|
||||
import net.minecraft.world.IBlockReader;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.fml.network.NetworkHooks;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.List;
|
||||
|
||||
public class PressurizerBlock extends ContainerBlock {
|
||||
public PressurizerBlock() {
|
||||
super(Properties.create(Material.ROCK).hardnessAndResistance(3).sound(SoundType.STONE));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActionResultType onBlockActivated(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand handIn, BlockRayTraceResult result) {
|
||||
PressurizerTileEntity tile = Utility.getTileEntity(PressurizerTileEntity.class, worldIn, pos);
|
||||
if (tile == null)
|
||||
return ActionResultType.PASS;
|
||||
if (!worldIn.isRemote)
|
||||
NetworkHooks.openGui((ServerPlayerEntity) player, tile, pos);
|
||||
return ActionResultType.SUCCESS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TileEntity createNewTileEntity(IBlockReader worldIn) {
|
||||
return new PressurizerTileEntity();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockRenderType getRenderType(BlockState state) {
|
||||
return BlockRenderType.MODEL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addInformation(ItemStack stack, @Nullable IBlockReader worldIn, List<ITextComponent> tooltip, ITooltipFlag flagIn) {
|
||||
Utility.addTooltip(this.getRegistryName().getPath(), tooltip);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
package de.ellpeck.prettypipes.pressurizer;
|
||||
|
||||
import de.ellpeck.prettypipes.Utility;
|
||||
import de.ellpeck.prettypipes.terminal.ItemTerminalTileEntity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.inventory.container.Container;
|
||||
import net.minecraft.inventory.container.ContainerType;
|
||||
import net.minecraft.inventory.container.Slot;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class PressurizerContainer extends Container {
|
||||
public final PressurizerTileEntity tile;
|
||||
|
||||
public PressurizerContainer(@Nullable ContainerType<?> type, int id, PlayerEntity player, BlockPos pos) {
|
||||
super(type, id);
|
||||
this.tile = Utility.getTileEntity(PressurizerTileEntity.class, player.world, pos);
|
||||
|
||||
for (int l = 0; l < 3; ++l)
|
||||
for (int j1 = 0; j1 < 9; ++j1)
|
||||
this.addSlot(new Slot(player.inventory, j1 + l * 9 + 9, 8 + j1 * 18, 55 + l * 18));
|
||||
for (int i1 = 0; i1 < 9; ++i1)
|
||||
this.addSlot(new Slot(player.inventory, i1, 8 + i1 * 18, 113));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack transferStackInSlot(PlayerEntity player, int slotIndex) {
|
||||
return Utility.transferStackInSlot(this, this::mergeItemStack, player, slotIndex, stack -> null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canInteractWith(PlayerEntity playerIn) {
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
package de.ellpeck.prettypipes.pressurizer;
|
||||
|
||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||
import de.ellpeck.prettypipes.PrettyPipes;
|
||||
import net.minecraft.client.gui.screen.inventory.ContainerScreen;
|
||||
import net.minecraft.client.gui.widget.Widget;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
import net.minecraft.entity.player.PlayerInventory;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.text.ITextComponent;
|
||||
import net.minecraft.util.text.TranslationTextComponent;
|
||||
|
||||
public class PressurizerGui extends ContainerScreen<PressurizerContainer> {
|
||||
private static final ResourceLocation TEXTURE = new ResourceLocation(PrettyPipes.ID, "textures/gui/pressurizer.png");
|
||||
|
||||
public PressurizerGui(PressurizerContainer screenContainer, PlayerInventory inv, ITextComponent titleIn) {
|
||||
super(screenContainer, inv, titleIn);
|
||||
this.xSize = 176;
|
||||
this.ySize = 137;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(int mouseX, int mouseY, float partialTicks) {
|
||||
this.renderBackground();
|
||||
super.render(mouseX, mouseY, partialTicks);
|
||||
// this.func_230459_a_(matrix, mouseX, mouseY);
|
||||
if (mouseX >= this.guiLeft + 26 && mouseY >= this.guiTop + 22 && mouseX < this.guiLeft + 26 + 124 && mouseY < this.guiTop + 22 + 12)
|
||||
this.renderTooltip(I18n.format("info." + PrettyPipes.ID + ".energy", this.container.tile.getEnergy(), this.container.tile.getMaxEnergy()), mouseX, mouseY);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void drawGuiContainerForegroundLayer(int mouseX, int mouseY) {
|
||||
this.font.drawString(this.playerInventory.getDisplayName().getString(), 8, this.ySize - 96 + 2, 4210752);
|
||||
this.font.drawString(this.title.getString(), 8, 6, 4210752);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void drawGuiContainerBackgroundLayer(float partialTicks, int x, int y) {
|
||||
this.getMinecraft().getTextureManager().bindTexture(TEXTURE);
|
||||
this.blit(this.guiLeft, this.guiTop, 0, 0, 176, 137);
|
||||
int energy = (int) (this.container.tile.getEnergyPercentage() * 124);
|
||||
this.blit(this.guiLeft + 26, this.guiTop + 22, 0, 137, energy, 12);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,168 @@
|
|||
package de.ellpeck.prettypipes.pressurizer;
|
||||
|
||||
import de.ellpeck.prettypipes.PrettyPipes;
|
||||
import de.ellpeck.prettypipes.Registry;
|
||||
import de.ellpeck.prettypipes.Utility;
|
||||
import de.ellpeck.prettypipes.network.PipeNetwork;
|
||||
import de.ellpeck.prettypipes.pipe.ConnectionType;
|
||||
import de.ellpeck.prettypipes.pipe.IPipeConnectable;
|
||||
import de.ellpeck.prettypipes.pipe.PipeTileEntity;
|
||||
import de.ellpeck.prettypipes.terminal.containers.ItemTerminalContainer;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.entity.player.PlayerInventory;
|
||||
import net.minecraft.inventory.container.Container;
|
||||
import net.minecraft.inventory.container.INamedContainerProvider;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraft.network.NetworkManager;
|
||||
import net.minecraft.network.play.server.SUpdateTileEntityPacket;
|
||||
import net.minecraft.tileentity.ITickableTileEntity;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.tileentity.TileEntityType;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.text.ITextComponent;
|
||||
import net.minecraft.util.text.TranslationTextComponent;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.common.capabilities.Capability;
|
||||
import net.minecraftforge.common.util.LazyOptional;
|
||||
import net.minecraftforge.energy.CapabilityEnergy;
|
||||
import net.minecraftforge.energy.EnergyStorage;
|
||||
import net.minecraftforge.energy.IEnergyStorage;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class PressurizerTileEntity extends TileEntity implements INamedContainerProvider, ITickableTileEntity, IPipeConnectable {
|
||||
|
||||
private final ModifiableEnergyStorage storage = new ModifiableEnergyStorage(64000, 512, 0);
|
||||
private final LazyOptional<IEnergyStorage> lazyStorage = LazyOptional.of(() -> this.storage);
|
||||
private final LazyOptional<IPipeConnectable> lazyThis = LazyOptional.of(() -> this);
|
||||
private int lastEnergy;
|
||||
|
||||
public PressurizerTileEntity() {
|
||||
super(Registry.pressurizerTileEntity);
|
||||
}
|
||||
|
||||
public boolean pressurizeItem(ItemStack stack, boolean simulate) {
|
||||
int amount = 100 * stack.getCount();
|
||||
return this.storage.extractInternal(amount, simulate) >= amount;
|
||||
}
|
||||
|
||||
public float getEnergyPercentage() {
|
||||
return this.getEnergy() / (float) this.getMaxEnergy();
|
||||
}
|
||||
|
||||
public int getEnergy() {
|
||||
return this.storage.getEnergyStored();
|
||||
}
|
||||
|
||||
public int getMaxEnergy() {
|
||||
return this.storage.getMaxEnergyStored();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundNBT write(CompoundNBT compound) {
|
||||
compound.putInt("energy", this.getEnergy());
|
||||
return super.write(compound);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(CompoundNBT nbt) {
|
||||
this.storage.setEnergyStored(nbt.getInt("energy"));
|
||||
super.read(nbt);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundNBT getUpdateTag() {
|
||||
return this.write(new CompoundNBT());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleUpdateTag(CompoundNBT tag) {
|
||||
this.read(tag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDataPacket(NetworkManager net, SUpdateTileEntityPacket pkt) {
|
||||
this.read(pkt.getNbtCompound());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ITextComponent getDisplayName() {
|
||||
return new TranslationTextComponent("container." + PrettyPipes.ID + ".pressurizer");
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Container createMenu(int window, PlayerInventory inv, PlayerEntity player) {
|
||||
return new PressurizerContainer(Registry.pressurizerContainer, window, player, this.pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> LazyOptional<T> getCapability(Capability<T> cap, Direction side) {
|
||||
if (cap == CapabilityEnergy.ENERGY) {
|
||||
return this.lazyStorage.cast();
|
||||
} else if (cap == Registry.pipeConnectableCapability) {
|
||||
return this.lazyThis.cast();
|
||||
} else {
|
||||
return LazyOptional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
super.remove();
|
||||
this.lazyStorage.invalidate();
|
||||
this.lazyThis.invalidate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
if (this.world.isRemote)
|
||||
return;
|
||||
// notify pipes in network about us
|
||||
if (this.world.getGameTime() % 10 == 0) {
|
||||
PipeNetwork network = PipeNetwork.get(this.world);
|
||||
for (Direction dir : Direction.values()) {
|
||||
BlockPos offset = this.pos.offset(dir);
|
||||
for (BlockPos node : network.getOrderedNetworkNodes(offset)) {
|
||||
if (!this.world.isBlockLoaded(node))
|
||||
continue;
|
||||
PipeTileEntity pipe = network.getPipe(node);
|
||||
if (pipe != null)
|
||||
pipe.pressurizer = this;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// send energy update
|
||||
if (this.lastEnergy != this.storage.getEnergyStored() && this.world.getGameTime() % 10 == 0) {
|
||||
this.lastEnergy = this.storage.getEnergyStored();
|
||||
Utility.sendTileEntityToClients(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConnectionType getConnectionType(BlockPos pipePos, Direction direction) {
|
||||
return ConnectionType.CONNECTED;
|
||||
}
|
||||
|
||||
private static class ModifiableEnergyStorage extends EnergyStorage {
|
||||
|
||||
public ModifiableEnergyStorage(int capacity, int maxReceive, int maxExtract) {
|
||||
super(capacity, maxReceive, maxExtract);
|
||||
}
|
||||
|
||||
private void setEnergyStored(int energy) {
|
||||
this.energy = energy;
|
||||
}
|
||||
|
||||
private int extractInternal(int maxExtract, boolean simulate) {
|
||||
int energyExtracted = Math.min(this.energy, maxExtract);
|
||||
if (!simulate)
|
||||
this.energy -= energyExtracted;
|
||||
return energyExtracted;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,16 +1,7 @@
|
|||
package de.ellpeck.prettypipes.terminal;
|
||||
|
||||
import de.ellpeck.prettypipes.Utility;
|
||||
import de.ellpeck.prettypipes.misc.ItemEqualityType;
|
||||
import de.ellpeck.prettypipes.network.PipeItem;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.IBlockReader;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.items.ItemHandlerHelper;
|
||||
import net.minecraftforge.items.wrapper.CombinedInvWrapper;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
|
@ -22,34 +13,4 @@ public class CraftingTerminalBlock extends ItemTerminalBlock {
|
|||
return new CraftingTerminalTileEntity();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack insertItem(World world, BlockPos pipePos, Direction direction, PipeItem item) {
|
||||
BlockPos pos = pipePos.offset(direction);
|
||||
CraftingTerminalTileEntity tile = Utility.getTileEntity(CraftingTerminalTileEntity.class, world, pos);
|
||||
if (tile != null) {
|
||||
ItemStack remain = item.stack;
|
||||
int lowestSlot = -1;
|
||||
do {
|
||||
for (int i = 0; i < tile.craftItems.getSlots(); i++) {
|
||||
ItemStack stack = tile.getRequestedCraftItem(i);
|
||||
int count = tile.isGhostItem(i) ? 0 : stack.getCount();
|
||||
if (!ItemHandlerHelper.canItemStacksStackRelaxed(stack, remain))
|
||||
continue;
|
||||
if (lowestSlot < 0 || !tile.isGhostItem(lowestSlot) && count < tile.getRequestedCraftItem(lowestSlot).getCount())
|
||||
lowestSlot = i;
|
||||
}
|
||||
if (lowestSlot >= 0) {
|
||||
ItemStack copy = remain.copy();
|
||||
copy.setCount(1);
|
||||
remain.shrink(1 - tile.craftItems.insertItem(lowestSlot, copy, false).getCount());
|
||||
if (remain.isEmpty())
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
}
|
||||
while (lowestSlot >= 0);
|
||||
return ItemHandlerHelper.insertItemStacked(tile.items, remain, false);
|
||||
}
|
||||
return item.stack;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -4,32 +4,37 @@ import com.google.common.collect.ArrayListMultimap;
|
|||
import com.google.common.collect.ListMultimap;
|
||||
import de.ellpeck.prettypipes.PrettyPipes;
|
||||
import de.ellpeck.prettypipes.Registry;
|
||||
import de.ellpeck.prettypipes.Utility;
|
||||
import de.ellpeck.prettypipes.misc.EquatableItemStack;
|
||||
import de.ellpeck.prettypipes.misc.ItemEqualityType;
|
||||
import de.ellpeck.prettypipes.network.NetworkItem;
|
||||
import de.ellpeck.prettypipes.network.NetworkLocation;
|
||||
import de.ellpeck.prettypipes.network.NetworkLock;
|
||||
import de.ellpeck.prettypipes.network.PipeNetwork;
|
||||
import de.ellpeck.prettypipes.packets.PacketGhostSlot;
|
||||
import de.ellpeck.prettypipes.packets.PacketHandler;
|
||||
import de.ellpeck.prettypipes.pipe.PipeTileEntity;
|
||||
import de.ellpeck.prettypipes.terminal.containers.CraftingTerminalContainer;
|
||||
import de.ellpeck.prettypipes.terminal.containers.ItemTerminalContainer;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.entity.player.PlayerInventory;
|
||||
import net.minecraft.inventory.container.Container;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.text.ITextComponent;
|
||||
import net.minecraft.util.text.Style;
|
||||
import net.minecraft.util.text.TextFormatting;
|
||||
import net.minecraft.util.text.TranslationTextComponent;
|
||||
import net.minecraftforge.items.ItemHandlerHelper;
|
||||
import net.minecraftforge.items.ItemStackHandler;
|
||||
import org.apache.commons.lang3.mutable.MutableInt;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.*;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public class CraftingTerminalTileEntity extends ItemTerminalTileEntity {
|
||||
|
||||
|
@ -59,29 +64,38 @@ public class CraftingTerminalTileEntity extends ItemTerminalTileEntity {
|
|||
|
||||
public void setGhostItems(ListMultimap<Integer, ItemStack> stacks) {
|
||||
this.updateItems();
|
||||
items:
|
||||
for (int i = 0; i < this.ghostItems.getSlots(); i++) {
|
||||
List<ItemStack> items = stacks.get(i);
|
||||
if (items.isEmpty()) {
|
||||
this.ghostItems.setStackInSlot(i, ItemStack.EMPTY);
|
||||
continue;
|
||||
}
|
||||
ItemStack toSet = items.get(0);
|
||||
// if we have more than one item to choose from, we want to pick the one that we have most of in the system
|
||||
if (items.size() > 1) {
|
||||
// set the item into the ghost slot that already has a variant of itself available in the system
|
||||
int highestAmount = 0;
|
||||
for (ItemStack stack : items) {
|
||||
EquatableItemStack equatable = new EquatableItemStack(stack);
|
||||
NetworkItem network = this.networkItems.get(equatable);
|
||||
if (network == null)
|
||||
continue;
|
||||
if (network.getLocations().stream().anyMatch(l -> l.getItemAmount(this.world, stack, ItemEqualityType.NBT) > 0)) {
|
||||
this.ghostItems.setStackInSlot(i, stack);
|
||||
continue items;
|
||||
int amount = 0;
|
||||
// check existing items
|
||||
NetworkItem network = this.networkItems.get(new EquatableItemStack(stack));
|
||||
if (network != null) {
|
||||
amount = network.getLocations().stream()
|
||||
.mapToInt(l -> l.getItemAmount(this.world, stack, ItemEqualityType.NBT))
|
||||
.sum();
|
||||
}
|
||||
// check craftables
|
||||
if (amount <= 0 && highestAmount <= 0) {
|
||||
PipeTileEntity pipe = this.getConnectedPipe();
|
||||
if (pipe != null)
|
||||
amount = PipeNetwork.get(this.world).getCraftableAmount(pipe.getPos(), null, stack, ItemEqualityType.NBT);
|
||||
}
|
||||
if (amount > highestAmount) {
|
||||
highestAmount = amount;
|
||||
toSet = stack;
|
||||
}
|
||||
}
|
||||
}
|
||||
// if the ghost slot wasn't set, then we don't have the item in the system
|
||||
// so just pick a random one to put into the slot
|
||||
this.ghostItems.setStackInSlot(i, items.get(0));
|
||||
this.ghostItems.setStackInSlot(i, toSet.copy());
|
||||
}
|
||||
|
||||
if (!this.world.isRemote) {
|
||||
|
@ -92,60 +106,29 @@ public class CraftingTerminalTileEntity extends ItemTerminalTileEntity {
|
|||
}
|
||||
}
|
||||
|
||||
public void requestCraftingItems(PlayerEntity player, boolean all) {
|
||||
public void requestCraftingItems(PlayerEntity player, int maxAmount) {
|
||||
PipeTileEntity pipe = this.getConnectedPipe();
|
||||
if (pipe == null)
|
||||
return;
|
||||
PipeNetwork network = PipeNetwork.get(this.world);
|
||||
network.startProfile("terminal_request_crafting");
|
||||
this.updateItems();
|
||||
|
||||
// the highest amount we can craft with the items we have
|
||||
int lowestAvailable = Integer.MAX_VALUE;
|
||||
// this is the amount of items required for each ingredient when crafting ONE
|
||||
Map<EquatableItemStack, MutableInt> requiredItems = new HashMap<>();
|
||||
for (int i = 0; i < this.craftItems.getSlots(); i++) {
|
||||
ItemStack requested = this.getRequestedCraftItem(i);
|
||||
if (requested.isEmpty())
|
||||
continue;
|
||||
MutableInt amount = requiredItems.computeIfAbsent(new EquatableItemStack(requested), s -> new MutableInt());
|
||||
amount.add(1);
|
||||
int fit = requested.getMaxStackSize() - (this.isGhostItem(i) ? 0 : requested.getCount());
|
||||
if (lowestAvailable > fit)
|
||||
lowestAvailable = fit;
|
||||
}
|
||||
for (Map.Entry<EquatableItemStack, MutableInt> entry : requiredItems.entrySet()) {
|
||||
EquatableItemStack stack = entry.getKey();
|
||||
NetworkItem item = this.networkItems.get(stack);
|
||||
// total amount of available items of this type
|
||||
int available = 0;
|
||||
if (item != null) {
|
||||
for (NetworkLocation location : item.getLocations()) {
|
||||
int amount = location.getItemAmount(this.world, stack.stack, ItemEqualityType.NBT);
|
||||
if (amount <= 0)
|
||||
continue;
|
||||
amount -= network.getLockedAmount(location.getPos(), stack.stack, ItemEqualityType.NBT);
|
||||
available += amount;
|
||||
}
|
||||
// divide the total by the amount required to get the amount that
|
||||
// we have available for each crafting slot that contains this item
|
||||
available /= entry.getValue().intValue();
|
||||
if (available < lowestAvailable)
|
||||
lowestAvailable = available;
|
||||
} else {
|
||||
lowestAvailable = 0;
|
||||
}
|
||||
if (available <= 0)
|
||||
player.sendMessage(new TranslationTextComponent("info." + PrettyPipes.ID + ".not_found", stack.stack.getDisplayName()).setStyle(new Style().setColor(TextFormatting.RED)));
|
||||
}
|
||||
// get the amount of crafts that we can do
|
||||
int lowestAvailable = getAvailableCrafts(pipe, this.craftItems.getSlots(), i -> ItemHandlerHelper.copyStackWithSize(this.getRequestedCraftItem(i), 1), this::isGhostItem, s -> {
|
||||
NetworkItem item = this.networkItems.get(s);
|
||||
return item != null ? item.getLocations() : Collections.emptyList();
|
||||
}, onItemUnavailable(player), ItemEqualityType.NBT);
|
||||
if (lowestAvailable > 0) {
|
||||
// if we're only crafting one item, pretend we only have enough for one
|
||||
if (!all)
|
||||
lowestAvailable = 1;
|
||||
// if we're limiting the amount, pretend we only have that amount available
|
||||
if (maxAmount < lowestAvailable)
|
||||
lowestAvailable = maxAmount;
|
||||
for (int i = 0; i < this.craftItems.getSlots(); i++) {
|
||||
ItemStack requested = this.getRequestedCraftItem(i);
|
||||
if (requested.isEmpty())
|
||||
continue;
|
||||
requested = requested.copy();
|
||||
requested.setCount(lowestAvailable);
|
||||
this.requestItemImpl(requested);
|
||||
this.requestItemImpl(requested, onItemUnavailable(player));
|
||||
}
|
||||
player.sendMessage(new TranslationTextComponent("info." + PrettyPipes.ID + ".sending_ingredients", lowestAvailable).setStyle(new Style().setColor(TextFormatting.GREEN)));
|
||||
}
|
||||
|
@ -174,4 +157,90 @@ public class CraftingTerminalTileEntity extends ItemTerminalTileEntity {
|
|||
public Container createMenu(int window, PlayerInventory inv, PlayerEntity player) {
|
||||
return new CraftingTerminalContainer(Registry.craftingTerminalContainer, window, player, this.pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack insertItem(BlockPos pipePos, Direction direction, ItemStack remain, boolean simulate) {
|
||||
BlockPos pos = pipePos.offset(direction);
|
||||
CraftingTerminalTileEntity tile = Utility.getTileEntity(CraftingTerminalTileEntity.class, this.world, pos);
|
||||
if (tile != null) {
|
||||
remain = remain.copy();
|
||||
int lowestSlot = -1;
|
||||
do {
|
||||
for (int i = 0; i < tile.craftItems.getSlots(); i++) {
|
||||
ItemStack stack = tile.getRequestedCraftItem(i);
|
||||
int count = tile.isGhostItem(i) ? 0 : stack.getCount();
|
||||
if (!ItemHandlerHelper.canItemStacksStack(stack, remain))
|
||||
continue;
|
||||
// ensure that a single non-stackable item can still enter a ghost slot
|
||||
if (!stack.isStackable() && count >= 1)
|
||||
continue;
|
||||
if (lowestSlot < 0 || !tile.isGhostItem(lowestSlot) && count < tile.getRequestedCraftItem(lowestSlot).getCount())
|
||||
lowestSlot = i;
|
||||
}
|
||||
if (lowestSlot >= 0) {
|
||||
ItemStack copy = remain.copy();
|
||||
copy.setCount(1);
|
||||
// if there were remaining items inserting into the slot with lowest contents, we're overflowing
|
||||
if (tile.craftItems.insertItem(lowestSlot, copy, simulate).getCount() > 0)
|
||||
break;
|
||||
remain.shrink(1);
|
||||
if (remain.isEmpty())
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
}
|
||||
while (lowestSlot >= 0);
|
||||
return ItemHandlerHelper.insertItemStacked(tile.items, remain, simulate);
|
||||
}
|
||||
return remain;
|
||||
}
|
||||
|
||||
public static int getAvailableCrafts(PipeTileEntity tile, int slots, Function<Integer, ItemStack> inputFunction, Predicate<Integer> isGhost, Function<EquatableItemStack, Collection<NetworkLocation>> locationsFunction, Consumer<ItemStack> unavailableConsumer, ItemEqualityType... equalityTypes) {
|
||||
PipeNetwork network = PipeNetwork.get(tile.getWorld());
|
||||
// the highest amount we can craft with the items we have
|
||||
int lowestAvailable = Integer.MAX_VALUE;
|
||||
// this is the amount of items required for each ingredient when crafting ONE
|
||||
Map<EquatableItemStack, MutableInt> requiredItems = new HashMap<>();
|
||||
for (int i = 0; i < slots; i++) {
|
||||
ItemStack requested = inputFunction.apply(i);
|
||||
if (requested.isEmpty())
|
||||
continue;
|
||||
MutableInt amount = requiredItems.computeIfAbsent(new EquatableItemStack(requested), s -> new MutableInt());
|
||||
amount.add(requested.getCount());
|
||||
// if no items fit into the crafting input, we still want to pretend they do for requesting
|
||||
int fit = Math.max(requested.getMaxStackSize() - (isGhost.test(i) ? 0 : requested.getCount()), 1);
|
||||
if (lowestAvailable > fit)
|
||||
lowestAvailable = fit;
|
||||
}
|
||||
for (Map.Entry<EquatableItemStack, MutableInt> entry : requiredItems.entrySet()) {
|
||||
EquatableItemStack stack = entry.getKey();
|
||||
|
||||
// total amount of available items of this type
|
||||
int available = 0;
|
||||
for (NetworkLocation location : locationsFunction.apply(stack)) {
|
||||
int amount = location.getItemAmount(tile.getWorld(), stack.stack, equalityTypes);
|
||||
if (amount <= 0)
|
||||
continue;
|
||||
amount -= network.getLockedAmount(location.getPos(), stack.stack, null, equalityTypes);
|
||||
available += amount;
|
||||
}
|
||||
// divide the total by the amount required to get the amount that
|
||||
// we have available for each crafting slot that contains this item
|
||||
available /= entry.getValue().intValue();
|
||||
|
||||
// check how many craftable items we have and add those on if we need to
|
||||
if (available < lowestAvailable) {
|
||||
int craftable = network.getCraftableAmount(tile.getPos(), unavailableConsumer, stack.stack, equalityTypes);
|
||||
if (craftable > 0)
|
||||
available += craftable / entry.getValue().intValue();
|
||||
}
|
||||
|
||||
// clamp to lowest available
|
||||
if (available < lowestAvailable)
|
||||
lowestAvailable = available;
|
||||
|
||||
if (available <= 0 && unavailableConsumer != null)
|
||||
unavailableConsumer.accept(stack.stack);
|
||||
}
|
||||
return lowestAvailable;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ import net.minecraftforge.items.ItemHandlerHelper;
|
|||
import javax.annotation.Nullable;
|
||||
import java.util.List;
|
||||
|
||||
public class ItemTerminalBlock extends ContainerBlock implements IPipeConnectable {
|
||||
public class ItemTerminalBlock extends ContainerBlock {
|
||||
public ItemTerminalBlock() {
|
||||
super(Properties.create(Material.ROCK).hardnessAndResistance(3).sound(SoundType.STONE));
|
||||
}
|
||||
|
@ -63,25 +63,6 @@ public class ItemTerminalBlock extends ContainerBlock implements IPipeConnectabl
|
|||
return new ItemTerminalTileEntity();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConnectionType getConnectionType(World world, BlockPos pipePos, Direction direction) {
|
||||
return ConnectionType.CONNECTED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack insertItem(World world, BlockPos pipePos, Direction direction, PipeItem item) {
|
||||
BlockPos pos = pipePos.offset(direction);
|
||||
ItemTerminalTileEntity tile = Utility.getTileEntity(ItemTerminalTileEntity.class, world, pos);
|
||||
if (tile != null)
|
||||
return ItemHandlerHelper.insertItemStacked(tile.items, item.stack, false);
|
||||
return item.stack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean allowsModules(World world, BlockPos pipePos, Direction direction) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockRenderType getRenderType(BlockState state) {
|
||||
return BlockRenderType.MODEL;
|
||||
|
|
|
@ -9,8 +9,11 @@ import de.ellpeck.prettypipes.misc.ItemOrder;
|
|||
import de.ellpeck.prettypipes.network.*;
|
||||
import de.ellpeck.prettypipes.packets.PacketHandler;
|
||||
import de.ellpeck.prettypipes.packets.PacketNetworkItems;
|
||||
import de.ellpeck.prettypipes.pipe.ConnectionType;
|
||||
import de.ellpeck.prettypipes.pipe.IPipeConnectable;
|
||||
import de.ellpeck.prettypipes.pipe.PipeTileEntity;
|
||||
import de.ellpeck.prettypipes.terminal.containers.ItemTerminalContainer;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.entity.player.PlayerInventory;
|
||||
import net.minecraft.entity.player.ServerPlayerEntity;
|
||||
|
@ -27,10 +30,14 @@ import net.minecraft.util.text.ITextComponent;
|
|||
import net.minecraft.util.text.Style;
|
||||
import net.minecraft.util.text.TextFormatting;
|
||||
import net.minecraft.util.text.TranslationTextComponent;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.server.ServerWorld;
|
||||
import net.minecraftforge.common.capabilities.Capability;
|
||||
import net.minecraftforge.common.util.Constants;
|
||||
import net.minecraftforge.common.util.Constants.NBT;
|
||||
import net.minecraftforge.common.util.LazyOptional;
|
||||
import net.minecraftforge.items.IItemHandler;
|
||||
import net.minecraftforge.items.ItemHandlerHelper;
|
||||
import net.minecraftforge.items.ItemStackHandler;
|
||||
import org.apache.commons.lang3.mutable.MutableInt;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
@ -39,9 +46,11 @@ import org.apache.commons.lang3.tuple.Triple;
|
|||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.*;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class ItemTerminalTileEntity extends TileEntity implements INamedContainerProvider, ITickableTileEntity {
|
||||
public class ItemTerminalTileEntity extends TileEntity implements INamedContainerProvider, ITickableTileEntity, IPipeConnectable {
|
||||
|
||||
public final ItemStackHandler items = new ItemStackHandler(12) {
|
||||
@Override
|
||||
|
@ -49,8 +58,9 @@ public class ItemTerminalTileEntity extends TileEntity implements INamedContaine
|
|||
return true;
|
||||
}
|
||||
};
|
||||
public Map<EquatableItemStack, NetworkItem> networkItems;
|
||||
private final Queue<NetworkLock> pendingRequests = new ArrayDeque<>();
|
||||
protected Map<EquatableItemStack, NetworkItem> networkItems;
|
||||
private final Queue<NetworkLock> existingRequests = new LinkedList<>();
|
||||
private final LazyOptional<IPipeConnectable> lazyThis = LazyOptional.of(() -> this);
|
||||
|
||||
protected ItemTerminalTileEntity(TileEntityType<?> tileEntityTypeIn) {
|
||||
super(tileEntityTypeIn);
|
||||
|
@ -70,22 +80,23 @@ public class ItemTerminalTileEntity extends TileEntity implements INamedContaine
|
|||
return;
|
||||
|
||||
boolean update = false;
|
||||
if (this.world.getGameTime() % 10 == 0) {
|
||||
int interval = pipe.pressurizer != null ? 2 : 10;
|
||||
if (this.world.getGameTime() % interval == 0) {
|
||||
for (int i = 6; i < 12; i++) {
|
||||
ItemStack extracted = this.items.extractItem(i, Integer.MAX_VALUE, true);
|
||||
if (extracted.isEmpty())
|
||||
continue;
|
||||
ItemStack remain = network.tryInsertItem(pipe.getPos(), this.pos, extracted, true);
|
||||
ItemStack remain = network.routeItem(pipe.getPos(), this.pos, extracted, true);
|
||||
if (remain.getCount() == extracted.getCount())
|
||||
continue;
|
||||
this.items.extractItem(i, extracted.getCount() - remain.getCount(), false);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!this.pendingRequests.isEmpty()) {
|
||||
NetworkLock request = this.pendingRequests.remove();
|
||||
if (!this.existingRequests.isEmpty()) {
|
||||
NetworkLock request = this.existingRequests.remove();
|
||||
network.resolveNetworkLock(request);
|
||||
network.requestItem(request.location, pipe.getPos(), this.pos, request.stack, ItemEqualityType.NBT);
|
||||
network.requestExistingItem(request.location, pipe.getPos(), this.pos, request, request.stack, ItemEqualityType.NBT);
|
||||
update = true;
|
||||
}
|
||||
}
|
||||
|
@ -101,8 +112,9 @@ public class ItemTerminalTileEntity extends TileEntity implements INamedContaine
|
|||
public void remove() {
|
||||
super.remove();
|
||||
PipeNetwork network = PipeNetwork.get(this.world);
|
||||
for (NetworkLock lock : this.pendingRequests)
|
||||
for (NetworkLock lock : this.existingRequests)
|
||||
network.resolveNetworkLock(lock);
|
||||
this.lazyThis.invalidate();
|
||||
}
|
||||
|
||||
public PipeTileEntity getConnectedPipe() {
|
||||
|
@ -116,18 +128,21 @@ public class ItemTerminalTileEntity extends TileEntity implements INamedContaine
|
|||
}
|
||||
|
||||
public void updateItems(PlayerEntity... playersToSync) {
|
||||
if (this.getConnectedPipe() == null)
|
||||
PipeTileEntity pipe = this.getConnectedPipe();
|
||||
if (pipe == null)
|
||||
return;
|
||||
this.networkItems = this.collectItems();
|
||||
if (playersToSync.length > 0) {
|
||||
List<ItemStack> clientItems = this.networkItems.values().stream().map(NetworkItem::asStack).collect(Collectors.toList());
|
||||
List<ItemStack> clientCraftables = PipeNetwork.get(this.world).getAllCraftables(pipe.getPos()).stream().map(Pair::getRight).collect(Collectors.toList());
|
||||
List<ItemStack> currentlyCrafting = this.getCurrentlyCrafting().stream().sorted(Comparator.comparingInt(ItemStack::getCount).reversed()).collect(Collectors.toList());
|
||||
for (PlayerEntity player : playersToSync) {
|
||||
if (!(player.openContainer instanceof ItemTerminalContainer))
|
||||
continue;
|
||||
ItemTerminalTileEntity tile = ((ItemTerminalContainer) player.openContainer).tile;
|
||||
if (tile != this)
|
||||
continue;
|
||||
PacketHandler.sendTo(player, new PacketNetworkItems(clientItems));
|
||||
PacketHandler.sendTo(player, new PacketNetworkItems(clientItems, clientCraftables, currentlyCrafting));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -136,46 +151,21 @@ public class ItemTerminalTileEntity extends TileEntity implements INamedContaine
|
|||
PipeNetwork network = PipeNetwork.get(this.world);
|
||||
network.startProfile("terminal_request_item");
|
||||
this.updateItems();
|
||||
int requested = this.requestItemImpl(stack);
|
||||
int requested = this.requestItemImpl(stack, onItemUnavailable(player));
|
||||
if (requested > 0) {
|
||||
player.sendMessage(new TranslationTextComponent("info." + PrettyPipes.ID + ".sending", requested, stack.getDisplayName()).setStyle(new Style().setColor(TextFormatting.GREEN)));
|
||||
} else {
|
||||
player.sendMessage(new TranslationTextComponent("info." + PrettyPipes.ID + ".not_found", stack.getDisplayName()).setStyle(new Style().setColor(TextFormatting.RED)));
|
||||
onItemUnavailable(player).accept(stack);
|
||||
}
|
||||
network.endProfile();
|
||||
}
|
||||
|
||||
protected int requestItemImpl(ItemStack stack) {
|
||||
PipeNetwork network = PipeNetwork.get(this.world);
|
||||
EquatableItemStack equatable = new EquatableItemStack(stack);
|
||||
NetworkItem item = this.networkItems.get(equatable);
|
||||
if (item != null) {
|
||||
int remain = stack.getCount();
|
||||
for (NetworkLocation location : item.getLocations()) {
|
||||
int amount = location.getItemAmount(this.world, stack, ItemEqualityType.NBT);
|
||||
if (amount <= 0)
|
||||
continue;
|
||||
amount -= network.getLockedAmount(location.getPos(), stack, ItemEqualityType.NBT);
|
||||
if (amount > 0) {
|
||||
if (remain < amount)
|
||||
amount = remain;
|
||||
remain -= amount;
|
||||
while (amount > 0) {
|
||||
ItemStack copy = stack.copy();
|
||||
copy.setCount(Math.min(stack.getMaxStackSize(), amount));
|
||||
NetworkLock lock = new NetworkLock(location, copy);
|
||||
this.pendingRequests.add(lock);
|
||||
network.createNetworkLock(lock);
|
||||
amount -= copy.getCount();
|
||||
|
||||
}
|
||||
if (remain <= 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
return stack.getCount() - remain;
|
||||
}
|
||||
return 0;
|
||||
public int requestItemImpl(ItemStack stack, Consumer<ItemStack> unavailableConsumer) {
|
||||
NetworkItem item = this.networkItems.get(new EquatableItemStack(stack));
|
||||
Collection<NetworkLocation> locations = item == null ? Collections.emptyList() : item.getLocations();
|
||||
Pair<List<NetworkLock>, ItemStack> ret = requestItemLater(this.world, this.getConnectedPipe().getPos(), locations, unavailableConsumer, stack, ItemEqualityType.NBT);
|
||||
this.existingRequests.addAll(ret.getLeft());
|
||||
return stack.getCount() - ret.getRight().getCount();
|
||||
}
|
||||
|
||||
protected PlayerEntity[] getLookingPlayers() {
|
||||
|
@ -201,18 +191,46 @@ public class ItemTerminalTileEntity extends TileEntity implements INamedContaine
|
|||
return items;
|
||||
}
|
||||
|
||||
private List<ItemStack> getCurrentlyCrafting() {
|
||||
PipeNetwork network = PipeNetwork.get(this.world);
|
||||
PipeTileEntity pipe = this.getConnectedPipe();
|
||||
if (pipe == null)
|
||||
return Collections.emptyList();
|
||||
List<Pair<BlockPos, ItemStack>> crafting = network.getCurrentlyCrafting(pipe.getPos());
|
||||
return crafting.stream().map(Pair::getRight).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public void cancelCrafting() {
|
||||
PipeNetwork network = PipeNetwork.get(this.world);
|
||||
PipeTileEntity pipe = this.getConnectedPipe();
|
||||
if (pipe == null)
|
||||
return;
|
||||
for (Pair<BlockPos, ItemStack> craftable : network.getAllCraftables(pipe.getPos())) {
|
||||
PipeTileEntity otherPipe = network.getPipe(craftable.getLeft());
|
||||
if (otherPipe != null) {
|
||||
for (NetworkLock lock : otherPipe.craftIngredientRequests)
|
||||
network.resolveNetworkLock(lock);
|
||||
otherPipe.craftIngredientRequests.clear();
|
||||
otherPipe.craftResultRequests.clear();
|
||||
}
|
||||
}
|
||||
PlayerEntity[] lookingPlayers = this.getLookingPlayers();
|
||||
if (lookingPlayers.length > 0)
|
||||
this.updateItems(lookingPlayers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundNBT write(CompoundNBT compound) {
|
||||
compound.put("items", this.items.serializeNBT());
|
||||
compound.put("requests", Utility.serializeAll(this.pendingRequests));
|
||||
compound.put("requests", Utility.serializeAll(this.existingRequests));
|
||||
return super.write(compound);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(CompoundNBT compound) {
|
||||
this.items.deserializeNBT(compound.getCompound("items"));
|
||||
this.pendingRequests.clear();
|
||||
this.pendingRequests.addAll(Utility.deserializeAll(compound.getList("requests", NBT.TAG_COMPOUND), NetworkLock::new));
|
||||
this.existingRequests.clear();
|
||||
this.existingRequests.addAll(Utility.deserializeAll(compound.getList("requests", NBT.TAG_COMPOUND), NetworkLock::new));
|
||||
super.read(compound);
|
||||
}
|
||||
|
||||
|
@ -226,4 +244,66 @@ public class ItemTerminalTileEntity extends TileEntity implements INamedContaine
|
|||
public Container createMenu(int window, PlayerInventory inv, PlayerEntity player) {
|
||||
return new ItemTerminalContainer(Registry.itemTerminalContainer, window, player, this.pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> LazyOptional<T> getCapability(Capability<T> cap, Direction side) {
|
||||
if (cap == Registry.pipeConnectableCapability)
|
||||
return this.lazyThis.cast();
|
||||
return LazyOptional.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConnectionType getConnectionType(BlockPos pipePos, Direction direction) {
|
||||
return ConnectionType.CONNECTED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack insertItem(BlockPos pipePos, Direction direction, ItemStack stack, boolean simulate) {
|
||||
BlockPos pos = pipePos.offset(direction);
|
||||
ItemTerminalTileEntity tile = Utility.getTileEntity(ItemTerminalTileEntity.class, world, pos);
|
||||
if (tile != null)
|
||||
return ItemHandlerHelper.insertItemStacked(tile.items, stack, simulate);
|
||||
return stack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean allowsModules(BlockPos pipePos, Direction direction) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public static Pair<List<NetworkLock>, ItemStack> requestItemLater(World world, BlockPos destPipe, Collection<NetworkLocation> locations, Consumer<ItemStack> unavailableConsumer, ItemStack stack, ItemEqualityType... equalityTypes) {
|
||||
List<NetworkLock> requests = new ArrayList<>();
|
||||
ItemStack remain = stack.copy();
|
||||
PipeNetwork network = PipeNetwork.get(world);
|
||||
// check for existing items
|
||||
for (NetworkLocation location : locations) {
|
||||
int amount = location.getItemAmount(world, stack, ItemEqualityType.NBT);
|
||||
if (amount <= 0)
|
||||
continue;
|
||||
amount -= network.getLockedAmount(location.getPos(), stack, null, ItemEqualityType.NBT);
|
||||
if (amount > 0) {
|
||||
if (remain.getCount() < amount)
|
||||
amount = remain.getCount();
|
||||
remain.shrink(amount);
|
||||
while (amount > 0) {
|
||||
ItemStack copy = stack.copy();
|
||||
copy.setCount(Math.min(stack.getMaxStackSize(), amount));
|
||||
NetworkLock lock = new NetworkLock(location, copy);
|
||||
network.createNetworkLock(lock);
|
||||
requests.add(lock);
|
||||
amount -= copy.getCount();
|
||||
}
|
||||
if (remain.isEmpty())
|
||||
break;
|
||||
}
|
||||
}
|
||||
// check for craftable items
|
||||
if (!remain.isEmpty())
|
||||
remain = network.requestCraftedItem(destPipe, unavailableConsumer, remain, equalityTypes);
|
||||
return Pair.of(requests, remain);
|
||||
}
|
||||
|
||||
public static Consumer<ItemStack> onItemUnavailable(PlayerEntity player) {
|
||||
return s -> player.sendMessage(new TranslationTextComponent("info." + PrettyPipes.ID + ".not_found").setStyle(new Style().setColor(TextFormatting.RED)));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@ package de.ellpeck.prettypipes.terminal.containers;
|
|||
|
||||
import de.ellpeck.prettypipes.Utility;
|
||||
import de.ellpeck.prettypipes.terminal.CraftingTerminalTileEntity;
|
||||
import de.ellpeck.prettypipes.terminal.ItemTerminalTileEntity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.entity.player.ServerPlayerEntity;
|
||||
import net.minecraft.inventory.CraftResultInventory;
|
||||
|
@ -17,10 +16,8 @@ import net.minecraft.item.crafting.ICraftingRecipe;
|
|||
import net.minecraft.item.crafting.IRecipeType;
|
||||
import net.minecraft.network.play.server.SSetSlotPacket;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraftforge.items.SlotItemHandler;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Optional;
|
||||
|
||||
|
@ -71,9 +68,9 @@ public class CraftingTerminalContainer extends ItemTerminalContainer {
|
|||
|
||||
@Override
|
||||
public ItemStack slotClick(int slotId, int dragType, ClickType clickTypeIn, PlayerEntity player) {
|
||||
if (slotId > 0) {
|
||||
if (slotId > 0 && clickTypeIn == ClickType.PICKUP) {
|
||||
Slot slot = this.inventorySlots.get(slotId);
|
||||
if (slot.inventory == this.craftInventory)
|
||||
if (slot.inventory == this.craftInventory && !slot.getHasStack())
|
||||
this.getTile().ghostItems.setStackInSlot(slot.getSlotIndex(), ItemStack.EMPTY);
|
||||
}
|
||||
return super.slotClick(slotId, dragType, clickTypeIn, player);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package de.ellpeck.prettypipes.terminal.containers;
|
||||
|
||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||
import com.mojang.blaze3d.platform.GlStateManager;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import de.ellpeck.prettypipes.PrettyPipes;
|
||||
|
@ -15,6 +16,7 @@ import net.minecraft.inventory.container.Slot;
|
|||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.text.ITextComponent;
|
||||
import net.minecraft.util.text.TranslationTextComponent;
|
||||
|
||||
public class CraftingTerminalGui extends ItemTerminalGui {
|
||||
private static final ResourceLocation TEXTURE = new ResourceLocation(PrettyPipes.ID, "textures/gui/crafting_terminal.png");
|
||||
|
@ -29,8 +31,8 @@ public class CraftingTerminalGui extends ItemTerminalGui {
|
|||
protected void init() {
|
||||
super.init();
|
||||
this.requestButton = this.addButton(new Button(this.guiLeft + 8, this.guiTop + 100, 50, 20, I18n.format("info." + PrettyPipes.ID + ".request"), button -> {
|
||||
int all = hasShiftDown() ? 1 : 0;
|
||||
PacketHandler.sendToServer(new PacketButton(this.container.tile.getPos(), PacketButton.ButtonResult.CRAFT_TERMINAL_REQUEST, all));
|
||||
int amount = requestModifier();
|
||||
PacketHandler.sendToServer(new PacketButton(this.container.tile.getPos(), PacketButton.ButtonResult.CRAFT_TERMINAL_REQUEST, amount));
|
||||
}));
|
||||
this.tick();
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package de.ellpeck.prettypipes.terminal.containers;
|
||||
|
||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||
import de.ellpeck.prettypipes.PrettyPipes;
|
||||
import de.ellpeck.prettypipes.misc.ItemOrder;
|
||||
import de.ellpeck.prettypipes.misc.ItemTerminalWidget;
|
||||
import de.ellpeck.prettypipes.misc.PlayerPrefs;
|
||||
import de.ellpeck.prettypipes.packets.PacketButton;
|
||||
|
@ -19,24 +19,35 @@ import net.minecraft.item.ItemStack;
|
|||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.util.text.ITextComponent;
|
||||
import net.minecraft.util.text.StringTextComponent;
|
||||
import net.minecraft.util.text.TranslationTextComponent;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class ItemTerminalGui extends ContainerScreen<ItemTerminalContainer> {
|
||||
|
||||
private static final ResourceLocation TEXTURE = new ResourceLocation(PrettyPipes.ID, "textures/gui/item_terminal.png");
|
||||
|
||||
public List<ItemStack> currentlyCrafting;
|
||||
public TextFieldWidget search;
|
||||
|
||||
// craftables have the second parameter set to true
|
||||
private final List<Pair<ItemStack, Boolean>> sortedItems = new ArrayList<>();
|
||||
private List<ItemStack> items;
|
||||
private List<ItemStack> sortedItems;
|
||||
private List<ItemStack> craftables;
|
||||
private Button minusButton;
|
||||
private Button plusButton;
|
||||
private Button requestButton;
|
||||
private Button orderButton;
|
||||
private Button ascendingButton;
|
||||
private Button cancelCraftingButton;
|
||||
private String lastSearchText;
|
||||
private int requestAmount = 1;
|
||||
private int scrollOffset;
|
||||
public TextFieldWidget search;
|
||||
private ItemStack hoveredCrafting;
|
||||
|
||||
public ItemTerminalGui(ItemTerminalContainer screenContainer, PlayerInventory inv, ITextComponent titleIn) {
|
||||
super(screenContainer, inv, titleIn);
|
||||
|
@ -54,6 +65,7 @@ public class ItemTerminalGui extends ContainerScreen<ItemTerminalContainer> {
|
|||
} else {
|
||||
this.requestAmount += modifier;
|
||||
}
|
||||
// 384 items is 6 stacks, which is what fits into the terminal slots
|
||||
if (this.requestAmount > 384)
|
||||
this.requestAmount = 384;
|
||||
}));
|
||||
|
@ -89,6 +101,9 @@ public class ItemTerminalGui extends ContainerScreen<ItemTerminalContainer> {
|
|||
prefs.save();
|
||||
this.updateWidgets();
|
||||
}));
|
||||
this.cancelCraftingButton = this.addButton(new Button(this.guiLeft + this.xSize + 4, this.guiTop + 4 + 64, 54, 20, I18n.format("info." + PrettyPipes.ID + ".cancel_all"), b -> {
|
||||
}));
|
||||
this.cancelCraftingButton.visible = false;
|
||||
for (int y = 0; y < 4; y++) {
|
||||
for (int x = 0; x < 9; x++)
|
||||
this.addButton(new ItemTerminalWidget(this.guiLeft + this.getXOffset() + 8 + x * 18, this.guiTop + 18 + y * 18, x, y, this));
|
||||
|
@ -121,6 +136,20 @@ public class ItemTerminalGui extends ContainerScreen<ItemTerminalContainer> {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseReleased(double mouseX, double mouseY, int button) {
|
||||
// we have to do the click logic here because JEI is activated when letting go of the mouse button
|
||||
// and vanilla buttons are activated when the click starts, so we'll always invoke jei accidentally by default
|
||||
if (button == 0 && this.cancelCraftingButton.visible && this.cancelCraftingButton.isHovered()) {
|
||||
if (this.currentlyCrafting != null && !this.currentlyCrafting.isEmpty()) {
|
||||
PacketHandler.sendToServer(new PacketButton(this.container.tile.getPos(), PacketButton.ButtonResult.CANCEL_CRAFTING));
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return super.mouseReleased(mouseX, mouseY, button);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean keyPressed(int x, int y, int z) {
|
||||
// for some reason we have to do this to make the text field allow the inventory key to be typed
|
||||
|
@ -132,8 +161,10 @@ public class ItemTerminalGui extends ContainerScreen<ItemTerminalContainer> {
|
|||
return super.keyPressed(x, y, z);
|
||||
}
|
||||
|
||||
public void updateItemList(List<ItemStack> items) {
|
||||
public void updateItemList(List<ItemStack> items, List<ItemStack> craftables, List<ItemStack> currentlyCrafting) {
|
||||
this.items = items;
|
||||
this.craftables = craftables;
|
||||
this.currentlyCrafting = currentlyCrafting;
|
||||
this.updateWidgets();
|
||||
}
|
||||
|
||||
|
@ -141,13 +172,22 @@ public class ItemTerminalGui extends ContainerScreen<ItemTerminalContainer> {
|
|||
PlayerPrefs prefs = PlayerPrefs.get();
|
||||
this.ascendingButton.setMessage(prefs.terminalAscending ? "^" : "v");
|
||||
this.orderButton.setMessage(prefs.terminalItemOrder.name().substring(0, 1));
|
||||
this.cancelCraftingButton.visible = this.currentlyCrafting != null && !this.currentlyCrafting.isEmpty();
|
||||
|
||||
Comparator<ItemStack> comparator = prefs.terminalItemOrder.comparator;
|
||||
if (!prefs.terminalAscending)
|
||||
comparator = comparator.reversed();
|
||||
|
||||
this.sortedItems = new ArrayList<>(this.items);
|
||||
this.sortedItems.sort(comparator);
|
||||
// add all items to the sorted items list
|
||||
this.sortedItems.clear();
|
||||
for (ItemStack stack : this.items)
|
||||
this.sortedItems.add(Pair.of(stack, false));
|
||||
for (ItemStack stack : this.craftables)
|
||||
this.sortedItems.add(Pair.of(stack, true));
|
||||
|
||||
// compare by craftability first, and then by the player's chosen order
|
||||
Comparator<Pair<ItemStack, Boolean>> fullComparator = Comparator.comparing(Pair::getRight);
|
||||
this.sortedItems.sort(fullComparator.thenComparing(Pair::getLeft, comparator));
|
||||
|
||||
String searchText = this.search.getText();
|
||||
if (!Strings.isNullOrEmpty(searchText)) {
|
||||
|
@ -155,11 +195,11 @@ public class ItemTerminalGui extends ContainerScreen<ItemTerminalContainer> {
|
|||
String search = searchText;
|
||||
String toCompare;
|
||||
if (search.startsWith("@")) {
|
||||
toCompare = s.getItem().getRegistryName().getNamespace();
|
||||
toCompare = s.getLeft().getItem().getCreatorModId(s.getLeft());
|
||||
search = search.substring(1);
|
||||
} else {
|
||||
// don't use formatted text here since we want to search for name
|
||||
toCompare = s.getDisplayName().getString();
|
||||
toCompare = s.getLeft().getDisplayName().getString();
|
||||
}
|
||||
return !toCompare.toLowerCase(Locale.ROOT).contains(search.toLowerCase(Locale.ROOT));
|
||||
});
|
||||
|
@ -174,9 +214,12 @@ public class ItemTerminalGui extends ContainerScreen<ItemTerminalContainer> {
|
|||
int index = i + this.scrollOffset * 9;
|
||||
if (index >= this.sortedItems.size()) {
|
||||
widget.stack = ItemStack.EMPTY;
|
||||
widget.craftable = false;
|
||||
widget.visible = false;
|
||||
} else {
|
||||
widget.stack = this.sortedItems.get(index);
|
||||
Pair<ItemStack, Boolean> stack = this.sortedItems.get(index);
|
||||
widget.stack = stack.getLeft();
|
||||
widget.craftable = stack.getRight();
|
||||
widget.visible = true;
|
||||
}
|
||||
}
|
||||
|
@ -198,15 +241,29 @@ public class ItemTerminalGui extends ContainerScreen<ItemTerminalContainer> {
|
|||
this.renderTooltip(I18n.format("info." + PrettyPipes.ID + "." + (prefs.terminalAscending ? "ascending" : "descending")), mouseX, mouseY);
|
||||
}
|
||||
this.renderHoveredToolTip(mouseX, mouseY);
|
||||
|
||||
// if (this.cancelCraftingButton.visible && this.cancelCraftingButton.isHovered()) {
|
||||
// String[] tooltip = I18n.format("info." + PrettyPipes.ID + ".cancel_all.desc").split("\n");
|
||||
// this.func_243308_b(Arrays.stream(tooltip).map(StringTextComponent::new).collect(Collectors.toList()), mouseX, mouseY);
|
||||
// }
|
||||
if (!this.hoveredCrafting.isEmpty())
|
||||
this.renderTooltip(this.hoveredCrafting, mouseX, mouseY);
|
||||
// this.func_230459_a_(mouseX, mouseY);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void drawGuiContainerForegroundLayer(int mouseX, int mouseY) {
|
||||
this.font.drawString(this.playerInventory.getDisplayName().getFormattedText(), 8 + this.getXOffset(), this.ySize - 96 + 2, 4210752);
|
||||
this.font.drawString(this.title.getFormattedText(), 8, 6, 4210752);
|
||||
this.font.drawString(this.playerInventory.getDisplayName().getString(), 8 + this.getXOffset(), this.ySize - 96 + 2, 4210752);
|
||||
this.font.drawString(this.title.getString(), 8, 6, 4210752);
|
||||
|
||||
String amount = String.valueOf(this.requestAmount);
|
||||
this.font.drawString(amount, (176 + 15 - this.font.getStringWidth(amount)) / 2F - 7 + this.getXOffset(), 106, 4210752);
|
||||
|
||||
if (this.currentlyCrafting != null && !this.currentlyCrafting.isEmpty()) {
|
||||
this.font.drawString(I18n.format("info." + PrettyPipes.ID + ".crafting"), this.xSize + 4, 4 + 6, 4210752);
|
||||
if (this.currentlyCrafting.size() > 6)
|
||||
this.font.drawString(". . .", this.xSize + 24, 4 + 51, 4210752);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -220,6 +277,31 @@ public class ItemTerminalGui extends ContainerScreen<ItemTerminalContainer> {
|
|||
} else {
|
||||
this.blit(this.guiLeft + this.getXOffset() + 172, this.guiTop + 18, 244, 241, 12, 15);
|
||||
}
|
||||
|
||||
// draw the items that are currently crafting
|
||||
this.hoveredCrafting = ItemStack.EMPTY;
|
||||
if (this.currentlyCrafting != null && !this.currentlyCrafting.isEmpty()) {
|
||||
this.getMinecraft().getTextureManager().bindTexture(TEXTURE);
|
||||
this.blit(this.guiLeft + this.xSize, this.guiTop + 4, 191, 0, 65, 89);
|
||||
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
for (ItemStack stack : this.currentlyCrafting) {
|
||||
int itemX = this.guiLeft + this.xSize + 4 + x * 18;
|
||||
int itemY = this.guiTop + 4 + 16 + y * 18;
|
||||
this.itemRenderer.renderItemAndEffectIntoGUI(stack, itemX, itemY);
|
||||
this.itemRenderer.renderItemOverlayIntoGUI(this.font, stack, itemX, itemY, String.valueOf(stack.getCount()));
|
||||
if (mouseX >= itemX && mouseY >= itemY && mouseX < itemX + 16 && mouseY < itemY + 18)
|
||||
this.hoveredCrafting = stack;
|
||||
x++;
|
||||
if (x >= 3) {
|
||||
x = 0;
|
||||
y++;
|
||||
if (y >= 2)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected ResourceLocation getTexture() {
|
||||
|
@ -244,7 +326,7 @@ public class ItemTerminalGui extends ContainerScreen<ItemTerminalContainer> {
|
|||
.map(w -> (ItemTerminalWidget) w);
|
||||
}
|
||||
|
||||
private static int requestModifier() {
|
||||
public static int requestModifier() {
|
||||
if (hasControlDown()) {
|
||||
return 10;
|
||||
} else if (hasShiftDown()) {
|
||||
|
|
|
@ -9,6 +9,7 @@ modLoader="javafml" #mandatory
|
|||
loaderVersion="[28,)" #mandatory (28 is current forge version)
|
||||
# A URL to refer people to when problems occur with this mod
|
||||
issueTrackerURL="https://github.com/Ellpeck/PrettyPipes" #optional
|
||||
license="MIT"
|
||||
# A list of mods - how many allowed here is determined by the individual mod loader
|
||||
[[mods]] #mandatory
|
||||
# The modid of the mod
|
||||
|
@ -24,9 +25,9 @@ displayName="Pretty Pipes" #mandatory
|
|||
# A file name (in the root of the mod JAR) containing a logo for display
|
||||
#logoFile="examplemod.png" #optional
|
||||
# A text field displayed in the mod UI
|
||||
credits="Commission for Violet" #optional
|
||||
#credits="" #optional
|
||||
# A text field displayed in the mod UI
|
||||
authors="Ellpeck" #optional
|
||||
# The description text for the mod (multi line!) (#mandatory)
|
||||
description='''
|
||||
wow pipes, how creative'''
|
||||
wow pipes, how creative'''
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"variants": {
|
||||
"": {
|
||||
"model": "prettypipes:block/pressurizer"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
{
|
||||
"_comment": "Unicode fonts only",
|
||||
"providers": [
|
||||
{
|
||||
"type": "legacy_unicode",
|
||||
"sizes": "minecraft:font/glyph_sizes.bin",
|
||||
"template": "minecraft:font/unicode_page_%s.png"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,11 +1,15 @@
|
|||
{
|
||||
"item.prettypipes.wrench": "Pipe Wrench",
|
||||
"info.prettypipes.wrench": "Allows modifying pipe connections\nPlaces blocks in offhand as covers\nSneak to remove cover or pipe",
|
||||
"item.prettypipes.blank_module": "Blank Module",
|
||||
"item.prettypipes.pipe_frame": "Pipe Frame",
|
||||
"info.prettypipes.pipe_frame": "Attach to a pipe or pipe-adjacent block\nShows amount of an item in the pipe's network",
|
||||
"item.prettypipes.low_extraction_module": "Low Extraction Module",
|
||||
"item.prettypipes.medium_extraction_module": "Medium Extraction Module",
|
||||
"item.prettypipes.high_extraction_module": "High Extraction Module",
|
||||
"item.prettypipes.low_crafting_module": "Low Crafting Module",
|
||||
"item.prettypipes.medium_crafting_module": "Medium Crafting Module",
|
||||
"item.prettypipes.high_crafting_module": "High Crafting Module",
|
||||
"item.prettypipes.low_filter_module": "Low Filter Module",
|
||||
"item.prettypipes.medium_filter_module": "Medium Filter Module",
|
||||
"item.prettypipes.high_filter_module": "High Filter Module",
|
||||
|
@ -15,6 +19,9 @@
|
|||
"item.prettypipes.low_low_priority_module": "Low Priority Module",
|
||||
"item.prettypipes.medium_low_priority_module": "Lower Priority Module",
|
||||
"item.prettypipes.high_low_priority_module": "Lowest Priority Module",
|
||||
"item.prettypipes.low_high_priority_module": "High Priority Module",
|
||||
"item.prettypipes.medium_high_priority_module": "Higher Priority Module",
|
||||
"item.prettypipes.high_high_priority_module": "Highest Priority Module",
|
||||
"item.prettypipes.low_retrieval_module": "Low Retrieval Module",
|
||||
"item.prettypipes.medium_retrieval_module": "Medium Retrieval Module",
|
||||
"item.prettypipes.high_retrieval_module": "High Retrieval Module",
|
||||
|
@ -22,26 +29,35 @@
|
|||
"item.prettypipes.damage_filter_modifier": "Damage Filter Modifier",
|
||||
"item.prettypipes.nbt_filter_modifier": "Data Filter Modifier",
|
||||
"item.prettypipes.tag_filter_modifier": "Tag Filter Modifier",
|
||||
"item.prettypipes.mod_filter_modifier": "Mod Filter Modifier",
|
||||
"item.prettypipes.redstone_module": "Redstone Module",
|
||||
"item.prettypipes.filter_increase_modifier": "Filter Increase Modifier",
|
||||
"info.prettypipes.extraction_module": "Pulls items from adjacent inventories\nFilters and pull rates vary by tier\nHigh tiers prevent over-sending",
|
||||
"info.prettypipes.filter_module": "Restricts flow from pipes into adjacent inventories\nFilter amount varies by tier",
|
||||
"info.prettypipes.speed_module": "Increases speed of items exiting adjacent inventories\nSpeed varies by tier",
|
||||
"info.prettypipes.low_priority_module": "Decreases the reception priority of adjacent inventories\nLower priority means items will prefer other inventories",
|
||||
"info.prettypipes.low_priority_module": "Decreases the reception priority of adjacent inventories\nLower priority means items will prefer other inventories, regardless of distance",
|
||||
"info.prettypipes.high_priority_module": "Increases the reception priority of adjacent inventories\nHigher priority means items will prefer this inventory, regardless of distance",
|
||||
"info.prettypipes.retrieval_module": "Pulls items from other inventories in the network\nFilters and pull rates vary by tier\nHigh tiers prevent over-sending",
|
||||
"info.prettypipes.stack_size_module": "Limits the amount of items that can enter adjacent inventories\nAutomatically prevents over-sending",
|
||||
"info.prettypipes.damage_filter_modifier": "Causes any filter slots to filter by item damage",
|
||||
"info.prettypipes.nbt_filter_modifier": "Causes any filter slots to filter by item data (NBT)",
|
||||
"info.prettypipes.tag_filter_modifier": "Causes any filter slots to filter by tags\n(Modern equivalent of the Ore Dictionary)",
|
||||
"info.prettypipes.mod_filter_modifier": "Causes any filter slots to filter by mod",
|
||||
"info.prettypipes.redstone_module": "Allows disabling the pipe with a redstone signal\nWorks for both extraction and retrieval",
|
||||
"info.prettypipes.item_terminal": "Allows viewing and requesting all items in a pipe network\nAlso has slots for putting items into the network",
|
||||
"info.prettypipes.crafting_terminal": "Allows requesting ingredients for crafting recipes\nSupports auto-filling from JEI if installed",
|
||||
"info.prettypipes.pressurizer": "Drastically increases item speed in the entire pipe network\nRequires FE (or RF) for each item transferred",
|
||||
"info.prettypipes.filter_increase_modifier": "Adds additional filter slots to the pipe\nSlots will be used by any module that filters items",
|
||||
"info.prettypipes.crafting_module": "Allows automatically crafting items into other items using the connected block\nDoesn't automatically extract from the block\nInput and output slots vary by tier\nSupports auto-filling from JEI if installed",
|
||||
"block.prettypipes.pipe": "Pipe",
|
||||
"block.prettypipes.item_terminal": "Item Terminal",
|
||||
"block.prettypipes.crafting_terminal": "Crafting Terminal",
|
||||
"block.prettypipes.pressurizer": "Pipe Pressurizer",
|
||||
"itemGroup.prettypipes": "Pretty Pipes",
|
||||
"container.prettypipes.pipe": "Pipe",
|
||||
"container.prettypipes.item_terminal": "Item Terminal",
|
||||
"container.prettypipes.crafting_terminal": "Crafting Terminal",
|
||||
"container.prettypipes.pressurizer": "Pipe Pressurizer",
|
||||
"info.prettypipes.whitelist": "Allowed",
|
||||
"info.prettypipes.blacklist": "Disallowed",
|
||||
"info.prettypipes.shift": "Hold Shift for info",
|
||||
|
@ -61,5 +77,9 @@
|
|||
"info.prettypipes.ascending": "Ascending",
|
||||
"info.prettypipes.descending": "Descending",
|
||||
"info.prettypipes.sync_jei.on": "Sync JEI Search",
|
||||
"info.prettypipes.sync_jei.off": "Don't Sync JEI Search"
|
||||
"info.prettypipes.sync_jei.off": "Don't Sync JEI Search",
|
||||
"info.prettypipes.energy": "%s / %s FE",
|
||||
"info.prettypipes.crafting": "Awaiting",
|
||||
"info.prettypipes.cancel_all": "Cancel",
|
||||
"info.prettypipes.cancel_all.desc": "Stops waiting for current crafting outputs\nDoesn't remove inputs from blocks"
|
||||
}
|
|
@ -1,65 +1,75 @@
|
|||
{
|
||||
"item.prettypipes.wrench": "Ключ трубы",
|
||||
"item.prettypipes.wrench": "Разводной ключ",
|
||||
"item.prettypipes.blank_module": "Пустой модуль",
|
||||
"item.prettypipes.pipe_frame": "Рама трубы",
|
||||
"info.prettypipes.pipe_frame": "Прикрепите к трубе или смежному с трубой блоку\nПоказывает количество предметов в трубопроводной сети",
|
||||
"info.prettypipes.pipe_frame": "Прикрепите к трубе или к соседнему блоку трубы.\nПоказывает кол-во предметов в сети труб.",
|
||||
"item.prettypipes.low_extraction_module": "Модуль низкого извлечения",
|
||||
"item.prettypipes.medium_extraction_module": "Модуль среднего извлечения",
|
||||
"item.prettypipes.high_extraction_module": "Модуль высокого извлечения",
|
||||
"item.prettypipes.low_crafting_module": "Модуль низкого создания",
|
||||
"item.prettypipes.medium_crafting_module": "Модуль среднего создания",
|
||||
"item.prettypipes.high_crafting_module": "Модуль высокого создания",
|
||||
"item.prettypipes.low_filter_module": "Модуль низкой фильтрации",
|
||||
"item.prettypipes.medium_filter_module": "Модуль средней фильтрации",
|
||||
"item.prettypipes.high_filter_module": "Модуль высокой фильтрации",
|
||||
"item.prettypipes.low_speed_module": "Модуль низкого увеличения скорости",
|
||||
"item.prettypipes.medium_speed_module": "Модуль среднего увеличения скорости",
|
||||
"item.prettypipes.high_speed_module": "Модуль высокого увеличения скорости",
|
||||
"item.prettypipes.low_speed_module": "Модуль низкого повышения скорости",
|
||||
"item.prettypipes.medium_speed_module": "Модуль среднего повышения скорости",
|
||||
"item.prettypipes.high_speed_module": "Модуль высокого повышения скорости",
|
||||
"item.prettypipes.low_low_priority_module": "Модуль низкого приоритета",
|
||||
"item.prettypipes.medium_low_priority_module": "Модуль более низкого приоритета",
|
||||
"item.prettypipes.high_low_priority_module": "Модуль самого низкого приоритета",
|
||||
"item.prettypipes.low_retrieval_module": "Модуль низкого поиска",
|
||||
"item.prettypipes.medium_retrieval_module": "Модуль среднего поиска",
|
||||
"item.prettypipes.high_retrieval_module": "Модуль высокого поиска",
|
||||
"item.prettypipes.stack_size_module": "Модуль ограничения стака",
|
||||
"item.prettypipes.damage_filter_modifier": "Модификатор фильтрации повреждений",
|
||||
"item.prettypipes.nbt_filter_modifier": "Модификатор фильтрации данных",
|
||||
"item.prettypipes.tag_filter_modifier": "Модификатор фильтрации тегов",
|
||||
"item.prettypipes.redstone_module": "Модуль редстоуна",
|
||||
"info.prettypipes.extraction_module": "Вытягивает предметы из соседних запасов\nФильтры и скорость вытягивания варьируются в зависимости от уровня\nВысокие уровни предотвращают чрезмерную отправку",
|
||||
"info.prettypipes.filter_module": "Ограничивает поток из труб в соседние запасы\nКоличество фильтров варьируется в зависимости от уровня",
|
||||
"info.prettypipes.speed_module": "Увеличивает скорость предметов, выходящих из соседних запасов\nСкорость зависит от уровня",
|
||||
"info.prettypipes.low_priority_module": "Уменьшает приоритет приема соседних запасов\nБолее низкий приоритет означает, что предметы предпочтут другие запасы",
|
||||
"info.prettypipes.retrieval_module": "Вытягивает товары из других запасов в сети\nФильтры и скорость вытягивания различаются в зависимости от уровня\nВысокие уровни предотвращают чрезмерную отправку",
|
||||
"info.prettypipes.stack_size_module": "Ограничивает количество предметов, которые могут войти в соседние запасы\nАвтоматически предотвращает чрезмерную отправку",
|
||||
"info.prettypipes.damage_filter_modifier": "Заставляет любые слоты фильтра фильтровать повреждение предмета",
|
||||
"info.prettypipes.nbt_filter_modifier": "Заставляет любые слоты фильтра фильтровать данные предмета (NBT)",
|
||||
"info.prettypipes.tag_filter_modifier": "Заставляет любые слоты фильтра фильтровать по тегам\n(Современный эквивалент словаря руд)",
|
||||
"info.prettypipes.redstone_module": "Позволяет отключить трубу с сигналом редстоуна\nРаботы как добыча, так и как поиск",
|
||||
"info.prettypipes.item_terminal": "Позволяет просматривать и запрашивать все элементы в трубопроводной сети\nТакже есть слоты для размещения предметов в сети",
|
||||
"info.prettypipes.crafting_terminal": "Позволяет запрашивать ингредиенты для изготовления рецептов\nПоддерживает автозаполнение из JEI, если установлено",
|
||||
"item.prettypipes.stack_size_module": "Модуль для ограничителя стэка",
|
||||
"item.prettypipes.damage_filter_modifier": "Модификатор для фильтрации повреждения",
|
||||
"item.prettypipes.nbt_filter_modifier": "Модификатор для фильтрации Данных",
|
||||
"item.prettypipes.tag_filter_modifier": "Модификатор для фильтрации Тэга",
|
||||
"item.prettypipes.redstone_module": "Модуль красного камня",
|
||||
"item.prettypipes.filter_increase_modifier": "Модификатор для ускорения фильтрации",
|
||||
"info.prettypipes.extraction_module": "Вытягивает предметы из соседних запасов.\nФильтры и скорость вытягивания варьируются в зависимости от уровня.\nВысокие уровни предотвращают завышенную отправку.",
|
||||
"info.prettypipes.filter_module": "Ограничивает поток из труб в соседние запасы.\nКо-во фильтров варьируются в зависимости от уровня.",
|
||||
"info.prettypipes.speed_module": "Повышает скорость предметов покидающих из соседних запасов.\nСкорость варьируются в зависимости от уровня.",
|
||||
"info.prettypipes.low_priority_module": "Снижает приоритет приёма из соседних запасов.\nБолее низкий приоритет означает, что предметы будут предпочитать другие запасы.",
|
||||
"info.prettypipes.retrieval_module": "Вытягивает предметы из других запасов в сети.\nФильтры и вытягивание варьируются в зависимости от уровня\nВысокие уровни предотвращают завышенную отправку.",
|
||||
"info.prettypipes.stack_size_module": "Ограничивает кол-во предметов, которые могут входить в соседние запасы\nАвтоматически предотвращает завышенную отправку.",
|
||||
"info.prettypipes.damage_filter_modifier": "Заставляет любые слоты фильтра, фильтровать по повреждению предмета.",
|
||||
"info.prettypipes.nbt_filter_modifier": "Заставляет любые слоты фильтра, фильтровать по Данным предмета (NBT).",
|
||||
"info.prettypipes.tag_filter_modifier": "Заставляет любые слоты фильтра, фильтровать по Тэгам предмета.\n(Современный эквивалент Словаря руд.).",
|
||||
"info.prettypipes.redstone_module": "Позволяет отключать трубы сигналом красного камня.\nРаботает как для извлечения, так и для поиска.",
|
||||
"info.prettypipes.item_terminal": "Позволяет просматривать и запрашивать все предметы в сети труб.\nТакже имеет слоты для введения предметов в сеть.",
|
||||
"info.prettypipes.crafting_terminal": "Позволяет запрашивать ингредиенты для рецептов созданий.\nПоддерживает автоматическую заполнение из JEI, если установлен.",
|
||||
"info.prettypipes.pressurizer": "Значительно повышает скорость предмета входящий в сеть труб.\nТребует FE (или RF) на каждый перемещённый предмет.",
|
||||
"info.prettypipes.filter_increase_modifier": "Добавляет дополнительную фильтрацию слотов в трубы.\nСлоты станут использовать любой модуль, который фильтрует предметы.",
|
||||
"info.prettypipes.crafting_module": "Позволяет автоматически создавать предметы в другие предметы при помощи соединённого блока.\nНе извлекается автоматически из блока\nВходные и выходные слоты варьируются в зависимости от уровня.\nПоддерживает автоматическое заполнение из JEI, если установлен.",
|
||||
"block.prettypipes.pipe": "Труба",
|
||||
"block.prettypipes.item_terminal": "Терминал предметов",
|
||||
"block.prettypipes.crafting_terminal": "Терминал предметов",
|
||||
"itemGroup.prettypipes": "Хорошенькие трубы",
|
||||
"block.prettypipes.item_terminal": "Предметный терминал",
|
||||
"block.prettypipes.crafting_terminal": "Ремесленный терминал",
|
||||
"block.prettypipes.pressurizer": "Трубный компенсатор давления",
|
||||
"itemGroup.prettypipes": "Pretty Pipes",
|
||||
"container.prettypipes.pipe": "Труба",
|
||||
"container.prettypipes.item_terminal": "Терминал предметов",
|
||||
"container.prettypipes.crafting_terminal": "Терминал предметов",
|
||||
"info.prettypipes.whitelist": "Разрешено",
|
||||
"info.prettypipes.blacklist": "Запрещено",
|
||||
"info.prettypipes.shift": "Удерживайте [Shift], чтобы узнать подробности",
|
||||
"info.prettypipes.populate": "Заполнять",
|
||||
"container.prettypipes.item_terminal": "Предметный терминал",
|
||||
"container.prettypipes.crafting_terminal": "Ремесленный терминал",
|
||||
"container.prettypipes.pressurizer": "Трубный компенсатор давления",
|
||||
"info.prettypipes.whitelist": "Разрешённый",
|
||||
"info.prettypipes.blacklist": "Запрещённый",
|
||||
"info.prettypipes.shift": "Зажмите Shift, для информации",
|
||||
"info.prettypipes.populate": "Заполнить",
|
||||
"info.prettypipes.populate.description": "Фильтрует предметы из соседних запасов",
|
||||
"info.prettypipes.max_stack_size": "Максимальное количество предметов",
|
||||
"info.prettypipes.limit_to_max_on": "Ограничить до 1 стака",
|
||||
"info.prettypipes.limit_to_max_off": "Не ограничать до 1 стака",
|
||||
"info.prettypipes.request": "Запрос",
|
||||
"info.prettypipes.max_stack_size": "Макс. кол-во предмета",
|
||||
"info.prettypipes.limit_to_max_on": "Ограничить на 1 стэк",
|
||||
"info.prettypipes.limit_to_max_off": "Не ограничивать на 1 стэк",
|
||||
"info.prettypipes.request": "Запросить",
|
||||
"info.prettypipes.not_found": "%s не найден",
|
||||
"info.prettypipes.sending": "Отправка %s %s",
|
||||
"info.prettypipes.sending_ingredients": "Отправка наборов ингридиентов: %s",
|
||||
"info.prettypipes.sending": "Отправление %s %s",
|
||||
"info.prettypipes.sending_ingredients": "Отправление наборов ингридиентов: %s.",
|
||||
"info.prettypipes.order": "Сортировать по %s",
|
||||
"info.prettypipes.order.amount": "Количеству",
|
||||
"info.prettypipes.order.name": "Имени",
|
||||
"info.prettypipes.order.mod": "Моду",
|
||||
"info.prettypipes.ascending": "Возростанию",
|
||||
"info.prettypipes.descending": "Убыванию",
|
||||
"info.prettypipes.sync_jei.on": "Синхронизировать поиск JEI",
|
||||
"info.prettypipes.sync_jei.off": "Не синхронизировать поиск JEI"
|
||||
"info.prettypipes.order.amount": "Кол-во",
|
||||
"info.prettypipes.order.name": "Название",
|
||||
"info.prettypipes.order.mod": "Мод",
|
||||
"info.prettypipes.ascending": "Возрастание",
|
||||
"info.prettypipes.descending": "Убывание",
|
||||
"info.prettypipes.sync_jei.on": "Синхронизовать поиск JEI",
|
||||
"info.prettypipes.sync_jei.off": "Не синхронизовать поиск JEI",
|
||||
"info.prettypipes.energy": "%s / %s FE"
|
||||
}
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"parent": "block/cube_column",
|
||||
"textures": {
|
||||
"end": "prettypipes:block/pressurizer",
|
||||
"side": "prettypipes:block/pressurizer"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"parent": "item/generated",
|
||||
"textures": {
|
||||
"layer0": "prettypipes:item/filter_increase_modifier"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"parent": "item/generated",
|
||||
"textures": {
|
||||
"layer0": "prettypipes:item/high_crafting_module"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"parent": "item/generated",
|
||||
"textures": {
|
||||
"layer0": "prettypipes:item/high_high_priority_module"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"parent": "item/generated",
|
||||
"textures": {
|
||||
"layer0": "prettypipes:item/low_crafting_module"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"parent": "item/generated",
|
||||
"textures": {
|
||||
"layer0": "prettypipes:item/low_high_priority_module"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"parent": "item/generated",
|
||||
"textures": {
|
||||
"layer0": "prettypipes:item/medium_crafting_module"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"parent": "item/generated",
|
||||
"textures": {
|
||||
"layer0": "prettypipes:item/medium_high_priority_module"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"parent": "item/generated",
|
||||
"textures": {
|
||||
"layer0": "prettypipes:item/mod_filter_modifier"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"parent": "prettypipes:block/pressurizer"
|
||||
}
|
After Width: | Height: | Size: 445 B |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 1 KiB |
After Width: | Height: | Size: 410 B |
After Width: | Height: | Size: 414 B |
After Width: | Height: | Size: 361 B |
After Width: | Height: | Size: 427 B |
After Width: | Height: | Size: 357 B |
After Width: | Height: | Size: 432 B |
After Width: | Height: | Size: 343 B |
After Width: | Height: | Size: 310 B |
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"type": "minecraft:block",
|
||||
"pools": [
|
||||
{
|
||||
"rolls": 1,
|
||||
"entries": [
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "prettypipes:pressurizer"
|
||||
}
|
||||
],
|
||||
"conditions": [
|
||||
{
|
||||
"condition": "minecraft:survives_explosion"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"type": "minecraft:crafting_shaped",
|
||||
"pattern": [
|
||||
" B ",
|
||||
"RMR",
|
||||
" R "
|
||||
],
|
||||
"key": {
|
||||
"R": {
|
||||
"item": "minecraft:redstone"
|
||||
},
|
||||
"B": {
|
||||
"item": "minecraft:iron_bars"
|
||||
},
|
||||
"M": {
|
||||
"item": "prettypipes:blank_module"
|
||||
}
|
||||
},
|
||||
"result": {
|
||||
"item": "prettypipes:filter_increase_modifier"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"type": "minecraft:crafting_shaped",
|
||||
"pattern": [
|
||||
"GIG",
|
||||
"GMG",
|
||||
"GIG"
|
||||
],
|
||||
"key": {
|
||||
"I": {
|
||||
"item": "minecraft:iron_ingot"
|
||||
},
|
||||
"G": {
|
||||
"item": "minecraft:gold_ingot"
|
||||
},
|
||||
"M": {
|
||||
"item": "prettypipes:medium_crafting_module"
|
||||
}
|
||||
},
|
||||
"result": {
|
||||
"item": "prettypipes:high_crafting_module"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"type": "minecraft:crafting_shaped",
|
||||
"pattern": [
|
||||
"CCC",
|
||||
"CMC",
|
||||
"CCC"
|
||||
],
|
||||
"key": {
|
||||
"C": {
|
||||
"item": "minecraft:paper"
|
||||
},
|
||||
"M": {
|
||||
"item": "prettypipes:medium_high_priority_module"
|
||||
}
|
||||
},
|
||||
"result": {
|
||||
"item": "prettypipes:high_high_priority_module"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"type": "minecraft:crafting_shaped",
|
||||
"pattern": [
|
||||
" P ",
|
||||
"RMR",
|
||||
" R "
|
||||
],
|
||||
"key": {
|
||||
"R": {
|
||||
"item": "minecraft:redstone"
|
||||
},
|
||||
"P": {
|
||||
"item": "minecraft:crafting_table"
|
||||
},
|
||||
"M": {
|
||||
"item": "prettypipes:blank_module"
|
||||
}
|
||||
},
|
||||
"result": {
|
||||
"item": "prettypipes:low_crafting_module"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"type": "minecraft:crafting_shaped",
|
||||
"pattern": [
|
||||
" C ",
|
||||
"RMR",
|
||||
" R "
|
||||
],
|
||||
"key": {
|
||||
"R": {
|
||||
"item": "minecraft:redstone"
|
||||
},
|
||||
"C": {
|
||||
"item": "minecraft:paper"
|
||||
},
|
||||
"M": {
|
||||
"item": "prettypipes:blank_module"
|
||||
}
|
||||
},
|
||||
"result": {
|
||||
"item": "prettypipes:low_high_priority_module"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"type": "minecraft:crafting_shaped",
|
||||
"pattern": [
|
||||
"GIG",
|
||||
"IMI",
|
||||
"GIG"
|
||||
],
|
||||
"key": {
|
||||
"I": {
|
||||
"item": "minecraft:iron_ingot"
|
||||
},
|
||||
"G": {
|
||||
"item": "minecraft:gold_ingot"
|
||||
},
|
||||
"M": {
|
||||
"item": "prettypipes:low_crafting_module"
|
||||
}
|
||||
},
|
||||
"result": {
|
||||
"item": "prettypipes:medium_crafting_module"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"type": "minecraft:crafting_shaped",
|
||||
"pattern": [
|
||||
" C ",
|
||||
"CMC",
|
||||
" C "
|
||||
],
|
||||
"key": {
|
||||
"C": {
|
||||
"item": "minecraft:paper"
|
||||
},
|
||||
"M": {
|
||||
"item": "prettypipes:low_high_priority_module"
|
||||
}
|
||||
},
|
||||
"result": {
|
||||
"item": "prettypipes:medium_high_priority_module"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"type": "minecraft:crafting_shaped",
|
||||
"pattern": [
|
||||
" H ",
|
||||
"RMR",
|
||||
" R "
|
||||
],
|
||||
"key": {
|
||||
"R": {
|
||||
"item": "minecraft:redstone"
|
||||
},
|
||||
"H": {
|
||||
"item": "minecraft:anvil"
|
||||
},
|
||||
"M": {
|
||||
"item": "prettypipes:blank_module"
|
||||
}
|
||||
},
|
||||
"result": {
|
||||
"item": "prettypipes:mod_filter_modifier"
|
||||
}
|
||||
}
|
22
src/main/resources/data/prettypipes/recipes/pressurizer.json
Normal file
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"type": "minecraft:crafting_shaped",
|
||||
"pattern": [
|
||||
"TST",
|
||||
"SRS",
|
||||
"TST"
|
||||
],
|
||||
"key": {
|
||||
"S": {
|
||||
"item": "prettypipes:high_speed_module"
|
||||
},
|
||||
"R": {
|
||||
"item": "minecraft:redstone_block"
|
||||
},
|
||||
"T": {
|
||||
"item": "minecraft:iron_ingot"
|
||||
}
|
||||
},
|
||||
"result": {
|
||||
"item": "prettypipes:pressurizer"
|
||||
}
|
||||
}
|