Compare commits

..

No commits in common. "ae5128971c8c29d89fe9abb4089b526e88c6b54a" and "b991f8575ff56ab28df3792232001b7448117a80" have entirely different histories.

76 changed files with 2093 additions and 1975 deletions

View file

@ -95,7 +95,7 @@ repositories {
configurations { configurations {
embed embed
implementation.extendsFrom(embed) compile.extendsFrom(embed)
} }
dependencies { dependencies {

View file

@ -8,8 +8,8 @@ import de.ellpeck.prettypipes.network.PipeNetwork;
import de.ellpeck.prettypipes.packets.PacketHandler; import de.ellpeck.prettypipes.packets.PacketHandler;
import de.ellpeck.prettypipes.pipe.IPipeConnectable; import de.ellpeck.prettypipes.pipe.IPipeConnectable;
import de.ellpeck.prettypipes.pipe.PipeBlock; import de.ellpeck.prettypipes.pipe.PipeBlock;
import de.ellpeck.prettypipes.pipe.PipeBlockEntity;
import de.ellpeck.prettypipes.pipe.PipeRenderer; 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.AbstractPipeContainer;
import de.ellpeck.prettypipes.pipe.containers.MainPipeContainer; import de.ellpeck.prettypipes.pipe.containers.MainPipeContainer;
import de.ellpeck.prettypipes.pipe.containers.MainPipeGui; import de.ellpeck.prettypipes.pipe.containers.MainPipeGui;
@ -36,37 +36,39 @@ import de.ellpeck.prettypipes.pipe.modules.stacksize.StackSizeModuleContainer;
import de.ellpeck.prettypipes.pipe.modules.stacksize.StackSizeModuleGui; import de.ellpeck.prettypipes.pipe.modules.stacksize.StackSizeModuleGui;
import de.ellpeck.prettypipes.pipe.modules.stacksize.StackSizeModuleItem; import de.ellpeck.prettypipes.pipe.modules.stacksize.StackSizeModuleItem;
import de.ellpeck.prettypipes.pressurizer.PressurizerBlock; import de.ellpeck.prettypipes.pressurizer.PressurizerBlock;
import de.ellpeck.prettypipes.pressurizer.PressurizerBlockEntity;
import de.ellpeck.prettypipes.pressurizer.PressurizerContainer; import de.ellpeck.prettypipes.pressurizer.PressurizerContainer;
import de.ellpeck.prettypipes.pressurizer.PressurizerGui; import de.ellpeck.prettypipes.pressurizer.PressurizerGui;
import de.ellpeck.prettypipes.pressurizer.PressurizerBlockEntity;
import de.ellpeck.prettypipes.terminal.CraftingTerminalBlock; import de.ellpeck.prettypipes.terminal.CraftingTerminalBlock;
import de.ellpeck.prettypipes.terminal.CraftingTerminalBlockEntity; import de.ellpeck.prettypipes.terminal.CraftingTerminalTileEntity;
import de.ellpeck.prettypipes.terminal.ItemTerminalBlock; import de.ellpeck.prettypipes.terminal.ItemTerminalBlock;
import de.ellpeck.prettypipes.terminal.ItemTerminalBlockEntity; import de.ellpeck.prettypipes.terminal.ItemTerminalTileEntity;
import de.ellpeck.prettypipes.terminal.containers.CraftingTerminalContainer; import de.ellpeck.prettypipes.terminal.containers.CraftingTerminalContainer;
import de.ellpeck.prettypipes.terminal.containers.CraftingTerminalGui; import de.ellpeck.prettypipes.terminal.containers.CraftingTerminalGui;
import de.ellpeck.prettypipes.terminal.containers.ItemTerminalContainer; import de.ellpeck.prettypipes.terminal.containers.ItemTerminalContainer;
import de.ellpeck.prettypipes.terminal.containers.ItemTerminalGui; import de.ellpeck.prettypipes.terminal.containers.ItemTerminalGui;
import net.minecraft.client.gui.screens.MenuScreens; import net.minecraft.block.Block;
import net.minecraft.client.renderer.ItemBlockRenderTypes; import net.minecraft.client.gui.ScreenManager;
import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.blockentity.BlockEntityRenderers; import net.minecraft.client.renderer.RenderTypeLookup;
import net.minecraft.client.renderer.entity.EntityRenderers; import net.minecraft.entity.EntityClassification;
import net.minecraft.world.entity.EntityType; import net.minecraft.entity.EntityType;
import net.minecraft.world.entity.MobCategory; import net.minecraft.inventory.container.ContainerType;
import net.minecraft.world.inventory.MenuType; import net.minecraft.item.BlockItem;
import net.minecraft.world.item.BlockItem; import net.minecraft.item.Item;
import net.minecraft.world.item.CreativeModeTab; import net.minecraft.item.ItemGroup;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.Block; import net.minecraft.nbt.INBT;
import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.tileentity.TileEntityType;
import net.minecraft.util.Direction;
import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.capabilities.CapabilityInject;
import net.minecraftforge.common.capabilities.CapabilityManager; import net.minecraftforge.common.capabilities.CapabilityManager;
import net.minecraftforge.common.capabilities.CapabilityToken; import net.minecraftforge.common.extensions.IForgeContainerType;
import net.minecraftforge.common.extensions.IForgeMenuType;
import net.minecraftforge.event.RegistryEvent; import net.minecraftforge.event.RegistryEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.client.registry.ClientRegistry;
import net.minecraftforge.fml.client.registry.RenderingRegistry;
import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.Mod.EventBusSubscriber.Bus; import net.minecraftforge.fml.common.Mod.EventBusSubscriber.Bus;
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
@ -74,6 +76,7 @@ import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
import net.minecraftforge.registries.ForgeRegistries; import net.minecraftforge.registries.ForgeRegistries;
import net.minecraftforge.registries.IForgeRegistry; import net.minecraftforge.registries.IForgeRegistry;
import javax.annotation.Nullable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
@ -83,46 +86,46 @@ import java.util.function.BiFunction;
@Mod.EventBusSubscriber(bus = Bus.MOD) @Mod.EventBusSubscriber(bus = Bus.MOD)
public final class Registry { public final class Registry {
public static final CreativeModeTab TAB = new CreativeModeTab(PrettyPipes.ID) { public static final ItemGroup GROUP = new ItemGroup(PrettyPipes.ID) {
@Override @Override
public ItemStack makeIcon() { public ItemStack createIcon() {
return new ItemStack(wrenchItem); return new ItemStack(wrenchItem);
} }
}; };
public static Capability<PipeNetwork> pipeNetworkCapability = CapabilityManager.get(new CapabilityToken<>() { @CapabilityInject(PipeNetwork.class)
}); public static Capability<PipeNetwork> pipeNetworkCapability;
public static Capability<IPipeConnectable> pipeConnectableCapability = CapabilityManager.get(new CapabilityToken<>() { @CapabilityInject(IPipeConnectable.class)
}); public static Capability<IPipeConnectable> pipeConnectableCapability;
public static Item wrenchItem; public static Item wrenchItem;
public static Item pipeFrameItem; public static Item pipeFrameItem;
public static Block pipeBlock; public static Block pipeBlock;
public static BlockEntityType<PipeBlockEntity> pipeBlockEntity; public static TileEntityType<PipeTileEntity> pipeTileEntity;
public static MenuType<MainPipeContainer> pipeContainer; public static ContainerType<MainPipeContainer> pipeContainer;
public static Block itemTerminalBlock; public static Block itemTerminalBlock;
public static BlockEntityType<ItemTerminalBlockEntity> itemTerminalBlockEntity; public static TileEntityType<ItemTerminalTileEntity> itemTerminalTileEntity;
public static MenuType<ItemTerminalContainer> itemTerminalContainer; public static ContainerType<ItemTerminalContainer> itemTerminalContainer;
public static Block craftingTerminalBlock; public static Block craftingTerminalBlock;
public static BlockEntityType<CraftingTerminalBlockEntity> craftingTerminalBlockEntity; public static TileEntityType<CraftingTerminalTileEntity> craftingTerminalTileEntity;
public static MenuType<CraftingTerminalContainer> craftingTerminalContainer; public static ContainerType<CraftingTerminalContainer> craftingTerminalContainer;
public static EntityType<PipeFrameEntity> pipeFrameEntity; public static EntityType<PipeFrameEntity> pipeFrameEntity;
public static Block pressurizerBlock; public static Block pressurizerBlock;
public static BlockEntityType<PressurizerBlockEntity> pressurizerBlockEntity; public static TileEntityType<PressurizerBlockEntity> pressurizerTileEntity;
public static MenuType<PressurizerContainer> pressurizerContainer; public static ContainerType<PressurizerContainer> pressurizerContainer;
public static MenuType<ExtractionModuleContainer> extractionModuleContainer; public static ContainerType<ExtractionModuleContainer> extractionModuleContainer;
public static MenuType<FilterModuleContainer> filterModuleContainer; public static ContainerType<FilterModuleContainer> filterModuleContainer;
public static MenuType<RetrievalModuleContainer> retrievalModuleContainer; public static ContainerType<RetrievalModuleContainer> retrievalModuleContainer;
public static MenuType<StackSizeModuleContainer> stackSizeModuleContainer; public static ContainerType<StackSizeModuleContainer> stackSizeModuleContainer;
public static MenuType<FilterIncreaseModuleContainer> filterIncreaseModuleContainer; public static ContainerType<FilterIncreaseModuleContainer> filterIncreaseModuleContainer;
public static MenuType<CraftingModuleContainer> craftingModuleContainer; public static ContainerType<CraftingModuleContainer> craftingModuleContainer;
public static MenuType<FilterModifierModuleContainer> filterModifierModuleContainer; public static ContainerType<FilterModifierModuleContainer> filterModifierModuleContainer;
@SubscribeEvent @SubscribeEvent
public static void registerBlocks(RegistryEvent.Register<Block> event) { public static void registerBlocks(RegistryEvent.Register<Block> event) {
@ -136,10 +139,10 @@ public final class Registry {
@SubscribeEvent @SubscribeEvent
public static void registerItems(RegistryEvent.Register<Item> event) { public static void registerItems(RegistryEvent.Register<Item> event) {
var registry = event.getRegistry(); IForgeRegistry<Item> registry = event.getRegistry();
registry.registerAll( registry.registerAll(
wrenchItem = new WrenchItem().setRegistryName("wrench"), wrenchItem = new WrenchItem().setRegistryName("wrench"),
new Item(new Item.Properties().tab(TAB)).setRegistryName("blank_module"), new Item(new Item.Properties().group(GROUP)).setRegistryName("blank_module"),
pipeFrameItem = new PipeFrameItem().setRegistryName("pipe_frame") pipeFrameItem = new PipeFrameItem().setRegistryName("pipe_frame")
); );
registry.registerAll(createTieredModule("extraction_module", ExtractionModuleItem::new)); registry.registerAll(createTieredModule("extraction_module", ExtractionModuleItem::new));
@ -157,33 +160,33 @@ public final class Registry {
ForgeRegistries.BLOCKS.getValues().stream() ForgeRegistries.BLOCKS.getValues().stream()
.filter(b -> b.getRegistryName().getNamespace().equals(PrettyPipes.ID)) .filter(b -> b.getRegistryName().getNamespace().equals(PrettyPipes.ID))
.forEach(b -> registry.register(new BlockItem(b, new Item.Properties().tab(TAB)).setRegistryName(b.getRegistryName()))); .forEach(b -> registry.register(new BlockItem(b, new Item.Properties().group(GROUP)).setRegistryName(b.getRegistryName())));
} }
@SubscribeEvent @SubscribeEvent
public static void registerBlockEntities(RegistryEvent.Register<BlockEntityType<?>> event) { public static void registerTiles(RegistryEvent.Register<TileEntityType<?>> event) {
event.getRegistry().registerAll( event.getRegistry().registerAll(
pipeBlockEntity = (BlockEntityType<PipeBlockEntity>) BlockEntityType.Builder.of(PipeBlockEntity::new, pipeBlock).build(null).setRegistryName("pipe"), pipeTileEntity = (TileEntityType<PipeTileEntity>) TileEntityType.Builder.create(PipeTileEntity::new, pipeBlock).build(null).setRegistryName("pipe"),
itemTerminalBlockEntity = (BlockEntityType<ItemTerminalBlockEntity>) BlockEntityType.Builder.of(ItemTerminalBlockEntity::new, itemTerminalBlock).build(null).setRegistryName("item_terminal"), itemTerminalTileEntity = (TileEntityType<ItemTerminalTileEntity>) TileEntityType.Builder.create(ItemTerminalTileEntity::new, itemTerminalBlock).build(null).setRegistryName("item_terminal"),
craftingTerminalBlockEntity = (BlockEntityType<CraftingTerminalBlockEntity>) BlockEntityType.Builder.of(CraftingTerminalBlockEntity::new, craftingTerminalBlock).build(null).setRegistryName("crafting_terminal"), craftingTerminalTileEntity = (TileEntityType<CraftingTerminalTileEntity>) TileEntityType.Builder.create(CraftingTerminalTileEntity::new, craftingTerminalBlock).build(null).setRegistryName("crafting_terminal"),
pressurizerBlockEntity = (BlockEntityType<PressurizerBlockEntity>) BlockEntityType.Builder.of(PressurizerBlockEntity::new, pressurizerBlock).build(null).setRegistryName("pressurizer") pressurizerTileEntity = (TileEntityType<PressurizerBlockEntity>) TileEntityType.Builder.create(PressurizerBlockEntity::new, pressurizerBlock).build(null).setRegistryName("pressurizer")
); );
} }
@SubscribeEvent @SubscribeEvent
public static void registerEntities(RegistryEvent.Register<EntityType<?>> event) { public static void registerEntities(RegistryEvent.Register<EntityType<?>> event) {
event.getRegistry().registerAll( event.getRegistry().registerAll(
pipeFrameEntity = (EntityType<PipeFrameEntity>) EntityType.Builder.<PipeFrameEntity>of(PipeFrameEntity::new, MobCategory.MISC).build("pipe_frame").setRegistryName("pipe_frame") pipeFrameEntity = (EntityType<PipeFrameEntity>) EntityType.Builder.<PipeFrameEntity>create(PipeFrameEntity::new, EntityClassification.MISC).build("pipe_frame").setRegistryName("pipe_frame")
); );
} }
@SubscribeEvent @SubscribeEvent
public static void registerContainers(RegistryEvent.Register<MenuType<?>> event) { public static void registerContainers(RegistryEvent.Register<ContainerType<?>> event) {
event.getRegistry().registerAll( event.getRegistry().registerAll(
pipeContainer = (MenuType<MainPipeContainer>) IForgeMenuType.create((windowId, inv, data) -> new MainPipeContainer(pipeContainer, windowId, inv.player, data.readBlockPos())).setRegistryName("pipe"), pipeContainer = (ContainerType<MainPipeContainer>) IForgeContainerType.create((windowId, inv, data) -> new MainPipeContainer(pipeContainer, windowId, inv.player, data.readBlockPos())).setRegistryName("pipe"),
itemTerminalContainer = (MenuType<ItemTerminalContainer>) IForgeMenuType.create((windowId, inv, data) -> new ItemTerminalContainer(itemTerminalContainer, windowId, inv.player, data.readBlockPos())).setRegistryName("item_terminal"), itemTerminalContainer = (ContainerType<ItemTerminalContainer>) IForgeContainerType.create((windowId, inv, data) -> new ItemTerminalContainer(itemTerminalContainer, windowId, inv.player, data.readBlockPos())).setRegistryName("item_terminal"),
craftingTerminalContainer = (MenuType<CraftingTerminalContainer>) IForgeMenuType.create((windowId, inv, data) -> new CraftingTerminalContainer(craftingTerminalContainer, windowId, inv.player, data.readBlockPos())).setRegistryName("crafting_terminal"), craftingTerminalContainer = (ContainerType<CraftingTerminalContainer>) IForgeContainerType.create((windowId, inv, data) -> new CraftingTerminalContainer(craftingTerminalContainer, windowId, inv.player, data.readBlockPos())).setRegistryName("crafting_terminal"),
pressurizerContainer = (MenuType<PressurizerContainer>) IForgeMenuType.create((windowId, inv, data) -> new PressurizerContainer(pressurizerContainer, windowId, inv.player, data.readBlockPos())).setRegistryName("pressurizer"), pressurizerContainer = (ContainerType<PressurizerContainer>) IForgeContainerType.create((windowId, inv, data) -> new PressurizerContainer(pressurizerContainer, windowId, inv.player, data.readBlockPos())).setRegistryName("pressurizer"),
extractionModuleContainer = createPipeContainer("extraction_module"), extractionModuleContainer = createPipeContainer("extraction_module"),
filterModuleContainer = createPipeContainer("filter_module"), filterModuleContainer = createPipeContainer("filter_module"),
retrievalModuleContainer = createPipeContainer("retrieval_module"), retrievalModuleContainer = createPipeContainer("retrieval_module"),
@ -194,44 +197,60 @@ public final class Registry {
); );
} }
private static <T extends AbstractPipeContainer<?>> MenuType<T> createPipeContainer(String name) { private static <T extends AbstractPipeContainer<?>> ContainerType<T> createPipeContainer(String name) {
return (MenuType<T>) IForgeMenuType.create((windowId, inv, data) -> { return (ContainerType<T>) IForgeContainerType.create((windowId, inv, data) -> {
var tile = Utility.getBlockEntity(PipeBlockEntity.class, inv.player.level, data.readBlockPos()); PipeTileEntity tile = Utility.getBlockEntity(PipeTileEntity.class, inv.player.world, data.readBlockPos());
var moduleIndex = data.readInt(); int moduleIndex = data.readInt();
var moduleStack = tile.modules.getStackInSlot(moduleIndex); ItemStack moduleStack = tile.modules.getStackInSlot(moduleIndex);
return ((IModule) moduleStack.getItem()).getContainer(moduleStack, tile, windowId, inv, inv.player, moduleIndex); return ((IModule) moduleStack.getItem()).getContainer(moduleStack, tile, windowId, inv, inv.player, moduleIndex);
}).setRegistryName(name); }).setRegistryName(name);
} }
private static Item[] createTieredModule(String name, BiFunction<String, ModuleTier, ModuleItem> item) { private static Item[] createTieredModule(String name, BiFunction<String, ModuleTier, ModuleItem> item) {
List<Item> items = new ArrayList<>(); List<Item> items = new ArrayList<>();
for (var tier : ModuleTier.values()) for (ModuleTier tier : ModuleTier.values())
items.add(item.apply(name, tier).setRegistryName(tier.name().toLowerCase(Locale.ROOT) + "_" + name)); items.add(item.apply(name, tier).setRegistryName(tier.name().toLowerCase(Locale.ROOT) + "_" + name));
return items.toArray(new Item[0]); return items.toArray(new Item[0]);
} }
public static void setup(FMLCommonSetupEvent event) { public static void setup(FMLCommonSetupEvent event) {
registerCap(PipeNetwork.class);
registerCap(IPipeConnectable.class);
PacketHandler.setup(); PacketHandler.setup();
} }
public static final class Client { public static final class Client {
public static void setup(FMLClientSetupEvent event) { public static void setup(FMLClientSetupEvent event) {
ItemBlockRenderTypes.setRenderLayer(pipeBlock, RenderType.cutout()); RenderTypeLookup.setRenderLayer(pipeBlock, RenderType.getCutout());
BlockEntityRenderers.register(pipeBlockEntity, PipeRenderer::new); ClientRegistry.bindTileEntityRenderer(pipeTileEntity, PipeRenderer::new);
EntityRenderers.register(pipeFrameEntity, PipeFrameRenderer::new); RenderingRegistry.registerEntityRenderingHandler(pipeFrameEntity, PipeFrameRenderer::new);
MenuScreens.register(pipeContainer, MainPipeGui::new); ScreenManager.registerFactory(pipeContainer, MainPipeGui::new);
MenuScreens.register(itemTerminalContainer, ItemTerminalGui::new); ScreenManager.registerFactory(itemTerminalContainer, ItemTerminalGui::new);
MenuScreens.register(pressurizerContainer, PressurizerGui::new); ScreenManager.registerFactory(pressurizerContainer, PressurizerGui::new);
MenuScreens.register(craftingTerminalContainer, CraftingTerminalGui::new); ScreenManager.registerFactory(craftingTerminalContainer, CraftingTerminalGui::new);
MenuScreens.register(extractionModuleContainer, ExtractionModuleGui::new); ScreenManager.registerFactory(extractionModuleContainer, ExtractionModuleGui::new);
MenuScreens.register(filterModuleContainer, FilterModuleGui::new); ScreenManager.registerFactory(filterModuleContainer, FilterModuleGui::new);
MenuScreens.register(retrievalModuleContainer, RetrievalModuleGui::new); ScreenManager.registerFactory(retrievalModuleContainer, RetrievalModuleGui::new);
MenuScreens.register(stackSizeModuleContainer, StackSizeModuleGui::new); ScreenManager.registerFactory(stackSizeModuleContainer, StackSizeModuleGui::new);
MenuScreens.register(filterIncreaseModuleContainer, FilterIncreaseModuleGui::new); ScreenManager.registerFactory(filterIncreaseModuleContainer, FilterIncreaseModuleGui::new);
MenuScreens.register(craftingModuleContainer, CraftingModuleGui::new); ScreenManager.registerFactory(craftingModuleContainer, CraftingModuleGui::new);
MenuScreens.register(filterModifierModuleContainer, FilterModifierModuleGui::new); ScreenManager.registerFactory(filterModifierModuleContainer, FilterModifierModuleGui::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);
}
} }

View file

@ -5,20 +5,25 @@ import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.resources.language.I18n; import net.minecraft.client.resources.language.I18n;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;
import net.minecraft.network.chat.*; import net.minecraft.network.chat.*;
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket; import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.Containers; import net.minecraft.world.Containers;
import net.minecraft.world.WorldlyContainer;
import net.minecraft.world.WorldlyContainerHolder; import net.minecraft.world.WorldlyContainerHolder;
import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.inventory.Slot;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.BlockGetter; import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;
import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraftforge.common.util.INBTSerializable; import net.minecraftforge.common.util.INBTSerializable;
import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.wrapper.SidedInvWrapper; import net.minecraftforge.items.wrapper.SidedInvWrapper;
@ -31,7 +36,7 @@ import java.util.function.Function;
public final class Utility { public final class Utility {
public static <T extends BlockEntity> T getBlockEntity(Class<T> type, BlockGetter world, BlockPos pos) { public static <T extends BlockEntity> T getBlockEntity(Class<T> type, LevelAccessor world, BlockPos pos) {
var tile = world.getBlockEntity(pos); var tile = world.getBlockEntity(pos);
return type.isInstance(tile) ? (T) tile : null; return type.isInstance(tile) ? (T) tile : null;
} }
@ -50,7 +55,7 @@ public final class Utility {
return Direction.fromNormal(diff.getX(), diff.getY(), diff.getZ()); return Direction.fromNormal(diff.getX(), diff.getY(), diff.getZ());
} }
public static void addTooltip(String name, List<Component> tooltip) { public static void addTooltip(String name, List<MutableComponent> tooltip) {
if (Screen.hasShiftDown()) { if (Screen.hasShiftDown()) {
var content = I18n.get("info." + PrettyPipes.ID + "." + name).split("\n"); var content = I18n.get("info." + PrettyPipes.ID + "." + name).split("\n");
for (var s : content) for (var s : content)

View file

@ -1,29 +1,42 @@
package de.ellpeck.prettypipes.entities; package de.ellpeck.prettypipes.entities;
import de.ellpeck.prettypipes.Registry; import de.ellpeck.prettypipes.Registry;
import de.ellpeck.prettypipes.network.NetworkLocation;
import de.ellpeck.prettypipes.network.PipeNetwork; import de.ellpeck.prettypipes.network.PipeNetwork;
import de.ellpeck.prettypipes.pipe.PipeBlock; import de.ellpeck.prettypipes.pipe.PipeBlock;
import net.minecraft.block.BlockState;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
import net.minecraft.network.FriendlyByteBuf; import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.item.ItemFrameEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.FilledMapItem;
import net.minecraft.network.syncher.EntityDataAccessor; import net.minecraft.network.syncher.EntityDataAccessor;
import net.minecraft.network.syncher.EntityDataSerializers; import net.minecraft.network.syncher.EntityDataSerializers;
import net.minecraft.network.syncher.SynchedEntityData; import net.minecraft.network.syncher.SynchedEntityData;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.decoration.ItemFrame; import net.minecraft.world.entity.decoration.ItemFrame;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.GameRules; import net.minecraft.item.Items;
import net.minecraft.network.IPacket;
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.math.BlockPos;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.world.GameRules;
import net.minecraft.world.World;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraft.world.phys.HitResult; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.storage.MapData;
import net.minecraftforge.entity.IEntityAdditionalSpawnData; import net.minecraftforge.entity.IEntityAdditionalSpawnData;
import net.minecraftforge.fml.common.registry.IEntityAdditionalSpawnData;
import net.minecraftforge.fml.network.NetworkHooks;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.List;
public class PipeFrameEntity extends ItemFrame implements IEntityAdditionalSpawnData { public class PipeFrameEntity extends ItemFrame implements IEntityAdditionalSpawnData {
@ -52,15 +65,15 @@ public class PipeFrameEntity extends ItemFrame implements IEntityAdditionalSpawn
return; return;
if (this.tickCount % 40 != 0) if (this.tickCount % 40 != 0)
return; return;
var network = PipeNetwork.get(this.level); PipeNetwork network = PipeNetwork.get(this.level);
var attached = getAttachedPipe(this.level, this.pos, this.direction); BlockPos attached = getAttachedPipe(this.level, this.pos, this.direction);
if (attached != null) { if (attached != null) {
var node = network.getNodeFromPipe(attached); BlockPos node = network.getNodeFromPipe(attached);
if (node != null) { if (node != null) {
var stack = this.getItem(); ItemStack stack = this.getItem();
if (!stack.isEmpty()) { if (!stack.isEmpty()) {
var items = network.getOrderedNetworkItems(node); List<NetworkLocation> items = network.getOrderedNetworkItems(node);
var amount = items.stream().mapToInt(i -> i.getItemAmount(this.level, stack)).sum(); int amount = items.stream().mapToInt(i -> i.getItemAmount(this.level, stack)).sum();
this.entityData.set(AMOUNT, amount); this.entityData.set(AMOUNT, amount);
return; return;
} }
@ -70,97 +83,103 @@ public class PipeFrameEntity extends ItemFrame implements IEntityAdditionalSpawn
} }
@Override @Override
public boolean survives() { public boolean onValidSurface() {
return super.survives() && canPlace(this.level, this.pos, this.direction); return super.onValidSurface() && canPlace(this.world, this.hangingPosition, this.facingDirection);
} }
private static BlockPos getAttachedPipe(Level world, BlockPos pos, Direction direction) { private static BlockPos getAttachedPipe(Level world, BlockPos pos, Direction direction) {
for (var i = 1; i <= 2; i++) { for (int i = 1; i <= 2; i++) {
var offset = pos.relative(direction.getOpposite(), i); BlockPos offset = pos.relative(direction.getOpposite(), i);
var state = world.getBlockState(offset); BlockState state = world.getBlockState(offset);
if (state.getBlock() instanceof PipeBlock) if (state.getBlock() instanceof PipeBlock)
return offset; return offset;
} }
return null; return null;
} }
public static boolean canPlace(Level world, BlockPos pos, Direction direction) { public static boolean canPlace(World world, BlockPos pos, Direction direction) {
return getAttachedPipe(world, pos, direction) != null; return getAttachedPipe(world, pos, direction) != null;
} }
public int getAmount() { public int getAmount() {
return this.entityData.get(AMOUNT); return this.dataManager.get(AMOUNT);
} }
@Override @Override
public boolean hurt(DamageSource source, float amount) { public boolean attackEntityFrom(DamageSource source, float amount) {
if (this.isInvulnerableTo(source)) { if (this.isInvulnerableTo(source)) {
return false; return false;
} else if (!source.isExplosion() && !this.getItem().isEmpty()) { } else if (!source.isExplosion() && !this.getDisplayedItem().isEmpty()) {
if (!this.level.isClientSide) { if (!this.world.isRemote) {
this.dropItemOrSelf(source.getDirectEntity(), false); this.dropItemOrSelf(source.getTrueSource(), false);
this.playSound(SoundEvents.ITEM_FRAME_REMOVE_ITEM, 1.0F, 1.0F); this.playSound(SoundEvents.ENTITY_ITEM_FRAME_REMOVE_ITEM, 1.0F, 1.0F);
} }
return true; return true;
} else { } else {
return super.hurt(source, amount); return super.attackEntityFrom(source, amount);
} }
} }
@Override @Override
public void dropItem(@Nullable Entity brokenEntity) { public void onBroken(@Nullable Entity brokenEntity) {
this.playSound(SoundEvents.ITEM_FRAME_BREAK, 1.0F, 1.0F); this.playSound(SoundEvents.ENTITY_ITEM_FRAME_BREAK, 1.0F, 1.0F);
this.dropItemOrSelf(brokenEntity, true); this.dropItemOrSelf(brokenEntity, true);
} }
private void dropItemOrSelf(@Nullable Entity entityIn, boolean b) { private void dropItemOrSelf(@Nullable Entity entityIn, boolean b) {
if (!this.level.getGameRules().getBoolean(GameRules.RULE_DOENTITYDROPS)) { if (!this.world.getGameRules().getBoolean(GameRules.DO_ENTITY_DROPS)) {
if (entityIn == null) if (entityIn == null)
this.getItem().setEntityRepresentation(null); this.getDisplayedItem().setAttachedEntity(null);
} else { } else {
var itemstack = this.getItem(); ItemStack itemstack = this.getDisplayedItem();
this.setItem(ItemStack.EMPTY); this.setDisplayedItem(ItemStack.EMPTY);
if (entityIn instanceof Player playerentity) { if (entityIn instanceof PlayerEntity) {
if (playerentity.isCreative()) { PlayerEntity playerentity = (PlayerEntity) entityIn;
itemstack.setEntityRepresentation(null); if (playerentity.abilities.isCreativeMode) {
itemstack.setAttachedEntity(null);
return; return;
} }
} }
if (b) if (b)
this.spawnAtLocation(Registry.pipeFrameItem); this.entityDropItem(Registry.pipeFrameItem);
if (!itemstack.isEmpty()) { if (!itemstack.isEmpty()) {
itemstack = itemstack.copy(); itemstack = itemstack.copy();
itemstack.setEntityRepresentation(null); itemstack.setAttachedEntity(null);
this.spawnAtLocation(itemstack); this.entityDropItem(itemstack);
} }
} }
} }
@Override @Override
public InteractionResult interact(Player player, InteractionHand hand) { public ActionResultType processInitialInteract(PlayerEntity player, Hand hand) {
if (this.getItem().isEmpty()) if (this.getDisplayedItem().isEmpty())
return super.interact(player, hand); return super.processInitialInteract(player, hand);
return InteractionResult.FAIL; return ActionResultType.FAIL;
} }
@Override @Override
public ItemStack getPickedResult(HitResult target) { public ItemStack getPickedResult(RayTraceResult target) {
return new ItemStack(Registry.pipeFrameItem); return new ItemStack(Registry.pipeFrameItem);
} }
@Override @Override
public void writeSpawnData(FriendlyByteBuf buffer) { public IPacket<?> createSpawnPacket() {
buffer.writeBlockPos(this.pos); return NetworkHooks.getEntitySpawningPacket(this);
buffer.writeInt(this.direction.ordinal());
} }
@Override @Override
public void readSpawnData(FriendlyByteBuf additionalData) { public void writeSpawnData(PacketBuffer buffer) {
this.pos = additionalData.readBlockPos(); buffer.writeBlockPos(this.hangingPosition);
this.direction = Direction.values()[additionalData.readInt()]; buffer.writeInt(this.facingDirection.getIndex());
}
@Override
public void readSpawnData(PacketBuffer additionalData) {
this.hangingPosition = additionalData.readBlockPos();
this.updateFacingWithBoundingBox(Direction.values()[additionalData.readInt()]);
} }
} }

View file

@ -1,37 +1,42 @@
package de.ellpeck.prettypipes.entities; package de.ellpeck.prettypipes.entities;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.math.Vector3f; import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.renderer.entity.EntityRendererProvider; import net.minecraft.client.renderer.IRenderTypeBuffer;
import net.minecraft.client.renderer.entity.EntityRendererManager;
import net.minecraft.client.renderer.entity.ItemFrameRenderer; import net.minecraft.client.renderer.entity.ItemFrameRenderer;
import net.minecraft.entity.item.ItemFrameEntity;
import net.minecraft.util.Direction;
import net.minecraft.util.math.vector.Matrix4f;
import net.minecraft.util.math.vector.Vector3d;
import net.minecraft.util.math.vector.Vector3f;
public class PipeFrameRenderer extends ItemFrameRenderer<PipeFrameEntity> { public class PipeFrameRenderer extends ItemFrameRenderer {
public PipeFrameRenderer(EntityRendererManager renderManagerIn) {
public PipeFrameRenderer(EntityRendererProvider.Context renderManagerIn) { super(renderManagerIn, Minecraft.getInstance().getItemRenderer());
super(renderManagerIn);
} }
@Override @Override
public void render(PipeFrameEntity entityIn, float entityYaw, float partialTicks, PoseStack matrixStackIn, MultiBufferSource bufferIn, int packedLightIn) { public void render(ItemFrameEntity entityIn, float entityYaw, float partialTicks, MatrixStack matrixStackIn, IRenderTypeBuffer bufferIn, int packedLightIn) {
super.render(entityIn, entityYaw, partialTicks, matrixStackIn, bufferIn, packedLightIn); super.render(entityIn, entityYaw, partialTicks, matrixStackIn, bufferIn, packedLightIn);
matrixStackIn.pushPose(); matrixStackIn.push();
var direction = entityIn.getDirection(); Direction direction = entityIn.getHorizontalFacing();
var vec3d = this.getRenderOffset(entityIn, partialTicks); Vector3d vec3d = this.getRenderOffset(entityIn, partialTicks);
matrixStackIn.translate(-vec3d.x, -vec3d.y, -vec3d.z); matrixStackIn.translate(-vec3d.getX(), -vec3d.getY(), -vec3d.getZ());
matrixStackIn.translate(direction.getStepX() * 0.46875, direction.getStepY() * 0.46875, direction.getStepZ() * 0.46875); matrixStackIn.translate(direction.getXOffset() * 0.46875, direction.getYOffset() * 0.46875, direction.getZOffset() * 0.46875);
matrixStackIn.mulPose(Vector3f.XP.rotationDegrees(entityIn.getXRot())); matrixStackIn.rotate(Vector3f.XP.rotationDegrees(entityIn.rotationPitch));
matrixStackIn.mulPose(Vector3f.YP.rotationDegrees(180.0F - entityIn.getYRot())); matrixStackIn.rotate(Vector3f.YP.rotationDegrees(180.0F - entityIn.rotationYaw));
var font = this.getFont(); FontRenderer font = this.getFontRendererFromRenderManager();
var amount = entityIn.getAmount(); int amount = ((PipeFrameEntity) entityIn).getAmount();
var ammountStrg = amount < 0 ? "?" : String.valueOf(amount); String ammountStrg = amount < 0 ? "?" : String.valueOf(amount);
var x = 0.5F - font.width(ammountStrg) / 2F; float x = 0.5F - font.getStringWidth(ammountStrg) / 2F;
var matrix4f = matrixStackIn.last().pose(); Matrix4f matrix4f = matrixStackIn.getLast().getMatrix();
matrixStackIn.translate(0, 0.285F, 0.415F); matrixStackIn.translate(0, 0.285F, 0.415F);
matrixStackIn.scale(-0.02F, -0.02F, 0.02F); matrixStackIn.scale(-0.02F, -0.02F, 0.02F);
font.drawInBatch(ammountStrg, x, 0, 0xFFFFFF, true, matrix4f, bufferIn, false, 0, packedLightIn); font.renderString(ammountStrg, x, 0, 0xFFFFFF, true, matrix4f, bufferIn, false, 0, packedLightIn);
matrixStackIn.popPose(); matrixStackIn.pop();
} }
} }

View file

@ -1,12 +1,12 @@
package de.ellpeck.prettypipes.items; package de.ellpeck.prettypipes.items;
import de.ellpeck.prettypipes.misc.ItemFilter; import de.ellpeck.prettypipes.misc.ItemFilter;
import de.ellpeck.prettypipes.pipe.PipeBlockEntity; import de.ellpeck.prettypipes.pipe.PipeTileEntity;
import de.ellpeck.prettypipes.pipe.containers.AbstractPipeContainer; import de.ellpeck.prettypipes.pipe.containers.AbstractPipeContainer;
import net.minecraft.core.BlockPos; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.world.entity.player.Inventory; import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.util.math.BlockPos;
import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.IItemHandler;
import java.util.List; import java.util.List;
@ -15,33 +15,33 @@ import java.util.function.Consumer;
public interface IModule { public interface IModule {
void tick(ItemStack module, PipeBlockEntity tile); void tick(ItemStack module, PipeTileEntity tile);
boolean canNetworkSee(ItemStack module, PipeBlockEntity tile); boolean canNetworkSee(ItemStack module, PipeTileEntity tile);
boolean canAcceptItem(ItemStack module, PipeBlockEntity tile, ItemStack stack); boolean canAcceptItem(ItemStack module, PipeTileEntity tile, ItemStack stack);
int getMaxInsertionAmount(ItemStack module, PipeBlockEntity tile, ItemStack stack, IItemHandler destination); int getMaxInsertionAmount(ItemStack module, PipeTileEntity tile, ItemStack stack, IItemHandler destination);
int getPriority(ItemStack module, PipeBlockEntity tile); int getPriority(ItemStack module, PipeTileEntity tile);
boolean isCompatible(ItemStack module, PipeBlockEntity tile, IModule other); boolean isCompatible(ItemStack module, PipeTileEntity tile, IModule other);
boolean hasContainer(ItemStack module, PipeBlockEntity tile); boolean hasContainer(ItemStack module, PipeTileEntity tile);
AbstractPipeContainer<?> getContainer(ItemStack module, PipeBlockEntity tile, int windowId, Inventory inv, Player player, int moduleIndex); AbstractPipeContainer<?> getContainer(ItemStack module, PipeTileEntity tile, int windowId, PlayerInventory inv, PlayerEntity player, int moduleIndex);
float getItemSpeedIncrease(ItemStack module, PipeBlockEntity tile); float getItemSpeedIncrease(ItemStack module, PipeTileEntity tile);
boolean canPipeWork(ItemStack module, PipeBlockEntity tile); boolean canPipeWork(ItemStack module, PipeTileEntity tile);
List<ItemStack> getAllCraftables(ItemStack module, PipeBlockEntity tile); List<ItemStack> getAllCraftables(ItemStack module, PipeTileEntity tile);
int getCraftableAmount(ItemStack module, PipeBlockEntity tile, Consumer<ItemStack> unavailableConsumer, ItemStack stack, Stack<ItemStack> dependencyChain); int getCraftableAmount(ItemStack module, PipeTileEntity tile, Consumer<ItemStack> unavailableConsumer, ItemStack stack, Stack<ItemStack> dependencyChain);
ItemStack craft(ItemStack module, PipeBlockEntity tile, BlockPos destPipe, Consumer<ItemStack> unavailableConsumer, ItemStack stack, Stack<ItemStack> dependencyChain); ItemStack craft(ItemStack module, PipeTileEntity tile, BlockPos destPipe, Consumer<ItemStack> unavailableConsumer, ItemStack stack, Stack<ItemStack> dependencyChain);
Integer getCustomNextNode(ItemStack module, PipeBlockEntity tile, List<BlockPos> nodes, int index); Integer getCustomNextNode(ItemStack module, PipeTileEntity tile, List<BlockPos> nodes, int index);
ItemFilter getItemFilter(ItemStack module, PipeBlockEntity tile); ItemFilter getItemFilter(ItemStack module, PipeTileEntity tile);
} }

View file

@ -3,16 +3,16 @@ package de.ellpeck.prettypipes.items;
import de.ellpeck.prettypipes.Registry; import de.ellpeck.prettypipes.Registry;
import de.ellpeck.prettypipes.Utility; import de.ellpeck.prettypipes.Utility;
import de.ellpeck.prettypipes.misc.ItemFilter; import de.ellpeck.prettypipes.misc.ItemFilter;
import de.ellpeck.prettypipes.pipe.PipeBlockEntity; import de.ellpeck.prettypipes.pipe.PipeTileEntity;
import de.ellpeck.prettypipes.pipe.containers.AbstractPipeContainer; import de.ellpeck.prettypipes.pipe.containers.AbstractPipeContainer;
import net.minecraft.core.BlockPos; import net.minecraft.client.util.ITooltipFlag;
import net.minecraft.network.chat.Component; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.world.entity.player.Inventory; import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.world.entity.player.Player; import net.minecraft.item.Item;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.TooltipFlag; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.level.Level; import net.minecraft.util.text.ITextComponent;
import net.minecraft.world.World;
import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.IItemHandler;
@ -28,79 +28,79 @@ public abstract class ModuleItem extends Item implements IModule {
private final String name; private final String name;
public ModuleItem(String name) { public ModuleItem(String name) {
super(new Properties().tab(Registry.TAB).stacksTo(16)); super(new Properties().group(Registry.GROUP).maxStackSize(16));
this.name = name; this.name = name;
} }
@Override @Override
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
public void appendHoverText(ItemStack stack, @Nullable Level worldIn, List<Component> tooltip, TooltipFlag flagIn) { public void addInformation(ItemStack stack, @Nullable World worldIn, List<ITextComponent> tooltip, ITooltipFlag flagIn) {
super.appendHoverText(stack, worldIn, tooltip, flagIn); super.addInformation(stack, worldIn, tooltip, flagIn);
Utility.addTooltip(this.name, tooltip); Utility.addTooltip(this.name, tooltip);
} }
@Override @Override
public void tick(ItemStack module, PipeBlockEntity tile) { public void tick(ItemStack module, PipeTileEntity tile) {
} }
@Override @Override
public boolean canNetworkSee(ItemStack module, PipeBlockEntity tile) { public boolean canNetworkSee(ItemStack module, PipeTileEntity tile) {
return true; return true;
} }
@Override @Override
public boolean canAcceptItem(ItemStack module, PipeBlockEntity tile, ItemStack stack) { public boolean canAcceptItem(ItemStack module, PipeTileEntity tile, ItemStack stack) {
return true; return true;
} }
@Override @Override
public int getMaxInsertionAmount(ItemStack module, PipeBlockEntity tile, ItemStack stack, IItemHandler destination) { public int getMaxInsertionAmount(ItemStack module, PipeTileEntity tile, ItemStack stack, IItemHandler destination) {
return Integer.MAX_VALUE; return Integer.MAX_VALUE;
} }
@Override @Override
public int getPriority(ItemStack module, PipeBlockEntity tile) { public int getPriority(ItemStack module, PipeTileEntity tile) {
return 0; return 0;
} }
@Override @Override
public AbstractPipeContainer<?> getContainer(ItemStack module, PipeBlockEntity tile, int windowId, Inventory inv, Player player, int moduleIndex) { public AbstractPipeContainer<?> getContainer(ItemStack module, PipeTileEntity tile, int windowId, PlayerInventory inv, PlayerEntity player, int moduleIndex) {
return null; return null;
} }
@Override @Override
public float getItemSpeedIncrease(ItemStack module, PipeBlockEntity tile) { public float getItemSpeedIncrease(ItemStack module, PipeTileEntity tile) {
return 0; return 0;
} }
@Override @Override
public boolean canPipeWork(ItemStack module, PipeBlockEntity tile) { public boolean canPipeWork(ItemStack module, PipeTileEntity tile) {
return true; return true;
} }
@Override @Override
public List<ItemStack> getAllCraftables(ItemStack module, PipeBlockEntity tile) { public List<ItemStack> getAllCraftables(ItemStack module, PipeTileEntity tile) {
return Collections.emptyList(); return Collections.emptyList();
} }
@Override @Override
public int getCraftableAmount(ItemStack module, PipeBlockEntity tile, Consumer<ItemStack> unavailableConsumer, ItemStack stack, Stack<ItemStack> dependencyChain) { public int getCraftableAmount(ItemStack module, PipeTileEntity tile, Consumer<ItemStack> unavailableConsumer, ItemStack stack, Stack<ItemStack> dependencyChain) {
return 0; return 0;
} }
@Override @Override
public ItemStack craft(ItemStack module, PipeBlockEntity tile, BlockPos destPipe, Consumer<ItemStack> unavailableConsumer, ItemStack stack, Stack<ItemStack> dependencyChain) { public ItemStack craft(ItemStack module, PipeTileEntity tile, BlockPos destPipe, Consumer<ItemStack> unavailableConsumer, ItemStack stack, Stack<ItemStack> dependencyChain) {
return stack; return stack;
} }
@Override @Override
public Integer getCustomNextNode(ItemStack module, PipeBlockEntity tile, List<BlockPos> nodes, int index) { public Integer getCustomNextNode(ItemStack module, PipeTileEntity tile, List<BlockPos> nodes, int index) {
return null; return null;
} }
@Override @Override
public ItemFilter getItemFilter(ItemStack module, PipeBlockEntity tile) { public ItemFilter getItemFilter(ItemStack module, PipeTileEntity tile) {
return null; return null;
} }
} }

View file

@ -3,68 +3,71 @@ package de.ellpeck.prettypipes.items;
import de.ellpeck.prettypipes.Registry; import de.ellpeck.prettypipes.Registry;
import de.ellpeck.prettypipes.Utility; import de.ellpeck.prettypipes.Utility;
import de.ellpeck.prettypipes.entities.PipeFrameEntity; import de.ellpeck.prettypipes.entities.PipeFrameEntity;
import net.minecraft.core.BlockPos; import net.minecraft.block.BlockState;
import net.minecraft.core.Direction; import net.minecraft.client.util.ITooltipFlag;
import net.minecraft.network.chat.Component; import net.minecraft.entity.EntityType;
import net.minecraft.world.InteractionResult; import net.minecraft.entity.item.HangingEntity;
import net.minecraft.world.entity.EntityType; import net.minecraft.entity.item.ItemFrameEntity;
import net.minecraft.world.entity.decoration.HangingEntity; import net.minecraft.entity.item.PaintingEntity;
import net.minecraft.world.entity.player.Player; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.world.item.Item; import net.minecraft.item.Item;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.TooltipFlag; import net.minecraft.item.ItemUseContext;
import net.minecraft.world.item.context.UseOnContext; import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.level.Level; import net.minecraft.util.ActionResultType;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.world.World;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.List; import java.util.List;
public class PipeFrameItem extends Item { public class PipeFrameItem extends Item {
public PipeFrameItem() { public PipeFrameItem() {
super(new Properties().tab(Registry.TAB)); super(new Properties().group(Registry.GROUP));
} }
// HangingEntityItem copypasta mostly, since it hardcodes the entities bleh // HangingEntityItem copypasta mostly, since it hardcodes the entities bleh
@Override @Override
public InteractionResult useOn(UseOnContext context) { public ActionResultType onItemUse(ItemUseContext context) {
var blockpos = context.getClickedPos(); BlockPos blockpos = context.getPos();
var direction = context.getClickedFace(); Direction direction = context.getFace();
var blockpos1 = blockpos.relative(direction); BlockPos blockpos1 = blockpos.offset(direction);
var playerentity = context.getPlayer(); PlayerEntity playerentity = context.getPlayer();
var itemstack = context.getItemInHand(); ItemStack itemstack = context.getItem();
if (playerentity != null && !this.canPlace(playerentity, direction, itemstack, blockpos1)) { if (playerentity != null && !this.canPlace(playerentity, direction, itemstack, blockpos1)) {
return InteractionResult.FAIL; return ActionResultType.FAIL;
} else { } else {
var world = context.getLevel(); World world = context.getWorld();
HangingEntity hangingentity = new PipeFrameEntity(Registry.pipeFrameEntity, world, blockpos1, direction); HangingEntity hangingentity = new PipeFrameEntity(Registry.pipeFrameEntity, world, blockpos1, direction);
var compoundTag = itemstack.getTag(); CompoundTag CompoundTag = itemstack.getTag();
if (compoundTag != null) { if (CompoundTag != null) {
EntityType.updateCustomEntityTag(world, playerentity, hangingentity, compoundTag); EntityType.applyItemNBT(world, playerentity, hangingentity, CompoundTag);
} }
if (hangingentity.survives()) { if (hangingentity.onValidSurface()) {
if (!world.isClientSide) { if (!world.isRemote) {
hangingentity.playPlacementSound(); hangingentity.playPlaceSound();
world.addFreshEntity(hangingentity); world.addEntity(hangingentity);
} }
itemstack.shrink(1); itemstack.shrink(1);
return InteractionResult.SUCCESS; return ActionResultType.SUCCESS;
} else { } else {
return InteractionResult.CONSUME; return ActionResultType.CONSUME;
} }
} }
} }
protected boolean canPlace(Player playerIn, Direction directionIn, ItemStack itemStackIn, BlockPos posIn) { protected boolean canPlace(PlayerEntity playerIn, Direction directionIn, ItemStack itemStackIn, BlockPos posIn) {
return !directionIn.getAxis().isVertical() && playerIn.mayUseItemAt(posIn, directionIn, itemStackIn) && PipeFrameEntity.canPlace(playerIn.level, posIn, directionIn); return !directionIn.getAxis().isVertical() && playerIn.canPlayerEdit(posIn, directionIn, itemStackIn) && PipeFrameEntity.canPlace(playerIn.world, posIn, directionIn);
} }
@Override @Override
public void appendHoverText(ItemStack stack, @Nullable Level worldIn, List<Component> tooltip, TooltipFlag flagIn) { public void addInformation(ItemStack stack, @Nullable World worldIn, List<ITextComponent> tooltip, ITooltipFlag flagIn) {
super.appendHoverText(stack, worldIn, tooltip, flagIn); super.addInformation(stack, worldIn, tooltip, flagIn);
Utility.addTooltip(this.getRegistryName().getPath(), tooltip); Utility.addTooltip(this.getRegistryName().getPath(), tooltip);
} }
} }

View file

@ -4,45 +4,48 @@ import de.ellpeck.prettypipes.Registry;
import de.ellpeck.prettypipes.Utility; import de.ellpeck.prettypipes.Utility;
import de.ellpeck.prettypipes.pipe.ConnectionType; import de.ellpeck.prettypipes.pipe.ConnectionType;
import de.ellpeck.prettypipes.pipe.PipeBlock; import de.ellpeck.prettypipes.pipe.PipeBlock;
import de.ellpeck.prettypipes.pipe.PipeBlockEntity; import de.ellpeck.prettypipes.pipe.PipeTileEntity;
import net.minecraft.network.chat.Component; import net.minecraft.block.Block;
import net.minecraft.sounds.SoundEvents; import net.minecraft.block.BlockState;
import net.minecraft.sounds.SoundSource; import net.minecraft.client.util.ITooltipFlag;
import net.minecraft.world.InteractionResult; import net.minecraft.enchantment.Enchantment;
import net.minecraft.world.item.BlockItem; import net.minecraft.enchantment.Enchantments;
import net.minecraft.world.item.Item; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.world.item.ItemStack; import net.minecraft.item.*;
import net.minecraft.world.item.TooltipFlag; import net.minecraft.state.EnumProperty;
import net.minecraft.world.item.context.BlockPlaceContext; import net.minecraft.util.ActionResultType;
import net.minecraft.world.item.context.UseOnContext; import net.minecraft.util.Direction;
import net.minecraft.world.item.enchantment.Enchantment; import net.minecraft.util.SoundCategory;
import net.minecraft.world.item.enchantment.Enchantments; import net.minecraft.util.SoundEvents;
import net.minecraft.world.level.Level; import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.world.level.block.Block; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.level.block.EntityBlock; 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.List;
import java.util.Map;
public class WrenchItem extends Item { public class WrenchItem extends Item {
public WrenchItem() { public WrenchItem() {
super(new Item.Properties().stacksTo(1).tab(Registry.TAB)); super(new Item.Properties().maxStackSize(1).group(Registry.GROUP));
} }
@Override @Override
public InteractionResult useOn(UseOnContext context) { public ActionResultType onItemUse(ItemUseContext context) {
var world = context.getLevel(); World world = context.getWorld();
var pos = context.getClickedPos(); BlockPos pos = context.getPos();
var player = context.getPlayer(); PlayerEntity player = context.getPlayer();
var state = world.getBlockState(pos); BlockState state = world.getBlockState(pos);
if (!(state.getBlock() instanceof PipeBlock)) if (!(state.getBlock() instanceof PipeBlock))
return InteractionResult.PASS; return ActionResultType.PASS;
var tile = Utility.getBlockEntity(PipeBlockEntity.class, world, pos); PipeTileEntity tile = Utility.getBlockEntity(PipeTileEntity.class, world, pos);
if (tile == null) if (tile == null)
return InteractionResult.FAIL; return ActionResultType.FAIL;
if (player.isCrouching()) { if (player.isSneaking()) {
if (!world.isClientSide) { if (!world.isRemote) {
if (tile.cover != null) { if (tile.cover != null) {
// remove the cover // remove the cover
tile.removeCover(player, context.getHand()); tile.removeCover(player, context.getHand());
@ -50,64 +53,64 @@ public class WrenchItem extends Item {
} else { } else {
// remove the pipe // remove the pipe
PipeBlock.dropItems(world, pos, player); PipeBlock.dropItems(world, pos, player);
Block.dropResources(state, world, pos, tile, null, ItemStack.EMPTY); Block.spawnDrops(state, world, pos, tile, null, ItemStack.EMPTY);
world.removeBlock(pos, false); world.removeBlock(pos, false);
} }
world.playSound(null, pos, SoundEvents.ITEM_FRAME_REMOVE_ITEM, SoundSource.PLAYERS, 1, 1); world.playSound(null, pos, SoundEvents.ENTITY_ITEM_FRAME_REMOVE_ITEM, SoundCategory.PLAYERS, 1, 1);
} }
return InteractionResult.sidedSuccess(world.isClientSide); return ActionResultType.func_233537_a_(world.isRemote);
} }
// placing covers // placing covers
if (tile.cover == null) { if (tile.cover == null) {
var offhand = player.getOffhandItem(); ItemStack offhand = player.getHeldItemOffhand();
if (offhand.getItem() instanceof BlockItem) { if (offhand.getItem() instanceof BlockItem) {
if (!world.isClientSide) { if (!world.isRemote) {
var blockContext = new BlockPlaceContext(context); BlockItemUseContext blockContext = new BlockItemUseContext(context);
var block = ((BlockItem) offhand.getItem()).getBlock(); Block block = ((BlockItem) offhand.getItem()).getBlock();
var cover = block.getStateForPlacement(blockContext); BlockState cover = block.getStateForPlacement(blockContext);
if (cover != null && !(block instanceof EntityBlock)) { if (cover != null && !block.hasTileEntity(cover)) {
tile.cover = cover; tile.cover = cover;
Utility.sendBlockEntityToClients(tile); Utility.sendBlockEntityToClients(tile);
offhand.shrink(1); offhand.shrink(1);
world.playSound(null, pos, SoundEvents.ITEM_FRAME_ADD_ITEM, SoundSource.PLAYERS, 1, 1); world.playSound(null, pos, SoundEvents.ENTITY_ITEM_FRAME_ADD_ITEM, SoundCategory.PLAYERS, 1, 1);
} }
} }
return InteractionResult.sidedSuccess(world.isClientSide); return ActionResultType.func_233537_a_(world.isRemote);
} }
} }
// disabling directions // disabling directions
for (var entry : PipeBlock.DIR_SHAPES.entrySet()) { for (Map.Entry<Direction, VoxelShape> entry : PipeBlock.DIR_SHAPES.entrySet()) {
var box = entry.getValue().bounds().move(pos).inflate(0.001F); AxisAlignedBB box = entry.getValue().getBoundingBox().offset(pos).grow(0.001F);
if (!box.contains(context.getClickLocation())) if (!box.contains(context.getHitVec()))
continue; continue;
var prop = PipeBlock.DIRECTIONS.get(entry.getKey()); EnumProperty<ConnectionType> prop = PipeBlock.DIRECTIONS.get(entry.getKey());
var curr = state.getValue(prop); ConnectionType curr = state.get(prop);
if (curr == ConnectionType.DISCONNECTED) if (curr == ConnectionType.DISCONNECTED)
continue; continue;
if (!world.isClientSide) { if (!world.isRemote) {
var newType = curr == ConnectionType.BLOCKED ? ConnectionType.CONNECTED : ConnectionType.BLOCKED; ConnectionType newType = curr == ConnectionType.BLOCKED ? ConnectionType.CONNECTED : ConnectionType.BLOCKED;
var otherPos = pos.relative(entry.getKey()); BlockPos otherPos = pos.offset(entry.getKey());
var otherState = world.getBlockState(otherPos); BlockState otherState = world.getBlockState(otherPos);
if (otherState.getBlock() instanceof PipeBlock) { if (otherState.getBlock() instanceof PipeBlock) {
otherState = otherState.setValue(PipeBlock.DIRECTIONS.get(entry.getKey().getOpposite()), newType); otherState = otherState.with(PipeBlock.DIRECTIONS.get(entry.getKey().getOpposite()), newType);
world.setBlockAndUpdate(otherPos, otherState); world.setBlockState(otherPos, otherState);
PipeBlock.onStateChanged(world, otherPos, otherState); PipeBlock.onStateChanged(world, otherPos, otherState);
} }
var newState = state.setValue(prop, newType); BlockState newState = state.with(prop, newType);
world.setBlockAndUpdate(pos, newState); world.setBlockState(pos, newState);
PipeBlock.onStateChanged(world, pos, newState); PipeBlock.onStateChanged(world, pos, newState);
world.playSound(null, pos, SoundEvents.ITEM_FRAME_ROTATE_ITEM, SoundSource.PLAYERS, 1, 1); world.playSound(null, pos, SoundEvents.ENTITY_ITEM_FRAME_ROTATE_ITEM, SoundCategory.PLAYERS, 1, 1);
} }
return InteractionResult.sidedSuccess(world.isClientSide); return ActionResultType.func_233537_a_(world.isRemote);
} }
return InteractionResult.PASS; return ActionResultType.PASS;
} }
@Override @Override
public void appendHoverText(ItemStack stack, Level worldIn, List<Component> tooltip, TooltipFlag flagIn) { public void addInformation(ItemStack stack, World worldIn, List<ITextComponent> tooltip, ITooltipFlag flagIn) {
Utility.addTooltip(this.getRegistryName().getPath(), tooltip); Utility.addTooltip(this.getRegistryName().getPath(), tooltip);
} }

View file

@ -5,11 +5,21 @@ import net.minecraft.world.item.ItemStack;
import java.util.Arrays; import java.util.Arrays;
import java.util.Objects; import java.util.Objects;
public record EquatableItemStack(ItemStack stack, ItemEquality... equalityTypes) { public class EquatableItemStack {
public final ItemStack stack;
public final ItemEquality[] equalityTypes;
public EquatableItemStack(ItemStack stack, ItemEquality... equalityTypes) {
this.stack = stack;
this.equalityTypes = equalityTypes;
}
public boolean equals(Object o) { public boolean equals(Object o) {
if (o instanceof EquatableItemStack other) if (o instanceof EquatableItemStack) {
EquatableItemStack other = (EquatableItemStack) o;
return Arrays.equals(this.equalityTypes, other.equalityTypes) && ItemEquality.compareItems(this.stack, other.stack, this.equalityTypes); return Arrays.equals(this.equalityTypes, other.equalityTypes) && ItemEquality.compareItems(this.stack, other.stack, this.equalityTypes);
}
return false; return false;
} }

View file

@ -3,7 +3,7 @@ package de.ellpeck.prettypipes.misc;
import de.ellpeck.prettypipes.PrettyPipes; import de.ellpeck.prettypipes.PrettyPipes;
import de.ellpeck.prettypipes.network.PipeNetwork; import de.ellpeck.prettypipes.network.PipeNetwork;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.Level; import net.minecraft.world.World;
import net.minecraftforge.event.AttachCapabilitiesEvent; import net.minecraftforge.event.AttachCapabilitiesEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod;
@ -12,7 +12,7 @@ import net.minecraftforge.fml.common.Mod;
public final class Events { public final class Events {
@SubscribeEvent @SubscribeEvent
public static void onWorldCaps(AttachCapabilitiesEvent<Level> event) { public static void onWorldCaps(AttachCapabilitiesEvent<World> event) {
event.addCapability(new ResourceLocation(PrettyPipes.ID, "network"), new PipeNetwork(event.getObject())); event.addCapability(new ResourceLocation(PrettyPipes.ID, "network"), new PipeNetwork(event.getObject()));
} }
} }

View file

@ -1,11 +1,11 @@
package de.ellpeck.prettypipes.misc; package de.ellpeck.prettypipes.misc;
import net.minecraft.world.entity.player.Player; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.inventory.container.Container;
import net.minecraft.inventory.container.Slot;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.SlotItemHandler; import net.minecraftforge.items.SlotItemHandler;
import org.jetbrains.annotations.NotNull;
public class FilterSlot extends SlotItemHandler { public class FilterSlot extends SlotItemHandler {
@ -16,9 +16,9 @@ public class FilterSlot extends SlotItemHandler {
this.onlyOneItem = onlyOneItem; this.onlyOneItem = onlyOneItem;
} }
public static boolean checkFilter(AbstractContainerMenu container, int slotId, Player player) { public static boolean checkFilter(Container container, int slotId, PlayerEntity player) {
if (slotId >= 0 && slotId < container.slots.size()) { if (slotId >= 0 && slotId < container.inventorySlots.size()) {
var slot = container.getSlot(slotId); Slot slot = container.getSlot(slotId);
if (slot instanceof FilterSlot) { if (slot instanceof FilterSlot) {
((FilterSlot) slot).slotClick(player); ((FilterSlot) slot).slotClick(player);
return true; return true;
@ -27,33 +27,32 @@ public class FilterSlot extends SlotItemHandler {
return false; return false;
} }
private void slotClick(Player player) { private void slotClick(PlayerEntity player) {
var heldStack = player.inventoryMenu.getCarried(); ItemStack heldStack = player.inventory.getItemStack();
var stackInSlot = this.getItem(); ItemStack stackInSlot = this.getStack();
if (!stackInSlot.isEmpty() && heldStack.isEmpty()) { if (!stackInSlot.isEmpty() && heldStack.isEmpty()) {
this.safeInsert(ItemStack.EMPTY); this.putStack(ItemStack.EMPTY);
} else if (!heldStack.isEmpty()) { } else if (!heldStack.isEmpty()) {
var s = heldStack.copy(); ItemStack s = heldStack.copy();
if (this.onlyOneItem) if (this.onlyOneItem)
s.setCount(1); s.setCount(1);
this.safeInsert(s); this.putStack(s);
} }
} }
@Override @Override
public boolean mayPlace(@NotNull ItemStack stack) { public boolean isItemValid(ItemStack stack) {
return false; return false;
} }
@Override @Override
public ItemStack safeInsert(ItemStack stack) { public void putStack(ItemStack stack) {
return super.safeInsert(stack.copy()); super.putStack(stack.copy());
} }
@Override @Override
public boolean mayPickup(Player playerIn) { public boolean canTakeStack(PlayerEntity playerIn) {
return false; return false;
} }
} }

View file

@ -3,19 +3,18 @@ package de.ellpeck.prettypipes.misc;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
import de.ellpeck.prettypipes.PrettyPipes; import de.ellpeck.prettypipes.PrettyPipes;
import de.ellpeck.prettypipes.packets.PacketButton; import de.ellpeck.prettypipes.packets.PacketButton;
import de.ellpeck.prettypipes.pipe.PipeBlockEntity; import de.ellpeck.prettypipes.pipe.PipeTileEntity;
import de.ellpeck.prettypipes.pipe.modules.modifier.FilterModifierModuleItem; import de.ellpeck.prettypipes.pipe.modules.modifier.FilterModifierModuleItem;
import net.minecraft.ChatFormatting; import net.minecraft.ChatFormatting;
import net.minecraft.client.gui.components.AbstractWidget;
import net.minecraft.client.gui.components.Button; import net.minecraft.client.gui.components.Button;
import net.minecraft.client.gui.components.Widget;
import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.gui.screens.Screen;
import net.minecraft.core.Direction;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.TranslatableComponent; import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.world.inventory.Slot; import net.minecraft.world.inventory.Slot;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.ItemHandlerHelper; import net.minecraftforge.items.ItemHandlerHelper;
import net.minecraftforge.items.ItemStackHandler; import net.minecraftforge.items.ItemStackHandler;
@ -26,14 +25,14 @@ import java.util.function.Supplier;
public class ItemFilter extends ItemStackHandler { public class ItemFilter extends ItemStackHandler {
private final ItemStack stack; private final ItemStack stack;
private final PipeBlockEntity pipe; private final PipeTileEntity pipe;
public boolean isWhitelist; public boolean isWhitelist;
public boolean canPopulateFromInventories; public boolean canPopulateFromInventories;
public boolean canModifyWhitelist = true; public boolean canModifyWhitelist = true;
private boolean modified; private boolean modified;
public ItemFilter(int size, ItemStack stack, PipeBlockEntity pipe) { public ItemFilter(int size, ItemStack stack, PipeTileEntity pipe) {
super(size); super(size);
this.stack = stack; this.stack = stack;
this.pipe = pipe; this.pipe = pipe;
@ -43,23 +42,23 @@ public class ItemFilter extends ItemStackHandler {
public List<Slot> getSlots(int x, int y) { public List<Slot> getSlots(int x, int y) {
List<Slot> slots = new ArrayList<>(); List<Slot> slots = new ArrayList<>();
for (var i = 0; i < this.getSlots(); i++) for (int i = 0; i < this.getSlots(); i++)
slots.add(new FilterSlot(this, i, x + i % 9 * 18, y + i / 9 * 18, true)); slots.add(new FilterSlot(this, i, x + i % 9 * 18, y + i / 9 * 18, true));
return slots; return slots;
} }
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
public List<AbstractWidget> getButtons(Screen gui, int x, int y) { public List<Widget> getButtons(Screen gui, int x, int y) {
List<AbstractWidget> buttons = new ArrayList<>(); List<Widget> buttons = new ArrayList<>();
if (this.canModifyWhitelist) { if (this.canModifyWhitelist) {
var whitelistText = (Supplier<TranslatableComponent>) () -> new TranslatableComponent("info." + PrettyPipes.ID + "." + (this.isWhitelist ? "whitelist" : "blacklist")); Supplier<TranslatableComponent> whitelistText = () -> new TranslatableComponent("info." + PrettyPipes.ID + "." + (this.isWhitelist ? "whitelist" : "blacklist"));
buttons.add(new Button(x, y, 70, 20, whitelistText.get(), button -> { buttons.add(new Button(x, y, 70, 20, whitelistText.get(), button -> {
PacketButton.sendAndExecute(this.pipe.getBlockPos(), PacketButton.ButtonResult.FILTER_CHANGE, 0); PacketButton.sendAndExecute(this.pipe.getPos(), PacketButton.ButtonResult.FILTER_CHANGE, 0);
button.setMessage(whitelistText.get()); button.setMessage(whitelistText.get());
})); }));
} }
if (this.canPopulateFromInventories) { if (this.canPopulateFromInventories) {
buttons.add(new Button(x + 72, y, 70, 20, new TranslatableComponent("info." + PrettyPipes.ID + ".populate"), button -> PacketButton.sendAndExecute(this.pipe.getBlockPos(), PacketButton.ButtonResult.FILTER_CHANGE, 1)) { buttons.add(new Button(x + 72, y, 70, 20, new TranslatableComponent("info." + PrettyPipes.ID + ".populate"), button -> PacketButton.sendAndExecute(this.pipe.getPos(), PacketButton.ButtonResult.FILTER_CHANGE, 1)) {
@Override @Override
public void renderToolTip(PoseStack matrix, int x, int y) { public void renderToolTip(PoseStack matrix, int x, int y) {
gui.renderTooltip(matrix, new TranslatableComponent("info." + PrettyPipes.ID + ".populate.description").withStyle(ChatFormatting.GRAY), x, y); gui.renderTooltip(matrix, new TranslatableComponent("info." + PrettyPipes.ID + ".populate.description").withStyle(ChatFormatting.GRAY), x, y);
@ -76,19 +75,19 @@ public class ItemFilter extends ItemStackHandler {
this.save(); this.save();
} else if (id == 1 && this.canPopulateFromInventories) { } else if (id == 1 && this.canPopulateFromInventories) {
// populate filter from inventories // populate filter from inventories
var filters = this.pipe.getFilters(); List<ItemFilter> filters = this.pipe.getFilters();
for (var direction : Direction.values()) { for (Direction direction : Direction.values()) {
var handler = this.pipe.getItemHandler(direction); IItemHandler handler = this.pipe.getItemHandler(direction);
if (handler == null) if (handler == null)
continue; continue;
for (var i = 0; i < handler.getSlots(); i++) { for (int i = 0; i < handler.getSlots(); i++) {
var stack = handler.getStackInSlot(i); ItemStack stack = handler.getStackInSlot(i);
if (stack.isEmpty() || this.isFiltered(stack)) if (stack.isEmpty() || this.isFiltered(stack))
continue; continue;
var copy = stack.copy(); ItemStack copy = stack.copy();
copy.setCount(1); copy.setCount(1);
// try inserting into ourselves and any filter increase modifiers // try inserting into ourselves and any filter increase modifiers
for (var filter : filters) { for (ItemFilter filter : filters) {
if (ItemHandlerHelper.insertItem(filter, copy, false).isEmpty()) { if (ItemHandlerHelper.insertItem(filter, copy, false).isEmpty()) {
filter.save(); filter.save();
break; break;
@ -104,11 +103,11 @@ public class ItemFilter extends ItemStackHandler {
} }
private boolean isFiltered(ItemStack stack) { private boolean isFiltered(ItemStack stack) {
var types = getEqualityTypes(this.pipe); ItemEquality[] types = getEqualityTypes(this.pipe);
// also check if any filter increase modules have the item we need // also check if any filter increase modules have the item we need
for (ItemStackHandler handler : this.pipe.getFilters()) { for (ItemStackHandler handler : this.pipe.getFilters()) {
for (var i = 0; i < handler.getSlots(); i++) { for (int i = 0; i < handler.getSlots(); i++) {
var filter = handler.getStackInSlot(i); ItemStack filter = handler.getStackInSlot(i);
if (filter.isEmpty()) if (filter.isEmpty())
continue; continue;
if (ItemEquality.compareItems(stack, filter, types)) if (ItemEquality.compareItems(stack, filter, types))
@ -127,7 +126,7 @@ public class ItemFilter extends ItemStackHandler {
@Override @Override
public CompoundTag serializeNBT() { public CompoundTag serializeNBT() {
var nbt = super.serializeNBT(); CompoundTag nbt = super.serializeNBT();
if (this.canModifyWhitelist) if (this.canModifyWhitelist)
nbt.putBoolean("whitelist", this.isWhitelist); nbt.putBoolean("whitelist", this.isWhitelist);
return nbt; return nbt;
@ -145,7 +144,7 @@ public class ItemFilter extends ItemStackHandler {
this.modified = true; this.modified = true;
} }
public static ItemEquality[] getEqualityTypes(PipeBlockEntity pipe) { public static ItemEquality[] getEqualityTypes(PipeTileEntity pipe) {
return pipe.streamModules() return pipe.streamModules()
.filter(m -> m.getRight() instanceof FilterModifierModuleItem) .filter(m -> m.getRight() instanceof FilterModifierModuleItem)
.map(m -> ((FilterModifierModuleItem) m.getRight()).getEqualityType(m.getLeft())) .map(m -> ((FilterModifierModuleItem) m.getRight()).getEqualityType(m.getLeft()))
@ -153,7 +152,6 @@ public class ItemFilter extends ItemStackHandler {
} }
public interface IFilteredContainer { public interface IFilteredContainer {
ItemFilter getFilter(); ItemFilter getFilter();
} }
} }

View file

@ -1,17 +1,26 @@
package de.ellpeck.prettypipes.misc; package de.ellpeck.prettypipes.misc;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.PoseStack; import de.ellpeck.prettypipes.PrettyPipes;
import de.ellpeck.prettypipes.terminal.containers.ItemTerminalGui; import de.ellpeck.prettypipes.terminal.containers.ItemTerminalGui;
import net.minecraft.ChatFormatting; import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.components.AbstractWidget; import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.gui.narration.NarrationElementOutput; import net.minecraft.client.gui.screen.inventory.ContainerScreen;
import net.minecraft.network.chat.TextComponent; import net.minecraft.client.gui.widget.Widget;
import net.minecraft.client.renderer.ItemRenderer;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.resources.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.Optional; import java.util.List;
public class ItemTerminalWidget extends AbstractWidget { public class ItemTerminalWidget extends Widget {
private final ItemTerminalGui screen; private final ItemTerminalGui screen;
public final int gridX; public final int gridX;
@ -21,7 +30,7 @@ public class ItemTerminalWidget extends AbstractWidget {
public boolean craftable; public boolean craftable;
public ItemTerminalWidget(int xIn, int yIn, int gridX, int gridY, ItemTerminalGui screen) { public ItemTerminalWidget(int xIn, int yIn, int gridX, int gridY, ItemTerminalGui screen) {
super(xIn, yIn, 16, 16, new TextComponent("")); super(xIn, yIn, 16, 16, new StringTextComponent(""));
this.gridX = gridX; this.gridX = gridX;
this.gridY = gridY; this.gridY = gridY;
this.screen = screen; this.screen = screen;
@ -35,25 +44,25 @@ public class ItemTerminalWidget extends AbstractWidget {
} }
@Override @Override
public void renderButton(PoseStack matrix, int mouseX, int mouseY, float partialTicks) { public void renderButton(MatrixStack matrix, int mouseX, int mouseY, float partialTicks) {
var mc = this.screen.getMinecraft(); Minecraft mc = this.screen.getMinecraft();
var renderer = mc.getItemRenderer(); ItemRenderer renderer = mc.getItemRenderer();
this.setBlitOffset(100); this.setBlitOffset(100);
renderer.blitOffset = 100; renderer.zLevel = 100;
if (this.selected) if (this.selected)
fill(matrix, this.x, this.y, this.x + 16, this.y + 16, -2130706433); fill(matrix, this.x, this.y, this.x + 16, this.y + 16, -2130706433);
RenderSystem.enableDepthTest(); RenderSystem.enableDepthTest();
renderer.renderGuiItem(this.stack, this.x, this.y); renderer.renderItemAndEffectIntoGUI(mc.player, this.stack, this.x, this.y);
var amount = !this.craftable ? this.stack.getCount() : 0; int amount = !this.craftable ? this.stack.getCount() : 0;
var amountStrg = this.stack.getCount() >= 1000 ? amount / 1000 + "k" : String.valueOf(amount); String amountStrg = this.stack.getCount() >= 1000 ? amount / 1000 + "k" : String.valueOf(amount);
matrix.pushPose(); RenderSystem.pushMatrix();
matrix.scale(0.8F, 0.8F, 1); RenderSystem.scalef(0.8F, 0.8F, 1);
renderer.renderGuiItemDecorations(mc.font, this.stack, (int) (this.x / 0.8F) + 4, (int) (this.y / 0.8F) + 4, amountStrg); renderer.renderItemOverlayIntoGUI(mc.fontRenderer, this.stack, (int) (this.x / 0.8F) + 4, (int) (this.y / 0.8F) + 4, amountStrg);
matrix.popPose(); RenderSystem.popMatrix();
renderer.blitOffset = 0; renderer.zLevel = 0;
this.setBlitOffset(0); this.setBlitOffset(0);
if (this.isHoveredOrFocused()) { if (this.isHovered()) {
RenderSystem.disableDepthTest(); RenderSystem.disableDepthTest();
RenderSystem.colorMask(true, true, true, false); RenderSystem.colorMask(true, true, true, false);
this.fillGradient(matrix, this.x, this.y, this.x + 16, this.y + 16, -2130706433, -2130706433); this.fillGradient(matrix, this.x, this.y, this.x + 16, this.y + 16, -2130706433, -2130706433);
@ -63,21 +72,18 @@ public class ItemTerminalWidget extends AbstractWidget {
} }
@Override @Override
public void renderToolTip(PoseStack matrix, int mouseX, int mouseY) { public void renderToolTip(MatrixStack matrix, int mouseX, int mouseY) {
if (this.visible && this.isHoveredOrFocused()) { if (this.visible && this.isHovered()) {
var tooltip = this.screen.getTooltipFromItem(this.stack); GuiUtils.preItemToolTip(this.stack);
List<ITextComponent> tooltip = this.screen.getTooltipFromItem(this.stack);
if (this.stack.getCount() >= 1000) { if (this.stack.getCount() >= 1000) {
var comp = tooltip.get(0); ITextComponent comp = tooltip.get(0);
if (comp instanceof TextComponent text) { if (comp instanceof TextComponent) {
tooltip.set(0, text.append(new TextComponent(" (" + this.stack.getCount() + ')').withStyle(ChatFormatting.BOLD))); tooltip.set(0, ((TextComponent) comp).append(new StringTextComponent(" (" + this.stack.getCount() + ')').mergeStyle(TextFormatting.BOLD)));
} }
} }
this.screen.renderTooltip(matrix, tooltip, Optional.empty(), mouseX, mouseY); this.screen.func_243308_b(matrix, tooltip, mouseX, mouseY);
GuiUtils.postItemToolTip();
} }
} }
@Override
public void updateNarration(NarrationElementOutput output) {
this.defaultButtonNarrationText(output);
}
} }

View file

@ -4,11 +4,9 @@ import com.google.gson.Gson;
import com.google.gson.GsonBuilder; import com.google.gson.GsonBuilder;
import de.ellpeck.prettypipes.PrettyPipes; import de.ellpeck.prettypipes.PrettyPipes;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.entity.player.PlayerEntity;
import java.io.File; import java.io.*;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class PlayerPrefs { public class PlayerPrefs {
@ -20,10 +18,10 @@ public class PlayerPrefs {
public boolean syncJei = true; public boolean syncJei = true;
public void save() { public void save() {
var file = getFile(); File file = getFile();
if (file.exists()) if (file.exists())
file.delete(); file.delete();
try (var writer = new FileWriter(file)) { try (FileWriter writer = new FileWriter(file)) {
GSON.toJson(this, writer); GSON.toJson(this, writer);
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
@ -32,9 +30,9 @@ public class PlayerPrefs {
public static PlayerPrefs get() { public static PlayerPrefs get() {
if (instance == null) { if (instance == null) {
var file = getFile(); File file = getFile();
if (file.exists()) { if (file.exists()) {
try (var reader = new FileReader(file)) { try (FileReader reader = new FileReader(file)) {
instance = GSON.fromJson(reader, PlayerPrefs.class); instance = GSON.fromJson(reader, PlayerPrefs.class);
return instance; return instance;
} catch (IOException e) { } catch (IOException e) {
@ -47,7 +45,7 @@ public class PlayerPrefs {
} }
private static File getFile() { private static File getFile() {
var location = Minecraft.getInstance().gameDirectory; File location = Minecraft.getInstance().gameDir;
return new File(location, PrettyPipes.ID + "prefs"); return new File(location, PrettyPipes.ID + "prefs");
} }
} }

View file

@ -32,9 +32,9 @@ public class NetworkEdge extends DefaultWeightedEdge implements INBTSerializable
@Override @Override
public CompoundTag serializeNBT() { public CompoundTag serializeNBT() {
var nbt = new CompoundTag(); CompoundTag nbt = new CompoundTag();
var list = new ListTag(); ListTag list = new ListTag();
for (var pos : this.pipes) for (BlockPos pos : this.pipes)
list.add(NbtUtils.writeBlockPos(pos)); list.add(NbtUtils.writeBlockPos(pos));
nbt.put("pipes", list); nbt.put("pipes", list);
return nbt; return nbt;
@ -43,8 +43,8 @@ public class NetworkEdge extends DefaultWeightedEdge implements INBTSerializable
@Override @Override
public void deserializeNBT(CompoundTag nbt) { public void deserializeNBT(CompoundTag nbt) {
this.pipes.clear(); this.pipes.clear();
var list = nbt.getList("pipes", Tag.TAG_COMPOUND); ListTag list = nbt.getList("pipes", Tag.TAG_COMPOUND);
for (var i = 0; i < list.size(); i++) for (int i = 0; i < list.size(); i++)
this.pipes.add(NbtUtils.readBlockPos(list.getCompound(i))); this.pipes.add(NbtUtils.readBlockPos(list.getCompound(i)));
} }
} }

View file

@ -26,7 +26,7 @@ public class NetworkItem {
} }
public ItemStack asStack() { public ItemStack asStack() {
var stack = this.item.stack().copy(); ItemStack stack = this.item.stack.copy();
stack.setCount(this.amount); stack.setCount(this.amount);
return stack; return stack;
} }

View file

@ -1,13 +1,13 @@
package de.ellpeck.prettypipes.network; package de.ellpeck.prettypipes.network;
import de.ellpeck.prettypipes.misc.ItemEquality; import de.ellpeck.prettypipes.misc.ItemEquality;
import de.ellpeck.prettypipes.pipe.PipeBlockEntity; import de.ellpeck.prettypipes.pipe.PipeTileEntity;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.nbt.NbtUtils;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.level.Level; import net.minecraft.nbt.NBTUtil;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraftforge.common.util.INBTSerializable; import net.minecraftforge.common.util.INBTSerializable;
import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.IItemHandler;
@ -33,7 +33,7 @@ public class NetworkLocation implements INBTSerializable<CompoundTag> {
this.deserializeNBT(nbt); this.deserializeNBT(nbt);
} }
public List<Integer> getStackSlots(Level world, ItemStack stack, ItemEquality... equalityTypes) { public List<Integer> getStackSlots(World world, ItemStack stack, ItemEquality... equalityTypes) {
if (this.isEmpty(world)) if (this.isEmpty(world))
return Collections.emptyList(); return Collections.emptyList();
return this.getItems(world).entrySet().stream() return this.getItems(world).entrySet().stream()
@ -41,7 +41,7 @@ public class NetworkLocation implements INBTSerializable<CompoundTag> {
.map(Map.Entry::getKey).collect(Collectors.toList()); .map(Map.Entry::getKey).collect(Collectors.toList());
} }
public int getItemAmount(Level world, ItemStack stack, ItemEquality... equalityTypes) { public int getItemAmount(World world, ItemStack stack, ItemEquality... equalityTypes) {
if (this.isEmpty(world)) if (this.isEmpty(world))
return 0; return 0;
return this.getItems(world).entrySet().stream() return this.getItems(world).entrySet().stream()
@ -49,12 +49,12 @@ public class NetworkLocation implements INBTSerializable<CompoundTag> {
.mapToInt(kv -> kv.getValue().getCount()).sum(); .mapToInt(kv -> kv.getValue().getCount()).sum();
} }
public Map<Integer, ItemStack> getItems(Level world) { public Map<Integer, ItemStack> getItems(World world) {
if (this.itemCache == null) { if (this.itemCache == null) {
var handler = this.getItemHandler(world); IItemHandler handler = this.getItemHandler(world);
if (handler != null) { if (handler != null) {
for (var i = 0; i < handler.getSlots(); i++) { for (int i = 0; i < handler.getSlots(); i++) {
var stack = handler.getStackInSlot(i); ItemStack stack = handler.getStackInSlot(i);
// check if the slot is accessible to us // check if the slot is accessible to us
if (stack.isEmpty()) if (stack.isEmpty())
continue; continue;
@ -68,40 +68,40 @@ public class NetworkLocation implements INBTSerializable<CompoundTag> {
return this.itemCache; return this.itemCache;
} }
public boolean canExtract(Level world, int slot) { public boolean canExtract(World world, int slot) {
var handler = this.getItemHandler(world); IItemHandler handler = this.getItemHandler(world);
return handler != null && !handler.extractItem(slot, 1, true).isEmpty(); return handler != null && !handler.extractItem(slot, 1, true).isEmpty();
} }
public IItemHandler getItemHandler(Level world) { public IItemHandler getItemHandler(World world) {
if (this.handlerCache == null) { if (this.handlerCache == null) {
var network = PipeNetwork.get(world); PipeNetwork network = PipeNetwork.get(world);
var pipe = network.getPipe(this.pipePos); PipeTileEntity pipe = network.getPipe(this.pipePos);
this.handlerCache = pipe.getItemHandler(this.direction); this.handlerCache = pipe.getItemHandler(this.direction);
} }
return this.handlerCache; return this.handlerCache;
} }
public boolean isEmpty(Level world) { public boolean isEmpty(World world) {
var items = this.getItems(world); Map<Integer, ItemStack> items = this.getItems(world);
return items == null || items.isEmpty(); return items == null || items.isEmpty();
} }
public BlockPos getPos() { public BlockPos getPos() {
return this.pipePos.relative(this.direction); return this.pipePos.offset(this.direction);
} }
@Override @Override
public CompoundTag serializeNBT() { public CompoundTag serializeNBT() {
var nbt = new CompoundTag(); CompoundTag nbt = new CompoundTag();
nbt.put("pipe_pos", NbtUtils.writeBlockPos(this.pipePos)); nbt.put("pipe_pos", NBTUtil.writeBlockPos(this.pipePos));
nbt.putInt("direction", this.direction.ordinal()); nbt.putInt("direction", this.direction.getIndex());
return nbt; return nbt;
} }
@Override @Override
public void deserializeNBT(CompoundTag nbt) { public void deserializeNBT(CompoundTag nbt) {
this.pipePos = NbtUtils.readBlockPos(nbt.getCompound("pipe_pos")); this.pipePos = NBTUtil.readBlockPos(nbt.getCompound("pipe_pos"));
this.direction = Direction.values()[(nbt.getInt("direction"))]; this.direction = Direction.byIndex(nbt.getInt("direction"));
} }
} }

View file

@ -1,7 +1,8 @@
package de.ellpeck.prettypipes.network; package de.ellpeck.prettypipes.network;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;
import net.minecraftforge.common.util.INBTSerializable; import net.minecraftforge.common.util.INBTSerializable;
import java.util.Objects; import java.util.Objects;
@ -26,24 +27,26 @@ public class NetworkLock implements INBTSerializable<CompoundTag> {
@Override @Override
public CompoundTag serializeNBT() { public CompoundTag serializeNBT() {
var nbt = new CompoundTag(); CompoundTag nbt = new CompoundTag();
nbt.putUUID("id", this.lockId); nbt.putUniqueId("id", this.lockId);
nbt.put("location", this.location.serializeNBT()); nbt.put("location", this.location.serializeNBT());
nbt.put("stack", this.stack.save(new CompoundTag())); nbt.put("stack", this.stack.write(new CompoundTag()));
return nbt; return nbt;
} }
@Override @Override
public void deserializeNBT(CompoundTag nbt) { public void deserializeNBT(CompoundTag nbt) {
this.lockId = nbt.getUUID("id"); this.lockId = nbt.getUniqueId("id");
this.location = new NetworkLocation(nbt.getCompound("location")); this.location = new NetworkLocation(nbt.getCompound("location"));
this.stack = ItemStack.of(nbt.getCompound("stack")); this.stack = ItemStack.read(nbt.getCompound("stack"));
} }
@Override @Override
public boolean equals(Object o) { public boolean equals(Object o) {
if (o instanceof NetworkLock that) if (o instanceof NetworkLock) {
NetworkLock that = (NetworkLock) o;
return this.lockId.equals(that.lockId); return this.lockId.equals(that.lockId);
}
return false; return false;
} }

View file

@ -1,29 +1,33 @@
package de.ellpeck.prettypipes.network; package de.ellpeck.prettypipes.network;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.matrix.MatrixStack;
import de.ellpeck.prettypipes.PrettyPipes; import de.ellpeck.prettypipes.PrettyPipes;
import de.ellpeck.prettypipes.Utility; import de.ellpeck.prettypipes.Utility;
import de.ellpeck.prettypipes.pipe.IPipeConnectable;
import de.ellpeck.prettypipes.pipe.IPipeItem; import de.ellpeck.prettypipes.pipe.IPipeItem;
import de.ellpeck.prettypipes.pipe.PipeBlockEntity; import de.ellpeck.prettypipes.pipe.PipeTileEntity;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.IRenderTypeBuffer;
import net.minecraft.client.renderer.block.model.ItemTransforms; import net.minecraft.client.renderer.model.ItemCameraTransforms;
import net.minecraft.core.BlockPos; import net.minecraft.entity.item.ItemEntity;
import net.minecraft.item.BlockItem;
import net.minecraft.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag; import net.minecraft.nbt.ListTag;
import net.minecraft.nbt.NbtUtils; import net.minecraft.nbt.NBTUtil;
import net.minecraft.nbt.Tag; import net.minecraft.util.Direction;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.Mth; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.util.math.MathHelper;
import net.minecraft.world.item.BlockItem; import net.minecraft.util.math.vector.Vector3d;
import net.minecraft.world.item.Item; import net.minecraft.world.World;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.common.util.Constants;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.ItemHandlerHelper; import net.minecraftforge.items.ItemHandlerHelper;
import org.jgrapht.Graph;
import org.jgrapht.GraphPath; import org.jgrapht.GraphPath;
import java.util.ArrayList; import java.util.ArrayList;
@ -84,35 +88,35 @@ public class PipeItem implements IPipeItem {
// initialize position if new // initialize position if new
if (this.x == 0 && this.y == 0 && this.z == 0) { if (this.x == 0 && this.y == 0 && this.z == 0) {
this.x = Mth.lerp(0.5F, startInventory.getX(), this.currGoalPos.getX()) + 0.5F; this.x = MathHelper.lerp(0.5F, startInventory.getX(), this.currGoalPos.getX()) + 0.5F;
this.y = Mth.lerp(0.5F, startInventory.getY(), this.currGoalPos.getY()) + 0.5F; this.y = MathHelper.lerp(0.5F, startInventory.getY(), this.currGoalPos.getY()) + 0.5F;
this.z = Mth.lerp(0.5F, startInventory.getZ(), this.currGoalPos.getZ()) + 0.5F; this.z = MathHelper.lerp(0.5F, startInventory.getZ(), this.currGoalPos.getZ()) + 0.5F;
} }
} }
@Override @Override
public void updateInPipe(PipeBlockEntity currPipe) { public void updateInPipe(PipeTileEntity currPipe) {
// this prevents pipes being updated after one another // this prevents pipes being updated after one another
// causing an item that just switched to tick twice // causing an item that just switched to tick twice
var worldTick = currPipe.getLevel().getGameTime(); long worldTick = currPipe.getWorld().getGameTime();
if (this.lastWorldTick == worldTick) if (this.lastWorldTick == worldTick)
return; return;
this.lastWorldTick = worldTick; this.lastWorldTick = worldTick;
var motionLeft = this.speed; float motionLeft = this.speed;
while (motionLeft > 0) { while (motionLeft > 0) {
var currSpeed = Math.min(0.25F, motionLeft); float currSpeed = Math.min(0.25F, motionLeft);
motionLeft -= currSpeed; motionLeft -= currSpeed;
var myPos = new BlockPos(this.x, this.y, this.z); BlockPos myPos = new BlockPos(this.x, this.y, this.z);
if (!myPos.equals(currPipe.getBlockPos()) && (currPipe.getBlockPos().equals(this.getDestPipe()) || !myPos.equals(this.startInventory))) { 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 // we're done with the current pipe, so switch to the next one
currPipe.getItems().remove(this); currPipe.getItems().remove(this);
var next = this.getNextTile(currPipe, true); PipeTileEntity next = this.getNextTile(currPipe, true);
if (next == null) { if (next == null) {
if (!currPipe.getLevel().isClientSide) { if (!currPipe.getWorld().isRemote) {
if (currPipe.getBlockPos().equals(this.getDestPipe())) { if (currPipe.getPos().equals(this.getDestPipe())) {
// ...or store in our destination container if we reached our destination // ..or store in our destination container if we reached our destination
this.stack = this.store(currPipe); this.stack = this.store(currPipe);
if (!this.stack.isEmpty()) if (!this.stack.isEmpty())
this.onPathObstructed(currPipe, true); this.onPathObstructed(currPipe, true);
@ -126,29 +130,29 @@ public class PipeItem implements IPipeItem {
currPipe = next; currPipe = next;
} }
} else { } else {
var dist = (this.currGoalPos).distSqr(this.x - 0.5F, this.y - 0.5F, this.z - 0.5F, false); double dist = Vector3d.copy(this.currGoalPos).squareDistanceTo(this.x - 0.5F, this.y - 0.5F, this.z - 0.5F);
if (dist < currSpeed * currSpeed) { if (dist < currSpeed * currSpeed) {
// we're past the start of the pipe, so move to the center of the next pipe // we're past the start of the pipe, so move to the center of the next pipe
BlockPos nextPos; BlockPos nextPos;
var next = this.getNextTile(currPipe, false); PipeTileEntity next = this.getNextTile(currPipe, false);
if (next == null || next == currPipe) { if (next == null || next == currPipe) {
if (currPipe.getBlockPos().equals(this.getDestPipe())) { if (currPipe.getPos().equals(this.getDestPipe())) {
nextPos = this.destInventory; nextPos = this.destInventory;
} else { } else {
currPipe.getItems().remove(this); currPipe.getItems().remove(this);
if (!currPipe.getLevel().isClientSide) if (!currPipe.getWorld().isRemote)
this.onPathObstructed(currPipe, false); this.onPathObstructed(currPipe, false);
return; return;
} }
} else { } else {
nextPos = next.getBlockPos(); nextPos = next.getPos();
} }
var tolerance = 0.001F; float tolerance = 0.001F;
if (dist >= tolerance * tolerance) { if (dist >= tolerance * tolerance) {
// when going around corners, we want to move right up to the corner // when going around corners, we want to move right up to the corner
var motion = new Vec3(this.x - this.lastX, this.y - this.lastY, this.z - this.lastZ); Vector3d motion = new Vector3d(this.x - this.lastX, this.y - this.lastY, this.z - this.lastZ);
var diff = new Vec3(nextPos.getX() + 0.5F - this.x, nextPos.getY() + 0.5F - this.y, nextPos.getZ() + 0.5F - this.z); Vector3d diff = new Vector3d(nextPos.getX() + 0.5F - this.x, nextPos.getY() + 0.5F - this.y, nextPos.getZ() + 0.5F - this.z);
if (motion.cross(diff).length() >= tolerance) { if (motion.crossProduct(diff).length() >= tolerance) {
currSpeed = (float) Math.sqrt(dist); currSpeed = (float) Math.sqrt(dist);
} else { } else {
// we're not going around a corner, so continue // we're not going around a corner, so continue
@ -165,7 +169,7 @@ public class PipeItem implements IPipeItem {
this.lastY = this.y; this.lastY = this.y;
this.lastZ = this.z; this.lastZ = this.z;
var dist = new Vec3(this.currGoalPos.getX() + 0.5F - this.x, this.currGoalPos.getY() + 0.5F - this.y, this.currGoalPos.getZ() + 0.5F - this.z); Vector3d dist = new Vector3d(this.currGoalPos.getX() + 0.5F - this.x, this.currGoalPos.getY() + 0.5F - this.y, this.currGoalPos.getZ() + 0.5F - this.z);
dist = dist.normalize(); dist = dist.normalize();
this.x += dist.x * currSpeed; this.x += dist.x * currSpeed;
this.y += dist.y * currSpeed; this.y += dist.y * currSpeed;
@ -173,50 +177,50 @@ public class PipeItem implements IPipeItem {
} }
} }
protected void onPathObstructed(PipeBlockEntity currPipe, boolean tryReturn) { protected void onPathObstructed(PipeTileEntity currPipe, boolean tryReturn) {
if (currPipe.getLevel().isClientSide) if (currPipe.getWorld().isRemote)
return; return;
var network = PipeNetwork.get(currPipe.getLevel()); PipeNetwork network = PipeNetwork.get(currPipe.getWorld());
if (tryReturn) { if (tryReturn) {
// first time: we try to return to our input chest // first time: we try to return to our input chest
if (!this.retryOnObstruction && network.routeItemToLocation(currPipe.getBlockPos(), this.destInventory, this.getStartPipe(), this.startInventory, this.stack, speed -> this)) { if (!this.retryOnObstruction && network.routeItemToLocation(currPipe.getPos(), this.destInventory, this.getStartPipe(), this.startInventory, this.stack, speed -> this)) {
this.retryOnObstruction = true; this.retryOnObstruction = true;
return; return;
} }
// second time: we arrived at our input chest, it is full, so we try to find a different goal location // second time: we arrived at our input chest, it is full, so we try to find a different goal location
var remain = network.routeItem(currPipe.getBlockPos(), this.destInventory, this.stack, (stack, speed) -> this, false); ItemStack remain = network.routeItem(currPipe.getPos(), this.destInventory, this.stack, (stack, speed) -> this, false);
if (!remain.isEmpty()) if (!remain.isEmpty())
this.drop(currPipe.getLevel(), remain.copy()); this.drop(currPipe.getWorld(), remain.copy());
} else { } else {
// if all re-routing attempts fail, we drop // if all re-routing attempts fail, we drop
this.drop(currPipe.getLevel(), this.stack); this.drop(currPipe.getWorld(), this.stack);
} }
} }
@Override @Override
public void drop(Level world, ItemStack stack) { public void drop(World world, ItemStack stack) {
var item = new ItemEntity(world, this.x, this.y, this.z, stack.copy()); ItemEntity item = new ItemEntity(world, this.x, this.y, this.z, stack.copy());
item.level.addFreshEntity(item); item.world.addEntity(item);
} }
protected ItemStack store(PipeBlockEntity currPipe) { protected ItemStack store(PipeTileEntity currPipe) {
var dir = Utility.getDirectionFromOffset(this.destInventory, this.getDestPipe()); Direction dir = Utility.getDirectionFromOffset(this.destInventory, this.getDestPipe());
var connectable = currPipe.getPipeConnectable(dir); IPipeConnectable connectable = currPipe.getPipeConnectable(dir);
if (connectable != null) if (connectable != null)
return connectable.insertItem(currPipe.getBlockPos(), dir, this.stack, false); return connectable.insertItem(currPipe.getPos(), dir, this.stack, false);
var handler = currPipe.getItemHandler(dir); IItemHandler handler = currPipe.getItemHandler(dir);
if (handler != null) if (handler != null)
return ItemHandlerHelper.insertItemStacked(handler, this.stack, false); return ItemHandlerHelper.insertItemStacked(handler, this.stack, false);
return this.stack; return this.stack;
} }
protected PipeBlockEntity getNextTile(PipeBlockEntity currPipe, boolean progress) { protected PipeTileEntity getNextTile(PipeTileEntity currPipe, boolean progress) {
if (this.path.size() <= this.currentTile + 1) if (this.path.size() <= this.currentTile + 1)
return null; return null;
var pos = this.path.get(this.currentTile + 1); BlockPos pos = this.path.get(this.currentTile + 1);
if (progress) if (progress)
this.currentTile++; this.currentTile++;
var network = PipeNetwork.get(currPipe.getLevel()); PipeNetwork network = PipeNetwork.get(currPipe.getWorld());
return network.getPipe(pos); return network.getPipe(pos);
} }
@ -241,41 +245,41 @@ public class PipeItem implements IPipeItem {
@Override @Override
public CompoundTag serializeNBT() { public CompoundTag serializeNBT() {
var nbt = new CompoundTag(); CompoundTag nbt = new CompoundTag();
nbt.putString("type", this.type.toString()); nbt.putString("type", this.type.toString());
nbt.put("stack", this.stack.serializeNBT()); nbt.put("stack", this.stack.serializeNBT());
nbt.putFloat("speed", this.speed); nbt.putFloat("speed", this.speed);
nbt.put("start_inv", NbtUtils.writeBlockPos(this.startInventory)); nbt.put("start_inv", NBTUtil.writeBlockPos(this.startInventory));
nbt.put("dest_inv", NbtUtils.writeBlockPos(this.destInventory)); nbt.put("dest_inv", NBTUtil.writeBlockPos(this.destInventory));
nbt.put("curr_goal", NbtUtils.writeBlockPos(this.currGoalPos)); nbt.put("curr_goal", NBTUtil.writeBlockPos(this.currGoalPos));
nbt.putBoolean("drop_on_obstruction", this.retryOnObstruction); nbt.putBoolean("drop_on_obstruction", this.retryOnObstruction);
nbt.putInt("tile", this.currentTile); nbt.putInt("tile", this.currentTile);
nbt.putFloat("x", this.x); nbt.putFloat("x", this.x);
nbt.putFloat("y", this.y); nbt.putFloat("y", this.y);
nbt.putFloat("z", this.z); nbt.putFloat("z", this.z);
var list = new ListTag(); ListTag list = new ListTag();
for (var pos : this.path) for (BlockPos pos : this.path)
list.add(NbtUtils.writeBlockPos(pos)); list.add(NBTUtil.writeBlockPos(pos));
nbt.put("path", list); nbt.put("path", list);
return nbt; return nbt;
} }
@Override @Override
public void deserializeNBT(CompoundTag nbt) { public void deserializeNBT(CompoundTag nbt) {
this.stack = ItemStack.of(nbt.getCompound("stack")); this.stack = ItemStack.read(nbt.getCompound("stack"));
this.speed = nbt.getFloat("speed"); this.speed = nbt.getFloat("speed");
this.startInventory = NbtUtils.readBlockPos(nbt.getCompound("start_inv")); this.startInventory = NBTUtil.readBlockPos(nbt.getCompound("start_inv"));
this.destInventory = NbtUtils.readBlockPos(nbt.getCompound("dest_inv")); this.destInventory = NBTUtil.readBlockPos(nbt.getCompound("dest_inv"));
this.currGoalPos = NbtUtils.readBlockPos(nbt.getCompound("curr_goal")); this.currGoalPos = NBTUtil.readBlockPos(nbt.getCompound("curr_goal"));
this.retryOnObstruction = nbt.getBoolean("drop_on_obstruction"); this.retryOnObstruction = nbt.getBoolean("drop_on_obstruction");
this.currentTile = nbt.getInt("tile"); this.currentTile = nbt.getInt("tile");
this.x = nbt.getFloat("x"); this.x = nbt.getFloat("x");
this.y = nbt.getFloat("y"); this.y = nbt.getFloat("y");
this.z = nbt.getFloat("z"); this.z = nbt.getFloat("z");
this.path.clear(); this.path.clear();
var list = nbt.getList("path", Tag.TAG_COMPOUND); ListTag list = nbt.getList("path", Constants.NBT.TAG_COMPOUND);
for (var i = 0; i < list.size(); i++) for (int i = 0; i < list.size(); i++)
this.path.add(NbtUtils.readBlockPos(list.getCompound(i))); this.path.add(NBTUtil.readBlockPos(list.getCompound(i)));
} }
@Override @Override
@ -285,40 +289,40 @@ public class PipeItem implements IPipeItem {
@Override @Override
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
public void render(PipeBlockEntity tile, PoseStack matrixStack, Random random, float partialTicks, int light, int overlay, MultiBufferSource source) { public void render(PipeTileEntity tile, MatrixStack matrixStack, Random random, float partialTicks, int light, int overlay, IRenderTypeBuffer buffer) {
matrixStack.translate( matrixStack.translate(
Mth.lerp(partialTicks, this.lastX, this.x), MathHelper.lerp(partialTicks, this.lastX, this.x),
Mth.lerp(partialTicks, this.lastY, this.y), MathHelper.lerp(partialTicks, this.lastY, this.y),
Mth.lerp(partialTicks, this.lastZ, this.z)); MathHelper.lerp(partialTicks, this.lastZ, this.z));
if (this.stack.getItem() instanceof BlockItem) { if (this.stack.getItem() instanceof BlockItem) {
var scale = 0.7F; float scale = 0.7F;
matrixStack.scale(scale, scale, scale); matrixStack.scale(scale, scale, scale);
matrixStack.translate(0, -0.2F, 0); matrixStack.translate(0, -0.2F, 0);
} else { } else {
var scale = 0.45F; float scale = 0.45F;
matrixStack.scale(scale, scale, scale); matrixStack.scale(scale, scale, scale);
matrixStack.translate(0, -0.1F, 0); matrixStack.translate(0, -0.1F, 0);
} }
random.setSeed(Item.getId(this.stack.getItem()) + this.stack.getDamageValue()); random.setSeed(Item.getIdFromItem(this.stack.getItem()) + this.stack.getDamage());
var amount = this.getModelCount(); int amount = this.getModelCount();
for (var i = 0; i < amount; i++) { for (int i = 0; i < amount; i++) {
matrixStack.pushPose(); matrixStack.push();
if (amount > 1) { if (amount > 1) {
matrixStack.translate( 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, (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().renderStatic(this.stack, ItemTransforms.TransformType.GROUND, light, overlay, matrixStack, source, 0); Minecraft.getInstance().getItemRenderer().renderItem(this.stack, ItemCameraTransforms.TransformType.GROUND, light, overlay, matrixStack, buffer);
matrixStack.popPose(); matrixStack.pop();
} }
} }
protected int getModelCount() { protected int getModelCount() {
var i = 1; int i = 1;
if (this.stack.getCount() > 48) { if (this.stack.getCount() > 48) {
i = 5; i = 5;
} else if (this.stack.getCount() > 32) { } else if (this.stack.getCount() > 32) {
@ -332,32 +336,32 @@ public class PipeItem implements IPipeItem {
} }
protected static List<BlockPos> compilePath(GraphPath<BlockPos, NetworkEdge> path) { protected static List<BlockPos> compilePath(GraphPath<BlockPos, NetworkEdge> path) {
var graph = path.getGraph(); Graph<BlockPos, NetworkEdge> graph = path.getGraph();
List<BlockPos> ret = new ArrayList<>(); List<BlockPos> ret = new ArrayList<>();
var nodes = path.getVertexList(); List<BlockPos> nodes = path.getVertexList();
if (nodes.size() == 1) { if (nodes.size() == 1) {
// add the single pipe twice if there's only one // add the single pipe twice if there's only one
// this is a dirty hack, but it works fine so eh // this is a dirty hack but it works fine so eh
for (var i = 0; i < 2; i++) for (int i = 0; i < 2; i++)
ret.add(nodes.get(0)); ret.add(nodes.get(0));
return ret; return ret;
} }
for (var i = 0; i < nodes.size() - 1; i++) { for (int i = 0; i < nodes.size() - 1; i++) {
var first = nodes.get(i); BlockPos first = nodes.get(i);
var second = nodes.get(i + 1); BlockPos second = nodes.get(i + 1);
var edge = graph.getEdge(first, second); NetworkEdge edge = graph.getEdge(first, second);
var add = (Consumer<Integer>) j -> { Consumer<Integer> add = j -> {
var pos = edge.pipes.get(j); BlockPos pos = edge.pipes.get(j);
if (!ret.contains(pos)) if (!ret.contains(pos))
ret.add(pos); ret.add(pos);
}; };
// if the edge is the other way around, we need to loop through tiles // if the edge is the other way around, we need to loop through tiles
// the other way also // the other way also
if (!graph.getEdgeSource(edge).equals(first)) { if (!graph.getEdgeSource(edge).equals(first)) {
for (var j = edge.pipes.size() - 1; j >= 0; j--) for (int j = edge.pipes.size() - 1; j >= 0; j--)
add.accept(j); add.accept(j);
} else { } else {
for (var j = 0; j < edge.pipes.size(); j++) for (int j = 0; j < edge.pipes.size(); j++)
add.accept(j); add.accept(j);
} }
} }

View file

@ -11,21 +11,29 @@ import de.ellpeck.prettypipes.packets.PacketHandler;
import de.ellpeck.prettypipes.packets.PacketItemEnterPipe; import de.ellpeck.prettypipes.packets.PacketItemEnterPipe;
import de.ellpeck.prettypipes.pipe.IPipeItem; import de.ellpeck.prettypipes.pipe.IPipeItem;
import de.ellpeck.prettypipes.pipe.PipeBlock; import de.ellpeck.prettypipes.pipe.PipeBlock;
import de.ellpeck.prettypipes.pipe.PipeBlockEntity; import de.ellpeck.prettypipes.pipe.PipeTileEntity;
import net.minecraft.block.BlockState;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
import net.minecraft.nbt.*;
import net.minecraft.world.item.ItemStack;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag; import net.minecraft.nbt.ListTag;
import net.minecraft.nbt.NbtUtils; import net.minecraft.nbt.NBTUtil;
import net.minecraft.nbt.Tag; import net.minecraft.util.Direction;
import net.minecraft.world.item.ItemStack; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.capabilities.ICapabilitySerializable; import net.minecraftforge.common.capabilities.ICapabilitySerializable;
import net.minecraftforge.common.util.Constants.NBT;
import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.items.IItemHandler;
import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.lang3.tuple.Pair;
import org.jgrapht.GraphPath;
import org.jgrapht.ListenableGraph; import org.jgrapht.ListenableGraph;
import org.jgrapht.alg.interfaces.ShortestPathAlgorithm;
import org.jgrapht.alg.shortestpath.DijkstraShortestPath; import org.jgrapht.alg.shortestpath.DijkstraShortestPath;
import org.jgrapht.event.GraphEdgeChangeEvent; import org.jgrapht.event.GraphEdgeChangeEvent;
import org.jgrapht.event.GraphListener; import org.jgrapht.event.GraphListener;
@ -48,7 +56,7 @@ public class PipeNetwork implements ICapabilitySerializable<CompoundTag>, GraphL
public final ListenableGraph<BlockPos, NetworkEdge> graph; public final ListenableGraph<BlockPos, NetworkEdge> graph;
private final DijkstraShortestPath<BlockPos, NetworkEdge> dijkstra; private final DijkstraShortestPath<BlockPos, NetworkEdge> dijkstra;
private final Map<BlockPos, List<BlockPos>> nodeToConnectedNodes = new HashMap<>(); private final Map<BlockPos, List<BlockPos>> nodeToConnectedNodes = new HashMap<>();
private final Map<BlockPos, PipeBlockEntity> tileCache = new HashMap<>(); private final Map<BlockPos, PipeTileEntity> tileCache = new HashMap<>();
private final ListMultimap<BlockPos, IPipeItem> pipeItems = ArrayListMultimap.create(); private final ListMultimap<BlockPos, IPipeItem> pipeItems = ArrayListMultimap.create();
private final ListMultimap<BlockPos, NetworkLock> networkLocks = ArrayListMultimap.create(); private final ListMultimap<BlockPos, NetworkLock> networkLocks = ArrayListMultimap.create();
private final Level world; private final Level world;
@ -69,13 +77,13 @@ public class PipeNetwork implements ICapabilitySerializable<CompoundTag>, GraphL
@Override @Override
public CompoundTag serializeNBT() { public CompoundTag serializeNBT() {
var nbt = new CompoundTag(); CompoundTag nbt = new CompoundTag();
var nodes = new ListTag(); ListTag nodes = new ListTag();
for (var node : this.graph.vertexSet()) for (BlockPos node : this.graph.vertexSet())
nodes.add(NbtUtils.writeBlockPos(node)); nodes.add(NbtUtils.writeBlockPos(node));
nbt.put("nodes", nodes); nbt.put("nodes", nodes);
var edges = new ListTag(); ListTag edges = new ListTag();
for (var edge : this.graph.edgeSet()) for (NetworkEdge edge : this.graph.edgeSet())
edges.add(edge.serializeNBT()); edges.add(edge.serializeNBT());
nbt.put("edges", edges); nbt.put("edges", edges);
nbt.put("items", Utility.serializeAll(this.pipeItems.values())); nbt.put("items", Utility.serializeAll(this.pipeItems.values()));
@ -89,15 +97,15 @@ public class PipeNetwork implements ICapabilitySerializable<CompoundTag>, GraphL
this.pipeItems.clear(); this.pipeItems.clear();
this.networkLocks.clear(); this.networkLocks.clear();
var nodes = nbt.getList("nodes", Tag.TAG_COMPOUND); ListTag nodes = nbt.getList("nodes", Tag.TAG_COMPOUND);
for (var i = 0; i < nodes.size(); i++) for (int i = 0; i < nodes.size(); i++)
this.graph.addVertex(NbtUtils.readBlockPos(nodes.getCompound(i))); this.graph.addVertex(NBTUtil.readBlockPos(nodes.getCompound(i)));
var edges = nbt.getList("edges", Tag.TAG_COMPOUND); ListTag edges = nbt.getList("edges", Tag.TAG_COMPOUND);
for (var i = 0; i < edges.size(); i++) for (int i = 0; i < edges.size(); i++)
this.addEdge(new NetworkEdge(edges.getCompound(i))); this.addEdge(new NetworkEdge(edges.getCompound(i)));
for (var item : Utility.deserializeAll(nbt.getList("items", Tag.TAG_COMPOUND), IPipeItem::load)) for (IPipeItem item : Utility.deserializeAll(nbt.getList("items", NBT.TAG_COMPOUND), IPipeItem::load))
this.pipeItems.put(item.getCurrentPipe(), item); this.pipeItems.put(item.getCurrentPipe(), item);
for (var lock : Utility.deserializeAll(nbt.getList("locks", Tag.TAG_COMPOUND), NetworkLock::new)) for (NetworkLock lock : Utility.deserializeAll(nbt.getList("locks", NBT.TAG_COMPOUND), NetworkLock::new))
this.createNetworkLock(lock); this.createNetworkLock(lock);
} }
@ -118,12 +126,12 @@ public class PipeNetwork implements ICapabilitySerializable<CompoundTag>, GraphL
} }
public void onPipeChanged(BlockPos pos, BlockState state) { public void onPipeChanged(BlockPos pos, BlockState state) {
var neighbors = this.createAllEdges(pos, state, true); List<NetworkEdge> neighbors = this.createAllEdges(pos, state, true);
// if we only have one neighbor, then there can't be any new connections // if we only have one neighbor, then there can't be any new connections
if (neighbors.size() <= 1 && !this.isNode(pos)) if (neighbors.size() <= 1 && !this.isNode(pos))
return; return;
for (var edge : neighbors) { for (NetworkEdge edge : neighbors) {
var end = edge.getEndPipe(); BlockPos end = edge.getEndPipe();
this.refreshNode(end, this.world.getBlockState(end)); this.refreshNode(end, this.world.getBlockState(end));
} }
} }
@ -135,24 +143,24 @@ public class PipeNetwork implements ICapabilitySerializable<CompoundTag>, GraphL
public ItemStack routeItem(BlockPos startPipePos, BlockPos startInventory, ItemStack stack, BiFunction<ItemStack, Float, IPipeItem> itemSupplier, boolean preventOversending) { public ItemStack routeItem(BlockPos startPipePos, BlockPos startInventory, ItemStack stack, BiFunction<ItemStack, Float, IPipeItem> itemSupplier, boolean preventOversending) {
if (!this.isNode(startPipePos)) if (!this.isNode(startPipePos))
return stack; return stack;
if (!this.world.isLoaded(startPipePos)) if (!this.world.isBlockLoaded(startPipePos))
return stack; return stack;
var startPipe = this.getPipe(startPipePos); PipeTileEntity startPipe = this.getPipe(startPipePos);
if (startPipe == null) if (startPipe == null)
return stack; return stack;
this.startProfile("find_destination"); this.startProfile("find_destination");
var nodes = this.getOrderedNetworkNodes(startPipePos); List<BlockPos> nodes = this.getOrderedNetworkNodes(startPipePos);
for (var i = 0; i < nodes.size(); i++) { for (int i = 0; i < nodes.size(); i++) {
var pipePos = nodes.get(startPipe.getNextNode(nodes, i)); BlockPos pipePos = nodes.get(startPipe.getNextNode(nodes, i));
if (!this.world.isLoaded(pipePos)) if (!this.world.isBlockLoaded(pipePos))
continue; continue;
var pipe = this.getPipe(pipePos); PipeTileEntity pipe = this.getPipe(pipePos);
var dest = pipe.getAvailableDestination(stack, false, preventOversending); Pair<BlockPos, ItemStack> dest = pipe.getAvailableDestination(stack, false, preventOversending);
if (dest == null || dest.getLeft().equals(startInventory)) if (dest == null || dest.getLeft().equals(startInventory))
continue; continue;
var sup = (Function<Float, IPipeItem>) speed -> itemSupplier.apply(dest.getRight(), speed); Function<Float, IPipeItem> sup = speed -> itemSupplier.apply(dest.getRight(), speed);
if (this.routeItemToLocation(startPipePos, startInventory, pipe.getBlockPos(), dest.getLeft(), dest.getRight(), sup)) { if (this.routeItemToLocation(startPipePos, startInventory, pipe.getPos(), dest.getLeft(), dest.getRight(), sup)) {
var remain = stack.copy(); ItemStack remain = stack.copy();
remain.shrink(dest.getRight().getCount()); remain.shrink(dest.getRight().getCount());
this.endProfile(); this.endProfile();
return remain; return remain;
@ -165,17 +173,17 @@ public class PipeNetwork implements ICapabilitySerializable<CompoundTag>, GraphL
public boolean routeItemToLocation(BlockPos startPipePos, BlockPos startInventory, BlockPos destPipePos, BlockPos destInventory, ItemStack stack, Function<Float, IPipeItem> 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)) if (!this.isNode(startPipePos) || !this.isNode(destPipePos))
return false; return false;
if (!this.world.isLoaded(startPipePos) || !this.world.isLoaded(destPipePos)) if (!this.world.isBlockLoaded(startPipePos) || !this.world.isBlockLoaded(destPipePos))
return false; return false;
var startPipe = this.getPipe(startPipePos); PipeTileEntity startPipe = this.getPipe(startPipePos);
if (startPipe == null) if (startPipe == null)
return false; return false;
this.startProfile("get_path"); this.startProfile("get_path");
var path = this.dijkstra.getPath(startPipePos, destPipePos); GraphPath<BlockPos, NetworkEdge> path = this.dijkstra.getPath(startPipePos, destPipePos);
this.endProfile(); this.endProfile();
if (path == null) if (path == null)
return false; return false;
var item = itemSupplier.apply(startPipe.getItemSpeed(stack)); IPipeItem item = itemSupplier.apply(startPipe.getItemSpeed(stack));
item.setDestination(startInventory, destInventory, path); item.setDestination(startInventory, destInventory, path);
startPipe.addNewItem(item); startPipe.addNewItem(item);
PacketHandler.sendToAllLoaded(this.world, startPipePos, new PacketItemEnterPipe(startPipePos, item)); PacketHandler.sendToAllLoaded(this.world, startPipePos, new PacketItemEnterPipe(startPipePos, item));
@ -183,9 +191,9 @@ public class PipeNetwork implements ICapabilitySerializable<CompoundTag>, GraphL
} }
public ItemStack requestItem(BlockPos destPipe, BlockPos destInventory, ItemStack stack, ItemEquality... equalityTypes) { public ItemStack requestItem(BlockPos destPipe, BlockPos destInventory, ItemStack stack, ItemEquality... equalityTypes) {
var remain = stack.copy(); ItemStack remain = stack.copy();
// check existing items // check existing items
for (var location : this.getOrderedNetworkItems(destPipe)) { for (NetworkLocation location : this.getOrderedNetworkItems(destPipe)) {
remain = this.requestExistingItem(location, destPipe, destInventory, null, remain, equalityTypes); remain = this.requestExistingItem(location, destPipe, destInventory, null, remain, equalityTypes);
if (remain.isEmpty()) if (remain.isEmpty())
return remain; return remain;
@ -195,10 +203,10 @@ public class PipeNetwork implements ICapabilitySerializable<CompoundTag>, GraphL
} }
public ItemStack requestCraftedItem(BlockPos destPipe, Consumer<ItemStack> unavailableConsumer, ItemStack stack, Stack<ItemStack> dependencyChain, ItemEquality... equalityTypes) { public ItemStack requestCraftedItem(BlockPos destPipe, Consumer<ItemStack> unavailableConsumer, ItemStack stack, Stack<ItemStack> dependencyChain, ItemEquality... equalityTypes) {
for (var craftable : this.getAllCraftables(destPipe)) { for (Pair<BlockPos, ItemStack> craftable : this.getAllCraftables(destPipe)) {
if (!ItemEquality.compareItems(stack, craftable.getRight(), equalityTypes)) if (!ItemEquality.compareItems(stack, craftable.getRight(), equalityTypes))
continue; continue;
var pipe = this.getPipe(craftable.getLeft()); PipeTileEntity pipe = this.getPipe(craftable.getLeft());
if (pipe == null) if (pipe == null)
continue; continue;
stack = pipe.craft(destPipe, unavailableConsumer, stack, dependencyChain); stack = pipe.craft(destPipe, unavailableConsumer, stack, dependencyChain);
@ -216,21 +224,21 @@ public class PipeNetwork implements ICapabilitySerializable<CompoundTag>, GraphL
if (location.getPos().equals(destInventory)) if (location.getPos().equals(destInventory))
return stack; return stack;
// make sure we don't pull any locked items // make sure we don't pull any locked items
var amount = location.getItemAmount(this.world, stack, equalityTypes); int amount = location.getItemAmount(this.world, stack, equalityTypes);
if (amount <= 0) if (amount <= 0)
return stack; return stack;
amount -= this.getLockedAmount(location.getPos(), stack, ignoredLock, equalityTypes); amount -= this.getLockedAmount(location.getPos(), stack, ignoredLock, equalityTypes);
if (amount <= 0) if (amount <= 0)
return stack; return stack;
var remain = stack.copy(); ItemStack remain = stack.copy();
// make sure we only extract less than or equal to the requested amount // make sure we only extract less than or equal to the requested amount
if (remain.getCount() < amount) if (remain.getCount() < amount)
amount = remain.getCount(); amount = remain.getCount();
remain.shrink(amount); remain.shrink(amount);
for (int slot : location.getStackSlots(this.world, stack, equalityTypes)) { for (int slot : location.getStackSlots(this.world, stack, equalityTypes)) {
// try to extract from that location's inventory and send the item // try to extract from that location's inventory and send the item
var handler = location.getItemHandler(this.world); IItemHandler handler = location.getItemHandler(this.world);
var extracted = handler.extractItem(slot, amount, true); ItemStack extracted = handler.extractItem(slot, amount, true);
if (this.routeItemToLocation(location.pipePos, location.getPos(), destPipe, destInventory, extracted, speed -> itemSupplier.apply(extracted, speed))) { if (this.routeItemToLocation(location.pipePos, location.getPos(), destPipe, destInventory, extracted, speed -> itemSupplier.apply(extracted, speed))) {
handler.extractItem(slot, extracted.getCount(), false); handler.extractItem(slot, extracted.getCount(), false);
amount -= extracted.getCount(); amount -= extracted.getCount();
@ -241,10 +249,10 @@ public class PipeNetwork implements ICapabilitySerializable<CompoundTag>, GraphL
return remain; return remain;
} }
public PipeBlockEntity getPipe(BlockPos pos) { public PipeTileEntity getPipe(BlockPos pos) {
var tile = this.tileCache.get(pos); PipeTileEntity tile = this.tileCache.get(pos);
if (tile == null || tile.isRemoved()) { if (tile == null || tile.isRemoved()) {
tile = Utility.getBlockEntity(PipeBlockEntity.class, this.world, pos); tile = Utility.getBlockEntity(PipeTileEntity.class, this.world, pos);
this.tileCache.put(pos, tile); this.tileCache.put(pos, tile);
} }
return tile; return tile;
@ -257,14 +265,14 @@ public class PipeNetwork implements ICapabilitySerializable<CompoundTag>, GraphL
public List<Pair<BlockPos, ItemStack>> getCurrentlyCrafting(BlockPos node, ItemEquality... equalityTypes) { public List<Pair<BlockPos, ItemStack>> getCurrentlyCrafting(BlockPos node, ItemEquality... equalityTypes) {
this.startProfile("get_currently_crafting"); this.startProfile("get_currently_crafting");
List<Pair<BlockPos, ItemStack>> items = new ArrayList<>(); List<Pair<BlockPos, ItemStack>> items = new ArrayList<>();
var craftingPipes = this.getAllCraftables(node).stream().map(c -> this.getPipe(c.getLeft())).distinct().iterator(); Iterator<PipeTileEntity> craftingPipes = this.getAllCraftables(node).stream().map(c -> this.getPipe(c.getLeft())).distinct().iterator();
while (craftingPipes.hasNext()) { while (craftingPipes.hasNext()) {
var pipe = craftingPipes.next(); PipeTileEntity pipe = craftingPipes.next();
for (var request : pipe.craftResultRequests) { for (Pair<BlockPos, ItemStack> request : pipe.craftResultRequests) {
var dest = request.getLeft(); BlockPos dest = request.getLeft();
var stack = request.getRight(); ItemStack stack = request.getRight();
// add up all the items that should go to the same location // add up all the items that should go to the same location
var existing = items.stream() Optional<Pair<BlockPos, ItemStack>> existing = items.stream()
.filter(s -> s.getLeft().equals(dest) && ItemEquality.compareItems(s.getRight(), stack, equalityTypes)) .filter(s -> s.getLeft().equals(dest) && ItemEquality.compareItems(s.getRight(), stack, equalityTypes))
.findFirst(); .findFirst();
if (existing.isPresent()) { if (existing.isPresent()) {
@ -289,25 +297,25 @@ public class PipeNetwork implements ICapabilitySerializable<CompoundTag>, GraphL
return Collections.emptyList(); return Collections.emptyList();
this.startProfile("get_all_craftables"); this.startProfile("get_all_craftables");
List<Pair<BlockPos, ItemStack>> craftables = new ArrayList<>(); List<Pair<BlockPos, ItemStack>> craftables = new ArrayList<>();
for (var dest : this.getOrderedNetworkNodes(node)) { for (BlockPos dest : this.getOrderedNetworkNodes(node)) {
if (!this.world.isLoaded(dest)) if (!this.world.isBlockLoaded(dest))
continue; continue;
var pipe = this.getPipe(dest); PipeTileEntity pipe = this.getPipe(dest);
for (var stack : pipe.getAllCraftables()) for (ItemStack stack : pipe.getAllCraftables())
craftables.add(Pair.of(pipe.getBlockPos(), stack)); craftables.add(Pair.of(pipe.getPos(), stack));
} }
this.endProfile(); this.endProfile();
return craftables; return craftables;
} }
public int getCraftableAmount(BlockPos node, Consumer<ItemStack> unavailableConsumer, ItemStack stack, Stack<ItemStack> dependencyChain, ItemEquality... equalityTypes) { public int getCraftableAmount(BlockPos node, Consumer<ItemStack> unavailableConsumer, ItemStack stack, Stack<ItemStack> dependencyChain, ItemEquality... equalityTypes) {
var total = 0; int total = 0;
for (var pair : this.getAllCraftables(node)) { for (Pair<BlockPos, ItemStack> pair : this.getAllCraftables(node)) {
if (!ItemEquality.compareItems(pair.getRight(), stack, equalityTypes)) if (!ItemEquality.compareItems(pair.getRight(), stack, equalityTypes))
continue; continue;
if (!this.world.isLoaded(pair.getLeft())) if (!this.world.isBlockLoaded(pair.getLeft()))
continue; continue;
var pipe = this.getPipe(pair.getLeft()); PipeTileEntity pipe = this.getPipe(pair.getLeft());
if (pipe != null) if (pipe != null)
total += pipe.getCraftableAmount(unavailableConsumer, stack, dependencyChain); total += pipe.getCraftableAmount(unavailableConsumer, stack, dependencyChain);
} }
@ -319,20 +327,20 @@ public class PipeNetwork implements ICapabilitySerializable<CompoundTag>, GraphL
return Collections.emptyList(); return Collections.emptyList();
this.startProfile("get_network_items"); this.startProfile("get_network_items");
List<NetworkLocation> info = new ArrayList<>(); List<NetworkLocation> info = new ArrayList<>();
for (var dest : this.getOrderedNetworkNodes(node)) { for (BlockPos dest : this.getOrderedNetworkNodes(node)) {
if (!this.world.isLoaded(dest)) if (!this.world.isBlockLoaded(dest))
continue; continue;
var pipe = this.getPipe(dest); PipeTileEntity pipe = this.getPipe(dest);
if (!pipe.canNetworkSee()) if (!pipe.canNetworkSee())
continue; continue;
for (var dir : Direction.values()) { for (Direction dir : Direction.values()) {
var handler = pipe.getItemHandler(dir); IItemHandler handler = pipe.getItemHandler(dir);
if (handler == null) if (handler == null)
continue; continue;
// check if this handler already exists (double-connected pipes, double chests etc.) // check if this handler already exists (double-connected pipes, double chests etc.)
if (info.stream().anyMatch(l -> handler.equals(l.getItemHandler(this.world)))) if (info.stream().anyMatch(l -> handler.equals(l.getItemHandler(this.world))))
continue; continue;
var location = new NetworkLocation(dest, dir); NetworkLocation location = new NetworkLocation(dest, dir);
if (!location.isEmpty(this.world)) if (!location.isEmpty(this.world))
info.add(location); info.add(location);
} }
@ -362,7 +370,7 @@ public class PipeNetwork implements ICapabilitySerializable<CompoundTag>, GraphL
private void refreshNode(BlockPos pos, BlockState state) { private void refreshNode(BlockPos pos, BlockState state) {
this.startProfile("refresh_node"); this.startProfile("refresh_node");
this.graph.removeAllEdges(new ArrayList<>(this.graph.edgesOf(pos))); this.graph.removeAllEdges(new ArrayList<>(this.graph.edgesOf(pos)));
for (var edge : this.createAllEdges(pos, state, false)) for (NetworkEdge edge : this.createAllEdges(pos, state, false))
this.addEdge(edge); this.addEdge(edge);
this.endProfile(); this.endProfile();
} }
@ -376,11 +384,11 @@ public class PipeNetwork implements ICapabilitySerializable<CompoundTag>, GraphL
public BlockPos getNodeFromPipe(BlockPos pos) { public BlockPos getNodeFromPipe(BlockPos pos) {
if (this.isNode(pos)) if (this.isNode(pos))
return pos; return pos;
var state = this.world.getBlockState(pos); BlockState state = this.world.getBlockState(pos);
if (!(state.getBlock() instanceof PipeBlock)) if (!(state.getBlock() instanceof PipeBlock))
return null; return null;
for (var dir : Direction.values()) { for (Direction dir : Direction.values()) {
var edge = this.createEdge(pos, state, dir, false); NetworkEdge edge = this.createEdge(pos, state, dir, false);
if (edge != null) if (edge != null)
return edge.getEndPipe(); return edge.getEndPipe();
} }
@ -390,8 +398,8 @@ public class PipeNetwork implements ICapabilitySerializable<CompoundTag>, GraphL
private List<NetworkEdge> createAllEdges(BlockPos pos, BlockState state, boolean ignoreCurrBlocked) { private List<NetworkEdge> createAllEdges(BlockPos pos, BlockState state, boolean ignoreCurrBlocked) {
this.startProfile("create_all_edges"); this.startProfile("create_all_edges");
List<NetworkEdge> edges = new ArrayList<>(); List<NetworkEdge> edges = new ArrayList<>();
for (var dir : Direction.values()) { for (Direction dir : Direction.values()) {
var edge = this.createEdge(pos, state, dir, ignoreCurrBlocked); NetworkEdge edge = this.createEdge(pos, state, dir, ignoreCurrBlocked);
if (edge != null) if (edge != null)
edges.add(edge); edges.add(edge);
} }
@ -400,14 +408,14 @@ public class PipeNetwork implements ICapabilitySerializable<CompoundTag>, GraphL
} }
private NetworkEdge createEdge(BlockPos pos, BlockState state, Direction dir, boolean ignoreCurrBlocked) { private NetworkEdge createEdge(BlockPos pos, BlockState state, Direction dir, boolean ignoreCurrBlocked) {
if (!ignoreCurrBlocked && !state.getValue(PipeBlock.DIRECTIONS.get(dir)).isConnected()) if (!ignoreCurrBlocked && !state.get(PipeBlock.DIRECTIONS.get(dir)).isConnected())
return null; return null;
var currPos = pos.relative(dir); BlockPos currPos = pos.offset(dir);
var currState = this.world.getBlockState(currPos); BlockState currState = this.world.getBlockState(currPos);
if (!(currState.getBlock() instanceof PipeBlock)) if (!(currState.getBlock() instanceof PipeBlock))
return null; return null;
this.startProfile("create_edge"); this.startProfile("create_edge");
var edge = new NetworkEdge(); NetworkEdge edge = new NetworkEdge();
edge.pipes.add(pos); edge.pipes.add(pos);
edge.pipes.add(currPos); edge.pipes.add(currPos);
@ -419,12 +427,12 @@ public class PipeNetwork implements ICapabilitySerializable<CompoundTag>, GraphL
return edge; return edge;
} }
var found = false; boolean found = false;
for (var nextDir : Direction.values()) { for (Direction nextDir : Direction.values()) {
if (!currState.getValue(PipeBlock.DIRECTIONS.get(nextDir)).isConnected()) if (!currState.get(PipeBlock.DIRECTIONS.get(nextDir)).isConnected())
continue; continue;
var offset = currPos.relative(nextDir); BlockPos offset = currPos.offset(nextDir);
var offState = this.world.getBlockState(offset); BlockState offState = this.world.getBlockState(offset);
if (!(offState.getBlock() instanceof PipeBlock)) if (!(offState.getBlock() instanceof PipeBlock))
continue; continue;
if (edge.pipes.contains(offset)) if (edge.pipes.contains(offset))
@ -445,10 +453,10 @@ public class PipeNetwork implements ICapabilitySerializable<CompoundTag>, GraphL
public List<BlockPos> getOrderedNetworkNodes(BlockPos node) { public List<BlockPos> getOrderedNetworkNodes(BlockPos node) {
if (!this.isNode(node)) if (!this.isNode(node))
return Collections.emptyList(); return Collections.emptyList();
var ret = this.nodeToConnectedNodes.get(node); List<BlockPos> ret = this.nodeToConnectedNodes.get(node);
if (ret == null) { if (ret == null) {
this.startProfile("compile_connected_nodes"); this.startProfile("compile_connected_nodes");
var paths = this.dijkstra.getPaths(node); ShortestPathAlgorithm.SingleSourcePaths<BlockPos, NetworkEdge> paths = this.dijkstra.getPaths(node);
// sort destinations first by their priority (eg trash pipes should be last) // sort destinations first by their priority (eg trash pipes should be last)
// and then by their distance from the specified node // and then by their distance from the specified node
ret = Streams.stream(new BreadthFirstIterator<>(this.graph, node)) ret = Streams.stream(new BreadthFirstIterator<>(this.graph, node))
@ -464,7 +472,7 @@ public class PipeNetwork implements ICapabilitySerializable<CompoundTag>, GraphL
public void clearDestinationCache(BlockPos... nodes) { public void clearDestinationCache(BlockPos... nodes) {
this.startProfile("clear_node_cache"); this.startProfile("clear_node_cache");
// remove caches for the nodes // remove caches for the nodes
for (var node : nodes) for (BlockPos node : nodes)
this.nodeToConnectedNodes.keySet().remove(node); this.nodeToConnectedNodes.keySet().remove(node);
// remove caches that contain the nodes as a destination // remove caches that contain the nodes as a destination
this.nodeToConnectedNodes.values().removeIf(cached -> Arrays.stream(nodes).anyMatch(cached::contains)); this.nodeToConnectedNodes.values().removeIf(cached -> Arrays.stream(nodes).anyMatch(cached::contains));
@ -477,7 +485,7 @@ public class PipeNetwork implements ICapabilitySerializable<CompoundTag>, GraphL
public Stream<IPipeItem> getPipeItemsOnTheWay(BlockPos goalInv) { public Stream<IPipeItem> getPipeItemsOnTheWay(BlockPos goalInv) {
this.startProfile("get_pipe_items_on_the_way"); this.startProfile("get_pipe_items_on_the_way");
var 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(); this.endProfile();
return ret; return ret;
} }
@ -507,11 +515,11 @@ public class PipeNetwork implements ICapabilitySerializable<CompoundTag>, GraphL
} }
public void startProfile(String name) { public void startProfile(String name) {
this.world.getProfiler().push(() -> PrettyPipes.ID + ":pipe_network_" + name); this.world.getProfiler().startSection(() -> PrettyPipes.ID + ":pipe_network_" + name);
} }
public void endProfile() { public void endProfile() {
this.world.getProfiler().pop(); this.world.getProfiler().endSection();
} }
public static PipeNetwork get(Level world) { public static PipeNetwork get(Level world) {

View file

@ -2,25 +2,27 @@ package de.ellpeck.prettypipes.packets;
import de.ellpeck.prettypipes.Utility; import de.ellpeck.prettypipes.Utility;
import de.ellpeck.prettypipes.items.IModule; import de.ellpeck.prettypipes.items.IModule;
import de.ellpeck.prettypipes.misc.ItemFilter;
import de.ellpeck.prettypipes.misc.ItemFilter.IFilteredContainer; import de.ellpeck.prettypipes.misc.ItemFilter.IFilteredContainer;
import de.ellpeck.prettypipes.pipe.PipeBlockEntity; import de.ellpeck.prettypipes.pipe.PipeTileEntity;
import de.ellpeck.prettypipes.pipe.containers.AbstractPipeContainer; import de.ellpeck.prettypipes.pipe.containers.AbstractPipeContainer;
import de.ellpeck.prettypipes.pipe.modules.modifier.FilterModifierModuleContainer; import de.ellpeck.prettypipes.pipe.modules.modifier.FilterModifierModuleContainer;
import de.ellpeck.prettypipes.pipe.modules.modifier.FilterModifierModuleItem; import de.ellpeck.prettypipes.pipe.modules.modifier.FilterModifierModuleItem;
import de.ellpeck.prettypipes.pipe.modules.stacksize.StackSizeModuleItem; import de.ellpeck.prettypipes.pipe.modules.stacksize.StackSizeModuleItem;
import de.ellpeck.prettypipes.terminal.CraftingTerminalBlockEntity; import de.ellpeck.prettypipes.terminal.CraftingTerminalTileEntity;
import de.ellpeck.prettypipes.terminal.ItemTerminalBlockEntity; import de.ellpeck.prettypipes.terminal.ItemTerminalTileEntity;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.core.BlockPos; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.network.FriendlyByteBuf; import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.network.chat.Component; import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.server.level.ServerPlayer; import net.minecraft.inventory.container.Container;
import net.minecraft.world.MenuProvider; import net.minecraft.inventory.container.INamedContainerProvider;
import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.entity.player.Player; import net.minecraft.network.PacketBuffer;
import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.util.math.BlockPos;
import net.minecraftforge.network.NetworkEvent; import net.minecraft.util.text.ITextComponent;
import net.minecraftforge.network.NetworkHooks; import net.minecraftforge.fml.network.NetworkEvent;
import net.minecraftforge.fml.network.NetworkHooks;
import org.apache.logging.log4j.util.TriConsumer; import org.apache.logging.log4j.util.TriConsumer;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@ -42,15 +44,15 @@ public class PacketButton {
} }
public static PacketButton fromBytes(FriendlyByteBuf buf) { public static PacketButton fromBytes(PacketBuffer buf) {
var packet = new PacketButton(); PacketButton packet = new PacketButton();
packet.pos = buf.readBlockPos(); packet.pos = buf.readBlockPos();
packet.result = ButtonResult.values()[buf.readByte()]; packet.result = ButtonResult.values()[buf.readByte()];
packet.data = buf.readVarIntArray(); packet.data = buf.readVarIntArray();
return packet; return packet;
} }
public static void toBytes(PacketButton packet, FriendlyByteBuf buf) { public static void toBytes(PacketButton packet, PacketBuffer buf) {
buf.writeBlockPos(packet.pos); buf.writeBlockPos(packet.pos);
buf.writeByte(packet.result.ordinal()); buf.writeByte(packet.result.ordinal());
buf.writeVarIntArray(packet.data); buf.writeVarIntArray(packet.data);
@ -61,7 +63,7 @@ public class PacketButton {
ctx.get().enqueueWork(new Runnable() { ctx.get().enqueueWork(new Runnable() {
@Override @Override
public void run() { public void run() {
Player player = ctx.get().getSender(); PlayerEntity player = ctx.get().getSender();
message.result.action.accept(message.pos, message.data, player); message.result.action.accept(message.pos, message.data, player);
} }
}); });
@ -75,23 +77,22 @@ public class PacketButton {
public enum ButtonResult { public enum ButtonResult {
PIPE_TAB((pos, data, player) -> { PIPE_TAB((pos, data, player) -> {
var tile = Utility.getBlockEntity(PipeBlockEntity.class, player.level, pos); PipeTileEntity tile = Utility.getBlockEntity(PipeTileEntity.class, player.world, pos);
if (data[0] < 0) { if (data[0] < 0) {
NetworkHooks.openGui((ServerPlayer) player, tile, pos); NetworkHooks.openGui((ServerPlayerEntity) player, tile, pos);
} else { } else {
var stack = tile.modules.getStackInSlot(data[0]); ItemStack stack = tile.modules.getStackInSlot(data[0]);
NetworkHooks.openGui((ServerPlayer) player, new MenuProvider() { NetworkHooks.openGui((ServerPlayerEntity) player, new INamedContainerProvider() {
@Override @Override
public Component getDisplayName() { public ITextComponent getDisplayName() {
return stack.getDisplayName(); return stack.getDisplayName();
} }
@Nullable @Nullable
@Override @Override
public AbstractContainerMenu createMenu(int windowId, Inventory inv, Player player) { public Container createMenu(int windowId, PlayerInventory inv, PlayerEntity player) {
return ((IModule) stack.getItem()).getContainer(stack, tile, windowId, inv, player, data[0]); return ((IModule) stack.getItem()).getContainer(stack, tile, windowId, inv, player, data[0]);
} }
}, buf -> { }, buf -> {
buf.writeBlockPos(pos); buf.writeBlockPos(pos);
buf.writeInt(data[0]); buf.writeInt(data[0]);
@ -99,34 +100,34 @@ public class PacketButton {
} }
}), }),
FILTER_CHANGE((pos, data, player) -> { FILTER_CHANGE((pos, data, player) -> {
var container = (IFilteredContainer) player.containerMenu; IFilteredContainer container = (IFilteredContainer) player.openContainer;
var filter = container.getFilter(); ItemFilter filter = container.getFilter();
filter.onButtonPacket(data[0]); filter.onButtonPacket(data[0]);
}), }),
STACK_SIZE_MODULE_BUTTON((pos, data, player) -> { STACK_SIZE_MODULE_BUTTON((pos, data, player) -> {
var container = (AbstractPipeContainer<?>) player.containerMenu; AbstractPipeContainer<?> container = (AbstractPipeContainer<?>) player.openContainer;
StackSizeModuleItem.setLimitToMaxStackSize(container.moduleStack, !StackSizeModuleItem.getLimitToMaxStackSize(container.moduleStack)); StackSizeModuleItem.setLimitToMaxStackSize(container.moduleStack, !StackSizeModuleItem.getLimitToMaxStackSize(container.moduleStack));
}), }),
STACK_SIZE_AMOUNT((pos, data, player) -> { STACK_SIZE_AMOUNT((pos, data, player) -> {
var container = (AbstractPipeContainer<?>) player.containerMenu; AbstractPipeContainer<?> container = (AbstractPipeContainer<?>) player.openContainer;
StackSizeModuleItem.setMaxStackSize(container.moduleStack, data[0]); StackSizeModuleItem.setMaxStackSize(container.moduleStack, data[0]);
}), }),
CRAFT_TERMINAL_REQUEST((pos, data, player) -> { CRAFT_TERMINAL_REQUEST((pos, data, player) -> {
var tile = Utility.getBlockEntity(CraftingTerminalBlockEntity.class, player.level, pos); CraftingTerminalTileEntity tile = Utility.getBlockEntity(CraftingTerminalTileEntity.class, player.world, pos);
tile.requestCraftingItems(player, data[0]); tile.requestCraftingItems(player, data[0]);
}), }),
CANCEL_CRAFTING((pos, data, player) -> { CANCEL_CRAFTING((pos, data, player) -> {
var tile = Utility.getBlockEntity(ItemTerminalBlockEntity.class, player.level, pos); ItemTerminalTileEntity tile = Utility.getBlockEntity(ItemTerminalTileEntity.class, player.world, pos);
tile.cancelCrafting(); tile.cancelCrafting();
}), }),
TAG_FILTER((pos, data, player) -> { TAG_FILTER((pos, data, player) -> {
var container = (FilterModifierModuleContainer) player.containerMenu; FilterModifierModuleContainer container = (FilterModifierModuleContainer) player.openContainer;
FilterModifierModuleItem.setFilterTag(container.moduleStack, container.getTags().get(data[0])); FilterModifierModuleItem.setFilterTag(container.moduleStack, container.getTags().get(data[0]));
}); });
public final TriConsumer<BlockPos, int[], Player> action; public final TriConsumer<BlockPos, int[], PlayerEntity> action;
ButtonResult(TriConsumer<BlockPos, int[], Player> action) { ButtonResult(TriConsumer<BlockPos, int[], PlayerEntity> action) {
this.action = action; this.action = action;
} }
} }

View file

@ -1,12 +1,12 @@
package de.ellpeck.prettypipes.packets; package de.ellpeck.prettypipes.packets;
import de.ellpeck.prettypipes.pipe.modules.craft.CraftingModuleContainer; import de.ellpeck.prettypipes.pipe.modules.craft.CraftingModuleContainer;
import net.minecraft.network.FriendlyByteBuf; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.network.PacketBuffer;
import net.minecraftforge.fml.network.NetworkEvent;
import net.minecraftforge.items.ItemHandlerHelper; import net.minecraftforge.items.ItemHandlerHelper;
import net.minecraftforge.items.ItemStackHandler; import net.minecraftforge.items.ItemStackHandler;
import net.minecraftforge.network.NetworkEvent;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -26,24 +26,24 @@ public class PacketCraftingModuleTransfer {
} }
public static PacketCraftingModuleTransfer fromBytes(FriendlyByteBuf buf) { public static PacketCraftingModuleTransfer fromBytes(PacketBuffer buf) {
var packet = new PacketCraftingModuleTransfer(); PacketCraftingModuleTransfer packet = new PacketCraftingModuleTransfer();
packet.inputs = new ArrayList<>(); packet.inputs = new ArrayList<>();
for (var i = buf.readInt(); i > 0; i--) for (int i = buf.readInt(); i > 0; i--)
packet.inputs.add(buf.readItem()); packet.inputs.add(buf.readItemStack());
packet.outputs = new ArrayList<>(); packet.outputs = new ArrayList<>();
for (var i = buf.readInt(); i > 0; i--) for (int i = buf.readInt(); i > 0; i--)
packet.outputs.add(buf.readItem()); packet.outputs.add(buf.readItemStack());
return packet; return packet;
} }
public static void toBytes(PacketCraftingModuleTransfer packet, FriendlyByteBuf buf) { public static void toBytes(PacketCraftingModuleTransfer packet, PacketBuffer buf) {
buf.writeInt(packet.inputs.size()); buf.writeInt(packet.inputs.size());
for (var stack : packet.inputs) for (ItemStack stack : packet.inputs)
buf.writeItem(stack); buf.writeItemStack(stack);
buf.writeInt(packet.outputs.size()); buf.writeInt(packet.outputs.size());
for (var stack : packet.outputs) for (ItemStack stack : packet.outputs)
buf.writeItem(stack); buf.writeItemStack(stack);
} }
@SuppressWarnings("Convert2Lambda") @SuppressWarnings("Convert2Lambda")
@ -51,12 +51,13 @@ public class PacketCraftingModuleTransfer {
ctx.get().enqueueWork(new Runnable() { ctx.get().enqueueWork(new Runnable() {
@Override @Override
public void run() { public void run() {
Player player = ctx.get().getSender(); PlayerEntity player = ctx.get().getSender();
if (player.containerMenu instanceof CraftingModuleContainer container) { if (player.openContainer instanceof CraftingModuleContainer) {
CraftingModuleContainer container = (CraftingModuleContainer) player.openContainer;
copy(container.input, message.inputs); copy(container.input, message.inputs);
copy(container.output, message.outputs); copy(container.output, message.outputs);
container.modified = true; container.modified = true;
container.broadcastChanges(); container.detectAndSendChanges();
} }
} }
}); });
@ -64,9 +65,9 @@ public class PacketCraftingModuleTransfer {
} }
private static void copy(ItemStackHandler container, List<ItemStack> contents) { private static void copy(ItemStackHandler container, List<ItemStack> contents) {
for (var i = 0; i < container.getSlots(); i++) for (int i = 0; i < container.getSlots(); i++)
container.setStackInSlot(i, ItemStack.EMPTY); container.setStackInSlot(i, ItemStack.EMPTY);
for (var stack : contents) for (ItemStack stack : contents)
ItemHandlerHelper.insertItem(container, stack, false); ItemHandlerHelper.insertItem(container, stack, false);
} }
} }

View file

@ -3,13 +3,13 @@ package de.ellpeck.prettypipes.packets;
import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ListMultimap; import com.google.common.collect.ListMultimap;
import de.ellpeck.prettypipes.Utility; import de.ellpeck.prettypipes.Utility;
import de.ellpeck.prettypipes.terminal.CraftingTerminalBlockEntity; import de.ellpeck.prettypipes.terminal.CraftingTerminalTileEntity;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.core.BlockPos; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraftforge.network.NetworkEvent; import net.minecraft.network.PacketBuffer;
import net.minecraft.util.math.BlockPos;
import net.minecraftforge.fml.network.NetworkEvent;
import java.util.Map; import java.util.Map;
import java.util.function.Consumer; import java.util.function.Consumer;
@ -29,35 +29,35 @@ public class PacketGhostSlot {
} }
public static PacketGhostSlot fromBytes(FriendlyByteBuf buf) { public static PacketGhostSlot fromBytes(PacketBuffer buf) {
var packet = new PacketGhostSlot(); PacketGhostSlot packet = new PacketGhostSlot();
packet.pos = buf.readBlockPos(); packet.pos = buf.readBlockPos();
packet.stacks = ArrayListMultimap.create(); packet.stacks = ArrayListMultimap.create();
for (var i = buf.readInt(); i > 0; i--) for (int i = buf.readInt(); i > 0; i--)
packet.stacks.put(buf.readInt(), buf.readItem()); packet.stacks.put(buf.readInt(), buf.readItemStack());
return packet; return packet;
} }
public static void toBytes(PacketGhostSlot packet, FriendlyByteBuf buf) { public static void toBytes(PacketGhostSlot packet, PacketBuffer buf) {
buf.writeBlockPos(packet.pos); buf.writeBlockPos(packet.pos);
buf.writeInt(packet.stacks.size()); buf.writeInt(packet.stacks.size());
for (var entry : packet.stacks.entries()) { for (Map.Entry<Integer, ItemStack> entry : packet.stacks.entries()) {
buf.writeInt(entry.getKey()); buf.writeInt(entry.getKey());
buf.writeItem(entry.getValue()); buf.writeItemStack(entry.getValue());
} }
} }
@SuppressWarnings("Convert2Lambda") @SuppressWarnings("Convert2Lambda")
public static void onMessage(PacketGhostSlot message, Supplier<NetworkEvent.Context> ctx) { public static void onMessage(PacketGhostSlot message, Supplier<NetworkEvent.Context> ctx) {
var doIt = (Consumer<Player>) p -> { Consumer<PlayerEntity> doIt = p -> {
var tile = Utility.getBlockEntity(CraftingTerminalBlockEntity.class, p.level, message.pos); CraftingTerminalTileEntity tile = Utility.getBlockEntity(CraftingTerminalTileEntity.class, p.world, message.pos);
if (tile != null) if (tile != null)
tile.setGhostItems(message.stacks); tile.setGhostItems(message.stacks);
}; };
// this whole thing is a dirty hack for allowing the same packet to be used // this whole thing is a dirty hack for allowing the same packet to be used
// both client -> server and server -> client without any classloading issues // both client -> server and server -> client without any classloading issues
Player player = ctx.get().getSender(); PlayerEntity player = ctx.get().getSender();
// are we on the client? // are we on the client?
if (player == null) { if (player == null) {
ctx.get().enqueueWork(new Runnable() { ctx.get().enqueueWork(new Runnable() {

View file

@ -1,14 +1,15 @@
package de.ellpeck.prettypipes.packets; package de.ellpeck.prettypipes.packets;
import de.ellpeck.prettypipes.PrettyPipes; import de.ellpeck.prettypipes.PrettyPipes;
import net.minecraft.core.BlockPos; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerPlayer; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.entity.player.Player; import net.minecraft.world.IWorld;
import net.minecraft.world.level.Level; import net.minecraft.world.World;
import net.minecraftforge.network.NetworkRegistry; import net.minecraftforge.fml.network.NetworkRegistry;
import net.minecraftforge.network.PacketDistributor; import net.minecraftforge.fml.network.PacketDistributor;
import net.minecraftforge.network.simple.SimpleChannel; import net.minecraftforge.fml.network.simple.SimpleChannel;
public final class PacketHandler { public final class PacketHandler {
@ -25,12 +26,12 @@ public final class PacketHandler {
network.registerMessage(5, PacketCraftingModuleTransfer.class, PacketCraftingModuleTransfer::toBytes, PacketCraftingModuleTransfer::fromBytes, PacketCraftingModuleTransfer::onMessage); network.registerMessage(5, PacketCraftingModuleTransfer.class, PacketCraftingModuleTransfer::toBytes, PacketCraftingModuleTransfer::fromBytes, PacketCraftingModuleTransfer::onMessage);
} }
public static void sendToAllLoaded(Level world, BlockPos pos, Object message) { public static void sendToAllLoaded(World world, BlockPos pos, Object message) {
network.send(PacketDistributor.TRACKING_CHUNK.with(() -> world.getChunkAt(pos)), message); network.send(PacketDistributor.TRACKING_CHUNK.with(() -> world.getChunkAt(pos)), message);
} }
public static void sendTo(Player player, Object message) { public static void sendTo(PlayerEntity player, Object message) {
network.send(PacketDistributor.PLAYER.with(() -> (ServerPlayer) player), message); network.send(PacketDistributor.PLAYER.with(() -> (ServerPlayerEntity) player), message);
} }
public static void sendToServer(Object message) { public static void sendToServer(Object message) {

View file

@ -2,12 +2,12 @@ package de.ellpeck.prettypipes.packets;
import de.ellpeck.prettypipes.Utility; import de.ellpeck.prettypipes.Utility;
import de.ellpeck.prettypipes.pipe.IPipeItem; import de.ellpeck.prettypipes.pipe.IPipeItem;
import de.ellpeck.prettypipes.pipe.PipeBlockEntity; import de.ellpeck.prettypipes.pipe.PipeTileEntity;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.PacketBuffer;
import net.minecraftforge.network.NetworkEvent; import net.minecraft.util.math.BlockPos;
import net.minecraftforge.fml.network.NetworkEvent;
import java.util.function.Supplier; import java.util.function.Supplier;
@ -25,16 +25,16 @@ public class PacketItemEnterPipe {
} }
public static PacketItemEnterPipe fromBytes(FriendlyByteBuf buf) { public static PacketItemEnterPipe fromBytes(PacketBuffer buf) {
var client = new PacketItemEnterPipe(); PacketItemEnterPipe client = new PacketItemEnterPipe();
client.tilePos = buf.readBlockPos(); client.tilePos = buf.readBlockPos();
client.item = buf.readNbt(); client.item = buf.readCompoundTag();
return client; return client;
} }
public static void toBytes(PacketItemEnterPipe packet, FriendlyByteBuf buf) { public static void toBytes(PacketItemEnterPipe packet, PacketBuffer buf) {
buf.writeBlockPos(packet.tilePos); buf.writeBlockPos(packet.tilePos);
buf.writeNbt(packet.item); buf.writeCompoundTag(packet.item);
} }
@SuppressWarnings("Convert2Lambda") @SuppressWarnings("Convert2Lambda")
@ -42,11 +42,11 @@ public class PacketItemEnterPipe {
ctx.get().enqueueWork(new Runnable() { ctx.get().enqueueWork(new Runnable() {
@Override @Override
public void run() { public void run() {
var mc = Minecraft.getInstance(); Minecraft mc = Minecraft.getInstance();
if (mc.level == null) if (mc.world == null)
return; return;
var item = IPipeItem.load(message.item); IPipeItem item = IPipeItem.load(message.item);
var pipe = Utility.getBlockEntity(PipeBlockEntity.class, mc.level, message.tilePos); PipeTileEntity pipe = Utility.getBlockEntity(PipeTileEntity.class, mc.world, message.tilePos);
if (pipe != null) if (pipe != null)
pipe.getItems().add(item); pipe.getItems().add(item);
} }

View file

@ -2,9 +2,13 @@ package de.ellpeck.prettypipes.packets;
import de.ellpeck.prettypipes.terminal.containers.ItemTerminalGui; import de.ellpeck.prettypipes.terminal.containers.ItemTerminalGui;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.network.FriendlyByteBuf; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.inventory.container.Container;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraftforge.network.NetworkEvent; import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.PacketBuffer;
import net.minecraft.util.math.BlockPos;
import net.minecraftforge.fml.network.NetworkEvent;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -26,37 +30,37 @@ public class PacketNetworkItems {
} }
public static PacketNetworkItems fromBytes(FriendlyByteBuf buf) { public static PacketNetworkItems fromBytes(PacketBuffer buf) {
var client = new PacketNetworkItems(); PacketNetworkItems client = new PacketNetworkItems();
client.items = new ArrayList<>(); client.items = new ArrayList<>();
for (var i = buf.readVarInt(); i > 0; i--) { for (int i = buf.readVarInt(); i > 0; i--) {
var stack = buf.readItem(); ItemStack stack = buf.readItemStack();
stack.setCount(buf.readVarInt()); stack.setCount(buf.readVarInt());
client.items.add(stack); client.items.add(stack);
} }
client.craftables = new ArrayList<>(); client.craftables = new ArrayList<>();
for (var i = buf.readVarInt(); i > 0; i--) for (int i = buf.readVarInt(); i > 0; i--)
client.craftables.add(buf.readItem()); client.craftables.add(buf.readItemStack());
client.currentlyCrafting = new ArrayList<>(); client.currentlyCrafting = new ArrayList<>();
for (var i = buf.readVarInt(); i > 0; i--) for (int i = buf.readVarInt(); i > 0; i--)
client.currentlyCrafting.add(buf.readItem()); client.currentlyCrafting.add(buf.readItemStack());
return client; return client;
} }
public static void toBytes(PacketNetworkItems packet, FriendlyByteBuf buf) { public static void toBytes(PacketNetworkItems packet, PacketBuffer buf) {
buf.writeVarInt(packet.items.size()); buf.writeVarInt(packet.items.size());
for (var stack : packet.items) { for (ItemStack stack : packet.items) {
var copy = stack.copy(); ItemStack copy = stack.copy();
copy.setCount(1); copy.setCount(1);
buf.writeItem(copy); buf.writeItemStack(copy);
buf.writeVarInt(stack.getCount()); buf.writeVarInt(stack.getCount());
} }
buf.writeVarInt(packet.craftables.size()); buf.writeVarInt(packet.craftables.size());
for (var stack : packet.craftables) for (ItemStack stack : packet.craftables)
buf.writeItem(stack); buf.writeItemStack(stack);
buf.writeVarInt(packet.currentlyCrafting.size()); buf.writeVarInt(packet.currentlyCrafting.size());
for (var stack : packet.currentlyCrafting) for (ItemStack stack : packet.currentlyCrafting)
buf.writeItem(stack); buf.writeItemStack(stack);
} }
@SuppressWarnings("Convert2Lambda") @SuppressWarnings("Convert2Lambda")
@ -64,9 +68,9 @@ public class PacketNetworkItems {
ctx.get().enqueueWork(new Runnable() { ctx.get().enqueueWork(new Runnable() {
@Override @Override
public void run() { public void run() {
var mc = Minecraft.getInstance(); Minecraft mc = Minecraft.getInstance();
if (mc.screen instanceof ItemTerminalGui terminal) if (mc.currentScreen instanceof ItemTerminalGui)
terminal.updateItemList(message.items, message.craftables, message.currentlyCrafting); ((ItemTerminalGui) mc.currentScreen).updateItemList(message.items, message.craftables, message.currentlyCrafting);
} }
}); });
ctx.get().setPacketHandled(true); ctx.get().setPacketHandled(true);

View file

@ -1,12 +1,12 @@
package de.ellpeck.prettypipes.packets; package de.ellpeck.prettypipes.packets;
import de.ellpeck.prettypipes.Utility; import de.ellpeck.prettypipes.Utility;
import de.ellpeck.prettypipes.terminal.ItemTerminalBlockEntity; import de.ellpeck.prettypipes.terminal.ItemTerminalTileEntity;
import net.minecraft.core.BlockPos; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraftforge.network.NetworkEvent; import net.minecraft.network.PacketBuffer;
import net.minecraft.util.math.BlockPos;
import net.minecraftforge.fml.network.NetworkEvent;
import java.util.function.Supplier; import java.util.function.Supplier;
@ -26,17 +26,17 @@ public class PacketRequest {
} }
public static PacketRequest fromBytes(FriendlyByteBuf buf) { public static PacketRequest fromBytes(PacketBuffer buf) {
var packet = new PacketRequest(); PacketRequest packet = new PacketRequest();
packet.pos = buf.readBlockPos(); packet.pos = buf.readBlockPos();
packet.stack = buf.readItem(); packet.stack = buf.readItemStack();
packet.amount = buf.readVarInt(); packet.amount = buf.readVarInt();
return packet; return packet;
} }
public static void toBytes(PacketRequest packet, FriendlyByteBuf buf) { public static void toBytes(PacketRequest packet, PacketBuffer buf) {
buf.writeBlockPos(packet.pos); buf.writeBlockPos(packet.pos);
buf.writeItem(packet.stack); buf.writeItemStack(packet.stack);
buf.writeVarInt(packet.amount); buf.writeVarInt(packet.amount);
} }
@ -45,8 +45,8 @@ public class PacketRequest {
ctx.get().enqueueWork(new Runnable() { ctx.get().enqueueWork(new Runnable() {
@Override @Override
public void run() { public void run() {
Player player = ctx.get().getSender(); PlayerEntity player = ctx.get().getSender();
var tile = Utility.getBlockEntity(ItemTerminalBlockEntity.class, player.level, message.pos); ItemTerminalTileEntity tile = Utility.getBlockEntity(ItemTerminalTileEntity.class, player.world, message.pos);
message.stack.setCount(message.amount); message.stack.setCount(message.amount);
tile.requestItem(player, message.stack); tile.requestItem(player, message.stack);
} }

View file

@ -1,8 +1,8 @@
package de.ellpeck.prettypipes.pipe; package de.ellpeck.prettypipes.pipe;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
public interface IPipeConnectable { public interface IPipeConnectable {

View file

@ -1,14 +1,16 @@
package de.ellpeck.prettypipes.pipe; package de.ellpeck.prettypipes.pipe;
import com.mojang.blaze3d.vertex.PoseStack; 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.NetworkEdge;
import de.ellpeck.prettypipes.network.PipeItem; import de.ellpeck.prettypipes.network.PipeItem;
import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.IRenderTypeBuffer;
import net.minecraft.core.BlockPos;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.Level; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.common.util.INBTSerializable; import net.minecraftforge.common.util.INBTSerializable;
@ -29,9 +31,9 @@ public interface IPipeItem extends INBTSerializable<CompoundTag> {
void setDestination(BlockPos startInventory, BlockPos destInventory, GraphPath<BlockPos, NetworkEdge> path); void setDestination(BlockPos startInventory, BlockPos destInventory, GraphPath<BlockPos, NetworkEdge> path);
void updateInPipe(PipeBlockEntity currPipe); void updateInPipe(PipeTileEntity currPipe);
void drop(Level world, ItemStack stack); void drop(World world, ItemStack stack);
BlockPos getDestPipe(); BlockPos getDestPipe();
@ -42,11 +44,15 @@ public interface IPipeItem extends INBTSerializable<CompoundTag> {
int getItemsOnTheWay(BlockPos goalInv); int getItemsOnTheWay(BlockPos goalInv);
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
void render(PipeBlockEntity tile, PoseStack matrixStack, Random random, float partialTicks, int light, int overlay, MultiBufferSource source); void render(PipeTileEntity tile, MatrixStack matrixStack, Random random, float partialTicks, int light, int overlay, IRenderTypeBuffer buffer);
static IPipeItem load(CompoundTag nbt) { static IPipeItem load(CompoundTag nbt) {
var type = new ResourceLocation(nbt.getString("type")); // TODO legacy compat, remove eventually
var func = TYPES.get(type); if (!nbt.contains("type"))
nbt.putString("type", PipeItem.TYPE.toString());
ResourceLocation type = new ResourceLocation(nbt.getString("type"));
BiFunction<ResourceLocation, CompoundTag, IPipeItem> func = TYPES.get(type);
return func != null ? func.apply(type, nbt) : null; return func != null ? func.apply(type, nbt) : null;
} }
} }

View file

@ -5,36 +5,51 @@ import de.ellpeck.prettypipes.Registry;
import de.ellpeck.prettypipes.Utility; import de.ellpeck.prettypipes.Utility;
import de.ellpeck.prettypipes.items.IModule; import de.ellpeck.prettypipes.items.IModule;
import de.ellpeck.prettypipes.network.PipeNetwork; import de.ellpeck.prettypipes.network.PipeNetwork;
import net.minecraft.block.*;
import net.minecraft.block.material.Material;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
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.item.BlockItemUseContext;
import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerPlayer;
import net.minecraft.tags.FluidTags;
import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult; import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.context.BlockPlaceContext; import net.minecraft.state.EnumProperty;
import net.minecraft.world.level.BlockGetter; import net.minecraft.state.StateContainer;
import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.tags.FluidTags;
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.math.shapes.IBooleanFunction;
import net.minecraft.util.math.shapes.ISelectionContext;
import net.minecraft.util.math.shapes.VoxelShape;
import net.minecraft.util.math.shapes.VoxelShapes;
import net.minecraft.world.IBlockReader;
import net.minecraft.world.IWorld;
import net.minecraft.world.World;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.block.BaseEntityBlock;
import net.minecraft.world.level.block.*; import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.SoundType;
import net.minecraft.world.level.block.entity.BlockEntityTicker;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.BlockStateProperties; import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.level.block.state.properties.EnumProperty; import net.minecraft.world.level.block.state.properties.EnumProperty;
import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.level.material.Fluids;
import net.minecraft.world.level.material.Material; import net.minecraft.world.level.material.Material;
import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.shapes.BooleanOp;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.phys.shapes.VoxelShape; import net.minecraft.world.phys.shapes.VoxelShape;
import net.minecraftforge.fml.network.NetworkHooks;
import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.ItemHandlerHelper; import net.minecraftforge.items.ItemHandlerHelper;
import net.minecraftforge.network.NetworkHooks; import net.minecraftforge.network.NetworkHooks;
import org.apache.commons.lang3.mutable.MutableObject; import org.apache.commons.lang3.mutable.MutableObject;
@ -61,31 +76,31 @@ public class PipeBlock extends BaseEntityBlock {
.build(); .build();
static { static {
for (var dir : Direction.values()) for (Direction dir : Direction.values())
DIRECTIONS.put(dir, EnumProperty.create(dir.getName(), ConnectionType.class)); DIRECTIONS.put(dir, EnumProperty.create(dir.getName(), ConnectionType.class));
} }
public PipeBlock() { public PipeBlock() {
super(Block.Properties.of(Material.STONE).strength(2).sound(SoundType.STONE).noOcclusion()); super(Block.Properties.of(Material.STONE).strength(2).sound(SoundType.STONE).noOcclusion());
var state = this.defaultBlockState().setValue(BlockStateProperties.WATERLOGGED, false); BlockState state = this.defaultBlockState().setValue(BlockStateProperties.WATERLOGGED, false);
for (var prop : DIRECTIONS.values()) for (EnumProperty<ConnectionType> prop : DIRECTIONS.values())
state = state.setValue(prop, ConnectionType.DISCONNECTED); state = state.setValue(prop, ConnectionType.DISCONNECTED);
this.registerDefaultState(state); this.registerDefaultState(state);
} }
@Override @Override
public InteractionResult use(BlockState state, Level worldIn, BlockPos pos, Player player, InteractionHand handIn, BlockHitResult result) { public InteractionResult use(BlockState state, Level worldIn, BlockPos pos, Player player, InteractionHand handIn, BlockHitResult result) {
var tile = Utility.getBlockEntity(PipeBlockEntity.class, worldIn, pos); PipeTileEntity tile = Utility.getBlockEntity(PipeTileEntity.class, worldIn, pos);
if (tile == null) if (tile == null)
return InteractionResult.PASS; return InteractionResult.PASS;
if (!tile.canHaveModules()) if (!tile.canHaveModules())
return InteractionResult.PASS; return InteractionResult.PASS;
var stack = player.getItemInHand(handIn); ItemStack stack = player.getItemInHand(handIn);
if (stack.getItem() instanceof IModule) { if (stack.getItem() instanceof IModule) {
var copy = stack.copy(); ItemStack copy = stack.copy();
copy.setCount(1); copy.setCount(1);
var remain = ItemHandlerHelper.insertItem(tile.modules, copy, false); ItemStack remain = ItemHandlerHelper.insertItem(tile.modules, copy, false);
if (remain.isEmpty()) { if (remain.isEmpty()) {
stack.shrink(1); stack.shrink(1);
return InteractionResult.SUCCESS; return InteractionResult.SUCCESS;
@ -99,62 +114,62 @@ public class PipeBlock extends BaseEntityBlock {
} }
@Override @Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) { protected void fillStateContainer(StateContainer.Builder<Block, BlockState> builder) {
builder.add(DIRECTIONS.values().toArray(new EnumProperty[0])); builder.add(DIRECTIONS.values().toArray(new EnumProperty[0]));
builder.add(BlockStateProperties.WATERLOGGED); builder.add(BlockStateProperties.WATERLOGGED);
} }
@Override @Override
public FluidState getFluidState(BlockState state) { public FluidState getFluidState(BlockState state) {
return state.getValue(BlockStateProperties.WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(state); return state.get(BlockStateProperties.WATERLOGGED) ? Fluids.WATER.getStillFluidState(false) : super.getFluidState(state);
} }
@Override @Override
public void neighborChanged(BlockState state, Level worldIn, BlockPos pos, Block blockIn, BlockPos fromPos, boolean isMoving) { public void neighborChanged(BlockState state, World worldIn, BlockPos pos, Block blockIn, BlockPos fromPos, boolean isMoving) {
var newState = this.createState(worldIn, pos, state); BlockState newState = this.createState(worldIn, pos, state);
if (newState != state) { if (newState != state) {
worldIn.setBlockAndUpdate(pos, newState); worldIn.setBlockState(pos, newState);
onStateChanged(worldIn, pos, newState); onStateChanged(worldIn, pos, newState);
} }
} }
@Nullable @Nullable
@Override @Override
public BlockState getStateForPlacement(BlockPlaceContext context) { public BlockState getStateForPlacement(BlockItemUseContext context) {
return this.createState(context.getLevel(), context.getClickedPos(), this.defaultBlockState()); return this.createState(context.getWorld(), context.getPos(), this.getDefaultState());
} }
@Override @Override
public BlockState updateShape(BlockState stateIn, Direction facing, BlockState facingState, LevelAccessor worldIn, BlockPos currentPos, BlockPos facingPos) { public BlockState updatePostPlacement(BlockState stateIn, Direction facing, BlockState facingState, IWorld worldIn, BlockPos currentPos, BlockPos facingPos) {
if (stateIn.getValue(BlockStateProperties.WATERLOGGED)) if (stateIn.get(BlockStateProperties.WATERLOGGED))
worldIn.scheduleTick(currentPos, Fluids.WATER, Fluids.WATER.getTickDelay(worldIn)); worldIn.getPendingFluidTicks().scheduleTick(currentPos, Fluids.WATER, Fluids.WATER.getTickRate(worldIn));
return super.updateShape(stateIn, facing, facingState, worldIn, currentPos, facingPos); return super.updatePostPlacement(stateIn, facing, facingState, worldIn, currentPos, facingPos);
} }
@Override @Override
public void setPlacedBy(Level worldIn, BlockPos pos, BlockState state, @Nullable LivingEntity placer, ItemStack stack) { public void onBlockPlacedBy(World worldIn, BlockPos pos, BlockState state, @Nullable LivingEntity placer, ItemStack stack) {
onStateChanged(worldIn, pos, state); onStateChanged(worldIn, pos, state);
} }
@Override @Override
public VoxelShape getShape(BlockState state, BlockGetter worldIn, BlockPos pos, CollisionContext context) { 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); return this.cacheAndGetShape(state, worldIn, pos, s -> s.getShape(worldIn, pos, context), SHAPE_CACHE, null);
} }
@Override @Override
public VoxelShape getCollisionShape(BlockState state, BlockGetter worldIn, BlockPos pos, CollisionContext context) { 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 -> { 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 // make the shape a bit higher so we can jump up onto a higher block
var newShape = new MutableObject<VoxelShape>(Shapes.empty()); MutableObject<VoxelShape> newShape = new MutableObject<>(VoxelShapes.empty());
s.forAllBoxes((x1, y1, z1, x2, y2, z2) -> newShape.setValue(Shapes.join(Shapes.create(x1, y1, z1, x2, y2 + 3 / 16F, z2), newShape.getValue(), BooleanOp.OR))); 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().optimize(); return newShape.getValue().simplify();
}); });
} }
private VoxelShape cacheAndGetShape(BlockState state, BlockGetter worldIn, BlockPos pos, Function<BlockState, VoxelShape> coverShapeSelector, Map<Pair<BlockState, BlockState>, VoxelShape> cache, Function<VoxelShape, VoxelShape> shapeModifier) { 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; VoxelShape coverShape = null;
BlockState cover = null; BlockState cover = null;
var tile = Utility.getBlockEntity(PipeBlockEntity.class, worldIn, pos); PipeTileEntity tile = Utility.getBlockEntity(PipeTileEntity.class, worldIn, pos);
if (tile != null && tile.cover != null) { if (tile != null && tile.cover != null) {
cover = tile.cover; cover = tile.cover;
// try catch since the block might expect to find itself at the position // try catch since the block might expect to find itself at the position
@ -163,88 +178,88 @@ public class PipeBlock extends BaseEntityBlock {
} catch (Exception ignored) { } catch (Exception ignored) {
} }
} }
var key = Pair.of(state, cover); Pair<BlockState, BlockState> key = Pair.of(state, cover);
var shape = cache.get(key); VoxelShape shape = cache.get(key);
if (shape == null) { if (shape == null) {
shape = CENTER_SHAPE; shape = CENTER_SHAPE;
for (var entry : DIRECTIONS.entrySet()) { for (Map.Entry<Direction, EnumProperty<ConnectionType>> entry : DIRECTIONS.entrySet()) {
if (state.getValue(entry.getValue()).isConnected()) if (state.get(entry.getValue()).isConnected())
shape = Shapes.or(shape, DIR_SHAPES.get(entry.getKey())); shape = VoxelShapes.or(shape, DIR_SHAPES.get(entry.getKey()));
} }
if (shapeModifier != null) if (shapeModifier != null)
shape = shapeModifier.apply(shape); shape = shapeModifier.apply(shape);
if (coverShape != null) if (coverShape != null)
shape = Shapes.or(shape, coverShape); shape = VoxelShapes.or(shape, coverShape);
cache.put(key, shape); cache.put(key, shape);
} }
return shape; return shape;
} }
private BlockState createState(Level world, BlockPos pos, BlockState curr) { private BlockState createState(World world, BlockPos pos, BlockState curr) {
var state = this.defaultBlockState(); BlockState state = this.getDefaultState();
var fluid = world.getFluidState(pos); FluidState fluid = world.getFluidState(pos);
if (fluid.is(FluidTags.WATER) && fluid.getAmount() == 8) if (fluid.isTagged(FluidTags.WATER) && fluid.getLevel() == 8)
state = state.setValue(BlockStateProperties.WATERLOGGED, true); state = state.with(BlockStateProperties.WATERLOGGED, true);
for (var dir : Direction.values()) { for (Direction dir : Direction.values()) {
var prop = DIRECTIONS.get(dir); EnumProperty<ConnectionType> prop = DIRECTIONS.get(dir);
var type = this.getConnectionType(world, pos, dir, state); ConnectionType type = this.getConnectionType(world, pos, dir, state);
// don't reconnect on blocked faces // don't reconnect on blocked faces
if (type.isConnected() && curr.getValue(prop) == ConnectionType.BLOCKED) if (type.isConnected() && curr.get(prop) == ConnectionType.BLOCKED)
type = ConnectionType.BLOCKED; type = ConnectionType.BLOCKED;
state = state.setValue(prop, type); state = state.with(prop, type);
} }
return state; return state;
} }
protected ConnectionType getConnectionType(Level world, BlockPos pos, Direction direction, BlockState state) { protected ConnectionType getConnectionType(World world, BlockPos pos, Direction direction, BlockState state) {
var offset = pos.relative(direction); BlockPos offset = pos.offset(direction);
if (!world.isLoaded(offset)) if (!world.isBlockLoaded(offset))
return ConnectionType.DISCONNECTED; return ConnectionType.DISCONNECTED;
var opposite = direction.getOpposite(); Direction opposite = direction.getOpposite();
var tile = world.getBlockEntity(offset); TileEntity tile = world.getTileEntity(offset);
if (tile != null) { if (tile != null) {
var connectable = tile.getCapability(Registry.pipeConnectableCapability, opposite).orElse(null); IPipeConnectable connectable = tile.getCapability(Registry.pipeConnectableCapability, opposite).orElse(null);
if (connectable != null) if (connectable != null)
return connectable.getConnectionType(pos, direction); return connectable.getConnectionType(pos, direction);
var handler = tile.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, opposite).orElse(null); IItemHandler handler = tile.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, opposite).orElse(null);
if (handler != null) if (handler != null)
return ConnectionType.CONNECTED; return ConnectionType.CONNECTED;
} }
var blockHandler = Utility.getBlockItemHandler(world, offset, opposite); IItemHandler blockHandler = Utility.getBlockItemHandler(world, offset, opposite);
if (blockHandler != null) if (blockHandler != null)
return ConnectionType.CONNECTED; return ConnectionType.CONNECTED;
var offState = world.getBlockState(offset); BlockState offState = world.getBlockState(offset);
if (hasLegsTo(world, offState, offset, direction)) { if (hasLegsTo(world, offState, offset, direction)) {
if (DIRECTIONS.values().stream().noneMatch(d -> state.getValue(d) == ConnectionType.LEGS)) if (DIRECTIONS.values().stream().noneMatch(d -> state.get(d) == ConnectionType.LEGS))
return ConnectionType.LEGS; return ConnectionType.LEGS;
} }
return ConnectionType.DISCONNECTED; return ConnectionType.DISCONNECTED;
} }
protected static boolean hasLegsTo(Level world, BlockState state, BlockPos pos, Direction direction) { protected static boolean hasLegsTo(World world, BlockState state, BlockPos pos, Direction direction) {
if (state.getBlock() instanceof WallBlock || state.getBlock() instanceof FenceBlock) if (state.getBlock() instanceof WallBlock || state.getBlock() instanceof FenceBlock)
return direction == Direction.DOWN; return direction == Direction.DOWN;
if (state.getMaterial() == Material.STONE || state.getMaterial() == Material.METAL) if (state.getMaterial() == Material.ROCK || state.getMaterial() == Material.IRON)
return canSupportCenter(world, pos, direction.getOpposite()); return hasEnoughSolidSide(world, pos, direction.getOpposite());
return false; return false;
} }
public static void onStateChanged(Level world, BlockPos pos, BlockState newState) { 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 // wait a few ticks before checking if we have to drop our modules, so that things like iron -> gold chest work
var tile = Utility.getBlockEntity(PipeBlockEntity.class, world, pos); PipeTileEntity tile = Utility.getBlockEntity(PipeTileEntity.class, world, pos);
if (tile != null) if (tile != null)
tile.moduleDropCheck = 5; tile.moduleDropCheck = 5;
var network = PipeNetwork.get(world); PipeNetwork network = PipeNetwork.get(world);
var connections = 0; int connections = 0;
var force = false; boolean force = false;
for (var dir : Direction.values()) { for (Direction dir : Direction.values()) {
var value = newState.getValue(DIRECTIONS.get(dir)); ConnectionType value = newState.get(DIRECTIONS.get(dir));
if (!value.isConnected()) if (!value.isConnected())
continue; continue;
connections++; connections++;
var otherState = world.getBlockState(pos.relative(dir)); BlockState otherState = world.getBlockState(pos.offset(dir));
// force a node if we're connecting to a different block (inventory etc.) // force a node if we're connecting to a different block (inventory etc.)
if (otherState.getBlock() != newState.getBlock()) { if (otherState.getBlock() != newState.getBlock()) {
force = true; force = true;
@ -260,59 +275,53 @@ public class PipeBlock extends BaseEntityBlock {
} }
@Override @Override
public void onRemove(BlockState state, Level worldIn, BlockPos pos, BlockState newState, boolean isMoving) { public void onReplaced(BlockState state, World worldIn, BlockPos pos, BlockState newState, boolean isMoving) {
if (state.getBlock() != newState.getBlock()) { if (state.getBlock() != newState.getBlock()) {
var network = PipeNetwork.get(worldIn); PipeNetwork network = PipeNetwork.get(worldIn);
network.removeNode(pos); network.removeNode(pos);
network.onPipeChanged(pos, state); network.onPipeChanged(pos, state);
super.onRemove(state, worldIn, pos, newState, isMoving); super.onReplaced(state, worldIn, pos, newState, isMoving);
} }
} }
@Override @Override
public void playerWillDestroy(Level worldIn, BlockPos pos, BlockState state, Player player) { public void onBlockHarvested(World worldIn, BlockPos pos, BlockState state, PlayerEntity player) {
dropItems(worldIn, pos, player); dropItems(worldIn, pos, player);
super.playerWillDestroy(worldIn, pos, state, player); super.onBlockHarvested(worldIn, pos, state, player);
} }
@Override @Override
public boolean hasAnalogOutputSignal(BlockState state) { public boolean hasComparatorInputOverride(BlockState state) {
return true; return true;
} }
@Override @Override
public int getAnalogOutputSignal(BlockState state, Level world, BlockPos pos) { public int getComparatorInputOverride(BlockState blockState, World worldIn, BlockPos pos) {
var pipe = Utility.getBlockEntity(PipeBlockEntity.class, world, pos); PipeTileEntity pipe = Utility.getBlockEntity(PipeTileEntity.class, worldIn, pos);
if (pipe == null) if (pipe == null)
return 0; return 0;
return Math.min(15, pipe.getItems().size()); return Math.min(15, pipe.getItems().size());
} }
@org.jetbrains.annotations.Nullable @Nullable
@Override @Override
public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { public TileEntity createNewTileEntity(IBlockReader worldIn) {
return new PipeBlockEntity(pos, state); return new PipeTileEntity();
} }
@Override @Override
public RenderShape getRenderShape(BlockState state) { public BlockRenderType getRenderType(BlockState state) {
return RenderShape.MODEL; return BlockRenderType.MODEL;
} }
@org.jetbrains.annotations.Nullable public static void dropItems(World worldIn, BlockPos pos, PlayerEntity player) {
@Override PipeTileEntity tile = Utility.getBlockEntity(PipeTileEntity.class, worldIn, pos);
public <T extends BlockEntity> BlockEntityTicker<T> getTicker(Level level, BlockState state, BlockEntityType<T> type) {
return createTickerHelper(type, Registry.pipeBlockEntity, PipeBlockEntity::tick);
}
public static void dropItems(Level worldIn, BlockPos pos, Player player) {
var tile = Utility.getBlockEntity(PipeBlockEntity.class, worldIn, pos);
if (tile != null) { if (tile != null) {
Utility.dropInventory(tile, tile.modules); Utility.dropInventory(tile, tile.modules);
for (var item : tile.getItems()) for (IPipeItem item : tile.getItems())
item.drop(worldIn, item.getContent()); item.drop(worldIn, item.getContent());
if (tile.cover != null) if (tile.cover != null)
tile.removeCover(player, InteractionHand.MAIN_HAND); tile.removeCover(player, Hand.MAIN_HAND);
} }
} }
} }

View file

@ -1,51 +1,54 @@
package de.ellpeck.prettypipes.pipe; package de.ellpeck.prettypipes.pipe;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.vertex.IVertexBuilder;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.ItemBlockRenderTypes; import net.minecraft.client.renderer.BlockModelRenderer;
import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.IRenderTypeBuffer;
import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.blockentity.BlockEntityRenderer; import net.minecraft.client.renderer.RenderTypeLookup;
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; import net.minecraft.client.renderer.tileentity.TileEntityRenderer;
import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.math.BlockPos;
import net.minecraftforge.client.ForgeHooksClient; import net.minecraftforge.client.ForgeHooksClient;
import net.minecraftforge.client.model.pipeline.ForgeBlockModelRenderer; import net.minecraftforge.client.model.data.EmptyModelData;
import java.util.Random; import java.util.Random;
public class PipeRenderer implements BlockEntityRenderer<PipeBlockEntity> { public class PipeRenderer extends TileEntityRenderer<PipeTileEntity> {
private final Random random = new Random(); private final Random random = new Random();
public PipeRenderer(BlockEntityRendererProvider.Context ctx) { public PipeRenderer(TileEntityRendererDispatcher disp) {
super(disp);
} }
@Override @Override
public void render(PipeBlockEntity tile, float partialTicks, PoseStack matrixStack, MultiBufferSource source, int light, int overlay) { public void render(PipeTileEntity tile, float partialTicks, MatrixStack matrixStack, IRenderTypeBuffer buffer, int light, int overlay) {
if (!tile.getItems().isEmpty()) { if (!tile.getItems().isEmpty()) {
matrixStack.pushPose(); matrixStack.push();
var tilePos = tile.getBlockPos(); BlockPos tilePos = tile.getPos();
matrixStack.translate(-tilePos.getX(), -tilePos.getY(), -tilePos.getZ()); matrixStack.translate(-tilePos.getX(), -tilePos.getY(), -tilePos.getZ());
for (var item : tile.getItems()) { for (IPipeItem item : tile.getItems()) {
matrixStack.pushPose(); matrixStack.push();
item.render(tile, matrixStack, this.random, partialTicks, light, overlay, source); item.render(tile, matrixStack, this.random, partialTicks, light, overlay, buffer);
matrixStack.popPose(); matrixStack.pop();
} }
matrixStack.popPose(); matrixStack.pop();
} }
if (tile.cover != null) { if (tile.cover != null) {
matrixStack.pushPose(); matrixStack.push();
ForgeBlockModelRenderer.enableCaching(); BlockModelRenderer.enableCache();
var renderer = Minecraft.getInstance().getBlockRenderer(); for (RenderType layer : RenderType.getBlockRenderTypes()) {
for (var layer : RenderType.chunkBufferLayers()) { if (!RenderTypeLookup.canRenderInLayer(tile.cover, layer))
if (!ItemBlockRenderTypes.canRenderInLayer(tile.cover, layer))
continue; continue;
ForgeHooksClient.setRenderType(layer); ForgeHooksClient.setRenderLayer(layer);
renderer.getModelRenderer().tesselateBlock(tile.getLevel(), renderer.getBlockModel(tile.cover), tile.cover, tile.getBlockPos(), matrixStack, source.getBuffer(layer), true, new Random(), tile.cover.getSeed(tile.getBlockPos()), overlay); Minecraft.getInstance().getBlockRendererDispatcher().renderBlock(tile.cover, matrixStack, buffer, light, overlay, EmptyModelData.INSTANCE);
} }
ForgeHooksClient.setRenderType(null); ForgeHooksClient.setRenderLayer(null);
ForgeBlockModelRenderer.clearCache(); BlockModelRenderer.disableCache();
matrixStack.popPose(); matrixStack.pop();
} }
} }
} }

View file

@ -10,32 +10,38 @@ import de.ellpeck.prettypipes.network.NetworkLock;
import de.ellpeck.prettypipes.network.PipeNetwork; import de.ellpeck.prettypipes.network.PipeNetwork;
import de.ellpeck.prettypipes.pipe.containers.MainPipeContainer; import de.ellpeck.prettypipes.pipe.containers.MainPipeContainer;
import de.ellpeck.prettypipes.pressurizer.PressurizerBlockEntity; import de.ellpeck.prettypipes.pressurizer.PressurizerBlockEntity;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction; 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.Item;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;
import net.minecraft.nbt.NbtUtils; import net.minecraft.nbt.NbtUtils;
import net.minecraft.nbt.Tag;
import net.minecraft.network.Connection;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.Containers;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.MenuProvider;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level; import net.minecraft.nbt.ListTag;
import net.minecraft.world.level.block.Block; 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.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.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.AABB; import net.minecraft.world.server.ServerWorld;
import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.util.Constants.NBT;
import net.minecraftforge.common.util.Lazy; import net.minecraftforge.common.util.Lazy;
import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.CapabilityItemHandler;
@ -51,7 +57,7 @@ import java.util.function.Consumer;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
public class PipeBlockEntity extends BlockEntity implements MenuProvider, IPipeConnectable { public class PipeTileEntity extends BlockEntity implements INamedContainerProvider, ITickableTileEntity, IPipeConnectable {
public final ItemStackHandler modules = new ItemStackHandler(3) { public final ItemStackHandler modules = new ItemStackHandler(3) {
@Override @Override
@ -59,7 +65,7 @@ public class PipeBlockEntity extends BlockEntity implements MenuProvider, IPipeC
var item = stack.getItem(); var item = stack.getItem();
if (!(item instanceof IModule module)) if (!(item instanceof IModule module))
return false; return false;
return PipeBlockEntity.this.streamModules().allMatch(m -> module.isCompatible(stack, PipeBlockEntity.this, m.getRight()) && m.getRight().isCompatible(m.getLeft(), PipeBlockEntity.this, module)); return PipeTileEntity.this.streamModules().allMatch(m -> module.isCompatible(stack, PipeTileEntity.this, m.getRight()) && m.getRight().isCompatible(m.getLeft(), PipeTileEntity.this, module));
} }
@Override @Override
@ -75,13 +81,9 @@ public class PipeBlockEntity extends BlockEntity implements MenuProvider, IPipeC
protected List<IPipeItem> items; protected List<IPipeItem> items;
private int lastItemAmount; private int lastItemAmount;
private int priority; private int priority;
private final LazyOptional<PipeBlockEntity> lazyThis = LazyOptional.of(() -> this); private final LazyOptional<PipeTileEntity> lazyThis = LazyOptional.of(() -> this);
private final Lazy<Integer> workRandomizer = Lazy.of(() -> this.level.random.nextInt(200)); private final Lazy<Integer> workRandomizer = Lazy.of(() -> this.level.random.nextInt(200));
public PipeBlockEntity(BlockPos pos, BlockState state) {
super(Registry.pipeBlockEntity, pos, state);
}
@Override @Override
public void onChunkUnloaded() { public void onChunkUnloaded() {
PipeNetwork.get(this.level).uncachePipe(this.worldPosition); PipeNetwork.get(this.level).uncachePipe(this.worldPosition);
@ -94,9 +96,9 @@ public class PipeBlockEntity extends BlockEntity implements MenuProvider, IPipeC
compound.put("requests", Utility.serializeAll(this.craftIngredientRequests)); compound.put("requests", Utility.serializeAll(this.craftIngredientRequests));
if (this.cover != null) if (this.cover != null)
compound.put("cover", NbtUtils.writeBlockState(this.cover)); compound.put("cover", NbtUtils.writeBlockState(this.cover));
var results = new ListTag(); ListTag results = new ListTag();
for (var triple : this.craftResultRequests) { for (Pair<BlockPos, ItemStack> triple : this.craftResultRequests) {
var nbt = new CompoundTag(); CompoundTag nbt = new CompoundTag();
nbt.putLong("dest_pipe", triple.getLeft().asLong()); nbt.putLong("dest_pipe", triple.getLeft().asLong());
nbt.put("item", triple.getRight().serializeNBT()); nbt.put("item", triple.getRight().serializeNBT());
results.add(nbt); results.add(nbt);
@ -111,11 +113,11 @@ public class PipeBlockEntity extends BlockEntity implements MenuProvider, IPipeC
this.moduleDropCheck = compound.getInt("module_drop_check"); this.moduleDropCheck = compound.getInt("module_drop_check");
this.cover = compound.contains("cover") ? NbtUtils.readBlockState(compound.getCompound("cover")) : null; this.cover = compound.contains("cover") ? NbtUtils.readBlockState(compound.getCompound("cover")) : null;
this.craftIngredientRequests.clear(); this.craftIngredientRequests.clear();
this.craftIngredientRequests.addAll(Utility.deserializeAll(compound.getList("requests", Tag.TAG_COMPOUND), NetworkLock::new)); this.craftIngredientRequests.addAll(Utility.deserializeAll(compound.getList("requests", NBT.TAG_COMPOUND), NetworkLock::new));
this.craftResultRequests.clear(); this.craftResultRequests.clear();
var results = compound.getList("craft_results", Tag.TAG_COMPOUND); ListTag results = compound.getList("craft_results", NBT.TAG_COMPOUND);
for (var i = 0; i < results.size(); i++) { for (int i = 0; i < results.size(); i++) {
var nbt = results.getCompound(i); CompoundTag nbt = results.getCompound(i);
this.craftResultRequests.add(Pair.of( this.craftResultRequests.add(Pair.of(
BlockPos.of(nbt.getLong("dest_pipe")), BlockPos.of(nbt.getLong("dest_pipe")),
ItemStack.of(nbt.getCompound("item")))); ItemStack.of(nbt.getCompound("item"))));
@ -126,27 +128,72 @@ public class PipeBlockEntity extends BlockEntity implements MenuProvider, IPipeC
@Override @Override
public CompoundTag getUpdateTag() { public CompoundTag getUpdateTag() {
// sync pipe items on load // sync pipe items on load
var nbt = this.save(new CompoundTag()); CompoundTag nbt = this.write(new CompoundTag());
nbt.put("items", Utility.serializeAll(this.getItems())); nbt.put("items", Utility.serializeAll(this.getItems()));
return nbt; return nbt;
} }
@Override @Override
public void handleUpdateTag(CompoundTag nbt) { public void handleUpdateTag(BlockState state, CompoundTag nbt) {
this.load(nbt); this.read(state, nbt);
var items = this.getItems(); List<IPipeItem> items = this.getItems();
items.clear(); items.clear();
items.addAll(Utility.deserializeAll(nbt.getList("items", Tag.TAG_COMPOUND), IPipeItem::load)); items.addAll(Utility.deserializeAll(nbt.getList("items", NBT.TAG_COMPOUND), IPipeItem::load));
} }
@Override @Override
public void onDataPacket(Connection net, ClientboundBlockEntityDataPacket pkt) { public void onDataPacket(NetworkManager net, SUpdateTileEntityPacket pkt) {
this.load(pkt.getTag()); this.read(this.getBlockState(), 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();
while (modules.hasNext()) {
Pair<ItemStack, IModule> module = modules.next();
module.getRight().tick(module.getLeft(), this);
prio += module.getRight().getPriority(module.getLeft(), this);
}
if (prio != this.priority) {
this.priority = prio;
// clear the cache so that it's reevaluated based on priority
PipeNetwork.get(this.world).clearDestinationCache(this.pos);
}
profiler.endSection();
}
profiler.startSection("ticking_items");
List<IPipeItem> items = this.getItems();
for (int i = items.size() - 1; i >= 0; i--)
items.get(i).updateInPipe(this);
if (items.size() != this.lastItemAmount) {
this.lastItemAmount = items.size();
this.world.updateComparatorOutputLevel(this.pos, this.getBlockState().getBlock());
}
profiler.endSection();
} }
public List<IPipeItem> getItems() { public List<IPipeItem> getItems() {
if (this.items == null) if (this.items == null)
this.items = PipeNetwork.get(this.level).getItemsInPipe(this.worldPosition); this.items = PipeNetwork.get(this.world).getItemsInPipe(this.pos);
return this.items; return this.items;
} }
@ -159,23 +206,23 @@ public class PipeBlockEntity extends BlockEntity implements MenuProvider, IPipeC
} }
public boolean isConnected(Direction dir) { public boolean isConnected(Direction dir) {
return this.getBlockState().getValue(PipeBlock.DIRECTIONS.get(dir)).isConnected(); return this.getBlockState().get(PipeBlock.DIRECTIONS.get(dir)).isConnected();
} }
public Pair<BlockPos, ItemStack> getAvailableDestinationOrConnectable(ItemStack stack, boolean force, boolean preventOversending) { public Pair<BlockPos, ItemStack> getAvailableDestinationOrConnectable(ItemStack stack, boolean force, boolean preventOversending) {
var dest = this.getAvailableDestination(stack, force, preventOversending); Pair<BlockPos, ItemStack> dest = this.getAvailableDestination(stack, force, preventOversending);
if (dest != null) if (dest != null)
return dest; return dest;
// if there's no available destination, try inserting into terminals etc. // if there's no available destination, try inserting into terminals etc.
for (var dir : Direction.values()) { for (Direction dir : Direction.values()) {
var connectable = this.getPipeConnectable(dir); IPipeConnectable connectable = this.getPipeConnectable(dir);
if (connectable == null) if (connectable == null)
continue; continue;
var connectableRemain = connectable.insertItem(this.worldPosition, dir, stack, true); ItemStack connectableRemain = connectable.insertItem(this.getPos(), dir, stack, true);
if (connectableRemain.getCount() != stack.getCount()) { if (connectableRemain.getCount() != stack.getCount()) {
var inserted = stack.copy(); ItemStack inserted = stack.copy();
inserted.shrink(connectableRemain.getCount()); inserted.shrink(connectableRemain.getCount());
return Pair.of(this.worldPosition.relative(dir), inserted); return Pair.of(this.getPos().offset(dir), inserted);
} }
} }
return null; return null;
@ -186,47 +233,47 @@ public class PipeBlockEntity extends BlockEntity implements MenuProvider, IPipeC
return null; return null;
if (!force && this.streamModules().anyMatch(m -> !m.getRight().canAcceptItem(m.getLeft(), this, stack))) if (!force && this.streamModules().anyMatch(m -> !m.getRight().canAcceptItem(m.getLeft(), this, stack)))
return null; return null;
for (var dir : Direction.values()) { for (Direction dir : Direction.values()) {
var handler = this.getItemHandler(dir); IItemHandler handler = this.getItemHandler(dir);
if (handler == null) if (handler == null)
continue; continue;
var remain = ItemHandlerHelper.insertItem(handler, stack, true); ItemStack remain = ItemHandlerHelper.insertItem(handler, stack, true);
// did we insert anything? // did we insert anything?
if (remain.getCount() == stack.getCount()) if (remain.getCount() == stack.getCount())
continue; continue;
var toInsert = stack.copy(); ItemStack toInsert = stack.copy();
toInsert.shrink(remain.getCount()); toInsert.shrink(remain.getCount());
// limit to the max amount that modules allow us to insert // limit to the max amount that modules allow us to insert
var maxAmount = this.streamModules().mapToInt(m -> m.getRight().getMaxInsertionAmount(m.getLeft(), this, stack, handler)).min().orElse(Integer.MAX_VALUE); int maxAmount = this.streamModules().mapToInt(m -> m.getRight().getMaxInsertionAmount(m.getLeft(), this, stack, handler)).min().orElse(Integer.MAX_VALUE);
if (maxAmount < toInsert.getCount()) if (maxAmount < toInsert.getCount())
toInsert.setCount(maxAmount); toInsert.setCount(maxAmount);
var offset = this.worldPosition.relative(dir); BlockPos offset = this.pos.offset(dir);
if (preventOversending || maxAmount < Integer.MAX_VALUE) { if (preventOversending || maxAmount < Integer.MAX_VALUE) {
var network = PipeNetwork.get(this.level); PipeNetwork network = PipeNetwork.get(this.world);
// these are the items that are currently in the pipes, going to this inventory // these are the items that are currently in the pipes, going to this inventory
var onTheWay = network.getItemsOnTheWay(offset, null); int onTheWay = network.getItemsOnTheWay(offset, null);
if (onTheWay > 0) { if (onTheWay > 0) {
if (maxAmount < Integer.MAX_VALUE) { if (maxAmount < Integer.MAX_VALUE) {
// these are the items on the way, limited to items of the same type as stack // these are the items on the way, limited to items of the same type as stack
var onTheWaySame = network.getItemsOnTheWay(offset, stack); int onTheWaySame = network.getItemsOnTheWay(offset, stack);
// check if any modules are limiting us // check if any modules are limiting us
if (toInsert.getCount() + onTheWaySame > maxAmount) if (toInsert.getCount() + onTheWaySame > maxAmount)
toInsert.setCount(maxAmount - onTheWaySame); toInsert.setCount(maxAmount - onTheWaySame);
} }
// totalSpace will be the amount of items that fit into the attached container // totalSpace will be the amount of items that fit into the attached container
var totalSpace = 0; int totalSpace = 0;
for (var i = 0; i < handler.getSlots(); i++) { for (int i = 0; i < handler.getSlots(); i++) {
var copy = stack.copy(); ItemStack copy = stack.copy();
var maxStackSize = copy.getMaxStackSize(); int maxStackSize = copy.getMaxStackSize();
// if the container can store more than 64 items in this slot, then it's likely // 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 // a barrel or similar, meaning that the slot limit matters more than the max stack size
var limit = handler.getSlotLimit(i); int limit = handler.getSlotLimit(i);
if (limit > 64) if (limit > 64)
maxStackSize = limit; maxStackSize = limit;
copy.setCount(maxStackSize); copy.setCount(maxStackSize);
// this is an inaccurate check since it ignores the fact that some slots might // 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 // have space for items of other types, but it'll be good enough for us
var left = handler.insertItem(i, copy, true); ItemStack left = handler.insertItem(i, copy, true);
totalSpace += maxStackSize - 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 the items on the way plus the items we're trying to move are too much, reduce
@ -246,8 +293,8 @@ public class PipeBlockEntity extends BlockEntity implements MenuProvider, IPipeC
} }
public float getItemSpeed(ItemStack stack) { public float getItemSpeed(ItemStack stack) {
var moduleSpeed = (float) this.streamModules().mapToDouble(m -> m.getRight().getItemSpeedIncrease(m.getLeft(), this)).sum(); float moduleSpeed = (float) this.streamModules().mapToDouble(m -> m.getRight().getItemSpeedIncrease(m.getLeft(), this)).sum();
var pressureSpeed = this.pressurizer != null && this.pressurizer.pressurizeItem(stack, true) ? 0.45F : 0; float pressureSpeed = this.pressurizer != null && this.pressurizer.pressurizeItem(stack, true) ? 0.45F : 0;
return 0.05F + moduleSpeed + pressureSpeed; return 0.05F + moduleSpeed + pressureSpeed;
} }
@ -262,13 +309,13 @@ public class PipeBlockEntity extends BlockEntity implements MenuProvider, IPipeC
} }
public int getCraftableAmount(Consumer<ItemStack> unavailableConsumer, ItemStack stack, Stack<ItemStack> dependencyChain) { public int getCraftableAmount(Consumer<ItemStack> unavailableConsumer, ItemStack stack, Stack<ItemStack> dependencyChain) {
var total = 0; int total = 0;
var modules = this.streamModules().iterator(); Iterator<Pair<ItemStack, IModule>> modules = this.streamModules().iterator();
while (modules.hasNext()) { while (modules.hasNext()) {
var module = modules.next(); Pair<ItemStack, IModule> module = modules.next();
// make sure we don't factor in recursive dependencies like ingot -> block -> ingot etc. // make sure we don't factor in recursive dependencies like ingot -> block -> ingot etc.
if (dependencyChain.stream().noneMatch(d -> ItemEquality.compareItems(module.getLeft(), d, ItemEquality.NBT))) { if (dependencyChain.stream().noneMatch(d -> ItemEquality.compareItems(module.getLeft(), d, ItemEquality.NBT))) {
var amount = module.getRight().getCraftableAmount(module.getLeft(), this, unavailableConsumer, stack, dependencyChain); int amount = module.getRight().getCraftableAmount(module.getLeft(), this, unavailableConsumer, stack, dependencyChain);
if (amount > 0) if (amount > 0)
total += amount; total += amount;
} }
@ -277,9 +324,9 @@ public class PipeBlockEntity extends BlockEntity implements MenuProvider, IPipeC
} }
public ItemStack craft(BlockPos destPipe, Consumer<ItemStack> unavailableConsumer, ItemStack stack, Stack<ItemStack> dependencyChain) { public ItemStack craft(BlockPos destPipe, Consumer<ItemStack> unavailableConsumer, ItemStack stack, Stack<ItemStack> dependencyChain) {
var modules = this.streamModules().iterator(); Iterator<Pair<ItemStack, IModule>> modules = this.streamModules().iterator();
while (modules.hasNext()) { while (modules.hasNext()) {
var module = modules.next(); Pair<ItemStack, IModule> module = modules.next();
stack = module.getRight().craft(module.getLeft(), this, destPipe, unavailableConsumer, stack, dependencyChain); stack = module.getRight().craft(module.getLeft(), this, destPipe, unavailableConsumer, stack, dependencyChain);
if (stack.isEmpty()) if (stack.isEmpty())
break; break;
@ -288,24 +335,24 @@ public class PipeBlockEntity extends BlockEntity implements MenuProvider, IPipeC
} }
public IItemHandler getItemHandler(Direction dir) { public IItemHandler getItemHandler(Direction dir) {
var handler = this.getNeighborCap(dir, CapabilityItemHandler.ITEM_HANDLER_CAPABILITY); IItemHandler handler = this.getNeighborCap(dir, CapabilityItemHandler.ITEM_HANDLER_CAPABILITY);
if (handler != null) if (handler != null)
return handler; return handler;
return Utility.getBlockItemHandler(this.level, this.worldPosition.relative(dir), dir.getOpposite()); return Utility.getBlockItemHandler(this.world, this.pos.offset(dir), dir.getOpposite());
} }
public <T> T getNeighborCap(Direction dir, Capability<T> cap) { public <T> T getNeighborCap(Direction dir, Capability<T> cap) {
if (!this.isConnected(dir)) if (!this.isConnected(dir))
return null; return null;
var pos = this.worldPosition.relative(dir); BlockPos pos = this.pos.offset(dir);
var tile = this.level.getBlockEntity(pos); TileEntity tile = this.world.getTileEntity(pos);
if (tile != null) if (tile != null)
return tile.getCapability(cap, dir.getOpposite()).orElse(null); return tile.getCapability(cap, dir.getOpposite()).orElse(null);
return null; return null;
} }
public IPipeConnectable getPipeConnectable(Direction dir) { public IPipeConnectable getPipeConnectable(Direction dir) {
var tile = this.level.getBlockEntity(this.worldPosition.relative(dir)); TileEntity tile = this.world.getTileEntity(this.pos.offset(dir));
if (tile != null) if (tile != null)
return tile.getCapability(Registry.pipeConnectableCapability, dir.getOpposite()).orElse(null); return tile.getCapability(Registry.pipeConnectableCapability, dir.getOpposite()).orElse(null);
return null; return null;
@ -316,11 +363,11 @@ public class PipeBlockEntity extends BlockEntity implements MenuProvider, IPipeC
} }
public boolean canHaveModules() { public boolean canHaveModules() {
for (var dir : Direction.values()) { for (Direction dir : Direction.values()) {
if (this.isConnectedInventory(dir)) if (this.isConnectedInventory(dir))
return true; return true;
var connectable = this.getPipeConnectable(dir); IPipeConnectable connectable = this.getPipeConnectable(dir);
if (connectable != null && connectable.allowsModules(this.worldPosition, dir)) if (connectable != null && connectable.allowsModules(this.pos, dir))
return true; return true;
} }
return false; return false;
@ -332,8 +379,8 @@ public class PipeBlockEntity extends BlockEntity implements MenuProvider, IPipeC
public Stream<Pair<ItemStack, IModule>> streamModules() { public Stream<Pair<ItemStack, IModule>> streamModules() {
Stream.Builder<Pair<ItemStack, IModule>> builder = Stream.builder(); Stream.Builder<Pair<ItemStack, IModule>> builder = Stream.builder();
for (var i = 0; i < this.modules.getSlots(); i++) { for (int i = 0; i < this.modules.getSlots(); i++) {
var stack = this.modules.getStackInSlot(i); ItemStack stack = this.modules.getStackInSlot(i);
if (stack.isEmpty()) if (stack.isEmpty())
continue; continue;
builder.accept(Pair.of(stack, (IModule) stack.getItem())); builder.accept(Pair.of(stack, (IModule) stack.getItem()));
@ -341,17 +388,17 @@ public class PipeBlockEntity extends BlockEntity implements MenuProvider, IPipeC
return builder.build(); return builder.build();
} }
public void removeCover(Player player, InteractionHand hand) { public void removeCover(PlayerEntity player, Hand hand) {
if (this.level.isClientSide) if (this.world.isRemote)
return; return;
var drops = Block.getDrops(this.cover, (ServerLevel) this.level, this.worldPosition, null, player, player.getItemInHand(hand)); List<ItemStack> drops = Block.getDrops(this.cover, (ServerWorld) this.world, this.pos, null, player, player.getHeldItem(hand));
for (var drop : drops) for (ItemStack drop : drops)
Containers.dropItemStack(this.level, this.worldPosition.getX(), this.worldPosition.getY(), this.worldPosition.getZ(), drop); Block.spawnAsEntity(this.world, this.pos, drop);
this.cover = null; this.cover = null;
} }
public boolean shouldWorkNow(int speed) { public boolean shouldWorkNow(int speed) {
return (this.level.getGameTime() + this.workRandomizer.get()) % speed == 0; return (this.world.getGameTime() + this.workRandomizer.get()) % speed == 0;
} }
public int getNextNode(List<BlockPos> nodes, int index) { public int getNextNode(List<BlockPos> nodes, int index) {
@ -367,31 +414,31 @@ public class PipeBlockEntity extends BlockEntity implements MenuProvider, IPipeC
} }
@Override @Override
public void setRemoved() { public void remove() {
super.setRemoved(); super.remove();
this.getItems().clear(); this.getItems().clear();
var network = PipeNetwork.get(this.level); PipeNetwork network = PipeNetwork.get(this.world);
for (var lock : this.craftIngredientRequests) for (NetworkLock lock : this.craftIngredientRequests)
network.resolveNetworkLock(lock); network.resolveNetworkLock(lock);
this.lazyThis.invalidate(); this.lazyThis.invalidate();
} }
@Override @Override
public Component getDisplayName() { public ITextComponent getDisplayName() {
return new TranslatableComponent("container." + PrettyPipes.ID + ".pipe"); return new TranslationTextComponent("container." + PrettyPipes.ID + ".pipe");
} }
@Nullable @Nullable
@Override @Override
public AbstractContainerMenu createMenu(int window, Inventory inv, Player player) { public Container createMenu(int window, PlayerInventory inv, PlayerEntity player) {
return new MainPipeContainer(Registry.pipeContainer, window, player, PipeBlockEntity.this.worldPosition); return new MainPipeContainer(Registry.pipeContainer, window, player, PipeTileEntity.this.pos);
} }
@Override @Override
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
public AABB getRenderBoundingBox() { public AxisAlignedBB getRenderBoundingBox() {
// our render bounding box should always be the full block in case we're covered // our render bounding box should always be the full block in case we're covered
return new AABB(this.worldPosition); return new AxisAlignedBB(this.pos);
} }
@Override @Override
@ -403,54 +450,9 @@ public class PipeBlockEntity extends BlockEntity implements MenuProvider, IPipeC
@Override @Override
public ConnectionType getConnectionType(BlockPos pipePos, Direction direction) { public ConnectionType getConnectionType(BlockPos pipePos, Direction direction) {
var state = this.level.getBlockState(pipePos.relative(direction)); BlockState state = this.world.getBlockState(pipePos.offset(direction));
if (state.getValue(PipeBlock.DIRECTIONS.get(direction.getOpposite())) == ConnectionType.BLOCKED) if (state.get(PipeBlock.DIRECTIONS.get(direction.getOpposite())) == ConnectionType.BLOCKED)
return ConnectionType.BLOCKED; return ConnectionType.BLOCKED;
return ConnectionType.CONNECTED; return ConnectionType.CONNECTED;
} }
public static void tick(Level level, BlockPos pos, BlockState state, PipeBlockEntity pipe) {
// invalidate our pressurizer reference if it was removed
if (pipe.pressurizer != null && pipe.pressurizer.isRemoved())
pipe.pressurizer = null;
if (!pipe.level.isAreaLoaded(pipe.worldPosition, 1))
return;
var profiler = pipe.level.getProfiler();
if (!pipe.level.isClientSide) {
// drop modules here to give a bit of time for blocks to update (iron -> gold chest etc.)
if (pipe.moduleDropCheck > 0) {
pipe.moduleDropCheck--;
if (pipe.moduleDropCheck <= 0 && !pipe.canHaveModules())
Utility.dropInventory(pipe, pipe.modules);
}
profiler.push("ticking_modules");
var prio = 0;
var modules = pipe.streamModules().iterator();
while (modules.hasNext()) {
var module = modules.next();
module.getRight().tick(module.getLeft(), pipe);
prio += module.getRight().getPriority(module.getLeft(), pipe);
}
if (prio != pipe.priority) {
pipe.priority = prio;
// clear the cache so that it's reevaluated based on priority
PipeNetwork.get(pipe.level).clearDestinationCache(pipe.worldPosition);
}
profiler.pop();
}
profiler.push("ticking_items");
var items = pipe.getItems();
for (var i = items.size() - 1; i >= 0; i--)
items.get(i).updateInPipe(pipe);
if (items.size() != pipe.lastItemAmount) {
pipe.lastItemAmount = items.size();
pipe.level.updateNeighbourForOutputSignal(pipe.worldPosition, pipe.getBlockState().getBlock());
}
profiler.pop();
}
} }

View file

@ -3,28 +3,28 @@ package de.ellpeck.prettypipes.pipe.containers;
import de.ellpeck.prettypipes.Utility; import de.ellpeck.prettypipes.Utility;
import de.ellpeck.prettypipes.items.IModule; import de.ellpeck.prettypipes.items.IModule;
import de.ellpeck.prettypipes.misc.FilterSlot; import de.ellpeck.prettypipes.misc.FilterSlot;
import de.ellpeck.prettypipes.pipe.PipeBlockEntity; import de.ellpeck.prettypipes.pipe.PipeTileEntity;
import net.minecraft.core.BlockPos; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.world.entity.player.Player; import net.minecraft.inventory.container.ClickType;
import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.inventory.container.Container;
import net.minecraft.world.inventory.ClickType; import net.minecraft.inventory.container.ContainerType;
import net.minecraft.world.inventory.MenuType; import net.minecraft.inventory.container.Slot;
import net.minecraft.world.inventory.Slot;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.util.math.BlockPos;
import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.lang3.tuple.Pair;
import javax.annotation.Nullable; import javax.annotation.Nullable;
public abstract class AbstractPipeContainer<T extends IModule> extends AbstractContainerMenu { public abstract class AbstractPipeContainer<T extends IModule> extends Container {
public final PipeBlockEntity tile; public final PipeTileEntity tile;
public final T module; public final T module;
public final int moduleIndex; public final int moduleIndex;
public final ItemStack moduleStack; public final ItemStack moduleStack;
public AbstractPipeContainer(@Nullable MenuType<?> type, int id, Player player, BlockPos pos, int moduleIndex) { public AbstractPipeContainer(@Nullable ContainerType<?> type, int id, PlayerEntity player, BlockPos pos, int moduleIndex) {
super(type, id); super(type, id);
this.tile = Utility.getBlockEntity(PipeBlockEntity.class, player.level, pos); this.tile = Utility.getBlockEntity(PipeTileEntity.class, player.world, pos);
this.moduleStack = moduleIndex < 0 ? null : this.tile.modules.getStackInSlot(moduleIndex); this.moduleStack = moduleIndex < 0 ? null : this.tile.modules.getStackInSlot(moduleIndex);
this.module = moduleIndex < 0 ? null : (T) this.moduleStack.getItem(); this.module = moduleIndex < 0 ? null : (T) this.moduleStack.getItem();
this.moduleIndex = moduleIndex; this.moduleIndex = moduleIndex;
@ -32,18 +32,23 @@ public abstract class AbstractPipeContainer<T extends IModule> extends AbstractC
// needs to be done here so transferStackInSlot works correctly, bleh // needs to be done here so transferStackInSlot works correctly, bleh
this.addSlots(); this.addSlots();
for (var l = 0; l < 3; ++l) for (int l = 0; l < 3; ++l)
for (var j1 = 0; j1 < 9; ++j1) for (int j1 = 0; j1 < 9; ++j1)
this.addSlot(new Slot(player.getInventory(), j1 + l * 9 + 9, 8 + j1 * 18, 89 + l * 18 + 32)); this.addSlot(new Slot(player.inventory, j1 + l * 9 + 9, 8 + j1 * 18, 89 + l * 18 + 32));
for (var i1 = 0; i1 < 9; ++i1) for (int i1 = 0; i1 < 9; ++i1)
this.addSlot(new Slot(player.getInventory(), i1, 8 + i1 * 18, 147 + 32)); this.addSlot(new Slot(player.inventory, i1, 8 + i1 * 18, 147 + 32));
} }
protected abstract void addSlots(); protected abstract void addSlots();
@Override @Override
public ItemStack quickMoveStack(Player player, int slotIndex) { public boolean canInteractWith(PlayerEntity playerIn) {
return Utility.transferStackInSlot(this, this::moveItemStackTo, player, slotIndex, stack -> { return true;
}
@Override
public ItemStack transferStackInSlot(PlayerEntity player, int slotIndex) {
return Utility.transferStackInSlot(this, this::mergeItemStack, player, slotIndex, stack -> {
if (stack.getItem() instanceof IModule) if (stack.getItem() instanceof IModule)
return Pair.of(0, 3); return Pair.of(0, 3);
return null; return null;
@ -51,14 +56,9 @@ public abstract class AbstractPipeContainer<T extends IModule> extends AbstractC
} }
@Override @Override
public void clicked(int slotId, int dragType, ClickType clickTypeIn, Player player) { public ItemStack slotClick(int slotId, int dragType, ClickType clickTypeIn, PlayerEntity player) {
if (FilterSlot.checkFilter(this, slotId, player)) if (FilterSlot.checkFilter(this, slotId, player))
return; return ItemStack.EMPTY;
super.clicked(slotId, dragType, clickTypeIn, player); return super.slotClick(slotId, dragType, clickTypeIn, player);
}
@Override
public boolean stillValid(Player player) {
return true;
} }
} }

View file

@ -1,34 +1,34 @@
package de.ellpeck.prettypipes.pipe.containers; package de.ellpeck.prettypipes.pipe.containers;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.matrix.MatrixStack;
import de.ellpeck.prettypipes.PrettyPipes; import de.ellpeck.prettypipes.PrettyPipes;
import de.ellpeck.prettypipes.Registry; import de.ellpeck.prettypipes.Registry;
import de.ellpeck.prettypipes.items.IModule; import de.ellpeck.prettypipes.items.IModule;
import de.ellpeck.prettypipes.packets.PacketButton; import de.ellpeck.prettypipes.packets.PacketButton;
import de.ellpeck.prettypipes.packets.PacketHandler; import de.ellpeck.prettypipes.packets.PacketHandler;
import net.minecraft.client.gui.components.AbstractWidget; import net.minecraft.client.audio.SimpleSound;
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; import net.minecraft.client.gui.screen.inventory.ContainerScreen;
import net.minecraft.client.resources.sounds.SimpleSoundInstance; import net.minecraft.client.gui.widget.Widget;
import net.minecraft.network.chat.Component; import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.resources.ResourceLocation; import net.minecraft.inventory.container.Slot;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraftforge.items.SlotItemHandler; import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.SoundEvents;
import net.minecraft.util.text.ITextComponent;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
public abstract class AbstractPipeGui<T extends AbstractPipeContainer<?>> extends AbstractContainerScreen<T> { public abstract class AbstractPipeGui<T extends AbstractPipeContainer<?>> extends ContainerScreen<T> {
protected 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 List<Tab> tabs = new ArrayList<>();
private final ItemStack[] lastItems = new ItemStack[this.menu.tile.modules.getSlots()]; private final ItemStack[] lastItems = new ItemStack[this.container.tile.modules.getSlots()];
public AbstractPipeGui(T screenContainer, Inventory inv, Component titleIn) { public AbstractPipeGui(T screenContainer, PlayerInventory inv, ITextComponent titleIn) {
super(screenContainer, inv, titleIn); super(screenContainer, inv, titleIn);
this.imageWidth = 176; this.xSize = 176;
this.imageHeight = 171 + 32; this.ySize = 171 + 32;
} }
@Override @Override
@ -38,12 +38,12 @@ public abstract class AbstractPipeGui<T extends AbstractPipeContainer<?>> extend
} }
@Override @Override
public void containerTick() { public void tick() {
super.containerTick(); super.tick();
var changed = false; boolean changed = false;
for (var i = 0; i < this.menu.tile.modules.getSlots(); i++) { for (int i = 0; i < this.container.tile.modules.getSlots(); i++) {
var stack = this.menu.tile.modules.getStackInSlot(i); ItemStack stack = this.container.tile.modules.getStackInSlot(i);
if (stack != this.lastItems[i]) { if (stack != this.lastItems[i]) {
this.lastItems[i] = stack; this.lastItems[i] = stack;
changed = true; changed = true;
@ -54,44 +54,43 @@ public abstract class AbstractPipeGui<T extends AbstractPipeContainer<?>> extend
} }
@Override @Override
public void render(PoseStack matrix, int mouseX, int mouseY, float partialTicks) { public void render(MatrixStack matrix, int mouseX, int mouseY, float partialTicks) {
this.renderBackground(matrix); this.renderBackground(matrix);
super.render(matrix, mouseX, mouseY, partialTicks); super.render(matrix, mouseX, mouseY, partialTicks);
for (var widget : this.renderables) { for (Widget widget : this.buttons) {
if (widget instanceof AbstractWidget abstractWidget) { if (widget.isHovered())
if (abstractWidget.isHoveredOrFocused()) widget.renderToolTip(matrix, mouseX, mouseY);
abstractWidget.renderToolTip(matrix, mouseX, mouseY);
}
} }
this.renderTooltip(matrix, mouseX, mouseY); this.func_230459_a_(matrix, mouseX, mouseY);
} }
@Override @Override
protected void renderLabels(PoseStack matrix, int mouseX, int mouseY) { protected void drawGuiContainerForegroundLayer(MatrixStack matrix, int mouseX, int mouseY) {
this.font.draw(matrix, this.playerInventoryTitle.getString(), 8, this.imageHeight - 96 + 2, 4210752); this.font.drawString(matrix, this.playerInventory.getDisplayName().getString(), 8, this.ySize - 96 + 2, 4210752);
this.font.draw(matrix, this.title.getString(), 8, 6 + 32, 4210752); this.font.drawString(matrix, this.title.getString(), 8, 6 + 32, 4210752);
for (var tab : this.tabs) for (Tab tab : this.tabs)
tab.drawForeground(matrix, mouseX, mouseY); tab.drawForeground(matrix, mouseX, mouseY);
} }
@Override @Override
protected void renderBg(PoseStack matrix, float partialTicks, int mouseX, int mouseY) { protected void drawGuiContainerBackgroundLayer(MatrixStack matrix, float partialTicks, int mouseX, int mouseY) {
this.getMinecraft().getTextureManager().bindForSetup(TEXTURE); this.getMinecraft().getTextureManager().bindTexture(TEXTURE);
this.blit(matrix, this.leftPos, this.topPos + 32, 0, 0, 176, 171); this.blit(matrix, this.guiLeft, this.guiTop + 32, 0, 0, 176, 171);
for (var tab : this.tabs) for (Tab tab : this.tabs)
tab.draw(matrix); tab.draw(matrix);
// draw the slots since we're using a blank ui // draw the slots since we're using a blank ui
for (var slot : this.menu.slots) { for (Slot slot : this.container.inventorySlots) {
if (slot instanceof SlotItemHandler) if (slot.inventory == this.playerInventory)
this.blit(matrix, this.leftPos + slot.x - 1, this.topPos + slot.y - 1, 176, 62, 18, 18); continue;
this.blit(matrix, this.guiLeft + slot.xPos - 1, this.guiTop + slot.yPos - 1, 176, 62, 18, 18);
} }
} }
@Override @Override
public boolean mouseClicked(double x, double y, int button) { public boolean mouseClicked(double x, double y, int button) {
for (var tab : this.tabs) { for (Tab tab : this.tabs) {
if (tab.onClicked(x, y, button)) if (tab.onClicked(x, y, button))
return true; return true;
} }
@ -101,18 +100,17 @@ public abstract class AbstractPipeGui<T extends AbstractPipeContainer<?>> extend
private void initTabs() { private void initTabs() {
this.tabs.clear(); this.tabs.clear();
this.tabs.add(new Tab(new ItemStack(Registry.pipeBlock), 0, -1)); this.tabs.add(new Tab(new ItemStack(Registry.pipeBlock), 0, -1));
for (var i = 0; i < this.menu.tile.modules.getSlots(); i++) { for (int i = 0; i < this.container.tile.modules.getSlots(); i++) {
var stack = this.menu.tile.modules.getStackInSlot(i); ItemStack stack = this.container.tile.modules.getStackInSlot(i);
if (stack.isEmpty()) if (stack.isEmpty())
continue; continue;
var module = (IModule) stack.getItem(); IModule module = (IModule) stack.getItem();
if (module.hasContainer(stack, this.menu.tile)) if (module.hasContainer(stack, this.container.tile))
this.tabs.add(new Tab(stack, this.tabs.size(), i)); this.tabs.add(new Tab(stack, this.tabs.size(), i));
} }
} }
private class Tab { private class Tab {
private final ItemStack moduleStack; private final ItemStack moduleStack;
private final int index; private final int index;
private final int x; private final int x;
@ -121,16 +119,16 @@ public abstract class AbstractPipeGui<T extends AbstractPipeContainer<?>> extend
public Tab(ItemStack moduleStack, int tabIndex, int index) { public Tab(ItemStack moduleStack, int tabIndex, int index) {
this.moduleStack = moduleStack; this.moduleStack = moduleStack;
this.index = index; this.index = index;
this.x = AbstractPipeGui.this.leftPos + 5 + tabIndex * 28; this.x = AbstractPipeGui.this.guiLeft + 5 + tabIndex * 28;
this.y = AbstractPipeGui.this.topPos; this.y = AbstractPipeGui.this.guiTop;
} }
private void draw(PoseStack matrix) { private void draw(MatrixStack matrix) {
var y = 2; int y = 2;
var v = 0; int v = 0;
var height = 30; int height = 30;
var itemOffset = 9; int itemOffset = 9;
if (this.index == AbstractPipeGui.this.menu.moduleIndex) { if (this.index == AbstractPipeGui.this.container.moduleIndex) {
y = 0; y = 0;
v = 30; v = 30;
height = 32; height = 32;
@ -138,25 +136,25 @@ public abstract class AbstractPipeGui<T extends AbstractPipeContainer<?>> extend
} }
AbstractPipeGui.this.blit(matrix, this.x, this.y + y, 176, v, 28, height); AbstractPipeGui.this.blit(matrix, this.x, this.y + y, 176, v, 28, height);
AbstractPipeGui.this.itemRenderer.renderGuiItem(this.moduleStack, this.x + 6, this.y + itemOffset); AbstractPipeGui.this.itemRenderer.renderItemIntoGUI(this.moduleStack, this.x + 6, this.y + itemOffset);
AbstractPipeGui.this.getMinecraft().getTextureManager().bindForSetup(TEXTURE); AbstractPipeGui.this.getMinecraft().getTextureManager().bindTexture(TEXTURE);
} }
private void drawForeground(PoseStack matrix, int mouseX, int mouseY) { private void drawForeground(MatrixStack matrix, int mouseX, int mouseY) {
if (mouseX < this.x || mouseY < this.y || mouseX >= this.x + 28 || mouseY >= this.y + 32) if (mouseX < this.x || mouseY < this.y || mouseX >= this.x + 28 || mouseY >= this.y + 32)
return; return;
AbstractPipeGui.this.renderTooltip(matrix, this.moduleStack.getDisplayName(), mouseX - AbstractPipeGui.this.leftPos, mouseY - AbstractPipeGui.this.topPos); AbstractPipeGui.this.renderTooltip(matrix, this.moduleStack.getDisplayName(), mouseX - AbstractPipeGui.this.guiLeft, mouseY - AbstractPipeGui.this.guiTop);
} }
private boolean onClicked(double mouseX, double mouseY, int button) { private boolean onClicked(double mouseX, double mouseY, int button) {
if (this.index == AbstractPipeGui.this.menu.moduleIndex) if (this.index == AbstractPipeGui.this.container.moduleIndex)
return false; return false;
if (button != 0) if (button != 0)
return false; return false;
if (mouseX < this.x || mouseY < this.y || mouseX >= this.x + 28 || mouseY >= this.y + 32) if (mouseX < this.x || mouseY < this.y || mouseX >= this.x + 28 || mouseY >= this.y + 32)
return false; return false;
PacketHandler.sendToServer(new PacketButton(AbstractPipeGui.this.menu.tile.getBlockPos(), PacketButton.ButtonResult.PIPE_TAB, this.index)); PacketHandler.sendToServer(new PacketButton(AbstractPipeGui.this.container.tile.getPos(), PacketButton.ButtonResult.PIPE_TAB, this.index));
AbstractPipeGui.this.getMinecraft().getSoundManager().play(SimpleSoundInstance.forUI(SoundEvents.UI_BUTTON_CLICK, 1)); AbstractPipeGui.this.getMinecraft().getSoundHandler().play(SimpleSound.master(SoundEvents.UI_BUTTON_CLICK, 1));
return true; return true;
} }
} }

View file

@ -1,22 +1,21 @@
package de.ellpeck.prettypipes.pipe.containers; package de.ellpeck.prettypipes.pipe.containers;
import de.ellpeck.prettypipes.items.IModule; import de.ellpeck.prettypipes.items.IModule;
import net.minecraft.core.BlockPos; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.world.entity.player.Player; import net.minecraft.inventory.container.ContainerType;
import net.minecraft.world.inventory.MenuType; import net.minecraft.util.math.BlockPos;
import net.minecraftforge.items.SlotItemHandler; import net.minecraftforge.items.SlotItemHandler;
import javax.annotation.Nullable; import javax.annotation.Nullable;
public class MainPipeContainer extends AbstractPipeContainer<IModule> { public class MainPipeContainer extends AbstractPipeContainer<IModule> {
public MainPipeContainer(@Nullable ContainerType<?> type, int id, PlayerEntity player, BlockPos pos) {
public MainPipeContainer(@Nullable MenuType<?> type, int id, Player player, BlockPos pos) {
super(type, id, player, pos, -1); super(type, id, player, pos, -1);
} }
@Override @Override
protected void addSlots() { protected void addSlots() {
for (var i = 0; i < 3; i++) for (int i = 0; i < 3; i++)
this.addSlot(new SlotItemHandler(this.tile.modules, i, 62 + i * 18, 17 + 32)); this.addSlot(new SlotItemHandler(this.tile.modules, i, 62 + i * 18, 17 + 32));
} }
} }

View file

@ -1,11 +1,10 @@
package de.ellpeck.prettypipes.pipe.containers; package de.ellpeck.prettypipes.pipe.containers;
import net.minecraft.network.chat.Component; import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.world.entity.player.Inventory; import net.minecraft.util.text.ITextComponent;
public class MainPipeGui extends AbstractPipeGui<MainPipeContainer> { public class MainPipeGui extends AbstractPipeGui<MainPipeContainer> {
public MainPipeGui(MainPipeContainer screenContainer, PlayerInventory inv, ITextComponent titleIn) {
public MainPipeGui(MainPipeContainer screenContainer, Inventory inv, Component titleIn) {
super(screenContainer, inv, titleIn); super(screenContainer, inv, titleIn);
} }
} }

View file

@ -3,7 +3,7 @@ package de.ellpeck.prettypipes.pipe.modules;
import de.ellpeck.prettypipes.items.IModule; import de.ellpeck.prettypipes.items.IModule;
import de.ellpeck.prettypipes.items.ModuleItem; import de.ellpeck.prettypipes.items.ModuleItem;
import de.ellpeck.prettypipes.items.ModuleTier; import de.ellpeck.prettypipes.items.ModuleTier;
import de.ellpeck.prettypipes.pipe.PipeBlockEntity; import de.ellpeck.prettypipes.pipe.PipeTileEntity;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
public class HighPriorityModuleItem extends ModuleItem { public class HighPriorityModuleItem extends ModuleItem {
@ -15,17 +15,17 @@ public class HighPriorityModuleItem extends ModuleItem {
} }
@Override @Override
public int getPriority(ItemStack module, PipeBlockEntity tile) { public int getPriority(ItemStack module, PipeTileEntity tile) {
return this.priority; return this.priority;
} }
@Override @Override
public boolean isCompatible(ItemStack module, PipeBlockEntity tile, IModule other) { public boolean isCompatible(ItemStack module, PipeTileEntity tile, IModule other) {
return !(other instanceof HighPriorityModuleItem) && !(other instanceof LowPriorityModuleItem); return !(other instanceof HighPriorityModuleItem) && !(other instanceof LowPriorityModuleItem);
} }
@Override @Override
public boolean hasContainer(ItemStack module, PipeBlockEntity tile) { public boolean hasContainer(ItemStack module, PipeTileEntity tile) {
return false; return false;
} }
} }

View file

@ -3,7 +3,7 @@ package de.ellpeck.prettypipes.pipe.modules;
import de.ellpeck.prettypipes.items.IModule; import de.ellpeck.prettypipes.items.IModule;
import de.ellpeck.prettypipes.items.ModuleItem; import de.ellpeck.prettypipes.items.ModuleItem;
import de.ellpeck.prettypipes.items.ModuleTier; import de.ellpeck.prettypipes.items.ModuleTier;
import de.ellpeck.prettypipes.pipe.PipeBlockEntity; import de.ellpeck.prettypipes.pipe.PipeTileEntity;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
public class LowPriorityModuleItem extends ModuleItem { public class LowPriorityModuleItem extends ModuleItem {
@ -15,17 +15,17 @@ public class LowPriorityModuleItem extends ModuleItem {
} }
@Override @Override
public int getPriority(ItemStack module, PipeBlockEntity tile) { public int getPriority(ItemStack module, PipeTileEntity tile) {
return this.priority; return this.priority;
} }
@Override @Override
public boolean isCompatible(ItemStack module, PipeBlockEntity tile, IModule other) { public boolean isCompatible(ItemStack module, PipeTileEntity tile, IModule other) {
return !(other instanceof LowPriorityModuleItem) && !(other instanceof HighPriorityModuleItem); return !(other instanceof LowPriorityModuleItem) && !(other instanceof HighPriorityModuleItem);
} }
@Override @Override
public boolean hasContainer(ItemStack module, PipeBlockEntity tile) { public boolean hasContainer(ItemStack module, PipeTileEntity tile) {
return false; return false;
} }
} }

View file

@ -2,7 +2,7 @@ package de.ellpeck.prettypipes.pipe.modules;
import de.ellpeck.prettypipes.items.IModule; import de.ellpeck.prettypipes.items.IModule;
import de.ellpeck.prettypipes.items.ModuleItem; import de.ellpeck.prettypipes.items.ModuleItem;
import de.ellpeck.prettypipes.pipe.PipeBlockEntity; import de.ellpeck.prettypipes.pipe.PipeTileEntity;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
public class RedstoneModuleItem extends ModuleItem { public class RedstoneModuleItem extends ModuleItem {
@ -13,17 +13,17 @@ public class RedstoneModuleItem extends ModuleItem {
} }
@Override @Override
public boolean canPipeWork(ItemStack module, PipeBlockEntity tile) { public boolean canPipeWork(ItemStack module, PipeTileEntity tile) {
return !tile.getLevel().hasNeighborSignal(tile.getBlockPos()); return !tile.getWorld().isBlockPowered(tile.getPos());
} }
@Override @Override
public boolean isCompatible(ItemStack module, PipeBlockEntity tile, IModule other) { public boolean isCompatible(ItemStack module, PipeTileEntity tile, IModule other) {
return other != this; return other != this;
} }
@Override @Override
public boolean hasContainer(ItemStack module, PipeBlockEntity tile) { public boolean hasContainer(ItemStack module, PipeTileEntity tile) {
return false; return false;
} }
} }

View file

@ -2,9 +2,9 @@ package de.ellpeck.prettypipes.pipe.modules;
import de.ellpeck.prettypipes.items.IModule; import de.ellpeck.prettypipes.items.IModule;
import de.ellpeck.prettypipes.items.ModuleItem; import de.ellpeck.prettypipes.items.ModuleItem;
import de.ellpeck.prettypipes.pipe.PipeBlockEntity; import de.ellpeck.prettypipes.pipe.PipeTileEntity;
import net.minecraft.core.BlockPos;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.util.math.BlockPos;
import java.util.List; import java.util.List;
@ -19,25 +19,25 @@ public class SortingModuleItem extends ModuleItem {
} }
@Override @Override
public boolean isCompatible(ItemStack module, PipeBlockEntity tile, IModule other) { public boolean isCompatible(ItemStack module, PipeTileEntity tile, IModule other) {
return !(other instanceof SortingModuleItem); return !(other instanceof SortingModuleItem);
} }
@Override @Override
public boolean hasContainer(ItemStack module, PipeBlockEntity tile) { public boolean hasContainer(ItemStack module, PipeTileEntity tile) {
return false; return false;
} }
@Override @Override
public Integer getCustomNextNode(ItemStack module, PipeBlockEntity tile, List<BlockPos> nodes, int index) { public Integer getCustomNextNode(ItemStack module, PipeTileEntity tile, List<BlockPos> nodes, int index) {
switch (this.type) { switch (this.type) {
case ROUND_ROBIN: case ROUND_ROBIN:
// store an ever-increasing index and choose destinations based on that // store an ever-increasing index and choose destinations based on that
var next = module.hasTag() ? module.getTag().getInt("last") + 1 : 0; int next = module.hasTag() ? module.getTag().getInt("last") + 1 : 0;
module.getOrCreateTag().putInt("last", next); module.getOrCreateTag().putInt("last", next);
return next % nodes.size(); return next % nodes.size();
case RANDOM: case RANDOM:
return tile.getLevel().random.nextInt(nodes.size()); return tile.getWorld().rand.nextInt(nodes.size());
} }
return null; return null;
} }

View file

@ -3,7 +3,7 @@ package de.ellpeck.prettypipes.pipe.modules;
import de.ellpeck.prettypipes.items.IModule; import de.ellpeck.prettypipes.items.IModule;
import de.ellpeck.prettypipes.items.ModuleItem; import de.ellpeck.prettypipes.items.ModuleItem;
import de.ellpeck.prettypipes.items.ModuleTier; import de.ellpeck.prettypipes.items.ModuleTier;
import de.ellpeck.prettypipes.pipe.PipeBlockEntity; import de.ellpeck.prettypipes.pipe.PipeTileEntity;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
public class SpeedModuleItem extends ModuleItem { public class SpeedModuleItem extends ModuleItem {
@ -15,17 +15,17 @@ public class SpeedModuleItem extends ModuleItem {
} }
@Override @Override
public boolean isCompatible(ItemStack module, PipeBlockEntity tile, IModule other) { public boolean isCompatible(ItemStack module, PipeTileEntity tile, IModule other) {
return !(other instanceof SpeedModuleItem); return !(other instanceof SpeedModuleItem);
} }
@Override @Override
public boolean hasContainer(ItemStack module, PipeBlockEntity tile) { public boolean hasContainer(ItemStack module, PipeTileEntity tile) {
return false; return false;
} }
@Override @Override
public float getItemSpeedIncrease(ItemStack module, PipeBlockEntity tile) { public float getItemSpeedIncrease(ItemStack module, PipeTileEntity tile) {
return this.speedIncrease; return this.speedIncrease;
} }
} }

View file

@ -2,9 +2,9 @@ package de.ellpeck.prettypipes.pipe.modules.craft;
import de.ellpeck.prettypipes.misc.FilterSlot; import de.ellpeck.prettypipes.misc.FilterSlot;
import de.ellpeck.prettypipes.pipe.containers.AbstractPipeContainer; import de.ellpeck.prettypipes.pipe.containers.AbstractPipeContainer;
import net.minecraft.core.BlockPos; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.world.entity.player.Player; import net.minecraft.inventory.container.ContainerType;
import net.minecraft.world.inventory.MenuType; import net.minecraft.util.math.BlockPos;
import net.minecraftforge.items.ItemStackHandler; import net.minecraftforge.items.ItemStackHandler;
public class CraftingModuleContainer extends AbstractPipeContainer<CraftingModuleItem> { public class CraftingModuleContainer extends AbstractPipeContainer<CraftingModuleItem> {
@ -13,30 +13,29 @@ public class CraftingModuleContainer extends AbstractPipeContainer<CraftingModul
public ItemStackHandler output; public ItemStackHandler output;
public boolean modified; public boolean modified;
public CraftingModuleContainer(MenuType<?> type, int id, Player player, BlockPos pos, int moduleIndex) { public CraftingModuleContainer(ContainerType<?> type, int id, PlayerEntity player, BlockPos pos, int moduleIndex) {
super(type, id, player, pos, moduleIndex); super(type, id, player, pos, moduleIndex);
} }
@Override @Override
protected void addSlots() { protected void addSlots() {
this.input = this.module.getInput(this.moduleStack); this.input = this.module.getInput(this.moduleStack);
for (var i = 0; i < this.input.getSlots(); i++) { 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) { this.addSlot(new FilterSlot(this.input, i, (176 - this.module.inputSlots * 18) / 2 + 1 + i % 9 * 18, 17 + 32 + i / 9 * 18, false) {
@Override @Override
public void setChanged() { public void onSlotChanged() {
super.setChanged(); super.onSlotChanged();
CraftingModuleContainer.this.modified = true; CraftingModuleContainer.this.modified = true;
} }
}); });
} }
this.output = this.module.getOutput(this.moduleStack); this.output = this.module.getOutput(this.moduleStack);
for (var i = 0; i < this.output.getSlots(); i++) { 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) { this.addSlot(new FilterSlot(this.output, i, (176 - this.module.outputSlots * 18) / 2 + 1 + i % 9 * 18, 85 + i / 9 * 18, false) {
@Override @Override
public void setChanged() { public void onSlotChanged() {
super.setChanged(); super.onSlotChanged();
CraftingModuleContainer.this.modified = true; CraftingModuleContainer.this.modified = true;
} }
}); });
@ -44,8 +43,8 @@ public class CraftingModuleContainer extends AbstractPipeContainer<CraftingModul
} }
@Override @Override
public void removed(Player playerIn) { public void onContainerClosed(PlayerEntity playerIn) {
super.removed(playerIn); super.onContainerClosed(playerIn);
if (this.modified) if (this.modified)
this.module.save(this.input, this.output, this.moduleStack); this.module.save(this.input, this.output, this.moduleStack);
} }

View file

@ -1,20 +1,19 @@
package de.ellpeck.prettypipes.pipe.modules.craft; package de.ellpeck.prettypipes.pipe.modules.craft;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.matrix.MatrixStack;
import de.ellpeck.prettypipes.pipe.containers.AbstractPipeGui; import de.ellpeck.prettypipes.pipe.containers.AbstractPipeGui;
import net.minecraft.network.chat.Component; import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.world.entity.player.Inventory; import net.minecraft.util.text.ITextComponent;
public class CraftingModuleGui extends AbstractPipeGui<CraftingModuleContainer> { public class CraftingModuleGui extends AbstractPipeGui<CraftingModuleContainer> {
public CraftingModuleGui(CraftingModuleContainer screenContainer, PlayerInventory inv, ITextComponent titleIn) {
public CraftingModuleGui(CraftingModuleContainer screenContainer, Inventory inv, Component titleIn) {
super(screenContainer, inv, titleIn); super(screenContainer, inv, titleIn);
} }
@Override @Override
protected void renderBg(PoseStack matrix, float partialTicks, int mouseX, int mouseY) { protected void drawGuiContainerBackgroundLayer(MatrixStack matrix, float partialTicks, int mouseX, int mouseY) {
super.renderBg(matrix, partialTicks, mouseX, mouseY); super.drawGuiContainerBackgroundLayer(matrix, partialTicks, mouseX, mouseY);
this.getMinecraft().getTextureManager().bindForSetup(TEXTURE); this.getMinecraft().getTextureManager().bindTexture(TEXTURE);
this.blit(matrix, this.leftPos + 176 / 2 - 16 / 2, this.topPos + 32 + 18 * 2, 176, 80, 16, 16); this.blit(matrix, this.guiLeft + 176 / 2 - 16 / 2, this.guiTop + 32 + 18 * 2, 176, 80, 16, 16);
} }
} }

View file

@ -6,17 +6,19 @@ import de.ellpeck.prettypipes.items.ModuleItem;
import de.ellpeck.prettypipes.items.ModuleTier; import de.ellpeck.prettypipes.items.ModuleTier;
import de.ellpeck.prettypipes.misc.ItemEquality; import de.ellpeck.prettypipes.misc.ItemEquality;
import de.ellpeck.prettypipes.misc.ItemFilter; import de.ellpeck.prettypipes.misc.ItemFilter;
import de.ellpeck.prettypipes.network.NetworkLocation;
import de.ellpeck.prettypipes.network.NetworkLock; import de.ellpeck.prettypipes.network.NetworkLock;
import de.ellpeck.prettypipes.network.PipeNetwork; import de.ellpeck.prettypipes.network.PipeNetwork;
import de.ellpeck.prettypipes.pipe.PipeBlockEntity; import de.ellpeck.prettypipes.pipe.PipeTileEntity;
import de.ellpeck.prettypipes.pipe.containers.AbstractPipeContainer; import de.ellpeck.prettypipes.pipe.containers.AbstractPipeContainer;
import de.ellpeck.prettypipes.terminal.CraftingTerminalBlockEntity; import de.ellpeck.prettypipes.terminal.CraftingTerminalTileEntity;
import de.ellpeck.prettypipes.terminal.ItemTerminalBlockEntity; import de.ellpeck.prettypipes.terminal.ItemTerminalTileEntity;
import net.minecraft.core.BlockPos; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.Mth; import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraftforge.items.ItemStackHandler; import net.minecraftforge.items.ItemStackHandler;
import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.lang3.tuple.Pair;
@ -39,51 +41,51 @@ public class CraftingModuleItem extends ModuleItem {
} }
@Override @Override
public boolean isCompatible(ItemStack module, PipeBlockEntity tile, IModule other) { public boolean isCompatible(ItemStack module, PipeTileEntity tile, IModule other) {
return true; return true;
} }
@Override @Override
public boolean hasContainer(ItemStack module, PipeBlockEntity tile) { public boolean hasContainer(ItemStack module, PipeTileEntity tile) {
return true; return true;
} }
@Override @Override
public AbstractPipeContainer<?> getContainer(ItemStack module, PipeBlockEntity tile, int windowId, Inventory inv, Player player, int moduleIndex) { public AbstractPipeContainer<?> getContainer(ItemStack module, PipeTileEntity tile, int windowId, PlayerInventory inv, PlayerEntity player, int moduleIndex) {
return new CraftingModuleContainer(Registry.craftingModuleContainer, windowId, player, tile.getBlockPos(), moduleIndex); return new CraftingModuleContainer(Registry.craftingModuleContainer, windowId, player, tile.getPos(), moduleIndex);
} }
@Override @Override
public boolean canNetworkSee(ItemStack module, PipeBlockEntity tile) { public boolean canNetworkSee(ItemStack module, PipeTileEntity tile) {
return false; return false;
} }
@Override @Override
public boolean canAcceptItem(ItemStack module, PipeBlockEntity tile, ItemStack stack) { public boolean canAcceptItem(ItemStack module, PipeTileEntity tile, ItemStack stack) {
return false; return false;
} }
@Override @Override
public void tick(ItemStack module, PipeBlockEntity tile) { public void tick(ItemStack module, PipeTileEntity tile) {
if (!tile.shouldWorkNow(this.speed) || !tile.canWork()) if (!tile.shouldWorkNow(this.speed) || !tile.canWork())
return; return;
var network = PipeNetwork.get(tile.getLevel()); PipeNetwork network = PipeNetwork.get(tile.getWorld());
// process crafting ingredient requests // process crafting ingredient requests
if (!tile.craftIngredientRequests.isEmpty()) { if (!tile.craftIngredientRequests.isEmpty()) {
network.startProfile("crafting_ingredients"); network.startProfile("crafting_ingredients");
var request = tile.craftIngredientRequests.peek(); NetworkLock request = tile.craftIngredientRequests.peek();
var equalityTypes = ItemFilter.getEqualityTypes(tile); ItemEquality[] equalityTypes = ItemFilter.getEqualityTypes(tile);
var dest = tile.getAvailableDestination(request.stack, true, true); Pair<BlockPos, ItemStack> dest = tile.getAvailableDestination(request.stack, true, true);
if (dest != null) { if (dest != null) {
var requestRemain = network.requestExistingItem(request.location, tile.getBlockPos(), dest.getLeft(), request, dest.getRight(), equalityTypes); ItemStack requestRemain = network.requestExistingItem(request.location, tile.getPos(), dest.getLeft(), request, dest.getRight(), equalityTypes);
network.resolveNetworkLock(request); network.resolveNetworkLock(request);
tile.craftIngredientRequests.remove(); tile.craftIngredientRequests.remove();
// if we couldn't fit all items into the destination, create another request for the rest // if we couldn't fit all items into the destination, create another request for the rest
var remain = request.stack.copy(); ItemStack remain = request.stack.copy();
remain.shrink(dest.getRight().getCount() - requestRemain.getCount()); remain.shrink(dest.getRight().getCount() - requestRemain.getCount());
if (!remain.isEmpty()) { if (!remain.isEmpty()) {
var remainRequest = new NetworkLock(request.location, remain); NetworkLock remainRequest = new NetworkLock(request.location, remain);
tile.craftIngredientRequests.add(remainRequest); tile.craftIngredientRequests.add(remainRequest);
network.createNetworkLock(remainRequest); network.createNetworkLock(remainRequest);
} }
@ -93,17 +95,17 @@ public class CraftingModuleItem extends ModuleItem {
// pull requested crafting results from the network once they are stored // pull requested crafting results from the network once they are stored
if (!tile.craftResultRequests.isEmpty()) { if (!tile.craftResultRequests.isEmpty()) {
network.startProfile("crafting_results"); network.startProfile("crafting_results");
var items = network.getOrderedNetworkItems(tile.getBlockPos()); List<NetworkLocation> items = network.getOrderedNetworkItems(tile.getPos());
var equalityTypes = ItemFilter.getEqualityTypes(tile); ItemEquality[] equalityTypes = ItemFilter.getEqualityTypes(tile);
for (var request : tile.craftResultRequests) { for (Pair<BlockPos, ItemStack> request : tile.craftResultRequests) {
var remain = request.getRight().copy(); ItemStack remain = request.getRight().copy();
var destPipe = network.getPipe(request.getLeft()); PipeTileEntity destPipe = network.getPipe(request.getLeft());
if (destPipe != null) { if (destPipe != null) {
var dest = destPipe.getAvailableDestinationOrConnectable(remain, true, true); Pair<BlockPos, ItemStack> dest = destPipe.getAvailableDestinationOrConnectable(remain, true, true);
if (dest == null) if (dest == null)
continue; continue;
for (var item : items) { for (NetworkLocation item : items) {
var requestRemain = network.requestExistingItem(item, request.getLeft(), dest.getLeft(), null, dest.getRight(), equalityTypes); ItemStack requestRemain = network.requestExistingItem(item, request.getLeft(), dest.getLeft(), null, dest.getRight(), equalityTypes);
remain.shrink(dest.getRight().getCount() - requestRemain.getCount()); remain.shrink(dest.getRight().getCount() - requestRemain.getCount());
if (remain.isEmpty()) if (remain.isEmpty())
break; break;
@ -123,11 +125,11 @@ public class CraftingModuleItem extends ModuleItem {
} }
@Override @Override
public List<ItemStack> getAllCraftables(ItemStack module, PipeBlockEntity tile) { public List<ItemStack> getAllCraftables(ItemStack module, PipeTileEntity tile) {
List<ItemStack> ret = new ArrayList<>(); List<ItemStack> ret = new ArrayList<>();
var output = this.getOutput(module); ItemStackHandler output = this.getOutput(module);
for (var i = 0; i < output.getSlots(); i++) { for (int i = 0; i < output.getSlots(); i++) {
var stack = output.getStackInSlot(i); ItemStack stack = output.getStackInSlot(i);
if (!stack.isEmpty()) if (!stack.isEmpty())
ret.add(stack); ret.add(stack);
} }
@ -135,19 +137,19 @@ public class CraftingModuleItem extends ModuleItem {
} }
@Override @Override
public int getCraftableAmount(ItemStack module, PipeBlockEntity tile, Consumer<ItemStack> unavailableConsumer, ItemStack stack, Stack<ItemStack> dependencyChain) { public int getCraftableAmount(ItemStack module, PipeTileEntity tile, Consumer<ItemStack> unavailableConsumer, ItemStack stack, Stack<ItemStack> dependencyChain) {
var network = PipeNetwork.get(tile.getLevel()); PipeNetwork network = PipeNetwork.get(tile.getWorld());
var items = network.getOrderedNetworkItems(tile.getBlockPos()); List<NetworkLocation> items = network.getOrderedNetworkItems(tile.getPos());
var equalityTypes = ItemFilter.getEqualityTypes(tile); ItemEquality[] equalityTypes = ItemFilter.getEqualityTypes(tile);
var input = this.getInput(module); ItemStackHandler input = this.getInput(module);
var craftable = 0; int craftable = 0;
var output = this.getOutput(module); ItemStackHandler output = this.getOutput(module);
for (var i = 0; i < output.getSlots(); i++) { for (int i = 0; i < output.getSlots(); i++) {
var out = output.getStackInSlot(i); ItemStack out = output.getStackInSlot(i);
if (!out.isEmpty() && ItemEquality.compareItems(out, stack, equalityTypes)) { if (!out.isEmpty() && ItemEquality.compareItems(out, stack, equalityTypes)) {
// figure out how many crafting operations we can actually do with the input items we have in the network // figure out how many crafting operations we can actually do with the input items we have in the network
var availableCrafts = CraftingTerminalBlockEntity.getAvailableCrafts(tile, input.getSlots(), input::getStackInSlot, k -> true, s -> items, unavailableConsumer, addDependency(dependencyChain, module), equalityTypes); int availableCrafts = CraftingTerminalTileEntity.getAvailableCrafts(tile, input.getSlots(), input::getStackInSlot, k -> true, s -> items, unavailableConsumer, addDependency(dependencyChain, module), equalityTypes);
if (availableCrafts > 0) if (availableCrafts > 0)
craftable += out.getCount() * availableCrafts; craftable += out.getCount() * availableCrafts;
} }
@ -156,35 +158,35 @@ public class CraftingModuleItem extends ModuleItem {
} }
@Override @Override
public ItemStack craft(ItemStack module, PipeBlockEntity tile, BlockPos destPipe, Consumer<ItemStack> unavailableConsumer, ItemStack stack, Stack<ItemStack> dependencyChain) { public ItemStack craft(ItemStack module, PipeTileEntity tile, BlockPos destPipe, Consumer<ItemStack> unavailableConsumer, ItemStack stack, Stack<ItemStack> dependencyChain) {
// check if we can craft the required amount of items // check if we can craft the required amount of items
var craftableAmount = this.getCraftableAmount(module, tile, unavailableConsumer, stack, dependencyChain); int craftableAmount = this.getCraftableAmount(module, tile, unavailableConsumer, stack, dependencyChain);
if (craftableAmount <= 0) if (craftableAmount <= 0)
return stack; return stack;
var network = PipeNetwork.get(tile.getLevel()); PipeNetwork network = PipeNetwork.get(tile.getWorld());
var items = network.getOrderedNetworkItems(tile.getBlockPos()); List<NetworkLocation> items = network.getOrderedNetworkItems(tile.getPos());
var equalityTypes = ItemFilter.getEqualityTypes(tile); ItemEquality[] equalityTypes = ItemFilter.getEqualityTypes(tile);
var resultAmount = this.getResultAmountPerCraft(module, stack, equalityTypes); int resultAmount = this.getResultAmountPerCraft(module, stack, equalityTypes);
var requiredCrafts = Mth.ceil(stack.getCount() / (float) resultAmount); int requiredCrafts = MathHelper.ceil(stack.getCount() / (float) resultAmount);
var toCraft = Math.min(craftableAmount, requiredCrafts); int toCraft = Math.min(craftableAmount, requiredCrafts);
var input = this.getInput(module); ItemStackHandler input = this.getInput(module);
for (var i = 0; i < input.getSlots(); i++) { for (int i = 0; i < input.getSlots(); i++) {
var in = input.getStackInSlot(i); ItemStack in = input.getStackInSlot(i);
if (in.isEmpty()) if (in.isEmpty())
continue; continue;
var copy = in.copy(); ItemStack copy = in.copy();
copy.setCount(in.getCount() * toCraft); copy.setCount(in.getCount() * toCraft);
var ret = ItemTerminalBlockEntity.requestItemLater(tile.getLevel(), tile.getBlockPos(), items, unavailableConsumer, copy, addDependency(dependencyChain, module), equalityTypes); Pair<List<NetworkLock>, ItemStack> ret = ItemTerminalTileEntity.requestItemLater(tile.getWorld(), tile.getPos(), items, unavailableConsumer, copy, addDependency(dependencyChain, module), equalityTypes);
tile.craftIngredientRequests.addAll(ret.getLeft()); tile.craftIngredientRequests.addAll(ret.getLeft());
} }
var remain = stack.copy(); ItemStack remain = stack.copy();
remain.shrink(resultAmount * toCraft); remain.shrink(resultAmount * toCraft);
var result = stack.copy(); ItemStack result = stack.copy();
result.shrink(remain.getCount()); result.shrink(remain.getCount());
tile.craftResultRequests.add(Pair.of(destPipe, result)); tile.craftResultRequests.add(Pair.of(destPipe, result));
@ -192,21 +194,21 @@ public class CraftingModuleItem extends ModuleItem {
} }
public ItemStackHandler getInput(ItemStack module) { public ItemStackHandler getInput(ItemStack module) {
var handler = new ItemStackHandler(this.inputSlots); ItemStackHandler handler = new ItemStackHandler(this.inputSlots);
if (module.hasTag()) if (module.hasTag())
handler.deserializeNBT(module.getTag().getCompound("input")); handler.deserializeNBT(module.getTag().getCompound("input"));
return handler; return handler;
} }
public ItemStackHandler getOutput(ItemStack module) { public ItemStackHandler getOutput(ItemStack module) {
var handler = new ItemStackHandler(this.outputSlots); ItemStackHandler handler = new ItemStackHandler(this.outputSlots);
if (module.hasTag()) if (module.hasTag())
handler.deserializeNBT(module.getTag().getCompound("output")); handler.deserializeNBT(module.getTag().getCompound("output"));
return handler; return handler;
} }
public void save(ItemStackHandler input, ItemStackHandler output, ItemStack module) { public void save(ItemStackHandler input, ItemStackHandler output, ItemStack module) {
var tag = module.getOrCreateTag(); CompoundTag tag = module.getOrCreateTag();
if (input != null) if (input != null)
tag.put("input", input.serializeNBT()); tag.put("input", input.serializeNBT());
if (output != null) if (output != null)
@ -214,10 +216,10 @@ public class CraftingModuleItem extends ModuleItem {
} }
private int getResultAmountPerCraft(ItemStack module, ItemStack stack, ItemEquality... equalityTypes) { private int getResultAmountPerCraft(ItemStack module, ItemStack stack, ItemEquality... equalityTypes) {
var output = this.getOutput(module); ItemStackHandler output = this.getOutput(module);
var resultAmount = 0; int resultAmount = 0;
for (var i = 0; i < output.getSlots(); i++) { for (int i = 0; i < output.getSlots(); i++) {
var out = output.getStackInSlot(i); ItemStack out = output.getStackInSlot(i);
if (ItemEquality.compareItems(stack, out, equalityTypes)) if (ItemEquality.compareItems(stack, out, equalityTypes))
resultAmount += out.getCount(); resultAmount += out.getCount();
} }

View file

@ -3,9 +3,10 @@ package de.ellpeck.prettypipes.pipe.modules.extraction;
import de.ellpeck.prettypipes.misc.ItemFilter; import de.ellpeck.prettypipes.misc.ItemFilter;
import de.ellpeck.prettypipes.misc.ItemFilter.IFilteredContainer; import de.ellpeck.prettypipes.misc.ItemFilter.IFilteredContainer;
import de.ellpeck.prettypipes.pipe.containers.AbstractPipeContainer; import de.ellpeck.prettypipes.pipe.containers.AbstractPipeContainer;
import net.minecraft.core.BlockPos; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.world.entity.player.Player; import net.minecraft.inventory.container.ContainerType;
import net.minecraft.world.inventory.MenuType; import net.minecraft.inventory.container.Slot;
import net.minecraft.util.math.BlockPos;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@ -13,20 +14,20 @@ public class ExtractionModuleContainer extends AbstractPipeContainer<ExtractionM
public ItemFilter filter; public ItemFilter filter;
public ExtractionModuleContainer(@Nullable MenuType<?> type, int id, Player player, BlockPos pos, int moduleIndex) { public ExtractionModuleContainer(@Nullable ContainerType<?> type, int id, PlayerEntity player, BlockPos pos, int moduleIndex) {
super(type, id, player, pos, moduleIndex); super(type, id, player, pos, moduleIndex);
} }
@Override @Override
protected void addSlots() { protected void addSlots() {
this.filter = this.module.getItemFilter(this.moduleStack, this.tile); this.filter = this.module.getItemFilter(this.moduleStack, this.tile);
for (var slot : this.filter.getSlots((176 - this.module.filterSlots * 18) / 2 + 1, 17 + 32)) for (Slot slot : this.filter.getSlots((176 - this.module.filterSlots * 18) / 2 + 1, 17 + 32))
this.addSlot(slot); this.addSlot(slot);
} }
@Override @Override
public void removed(Player playerIn) { public void onContainerClosed(PlayerEntity playerIn) {
super.removed(playerIn); super.onContainerClosed(playerIn);
this.filter.save(); this.filter.save();
} }

View file

@ -1,19 +1,19 @@
package de.ellpeck.prettypipes.pipe.modules.extraction; package de.ellpeck.prettypipes.pipe.modules.extraction;
import de.ellpeck.prettypipes.pipe.containers.AbstractPipeGui; import de.ellpeck.prettypipes.pipe.containers.AbstractPipeGui;
import net.minecraft.network.chat.Component; import net.minecraft.client.gui.widget.Widget;
import net.minecraft.world.entity.player.Inventory; import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.util.text.ITextComponent;
public class ExtractionModuleGui extends AbstractPipeGui<ExtractionModuleContainer> { public class ExtractionModuleGui extends AbstractPipeGui<ExtractionModuleContainer> {
public ExtractionModuleGui(ExtractionModuleContainer screenContainer, PlayerInventory inv, ITextComponent titleIn) {
public ExtractionModuleGui(ExtractionModuleContainer screenContainer, Inventory inv, Component titleIn) {
super(screenContainer, inv, titleIn); super(screenContainer, inv, titleIn);
} }
@Override @Override
protected void init() { protected void init() {
super.init(); super.init();
for (var widget : this.menu.filter.getButtons(this, this.leftPos + 7, this.topPos + 17 + 32 + 20)) for (Widget widget : this.container.filter.getButtons(this, this.guiLeft + 7, this.guiTop + 17 + 32 + 20))
this.addRenderableWidget(widget); this.addButton(widget);
} }
} }

View file

@ -6,12 +6,13 @@ import de.ellpeck.prettypipes.items.ModuleItem;
import de.ellpeck.prettypipes.items.ModuleTier; import de.ellpeck.prettypipes.items.ModuleTier;
import de.ellpeck.prettypipes.misc.ItemFilter; import de.ellpeck.prettypipes.misc.ItemFilter;
import de.ellpeck.prettypipes.network.PipeNetwork; import de.ellpeck.prettypipes.network.PipeNetwork;
import de.ellpeck.prettypipes.pipe.PipeBlockEntity; import de.ellpeck.prettypipes.pipe.PipeTileEntity;
import de.ellpeck.prettypipes.pipe.containers.AbstractPipeContainer; import de.ellpeck.prettypipes.pipe.containers.AbstractPipeContainer;
import net.minecraft.core.Direction; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.world.entity.player.Inventory; import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.util.Direction;
import net.minecraftforge.items.IItemHandler;
public class ExtractionModuleItem extends ModuleItem { public class ExtractionModuleItem extends ModuleItem {
@ -29,23 +30,23 @@ public class ExtractionModuleItem extends ModuleItem {
} }
@Override @Override
public void tick(ItemStack module, PipeBlockEntity tile) { public void tick(ItemStack module, PipeTileEntity tile) {
if (!tile.shouldWorkNow(this.speed) || !tile.canWork()) if (!tile.shouldWorkNow(this.speed) || !tile.canWork())
return; return;
var filter = this.getItemFilter(module, tile); ItemFilter filter = this.getItemFilter(module, tile);
var network = PipeNetwork.get(tile.getLevel()); PipeNetwork network = PipeNetwork.get(tile.getWorld());
for (var dir : Direction.values()) { for (Direction dir : Direction.values()) {
var handler = tile.getItemHandler(dir); IItemHandler handler = tile.getItemHandler(dir);
if (handler == null) if (handler == null)
continue; continue;
for (var j = 0; j < handler.getSlots(); j++) { for (int j = 0; j < handler.getSlots(); j++) {
var stack = handler.extractItem(j, this.maxExtraction, true); ItemStack stack = handler.extractItem(j, this.maxExtraction, true);
if (stack.isEmpty()) if (stack.isEmpty())
continue; continue;
if (!filter.isAllowed(stack)) if (!filter.isAllowed(stack))
continue; continue;
var remain = network.routeItem(tile.getBlockPos(), tile.getBlockPos().relative(dir), stack, this.preventOversending); ItemStack remain = network.routeItem(tile.getPos(), tile.getPos().offset(dir), stack, this.preventOversending);
if (remain.getCount() != stack.getCount()) { if (remain.getCount() != stack.getCount()) {
handler.extractItem(j, stack.getCount() - remain.getCount(), false); handler.extractItem(j, stack.getCount() - remain.getCount(), false);
return; return;
@ -55,32 +56,32 @@ public class ExtractionModuleItem extends ModuleItem {
} }
@Override @Override
public boolean canNetworkSee(ItemStack module, PipeBlockEntity tile) { public boolean canNetworkSee(ItemStack module, PipeTileEntity tile) {
return false; return false;
} }
@Override @Override
public boolean canAcceptItem(ItemStack module, PipeBlockEntity tile, ItemStack stack) { public boolean canAcceptItem(ItemStack module, PipeTileEntity tile, ItemStack stack) {
return false; return false;
} }
@Override @Override
public boolean isCompatible(ItemStack module, PipeBlockEntity tile, IModule other) { public boolean isCompatible(ItemStack module, PipeTileEntity tile, IModule other) {
return !(other instanceof ExtractionModuleItem); return !(other instanceof ExtractionModuleItem);
} }
@Override @Override
public boolean hasContainer(ItemStack module, PipeBlockEntity tile) { public boolean hasContainer(ItemStack module, PipeTileEntity tile) {
return true; return true;
} }
@Override @Override
public AbstractPipeContainer<?> getContainer(ItemStack module, PipeBlockEntity tile, int windowId, Inventory inv, Player player, int moduleIndex) { public AbstractPipeContainer<?> getContainer(ItemStack module, PipeTileEntity tile, int windowId, PlayerInventory inv, PlayerEntity player, int moduleIndex) {
return new ExtractionModuleContainer(Registry.extractionModuleContainer, windowId, player, tile.getBlockPos(), moduleIndex); return new ExtractionModuleContainer(Registry.extractionModuleContainer, windowId, player, tile.getPos(), moduleIndex);
} }
@Override @Override
public ItemFilter getItemFilter(ItemStack module, PipeBlockEntity tile) { public ItemFilter getItemFilter(ItemStack module, PipeTileEntity tile) {
return new ItemFilter(this.filterSlots, module, tile); return new ItemFilter(this.filterSlots, module, tile);
} }
} }

View file

@ -2,29 +2,29 @@ package de.ellpeck.prettypipes.pipe.modules.filter;
import de.ellpeck.prettypipes.misc.ItemFilter; import de.ellpeck.prettypipes.misc.ItemFilter;
import de.ellpeck.prettypipes.pipe.containers.AbstractPipeContainer; import de.ellpeck.prettypipes.pipe.containers.AbstractPipeContainer;
import net.minecraft.core.BlockPos; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.world.entity.player.Player; import net.minecraft.inventory.container.ContainerType;
import net.minecraft.world.inventory.MenuType; import net.minecraft.inventory.container.Slot;
import net.minecraft.world.inventory.Slot; import net.minecraft.util.math.BlockPos;
public class FilterIncreaseModuleContainer extends AbstractPipeContainer<FilterIncreaseModuleItem> implements ItemFilter.IFilteredContainer { public class FilterIncreaseModuleContainer extends AbstractPipeContainer<FilterIncreaseModuleItem> implements ItemFilter.IFilteredContainer {
public ItemFilter filter; public ItemFilter filter;
public FilterIncreaseModuleContainer(MenuType<?> type, int id, Player player, BlockPos pos, int moduleIndex) { public FilterIncreaseModuleContainer(ContainerType<?> type, int id, PlayerEntity player, BlockPos pos, int moduleIndex) {
super(type, id, player, pos, moduleIndex); super(type, id, player, pos, moduleIndex);
} }
@Override @Override
protected void addSlots() { protected void addSlots() {
this.filter = this.module.getItemFilter(this.moduleStack, this.tile); this.filter = this.module.getItemFilter(this.moduleStack, this.tile);
for (var slot : this.filter.getSlots(8, 49)) for (Slot slot : this.filter.getSlots(8, 49))
this.addSlot(slot); this.addSlot(slot);
} }
@Override @Override
public void removed(Player playerIn) { public void onContainerClosed(PlayerEntity playerIn) {
super.removed(playerIn); super.onContainerClosed(playerIn);
this.filter.save(); this.filter.save();
} }

View file

@ -1,12 +1,11 @@
package de.ellpeck.prettypipes.pipe.modules.filter; package de.ellpeck.prettypipes.pipe.modules.filter;
import de.ellpeck.prettypipes.pipe.containers.AbstractPipeGui; import de.ellpeck.prettypipes.pipe.containers.AbstractPipeGui;
import net.minecraft.network.chat.Component; import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.world.entity.player.Inventory; import net.minecraft.util.text.ITextComponent;
public class FilterIncreaseModuleGui extends AbstractPipeGui<FilterIncreaseModuleContainer> { public class FilterIncreaseModuleGui extends AbstractPipeGui<FilterIncreaseModuleContainer> {
public FilterIncreaseModuleGui(FilterIncreaseModuleContainer screenContainer, PlayerInventory inv, ITextComponent titleIn) {
public FilterIncreaseModuleGui(FilterIncreaseModuleContainer screenContainer, Inventory inv, Component titleIn) {
super(screenContainer, inv, titleIn); super(screenContainer, inv, titleIn);
} }
} }

View file

@ -4,10 +4,10 @@ import de.ellpeck.prettypipes.Registry;
import de.ellpeck.prettypipes.items.IModule; import de.ellpeck.prettypipes.items.IModule;
import de.ellpeck.prettypipes.items.ModuleItem; import de.ellpeck.prettypipes.items.ModuleItem;
import de.ellpeck.prettypipes.misc.ItemFilter; import de.ellpeck.prettypipes.misc.ItemFilter;
import de.ellpeck.prettypipes.pipe.PipeBlockEntity; import de.ellpeck.prettypipes.pipe.PipeTileEntity;
import de.ellpeck.prettypipes.pipe.containers.AbstractPipeContainer; import de.ellpeck.prettypipes.pipe.containers.AbstractPipeContainer;
import net.minecraft.world.entity.player.Inventory; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.world.entity.player.Player; import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
public class FilterIncreaseModuleItem extends ModuleItem { public class FilterIncreaseModuleItem extends ModuleItem {
@ -18,23 +18,23 @@ public class FilterIncreaseModuleItem extends ModuleItem {
} }
@Override @Override
public boolean isCompatible(ItemStack module, PipeBlockEntity tile, IModule other) { public boolean isCompatible(ItemStack module, PipeTileEntity tile, IModule other) {
return true; return true;
} }
@Override @Override
public boolean hasContainer(ItemStack module, PipeBlockEntity tile) { public boolean hasContainer(ItemStack module, PipeTileEntity tile) {
return true; return true;
} }
@Override @Override
public AbstractPipeContainer<?> getContainer(ItemStack module, PipeBlockEntity tile, int windowId, Inventory inv, Player player, int moduleIndex) { public AbstractPipeContainer<?> getContainer(ItemStack module, PipeTileEntity tile, int windowId, PlayerInventory inv, PlayerEntity player, int moduleIndex) {
return new FilterIncreaseModuleContainer(Registry.filterIncreaseModuleContainer, windowId, player, tile.getBlockPos(), moduleIndex); return new FilterIncreaseModuleContainer(Registry.filterIncreaseModuleContainer, windowId, player, tile.getPos(), moduleIndex);
} }
@Override @Override
public ItemFilter getItemFilter(ItemStack module, PipeBlockEntity tile) { public ItemFilter getItemFilter(ItemStack module, PipeTileEntity tile) {
var filter = new ItemFilter(18, module, tile); ItemFilter filter = new ItemFilter(18, module, tile);
filter.canModifyWhitelist = false; filter.canModifyWhitelist = false;
return filter; return filter;
} }

View file

@ -3,10 +3,10 @@ package de.ellpeck.prettypipes.pipe.modules.insertion;
import de.ellpeck.prettypipes.misc.ItemFilter; import de.ellpeck.prettypipes.misc.ItemFilter;
import de.ellpeck.prettypipes.misc.ItemFilter.IFilteredContainer; import de.ellpeck.prettypipes.misc.ItemFilter.IFilteredContainer;
import de.ellpeck.prettypipes.pipe.containers.AbstractPipeContainer; import de.ellpeck.prettypipes.pipe.containers.AbstractPipeContainer;
import net.minecraft.core.BlockPos; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.world.entity.player.Player; import net.minecraft.inventory.container.ContainerType;
import net.minecraft.world.inventory.MenuType; import net.minecraft.inventory.container.Slot;
import net.minecraft.world.inventory.Slot; import net.minecraft.util.math.BlockPos;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@ -14,20 +14,20 @@ public class FilterModuleContainer extends AbstractPipeContainer<FilterModuleIte
public ItemFilter filter; public ItemFilter filter;
public FilterModuleContainer(@Nullable MenuType<?> type, int id, Player player, BlockPos pos, int moduleIndex) { public FilterModuleContainer(@Nullable ContainerType<?> type, int id, PlayerEntity player, BlockPos pos, int moduleIndex) {
super(type, id, player, pos, moduleIndex); super(type, id, player, pos, moduleIndex);
} }
@Override @Override
protected void addSlots() { protected void addSlots() {
this.filter = this.module.getItemFilter(this.moduleStack, this.tile); this.filter = this.module.getItemFilter(this.moduleStack, this.tile);
for (var slot : this.filter.getSlots((176 - Math.min(this.module.filterSlots, 9) * 18) / 2 + 1, 17 + 32)) for (Slot slot : this.filter.getSlots((176 - Math.min(this.module.filterSlots, 9) * 18) / 2 + 1, 17 + 32))
this.addSlot(slot); this.addSlot(slot);
} }
@Override @Override
public void removed(Player playerIn) { public void onContainerClosed(PlayerEntity playerIn) {
super.removed(playerIn); super.onContainerClosed(playerIn);
this.filter.save(); this.filter.save();
} }

View file

@ -1,21 +1,20 @@
package de.ellpeck.prettypipes.pipe.modules.insertion; package de.ellpeck.prettypipes.pipe.modules.insertion;
import de.ellpeck.prettypipes.pipe.containers.AbstractPipeGui; import de.ellpeck.prettypipes.pipe.containers.AbstractPipeGui;
import net.minecraft.client.gui.components.AbstractWidget; import net.minecraft.client.gui.widget.Widget;
import net.minecraft.network.chat.Component; import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.util.Mth; import net.minecraft.util.math.MathHelper;
import net.minecraft.world.entity.player.Inventory; import net.minecraft.util.text.ITextComponent;
public class FilterModuleGui extends AbstractPipeGui<FilterModuleContainer> { public class FilterModuleGui extends AbstractPipeGui<FilterModuleContainer> {
public FilterModuleGui(FilterModuleContainer screenContainer, PlayerInventory inv, ITextComponent titleIn) {
public FilterModuleGui(FilterModuleContainer screenContainer, Inventory inv, Component titleIn) {
super(screenContainer, inv, titleIn); super(screenContainer, inv, titleIn);
} }
@Override @Override
protected void init() { protected void init() {
super.init(); super.init();
for (var widget : this.menu.filter.getButtons(this, this.leftPos + 7, this.topPos + 17 + 32 + 18 * Mth.ceil(this.menu.filter.getSlots() / 9F) + 2)) for (Widget widget : this.container.filter.getButtons(this, this.guiLeft + 7, this.guiTop + 17 + 32 + 18 * MathHelper.ceil(this.container.filter.getSlots() / 9F) + 2))
this.addRenderableWidget(widget); this.addButton(widget);
} }
} }

View file

@ -5,10 +5,10 @@ import de.ellpeck.prettypipes.items.IModule;
import de.ellpeck.prettypipes.items.ModuleItem; import de.ellpeck.prettypipes.items.ModuleItem;
import de.ellpeck.prettypipes.items.ModuleTier; import de.ellpeck.prettypipes.items.ModuleTier;
import de.ellpeck.prettypipes.misc.ItemFilter; import de.ellpeck.prettypipes.misc.ItemFilter;
import de.ellpeck.prettypipes.pipe.PipeBlockEntity; import de.ellpeck.prettypipes.pipe.PipeTileEntity;
import de.ellpeck.prettypipes.pipe.containers.AbstractPipeContainer; import de.ellpeck.prettypipes.pipe.containers.AbstractPipeContainer;
import net.minecraft.world.entity.player.Inventory; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.world.entity.player.Player; import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
public class FilterModuleItem extends ModuleItem { public class FilterModuleItem extends ModuleItem {
@ -23,29 +23,29 @@ public class FilterModuleItem extends ModuleItem {
} }
@Override @Override
public boolean canAcceptItem(ItemStack module, PipeBlockEntity tile, ItemStack stack) { public boolean canAcceptItem(ItemStack module, PipeTileEntity tile, ItemStack stack) {
var filter = this.getItemFilter(module, tile); ItemFilter filter = this.getItemFilter(module, tile);
return filter.isAllowed(stack); return filter.isAllowed(stack);
} }
@Override @Override
public boolean isCompatible(ItemStack module, PipeBlockEntity tile, IModule other) { public boolean isCompatible(ItemStack module, PipeTileEntity tile, IModule other) {
return !(other instanceof FilterModuleItem); return !(other instanceof FilterModuleItem);
} }
@Override @Override
public boolean hasContainer(ItemStack module, PipeBlockEntity tile) { public boolean hasContainer(ItemStack module, PipeTileEntity tile) {
return true; return true;
} }
@Override @Override
public AbstractPipeContainer<?> getContainer(ItemStack module, PipeBlockEntity tile, int windowId, Inventory inv, Player player, int moduleIndex) { public AbstractPipeContainer<?> getContainer(ItemStack module, PipeTileEntity tile, int windowId, PlayerInventory inv, PlayerEntity player, int moduleIndex) {
return new FilterModuleContainer(Registry.filterModuleContainer, windowId, player, tile.getBlockPos(), moduleIndex); return new FilterModuleContainer(Registry.filterModuleContainer, windowId, player, tile.getPos(), moduleIndex);
} }
@Override @Override
public ItemFilter getItemFilter(ItemStack module, PipeBlockEntity tile) { public ItemFilter getItemFilter(ItemStack module, PipeTileEntity tile) {
var filter = new ItemFilter(this.filterSlots, module, tile); ItemFilter filter = new ItemFilter(this.filterSlots, module, tile);
filter.canPopulateFromInventories = this.canPopulateFromInventories; filter.canPopulateFromInventories = this.canPopulateFromInventories;
return filter; return filter;
} }

View file

@ -2,11 +2,11 @@ package de.ellpeck.prettypipes.pipe.modules.modifier;
import de.ellpeck.prettypipes.misc.ItemFilter; import de.ellpeck.prettypipes.misc.ItemFilter;
import de.ellpeck.prettypipes.pipe.containers.AbstractPipeContainer; import de.ellpeck.prettypipes.pipe.containers.AbstractPipeContainer;
import net.minecraft.core.BlockPos; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.resources.ResourceLocation; import net.minecraft.inventory.container.ContainerType;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.MenuType;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.math.BlockPos;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.HashSet; import java.util.HashSet;
@ -16,15 +16,15 @@ import java.util.stream.Collectors;
public class FilterModifierModuleContainer extends AbstractPipeContainer<FilterModifierModuleItem> { public class FilterModifierModuleContainer extends AbstractPipeContainer<FilterModifierModuleItem> {
public FilterModifierModuleContainer(@Nullable MenuType<?> type, int id, Player player, BlockPos pos, int moduleIndex) { public FilterModifierModuleContainer(@Nullable ContainerType<?> type, int id, PlayerEntity player, BlockPos pos, int moduleIndex) {
super(type, id, player, pos, moduleIndex); super(type, id, player, pos, moduleIndex);
} }
public List<ResourceLocation> getTags() { public List<ResourceLocation> getTags() {
Set<ResourceLocation> unsortedTags = new HashSet<>(); Set<ResourceLocation> unsortedTags = new HashSet<>();
for (var filter : this.tile.getFilters()) { for (ItemFilter filter : this.tile.getFilters()) {
for (var i = 0; i < filter.getSlots(); i++) { for (int i = 0; i < filter.getSlots(); i++) {
var stack = filter.getStackInSlot(i); ItemStack stack = filter.getStackInSlot(i);
unsortedTags.addAll(stack.getItem().getTags()); unsortedTags.addAll(stack.getItem().getTags());
} }
} }

View file

@ -1,60 +1,59 @@
package de.ellpeck.prettypipes.pipe.modules.modifier; package de.ellpeck.prettypipes.pipe.modules.modifier;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.matrix.MatrixStack;
import de.ellpeck.prettypipes.packets.PacketButton; import de.ellpeck.prettypipes.packets.PacketButton;
import de.ellpeck.prettypipes.pipe.containers.AbstractPipeGui; import de.ellpeck.prettypipes.pipe.containers.AbstractPipeGui;
import net.minecraft.ChatFormatting; import net.minecraft.client.audio.SimpleSound;
import net.minecraft.client.resources.sounds.SimpleSoundInstance; import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.sounds.SoundEvents; import net.minecraft.util.SoundEvents;
import net.minecraft.util.Mth; import net.minecraft.util.math.MathHelper;
import net.minecraft.world.entity.player.Inventory; import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TextFormatting;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
public class FilterModifierModuleGui extends AbstractPipeGui<FilterModifierModuleContainer> { public class FilterModifierModuleGui extends AbstractPipeGui<FilterModifierModuleContainer> {
private int scrollOffset; private int scrollOffset;
private boolean isScrolling; private boolean isScrolling;
private List<ResourceLocation> tags; private List<ResourceLocation> tags;
private final List<Tag> tagButtons = new ArrayList<>(); private final List<Tag> tagButtons = new ArrayList<>();
public FilterModifierModuleGui(FilterModifierModuleContainer screenContainer, Inventory inv, Component titleIn) { public FilterModifierModuleGui(FilterModifierModuleContainer screenContainer, PlayerInventory inv, ITextComponent titleIn) {
super(screenContainer, inv, titleIn); super(screenContainer, inv, titleIn);
} }
@Override @Override
protected void renderBg(PoseStack matrix, float partialTicks, int mouseX, int mouseY) { protected void drawGuiContainerBackgroundLayer(MatrixStack matrix, float partialTicks, int mouseX, int mouseY) {
super.renderBg(matrix, partialTicks, mouseX, mouseY); super.drawGuiContainerBackgroundLayer(matrix, partialTicks, mouseX, mouseY);
this.blit(matrix, this.leftPos + 7, this.topPos + 32 + 15, 0, 196, 162, 60); this.blit(matrix, this.guiLeft + 7, this.guiTop + 32 + 15, 0, 196, 162, 60);
for (var tag : this.tagButtons) for (Tag tag : this.tagButtons)
tag.draw(matrix, mouseX, mouseY); tag.draw(matrix, mouseX, mouseY);
if (this.tags.size() >= 6) { if (this.tags.size() >= 6) {
var percentage = this.scrollOffset / (float) (this.tags.size() - 5); float percentage = this.scrollOffset / (float) (this.tags.size() - 5);
this.blit(matrix, this.leftPos + 156, this.topPos + 32 + 16 + (int) (percentage * (58 - 15)), 232, 241, 12, 15); this.blit(matrix, this.guiLeft + 156, this.guiTop + 32 + 16 + (int) (percentage * (58 - 15)), 232, 241, 12, 15);
} else { } else {
this.blit(matrix, this.leftPos + 156, this.topPos + 32 + 16, 244, 241, 12, 15); this.blit(matrix, this.guiLeft + 156, this.guiTop + 32 + 16, 244, 241, 12, 15);
} }
} }
@Override @Override
protected void init() { protected void init() {
super.init(); super.init();
this.tags = this.menu.getTags(); this.tags = this.container.getTags();
this.updateWidgets(); this.updateWidgets();
} }
@Override @Override
public boolean mouseClicked(double mouseX, double mouseY, int button) { public boolean mouseClicked(double mouseX, double mouseY, int button) {
for (var tag : this.tagButtons) { for (Tag tag : this.tagButtons) {
if (tag.onClicked(mouseX, mouseY, button)) if (tag.onClicked(mouseX, mouseY, button))
return true; return true;
} }
if (button == 0 && mouseX >= this.leftPos + 156 && this.topPos + mouseY >= 32 + 16 && mouseX < this.leftPos + 156 + 12 && mouseY < this.topPos + 32 + 16 + 58) { if (button == 0 && mouseX >= this.guiLeft + 156 && this.guiTop + mouseY >= 32 + 16 && mouseX < this.guiLeft + 156 + 12 && mouseY < this.guiTop + 32 + 16 + 58) {
this.isScrolling = true; this.isScrolling = true;
return true; return true;
} }
@ -71,8 +70,8 @@ public class FilterModifierModuleGui extends AbstractPipeGui<FilterModifierModul
@Override @Override
public boolean mouseDragged(double mouseX, double mouseY, int i, double j, double k) { public boolean mouseDragged(double mouseX, double mouseY, int i, double j, double k) {
if (this.isScrolling) { if (this.isScrolling) {
var percentage = Mth.clamp(((float) mouseY - (this.topPos + 32 + 18)) / (58 - 15), 0, 1); float percentage = MathHelper.clamp(((float) mouseY - (this.guiTop + 32 + 18)) / (58 - 15), 0, 1);
var offset = (int) (percentage * (float) (this.tags.size() - 5)); int offset = (int) (percentage * (float) (this.tags.size() - 5));
if (offset != this.scrollOffset) { if (offset != this.scrollOffset) {
this.scrollOffset = offset; this.scrollOffset = offset;
this.updateWidgets(); this.updateWidgets();
@ -85,7 +84,7 @@ public class FilterModifierModuleGui extends AbstractPipeGui<FilterModifierModul
@Override @Override
public boolean mouseScrolled(double x, double y, double scroll) { public boolean mouseScrolled(double x, double y, double scroll) {
if (this.tags.size() >= 6) { if (this.tags.size() >= 6) {
var offset = Mth.clamp(this.scrollOffset - (int) Math.signum(scroll), 0, this.tags.size() - 5); int offset = MathHelper.clamp(this.scrollOffset - (int) Math.signum(scroll), 0, this.tags.size() - 5);
if (offset != this.scrollOffset) { if (offset != this.scrollOffset) {
this.scrollOffset = offset; this.scrollOffset = offset;
this.updateWidgets(); this.updateWidgets();
@ -96,10 +95,10 @@ public class FilterModifierModuleGui extends AbstractPipeGui<FilterModifierModul
private void updateWidgets() { private void updateWidgets() {
this.tagButtons.clear(); this.tagButtons.clear();
for (var i = 0; i < 5; i++) { for (int i = 0; i < 5; i++) {
if (i >= this.tags.size()) if (i >= this.tags.size())
break; break;
this.tagButtons.add(new Tag(this.tags.get(this.scrollOffset + i), this.leftPos + 10, this.topPos + 32 + 17 + i * 12)); this.tagButtons.add(new Tag(this.tags.get(this.scrollOffset + i), this.guiLeft + 10, this.guiTop + 32 + 17 + i * 12));
} }
} }
@ -115,15 +114,15 @@ public class FilterModifierModuleGui extends AbstractPipeGui<FilterModifierModul
this.y = y; this.y = y;
} }
private void draw(PoseStack matrix, double mouseX, double mouseY) { private void draw(MatrixStack matrix, double mouseX, double mouseY) {
var color = 4210752; int color = 4210752;
var text = this.tag.toString(); String text = this.tag.toString();
if (mouseX >= this.x && mouseY >= this.y && mouseX < this.x + 140 && mouseY < this.y + 12) if (mouseX >= this.x && mouseY >= this.y && mouseX < this.x + 140 && mouseY < this.y + 12)
color = 0xFFFFFF; color = 0xFFFFFF;
if (this.tag.equals(FilterModifierModuleItem.getFilterTag(FilterModifierModuleGui.this.menu.moduleStack))) if (this.tag.equals(FilterModifierModuleItem.getFilterTag(FilterModifierModuleGui.this.container.moduleStack)))
text = ChatFormatting.BOLD + text; text = TextFormatting.BOLD + text;
FilterModifierModuleGui.this.font.draw(matrix, text, this.x, this.y, color); FilterModifierModuleGui.this.font.drawString(matrix, text, this.x, this.y, color);
FilterModifierModuleGui.this.getMinecraft().getTextureManager().bindForSetup(TEXTURE); FilterModifierModuleGui.this.getMinecraft().getTextureManager().bindTexture(TEXTURE);
} }
private boolean onClicked(double mouseX, double mouseY, int button) { private boolean onClicked(double mouseX, double mouseY, int button) {
@ -131,8 +130,8 @@ public class FilterModifierModuleGui extends AbstractPipeGui<FilterModifierModul
return false; return false;
if (mouseX < this.x || mouseY < this.y || mouseX >= this.x + 140 || mouseY >= this.y + 12) if (mouseX < this.x || mouseY < this.y || mouseX >= this.x + 140 || mouseY >= this.y + 12)
return false; return false;
PacketButton.sendAndExecute(FilterModifierModuleGui.this.menu.tile.getBlockPos(), PacketButton.ButtonResult.TAG_FILTER, FilterModifierModuleGui.this.tags.indexOf(this.tag)); PacketButton.sendAndExecute(FilterModifierModuleGui.this.container.tile.getPos(), PacketButton.ButtonResult.TAG_FILTER, FilterModifierModuleGui.this.tags.indexOf(this.tag));
FilterModifierModuleGui.this.getMinecraft().getSoundManager().play(SimpleSoundInstance.forUI(SoundEvents.UI_BUTTON_CLICK, 1)); FilterModifierModuleGui.this.getMinecraft().getSoundHandler().play(SimpleSound.master(SoundEvents.UI_BUTTON_CLICK, 1));
return true; return true;
} }
} }

View file

@ -4,13 +4,19 @@ import de.ellpeck.prettypipes.Registry;
import de.ellpeck.prettypipes.items.IModule; import de.ellpeck.prettypipes.items.IModule;
import de.ellpeck.prettypipes.items.ModuleItem; import de.ellpeck.prettypipes.items.ModuleItem;
import de.ellpeck.prettypipes.misc.ItemEquality; import de.ellpeck.prettypipes.misc.ItemEquality;
import de.ellpeck.prettypipes.pipe.PipeBlockEntity; import de.ellpeck.prettypipes.pipe.PipeTileEntity;
import de.ellpeck.prettypipes.pipe.containers.AbstractPipeContainer; import de.ellpeck.prettypipes.pipe.containers.AbstractPipeContainer;
import joptsimple.internal.Strings; import joptsimple.internal.Strings;
import net.minecraft.resources.ResourceLocation; import net.minecraft.client.util.ITooltipFlag;
import net.minecraft.world.entity.player.Inventory; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.world.entity.player.Player; import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.world.World;
import javax.annotation.Nullable;
import java.util.List;
public class FilterModifierModuleItem extends ModuleItem { public class FilterModifierModuleItem extends ModuleItem {
@ -23,18 +29,23 @@ public class FilterModifierModuleItem extends ModuleItem {
} }
@Override @Override
public boolean isCompatible(ItemStack module, PipeBlockEntity tile, IModule other) { public boolean isCompatible(ItemStack module, PipeTileEntity tile, IModule other) {
return other != this; return other != this;
} }
@Override @Override
public boolean hasContainer(ItemStack module, PipeBlockEntity tile) { public boolean hasContainer(ItemStack module, PipeTileEntity tile) {
return this.type == ItemEquality.Type.TAG; return this.type == ItemEquality.Type.TAG;
} }
@Override @Override
public AbstractPipeContainer<?> getContainer(ItemStack module, PipeBlockEntity tile, int windowId, Inventory inv, Player player, int moduleIndex) { public AbstractPipeContainer<?> getContainer(ItemStack module, PipeTileEntity tile, int windowId, PlayerInventory inv, PlayerEntity player, int moduleIndex) {
return new FilterModifierModuleContainer(Registry.filterModifierModuleContainer, windowId, player, tile.getBlockPos(), moduleIndex); return new FilterModifierModuleContainer(Registry.filterModifierModuleContainer, windowId, player, tile.getPos(), moduleIndex);
}
@Override
public void addInformation(ItemStack stack, @Nullable World worldIn, List<ITextComponent> tooltip, ITooltipFlag flagIn) {
super.addInformation(stack, worldIn, tooltip, flagIn);
} }
public ItemEquality getEqualityType(ItemStack stack) { public ItemEquality getEqualityType(ItemStack stack) {
@ -48,7 +59,7 @@ public class FilterModifierModuleItem extends ModuleItem {
public static ResourceLocation getFilterTag(ItemStack stack) { public static ResourceLocation getFilterTag(ItemStack stack) {
if (!stack.hasTag()) if (!stack.hasTag())
return null; return null;
var tag = stack.getTag().getString("filter_tag"); String tag = stack.getTag().getString("filter_tag");
if (Strings.isNullOrEmpty(tag)) if (Strings.isNullOrEmpty(tag))
return null; return null;
return new ResourceLocation(tag); return new ResourceLocation(tag);

View file

@ -3,10 +3,10 @@ package de.ellpeck.prettypipes.pipe.modules.retrieval;
import de.ellpeck.prettypipes.misc.ItemFilter; import de.ellpeck.prettypipes.misc.ItemFilter;
import de.ellpeck.prettypipes.misc.ItemFilter.IFilteredContainer; import de.ellpeck.prettypipes.misc.ItemFilter.IFilteredContainer;
import de.ellpeck.prettypipes.pipe.containers.AbstractPipeContainer; import de.ellpeck.prettypipes.pipe.containers.AbstractPipeContainer;
import net.minecraft.core.BlockPos; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.world.entity.player.Player; import net.minecraft.inventory.container.ContainerType;
import net.minecraft.world.inventory.MenuType; import net.minecraft.inventory.container.Slot;
import net.minecraft.world.inventory.Slot; import net.minecraft.util.math.BlockPos;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@ -14,20 +14,20 @@ public class RetrievalModuleContainer extends AbstractPipeContainer<RetrievalMod
public ItemFilter filter; public ItemFilter filter;
public RetrievalModuleContainer(@Nullable MenuType<?> type, int id, Player player, BlockPos pos, int moduleIndex) { public RetrievalModuleContainer(@Nullable ContainerType<?> type, int id, PlayerEntity player, BlockPos pos, int moduleIndex) {
super(type, id, player, pos, moduleIndex); super(type, id, player, pos, moduleIndex);
} }
@Override @Override
protected void addSlots() { protected void addSlots() {
this.filter = this.module.getItemFilter(this.moduleStack, this.tile); this.filter = this.module.getItemFilter(this.moduleStack, this.tile);
for (var slot : this.filter.getSlots((176 - this.module.filterSlots * 18) / 2 + 1, 17 + 32)) for (Slot slot : this.filter.getSlots((176 - this.module.filterSlots * 18) / 2 + 1, 17 + 32))
this.addSlot(slot); this.addSlot(slot);
} }
@Override @Override
public void removed(Player playerIn) { public void onContainerClosed(PlayerEntity playerIn) {
super.removed(playerIn); super.onContainerClosed(playerIn);
this.filter.save(); this.filter.save();
} }

View file

@ -1,20 +1,19 @@
package de.ellpeck.prettypipes.pipe.modules.retrieval; package de.ellpeck.prettypipes.pipe.modules.retrieval;
import de.ellpeck.prettypipes.pipe.containers.AbstractPipeGui; import de.ellpeck.prettypipes.pipe.containers.AbstractPipeGui;
import net.minecraft.client.gui.components.AbstractWidget; import net.minecraft.client.gui.widget.Widget;
import net.minecraft.network.chat.Component; import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.world.entity.player.Inventory; import net.minecraft.util.text.ITextComponent;
public class RetrievalModuleGui extends AbstractPipeGui<RetrievalModuleContainer> { public class RetrievalModuleGui extends AbstractPipeGui<RetrievalModuleContainer> {
public RetrievalModuleGui(RetrievalModuleContainer screenContainer, PlayerInventory inv, ITextComponent titleIn) {
public RetrievalModuleGui(RetrievalModuleContainer screenContainer, Inventory inv, Component titleIn) {
super(screenContainer, inv, titleIn); super(screenContainer, inv, titleIn);
} }
@Override @Override
protected void init() { protected void init() {
super.init(); super.init();
for (var widget : this.menu.filter.getButtons(this, this.leftPos + 7, this.topPos + 17 + 32 + 20)) for (Widget widget : this.container.filter.getButtons(this, this.guiLeft + 7, this.guiTop + 17 + 32 + 20))
this.addRenderableWidget(widget); this.addButton(widget);
} }
} }

View file

@ -7,16 +7,15 @@ import de.ellpeck.prettypipes.items.ModuleTier;
import de.ellpeck.prettypipes.misc.ItemEquality; import de.ellpeck.prettypipes.misc.ItemEquality;
import de.ellpeck.prettypipes.misc.ItemFilter; import de.ellpeck.prettypipes.misc.ItemFilter;
import de.ellpeck.prettypipes.network.PipeNetwork; import de.ellpeck.prettypipes.network.PipeNetwork;
import de.ellpeck.prettypipes.pipe.PipeBlockEntity; import de.ellpeck.prettypipes.pipe.PipeTileEntity;
import de.ellpeck.prettypipes.pipe.containers.AbstractPipeContainer; import de.ellpeck.prettypipes.pipe.containers.AbstractPipeContainer;
import net.minecraft.core.BlockPos; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.world.entity.player.Inventory; import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.util.math.BlockPos;
import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.lang3.tuple.Pair;
public class RetrievalModuleItem extends ModuleItem { public class RetrievalModuleItem extends ModuleItem {
private final int maxExtraction; private final int maxExtraction;
private final int speed; private final int speed;
private final boolean preventOversending; private final boolean preventOversending;
@ -31,60 +30,60 @@ public class RetrievalModuleItem extends ModuleItem {
} }
@Override @Override
public void tick(ItemStack module, PipeBlockEntity tile) { public void tick(ItemStack module, PipeTileEntity tile) {
if (!tile.shouldWorkNow(this.speed) || !tile.canWork()) if (!tile.shouldWorkNow(this.speed) || !tile.canWork())
return; return;
var network = PipeNetwork.get(tile.getLevel()); PipeNetwork network = PipeNetwork.get(tile.getWorld());
var equalityTypes = ItemFilter.getEqualityTypes(tile); ItemEquality[] equalityTypes = ItemFilter.getEqualityTypes(tile);
// loop through filters to see which items to pull // loop through filters to see which items to pull
for (var subFilter : tile.getFilters()) { for (ItemFilter subFilter : tile.getFilters()) {
for (var f = 0; f < subFilter.getSlots(); f++) { for (int f = 0; f < subFilter.getSlots(); f++) {
var filtered = subFilter.getStackInSlot(f); ItemStack filtered = subFilter.getStackInSlot(f);
if (filtered.isEmpty()) if (filtered.isEmpty())
continue; continue;
var copy = filtered.copy(); ItemStack copy = filtered.copy();
copy.setCount(this.maxExtraction); copy.setCount(this.maxExtraction);
var dest = tile.getAvailableDestination(copy, true, this.preventOversending); Pair<BlockPos, ItemStack> dest = tile.getAvailableDestination(copy, true, this.preventOversending);
if (dest == null) if (dest == null)
continue; continue;
var remain = dest.getRight().copy(); ItemStack remain = dest.getRight().copy();
// are we already waiting for crafting results? If so, don't request those again // are we already waiting for crafting results? If so, don't request those again
remain.shrink(network.getCurrentlyCraftingAmount(tile.getBlockPos(), copy, equalityTypes)); remain.shrink(network.getCurrentlyCraftingAmount(tile.getPos(), copy, equalityTypes));
if (network.requestItem(tile.getBlockPos(), dest.getLeft(), remain, equalityTypes).isEmpty()) if (network.requestItem(tile.getPos(), dest.getLeft(), remain, equalityTypes).isEmpty())
break; break;
} }
} }
} }
@Override @Override
public boolean canNetworkSee(ItemStack module, PipeBlockEntity tile) { public boolean canNetworkSee(ItemStack module, PipeTileEntity tile) {
return false; return false;
} }
@Override @Override
public boolean canAcceptItem(ItemStack module, PipeBlockEntity tile, ItemStack stack) { public boolean canAcceptItem(ItemStack module, PipeTileEntity tile, ItemStack stack) {
return false; return false;
} }
@Override @Override
public boolean isCompatible(ItemStack module, PipeBlockEntity tile, IModule other) { public boolean isCompatible(ItemStack module, PipeTileEntity tile, IModule other) {
return !(other instanceof RetrievalModuleItem); return !(other instanceof RetrievalModuleItem);
} }
@Override @Override
public boolean hasContainer(ItemStack module, PipeBlockEntity tile) { public boolean hasContainer(ItemStack module, PipeTileEntity tile) {
return true; return true;
} }
@Override @Override
public AbstractPipeContainer<?> getContainer(ItemStack module, PipeBlockEntity tile, int windowId, Inventory inv, Player player, int moduleIndex) { public AbstractPipeContainer<?> getContainer(ItemStack module, PipeTileEntity tile, int windowId, PlayerInventory inv, PlayerEntity player, int moduleIndex) {
return new RetrievalModuleContainer(Registry.retrievalModuleContainer, windowId, player, tile.getBlockPos(), moduleIndex); return new RetrievalModuleContainer(Registry.retrievalModuleContainer, windowId, player, tile.getPos(), moduleIndex);
} }
@Override @Override
public ItemFilter getItemFilter(ItemStack module, PipeBlockEntity tile) { public ItemFilter getItemFilter(ItemStack module, PipeTileEntity tile) {
var filter = new ItemFilter(this.filterSlots, module, tile); ItemFilter filter = new ItemFilter(this.filterSlots, module, tile);
filter.canModifyWhitelist = false; filter.canModifyWhitelist = false;
filter.isWhitelist = true; filter.isWhitelist = true;
return filter; return filter;

View file

@ -1,15 +1,14 @@
package de.ellpeck.prettypipes.pipe.modules.stacksize; package de.ellpeck.prettypipes.pipe.modules.stacksize;
import de.ellpeck.prettypipes.pipe.containers.AbstractPipeContainer; import de.ellpeck.prettypipes.pipe.containers.AbstractPipeContainer;
import net.minecraft.core.BlockPos; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.world.entity.player.Player; import net.minecraft.inventory.container.ContainerType;
import net.minecraft.world.inventory.MenuType; import net.minecraft.util.math.BlockPos;
import javax.annotation.Nullable; import javax.annotation.Nullable;
public class StackSizeModuleContainer extends AbstractPipeContainer<StackSizeModuleItem> { public class StackSizeModuleContainer extends AbstractPipeContainer<StackSizeModuleItem> {
public StackSizeModuleContainer(@Nullable ContainerType<?> type, int id, PlayerEntity player, BlockPos pos, int moduleIndex) {
public StackSizeModuleContainer(@Nullable MenuType<?> type, int id, Player player, BlockPos pos, int moduleIndex) {
super(type, id, player, pos, moduleIndex); super(type, id, player, pos, moduleIndex);
} }

View file

@ -1,59 +1,57 @@
package de.ellpeck.prettypipes.pipe.modules.stacksize; package de.ellpeck.prettypipes.pipe.modules.stacksize;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.matrix.MatrixStack;
import de.ellpeck.prettypipes.PrettyPipes; import de.ellpeck.prettypipes.PrettyPipes;
import de.ellpeck.prettypipes.packets.PacketButton; import de.ellpeck.prettypipes.packets.PacketButton;
import de.ellpeck.prettypipes.packets.PacketButton.ButtonResult; import de.ellpeck.prettypipes.packets.PacketButton.ButtonResult;
import de.ellpeck.prettypipes.pipe.containers.AbstractPipeGui; import de.ellpeck.prettypipes.pipe.containers.AbstractPipeGui;
import net.minecraft.client.gui.components.Button; import net.minecraft.client.gui.widget.TextFieldWidget;
import net.minecraft.client.gui.components.EditBox; import net.minecraft.client.gui.widget.button.Button;
import net.minecraft.client.resources.language.I18n; import net.minecraft.client.resources.I18n;
import net.minecraft.network.chat.Component; import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.network.chat.TranslatableComponent; import net.minecraft.util.text.ITextComponent;
import net.minecraft.world.entity.player.Inventory; import net.minecraft.util.text.TranslationTextComponent;
import java.util.function.Supplier; import java.util.function.Supplier;
public class StackSizeModuleGui extends AbstractPipeGui<StackSizeModuleContainer> { public class StackSizeModuleGui extends AbstractPipeGui<StackSizeModuleContainer> {
public StackSizeModuleGui(StackSizeModuleContainer screenContainer, PlayerInventory inv, ITextComponent titleIn) {
public StackSizeModuleGui(StackSizeModuleContainer screenContainer, Inventory inv, Component titleIn) {
super(screenContainer, inv, titleIn); super(screenContainer, inv, titleIn);
} }
@Override @Override
protected void init() { protected void init() {
super.init(); super.init();
var textField = this.addRenderableWidget(new EditBox(this.font, this.leftPos + 7, this.topPos + 17 + 32 + 10, 40, 20, new TranslatableComponent("info." + PrettyPipes.ID + ".max_stack_size")) { TextFieldWidget textField = this.addButton(new TextFieldWidget(this.font, this.guiLeft + 7, this.guiTop + 17 + 32 + 10, 40, 20, new TranslationTextComponent("info." + PrettyPipes.ID + ".max_stack_size")) {
@Override @Override
public void insertText(String textToWrite) { public void writeText(String textToWrite) {
var ret = new StringBuilder(); StringBuilder ret = new StringBuilder();
for (var c : textToWrite.toCharArray()) { for (char c : textToWrite.toCharArray()) {
if (Character.isDigit(c)) if (Character.isDigit(c))
ret.append(c); ret.append(c);
} }
super.insertText(ret.toString()); super.writeText(ret.toString());
} }
}); });
textField.setValue(String.valueOf(StackSizeModuleItem.getMaxStackSize(this.menu.moduleStack))); textField.setText(String.valueOf(StackSizeModuleItem.getMaxStackSize(this.container.moduleStack)));
textField.setMaxLength(4); textField.setMaxStringLength(4);
textField.setResponder(s -> { textField.setResponder(s -> {
if (s.isEmpty()) if (s.isEmpty())
return; return;
var amount = Integer.parseInt(s); int amount = Integer.parseInt(s);
PacketButton.sendAndExecute(this.menu.tile.getBlockPos(), ButtonResult.STACK_SIZE_AMOUNT, amount); PacketButton.sendAndExecute(this.container.tile.getPos(), ButtonResult.STACK_SIZE_AMOUNT, amount);
}); });
var buttonText = (Supplier<TranslatableComponent>) () -> new TranslatableComponent("info." + PrettyPipes.ID + ".limit_to_max_" + (StackSizeModuleItem.getLimitToMaxStackSize(this.menu.moduleStack) ? "on" : "off")); Supplier<TranslationTextComponent> buttonText = () -> new TranslationTextComponent("info." + PrettyPipes.ID + ".limit_to_max_" + (StackSizeModuleItem.getLimitToMaxStackSize(this.container.moduleStack) ? "on" : "off"));
this.addRenderableWidget(new Button(this.leftPos + 7, this.topPos + 17 + 32 + 10 + 22, 120, 20, buttonText.get(), b -> { this.addButton(new Button(this.guiLeft + 7, this.guiTop + 17 + 32 + 10 + 22, 120, 20, buttonText.get(), b -> {
PacketButton.sendAndExecute(this.menu.tile.getBlockPos(), ButtonResult.STACK_SIZE_MODULE_BUTTON); PacketButton.sendAndExecute(this.container.tile.getPos(), ButtonResult.STACK_SIZE_MODULE_BUTTON);
b.setMessage(buttonText.get()); b.setMessage(buttonText.get());
})); }));
} }
@Override @Override
protected void renderLabels(PoseStack matrix, int mouseX, int mouseY) { protected void drawGuiContainerForegroundLayer(MatrixStack matrix, int mouseX, int mouseY) {
super.renderLabels(matrix, mouseX, mouseY); super.drawGuiContainerForegroundLayer(matrix, mouseX, mouseY);
this.font.draw(matrix, I18n.get("info." + PrettyPipes.ID + ".max_stack_size") + ":", 7, 17 + 32, 4210752); this.font.drawString(matrix, I18n.format("info." + PrettyPipes.ID + ".max_stack_size") + ":", 7, 17 + 32, 4210752);
} }
} }

View file

@ -4,10 +4,10 @@ import de.ellpeck.prettypipes.Registry;
import de.ellpeck.prettypipes.items.IModule; import de.ellpeck.prettypipes.items.IModule;
import de.ellpeck.prettypipes.items.ModuleItem; import de.ellpeck.prettypipes.items.ModuleItem;
import de.ellpeck.prettypipes.misc.ItemEquality; import de.ellpeck.prettypipes.misc.ItemEquality;
import de.ellpeck.prettypipes.pipe.PipeBlockEntity; import de.ellpeck.prettypipes.pipe.PipeTileEntity;
import de.ellpeck.prettypipes.pipe.containers.AbstractPipeContainer; import de.ellpeck.prettypipes.pipe.containers.AbstractPipeContainer;
import net.minecraft.world.entity.player.Inventory; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.world.entity.player.Player; import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.IItemHandler;
@ -20,7 +20,7 @@ public class StackSizeModuleItem extends ModuleItem {
public static int getMaxStackSize(ItemStack module) { public static int getMaxStackSize(ItemStack module) {
if (module.hasTag()) { if (module.hasTag()) {
var amount = module.getTag().getInt("max_stack_size"); int amount = module.getTag().getInt("max_stack_size");
if (amount > 0) if (amount > 0)
return amount; return amount;
} }
@ -42,13 +42,13 @@ public class StackSizeModuleItem extends ModuleItem {
} }
@Override @Override
public int getMaxInsertionAmount(ItemStack module, PipeBlockEntity tile, ItemStack stack, IItemHandler destination) { public int getMaxInsertionAmount(ItemStack module, PipeTileEntity tile, ItemStack stack, IItemHandler destination) {
var max = getMaxStackSize(module); int max = getMaxStackSize(module);
if (getLimitToMaxStackSize(module)) if (getLimitToMaxStackSize(module))
max = Math.min(max, stack.getMaxStackSize()); max = Math.min(max, stack.getMaxStackSize());
var amount = 0; int amount = 0;
for (var i = 0; i < destination.getSlots(); i++) { for (int i = 0; i < destination.getSlots(); i++) {
var stored = destination.getStackInSlot(i); ItemStack stored = destination.getStackInSlot(i);
if (stored.isEmpty()) if (stored.isEmpty())
continue; continue;
if (!ItemEquality.compareItems(stored, stack)) if (!ItemEquality.compareItems(stored, stack))
@ -61,17 +61,17 @@ public class StackSizeModuleItem extends ModuleItem {
} }
@Override @Override
public boolean isCompatible(ItemStack module, PipeBlockEntity tile, IModule other) { public boolean isCompatible(ItemStack module, PipeTileEntity tile, IModule other) {
return !(other instanceof StackSizeModuleItem); return !(other instanceof StackSizeModuleItem);
} }
@Override @Override
public boolean hasContainer(ItemStack module, PipeBlockEntity tile) { public boolean hasContainer(ItemStack module, PipeTileEntity tile) {
return true; return true;
} }
@Override @Override
public AbstractPipeContainer<?> getContainer(ItemStack module, PipeBlockEntity tile, int windowId, Inventory inv, Player player, int moduleIndex) { public AbstractPipeContainer<?> getContainer(ItemStack module, PipeTileEntity tile, int windowId, PlayerInventory inv, PlayerEntity player, int moduleIndex) {
return new StackSizeModuleContainer(Registry.stackSizeModuleContainer, windowId, player, tile.getBlockPos(), moduleIndex); return new StackSizeModuleContainer(Registry.stackSizeModuleContainer, windowId, player, tile.getPos(), moduleIndex);
} }
} }

View file

@ -1,68 +1,56 @@
package de.ellpeck.prettypipes.pressurizer; package de.ellpeck.prettypipes.pressurizer;
import de.ellpeck.prettypipes.Registry;
import de.ellpeck.prettypipes.Utility; import de.ellpeck.prettypipes.Utility;
import de.ellpeck.prettypipes.pipe.PipeBlockEntity; import net.minecraft.block.BlockRenderType;
import net.minecraft.core.BlockPos; import net.minecraft.block.BlockState;
import net.minecraft.network.chat.Component; import net.minecraft.block.ContainerBlock;
import net.minecraft.server.level.ServerPlayer; import net.minecraft.block.SoundType;
import net.minecraft.world.InteractionHand; import net.minecraft.block.material.Material;
import net.minecraft.world.InteractionResult; import net.minecraft.client.util.ITooltipFlag;
import net.minecraft.world.entity.player.Player; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.TooltipFlag; import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.level.BlockGetter; import net.minecraft.util.ActionResultType;
import net.minecraft.world.level.Level; import net.minecraft.util.Direction;
import net.minecraft.world.level.block.BaseEntityBlock; import net.minecraft.util.Hand;
import net.minecraft.world.level.block.RenderShape; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.level.block.SoundType; import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.util.text.ITextComponent;
import net.minecraft.world.level.block.entity.BlockEntityTicker; import net.minecraft.world.IBlockReader;
import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.World;
import net.minecraft.world.level.block.state.BlockBehaviour; import net.minecraftforge.fml.network.NetworkHooks;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.material.Material;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraftforge.network.NetworkHooks;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.List; import java.util.List;
public class PressurizerBlock extends BaseEntityBlock { public class PressurizerBlock extends ContainerBlock {
public PressurizerBlock() { public PressurizerBlock() {
super(BlockBehaviour.Properties.of(Material.STONE).strength(3).sound(SoundType.STONE)); super(Properties.create(Material.ROCK).hardnessAndResistance(3).sound(SoundType.STONE));
} }
@Override @Override
public InteractionResult use(BlockState state, Level worldIn, BlockPos pos, Player player, InteractionHand handIn, BlockHitResult result) { public ActionResultType onBlockActivated(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand handIn, BlockRayTraceResult result) {
var tile = Utility.getBlockEntity(PressurizerBlockEntity.class, worldIn, pos); PressurizerBlockEntity tile = Utility.getBlockEntity(PressurizerBlockEntity.class, worldIn, pos);
if (tile == null) if (tile == null)
return InteractionResult.PASS; return ActionResultType.PASS;
if (!worldIn.isClientSide) if (!worldIn.isRemote)
NetworkHooks.openGui((ServerPlayer) player, tile, pos); NetworkHooks.openGui((ServerPlayerEntity) player, tile, pos);
return InteractionResult.SUCCESS; return ActionResultType.SUCCESS;
}
@org.jetbrains.annotations.Nullable
@Override
public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {
return new PressurizerBlockEntity(pos, state);
} }
@Override @Override
public RenderShape getRenderShape(BlockState state) { public TileEntity createNewTileEntity(IBlockReader worldIn) {
return RenderShape.MODEL; return new PressurizerBlockEntity();
} }
@Override @Override
public void appendHoverText(ItemStack stack, @Nullable BlockGetter worldIn, List<Component> tooltip, TooltipFlag flagIn) { 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); Utility.addTooltip(this.getRegistryName().getPath(), tooltip);
} }
@org.jetbrains.annotations.Nullable
@Override
public <T extends BlockEntity> BlockEntityTicker<T> getTicker(Level level, BlockState state, BlockEntityType<T> type) {
return level.isClientSide ? null : createTickerHelper(type, Registry.pressurizerBlockEntity, PressurizerBlockEntity::tick);
}
} }

View file

@ -6,21 +6,25 @@ import de.ellpeck.prettypipes.Utility;
import de.ellpeck.prettypipes.network.PipeNetwork; import de.ellpeck.prettypipes.network.PipeNetwork;
import de.ellpeck.prettypipes.pipe.ConnectionType; import de.ellpeck.prettypipes.pipe.ConnectionType;
import de.ellpeck.prettypipes.pipe.IPipeConnectable; import de.ellpeck.prettypipes.pipe.IPipeConnectable;
import net.minecraft.core.BlockPos; import de.ellpeck.prettypipes.pipe.PipeTileEntity;
import net.minecraft.core.Direction; import net.minecraft.block.BlockState;
import net.minecraft.nbt.CompoundTag; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.network.Connection; import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.network.chat.Component; import net.minecraft.inventory.container.Container;
import net.minecraft.network.chat.TranslatableComponent; import net.minecraft.inventory.container.INamedContainerProvider;
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket;
import net.minecraft.world.MenuProvider;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level; import net.minecraft.nbt.CompoundTag;
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.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.energy.CapabilityEnergy; import net.minecraftforge.energy.CapabilityEnergy;
@ -29,19 +33,19 @@ import net.minecraftforge.energy.IEnergyStorage;
import javax.annotation.Nullable; import javax.annotation.Nullable;
public class PressurizerBlockEntity extends BlockEntity implements MenuProvider, IPipeConnectable { public class PressurizerBlockEntity extends BlockEntity implements INamedContainerProvider, ITickableTileEntity, IPipeConnectable {
private final ModifiableEnergyStorage storage = new ModifiableEnergyStorage(64000, 512, 0); private final ModifiableEnergyStorage storage = new ModifiableEnergyStorage(64000, 512, 0);
private final LazyOptional<IEnergyStorage> lazyStorage = LazyOptional.of(() -> this.storage); private final LazyOptional<IEnergyStorage> lazyStorage = LazyOptional.of(() -> this.storage);
private final LazyOptional<IPipeConnectable> lazyThis = LazyOptional.of(() -> this); private final LazyOptional<IPipeConnectable> lazyThis = LazyOptional.of(() -> this);
private int lastEnergy; private int lastEnergy;
public PressurizerBlockEntity(BlockPos pos, BlockState state) { public PressurizerBlockEntity() {
super(Registry.pressurizerBlockEntity, pos, state); super(Registry.pressurizerTileEntity);
} }
public boolean pressurizeItem(ItemStack stack, boolean simulate) { public boolean pressurizeItem(ItemStack stack, boolean simulate) {
var amount = 100 * stack.getCount(); int amount = 100 * stack.getCount();
return this.storage.extractInternal(amount, simulate) >= amount; return this.storage.extractInternal(amount, simulate) >= amount;
} }
@ -58,41 +62,41 @@ public class PressurizerBlockEntity extends BlockEntity implements MenuProvider,
} }
@Override @Override
public CompoundTag save(CompoundTag compound) { public CompoundTag write(CompoundTag compound) {
compound.putInt("energy", this.getEnergy()); compound.putInt("energy", this.getEnergy());
return super.save(compound); return super.write(compound);
} }
@Override @Override
public void load(CompoundTag nbt) { public void read(BlockState state, CompoundTag nbt) {
this.storage.setEnergyStored(nbt.getInt("energy")); this.storage.setEnergyStored(nbt.getInt("energy"));
super.load(nbt); super.read(state, nbt);
} }
@Override @Override
public CompoundTag getUpdateTag() { public CompoundTag getUpdateTag() {
return this.save(new CompoundTag()); return this.write(new CompoundTag());
} }
@Override @Override
public void handleUpdateTag(CompoundTag tag) { public void handleUpdateTag(BlockState state, CompoundTag tag) {
this.load(tag); this.read(state, tag);
} }
@Override @Override
public void onDataPacket(Connection net, ClientboundBlockEntityDataPacket pkt) { public void onDataPacket(NetworkManager net, SUpdateTileEntityPacket pkt) {
this.load(pkt.getTag()); this.read(this.getBlockState(), pkt.getNbtCompound());
} }
@Override @Override
public Component getDisplayName() { public ITextComponent getDisplayName() {
return new TranslatableComponent("container." + PrettyPipes.ID + ".pressurizer"); return new TranslationTextComponent("container." + PrettyPipes.ID + ".pressurizer");
} }
@Nullable @Nullable
@Override @Override
public AbstractContainerMenu createMenu(int window, Inventory inv, Player player) { public Container createMenu(int window, PlayerInventory inv, PlayerEntity player) {
return new PressurizerContainer(Registry.pressurizerContainer, window, player, this.worldPosition); return new PressurizerContainer(Registry.pressurizerContainer, window, player, this.pos);
} }
@Override @Override
@ -107,40 +111,43 @@ public class PressurizerBlockEntity extends BlockEntity implements MenuProvider,
} }
@Override @Override
public void setRemoved() { public void remove() {
super.setRemoved(); super.remove();
this.lazyStorage.invalidate(); this.lazyStorage.invalidate();
this.lazyThis.invalidate(); this.lazyThis.invalidate();
} }
@Override @Override
public ConnectionType getConnectionType(BlockPos pipePos, Direction direction) { public void tick() {
return ConnectionType.CONNECTED; if (this.world.isRemote)
} return;
public static void tick(Level level, BlockPos pos, BlockState state, PressurizerBlockEntity pressurizer) {
// notify pipes in network about us // notify pipes in network about us
if (pressurizer.level.getGameTime() % 10 == 0) { if (this.world.getGameTime() % 10 == 0) {
var network = PipeNetwork.get(pressurizer.level); PipeNetwork network = PipeNetwork.get(this.world);
for (var dir : Direction.values()) { for (Direction dir : Direction.values()) {
var offset = pressurizer.worldPosition.relative(dir); BlockPos offset = this.pos.offset(dir);
for (var node : network.getOrderedNetworkNodes(offset)) { for (BlockPos node : network.getOrderedNetworkNodes(offset)) {
if (!pressurizer.level.isLoaded(node)) if (!this.world.isBlockLoaded(node))
continue; continue;
var pipe = network.getPipe(node); PipeTileEntity pipe = network.getPipe(node);
if (pipe != null) if (pipe != null)
pipe.pressurizer = pressurizer; pipe.pressurizer = this;
} }
} }
} }
// send energy update // send energy update
if (pressurizer.lastEnergy != pressurizer.storage.getEnergyStored() && pressurizer.level.getGameTime() % 10 == 0) { if (this.lastEnergy != this.storage.getEnergyStored() && this.world.getGameTime() % 10 == 0) {
pressurizer.lastEnergy = pressurizer.storage.getEnergyStored(); this.lastEnergy = this.storage.getEnergyStored();
Utility.sendBlockEntityToClients(pressurizer); Utility.sendBlockEntityToClients(this);
} }
} }
@Override
public ConnectionType getConnectionType(BlockPos pipePos, Direction direction) {
return ConnectionType.CONNECTED;
}
private static class ModifiableEnergyStorage extends EnergyStorage { private static class ModifiableEnergyStorage extends EnergyStorage {
public ModifiableEnergyStorage(int capacity, int maxReceive, int maxExtract) { public ModifiableEnergyStorage(int capacity, int maxReceive, int maxExtract) {
@ -152,7 +159,7 @@ public class PressurizerBlockEntity extends BlockEntity implements MenuProvider,
} }
private int extractInternal(int maxExtract, boolean simulate) { private int extractInternal(int maxExtract, boolean simulate) {
var energyExtracted = Math.min(this.energy, maxExtract); int energyExtracted = Math.min(this.energy, maxExtract);
if (!simulate) if (!simulate)
this.energy -= energyExtracted; this.energy -= energyExtracted;
return energyExtracted; return energyExtracted;

View file

@ -2,36 +2,40 @@ package de.ellpeck.prettypipes.pressurizer;
import de.ellpeck.prettypipes.Utility; import de.ellpeck.prettypipes.Utility;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
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.world.entity.player.Player; import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.inventory.MenuType; import net.minecraft.world.inventory.MenuType;
import net.minecraft.world.inventory.Slot; import net.minecraft.world.inventory.Slot;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.util.math.BlockPos;
import javax.annotation.Nullable; import javax.annotation.Nullable;
public class PressurizerContainer extends AbstractContainerMenu { public class PressurizerContainer extends AbstractContainerMenu {
public final PressurizerBlockEntity tile; public final PressurizerBlockEntity tile;
public PressurizerContainer(@Nullable MenuType<?> type, int id, Player player, BlockPos pos) { public PressurizerContainer(@Nullable MenuType<?> type, int id, Player player, BlockPos pos) {
super(type, id); super(type, id);
this.tile = Utility.getBlockEntity(PressurizerBlockEntity.class, player.level, pos); this.tile = Utility.getBlockEntity(PressurizerBlockEntity.class, player.level, pos);
for (var l = 0; l < 3; ++l) for (int l = 0; l < 3; ++l)
for (var j1 = 0; j1 < 9; ++j1) for (int j1 = 0; j1 < 9; ++j1)
this.addSlot(new Slot(player.getInventory(), j1 + l * 9 + 9, 8 + j1 * 18, 55 + l * 18)); this.addSlot(new Slot(player.getInventory(), j1 + l * 9 + 9, 8 + j1 * 18, 55 + l * 18));
for (var i1 = 0; i1 < 9; ++i1) for (int i1 = 0; i1 < 9; ++i1)
this.addSlot(new Slot(player.getInventory(), i1, 8 + i1 * 18, 113)); this.addSlot(new Slot(player.getInventory(), i1, 8 + i1 * 18, 113));
} }
@Override @Override
public ItemStack quickMoveStack(Player player, int slotIndex) { public ItemStack transferStackInSlot(PlayerEntity player, int slotIndex) {
return Utility.transferStackInSlot(this, this::moveItemStackTo, player, slotIndex, stack -> null); return Utility.transferStackInSlot(this, this::mergeItemStack, player, slotIndex, stack -> null);
} }
@Override @Override
public boolean stillValid(Player player) { public boolean canInteractWith(PlayerEntity playerIn) {
return true; return true;
} }
} }

View file

@ -1,43 +1,43 @@
package de.ellpeck.prettypipes.pressurizer; package de.ellpeck.prettypipes.pressurizer;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.matrix.MatrixStack;
import de.ellpeck.prettypipes.PrettyPipes; import de.ellpeck.prettypipes.PrettyPipes;
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; import net.minecraft.client.gui.screen.inventory.ContainerScreen;
import net.minecraft.network.chat.Component; import net.minecraft.client.gui.widget.Widget;
import net.minecraft.network.chat.TranslatableComponent; import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.entity.player.Inventory; import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TranslationTextComponent;
public class PressurizerGui extends AbstractContainerScreen<PressurizerContainer> {
public class PressurizerGui extends ContainerScreen<PressurizerContainer> {
private static final ResourceLocation TEXTURE = new ResourceLocation(PrettyPipes.ID, "textures/gui/pressurizer.png"); private static final ResourceLocation TEXTURE = new ResourceLocation(PrettyPipes.ID, "textures/gui/pressurizer.png");
public PressurizerGui(PressurizerContainer screenContainer, Inventory inv, Component titleIn) { public PressurizerGui(PressurizerContainer screenContainer, PlayerInventory inv, ITextComponent titleIn) {
super(screenContainer, inv, titleIn); super(screenContainer, inv, titleIn);
this.imageWidth = 176; this.xSize = 176;
this.imageHeight = 137; this.ySize = 137;
} }
@Override @Override
public void render(PoseStack matrix, int mouseX, int mouseY, float partialTicks) { public void render(MatrixStack matrix, int mouseX, int mouseY, float partialTicks) {
this.renderBackground(matrix); this.renderBackground(matrix);
super.render(matrix, mouseX, mouseY, partialTicks); super.render(matrix, mouseX, mouseY, partialTicks);
this.renderTooltip(matrix, mouseX, mouseY); this.func_230459_a_(matrix, mouseX, mouseY);
if (mouseX >= this.leftPos + 26 && mouseY >= this.topPos + 22 && mouseX < this.leftPos + 26 + 124 && mouseY < this.topPos + 22 + 12) if (mouseX >= this.guiLeft + 26 && mouseY >= this.guiTop + 22 && mouseX < this.guiLeft + 26 + 124 && mouseY < this.guiTop + 22 + 12)
this.renderTooltip(matrix, new TranslatableComponent("info." + PrettyPipes.ID + ".energy", this.menu.tile.getEnergy(), this.menu.tile.getMaxEnergy()), mouseX, mouseY); this.renderTooltip(matrix, new TranslationTextComponent("info." + PrettyPipes.ID + ".energy", this.container.tile.getEnergy(), this.container.tile.getMaxEnergy()), mouseX, mouseY);
} }
@Override @Override
protected void renderLabels(PoseStack matrix, int mouseX, int mouseY) { protected void drawGuiContainerForegroundLayer(MatrixStack matrix, int mouseX, int mouseY) {
this.font.draw(matrix, this.playerInventoryTitle.getString(), 8, this.imageHeight - 96 + 2, 4210752); this.font.drawString(matrix, this.playerInventory.getDisplayName().getString(), 8, this.ySize - 96 + 2, 4210752);
this.font.draw(matrix, this.title.getString(), 8, 6, 4210752); this.font.drawString(matrix, this.title.getString(), 8, 6, 4210752);
} }
@Override @Override
protected void renderBg(PoseStack matrixStack, float partialTicks, int x, int y) { protected void drawGuiContainerBackgroundLayer(MatrixStack matrixStack, float partialTicks, int x, int y) {
this.getMinecraft().getTextureManager().bindForSetup(TEXTURE); this.getMinecraft().getTextureManager().bindTexture(TEXTURE);
this.blit(matrixStack, this.leftPos, this.topPos, 0, 0, 176, 137); this.blit(matrixStack, this.guiLeft, this.guiTop, 0, 0, 176, 137);
var energy = (int) (this.menu.tile.getEnergyPercentage() * 124); int energy = (int) (this.container.tile.getEnergyPercentage() * 124);
this.blit(matrixStack, this.leftPos + 26, this.topPos + 22, 0, 137, energy, 12); this.blit(matrixStack, this.guiLeft + 26, this.guiTop + 22, 0, 137, energy, 12);
} }
} }

View file

@ -1,23 +1,16 @@
package de.ellpeck.prettypipes.terminal; package de.ellpeck.prettypipes.terminal;
import de.ellpeck.prettypipes.Registry; import net.minecraft.tileentity.TileEntity;
import net.minecraft.core.BlockPos; import net.minecraft.world.IBlockReader;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.BlockEntity; import javax.annotation.Nullable;
import net.minecraft.world.level.block.entity.BlockEntityTicker;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
public class CraftingTerminalBlock extends ItemTerminalBlock { public class CraftingTerminalBlock extends ItemTerminalBlock {
@Nullable
@Override @Override
public @org.jetbrains.annotations.Nullable BlockEntity newBlockEntity(BlockPos pos, BlockState state) { public TileEntity createNewTileEntity(IBlockReader worldIn) {
return new CraftingTerminalBlockEntity(pos, state); return new CraftingTerminalTileEntity();
} }
@org.jetbrains.annotations.Nullable
@Override
public <T extends BlockEntity> BlockEntityTicker<T> getTicker(Level level, BlockState state, BlockEntityType<T> type) {
return createTickerHelper(type, Registry.craftingTerminalBlockEntity, ItemTerminalBlockEntity::tick);
}
} }

View file

@ -7,24 +7,25 @@ import de.ellpeck.prettypipes.Registry;
import de.ellpeck.prettypipes.Utility; import de.ellpeck.prettypipes.Utility;
import de.ellpeck.prettypipes.misc.EquatableItemStack; import de.ellpeck.prettypipes.misc.EquatableItemStack;
import de.ellpeck.prettypipes.misc.ItemEquality; import de.ellpeck.prettypipes.misc.ItemEquality;
import de.ellpeck.prettypipes.network.NetworkItem;
import de.ellpeck.prettypipes.network.NetworkLocation; import de.ellpeck.prettypipes.network.NetworkLocation;
import de.ellpeck.prettypipes.network.PipeNetwork; import de.ellpeck.prettypipes.network.PipeNetwork;
import de.ellpeck.prettypipes.packets.PacketGhostSlot; import de.ellpeck.prettypipes.packets.PacketGhostSlot;
import de.ellpeck.prettypipes.packets.PacketHandler; import de.ellpeck.prettypipes.packets.PacketHandler;
import de.ellpeck.prettypipes.pipe.PipeBlockEntity; import de.ellpeck.prettypipes.pipe.PipeTileEntity;
import de.ellpeck.prettypipes.terminal.containers.CraftingTerminalContainer; import de.ellpeck.prettypipes.terminal.containers.CraftingTerminalContainer;
import net.minecraft.ChatFormatting; import net.minecraft.block.BlockState;
import net.minecraft.core.BlockPos; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.core.Direction; import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.nbt.CompoundTag; import net.minecraft.inventory.container.Container;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.Style;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.nbt.CompoundTag;
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.ItemHandlerHelper;
import net.minecraftforge.items.ItemStackHandler; import net.minecraftforge.items.ItemStackHandler;
import org.apache.commons.lang3.mutable.MutableInt; import org.apache.commons.lang3.mutable.MutableInt;
@ -35,23 +36,23 @@ import java.util.function.Consumer;
import java.util.function.Function; import java.util.function.Function;
import java.util.function.Predicate; import java.util.function.Predicate;
public class CraftingTerminalBlockEntity extends ItemTerminalBlockEntity { public class CraftingTerminalTileEntity extends ItemTerminalTileEntity {
public final ItemStackHandler craftItems = new ItemStackHandler(9) { public final ItemStackHandler craftItems = new ItemStackHandler(9) {
@Override @Override
protected void onContentsChanged(int slot) { protected void onContentsChanged(int slot) {
for (var playerEntity : CraftingTerminalBlockEntity.this.getLookingPlayers()) for (PlayerEntity playerEntity : CraftingTerminalTileEntity.this.getLookingPlayers())
playerEntity.containerMenu.slotsChanged(null); playerEntity.openContainer.onCraftMatrixChanged(null);
} }
}; };
public final ItemStackHandler ghostItems = new ItemStackHandler(9); public final ItemStackHandler ghostItems = new ItemStackHandler(9);
public CraftingTerminalBlockEntity(BlockPos pos, BlockState state) { public CraftingTerminalTileEntity() {
super(Registry.craftingTerminalBlockEntity, pos, state); super(Registry.craftingTerminalTileEntity);
} }
public ItemStack getRequestedCraftItem(int slot) { public ItemStack getRequestedCraftItem(int slot) {
var stack = this.craftItems.getStackInSlot(slot); ItemStack stack = this.craftItems.getStackInSlot(slot);
if (!stack.isEmpty()) if (!stack.isEmpty())
return stack; return stack;
return this.ghostItems.getStackInSlot(slot); return this.ghostItems.getStackInSlot(slot);
@ -63,30 +64,30 @@ public class CraftingTerminalBlockEntity extends ItemTerminalBlockEntity {
public void setGhostItems(ListMultimap<Integer, ItemStack> stacks) { public void setGhostItems(ListMultimap<Integer, ItemStack> stacks) {
this.updateItems(); this.updateItems();
for (var i = 0; i < this.ghostItems.getSlots(); i++) { for (int i = 0; i < this.ghostItems.getSlots(); i++) {
var items = stacks.get(i); List<ItemStack> items = stacks.get(i);
if (items.isEmpty()) { if (items.isEmpty()) {
this.ghostItems.setStackInSlot(i, ItemStack.EMPTY); this.ghostItems.setStackInSlot(i, ItemStack.EMPTY);
continue; continue;
} }
var toSet = items.get(0); 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 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) { if (items.size() > 1) {
var highestAmount = 0; int highestAmount = 0;
for (var stack : items) { for (ItemStack stack : items) {
var amount = 0; int amount = 0;
// check existing items // check existing items
var network = this.networkItems.get(new EquatableItemStack(stack, ItemEquality.NBT)); NetworkItem network = this.networkItems.get(new EquatableItemStack(stack, ItemEquality.NBT));
if (network != null) { if (network != null) {
amount = network.getLocations().stream() amount = network.getLocations().stream()
.mapToInt(l -> l.getItemAmount(this.level, stack, ItemEquality.NBT)) .mapToInt(l -> l.getItemAmount(this.world, stack, ItemEquality.NBT))
.sum(); .sum();
} }
// check craftables // check craftables
if (amount <= 0 && highestAmount <= 0) { if (amount <= 0 && highestAmount <= 0) {
var pipe = this.getConnectedPipe(); PipeTileEntity pipe = this.getConnectedPipe();
if (pipe != null) if (pipe != null)
amount = PipeNetwork.get(this.level).getCraftableAmount(pipe.getBlockPos(), null, stack, new Stack<>(), ItemEquality.NBT); amount = PipeNetwork.get(this.world).getCraftableAmount(pipe.getPos(), null, stack, new Stack<>(), ItemEquality.NBT);
} }
if (amount > highestAmount) { if (amount > highestAmount) {
highestAmount = amount; highestAmount = amount;
@ -97,77 +98,77 @@ public class CraftingTerminalBlockEntity extends ItemTerminalBlockEntity {
this.ghostItems.setStackInSlot(i, toSet.copy()); this.ghostItems.setStackInSlot(i, toSet.copy());
} }
if (!this.level.isClientSide) { if (!this.world.isRemote) {
ListMultimap<Integer, ItemStack> clients = ArrayListMultimap.create(); ListMultimap<Integer, ItemStack> clients = ArrayListMultimap.create();
for (var i = 0; i < this.ghostItems.getSlots(); i++) for (int i = 0; i < this.ghostItems.getSlots(); i++)
clients.put(i, this.ghostItems.getStackInSlot(i)); clients.put(i, this.ghostItems.getStackInSlot(i));
PacketHandler.sendToAllLoaded(this.level, this.getBlockPos(), new PacketGhostSlot(this.getBlockPos(), clients)); PacketHandler.sendToAllLoaded(this.world, this.pos, new PacketGhostSlot(this.pos, clients));
} }
} }
public void requestCraftingItems(Player player, int maxAmount) { public void requestCraftingItems(PlayerEntity player, int maxAmount) {
var pipe = this.getConnectedPipe(); PipeTileEntity pipe = this.getConnectedPipe();
if (pipe == null) if (pipe == null)
return; return;
var network = PipeNetwork.get(this.level); PipeNetwork network = PipeNetwork.get(this.world);
network.startProfile("terminal_request_crafting"); network.startProfile("terminal_request_crafting");
this.updateItems(); this.updateItems();
// get the amount of crafts that we can do // get the amount of crafts that we can do
var lowestAvailable = getAvailableCrafts(pipe, this.craftItems.getSlots(), i -> ItemHandlerHelper.copyStackWithSize(this.getRequestedCraftItem(i), 1), this::isGhostItem, s -> { int lowestAvailable = getAvailableCrafts(pipe, this.craftItems.getSlots(), i -> ItemHandlerHelper.copyStackWithSize(this.getRequestedCraftItem(i), 1), this::isGhostItem, s -> {
var item = this.networkItems.get(s); NetworkItem item = this.networkItems.get(s);
return item != null ? item.getLocations() : Collections.emptyList(); return item != null ? item.getLocations() : Collections.emptyList();
}, onItemUnavailable(player), new Stack<>(), ItemEquality.NBT); }, onItemUnavailable(player), new Stack<>(), ItemEquality.NBT);
if (lowestAvailable > 0) { if (lowestAvailable > 0) {
// if we're limiting the amount, pretend we only have that amount available // if we're limiting the amount, pretend we only have that amount available
if (maxAmount < lowestAvailable) if (maxAmount < lowestAvailable)
lowestAvailable = maxAmount; lowestAvailable = maxAmount;
for (var i = 0; i < this.craftItems.getSlots(); i++) { for (int i = 0; i < this.craftItems.getSlots(); i++) {
var requested = this.getRequestedCraftItem(i); ItemStack requested = this.getRequestedCraftItem(i);
if (requested.isEmpty()) if (requested.isEmpty())
continue; continue;
requested = requested.copy(); requested = requested.copy();
requested.setCount(lowestAvailable); requested.setCount(lowestAvailable);
this.requestItemImpl(requested, onItemUnavailable(player)); this.requestItemImpl(requested, onItemUnavailable(player));
} }
player.sendMessage(new TranslatableComponent("info." + PrettyPipes.ID + ".sending_ingredients", lowestAvailable).setStyle(Style.EMPTY.applyFormat(ChatFormatting.GREEN)), UUID.randomUUID()); player.sendMessage(new TranslationTextComponent("info." + PrettyPipes.ID + ".sending_ingredients", lowestAvailable).setStyle(Style.EMPTY.setFormatting(TextFormatting.GREEN)), UUID.randomUUID());
} }
network.endProfile(); network.endProfile();
} }
@Override @Override
public CompoundTag save(CompoundTag compound) { public CompoundTag write(CompoundTag compound) {
compound.put("craft_items", this.craftItems.serializeNBT()); compound.put("craft_items", this.craftItems.serializeNBT());
return super.save(compound); return super.write(compound);
} }
@Override @Override
public void load(CompoundTag compound) { public void read(BlockState state, CompoundTag compound) {
this.craftItems.deserializeNBT(compound.getCompound("craft_items")); this.craftItems.deserializeNBT(compound.getCompound("craft_items"));
super.load(compound); super.read(state, compound);
} }
@Override @Override
public Component getDisplayName() { public ITextComponent getDisplayName() {
return new TranslatableComponent("container." + PrettyPipes.ID + ".crafting_terminal"); return new TranslationTextComponent("container." + PrettyPipes.ID + ".crafting_terminal");
} }
@Nullable @Nullable
@Override @Override
public AbstractContainerMenu createMenu(int window, Inventory inv, Player player) { public Container createMenu(int window, PlayerInventory inv, PlayerEntity player) {
return new CraftingTerminalContainer(Registry.craftingTerminalContainer, window, player, this.worldPosition); return new CraftingTerminalContainer(Registry.craftingTerminalContainer, window, player, this.pos);
} }
@Override @Override
public ItemStack insertItem(BlockPos pipePos, Direction direction, ItemStack remain, boolean simulate) { public ItemStack insertItem(BlockPos pipePos, Direction direction, ItemStack remain, boolean simulate) {
var pos = pipePos.relative(direction); BlockPos pos = pipePos.offset(direction);
var tile = Utility.getBlockEntity(CraftingTerminalBlockEntity.class, this.level, pos); CraftingTerminalTileEntity tile = Utility.getBlockEntity(CraftingTerminalTileEntity.class, this.world, pos);
if (tile != null) { if (tile != null) {
remain = remain.copy(); remain = remain.copy();
var lowestSlot = -1; int lowestSlot = -1;
do { do {
for (var i = 0; i < tile.craftItems.getSlots(); i++) { for (int i = 0; i < tile.craftItems.getSlots(); i++) {
var stack = tile.getRequestedCraftItem(i); ItemStack stack = tile.getRequestedCraftItem(i);
var count = tile.isGhostItem(i) ? 0 : stack.getCount(); int count = tile.isGhostItem(i) ? 0 : stack.getCount();
if (!ItemHandlerHelper.canItemStacksStack(stack, remain)) if (!ItemHandlerHelper.canItemStacksStack(stack, remain))
continue; continue;
// ensure that a single non-stackable item can still enter a ghost slot // ensure that a single non-stackable item can still enter a ghost slot
@ -177,7 +178,7 @@ public class CraftingTerminalBlockEntity extends ItemTerminalBlockEntity {
lowestSlot = i; lowestSlot = i;
} }
if (lowestSlot >= 0) { if (lowestSlot >= 0) {
var copy = remain.copy(); ItemStack copy = remain.copy();
copy.setCount(1); copy.setCount(1);
// if there were remaining items inserting into the slot with lowest contents, we're overflowing // if there were remaining items inserting into the slot with lowest contents, we're overflowing
if (tile.craftItems.insertItem(lowestSlot, copy, simulate).getCount() > 0) if (tile.craftItems.insertItem(lowestSlot, copy, simulate).getCount() > 0)
@ -193,33 +194,33 @@ public class CraftingTerminalBlockEntity extends ItemTerminalBlockEntity {
return remain; return remain;
} }
public static int getAvailableCrafts(PipeBlockEntity tile, int slots, Function<Integer, ItemStack> inputFunction, Predicate<Integer> isGhost, Function<EquatableItemStack, Collection<NetworkLocation>> locationsFunction, Consumer<ItemStack> unavailableConsumer, Stack<ItemStack> dependencyChain, ItemEquality... equalityTypes) { public static int getAvailableCrafts(PipeTileEntity tile, int slots, Function<Integer, ItemStack> inputFunction, Predicate<Integer> isGhost, Function<EquatableItemStack, Collection<NetworkLocation>> locationsFunction, Consumer<ItemStack> unavailableConsumer, Stack<ItemStack> dependencyChain, ItemEquality... equalityTypes) {
var network = PipeNetwork.get(tile.getLevel()); PipeNetwork network = PipeNetwork.get(tile.getWorld());
// the highest amount we can craft with the items we have // the highest amount we can craft with the items we have
var lowestAvailable = Integer.MAX_VALUE; int lowestAvailable = Integer.MAX_VALUE;
// this is the amount of items required for each ingredient when crafting ONE // this is the amount of items required for each ingredient when crafting ONE
Map<EquatableItemStack, MutableInt> requiredItems = new HashMap<>(); Map<EquatableItemStack, MutableInt> requiredItems = new HashMap<>();
for (var i = 0; i < slots; i++) { for (int i = 0; i < slots; i++) {
var requested = inputFunction.apply(i); ItemStack requested = inputFunction.apply(i);
if (requested.isEmpty()) if (requested.isEmpty())
continue; continue;
var amount = requiredItems.computeIfAbsent(new EquatableItemStack(requested, equalityTypes), s -> new MutableInt()); MutableInt amount = requiredItems.computeIfAbsent(new EquatableItemStack(requested, equalityTypes), s -> new MutableInt());
amount.add(requested.getCount()); amount.add(requested.getCount());
// if no items fit into the crafting input, we still want to pretend they do for requesting // if no items fit into the crafting input, we still want to pretend they do for requesting
var fit = Math.max(requested.getMaxStackSize() - (isGhost.test(i) ? 0 : requested.getCount()), 1); int fit = Math.max(requested.getMaxStackSize() - (isGhost.test(i) ? 0 : requested.getCount()), 1);
if (lowestAvailable > fit) if (lowestAvailable > fit)
lowestAvailable = fit; lowestAvailable = fit;
} }
for (var entry : requiredItems.entrySet()) { for (Map.Entry<EquatableItemStack, MutableInt> entry : requiredItems.entrySet()) {
var stack = entry.getKey(); EquatableItemStack stack = entry.getKey();
// total amount of available items of this type // total amount of available items of this type
var available = 0; int available = 0;
for (var location : locationsFunction.apply(stack)) { for (NetworkLocation location : locationsFunction.apply(stack)) {
var amount = location.getItemAmount(tile.getLevel(), stack.stack(), equalityTypes); int amount = location.getItemAmount(tile.getWorld(), stack.stack, equalityTypes);
if (amount <= 0) if (amount <= 0)
continue; continue;
amount -= network.getLockedAmount(location.getPos(), stack.stack(), null, equalityTypes); amount -= network.getLockedAmount(location.getPos(), stack.stack, null, equalityTypes);
available += amount; available += amount;
} }
// divide the total by the amount required to get the amount that // divide the total by the amount required to get the amount that
@ -228,17 +229,17 @@ public class CraftingTerminalBlockEntity extends ItemTerminalBlockEntity {
// check how many craftable items we have and add those on if we need to // check how many craftable items we have and add those on if we need to
if (available < lowestAvailable) { if (available < lowestAvailable) {
var craftable = network.getCraftableAmount(tile.getBlockPos(), unavailableConsumer, stack.stack(), dependencyChain, equalityTypes); int craftable = network.getCraftableAmount(tile.getPos(), unavailableConsumer, stack.stack, dependencyChain, equalityTypes);
if (craftable > 0) if (craftable > 0)
available += craftable / entry.getValue().intValue(); available += craftable / entry.getValue().intValue();
} }
// clamp to the lowest available // clamp to lowest available
if (available < lowestAvailable) if (available < lowestAvailable)
lowestAvailable = available; lowestAvailable = available;
if (available <= 0 && unavailableConsumer != null) if (available <= 0 && unavailableConsumer != null)
unavailableConsumer.accept(stack.stack()); unavailableConsumer.accept(stack.stack);
} }
return lowestAvailable; return lowestAvailable;
} }

View file

@ -1,88 +1,79 @@
package de.ellpeck.prettypipes.terminal; package de.ellpeck.prettypipes.terminal;
import de.ellpeck.prettypipes.Registry;
import de.ellpeck.prettypipes.Utility; import de.ellpeck.prettypipes.Utility;
import net.minecraft.ChatFormatting; import net.minecraft.block.BlockRenderType;
import net.minecraft.core.BlockPos; import net.minecraft.block.BlockState;
import net.minecraft.network.chat.Component; import net.minecraft.block.ContainerBlock;
import net.minecraft.network.chat.TranslatableComponent; import net.minecraft.block.SoundType;
import net.minecraft.server.level.ServerPlayer; import net.minecraft.block.material.Material;
import net.minecraft.world.InteractionHand; import net.minecraft.client.util.ITooltipFlag;
import net.minecraft.world.InteractionResult; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.world.entity.player.Player; import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.TooltipFlag; import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.level.BlockGetter; import net.minecraft.util.ActionResultType;
import net.minecraft.world.level.Level; import net.minecraft.util.Direction;
import net.minecraft.world.level.block.BaseEntityBlock; import net.minecraft.util.Hand;
import net.minecraft.world.level.block.RenderShape; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.level.block.SoundType; import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.util.text.ITextComponent;
import net.minecraft.world.level.block.entity.BlockEntityTicker; import net.minecraft.util.text.TextFormatting;
import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.util.text.TranslationTextComponent;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.IBlockReader;
import net.minecraft.world.level.material.Material; import net.minecraft.world.World;
import net.minecraft.world.phys.BlockHitResult; import net.minecraftforge.fml.network.NetworkHooks;
import net.minecraftforge.network.NetworkHooks;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
public class ItemTerminalBlock extends BaseEntityBlock { public class ItemTerminalBlock extends ContainerBlock {
public ItemTerminalBlock() { public ItemTerminalBlock() {
super(Properties.of(Material.STONE).strength(3).sound(SoundType.STONE)); super(Properties.create(Material.ROCK).hardnessAndResistance(3).sound(SoundType.STONE));
} }
@Override @Override
public InteractionResult use(BlockState state, Level worldIn, BlockPos pos, Player player, InteractionHand handIn, BlockHitResult result) { public ActionResultType onBlockActivated(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand handIn, BlockRayTraceResult result) {
var tile = Utility.getBlockEntity(ItemTerminalBlockEntity.class, worldIn, pos); ItemTerminalTileEntity tile = Utility.getBlockEntity(ItemTerminalTileEntity.class, worldIn, pos);
if (tile == null) if (tile == null)
return InteractionResult.PASS; return ActionResultType.PASS;
var reason = tile.getInvalidTerminalReason(); String reason = tile.getInvalidTerminalReason();
if (reason != null) { if (reason != null) {
if (!worldIn.isClientSide) if (!worldIn.isRemote)
player.sendMessage(new TranslatableComponent(reason).withStyle(ChatFormatting.RED), UUID.randomUUID()); player.sendMessage(new TranslationTextComponent(reason).mergeStyle(TextFormatting.RED), UUID.randomUUID());
return InteractionResult.SUCCESS; return ActionResultType.SUCCESS;
} }
if (!worldIn.isClientSide) { if (!worldIn.isRemote) {
NetworkHooks.openGui((ServerPlayer) player, tile, pos); NetworkHooks.openGui((ServerPlayerEntity) player, tile, pos);
tile.updateItems(player); tile.updateItems(player);
} }
return InteractionResult.SUCCESS; return ActionResultType.SUCCESS;
} }
@Override @Override
public void onRemove(BlockState state, Level worldIn, BlockPos pos, BlockState newState, boolean isMoving) { public void onReplaced(BlockState state, World worldIn, BlockPos pos, BlockState newState, boolean isMoving) {
if (state.getBlock() != newState.getBlock()) { if (state.getBlock() != newState.getBlock()) {
var tile = Utility.getBlockEntity(ItemTerminalBlockEntity.class, worldIn, pos); ItemTerminalTileEntity tile = Utility.getBlockEntity(ItemTerminalTileEntity.class, worldIn, pos);
if (tile != null) if (tile != null)
Utility.dropInventory(tile, tile.items); Utility.dropInventory(tile, tile.items);
super.onRemove(state, worldIn, pos, newState, isMoving); super.onReplaced(state, worldIn, pos, newState, isMoving);
} }
} }
@org.jetbrains.annotations.Nullable @Nullable
@Override @Override
public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { public TileEntity createNewTileEntity(IBlockReader worldIn) {
return new ItemTerminalBlockEntity(pos, state); return new ItemTerminalTileEntity();
} }
@Override @Override
public RenderShape getRenderShape(BlockState state) { public BlockRenderType getRenderType(BlockState state) {
return RenderShape.MODEL; return BlockRenderType.MODEL;
} }
@Override @Override
public void appendHoverText(ItemStack stack, @Nullable BlockGetter worldIn, List<Component> tooltip, TooltipFlag flagIn) { public void addInformation(ItemStack stack, @Nullable IBlockReader worldIn, List<ITextComponent> tooltip, ITooltipFlag flagIn) {
Utility.addTooltip(this.getRegistryName().getPath(), tooltip); Utility.addTooltip(this.getRegistryName().getPath(), tooltip);
} }
@org.jetbrains.annotations.Nullable
@Override
public <T extends BlockEntity> BlockEntityTicker<T> getTicker(Level level, BlockState state, BlockEntityType<T> type) {
return createTickerHelper(type, Registry.itemTerminalBlockEntity, ItemTerminalBlockEntity::tick);
}
} }

View file

@ -13,26 +13,27 @@ import de.ellpeck.prettypipes.packets.PacketHandler;
import de.ellpeck.prettypipes.packets.PacketNetworkItems; import de.ellpeck.prettypipes.packets.PacketNetworkItems;
import de.ellpeck.prettypipes.pipe.ConnectionType; import de.ellpeck.prettypipes.pipe.ConnectionType;
import de.ellpeck.prettypipes.pipe.IPipeConnectable; import de.ellpeck.prettypipes.pipe.IPipeConnectable;
import de.ellpeck.prettypipes.pipe.PipeBlockEntity; import de.ellpeck.prettypipes.pipe.PipeTileEntity;
import de.ellpeck.prettypipes.terminal.containers.ItemTerminalContainer; import de.ellpeck.prettypipes.terminal.containers.ItemTerminalContainer;
import net.minecraft.ChatFormatting; import net.minecraft.block.BlockState;
import net.minecraft.core.BlockPos; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.core.Direction; import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.nbt.CompoundTag; import net.minecraft.inventory.container.Container;
import net.minecraft.nbt.Tag; import net.minecraft.inventory.container.INamedContainerProvider;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.Style;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.world.MenuProvider;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level; import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.tileentity.ITickableTileEntity;
import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.level.block.state.BlockState; 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.Style;
import net.minecraft.util.text.TextFormatting;
import net.minecraft.util.text.TranslationTextComponent;
import net.minecraft.world.World;
import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.util.Constants.NBT;
import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.items.ItemHandlerHelper; import net.minecraftforge.items.ItemHandlerHelper;
import net.minecraftforge.items.ItemStackHandler; import net.minecraftforge.items.ItemStackHandler;
@ -44,7 +45,7 @@ import java.util.*;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.stream.Collectors; import java.util.stream.Collectors;
public class ItemTerminalBlockEntity extends BlockEntity implements IPipeConnectable, MenuProvider { public class ItemTerminalTileEntity extends TileEntity implements INamedContainerProvider, ITickableTileEntity, IPipeConnectable {
public final ItemStackHandler items = new ItemStackHandler(12) { public final ItemStackHandler items = new ItemStackHandler(12) {
@Override @Override
@ -56,64 +57,65 @@ public class ItemTerminalBlockEntity extends BlockEntity implements IPipeConnect
private final Queue<NetworkLock> existingRequests = new LinkedList<>(); private final Queue<NetworkLock> existingRequests = new LinkedList<>();
private final LazyOptional<IPipeConnectable> lazyThis = LazyOptional.of(() -> this); private final LazyOptional<IPipeConnectable> lazyThis = LazyOptional.of(() -> this);
public ItemTerminalBlockEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) { protected ItemTerminalTileEntity(TileEntityType<?> tileEntityTypeIn) {
super(type, pos, state); super(tileEntityTypeIn);
} }
public ItemTerminalBlockEntity(BlockPos pos, BlockState state) { public ItemTerminalTileEntity() {
this(Registry.itemTerminalBlockEntity, pos, state); this(Registry.itemTerminalTileEntity);
} }
public static void tick(Level level, BlockPos pos, BlockState state, ItemTerminalBlockEntity terminal) { @Override
if (terminal.level.isClientSide) public void tick() {
if (this.world.isRemote)
return; return;
var network = PipeNetwork.get(terminal.level); PipeNetwork network = PipeNetwork.get(this.world);
var pipe = terminal.getConnectedPipe(); PipeTileEntity pipe = this.getConnectedPipe();
if (pipe == null) if (pipe == null)
return; return;
var update = false; boolean update = false;
var interval = pipe.pressurizer != null ? 2 : 10; int interval = pipe.pressurizer != null ? 2 : 10;
if (terminal.level.getGameTime() % interval == 0) { if (this.world.getGameTime() % interval == 0) {
for (var i = 6; i < 12; i++) { for (int i = 6; i < 12; i++) {
var extracted = terminal.items.extractItem(i, Integer.MAX_VALUE, true); ItemStack extracted = this.items.extractItem(i, Integer.MAX_VALUE, true);
if (extracted.isEmpty()) if (extracted.isEmpty())
continue; continue;
var remain = network.routeItem(pipe.getBlockPos(), terminal.getBlockPos(), extracted, true); ItemStack remain = network.routeItem(pipe.getPos(), this.pos, extracted, true);
if (remain.getCount() == extracted.getCount()) if (remain.getCount() == extracted.getCount())
continue; continue;
terminal.items.extractItem(i, extracted.getCount() - remain.getCount(), false); this.items.extractItem(i, extracted.getCount() - remain.getCount(), false);
break; break;
} }
if (!terminal.existingRequests.isEmpty()) { if (!this.existingRequests.isEmpty()) {
var request = terminal.existingRequests.remove(); NetworkLock request = this.existingRequests.remove();
network.resolveNetworkLock(request); network.resolveNetworkLock(request);
network.requestExistingItem(request.location, pipe.getBlockPos(), terminal.getBlockPos(), request, request.stack, ItemEquality.NBT); network.requestExistingItem(request.location, pipe.getPos(), this.pos, request, request.stack, ItemEquality.NBT);
update = true; update = true;
} }
} }
if (terminal.level.getGameTime() % 100 == 0 || update) { if (this.world.getGameTime() % 100 == 0 || update) {
var lookingPlayers = terminal.getLookingPlayers(); PlayerEntity[] lookingPlayers = this.getLookingPlayers();
if (lookingPlayers.length > 0) if (lookingPlayers.length > 0)
terminal.updateItems(lookingPlayers); this.updateItems(lookingPlayers);
} }
} }
@Override @Override
public void setRemoved() { public void remove() {
super.setRemoved(); super.remove();
var network = PipeNetwork.get(this.level); PipeNetwork network = PipeNetwork.get(this.world);
for (var lock : this.existingRequests) for (NetworkLock lock : this.existingRequests)
network.resolveNetworkLock(lock); network.resolveNetworkLock(lock);
this.lazyThis.invalidate(); this.lazyThis.invalidate();
} }
public String getInvalidTerminalReason() { public String getInvalidTerminalReason() {
var network = PipeNetwork.get(this.level); PipeNetwork network = PipeNetwork.get(this.world);
var pipes = Arrays.stream(Direction.values()) long pipes = Arrays.stream(Direction.values())
.map(d -> network.getPipe(this.worldPosition.relative(d))) .map(d -> network.getPipe(this.pos.offset(d)))
.filter(Objects::nonNull).count(); .filter(Objects::nonNull).count();
if (pipes <= 0) if (pipes <= 0)
return "info." + PrettyPipes.ID + ".no_pipe_connected"; return "info." + PrettyPipes.ID + ".no_pipe_connected";
@ -122,42 +124,43 @@ public class ItemTerminalBlockEntity extends BlockEntity implements IPipeConnect
return null; return null;
} }
public PipeBlockEntity getConnectedPipe() { public PipeTileEntity getConnectedPipe() {
var network = PipeNetwork.get(this.level); PipeNetwork network = PipeNetwork.get(this.world);
for (var dir : Direction.values()) { for (Direction dir : Direction.values()) {
var pipe = network.getPipe(this.worldPosition.relative(dir)); PipeTileEntity pipe = network.getPipe(this.pos.offset(dir));
if (pipe != null) if (pipe != null)
return pipe; return pipe;
} }
return null; return null;
} }
public void updateItems(Player... playersToSync) { public void updateItems(PlayerEntity... playersToSync) {
var pipe = this.getConnectedPipe(); PipeTileEntity pipe = this.getConnectedPipe();
if (pipe == null) if (pipe == null)
return; return;
this.networkItems = this.collectItems(ItemEquality.NBT); this.networkItems = this.collectItems(ItemEquality.NBT);
if (playersToSync.length > 0) { if (playersToSync.length > 0) {
var clientItems = this.networkItems.values().stream().map(NetworkItem::asStack).collect(Collectors.toList()); List<ItemStack> clientItems = this.networkItems.values().stream().map(NetworkItem::asStack).collect(Collectors.toList());
var clientCraftables = PipeNetwork.get(this.level).getAllCraftables(pipe.getBlockPos()).stream().map(Pair::getRight).collect(Collectors.toList()); List<ItemStack> clientCraftables = PipeNetwork.get(this.world).getAllCraftables(pipe.getPos()).stream().map(Pair::getRight).collect(Collectors.toList());
var currentlyCrafting = this.getCurrentlyCrafting().stream().sorted(Comparator.comparingInt(ItemStack::getCount).reversed()).collect(Collectors.toList()); List<ItemStack> currentlyCrafting = this.getCurrentlyCrafting().stream().sorted(Comparator.comparingInt(ItemStack::getCount).reversed()).collect(Collectors.toList());
for (var player : playersToSync) { for (PlayerEntity player : playersToSync) {
if (!(player.containerMenu instanceof ItemTerminalContainer container)) if (!(player.openContainer instanceof ItemTerminalContainer))
continue; continue;
if (container.tile != this) ItemTerminalTileEntity tile = ((ItemTerminalContainer) player.openContainer).tile;
if (tile != this)
continue; continue;
PacketHandler.sendTo(player, new PacketNetworkItems(clientItems, clientCraftables, currentlyCrafting)); PacketHandler.sendTo(player, new PacketNetworkItems(clientItems, clientCraftables, currentlyCrafting));
} }
} }
} }
public void requestItem(Player player, ItemStack stack) { public void requestItem(PlayerEntity player, ItemStack stack) {
var network = PipeNetwork.get(this.level); PipeNetwork network = PipeNetwork.get(this.world);
network.startProfile("terminal_request_item"); network.startProfile("terminal_request_item");
this.updateItems(); this.updateItems();
var requested = this.requestItemImpl(stack, onItemUnavailable(player)); int requested = this.requestItemImpl(stack, onItemUnavailable(player));
if (requested > 0) { if (requested > 0) {
player.sendMessage(new TranslatableComponent("info." + PrettyPipes.ID + ".sending", requested, stack.getDisplayName()).setStyle(Style.EMPTY.applyFormat(ChatFormatting.GREEN)), UUID.randomUUID()); player.sendMessage(new TranslationTextComponent("info." + PrettyPipes.ID + ".sending", requested, stack.getDisplayName()).setStyle(Style.EMPTY.setFormatting(TextFormatting.GREEN)), UUID.randomUUID());
} else { } else {
onItemUnavailable(player).accept(stack); onItemUnavailable(player).accept(stack);
} }
@ -165,29 +168,32 @@ public class ItemTerminalBlockEntity extends BlockEntity implements IPipeConnect
} }
public int requestItemImpl(ItemStack stack, Consumer<ItemStack> unavailableConsumer) { public int requestItemImpl(ItemStack stack, Consumer<ItemStack> unavailableConsumer) {
var item = this.networkItems.get(new EquatableItemStack(stack, ItemEquality.NBT)); NetworkItem item = this.networkItems.get(new EquatableItemStack(stack, ItemEquality.NBT));
Collection<NetworkLocation> locations = item == null ? Collections.emptyList() : item.getLocations(); Collection<NetworkLocation> locations = item == null ? Collections.emptyList() : item.getLocations();
var ret = requestItemLater(this.level, this.getConnectedPipe().getBlockPos(), locations, unavailableConsumer, stack, new Stack<>(), ItemEquality.NBT); Pair<List<NetworkLock>, ItemStack> ret = requestItemLater(this.world, this.getConnectedPipe().getPos(), locations, unavailableConsumer, stack, new Stack<>(), ItemEquality.NBT);
this.existingRequests.addAll(ret.getLeft()); this.existingRequests.addAll(ret.getLeft());
return stack.getCount() - ret.getRight().getCount(); return stack.getCount() - ret.getRight().getCount();
} }
protected Player[] getLookingPlayers() { protected PlayerEntity[] getLookingPlayers() {
return this.level.players().stream().filter(p -> p.containerMenu instanceof ItemTerminalContainer container && container.tile == this).toArray(Player[]::new); return this.world.getPlayers().stream()
.filter(p -> p.openContainer instanceof ItemTerminalContainer)
.filter(p -> ((ItemTerminalContainer) p.openContainer).tile == this)
.toArray(PlayerEntity[]::new);
} }
private Map<EquatableItemStack, NetworkItem> collectItems(ItemEquality... equalityTypes) { private Map<EquatableItemStack, NetworkItem> collectItems(ItemEquality... equalityTypes) {
var network = PipeNetwork.get(this.level); PipeNetwork network = PipeNetwork.get(this.world);
network.startProfile("terminal_collect_items"); network.startProfile("terminal_collect_items");
var pipe = this.getConnectedPipe(); PipeTileEntity pipe = this.getConnectedPipe();
Map<EquatableItemStack, NetworkItem> items = new HashMap<>(); Map<EquatableItemStack, NetworkItem> items = new HashMap<>();
for (var location : network.getOrderedNetworkItems(pipe.getBlockPos())) { for (NetworkLocation location : network.getOrderedNetworkItems(pipe.getPos())) {
for (var entry : location.getItems(this.level).entrySet()) { for (Map.Entry<Integer, ItemStack> entry : location.getItems(this.world).entrySet()) {
// make sure we can extract from this slot to display it // make sure we can extract from this slot to display it
if (!location.canExtract(this.level, entry.getKey())) if (!location.canExtract(this.world, entry.getKey()))
continue; continue;
var equatable = new EquatableItemStack(entry.getValue(), equalityTypes); EquatableItemStack equatable = new EquatableItemStack(entry.getValue(), equalityTypes);
var item = items.computeIfAbsent(equatable, NetworkItem::new); NetworkItem item = items.computeIfAbsent(equatable, NetworkItem::new);
item.add(location, entry.getValue()); item.add(location, entry.getValue());
} }
} }
@ -196,57 +202,57 @@ public class ItemTerminalBlockEntity extends BlockEntity implements IPipeConnect
} }
private List<ItemStack> getCurrentlyCrafting() { private List<ItemStack> getCurrentlyCrafting() {
var network = PipeNetwork.get(this.level); PipeNetwork network = PipeNetwork.get(this.world);
var pipe = this.getConnectedPipe(); PipeTileEntity pipe = this.getConnectedPipe();
if (pipe == null) if (pipe == null)
return Collections.emptyList(); return Collections.emptyList();
var crafting = network.getCurrentlyCrafting(pipe.getBlockPos()); List<Pair<BlockPos, ItemStack>> crafting = network.getCurrentlyCrafting(pipe.getPos());
return crafting.stream().map(Pair::getRight).collect(Collectors.toList()); return crafting.stream().map(Pair::getRight).collect(Collectors.toList());
} }
public void cancelCrafting() { public void cancelCrafting() {
var network = PipeNetwork.get(this.level); PipeNetwork network = PipeNetwork.get(this.world);
var pipe = this.getConnectedPipe(); PipeTileEntity pipe = this.getConnectedPipe();
if (pipe == null) if (pipe == null)
return; return;
for (var craftable : network.getAllCraftables(pipe.getBlockPos())) { for (Pair<BlockPos, ItemStack> craftable : network.getAllCraftables(pipe.getPos())) {
var otherPipe = network.getPipe(craftable.getLeft()); PipeTileEntity otherPipe = network.getPipe(craftable.getLeft());
if (otherPipe != null) { if (otherPipe != null) {
for (var lock : otherPipe.craftIngredientRequests) for (NetworkLock lock : otherPipe.craftIngredientRequests)
network.resolveNetworkLock(lock); network.resolveNetworkLock(lock);
otherPipe.craftIngredientRequests.clear(); otherPipe.craftIngredientRequests.clear();
otherPipe.craftResultRequests.clear(); otherPipe.craftResultRequests.clear();
} }
} }
var lookingPlayers = this.getLookingPlayers(); PlayerEntity[] lookingPlayers = this.getLookingPlayers();
if (lookingPlayers.length > 0) if (lookingPlayers.length > 0)
this.updateItems(lookingPlayers); this.updateItems(lookingPlayers);
} }
@Override @Override
public CompoundTag save(CompoundTag compound) { public CompoundTag write(CompoundTag compound) {
compound.put("items", this.items.serializeNBT()); compound.put("items", this.items.serializeNBT());
compound.put("requests", Utility.serializeAll(this.existingRequests)); compound.put("requests", Utility.serializeAll(this.existingRequests));
return super.save(compound); return super.write(compound);
} }
@Override @Override
public void load(CompoundTag compound) { public void read(BlockState state, CompoundTag compound) {
this.items.deserializeNBT(compound.getCompound("items")); this.items.deserializeNBT(compound.getCompound("items"));
this.existingRequests.clear(); this.existingRequests.clear();
this.existingRequests.addAll(Utility.deserializeAll(compound.getList("requests", Tag.TAG_COMPOUND), NetworkLock::new)); this.existingRequests.addAll(Utility.deserializeAll(compound.getList("requests", NBT.TAG_COMPOUND), NetworkLock::new));
super.load(compound); super.read(state, compound);
} }
@Override @Override
public Component getDisplayName() { public ITextComponent getDisplayName() {
return new TranslatableComponent("container." + PrettyPipes.ID + ".item_terminal"); return new TranslationTextComponent("container." + PrettyPipes.ID + ".item_terminal");
} }
@Nullable @Nullable
@Override @Override
public AbstractContainerMenu createMenu(int window, Inventory inv, Player player) { public Container createMenu(int window, PlayerInventory inv, PlayerEntity player) {
return new ItemTerminalContainer(Registry.itemTerminalContainer, window, player, this.worldPosition); return new ItemTerminalContainer(Registry.itemTerminalContainer, window, player, this.pos);
} }
@Override @Override
@ -263,8 +269,8 @@ public class ItemTerminalBlockEntity extends BlockEntity implements IPipeConnect
@Override @Override
public ItemStack insertItem(BlockPos pipePos, Direction direction, ItemStack stack, boolean simulate) { public ItemStack insertItem(BlockPos pipePos, Direction direction, ItemStack stack, boolean simulate) {
var pos = pipePos.relative(direction); BlockPos pos = pipePos.offset(direction);
var tile = Utility.getBlockEntity(ItemTerminalBlockEntity.class, this.level, pos); ItemTerminalTileEntity tile = Utility.getBlockEntity(ItemTerminalTileEntity.class, world, pos);
if (tile != null) if (tile != null)
return ItemHandlerHelper.insertItemStacked(tile.items, stack, simulate); return ItemHandlerHelper.insertItemStacked(tile.items, stack, simulate);
return stack; return stack;
@ -275,13 +281,13 @@ public class ItemTerminalBlockEntity extends BlockEntity implements IPipeConnect
return true; return true;
} }
public static Pair<List<NetworkLock>, ItemStack> requestItemLater(Level world, BlockPos destPipe, Collection<NetworkLocation> locations, Consumer<ItemStack> unavailableConsumer, ItemStack stack, Stack<ItemStack> dependencyChain, ItemEquality... equalityTypes) { public static Pair<List<NetworkLock>, ItemStack> requestItemLater(World world, BlockPos destPipe, Collection<NetworkLocation> locations, Consumer<ItemStack> unavailableConsumer, ItemStack stack, Stack<ItemStack> dependencyChain, ItemEquality... equalityTypes) {
List<NetworkLock> requests = new ArrayList<>(); List<NetworkLock> requests = new ArrayList<>();
var remain = stack.copy(); ItemStack remain = stack.copy();
var network = PipeNetwork.get(world); PipeNetwork network = PipeNetwork.get(world);
// check for existing items // check for existing items
for (var location : locations) { for (NetworkLocation location : locations) {
var amount = location.getItemAmount(world, stack, equalityTypes); int amount = location.getItemAmount(world, stack, equalityTypes);
if (amount <= 0) if (amount <= 0)
continue; continue;
amount -= network.getLockedAmount(location.getPos(), stack, null, equalityTypes); amount -= network.getLockedAmount(location.getPos(), stack, null, equalityTypes);
@ -290,9 +296,9 @@ public class ItemTerminalBlockEntity extends BlockEntity implements IPipeConnect
amount = remain.getCount(); amount = remain.getCount();
remain.shrink(amount); remain.shrink(amount);
while (amount > 0) { while (amount > 0) {
var copy = stack.copy(); ItemStack copy = stack.copy();
copy.setCount(Math.min(stack.getMaxStackSize(), amount)); copy.setCount(Math.min(stack.getMaxStackSize(), amount));
var lock = new NetworkLock(location, copy); NetworkLock lock = new NetworkLock(location, copy);
network.createNetworkLock(lock); network.createNetworkLock(lock);
requests.add(lock); requests.add(lock);
amount -= copy.getCount(); amount -= copy.getCount();
@ -307,7 +313,7 @@ public class ItemTerminalBlockEntity extends BlockEntity implements IPipeConnect
return Pair.of(requests, remain); return Pair.of(requests, remain);
} }
public static Consumer<ItemStack> onItemUnavailable(Player player) { public static Consumer<ItemStack> onItemUnavailable(PlayerEntity player) {
return s -> player.sendMessage(new TranslatableComponent("info." + PrettyPipes.ID + ".not_found", s.getDisplayName()).setStyle(Style.EMPTY.applyFormat(ChatFormatting.RED)), UUID.randomUUID()); return s -> player.sendMessage(new TranslationTextComponent("info." + PrettyPipes.ID + ".not_found", s.getDisplayName()).setStyle(Style.EMPTY.setFormatting(TextFormatting.RED)), UUID.randomUUID());
} }
} }

View file

@ -1,57 +1,64 @@
package de.ellpeck.prettypipes.terminal.containers; package de.ellpeck.prettypipes.terminal.containers;
import de.ellpeck.prettypipes.Utility; import de.ellpeck.prettypipes.Utility;
import de.ellpeck.prettypipes.terminal.CraftingTerminalBlockEntity; import de.ellpeck.prettypipes.terminal.CraftingTerminalTileEntity;
import net.minecraft.core.BlockPos; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket; import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.server.level.ServerPlayer; import net.minecraft.inventory.CraftResultInventory;
import net.minecraft.world.Container; import net.minecraft.inventory.CraftingInventory;
import net.minecraft.world.entity.player.Player; import net.minecraft.inventory.IInventory;
import net.minecraft.world.inventory.*; import net.minecraft.inventory.container.ClickType;
import net.minecraft.inventory.container.ContainerType;
import net.minecraft.inventory.container.CraftingResultSlot;
import net.minecraft.inventory.container.Slot;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.RecipeType; 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 org.apache.commons.lang3.tuple.Pair; import org.apache.commons.lang3.tuple.Pair;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.Optional;
public class CraftingTerminalContainer extends ItemTerminalContainer { public class CraftingTerminalContainer extends ItemTerminalContainer {
public CraftingContainer craftInventory; public CraftingInventory craftInventory;
public ResultContainer craftResult; public CraftResultInventory craftResult;
private final Player player; private final PlayerEntity player;
public CraftingTerminalContainer(@Nullable MenuType<?> type, int id, Player player, BlockPos pos) { public CraftingTerminalContainer(@Nullable ContainerType<?> type, int id, PlayerEntity player, BlockPos pos) {
super(type, id, player, pos); super(type, id, player, pos);
this.player = player; this.player = player;
this.slotsChanged(this.craftInventory); this.onCraftMatrixChanged(this.craftInventory);
} }
@Override @Override
protected void addDataSlots(ContainerData data) { protected void addOwnSlots(PlayerEntity player) {
this.craftInventory = new WrappedCraftingInventory(this.getTile().craftItems, this, 3, 3); this.craftInventory = new WrappedCraftingInventory(this.getTile().craftItems, this, 3, 3);
this.craftResult = new ResultContainer(); this.craftResult = new CraftResultInventory();
this.addSlot(new ResultSlot(this.player, this.craftInventory, this.craftResult, 0, 25, 77)); this.addSlot(new CraftingResultSlot(player, this.craftInventory, this.craftResult, 0, 25, 77));
for (var i = 0; i < 3; i++) for (int i = 0; i < 3; i++)
for (var j = 0; j < 3; j++) for (int j = 0; j < 3; j++)
this.addSlot(new Slot(this.craftInventory, j + i * 3, 7 + j * 18, 18 + i * 18)); this.addSlot(new Slot(this.craftInventory, j + i * 3, 7 + j * 18, 18 + i * 18));
super.addDataSlots(data); super.addOwnSlots(player);
} }
@Override @Override
public void slotsChanged(Container inventoryIn) { public void onCraftMatrixChanged(IInventory inventoryIn) {
if (!this.player.level.isClientSide) { if (!this.player.world.isRemote) {
var ret = ItemStack.EMPTY; ItemStack ret = ItemStack.EMPTY;
var optional = this.player.level.getServer().getRecipeManager().getRecipeFor(RecipeType.CRAFTING, this.craftInventory, this.player.level); Optional<ICraftingRecipe> optional = this.player.world.getServer().getRecipeManager().getRecipe(IRecipeType.CRAFTING, this.craftInventory, this.player.world);
if (optional.isPresent()) if (optional.isPresent())
ret = optional.get().assemble(this.craftInventory); ret = optional.get().getCraftingResult(this.craftInventory);
this.craftResult.setItem(0, ret); this.craftResult.setInventorySlotContents(0, ret);
((ServerPlayer) this.player).connection.send(new ClientboundContainerSetSlotPacket(this.containerId, 0, 0, ret)); ((ServerPlayerEntity) this.player).connection.sendPacket(new SSetSlotPacket(this.windowId, 0, ret));
} }
} }
@Override @Override
public ItemStack quickMoveStack(Player player, int slotIndex) { public ItemStack transferStackInSlot(PlayerEntity player, int slotIndex) {
return Utility.transferStackInSlot(this, this::moveItemStackTo, player, slotIndex, stack -> Pair.of(6 + 10, 12 + 10)); return Utility.transferStackInSlot(this, this::mergeItemStack, player, slotIndex, stack -> Pair.of(6 + 10, 12 + 10));
} }
@Override @Override
@ -60,16 +67,16 @@ public class CraftingTerminalContainer extends ItemTerminalContainer {
} }
@Override @Override
public void clicked(int slotId, int dragType, ClickType clickTypeIn, Player player) { public ItemStack slotClick(int slotId, int dragType, ClickType clickTypeIn, PlayerEntity player) {
if (slotId > 0 && clickTypeIn == ClickType.PICKUP) { if (slotId > 0 && clickTypeIn == ClickType.PICKUP) {
var slot = this.slots.get(slotId); Slot slot = this.inventorySlots.get(slotId);
if (slot.container == this.craftInventory && !slot.hasItem()) if (slot.inventory == this.craftInventory && !slot.getHasStack())
this.getTile().ghostItems.setStackInSlot(slot.getSlotIndex(), ItemStack.EMPTY); this.getTile().ghostItems.setStackInSlot(slot.getSlotIndex(), ItemStack.EMPTY);
} }
super.clicked(slotId, dragType, clickTypeIn, player); return super.slotClick(slotId, dragType, clickTypeIn, player);
} }
public CraftingTerminalBlockEntity getTile() { public CraftingTerminalTileEntity getTile() {
return (CraftingTerminalBlockEntity) this.tile; return (CraftingTerminalTileEntity) this.tile;
} }
} }

View file

@ -1,42 +1,49 @@
package de.ellpeck.prettypipes.terminal.containers; package de.ellpeck.prettypipes.terminal.containers;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.platform.GlStateManager;
import com.mojang.blaze3d.systems.RenderSystem;
import de.ellpeck.prettypipes.PrettyPipes; import de.ellpeck.prettypipes.PrettyPipes;
import de.ellpeck.prettypipes.packets.PacketButton; import de.ellpeck.prettypipes.packets.PacketButton;
import de.ellpeck.prettypipes.packets.PacketHandler; import de.ellpeck.prettypipes.packets.PacketHandler;
import net.minecraft.client.gui.components.Button; import de.ellpeck.prettypipes.packets.PacketRequest;
import net.minecraft.network.chat.Component; import de.ellpeck.prettypipes.terminal.CraftingTerminalTileEntity;
import net.minecraft.network.chat.TranslatableComponent; import net.minecraft.client.gui.widget.Widget;
import net.minecraft.client.gui.widget.button.Button;
import net.minecraft.client.resources.I18n;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.inventory.container.Slot;
import net.minecraft.world.item.ItemStack;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.entity.player.Inventory; import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TranslationTextComponent;
public class CraftingTerminalGui extends ItemTerminalGui { public class CraftingTerminalGui extends ItemTerminalGui {
private static final ResourceLocation TEXTURE = new ResourceLocation(PrettyPipes.ID, "textures/gui/crafting_terminal.png"); private static final ResourceLocation TEXTURE = new ResourceLocation(PrettyPipes.ID, "textures/gui/crafting_terminal.png");
private Button requestButton; private Button requestButton;
public CraftingTerminalGui(ItemTerminalContainer screenContainer, Inventory inv, Component titleIn) { public CraftingTerminalGui(ItemTerminalContainer screenContainer, PlayerInventory inv, ITextComponent titleIn) {
super(screenContainer, inv, titleIn); super(screenContainer, inv, titleIn);
this.imageWidth = 256; this.xSize = 256;
} }
@Override @Override
protected void init() { protected void init() {
super.init(); super.init();
this.requestButton = this.addRenderableWidget(new Button(this.leftPos + 8, this.topPos + 100, 50, 20, new TranslatableComponent("info." + PrettyPipes.ID + ".request"), button -> { this.requestButton = this.addButton(new Button(this.guiLeft + 8, this.guiTop + 100, 50, 20, new TranslationTextComponent("info." + PrettyPipes.ID + ".request"), button -> {
var amount = requestModifier(); int amount = requestModifier();
PacketHandler.sendToServer(new PacketButton(this.menu.tile.getBlockPos(), PacketButton.ButtonResult.CRAFT_TERMINAL_REQUEST, amount)); PacketHandler.sendToServer(new PacketButton(this.container.tile.getPos(), PacketButton.ButtonResult.CRAFT_TERMINAL_REQUEST, amount));
})); }));
this.tick(); this.tick();
} }
@Override @Override
public void containerTick() { public void tick() {
super.containerTick(); super.tick();
var tile = this.getCraftingContainer().getTile(); CraftingTerminalTileEntity tile = this.getCraftingContainer().getTile();
this.requestButton.active = false; this.requestButton.active = false;
for (var i = 0; i < tile.craftItems.getSlots(); i++) { for (int i = 0; i < tile.craftItems.getSlots(); i++) {
var stack = tile.getRequestedCraftItem(i); ItemStack stack = tile.getRequestedCraftItem(i);
if (!stack.isEmpty() && stack.getCount() < stack.getMaxStackSize()) { if (!stack.isEmpty() && stack.getCount() < stack.getMaxStackSize()) {
this.requestButton.active = true; this.requestButton.active = true;
break; break;
@ -45,23 +52,23 @@ public class CraftingTerminalGui extends ItemTerminalGui {
} }
@Override @Override
protected void renderLabels(PoseStack matrix, int mouseX, int mouseY) { protected void drawGuiContainerForegroundLayer(MatrixStack matrix, int mouseX, int mouseY) {
super.renderLabels(matrix, mouseX, mouseY); super.drawGuiContainerForegroundLayer(matrix, mouseX, mouseY);
var container = this.getCraftingContainer(); CraftingTerminalContainer container = this.getCraftingContainer();
var tile = container.getTile(); CraftingTerminalTileEntity tile = container.getTile();
for (var i = 0; i < tile.ghostItems.getSlots(); i++) { for (int i = 0; i < tile.ghostItems.getSlots(); i++) {
if (!tile.craftItems.getStackInSlot(i).isEmpty()) if (!tile.craftItems.getStackInSlot(i).isEmpty())
continue; continue;
var ghost = tile.ghostItems.getStackInSlot(i); ItemStack ghost = tile.ghostItems.getStackInSlot(i);
if (ghost.isEmpty()) if (ghost.isEmpty())
continue; continue;
var finalI = i; int finalI = i;
var slot = container.slots.stream().filter(s -> s.container == container.craftInventory && s.getSlotIndex() == finalI).findFirst().orElse(null); Slot slot = container.inventorySlots.stream().filter(s -> s.inventory == container.craftInventory && s.getSlotIndex() == finalI).findFirst().orElse(null);
if (slot == null) if (slot == null)
continue; continue;
this.minecraft.getItemRenderer().renderGuiItem(ghost, slot.x, slot.y); this.minecraft.getItemRenderer().renderItemIntoGUI(ghost, slot.xPos, slot.yPos);
this.minecraft.getItemRenderer().renderGuiItemDecorations(this.font, ghost, slot.x, slot.y, "0"); this.minecraft.getItemRenderer().renderItemOverlayIntoGUI(this.font, ghost, slot.xPos, slot.yPos, "0");
} }
} }
@ -76,6 +83,6 @@ public class CraftingTerminalGui extends ItemTerminalGui {
} }
protected CraftingTerminalContainer getCraftingContainer() { protected CraftingTerminalContainer getCraftingContainer() {
return (CraftingTerminalContainer) this.menu; return (CraftingTerminalContainer) this.container;
} }
} }

View file

@ -1,41 +1,44 @@
package de.ellpeck.prettypipes.terminal.containers; package de.ellpeck.prettypipes.terminal.containers;
import de.ellpeck.prettypipes.Utility; import de.ellpeck.prettypipes.Utility;
import de.ellpeck.prettypipes.terminal.ItemTerminalBlockEntity; import de.ellpeck.prettypipes.terminal.ItemTerminalTileEntity;
import net.minecraft.core.BlockPos; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.world.entity.player.Player; import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.inventory.container.ClickType;
import net.minecraft.world.inventory.MenuType; import net.minecraft.inventory.container.Container;
import net.minecraft.world.inventory.Slot; import net.minecraft.inventory.container.ContainerType;
import net.minecraft.inventory.container.Slot;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.server.ServerWorld;
import net.minecraftforge.items.SlotItemHandler; import net.minecraftforge.items.SlotItemHandler;
import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.lang3.tuple.Pair;
import javax.annotation.Nullable; import javax.annotation.Nullable;
public class ItemTerminalContainer extends AbstractContainerMenu { public class ItemTerminalContainer extends Container {
public final ItemTerminalBlockEntity tile; public final ItemTerminalTileEntity tile;
public ItemTerminalContainer(@Nullable MenuType<?> type, int id, Player player, BlockPos pos) { public ItemTerminalContainer(@Nullable ContainerType<?> type, int id, PlayerEntity player, BlockPos pos) {
super(type, id); super(type, id);
this.tile = Utility.getBlockEntity(ItemTerminalBlockEntity.class, player.level, pos); this.tile = Utility.getBlockEntity(ItemTerminalTileEntity.class, player.world, pos);
this.addOwnSlots(player); this.addOwnSlots(player);
var off = this.getSlotXOffset(); int off = this.getSlotXOffset();
for (var l = 0; l < 3; ++l) for (int l = 0; l < 3; ++l)
for (var j1 = 0; j1 < 9; ++j1) for (int j1 = 0; j1 < 9; ++j1)
this.addSlot(new Slot(player.getInventory(), j1 + l * 9 + 9, 8 + off + j1 * 18, 154 + l * 18)); this.addSlot(new Slot(player.inventory, j1 + l * 9 + 9, 8 + off + j1 * 18, 154 + l * 18));
for (var i1 = 0; i1 < 9; ++i1) for (int i1 = 0; i1 < 9; ++i1)
this.addSlot(new Slot(player.getInventory(), i1, 8 + off + i1 * 18, 212)); this.addSlot(new Slot(player.inventory, i1, 8 + off + i1 * 18, 212));
} }
protected void addOwnSlots(Player player) { protected void addOwnSlots(PlayerEntity player) {
var off = this.getSlotXOffset(); int off = this.getSlotXOffset();
for (var i = 0; i < 6; i++) for (int i = 0; i < 6; i++)
this.addSlot(new SlotItemHandler(this.tile.items, i, 8 + off + i % 3 * 18, 102 + i / 3 * 18)); this.addSlot(new SlotItemHandler(this.tile.items, i, 8 + off + i % 3 * 18, 102 + i / 3 * 18));
for (var i = 0; i < 6; i++) for (int i = 0; i < 6; i++)
this.addSlot(new SlotItemHandler(this.tile.items, i + 6, 116 + off + i % 3 * 18, 102 + i / 3 * 18)); this.addSlot(new SlotItemHandler(this.tile.items, i + 6, 116 + off + i % 3 * 18, 102 + i / 3 * 18));
} }
@ -44,12 +47,12 @@ public class ItemTerminalContainer extends AbstractContainerMenu {
} }
@Override @Override
public ItemStack quickMoveStack(Player player, int slotIndex) { public ItemStack transferStackInSlot(PlayerEntity player, int slotIndex) {
return Utility.transferStackInSlot(this, this::moveItemStackTo, player, slotIndex, stack -> Pair.of(6, 12)); return Utility.transferStackInSlot(this, this::mergeItemStack, player, slotIndex, stack -> Pair.of(6, 12));
} }
@Override @Override
public boolean stillValid(Player player) { public boolean canInteractWith(PlayerEntity playerIn) {
return true; return true;
} }
} }

View file

@ -1,7 +1,6 @@
package de.ellpeck.prettypipes.terminal.containers; package de.ellpeck.prettypipes.terminal.containers;
import com.mojang.blaze3d.platform.InputConstants; import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.vertex.PoseStack;
import de.ellpeck.prettypipes.PrettyPipes; import de.ellpeck.prettypipes.PrettyPipes;
import de.ellpeck.prettypipes.misc.ItemTerminalWidget; import de.ellpeck.prettypipes.misc.ItemTerminalWidget;
import de.ellpeck.prettypipes.misc.PlayerPrefs; import de.ellpeck.prettypipes.misc.PlayerPrefs;
@ -9,29 +8,31 @@ import de.ellpeck.prettypipes.packets.PacketButton;
import de.ellpeck.prettypipes.packets.PacketHandler; import de.ellpeck.prettypipes.packets.PacketHandler;
import de.ellpeck.prettypipes.packets.PacketRequest; import de.ellpeck.prettypipes.packets.PacketRequest;
import joptsimple.internal.Strings; import joptsimple.internal.Strings;
import net.minecraft.client.gui.components.Button; import net.minecraft.client.gui.screen.inventory.ContainerScreen;
import net.minecraft.client.gui.components.EditBox; import net.minecraft.client.gui.widget.TextFieldWidget;
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; import net.minecraft.client.gui.widget.Widget;
import net.minecraft.client.resources.language.I18n; import net.minecraft.client.gui.widget.button.Button;
import net.minecraft.network.chat.Component; import net.minecraft.client.resources.I18n;
import net.minecraft.network.chat.TextComponent; import net.minecraft.client.util.InputMappings;
import net.minecraft.network.chat.TranslatableComponent; import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.Mth;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.resources.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 org.apache.commons.lang3.tuple.Pair;
import java.util.*; import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
public class ItemTerminalGui extends AbstractContainerScreen<ItemTerminalContainer> { public class ItemTerminalGui extends ContainerScreen<ItemTerminalContainer> {
private static final ResourceLocation TEXTURE = new ResourceLocation(PrettyPipes.ID, "textures/gui/item_terminal.png"); private static final ResourceLocation TEXTURE = new ResourceLocation(PrettyPipes.ID, "textures/gui/item_terminal.png");
public List<ItemStack> currentlyCrafting; public List<ItemStack> currentlyCrafting;
public EditBox search; public TextFieldWidget search;
// craftables have the second parameter set to true // craftables have the second parameter set to true
private final List<Pair<ItemStack, Boolean>> sortedItems = new ArrayList<>(); private final List<Pair<ItemStack, Boolean>> sortedItems = new ArrayList<>();
@ -49,24 +50,24 @@ public class ItemTerminalGui extends AbstractContainerScreen<ItemTerminalContain
private ItemStack hoveredCrafting; private ItemStack hoveredCrafting;
private boolean isScrolling; private boolean isScrolling;
public ItemTerminalGui(ItemTerminalContainer screenContainer, Inventory inv, Component titleIn) { public ItemTerminalGui(ItemTerminalContainer screenContainer, PlayerInventory inv, ITextComponent titleIn) {
super(screenContainer, inv, titleIn); super(screenContainer, inv, titleIn);
this.imageWidth = 176 + 15; this.xSize = 176 + 15;
this.imageHeight = 236; this.ySize = 236;
} }
@Override @Override
protected void init() { protected void init() {
super.init(); super.init();
this.search = this.addRenderableWidget(new EditBox(this.font, this.leftPos + this.getXOffset() + 97, this.topPos + 6, 86, 8, new TextComponent(""))); this.search = this.addButton(new TextFieldWidget(this.font, this.guiLeft + this.getXOffset() + 97, this.guiTop + 6, 86, 8, new StringTextComponent("")));
this.search.setBordered(false); this.search.setEnableBackgroundDrawing(false);
this.lastSearchText = ""; this.lastSearchText = "";
if (this.items != null) if (this.items != null)
this.updateWidgets(); this.updateWidgets();
this.plusButton = this.addRenderableWidget(new Button(this.leftPos + this.getXOffset() + 95 - 7 + 12, this.topPos + 103, 12, 12, new TextComponent("+"), button -> { this.plusButton = this.addButton(new Button(this.guiLeft + this.getXOffset() + 95 - 7 + 12, this.guiTop + 103, 12, 12, new StringTextComponent("+"), button -> {
var modifier = requestModifier(); int modifier = requestModifier();
if (modifier > 1 && this.requestAmount == 1) { if (modifier > 1 && this.requestAmount == 1) {
this.requestAmount = modifier; this.requestAmount = modifier;
} else { } else {
@ -76,44 +77,44 @@ public class ItemTerminalGui extends AbstractContainerScreen<ItemTerminalContain
if (this.requestAmount > 384) if (this.requestAmount > 384)
this.requestAmount = 384; this.requestAmount = 384;
})); }));
this.minusButton = this.addRenderableWidget(new Button(this.leftPos + this.getXOffset() + 95 - 7 - 24, this.topPos + 103, 12, 12, new TextComponent("-"), button -> { this.minusButton = this.addButton(new Button(this.guiLeft + this.getXOffset() + 95 - 7 - 24, this.guiTop + 103, 12, 12, new StringTextComponent("-"), button -> {
this.requestAmount -= requestModifier(); this.requestAmount -= requestModifier();
if (this.requestAmount < 1) if (this.requestAmount < 1)
this.requestAmount = 1; this.requestAmount = 1;
})); }));
this.minusButton.active = false; this.minusButton.active = false;
this.requestButton = this.addRenderableWidget(new Button(this.leftPos + this.getXOffset() + 95 - 7 - 25, this.topPos + 115, 50, 20, new TranslatableComponent("info." + PrettyPipes.ID + ".request"), button -> { this.requestButton = this.addButton(new Button(this.guiLeft + this.getXOffset() + 95 - 7 - 25, this.guiTop + 115, 50, 20, new TranslationTextComponent("info." + PrettyPipes.ID + ".request"), button -> {
var widget = this.streamWidgets().filter(w -> w.selected).findFirst(); Optional<ItemTerminalWidget> widget = this.streamWidgets().filter(w -> w.selected).findFirst();
if (!widget.isPresent()) if (!widget.isPresent())
return; return;
var stack = widget.get().stack.copy(); ItemStack stack = widget.get().stack.copy();
stack.setCount(1); stack.setCount(1);
PacketHandler.sendToServer(new PacketRequest(this.menu.tile.getBlockPos(), stack, this.requestAmount)); PacketHandler.sendToServer(new PacketRequest(this.container.tile.getPos(), stack, this.requestAmount));
this.requestAmount = 1; this.requestAmount = 1;
})); }));
this.requestButton.active = false; this.requestButton.active = false;
this.orderButton = this.addRenderableWidget(new Button(this.leftPos - 22, this.topPos, 20, 20, new TextComponent(""), button -> { this.orderButton = this.addButton(new Button(this.guiLeft - 22, this.guiTop, 20, 20, new StringTextComponent(""), button -> {
if (this.sortedItems == null) if (this.sortedItems == null)
return; return;
var prefs = PlayerPrefs.get(); PlayerPrefs prefs = PlayerPrefs.get();
prefs.terminalItemOrder = prefs.terminalItemOrder.next(); prefs.terminalItemOrder = prefs.terminalItemOrder.next();
prefs.save(); prefs.save();
this.updateWidgets(); this.updateWidgets();
})); }));
this.ascendingButton = this.addRenderableWidget(new Button(this.leftPos - 22, this.topPos + 22, 20, 20, new TextComponent(""), button -> { this.ascendingButton = this.addButton(new Button(this.guiLeft - 22, this.guiTop + 22, 20, 20, new StringTextComponent(""), button -> {
if (this.sortedItems == null) if (this.sortedItems == null)
return; return;
var prefs = PlayerPrefs.get(); PlayerPrefs prefs = PlayerPrefs.get();
prefs.terminalAscending = !prefs.terminalAscending; prefs.terminalAscending = !prefs.terminalAscending;
prefs.save(); prefs.save();
this.updateWidgets(); this.updateWidgets();
})); }));
this.cancelCraftingButton = this.addRenderableWidget(new Button(this.leftPos + this.imageWidth + 4, this.topPos + 4 + 64, 54, 20, new TranslatableComponent("info." + PrettyPipes.ID + ".cancel_all"), b -> { this.cancelCraftingButton = this.addButton(new Button(this.guiLeft + this.xSize + 4, this.guiTop + 4 + 64, 54, 20, new TranslationTextComponent("info." + PrettyPipes.ID + ".cancel_all"), b -> {
})); }));
this.cancelCraftingButton.visible = false; this.cancelCraftingButton.visible = false;
for (var y = 0; y < 4; y++) { for (int y = 0; y < 4; y++) {
for (var x = 0; x < 9; x++) for (int x = 0; x < 9; x++)
this.addRenderableWidget(new ItemTerminalWidget(this.leftPos + this.getXOffset() + 8 + x * 18, this.topPos + 18 + y * 18, x, y, this)); this.addButton(new ItemTerminalWidget(this.guiLeft + this.getXOffset() + 8 + x * 18, this.guiTop + 18 + y * 18, x, y, this));
} }
} }
@ -122,15 +123,15 @@ public class ItemTerminalGui extends AbstractContainerScreen<ItemTerminalContain
} }
@Override @Override
public void containerTick() { public void tick() {
super.containerTick(); super.tick();
this.requestButton.active = this.streamWidgets().anyMatch(w -> w.selected); this.requestButton.active = this.streamWidgets().anyMatch(w -> w.selected);
this.plusButton.active = this.requestAmount < 384; this.plusButton.active = this.requestAmount < 384;
this.minusButton.active = this.requestAmount > 1; this.minusButton.active = this.requestAmount > 1;
this.search.tick(); this.search.tick();
if (this.items != null) { if (this.items != null) {
var text = this.search.getValue(); String text = this.search.getText();
if (!this.lastSearchText.equals(text)) { if (!this.lastSearchText.equals(text)) {
this.lastSearchText = text; this.lastSearchText = text;
this.updateWidgets(); this.updateWidgets();
@ -140,7 +141,7 @@ public class ItemTerminalGui extends AbstractContainerScreen<ItemTerminalContain
@Override @Override
public boolean mouseClicked(double mouseX, double mouseY, int button) { public boolean mouseClicked(double mouseX, double mouseY, int button) {
if (button == 0 && mouseX >= this.leftPos + this.getXOffset() + 172 && this.topPos + mouseY >= 18 && mouseX < this.leftPos + this.getXOffset() + 172 + 12 && mouseY < this.topPos + 18 + 70) { if (button == 0 && mouseX >= this.guiLeft + this.getXOffset() + 172 && this.guiTop + mouseY >= 18 && mouseX < this.guiLeft + this.getXOffset() + 172 + 12 && mouseY < this.guiTop + 18 + 70) {
this.isScrolling = true; this.isScrolling = true;
return true; return true;
} }
@ -151,9 +152,9 @@ public class ItemTerminalGui extends AbstractContainerScreen<ItemTerminalContain
public boolean mouseReleased(double mouseX, double mouseY, int button) { 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 // 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 // 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.isHoveredOrFocused()) { if (button == 0 && this.cancelCraftingButton.visible && this.cancelCraftingButton.isHovered()) {
if (this.currentlyCrafting != null && !this.currentlyCrafting.isEmpty()) { if (this.currentlyCrafting != null && !this.currentlyCrafting.isEmpty()) {
PacketHandler.sendToServer(new PacketButton(this.menu.tile.getBlockPos(), PacketButton.ButtonResult.CANCEL_CRAFTING)); PacketHandler.sendToServer(new PacketButton(this.container.tile.getPos(), PacketButton.ButtonResult.CANCEL_CRAFTING));
return true; return true;
} }
@ -162,7 +163,7 @@ public class ItemTerminalGui extends AbstractContainerScreen<ItemTerminalContain
this.isScrolling = false; this.isScrolling = false;
else if (button == 1 && mouseX >= this.search.x && mouseX <= this.search.x + this.search.getWidth() && mouseY >= this.search.y && mouseY <= this.search.y + 8) { else if (button == 1 && mouseX >= this.search.x && mouseX <= this.search.x + this.search.getWidth() && mouseY >= this.search.y && mouseY <= this.search.y + 8) {
//clear text from search field when letting go of right mouse button within search field //clear text from search field when letting go of right mouse button within search field
this.search.setValue(""); this.search.setText("");
return true; return true;
} }
return super.mouseReleased(mouseX, mouseY, button); return super.mouseReleased(mouseX, mouseY, button);
@ -171,8 +172,8 @@ public class ItemTerminalGui extends AbstractContainerScreen<ItemTerminalContain
@Override @Override
public boolean mouseDragged(double mouseX, double mouseY, int i, double j, double k) { public boolean mouseDragged(double mouseX, double mouseY, int i, double j, double k) {
if (this.isScrolling) { if (this.isScrolling) {
var percentage = Mth.clamp(((float) mouseY - (this.topPos + 18) - 7.5F) / (70 - 15), 0, 1); float percentage = MathHelper.clamp(((float) mouseY - (this.guiTop + 18) - 7.5F) / (70 - 15), 0, 1);
var offset = (int) (percentage * (float) (this.sortedItems.size() / 9 - 3)); int offset = (int) (percentage * (float) (this.sortedItems.size() / 9 - 3));
if (offset != this.scrollOffset) { if (offset != this.scrollOffset) {
this.scrollOffset = offset; this.scrollOffset = offset;
this.updateWidgets(); this.updateWidgets();
@ -186,8 +187,8 @@ public class ItemTerminalGui extends AbstractContainerScreen<ItemTerminalContain
public boolean keyPressed(int x, int y, int z) { 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 // for some reason we have to do this to make the text field allow the inventory key to be typed
if (this.search.isFocused()) { if (this.search.isFocused()) {
var mouseKey = InputConstants.getKey(x, y); InputMappings.Input mouseKey = InputMappings.getInputByCode(x, y);
if (this.minecraft.options.keyInventory.isActiveAndMatches(mouseKey)) if (this.minecraft.gameSettings.keyBindInventory.isActiveAndMatches(mouseKey))
return false; return false;
} }
return super.keyPressed(x, y, z); return super.keyPressed(x, y, z);
@ -201,30 +202,30 @@ public class ItemTerminalGui extends AbstractContainerScreen<ItemTerminalContain
} }
public void updateWidgets() { public void updateWidgets() {
var prefs = PlayerPrefs.get(); PlayerPrefs prefs = PlayerPrefs.get();
this.ascendingButton.setMessage(new TextComponent(prefs.terminalAscending ? "^" : "v")); this.ascendingButton.setMessage(new StringTextComponent(prefs.terminalAscending ? "^" : "v"));
this.orderButton.setMessage(new TextComponent(prefs.terminalItemOrder.name().substring(0, 1))); this.orderButton.setMessage(new StringTextComponent(prefs.terminalItemOrder.name().substring(0, 1)));
this.cancelCraftingButton.visible = this.currentlyCrafting != null && !this.currentlyCrafting.isEmpty(); this.cancelCraftingButton.visible = this.currentlyCrafting != null && !this.currentlyCrafting.isEmpty();
var comparator = prefs.terminalItemOrder.comparator; Comparator<ItemStack> comparator = prefs.terminalItemOrder.comparator;
if (!prefs.terminalAscending) if (!prefs.terminalAscending)
comparator = comparator.reversed(); comparator = comparator.reversed();
// add all items to the sorted items list // add all items to the sorted items list
this.sortedItems.clear(); this.sortedItems.clear();
for (var stack : this.items) for (ItemStack stack : this.items)
this.sortedItems.add(Pair.of(stack, false)); this.sortedItems.add(Pair.of(stack, false));
for (var stack : this.craftables) for (ItemStack stack : this.craftables)
this.sortedItems.add(Pair.of(stack, true)); this.sortedItems.add(Pair.of(stack, true));
// compare by craftability first, and then by the player's chosen order // compare by craftability first, and then by the player's chosen order
Comparator<Pair<ItemStack, Boolean>> fullComparator = Comparator.comparing(Pair::getRight); Comparator<Pair<ItemStack, Boolean>> fullComparator = Comparator.comparing(Pair::getRight);
this.sortedItems.sort(fullComparator.thenComparing(Pair::getLeft, comparator)); this.sortedItems.sort(fullComparator.thenComparing(Pair::getLeft, comparator));
var searchText = this.search.getValue(); String searchText = this.search.getText();
if (!Strings.isNullOrEmpty(searchText)) { if (!Strings.isNullOrEmpty(searchText)) {
this.sortedItems.removeIf(s -> { this.sortedItems.removeIf(s -> {
var search = searchText; String search = searchText;
String toCompare; String toCompare;
if (search.startsWith("@")) { if (search.startsWith("@")) {
toCompare = s.getLeft().getItem().getCreatorModId(s.getLeft()); toCompare = s.getLeft().getItem().getCreatorModId(s.getLeft());
@ -240,16 +241,16 @@ public class ItemTerminalGui extends AbstractContainerScreen<ItemTerminalContain
if (this.sortedItems.size() < 9 * 4) if (this.sortedItems.size() < 9 * 4)
this.scrollOffset = 0; this.scrollOffset = 0;
var widgets = this.streamWidgets().collect(Collectors.toList()); List<ItemTerminalWidget> widgets = this.streamWidgets().collect(Collectors.toList());
for (var i = 0; i < widgets.size(); i++) { for (int i = 0; i < widgets.size(); i++) {
var widget = widgets.get(i); ItemTerminalWidget widget = widgets.get(i);
var index = i + this.scrollOffset * 9; int index = i + this.scrollOffset * 9;
if (index >= this.sortedItems.size()) { if (index >= this.sortedItems.size()) {
widget.stack = ItemStack.EMPTY; widget.stack = ItemStack.EMPTY;
widget.craftable = false; widget.craftable = false;
widget.visible = false; widget.visible = false;
} else { } else {
var stack = this.sortedItems.get(index); Pair<ItemStack, Boolean> stack = this.sortedItems.get(index);
widget.stack = stack.getLeft(); widget.stack = stack.getLeft();
widget.craftable = stack.getRight(); widget.craftable = stack.getRight();
widget.visible = true; widget.visible = true;
@ -258,69 +259,69 @@ public class ItemTerminalGui extends AbstractContainerScreen<ItemTerminalContain
} }
@Override @Override
public void render(PoseStack matrix, int mouseX, int mouseY, float partialTicks) { public void render(MatrixStack matrix, int mouseX, int mouseY, float partialTicks) {
this.renderBackground(matrix); this.renderBackground(matrix);
super.render(matrix, mouseX, mouseY, partialTicks); super.render(matrix, mouseX, mouseY, partialTicks);
for (var widget : this.renderables) { for (Widget widget : this.buttons) {
if (widget instanceof ItemTerminalWidget terminal) if (widget instanceof ItemTerminalWidget)
terminal.renderToolTip(matrix, mouseX, mouseY); widget.renderToolTip(matrix, mouseX, mouseY);
} }
if (this.sortedItems != null) { if (this.sortedItems != null) {
var prefs = PlayerPrefs.get(); PlayerPrefs prefs = PlayerPrefs.get();
if (this.orderButton.isHoveredOrFocused()) if (this.orderButton.isHovered())
this.renderTooltip(matrix, new TranslatableComponent("info." + PrettyPipes.ID + ".order", I18n.get("info." + PrettyPipes.ID + ".order." + prefs.terminalItemOrder.name().toLowerCase(Locale.ROOT))), mouseX, mouseY); this.renderTooltip(matrix, new TranslationTextComponent("info." + PrettyPipes.ID + ".order", I18n.format("info." + PrettyPipes.ID + ".order." + prefs.terminalItemOrder.name().toLowerCase(Locale.ROOT))), mouseX, mouseY);
if (this.ascendingButton.isHoveredOrFocused()) if (this.ascendingButton.isHovered())
this.renderTooltip(matrix, new TranslatableComponent("info." + PrettyPipes.ID + "." + (prefs.terminalAscending ? "ascending" : "descending")), mouseX, mouseY); this.renderTooltip(matrix, new TranslationTextComponent("info." + PrettyPipes.ID + "." + (prefs.terminalAscending ? "ascending" : "descending")), mouseX, mouseY);
} }
if (this.cancelCraftingButton.visible && this.cancelCraftingButton.isHoveredOrFocused()) { if (this.cancelCraftingButton.visible && this.cancelCraftingButton.isHovered()) {
var tooltip = I18n.get("info." + PrettyPipes.ID + ".cancel_all.desc").split("\n"); String[] tooltip = I18n.format("info." + PrettyPipes.ID + ".cancel_all.desc").split("\n");
this.renderComponentTooltip(matrix, Arrays.stream(tooltip).map(TextComponent::new).collect(Collectors.toList()), mouseX, mouseY); this.func_243308_b(matrix, Arrays.stream(tooltip).map(StringTextComponent::new).collect(Collectors.toList()), mouseX, mouseY);
} }
if (!this.hoveredCrafting.isEmpty()) if (!this.hoveredCrafting.isEmpty())
this.renderTooltip(matrix, this.hoveredCrafting, mouseX, mouseY); this.renderTooltip(matrix, this.hoveredCrafting, mouseX, mouseY);
this.renderTooltip(matrix, mouseX, mouseY); this.func_230459_a_(matrix, mouseX, mouseY);
} }
@Override @Override
protected void renderLabels(PoseStack matrix, int mouseX, int mouseY) { protected void drawGuiContainerForegroundLayer(MatrixStack matrix, int mouseX, int mouseY) {
this.font.draw(matrix, this.playerInventoryTitle.getString(), 8 + this.getXOffset(), this.imageHeight - 96 + 2, 4210752); this.font.drawString(matrix, this.playerInventory.getDisplayName().getString(), 8 + this.getXOffset(), this.ySize - 96 + 2, 4210752);
this.font.draw(matrix, this.title.getString(), 8, 6, 4210752); this.font.drawString(matrix, this.title.getString(), 8, 6, 4210752);
var amount = String.valueOf(this.requestAmount); String amount = String.valueOf(this.requestAmount);
this.font.draw(matrix, amount, (176 + 15 - this.font.width(amount)) / 2F - 7 + this.getXOffset(), 106, 4210752); this.font.drawString(matrix, amount, (176 + 15 - this.font.getStringWidth(amount)) / 2F - 7 + this.getXOffset(), 106, 4210752);
if (this.currentlyCrafting != null && !this.currentlyCrafting.isEmpty()) { if (this.currentlyCrafting != null && !this.currentlyCrafting.isEmpty()) {
this.font.draw(matrix, I18n.get("info." + PrettyPipes.ID + ".crafting"), this.imageWidth + 4, 4 + 6, 4210752); this.font.drawString(matrix, I18n.format("info." + PrettyPipes.ID + ".crafting"), this.xSize + 4, 4 + 6, 4210752);
if (this.currentlyCrafting.size() > 6) if (this.currentlyCrafting.size() > 6)
this.font.draw(matrix, ". . .", this.imageWidth + 24, 4 + 51, 4210752); this.font.drawString(matrix, ". . .", this.xSize + 24, 4 + 51, 4210752);
} }
} }
@Override @Override
protected void renderBg(PoseStack matrix, float partialTicks, int mouseX, int mouseY) { protected void drawGuiContainerBackgroundLayer(MatrixStack matrix, float partialTicks, int mouseX, int mouseY) {
this.getMinecraft().getTextureManager().bindForSetup(this.getTexture()); this.getMinecraft().getTextureManager().bindTexture(this.getTexture());
this.blit(matrix, this.leftPos, this.topPos, 0, 0, this.imageWidth, this.imageHeight); this.blit(matrix, this.guiLeft, this.guiTop, 0, 0, this.xSize, this.ySize);
if (this.sortedItems != null && this.sortedItems.size() >= 9 * 4) { if (this.sortedItems != null && this.sortedItems.size() >= 9 * 4) {
var percentage = this.scrollOffset / (float) (this.sortedItems.size() / 9 - 3); float percentage = this.scrollOffset / (float) (this.sortedItems.size() / 9 - 3);
this.blit(matrix, this.leftPos + this.getXOffset() + 172, this.topPos + 18 + (int) (percentage * (70 - 15)), 232, 241, 12, 15); this.blit(matrix, this.guiLeft + this.getXOffset() + 172, this.guiTop + 18 + (int) (percentage * (70 - 15)), 232, 241, 12, 15);
} else { } else {
this.blit(matrix, this.leftPos + this.getXOffset() + 172, this.topPos + 18, 244, 241, 12, 15); this.blit(matrix, this.guiLeft + this.getXOffset() + 172, this.guiTop + 18, 244, 241, 12, 15);
} }
// draw the items that are currently crafting // draw the items that are currently crafting
this.hoveredCrafting = ItemStack.EMPTY; this.hoveredCrafting = ItemStack.EMPTY;
if (this.currentlyCrafting != null && !this.currentlyCrafting.isEmpty()) { if (this.currentlyCrafting != null && !this.currentlyCrafting.isEmpty()) {
this.getMinecraft().getTextureManager().bindForSetup(TEXTURE); this.getMinecraft().getTextureManager().bindTexture(TEXTURE);
this.blit(matrix, this.leftPos + this.imageWidth, this.topPos + 4, 191, 0, 65, 89); this.blit(matrix, this.guiLeft + this.xSize, this.guiTop + 4, 191, 0, 65, 89);
var x = 0; int x = 0;
var y = 0; int y = 0;
for (var stack : this.currentlyCrafting) { for (ItemStack stack : this.currentlyCrafting) {
var itemX = this.leftPos + this.imageWidth + 4 + x * 18; int itemX = this.guiLeft + this.xSize + 4 + x * 18;
var itemY = this.topPos + 4 + 16 + y * 18; int itemY = this.guiTop + 4 + 16 + y * 18;
this.itemRenderer.renderGuiItem(stack, itemX, itemY); this.itemRenderer.renderItemAndEffectIntoGUI(stack, itemX, itemY);
this.itemRenderer.renderGuiItemDecorations(this.font, stack, itemX, itemY, String.valueOf(stack.getCount())); this.itemRenderer.renderItemOverlayIntoGUI(this.font, stack, itemX, itemY, String.valueOf(stack.getCount()));
if (mouseX >= itemX && mouseY >= itemY && mouseX < itemX + 16 && mouseY < itemY + 18) if (mouseX >= itemX && mouseY >= itemY && mouseX < itemX + 16 && mouseY < itemY + 18)
this.hoveredCrafting = stack; this.hoveredCrafting = stack;
x++; x++;
@ -341,7 +342,7 @@ public class ItemTerminalGui extends AbstractContainerScreen<ItemTerminalContain
@Override @Override
public boolean mouseScrolled(double x, double y, double scroll) { public boolean mouseScrolled(double x, double y, double scroll) {
if (this.sortedItems != null && this.sortedItems.size() >= 9 * 4) { if (this.sortedItems != null && this.sortedItems.size() >= 9 * 4) {
var offset = Mth.clamp(this.scrollOffset - (int) Math.signum(scroll), 0, this.sortedItems.size() / 9 - 3); int offset = MathHelper.clamp(this.scrollOffset - (int) Math.signum(scroll), 0, this.sortedItems.size() / 9 - 3);
if (offset != this.scrollOffset) { if (offset != this.scrollOffset) {
this.scrollOffset = offset; this.scrollOffset = offset;
this.updateWidgets(); this.updateWidgets();
@ -351,7 +352,7 @@ public class ItemTerminalGui extends AbstractContainerScreen<ItemTerminalContain
} }
public Stream<ItemTerminalWidget> streamWidgets() { public Stream<ItemTerminalWidget> streamWidgets() {
return this.renderables.stream() return this.buttons.stream()
.filter(w -> w instanceof ItemTerminalWidget) .filter(w -> w instanceof ItemTerminalWidget)
.map(w -> (ItemTerminalWidget) w); .map(w -> (ItemTerminalWidget) w);
} }

View file

@ -1,30 +1,32 @@
package de.ellpeck.prettypipes.terminal.containers; package de.ellpeck.prettypipes.terminal.containers;
import net.minecraft.world.entity.player.StackedContents; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.inventory.CraftingInventory;
import net.minecraft.world.inventory.CraftingContainer; import net.minecraft.inventory.ItemStackHelper;
import net.minecraft.inventory.container.Container;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.item.crafting.RecipeItemHelper;
import net.minecraftforge.items.ItemStackHandler; import net.minecraftforge.items.ItemStackHandler;
public class WrappedCraftingInventory extends CraftingContainer { public class WrappedCraftingInventory extends CraftingInventory {
private final ItemStackHandler items; private final ItemStackHandler items;
private final AbstractContainerMenu eventHandler; private final Container eventHandler;
public WrappedCraftingInventory(ItemStackHandler items, AbstractContainerMenu eventHandlerIn, int width, int height) { public WrappedCraftingInventory(ItemStackHandler items, Container eventHandlerIn, int width, int height) {
super(eventHandlerIn, width, height); super(eventHandlerIn, width, height);
this.eventHandler = eventHandlerIn; this.eventHandler = eventHandlerIn;
this.items = items; this.items = items;
} }
@Override @Override
public int getContainerSize() { public int getSizeInventory() {
return this.items.getSlots(); return this.items.getSlots();
} }
@Override @Override
public boolean isEmpty() { public boolean isEmpty() {
for (var i = 0; i < this.items.getSlots(); i++) { for (int i = 0; i < this.items.getSlots(); i++) {
if (!this.items.getStackInSlot(i).isEmpty()) if (!this.items.getStackInSlot(i).isEmpty())
return false; return false;
} }
@ -32,41 +34,41 @@ public class WrappedCraftingInventory extends CraftingContainer {
} }
@Override @Override
public ItemStack getItem(int index) { public ItemStack getStackInSlot(int index) {
return this.items.getStackInSlot(index); return this.items.getStackInSlot(index);
} }
@Override @Override
public ItemStack removeItemNoUpdate(int index) { public ItemStack removeStackFromSlot(int index) {
var before = this.items.getStackInSlot(index); ItemStack before = this.items.getStackInSlot(index);
this.items.setStackInSlot(index, ItemStack.EMPTY); this.items.setStackInSlot(index, ItemStack.EMPTY);
return before; return before;
} }
@Override @Override
public ItemStack removeItem(int index, int count) { public ItemStack decrStackSize(int index, int count) {
var slotStack = this.items.getStackInSlot(index); ItemStack slotStack = this.items.getStackInSlot(index);
var ret = !slotStack.isEmpty() && count > 0 ? slotStack.split(count) : ItemStack.EMPTY; ItemStack ret = !slotStack.isEmpty() && count > 0 ? slotStack.split(count) : ItemStack.EMPTY;
if (!ret.isEmpty()) if (!ret.isEmpty())
this.eventHandler.slotsChanged(this); this.eventHandler.onCraftMatrixChanged(this);
return ret; return ret;
} }
@Override @Override
public void setItem(int index, ItemStack stack) { public void setInventorySlotContents(int index, ItemStack stack) {
this.items.setStackInSlot(index, stack); this.items.setStackInSlot(index, stack);
this.eventHandler.slotsChanged(this); this.eventHandler.onCraftMatrixChanged(this);
} }
@Override @Override
public void clearContent() { public void clear() {
for (var i = 0; i < this.items.getSlots(); i++) for (int i = 0; i < this.items.getSlots(); i++)
this.items.setStackInSlot(i, ItemStack.EMPTY); this.items.setStackInSlot(i, ItemStack.EMPTY);
} }
@Override @Override
public void fillStackedContents(StackedContents helper) { public void fillStackedContents(RecipeItemHelper helper) {
for (var i = 0; i < this.items.getSlots(); i++) for (int i = 0; i < this.items.getSlots(); i++)
helper.accountStack(this.items.getStackInSlot(i)); helper.accountPlainStack(this.items.getStackInSlot(i));
} }
} }