diff --git a/build.gradle b/build.gradle index afa76c8a1..415ead953 100644 --- a/build.gradle +++ b/build.gradle @@ -20,7 +20,7 @@ archivesBaseName = 'create' sourceCompatibility = targetCompatibility = compileJava.sourceCompatibility = compileJava.targetCompatibility = '1.8' minecraft { - mappings channel: 'snapshot', version: '20190917-1.14.3' + mappings channel: 'snapshot', version: '20190927-1.14.3' runs { client { @@ -71,12 +71,12 @@ repositories { } dependencies { - minecraft 'net.minecraftforge:forge:1.14.4-28.1.6' + minecraft 'net.minecraftforge:forge:1.14.4-28.1.22' // compile against the JEI API but do not include it at runtime compileOnly fg.deobf("mezz.jei:jei-1.14.4:6.0.0.10:api") // at runtime, use the full JEI jar - runtimeOnly fg.deobf("mezz.jei:jei-1.14.4:6.0.0.10") + runtimeOnly fg.deobf("mezz.jei:jei-1.14.4:6.0.0.13") } jar { diff --git a/src/main/java/com/simibubi/create/AllBlocks.java b/src/main/java/com/simibubi/create/AllBlocks.java index b5864318a..04795b8b5 100644 --- a/src/main/java/com/simibubi/create/AllBlocks.java +++ b/src/main/java/com/simibubi/create/AllBlocks.java @@ -37,15 +37,19 @@ import com.simibubi.create.modules.curiosities.symmetry.block.CrossPlaneSymmetry import com.simibubi.create.modules.curiosities.symmetry.block.PlaneSymmetryBlock; import com.simibubi.create.modules.curiosities.symmetry.block.TriplePlaneSymmetryBlock; import com.simibubi.create.modules.gardens.CocoaLogBlock; -import com.simibubi.create.modules.logistics.block.BeltFunnelBlock; -import com.simibubi.create.modules.logistics.block.EntityDetectorBlock; -import com.simibubi.create.modules.logistics.block.ExtractorBlock; -import com.simibubi.create.modules.logistics.block.FlexcrateBlock; -import com.simibubi.create.modules.logistics.block.LinkedExtractorBlock; import com.simibubi.create.modules.logistics.block.RedstoneBridgeBlock; import com.simibubi.create.modules.logistics.block.StockswitchBlock; +import com.simibubi.create.modules.logistics.block.belts.BeltFunnelBlock; +import com.simibubi.create.modules.logistics.block.belts.EntityDetectorBlock; +import com.simibubi.create.modules.logistics.block.belts.ExtractorBlock; +import com.simibubi.create.modules.logistics.block.belts.LinkedExtractorBlock; import com.simibubi.create.modules.logistics.block.diodes.FlexpeaterBlock; import com.simibubi.create.modules.logistics.block.diodes.PulseRepeaterBlock; +import com.simibubi.create.modules.logistics.block.inventories.FlexcrateBlock; +import com.simibubi.create.modules.logistics.management.base.LogisticalCasingBlock; +import com.simibubi.create.modules.logistics.management.base.LogisticalControllerBlock; +import com.simibubi.create.modules.logistics.management.base.LogisticalControllerBlock.LogisticalControllerIndicatorBlock; +import com.simibubi.create.modules.logistics.management.index.LogisticalIndexBlock; import com.simibubi.create.modules.palettes.GlassPaneBlock; import com.simibubi.create.modules.schematics.block.CreativeCrateBlock; import com.simibubi.create.modules.schematics.block.SchematicTableBlock; @@ -125,6 +129,10 @@ public enum AllBlocks { PULSE_REPEATER(new PulseRepeaterBlock()), FLEXPEATER(new FlexpeaterBlock()), FLEXPEATER_INDICATOR(new RenderUtilityBlock()), + LOGISTICAL_CASING(new LogisticalCasingBlock()), + LOGISTICAL_CONTROLLER(new LogisticalControllerBlock()), + LOGISTICAL_CONTROLLER_INDICATOR(new LogisticalControllerIndicatorBlock()), + LOGISTICAL_INDEX(new LogisticalIndexBlock()), __CURIOSITIES__(), SYMMETRY_PLANE(new PlaneSymmetryBlock()), diff --git a/src/main/java/com/simibubi/create/AllContainers.java b/src/main/java/com/simibubi/create/AllContainers.java index fb0153905..1b4fdc896 100644 --- a/src/main/java/com/simibubi/create/AllContainers.java +++ b/src/main/java/com/simibubi/create/AllContainers.java @@ -1,7 +1,9 @@ package com.simibubi.create; -import com.simibubi.create.modules.logistics.block.FlexcrateContainer; -import com.simibubi.create.modules.logistics.block.FlexcrateScreen; +import com.simibubi.create.modules.logistics.block.inventories.FlexcrateContainer; +import com.simibubi.create.modules.logistics.block.inventories.FlexcrateScreen; +import com.simibubi.create.modules.logistics.management.index.LogisticalIndexContainer; +import com.simibubi.create.modules.logistics.management.index.LogisticalIndexScreen; import com.simibubi.create.modules.schematics.block.SchematicTableContainer; import com.simibubi.create.modules.schematics.block.SchematicTableScreen; import com.simibubi.create.modules.schematics.block.SchematicannonContainer; @@ -29,6 +31,7 @@ public enum AllContainers { SCHEMATIC_TABLE(SchematicTableContainer::new), SCHEMATICANNON(SchematicannonContainer::new), FLEXCRATE(FlexcrateContainer::new), + LOGISTICAL_INDEX(LogisticalIndexContainer::new), ; @@ -54,6 +57,7 @@ public enum AllContainers { bind(SCHEMATIC_TABLE, SchematicTableScreen::new); bind(SCHEMATICANNON, SchematicannonScreen::new); bind(FLEXCRATE, FlexcrateScreen::new); + bind(LOGISTICAL_INDEX, LogisticalIndexScreen::new); } @OnlyIn(Dist.CLIENT) diff --git a/src/main/java/com/simibubi/create/AllEntities.java b/src/main/java/com/simibubi/create/AllEntities.java new file mode 100644 index 000000000..8cb707c2a --- /dev/null +++ b/src/main/java/com/simibubi/create/AllEntities.java @@ -0,0 +1,61 @@ +package com.simibubi.create; + +import java.util.function.Function; + +import com.simibubi.create.modules.logistics.entity.CardboardBoxEntity; +import com.simibubi.create.modules.logistics.entity.CardboardBoxEntityRenderer; + +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityClassification; +import net.minecraft.entity.EntityType; +import net.minecraft.entity.EntityType.Builder; +import net.minecraft.entity.EntityType.IFactory; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.event.RegistryEvent; +import net.minecraftforge.fml.client.registry.RenderingRegistry; + +public enum AllEntities { + + CARDBOARD_BOX(CardboardBoxEntity::new, 30, 3, CardboardBoxEntity::build), + + ; + + private IFactory factory; + private int range; + private int updateFrequency; + private Function, EntityType.Builder> propertyBuilder; + private EntityClassification group; + + public EntityType type; + + private AllEntities(IFactory factory, int range, int updateFrequency, + Function, EntityType.Builder> propertyBuilder) { + this.factory = factory; + this.range = range; + this.updateFrequency = updateFrequency; + this.propertyBuilder = propertyBuilder; + } + + public static void register(final RegistryEvent.Register> event) { + for (AllEntities entity : values()) { + String id = entity.name().toLowerCase(); + ResourceLocation resourceLocation = new ResourceLocation(Create.ID, id); + Builder builder = EntityType.Builder.create(entity.factory, entity.group) + .setTrackingRange(entity.range).setUpdateInterval(entity.updateFrequency) + .setShouldReceiveVelocityUpdates(true); + if (entity.propertyBuilder != null) + builder = entity.propertyBuilder.apply(builder); + entity.type = builder.build(id).setRegistryName(resourceLocation); + event.getRegistry().register(entity.type); + } + + } + + @OnlyIn(value = Dist.CLIENT) + public static void registerRenderers() { + RenderingRegistry.registerEntityRenderingHandler(CardboardBoxEntity.class, CardboardBoxEntityRenderer::new); + } + +} diff --git a/src/main/java/com/simibubi/create/AllItems.java b/src/main/java/com/simibubi/create/AllItems.java index 57502af0a..3f886bdb6 100644 --- a/src/main/java/com/simibubi/create/AllItems.java +++ b/src/main/java/com/simibubi/create/AllItems.java @@ -10,6 +10,10 @@ import com.simibubi.create.modules.curiosities.placementHandgun.BuilderGunItemRe import com.simibubi.create.modules.curiosities.symmetry.SymmetryWandItem; import com.simibubi.create.modules.curiosities.symmetry.client.SymmetryWandItemRenderer; import com.simibubi.create.modules.gardens.TreeFertilizerItem; +import com.simibubi.create.modules.logistics.item.CardboardBoxItem; +import com.simibubi.create.modules.logistics.management.LogisticalDialItem; +import com.simibubi.create.modules.logistics.management.base.LogisticalControllerBlock.Type; +import com.simibubi.create.modules.logistics.management.base.LogisticalControllerItem; import com.simibubi.create.modules.schematics.item.SchematicAndQuillItem; import com.simibubi.create.modules.schematics.item.SchematicItem; @@ -76,6 +80,19 @@ public enum AllItems { DOUGH(ingredient()), PROPELLER(ingredient()), + __LOGISTICS__(), + CARDBOARD_BOX_1616(new CardboardBoxItem(standardItemProperties())), + CARDBOARD_BOX_1612(new CardboardBoxItem(standardItemProperties())), + CARDBOARD_BOX_1416(new CardboardBoxItem(standardItemProperties())), + CARDBOARD_BOX_1410(new CardboardBoxItem(standardItemProperties())), + + LOGISTICAL_DIAL(new LogisticalDialItem(standardItemProperties())), + LOGISTICAL_CONTROLLER_SUPPLY(new LogisticalControllerItem(standardItemProperties(), Type.SUPPLY)), + LOGISTICAL_CONTROLLER_REQUEST(new LogisticalControllerItem(standardItemProperties(), Type.REQUEST)), + LOGISTICAL_CONTROLLER_STORAGE(new LogisticalControllerItem(standardItemProperties(), Type.STORAGE)), + LOGISTICAL_CONTROLLER_CALCULATION(new LogisticalControllerItem(standardItemProperties(), Type.CALCULATION)), + LOGISTICAL_CONTROLLER_TRANSACTIONS(new LogisticalControllerItem(standardItemProperties(), Type.TRANSACTIONS)), + ; private static class CategoryTracker { @@ -129,6 +146,10 @@ public enum AllItems { public boolean typeOf(ItemStack stack) { return stack.getItem() == item; } + + public ItemStack asStack() { + return new ItemStack(item); + } // Client diff --git a/src/main/java/com/simibubi/create/AllKeys.java b/src/main/java/com/simibubi/create/AllKeys.java index ee857e4f6..ffb5b4367 100644 --- a/src/main/java/com/simibubi/create/AllKeys.java +++ b/src/main/java/com/simibubi/create/AllKeys.java @@ -9,7 +9,7 @@ import net.minecraftforge.fml.client.registry.ClientRegistry; public enum AllKeys { - TOOL_MENU("toolmenu", GLFW.GLFW_KEY_LEFT_ALT), + TOOL_MENU("toolmenu", GLFW.GLFW_KEY_LEFT_ALT), ACTIVATE_TOOL("", GLFW.GLFW_KEY_LEFT_CONTROL), ; @@ -30,7 +30,7 @@ public enum AllKeys { key.keybind = new KeyBinding(key.description, key.key, Create.NAME); if (!key.modifiable) continue; - + ClientRegistry.registerKeyBinding(key.keybind); } } diff --git a/src/main/java/com/simibubi/create/AllPackets.java b/src/main/java/com/simibubi/create/AllPackets.java index 4cda41e0c..7dc2d2c6d 100644 --- a/src/main/java/com/simibubi/create/AllPackets.java +++ b/src/main/java/com/simibubi/create/AllPackets.java @@ -11,6 +11,8 @@ import com.simibubi.create.modules.contraptions.receivers.constructs.ConfigureCh import com.simibubi.create.modules.curiosities.placementHandgun.BuilderGunBeamPacket; import com.simibubi.create.modules.curiosities.symmetry.SymmetryEffectPacket; import com.simibubi.create.modules.logistics.block.diodes.ConfigureFlexpeaterPacket; +import com.simibubi.create.modules.logistics.management.index.IndexContainerUpdatePacket; +import com.simibubi.create.modules.logistics.management.index.IndexOrderRequest; import com.simibubi.create.modules.logistics.packet.ConfigureFlexcratePacket; import com.simibubi.create.modules.logistics.packet.ConfigureStockswitchPacket; import com.simibubi.create.modules.schematics.packet.ConfigureSchematicannonPacket; @@ -35,10 +37,12 @@ public enum AllPackets { CONFIGURE_FLEXPEATER(ConfigureFlexpeaterPacket.class, ConfigureFlexpeaterPacket::new), PLACE_SCHEMATIC(SchematicPlacePacket.class, SchematicPlacePacket::new), UPLOAD_SCHEMATIC(SchematicUploadPacket.class, SchematicUploadPacket::new), - + INDEX_ORDER_REQUEST(IndexOrderRequest.class, IndexOrderRequest::new), + // Server to Client SYMMETRY_EFFECT(SymmetryEffectPacket.class, SymmetryEffectPacket::new), BEAM_EFFECT(BuilderGunBeamPacket.class, BuilderGunBeamPacket::new), + INDEX_CONTAINER_UPDATE(IndexContainerUpdatePacket.class, IndexContainerUpdatePacket::new), ; diff --git a/src/main/java/com/simibubi/create/AllTileEntities.java b/src/main/java/com/simibubi/create/AllTileEntities.java index 966e1955e..82ae2d708 100644 --- a/src/main/java/com/simibubi/create/AllTileEntities.java +++ b/src/main/java/com/simibubi/create/AllTileEntities.java @@ -30,19 +30,28 @@ import com.simibubi.create.modules.contraptions.relays.SplitShaftTileEntityRende import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntity; import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntityRenderer; import com.simibubi.create.modules.curiosities.partialWindows.WindowInABlockTileEntity; -import com.simibubi.create.modules.logistics.block.BeltFunnelTileEntity; -import com.simibubi.create.modules.logistics.block.EntityDetectorTileEntity; -import com.simibubi.create.modules.logistics.block.EntityDetectorTileEntityRenderer; -import com.simibubi.create.modules.logistics.block.ExtractorTileEntity; -import com.simibubi.create.modules.logistics.block.ExtractorTileEntityRenderer; -import com.simibubi.create.modules.logistics.block.FlexcrateTileEntity; -import com.simibubi.create.modules.logistics.block.LinkedExtractorTileEntity; -import com.simibubi.create.modules.logistics.block.LinkedExtractorTileEntityRenderer; import com.simibubi.create.modules.logistics.block.LinkedTileEntityRenderer; import com.simibubi.create.modules.logistics.block.RedstoneBridgeTileEntity; import com.simibubi.create.modules.logistics.block.StockswitchTileEntity; +import com.simibubi.create.modules.logistics.block.belts.BeltFunnelTileEntity; +import com.simibubi.create.modules.logistics.block.belts.EntityDetectorTileEntity; +import com.simibubi.create.modules.logistics.block.belts.EntityDetectorTileEntityRenderer; +import com.simibubi.create.modules.logistics.block.belts.ExtractorTileEntity; +import com.simibubi.create.modules.logistics.block.belts.ExtractorTileEntityRenderer; +import com.simibubi.create.modules.logistics.block.belts.LinkedExtractorTileEntity; +import com.simibubi.create.modules.logistics.block.belts.LinkedExtractorTileEntityRenderer; import com.simibubi.create.modules.logistics.block.diodes.FlexpeaterTileEntity; import com.simibubi.create.modules.logistics.block.diodes.FlexpeaterTileEntityRenderer; +import com.simibubi.create.modules.logistics.block.inventories.FlexcrateTileEntity; +import com.simibubi.create.modules.logistics.management.base.LogisticalCasingTileEntity; +import com.simibubi.create.modules.logistics.management.base.LogisticalControllerTileEntity; +import com.simibubi.create.modules.logistics.management.base.LogisticalControllerTileEntityRenderer; +import com.simibubi.create.modules.logistics.management.controller.CalculationTileEntity; +import com.simibubi.create.modules.logistics.management.controller.RequestTileEntity; +import com.simibubi.create.modules.logistics.management.controller.StorageTileEntity; +import com.simibubi.create.modules.logistics.management.controller.SupplyTileEntity; +import com.simibubi.create.modules.logistics.management.controller.TransactionsTileEntity; +import com.simibubi.create.modules.logistics.management.index.LogisticalIndexTileEntity; import com.simibubi.create.modules.schematics.block.SchematicTableTileEntity; import com.simibubi.create.modules.schematics.block.SchematicannonRenderer; import com.simibubi.create.modules.schematics.block.SchematicannonTileEntity; @@ -95,6 +104,13 @@ public enum AllTileEntities { BELT_FUNNEL(BeltFunnelTileEntity::new, AllBlocks.BELT_FUNNEL), ENTITY_DETECTOR(EntityDetectorTileEntity::new, AllBlocks.ENTITY_DETECTOR), FLEXPEATER(FlexpeaterTileEntity::new, AllBlocks.FLEXPEATER), + LOGISTICAL_CASING(LogisticalCasingTileEntity::new, AllBlocks.LOGISTICAL_CASING), + LOGISTICAL_SUPPLY_CONTROLLER(SupplyTileEntity::new, AllBlocks.LOGISTICAL_CONTROLLER), + LOGISTICAL_REQUEST_CONTROLLER(RequestTileEntity::new, AllBlocks.LOGISTICAL_CONTROLLER), + LOGISTICAL_STORAGE_CONTROLLER(StorageTileEntity::new, AllBlocks.LOGISTICAL_CONTROLLER), + LOGISTICAL_CALCULATION_CONTROLLER(CalculationTileEntity::new, AllBlocks.LOGISTICAL_CONTROLLER), + LOGISTICAL_TRANSATIONS_CONTROLLER(TransactionsTileEntity::new, AllBlocks.LOGISTICAL_CONTROLLER), + LOGISTICAL_INDEX(LogisticalIndexTileEntity::new, AllBlocks.LOGISTICAL_INDEX), // Curiosities WINDOW_IN_A_BLOCK(WindowInABlockTileEntity::new, AllBlocks.WINDOW_IN_A_BLOCK), @@ -148,6 +164,7 @@ public enum AllTileEntities { bind(EntityDetectorTileEntity.class, new EntityDetectorTileEntityRenderer()); bind(MechanicalPressTileEntity.class, new MechanicalPressTileEntityRenderer()); bind(FlexpeaterTileEntity.class, new FlexpeaterTileEntityRenderer()); + bind(LogisticalControllerTileEntity.class, new LogisticalControllerTileEntityRenderer()); } @OnlyIn(Dist.CLIENT) diff --git a/src/main/java/com/simibubi/create/Create.java b/src/main/java/com/simibubi/create/Create.java index 6fdf530b7..c22e66c3e 100644 --- a/src/main/java/com/simibubi/create/Create.java +++ b/src/main/java/com/simibubi/create/Create.java @@ -6,9 +6,11 @@ import org.apache.logging.log4j.Logger; import com.simibubi.create.modules.ModuleLoadedCondition; import com.simibubi.create.modules.contraptions.receivers.constructs.MovingConstructHandler; import com.simibubi.create.modules.logistics.FrequencyHandler; +import com.simibubi.create.modules.logistics.management.LogisticalNetworkHandler; import com.simibubi.create.modules.schematics.ServerSchematicLoader; import net.minecraft.block.Block; +import net.minecraft.entity.EntityType; import net.minecraft.item.Item; import net.minecraft.item.ItemGroup; import net.minecraft.item.crafting.IRecipeSerializer; @@ -35,6 +37,7 @@ public class Create { public static ServerSchematicLoader schematicReceiver; public static FrequencyHandler frequencyHandler; public static MovingConstructHandler constructHandler; + public static LogisticalNetworkHandler logisticalNetworkHandler; public static ModConfig config; @@ -48,6 +51,8 @@ public class Create { schematicReceiver = new ServerSchematicLoader(); frequencyHandler = new FrequencyHandler(); constructHandler = new MovingConstructHandler(); + logisticalNetworkHandler = new LogisticalNetworkHandler(); + CraftingHelper.register(new ModuleLoadedCondition.Serializer()); AllPackets.registerPackets(); } @@ -67,6 +72,11 @@ public class Create { public static void registerRecipes(RegistryEvent.Register> event) { AllRecipes.register(event); } + + @SubscribeEvent + public static void registerEntities(final RegistryEvent.Register> event) { + AllEntities.register(event); + } @SubscribeEvent public static void createConfigs(ModConfig.ModConfigEvent event) { diff --git a/src/main/java/com/simibubi/create/CreateClient.java b/src/main/java/com/simibubi/create/CreateClient.java index 1b1323e44..7005ecdf6 100644 --- a/src/main/java/com/simibubi/create/CreateClient.java +++ b/src/main/java/com/simibubi/create/CreateClient.java @@ -54,6 +54,7 @@ public class CreateClient { AllTileEntities.registerRenderers(); AllItems.registerColorHandlers(); AllBlocks.registerColorHandlers(); + AllEntities.registerRenderers(); IResourceManager resourceManager = Minecraft.getInstance().getResourceManager(); if (resourceManager instanceof IReloadableResourceManager) diff --git a/src/main/java/com/simibubi/create/CreateItemGroup.java b/src/main/java/com/simibubi/create/CreateItemGroup.java index 4fdd1e99c..b15e55879 100644 --- a/src/main/java/com/simibubi/create/CreateItemGroup.java +++ b/src/main/java/com/simibubi/create/CreateItemGroup.java @@ -15,7 +15,7 @@ public final class CreateItemGroup extends ItemGroup { @Override public ItemStack createIcon() { - return new ItemStack(AllItems.SYMMETRY_WAND.get()); + return new ItemStack(AllBlocks.COGWHEEL.get()); } @Override diff --git a/src/main/java/com/simibubi/create/Events.java b/src/main/java/com/simibubi/create/Events.java index 368b1c013..145592020 100644 --- a/src/main/java/com/simibubi/create/Events.java +++ b/src/main/java/com/simibubi/create/Events.java @@ -45,6 +45,7 @@ public class Events { IWorld world = event.getWorld(); Create.frequencyHandler.onLoadWorld(world); Create.constructHandler.onLoadWorld(world); + Create.logisticalNetworkHandler.onLoadWorld(world); } @SubscribeEvent @@ -52,6 +53,7 @@ public class Events { IWorld world = event.getWorld(); Create.frequencyHandler.onUnloadWorld(world); Create.constructHandler.onUnloadWorld(world); + Create.logisticalNetworkHandler.onUnloadWorld(world); } @SubscribeEvent @@ -81,7 +83,8 @@ public class Events { if (AllBlocks.WINDOW_IN_A_BLOCK.typeOf(blockState)) return; - world.setBlockState(pos, AllBlocks.WINDOW_IN_A_BLOCK.get().getDefaultState()); + BlockState defaultState = AllBlocks.WINDOW_IN_A_BLOCK.get().getDefaultState(); + world.setBlockState(pos, defaultState); TileEntity te = world.getTileEntity(pos); if (te != null && te instanceof WindowInABlockTileEntity) { WindowInABlockTileEntity wte = (WindowInABlockTileEntity) te; diff --git a/src/main/java/com/simibubi/create/ScreenResources.java b/src/main/java/com/simibubi/create/ScreenResources.java index ede2380d6..38baf178c 100644 --- a/src/main/java/com/simibubi/create/ScreenResources.java +++ b/src/main/java/com/simibubi/create/ScreenResources.java @@ -5,16 +5,16 @@ import net.minecraft.client.gui.AbstractGui; import net.minecraft.util.ResourceLocation; public enum ScreenResources { - + // Inventories PLAYER_INVENTORY("player_inventory.png", 176, 108), WAND_SYMMETRY("wand_symmetry.png", 207, 58), PLACEMENT_GUN("placement_handgun.png", 217, 70), - + SCHEMATIC_TABLE("schematic_table.png", 207, 89), SCHEMATIC_TABLE_PROGRESS("schematic_table.png", 209, 0, 24, 17), SCHEMATIC("schematic.png", 207, 95), - + SCHEMATICANNON("schematicannon.png", 247, 161), SCHEMATICANNON_PROGRESS("schematicannon.png", 0, 161, 121, 16), SCHEMATICANNON_PROGRESS_2("schematicannon.png", 122, 161, 16, 15), @@ -23,7 +23,7 @@ public enum ScreenResources { FLEXCRATE("flex_crate_and_stockpile_switch.png", 125, 129), FLEXCRATE_LOCKED_SLOT("flex_crate_and_stockpile_switch.png", 138, 0, 18, 18), - + STOCKSWITCH("flex_crate_and_stockpile_switch.png", 0, 129, 205, 93), STOCKSWITCH_INTERVAL("flex_crate_and_stockpile_switch.png", 0, 222, 198, 17), STOCKSWITCH_INTERVAL_END("flex_crate_and_stockpile_switch.png", 0, 239, 198, 17), @@ -31,14 +31,36 @@ public enum ScreenResources { STOCKSWITCH_CURSOR_OFF("flex_crate_and_stockpile_switch.png", 226, 129, 8, 21), STOCKSWITCH_BOUND_LEFT("flex_crate_and_stockpile_switch.png", 234, 129, 7, 21), STOCKSWITCH_BOUND_RIGHT("flex_crate_and_stockpile_switch.png", 241, 129, 7, 21), - + + // Logistical Index + INDEX_TOP("index.png", 41, 0, 174, 22), + INDEX_TOP_TRIM("index.png", 41, 22, 174, 6), + INDEX_MIDDLE("index.png", 41, 28, 183, 178), + INDEX_BOTTOM_TRIM("index.png", 41, 206, 174, 6), + INDEX_BOTTOM("index.png", 41, 212, 181, 44), + INDEX_SCROLLER_TOP("index.png", 224, 31, 10, 6), + INDEX_SCROLLER_MIDDLE("index.png", 224, 37, 10, 6), + INDEX_SCROLLER_BOTTOM("index.png", 224, 43, 10, 6), + INDEX_TAB("index.png", 0, 55, 22, 22), + INDEX_TAB_ACTIVE("index.png", 0, 77, 22, 22), + INDEX_SEARCH("index.png", 0, 99, 28, 19), + INDEX_SEARCH_OVERLAY("widgets.png", 0, 81, 176, 20), + + SLOT_FRAME("index.png", 0, 118, 18, 18), + SLOT_INNER("index.png", 18, 118, 18, 18), + DISABLED_SLOT_FRAME("index.png", 0, 136, 18, 18), + DISABLED_SLOT_INNER("index.png", 18, 136, 18, 18), + CRAFTY_SLOT_FRAME("index.png", 0, 154, 18, 18), + CRAFTY_SLOT_INNER("index.png", 18, 154, 18, 18), + SELECTED_SLOT_INNER("index.png", 18, 172, 18, 18), + // JEI CRUSHING_RECIPE("recipes1.png", 177, 109), FAN_RECIPE("recipes1.png", 0, 128, 177, 109), BLOCKZAPPER_UPGRADE_RECIPE("recipes2.png", 144, 66), PRESSER_RECIPE("recipes2.png", 0, 108, 177, 109), WASHING_RECIPE("recipes3.png", 177, 109), - + // Widgets PALETTE_BUTTON("palette_picker.png", 0, 236, 20, 20), TEXT_INPUT("widgets.png", 0, 28, 194, 47), @@ -51,9 +73,9 @@ public enum ScreenResources { INDICATOR_YELLOW("widgets.png", 18, 23, 18, 5), INDICATOR_RED("widgets.png", 36, 23, 18, 5), GRAY("background.png", 0, 0, 16, 16), - + BLUEPRINT_SLOT("widgets.png", 90, 0, 24, 24), - + // Icons ICON_NONE("icons.png", 16, 16, 16, 16), ICON_ADD("icons.png", 16, 16), @@ -61,28 +83,28 @@ public enum ScreenResources { ICON_3x3("icons.png", 32, 0, 16, 16), ICON_TARGET("icons.png", 48, 0, 16, 16), ICON_CONFIRM("icons.png", 0, 16, 16, 16), - + ICON_OPEN_FOLDER("icons.png", 32, 16, 16, 16), ICON_REFRESH("icons.png", 48, 16, 16, 16), - + ICON_DONT_REPLACE("icons.png", 0, 32, 16, 16), ICON_REPLACE_SOLID("icons.png", 16, 32, 16, 16), ICON_REPLACE_ANY("icons.png", 32, 32, 16, 16), ICON_REPLACE_EMPTY("icons.png", 48, 32, 16, 16), - + ICON_TOOL_DEPLOY("icons.png", 0, 48, 16, 16), ICON_SKIP_MISSING("icons.png", 16, 48, 16, 16), ICON_SKIP_TILES("icons.png", 32, 48, 16, 16), - + ICON_TOOL_MOVE_XZ("icons.png", 0, 64, 16, 16), ICON_TOOL_MOVE_Y("icons.png", 16, 64, 16, 16), ICON_TOOL_ROTATE("icons.png", 32, 64, 16, 16), ICON_TOOL_MIRROR("icons.png", 48, 64, 16, 16), - + ICON_PLAY("icons.png", 0, 80, 16, 16), ICON_PAUSE("icons.png", 16, 80, 16, 16), ICON_STOP("icons.png", 32, 80, 16, 16), - + ICON_PATTERN_SOLID("icons.png", 0, 96, 16, 16), ICON_PATTERN_CHECKERED("icons.png", 16, 96, 16, 16), ICON_PATTERN_CHECKERED_INVERSED("icons.png", 32, 96, 16, 16), @@ -91,29 +113,31 @@ public enum ScreenResources { ICON_PATTERN_CHANCE_75("icons.png", 16, 112, 16, 16), ICON_FOLLOW_DIAGONAL("icons.png", 32, 112, 16, 16), ICON_FOLLOW_MATERIAL("icons.png", 48, 112, 16, 16), - + ; - + public static final int FONT_COLOR = 0x575F7A; - + public final ResourceLocation location; public int width, height; public int startX, startY; - + private ScreenResources(String location, int width, int height) { this(location, 0, 0, width, height); } - + private ScreenResources(String location, int startX, int startY, int width, int height) { this.location = new ResourceLocation(Create.ID, "textures/gui/" + location); - this.width = width; this.height = height; - this.startX = startX; this.startY = startY; + this.width = width; + this.height = height; + this.startX = startX; + this.startY = startY; } - + public void bind() { Minecraft.getInstance().getTextureManager().bindTexture(location); } - + public void draw(AbstractGui screen, int i, int j) { bind(); screen.blit(i, j, startX, startY, width, height); diff --git a/src/main/java/com/simibubi/create/foundation/block/ProperStairsBlock.java b/src/main/java/com/simibubi/create/foundation/block/ProperStairsBlock.java index 5efbf5045..35892d1fd 100644 --- a/src/main/java/com/simibubi/create/foundation/block/ProperStairsBlock.java +++ b/src/main/java/com/simibubi/create/foundation/block/ProperStairsBlock.java @@ -6,7 +6,7 @@ import net.minecraft.block.StairsBlock; public class ProperStairsBlock extends StairsBlock { public ProperStairsBlock(Block block) { - super(block.getDefaultState(), Properties.from(block)); + super(() -> block.getDefaultState(), Properties.from(block)); } } diff --git a/src/main/java/com/simibubi/create/foundation/block/TileEntityExtension.java b/src/main/java/com/simibubi/create/foundation/block/TileEntityExtension.java new file mode 100644 index 000000000..7a99d10ab --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/block/TileEntityExtension.java @@ -0,0 +1,7 @@ +package com.simibubi.create.foundation.block; + +import net.minecraft.tileentity.TileEntity; + +public abstract class TileEntityExtension { + +} diff --git a/src/main/java/com/simibubi/create/foundation/gui/widgets/InterpolatedChasingValue.java b/src/main/java/com/simibubi/create/foundation/gui/widgets/InterpolatedChasingValue.java new file mode 100644 index 000000000..e18b5f6d4 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/gui/widgets/InterpolatedChasingValue.java @@ -0,0 +1,26 @@ +package com.simibubi.create.foundation.gui.widgets; + +public class InterpolatedChasingValue extends InterpolatedValue { + + float speed = 0.5f; + float target = 0; + float eps = 1 / 4096f; + + public void tick() { + float diff = target - value; + if (Math.abs(diff) < eps) + return; + set(value + (diff) * speed); + } + + public InterpolatedChasingValue withSpeed(float speed) { + this.speed = speed; + return this; + } + + public InterpolatedChasingValue target(float target) { + this.target = target; + return this; + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/gui/widgets/InterpolatedValue.java b/src/main/java/com/simibubi/create/foundation/gui/widgets/InterpolatedValue.java new file mode 100644 index 000000000..6739f39af --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/gui/widgets/InterpolatedValue.java @@ -0,0 +1,20 @@ +package com.simibubi.create.foundation.gui.widgets; + +import net.minecraft.util.math.MathHelper; + +public class InterpolatedValue { + + public float value = 0; + public float lastValue = 0; + + public InterpolatedValue set(float value) { + lastValue = this.value; + this.value = value; + return this; + } + + public float get(float partialTicks) { + return MathHelper.lerp(partialTicks, lastValue, value); + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/type/CombinedCountedItemsList.java b/src/main/java/com/simibubi/create/foundation/type/CombinedCountedItemsList.java new file mode 100644 index 000000000..c020e360e --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/type/CombinedCountedItemsList.java @@ -0,0 +1,36 @@ +package com.simibubi.create.foundation.type; + +import java.util.HashMap; +import java.util.Map; + +public class CombinedCountedItemsList { + + protected Map lists = new HashMap<>(); + protected CountedItemsList combined = new CountedItemsList(); + boolean combinedListDirty = true; + + public void add(T key, CountedItemsList list) { + lists.put(key, list); + combinedListDirty = true; + } + + public void remove(T key) { + lists.remove(key); + combinedListDirty = true; + } + + public void clear() { + lists.clear(); + combinedListDirty = true; + } + + public CountedItemsList get() { + if (combinedListDirty) { + combined = new CountedItemsList(); + lists.values().forEach(list -> list.getFlattenedList().forEach(combined::add)); + combinedListDirty = false; + } + return combined; + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/type/CountedItemsList.java b/src/main/java/com/simibubi/create/foundation/type/CountedItemsList.java new file mode 100644 index 000000000..bb63a5e58 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/type/CountedItemsList.java @@ -0,0 +1,182 @@ +package com.simibubi.create.foundation.type; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.PriorityQueue; +import java.util.Set; + +import com.google.common.collect.Sets; + +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.CompoundNBT; +import net.minecraftforge.items.IItemHandler; +import net.minecraftforge.items.ItemHandlerHelper; + +public class CountedItemsList { + + Map> items = new HashMap<>(); + + Collection flattenedList = new PriorityQueue<>(); + boolean flattenedListDirty = true; + + public CountedItemsList() { + } + + public CountedItemsList(IItemHandler inventory) { + for (int slot = 0; slot < inventory.getSlots(); slot++) + add(inventory.extractItem(slot, inventory.getSlotLimit(slot), true)); + } + + public List getStacksToUpdate(CountedItemsList newList) { + List changes = new ArrayList<>(); + for (Item key : Sets.union(items.keySet(), newList.items.keySet())) { + Set currentSet = items.get(key); + Set newSet = newList.items.get(key); + + if (currentSet == null) { + changes.addAll(newSet); + continue; + } + if (newSet == null) { + currentSet.forEach(entry -> changes.add(new ItemStackEntry(entry.stack, 0))); + continue; + } + + Set remainderNew = new HashSet<>(newSet); + OuterLoop: for (ItemStackEntry entry : currentSet) { + for (ItemStackEntry newEntry : newSet) { + if (!entry.matches(newEntry.stack)) + continue; + remainderNew.remove(newEntry); + if (entry.amount != newEntry.amount) + changes.add(newEntry); + continue OuterLoop; + } + changes.add(new ItemStackEntry(entry.stack, 0)); + } + changes.addAll(remainderNew); + } + + return changes; + } + + public void add(ItemStack stack) { + add(stack, stack.getCount()); + } + + public void add(ItemStackEntry entry) { + add(entry.stack, entry.amount); + } + + public void add(ItemStack stack, int amount) { + if (stack.isEmpty()) + return; + + Set stackSet = getOrCreateItemSet(stack); + for (ItemStackEntry entry : stackSet) { + if (!entry.matches(stack)) + continue; + entry.amount += amount; + return; + } + stackSet.add(new ItemStackEntry(stack, amount)); + flattenedListDirty = true; + } + + public boolean contains(ItemStack stack) { + return getItemCount(stack) != 0; + } + + public int getItemCount(ItemStack stack) { + Set stackSet = getItemSet(stack); + if (stackSet == null) + return 0; + for (ItemStackEntry entry : stackSet) { + if (!entry.matches(stack)) + continue; + return entry.amount; + } + return 0; + } + + public void setItemCount(ItemStack stack, int amount) { + remove(stack); + add(stack, amount); + } + + public void remove(ItemStack stack) { + Set stackSet = getItemSet(stack); + if (stackSet == null) + return; + + for (Iterator iterator = stackSet.iterator(); iterator.hasNext();) { + ItemStackEntry entry = iterator.next(); + if (entry.matches(stack)) { + iterator.remove(); + flattenedListDirty = true; + return; + } + } + } + + public Collection getFlattenedList() { + if (flattenedListDirty) { + flattenedList.clear(); + items.values().forEach(set -> flattenedList.addAll(set)); + flattenedListDirty = false; + } + return flattenedList; + } + + private Set getItemSet(ItemStack stack) { + return items.get(stack.getItem()); + } + + private Set getOrCreateItemSet(ItemStack stack) { + if (!items.containsKey(stack.getItem())) + items.put(stack.getItem(), new HashSet<>()); + return getItemSet(stack); + } + + public class ItemStackEntry implements Comparable { + public ItemStack stack; + public int amount; + + public ItemStackEntry(ItemStack stack) { + this(stack, stack.getCount()); + } + + public ItemStackEntry(CompoundNBT nbt) { + this(ItemStack.read(nbt.getCompound("Item")), nbt.getInt("Amount")); + } + + public ItemStackEntry(ItemStack stack, int amount) { + this.stack = stack.copy(); + this.amount = amount; + } + + public boolean matches(ItemStack other) { + return ItemHandlerHelper.canItemStacksStack(other, stack); + } + + public CompoundNBT serializeNBT() { + CompoundNBT nbt = new CompoundNBT(); + nbt.put("Item", stack.serializeNBT()); + nbt.putInt("Amount", amount); + return nbt; + } + + @Override + public int compareTo(ItemStackEntry o) { + return amount - o.amount; + } + + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/utility/ColorHelper.java b/src/main/java/com/simibubi/create/foundation/utility/ColorHelper.java index 8b48f2738..d987cbf87 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/ColorHelper.java +++ b/src/main/java/com/simibubi/create/foundation/utility/ColorHelper.java @@ -1,5 +1,7 @@ package com.simibubi.create.foundation.utility; +import com.mojang.blaze3d.platform.GlStateManager; + public class ColorHelper { public static int rainbowColor(int timeStep) { @@ -39,4 +41,17 @@ public class ColorHelper { return color; } + public static void glColor(int color) { + color = mixColors(color, 0xFFFFFF, .5f); + int r = (color >> 16); + int g = (color >> 8) & 0xFF; + int b = color & 0xFF; + + GlStateManager.color4f(r / 256f, g / 256f, b / 256f, 1); + } + + public static void glResetColor() { + GlStateManager.color4f(1, 1, 1, 1); + } + } diff --git a/src/main/java/com/simibubi/create/foundation/utility/ItemHelper.java b/src/main/java/com/simibubi/create/foundation/utility/ItemHelper.java index 79557ac17..ae91f1ba7 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/ItemHelper.java +++ b/src/main/java/com/simibubi/create/foundation/utility/ItemHelper.java @@ -4,6 +4,8 @@ import java.util.ArrayList; import java.util.List; import net.minecraft.item.ItemStack; +import net.minecraftforge.items.IItemHandler; +import net.minecraftforge.items.ItemHandlerHelper; public class ItemHelper { @@ -11,13 +13,37 @@ public class ItemHelper { List stacks = new ArrayList<>(); ItemStack result = out.copy(); result.setCount(in.getCount() * out.getCount()); - + while (result.getCount() > result.getMaxStackSize()) { stacks.add(result.split(result.getMaxStackSize())); } - + stacks.add(result); return stacks; } + public static void addToList(ItemStack stack, List stacks) { + for (ItemStack s : stacks) { + if (!ItemHandlerHelper.canItemStacksStack(stack, s)) + continue; + int transferred = Math.min(s.getMaxStackSize() - s.getCount(), stack.getCount()); + s.grow(transferred); + stack.shrink(transferred); + } + if (stack.getCount() > 0) + stacks.add(stack); + } + + public static boolean isSameInventory(IItemHandler h1, IItemHandler h2) { + if (h1 == null || h2 == null) + return false; + if (h1.getSlots() != h2.getSlots()) + return false; + for (int slot = 0; slot < h1.getSlots(); slot++) { + if (h1.getStackInSlot(slot) != h2.getStackInSlot(slot)) + return false; + } + return true; + } + } diff --git a/src/main/java/com/simibubi/create/foundation/utility/TessellatorHelper.java b/src/main/java/com/simibubi/create/foundation/utility/TessellatorHelper.java index ecb0f521e..052442c47 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/TessellatorHelper.java +++ b/src/main/java/com/simibubi/create/foundation/utility/TessellatorHelper.java @@ -9,6 +9,7 @@ import net.minecraft.client.renderer.ActiveRenderInfo; import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.client.renderer.Tessellator; import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.client.renderer.vertex.VertexFormat; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; @@ -30,7 +31,11 @@ public class TessellatorHelper { } public static void begin() { - Tessellator.getInstance().getBuffer().begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX); + begin(DefaultVertexFormats.POSITION_TEX); + } + + public static void begin(VertexFormat format) { + Tessellator.getInstance().getBuffer().begin(GL11.GL_QUADS, format); } public static void draw() { diff --git a/src/main/java/com/simibubi/create/modules/contraptions/CachedBufferReloader.java b/src/main/java/com/simibubi/create/modules/contraptions/CachedBufferReloader.java index 713c83f90..6f1fb9c9a 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/CachedBufferReloader.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/CachedBufferReloader.java @@ -4,6 +4,7 @@ import com.simibubi.create.modules.contraptions.base.KineticTileEntityRenderer; import com.simibubi.create.modules.contraptions.receivers.constructs.MechanicalBearingTileEntityRenderer; import com.simibubi.create.modules.contraptions.receivers.constructs.MechanicalPistonTileEntityRenderer; import com.simibubi.create.modules.logistics.block.diodes.FlexpeaterTileEntityRenderer; +import com.simibubi.create.modules.logistics.management.base.LogisticalControllerTileEntityRenderer; import net.minecraft.client.resources.ReloadListener; import net.minecraft.profiler.IProfiler; @@ -22,6 +23,7 @@ public class CachedBufferReloader extends ReloadListener { MechanicalPistonTileEntityRenderer.invalidateCache(); MechanicalBearingTileEntityRenderer.invalidateCache(); FlexpeaterTileEntityRenderer.invalidateCache(); + LogisticalControllerTileEntityRenderer.invalidateCache(); } diff --git a/src/main/java/com/simibubi/create/modules/contraptions/receivers/DrillTileEntity.java b/src/main/java/com/simibubi/create/modules/contraptions/receivers/DrillTileEntity.java index 8aa1da827..597087a7b 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/receivers/DrillTileEntity.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/receivers/DrillTileEntity.java @@ -29,7 +29,7 @@ public class DrillTileEntity extends KineticTileEntity implements ITickableTileE private static final AtomicInteger NEXT_DRILL_ID = new AtomicInteger(); - private static DamageSource damageSourceDrill = new DamageSource("create.drill").setDamageBypassesArmor(); + public static DamageSource damageSourceDrill = new DamageSource("create.drill").setDamageBypassesArmor(); private int ticksUntilNextProgress; private int destroyProgress; private int drillId = -NEXT_DRILL_ID.incrementAndGet(); diff --git a/src/main/java/com/simibubi/create/modules/curiosities/partialWindows/WindowInABlockBlock.java b/src/main/java/com/simibubi/create/modules/curiosities/partialWindows/WindowInABlockBlock.java index 1b5b76059..08ea23e6b 100644 --- a/src/main/java/com/simibubi/create/modules/curiosities/partialWindows/WindowInABlockBlock.java +++ b/src/main/java/com/simibubi/create/modules/curiosities/partialWindows/WindowInABlockBlock.java @@ -171,7 +171,7 @@ public class WindowInABlockBlock extends PaneBlock public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) { WindowInABlockTileEntity tileEntity = getTileEntity(worldIn, pos); if (tileEntity == null) - return VoxelShapes.empty(); + return makeCuboidShape(7, 0, 7, 9, 16, 9); VoxelShape shape1 = tileEntity.getPartialBlock().getShape(worldIn, pos, context); VoxelShape shape2 = tileEntity.getWindowBlock().getShape(worldIn, pos, context); return VoxelShapes.or(shape1, shape2); diff --git a/src/main/java/com/simibubi/create/modules/curiosities/partialWindows/WindowInABlockTileEntity.java b/src/main/java/com/simibubi/create/modules/curiosities/partialWindows/WindowInABlockTileEntity.java index 0a5ca65bf..0f3e5ba0c 100644 --- a/src/main/java/com/simibubi/create/modules/curiosities/partialWindows/WindowInABlockTileEntity.java +++ b/src/main/java/com/simibubi/create/modules/curiosities/partialWindows/WindowInABlockTileEntity.java @@ -12,17 +12,27 @@ import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.NBTUtil; import net.minecraft.util.Direction; import net.minecraft.util.math.BlockPos; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.client.model.data.IModelData; import net.minecraftforge.client.model.data.ModelDataMap; +import net.minecraftforge.fml.DistExecutor; public class WindowInABlockTileEntity extends SyncedTileEntity { private BlockState partialBlock = Blocks.AIR.getDefaultState(); private BlockState windowBlock = Blocks.AIR.getDefaultState(); + + @OnlyIn(value = Dist.CLIENT) private IModelData modelData; public WindowInABlockTileEntity() { super(AllTileEntities.WINDOW_IN_A_BLOCK.type); + DistExecutor.runWhenOn(Dist.CLIENT, () -> this::initDataMap); + } + + @OnlyIn(value = Dist.CLIENT) + private void initDataMap() { modelData = new ModelDataMap.Builder().withInitial(WINDOW_BLOCK, Blocks.AIR.getDefaultState()) .withInitial(PARTIAL_BLOCK, Blocks.AIR.getDefaultState()) .withInitial(WindowInABlockModel.POSITION, BlockPos.ZERO).build(); @@ -57,6 +67,7 @@ public class WindowInABlockTileEntity extends SyncedTileEntity { markDirty(); } + @OnlyIn(value = Dist.CLIENT) @Override public IModelData getModelData() { modelData.setData(WindowInABlockModel.PARTIAL_BLOCK, partialBlock); diff --git a/src/main/java/com/simibubi/create/modules/logistics/block/IExtractor.java b/src/main/java/com/simibubi/create/modules/logistics/block/IExtractor.java index 074ebd75f..bcb69d095 100644 --- a/src/main/java/com/simibubi/create/modules/logistics/block/IExtractor.java +++ b/src/main/java/com/simibubi/create/modules/logistics/block/IExtractor.java @@ -1,11 +1,17 @@ package com.simibubi.create.modules.logistics.block; +import static net.minecraft.state.properties.BlockStateProperties.HORIZONTAL_FACING; + import com.simibubi.create.CreateConfig; import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.modules.logistics.entity.CardboardBoxEntity; +import com.simibubi.create.modules.logistics.item.CardboardBoxItem; +import net.minecraft.entity.Entity; import net.minecraft.entity.item.ItemEntity; import net.minecraft.item.ItemStack; import net.minecraft.tileentity.ITickableTileEntity; +import net.minecraft.util.Direction; import net.minecraft.util.SoundCategory; import net.minecraft.util.SoundEvents; import net.minecraft.util.math.AxisAlignedBB; @@ -168,10 +174,20 @@ public interface IExtractor extends ITickableTileEntity, IInventoryManipulator { if (!simulate && hasEnoughItems) { World world = getWorld(); Vec3d pos = VecHelper.getCenterOf(getPos()).add(0, -0.5f, 0); - ItemEntity entityIn = new ItemEntity(world, pos.x, pos.y, pos.z, extracting); - entityIn.setMotion(Vec3d.ZERO); + Entity entityIn = null; + + if (extracting.getItem() instanceof CardboardBoxItem) { + Direction face = getWorld().getBlockState(getPos()).get(HORIZONTAL_FACING).getOpposite(); + entityIn = new CardboardBoxEntity(world, pos, extracting, face); + world.playSound(null, getPos(), SoundEvents.ENTITY_ITEM_PICKUP, SoundCategory.BLOCKS, .25f, .05f); + + } else { + entityIn = new ItemEntity(world, pos.x, pos.y, pos.z, extracting); + entityIn.setMotion(Vec3d.ZERO); + world.playSound(null, getPos(), SoundEvents.ENTITY_ITEM_PICKUP, SoundCategory.BLOCKS, .125f, .1f); + } + world.addEntity(entityIn); - world.playSound(null, getPos(), SoundEvents.ENTITY_ITEM_PICKUP, SoundCategory.BLOCKS, .125f, .1f); } return extracting; diff --git a/src/main/java/com/simibubi/create/modules/logistics/block/BeltFunnelBlock.java b/src/main/java/com/simibubi/create/modules/logistics/block/belts/BeltFunnelBlock.java similarity index 87% rename from src/main/java/com/simibubi/create/modules/logistics/block/BeltFunnelBlock.java rename to src/main/java/com/simibubi/create/modules/logistics/block/belts/BeltFunnelBlock.java index b591fad53..c3b32e0f3 100644 --- a/src/main/java/com/simibubi/create/modules/logistics/block/BeltFunnelBlock.java +++ b/src/main/java/com/simibubi/create/modules/logistics/block/belts/BeltFunnelBlock.java @@ -1,4 +1,4 @@ -package com.simibubi.create.modules.logistics.block; +package com.simibubi.create.modules.logistics.block.belts; import java.util.Arrays; import java.util.List; @@ -11,6 +11,8 @@ import com.simibubi.create.modules.contraptions.relays.belt.AllBeltAttachments.B import com.simibubi.create.modules.contraptions.relays.belt.AllBeltAttachments.IBeltAttachment; import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock; import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Slope; +import com.simibubi.create.modules.logistics.block.IInventoryManipulator; +import com.simibubi.create.modules.logistics.entity.CardboardBoxEntity; import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntity; import net.minecraft.block.Block; @@ -35,10 +37,8 @@ import net.minecraft.world.World; public class BeltFunnelBlock extends HorizontalBlock implements IBeltAttachment, IWithTileEntity { - public static final VoxelShape - SHAPE_NORTH = makeCuboidShape(3, -4, -1, 13, 8, 5), - SHAPE_SOUTH = makeCuboidShape(3, -4, 11, 13, 8, 17), - SHAPE_WEST = makeCuboidShape(-1, -4, 3, 5, 8, 13), + public static final VoxelShape SHAPE_NORTH = makeCuboidShape(3, -4, -1, 13, 8, 5), + SHAPE_SOUTH = makeCuboidShape(3, -4, 11, 13, 8, 17), SHAPE_WEST = makeCuboidShape(-1, -4, 3, 5, 8, 13), SHAPE_EAST = makeCuboidShape(11, -4, 3, 17, 8, 13); public BeltFunnelBlock() { @@ -135,15 +135,16 @@ public class BeltFunnelBlock extends HorizontalBlock implements IBeltAttachment, @Override public boolean handleEntity(BeltTileEntity te, Entity entity, BeltAttachmentState state) { - if (!(entity instanceof ItemEntity)) + boolean isItem = entity instanceof ItemEntity; + if (!isItem && !(entity instanceof CardboardBoxEntity)) return false; boolean slope = te.getBlockState().get(BeltBlock.SLOPE) != Slope.HORIZONTAL; - if (entity.getPositionVec().distanceTo(VecHelper.getCenterOf(te.getPos())) > (slope ? .6f : .4f)) + if (isItem && entity.getPositionVec().distanceTo(VecHelper.getCenterOf(te.getPos())) > (slope ? .6f : .4f)) return false; entity.setMotion(Vec3d.ZERO); withTileEntityDo(te.getWorld(), state.attachmentPos, funnelTE -> { - funnelTE.tryToInsert((ItemEntity) entity); + funnelTE.tryToInsert(entity); }); return true; diff --git a/src/main/java/com/simibubi/create/modules/logistics/block/BeltFunnelTileEntity.java b/src/main/java/com/simibubi/create/modules/logistics/block/belts/BeltFunnelTileEntity.java similarity index 77% rename from src/main/java/com/simibubi/create/modules/logistics/block/BeltFunnelTileEntity.java rename to src/main/java/com/simibubi/create/modules/logistics/block/belts/BeltFunnelTileEntity.java index d568c2ef2..9e1e2f16c 100644 --- a/src/main/java/com/simibubi/create/modules/logistics/block/BeltFunnelTileEntity.java +++ b/src/main/java/com/simibubi/create/modules/logistics/block/belts/BeltFunnelTileEntity.java @@ -1,8 +1,11 @@ -package com.simibubi.create.modules.logistics.block; +package com.simibubi.create.modules.logistics.block.belts; import com.simibubi.create.AllTileEntities; import com.simibubi.create.foundation.block.SyncedTileEntity; +import com.simibubi.create.modules.logistics.block.IInventoryManipulator; +import com.simibubi.create.modules.logistics.entity.CardboardBoxEntity; +import net.minecraft.entity.Entity; import net.minecraft.entity.item.ItemEntity; import net.minecraft.item.ItemStack; import net.minecraft.nbt.CompoundNBT; @@ -33,12 +36,12 @@ public class BeltFunnelTileEntity extends SyncedTileEntity implements ITickableT waitingForInventorySpace = compound.getBoolean("Waiting"); super.read(compound); } - + @Override public void onLoad() { initialize = true; } - + @Override public void readClientUpdate(CompoundNBT tag) { super.readClientUpdate(tag); @@ -61,7 +64,7 @@ public class BeltFunnelTileEntity extends SyncedTileEntity implements ITickableT public LazyOptional getInventory() { return inventory; } - + @Override public void tick() { if (initialize && hasWorld()) { @@ -69,7 +72,7 @@ public class BeltFunnelTileEntity extends SyncedTileEntity implements ITickableT initialize = false; } } - + @Override public void setInventory(LazyOptional inventory) { this.inventory = inventory; @@ -83,13 +86,18 @@ public class BeltFunnelTileEntity extends SyncedTileEntity implements ITickableT sendData(); } - public void tryToInsert(ItemEntity entity) { + public void tryToInsert(Entity entity) { if (!inventory.isPresent()) return; if (waitingForInventorySpace) return; - ItemStack stack = entity.getItem().copy(); + ItemStack stack = null; + if (entity instanceof ItemEntity) + stack = ((ItemEntity) entity).getItem().copy(); + if (entity instanceof CardboardBoxEntity) + stack = ((CardboardBoxEntity) entity).getBox().copy(); + IItemHandler inv = inventory.orElse(null); for (int slot = 0; slot < inv.getSlots(); slot++) { stack = inv.insertItem(slot, stack, world.isRemote); @@ -97,12 +105,12 @@ public class BeltFunnelTileEntity extends SyncedTileEntity implements ITickableT if (!world.isRemote) { entity.remove(); world.playSound(null, pos, SoundEvents.ENTITY_GENERIC_EAT, SoundCategory.BLOCKS, .125f, 1f); - } - else { + } else { Vec3i directionVec = getBlockState().get(BlockStateProperties.HORIZONTAL_FACING).getDirectionVec(); - float xSpeed = directionVec.getX() * 1/8f; - float zSpeed = directionVec.getZ() * 1/8f; - world.addParticle(new ItemParticleData(ParticleTypes.ITEM, entity.getItem()), entity.posX, entity.posY, entity.posZ, xSpeed, 1/6f, zSpeed); + float xSpeed = directionVec.getX() * 1 / 8f; + float zSpeed = directionVec.getZ() * 1 / 8f; + world.addParticle(new ItemParticleData(ParticleTypes.ITEM, stack), entity.posX, + entity.posY, entity.posZ, xSpeed, 1 / 6f, zSpeed); } return; } @@ -111,8 +119,9 @@ public class BeltFunnelTileEntity extends SyncedTileEntity implements ITickableT waitingForInventorySpace = true; sendData(); - if (!stack.equals(entity.getItem(), false)) - entity.setItem(stack); + if (entity instanceof ItemEntity) + if (!stack.equals(((ItemEntity) entity).getItem(), false)) + ((ItemEntity) entity).setItem(stack); } diff --git a/src/main/java/com/simibubi/create/modules/logistics/block/EntityDetectorBlock.java b/src/main/java/com/simibubi/create/modules/logistics/block/belts/EntityDetectorBlock.java similarity index 98% rename from src/main/java/com/simibubi/create/modules/logistics/block/EntityDetectorBlock.java rename to src/main/java/com/simibubi/create/modules/logistics/block/belts/EntityDetectorBlock.java index d6b9e8d7f..48225c77b 100644 --- a/src/main/java/com/simibubi/create/modules/logistics/block/EntityDetectorBlock.java +++ b/src/main/java/com/simibubi/create/modules/logistics/block/belts/EntityDetectorBlock.java @@ -1,4 +1,4 @@ -package com.simibubi.create.modules.logistics.block; +package com.simibubi.create.modules.logistics.block.belts; import java.util.ArrayList; import java.util.Arrays; @@ -14,6 +14,7 @@ import com.simibubi.create.modules.contraptions.relays.belt.AllBeltAttachments.I import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock; import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Part; import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Slope; +import com.simibubi.create.modules.logistics.block.IBlockWithFilter; import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntity; import net.minecraft.block.Block; diff --git a/src/main/java/com/simibubi/create/modules/logistics/block/EntityDetectorTileEntity.java b/src/main/java/com/simibubi/create/modules/logistics/block/belts/EntityDetectorTileEntity.java similarity index 87% rename from src/main/java/com/simibubi/create/modules/logistics/block/EntityDetectorTileEntity.java rename to src/main/java/com/simibubi/create/modules/logistics/block/belts/EntityDetectorTileEntity.java index 5866141b6..518dbc9e7 100644 --- a/src/main/java/com/simibubi/create/modules/logistics/block/EntityDetectorTileEntity.java +++ b/src/main/java/com/simibubi/create/modules/logistics/block/belts/EntityDetectorTileEntity.java @@ -1,7 +1,8 @@ -package com.simibubi.create.modules.logistics.block; +package com.simibubi.create.modules.logistics.block.belts; import com.simibubi.create.AllTileEntities; import com.simibubi.create.foundation.block.SyncedTileEntity; +import com.simibubi.create.modules.logistics.block.IHaveFilter; import net.minecraft.item.ItemStack; import net.minecraft.nbt.CompoundNBT; diff --git a/src/main/java/com/simibubi/create/modules/logistics/block/EntityDetectorTileEntityRenderer.java b/src/main/java/com/simibubi/create/modules/logistics/block/belts/EntityDetectorTileEntityRenderer.java similarity index 87% rename from src/main/java/com/simibubi/create/modules/logistics/block/EntityDetectorTileEntityRenderer.java rename to src/main/java/com/simibubi/create/modules/logistics/block/belts/EntityDetectorTileEntityRenderer.java index c824f1f10..008a8f023 100644 --- a/src/main/java/com/simibubi/create/modules/logistics/block/EntityDetectorTileEntityRenderer.java +++ b/src/main/java/com/simibubi/create/modules/logistics/block/belts/EntityDetectorTileEntityRenderer.java @@ -1,6 +1,7 @@ -package com.simibubi.create.modules.logistics.block; +package com.simibubi.create.modules.logistics.block.belts; import com.mojang.blaze3d.platform.GLX; +import com.simibubi.create.modules.logistics.block.FilteredTileEntityRenderer; import net.minecraft.client.renderer.tileentity.TileEntityRenderer; import net.minecraft.state.properties.BlockStateProperties; diff --git a/src/main/java/com/simibubi/create/modules/logistics/block/ExtractorBlock.java b/src/main/java/com/simibubi/create/modules/logistics/block/belts/ExtractorBlock.java similarity index 96% rename from src/main/java/com/simibubi/create/modules/logistics/block/ExtractorBlock.java rename to src/main/java/com/simibubi/create/modules/logistics/block/belts/ExtractorBlock.java index 18635e0b7..2644ea845 100644 --- a/src/main/java/com/simibubi/create/modules/logistics/block/ExtractorBlock.java +++ b/src/main/java/com/simibubi/create/modules/logistics/block/belts/ExtractorBlock.java @@ -1,9 +1,11 @@ -package com.simibubi.create.modules.logistics.block; +package com.simibubi.create.modules.logistics.block.belts; import java.util.ArrayList; import java.util.List; import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.modules.logistics.block.IBlockWithFilter; +import com.simibubi.create.modules.logistics.block.IExtractor; import net.minecraft.block.Block; import net.minecraft.block.BlockState; diff --git a/src/main/java/com/simibubi/create/modules/logistics/block/ExtractorTileEntity.java b/src/main/java/com/simibubi/create/modules/logistics/block/belts/ExtractorTileEntity.java similarity index 93% rename from src/main/java/com/simibubi/create/modules/logistics/block/ExtractorTileEntity.java rename to src/main/java/com/simibubi/create/modules/logistics/block/belts/ExtractorTileEntity.java index 4d59e6d4a..d6a3e8855 100644 --- a/src/main/java/com/simibubi/create/modules/logistics/block/ExtractorTileEntity.java +++ b/src/main/java/com/simibubi/create/modules/logistics/block/belts/ExtractorTileEntity.java @@ -1,8 +1,10 @@ -package com.simibubi.create.modules.logistics.block; +package com.simibubi.create.modules.logistics.block.belts; import com.simibubi.create.AllTileEntities; import com.simibubi.create.CreateConfig; import com.simibubi.create.foundation.block.SyncedTileEntity; +import com.simibubi.create.modules.logistics.block.IExtractor; +import com.simibubi.create.modules.logistics.block.IHaveFilter; import net.minecraft.item.ItemStack; import net.minecraft.nbt.CompoundNBT; diff --git a/src/main/java/com/simibubi/create/modules/logistics/block/ExtractorTileEntityRenderer.java b/src/main/java/com/simibubi/create/modules/logistics/block/belts/ExtractorTileEntityRenderer.java similarity index 81% rename from src/main/java/com/simibubi/create/modules/logistics/block/ExtractorTileEntityRenderer.java rename to src/main/java/com/simibubi/create/modules/logistics/block/belts/ExtractorTileEntityRenderer.java index 3146efe77..45df232bf 100644 --- a/src/main/java/com/simibubi/create/modules/logistics/block/ExtractorTileEntityRenderer.java +++ b/src/main/java/com/simibubi/create/modules/logistics/block/belts/ExtractorTileEntityRenderer.java @@ -1,4 +1,6 @@ -package com.simibubi.create.modules.logistics.block; +package com.simibubi.create.modules.logistics.block.belts; + +import com.simibubi.create.modules.logistics.block.FilteredTileEntityRenderer; import net.minecraft.client.renderer.tileentity.TileEntityRenderer; diff --git a/src/main/java/com/simibubi/create/modules/logistics/block/LinkedExtractorBlock.java b/src/main/java/com/simibubi/create/modules/logistics/block/belts/LinkedExtractorBlock.java similarity index 95% rename from src/main/java/com/simibubi/create/modules/logistics/block/LinkedExtractorBlock.java rename to src/main/java/com/simibubi/create/modules/logistics/block/belts/LinkedExtractorBlock.java index 6774d518d..5316d6e69 100644 --- a/src/main/java/com/simibubi/create/modules/logistics/block/LinkedExtractorBlock.java +++ b/src/main/java/com/simibubi/create/modules/logistics/block/belts/LinkedExtractorBlock.java @@ -1,4 +1,4 @@ -package com.simibubi.create.modules.logistics.block; +package com.simibubi.create.modules.logistics.block.belts; import java.util.ArrayList; import java.util.List; @@ -6,6 +6,7 @@ import java.util.List; import org.apache.commons.lang3.tuple.Pair; import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.modules.logistics.block.IBlockWithFrequency; import net.minecraft.block.Block; import net.minecraft.block.BlockState; diff --git a/src/main/java/com/simibubi/create/modules/logistics/block/LinkedExtractorTileEntity.java b/src/main/java/com/simibubi/create/modules/logistics/block/belts/LinkedExtractorTileEntity.java similarity index 92% rename from src/main/java/com/simibubi/create/modules/logistics/block/LinkedExtractorTileEntity.java rename to src/main/java/com/simibubi/create/modules/logistics/block/belts/LinkedExtractorTileEntity.java index d2badee55..1d8b5b88c 100644 --- a/src/main/java/com/simibubi/create/modules/logistics/block/LinkedExtractorTileEntity.java +++ b/src/main/java/com/simibubi/create/modules/logistics/block/belts/LinkedExtractorTileEntity.java @@ -1,10 +1,13 @@ -package com.simibubi.create.modules.logistics.block; +package com.simibubi.create.modules.logistics.block.belts; import static net.minecraft.state.properties.BlockStateProperties.POWERED; import com.simibubi.create.AllTileEntities; import com.simibubi.create.CreateConfig; import com.simibubi.create.modules.logistics.IReceiveWireless; +import com.simibubi.create.modules.logistics.block.IExtractor; +import com.simibubi.create.modules.logistics.block.IHaveFilter; +import com.simibubi.create.modules.logistics.block.LinkedTileEntity; import net.minecraft.item.ItemStack; import net.minecraft.nbt.CompoundNBT; diff --git a/src/main/java/com/simibubi/create/modules/logistics/block/LinkedExtractorTileEntityRenderer.java b/src/main/java/com/simibubi/create/modules/logistics/block/belts/LinkedExtractorTileEntityRenderer.java similarity index 78% rename from src/main/java/com/simibubi/create/modules/logistics/block/LinkedExtractorTileEntityRenderer.java rename to src/main/java/com/simibubi/create/modules/logistics/block/belts/LinkedExtractorTileEntityRenderer.java index e066e8579..328ea47cd 100644 --- a/src/main/java/com/simibubi/create/modules/logistics/block/LinkedExtractorTileEntityRenderer.java +++ b/src/main/java/com/simibubi/create/modules/logistics/block/belts/LinkedExtractorTileEntityRenderer.java @@ -1,4 +1,7 @@ -package com.simibubi.create.modules.logistics.block; +package com.simibubi.create.modules.logistics.block.belts; + +import com.simibubi.create.modules.logistics.block.FilteredTileEntityRenderer; +import com.simibubi.create.modules.logistics.block.LinkedTileEntityRenderer; import net.minecraft.client.renderer.tileentity.TileEntityRenderer; diff --git a/src/main/java/com/simibubi/create/modules/logistics/block/FlexcrateBlock.java b/src/main/java/com/simibubi/create/modules/logistics/block/inventories/FlexcrateBlock.java similarity index 97% rename from src/main/java/com/simibubi/create/modules/logistics/block/FlexcrateBlock.java rename to src/main/java/com/simibubi/create/modules/logistics/block/inventories/FlexcrateBlock.java index d2053d06f..e264502d7 100644 --- a/src/main/java/com/simibubi/create/modules/logistics/block/FlexcrateBlock.java +++ b/src/main/java/com/simibubi/create/modules/logistics/block/inventories/FlexcrateBlock.java @@ -1,4 +1,4 @@ -package com.simibubi.create.modules.logistics.block; +package com.simibubi.create.modules.logistics.block.inventories; import net.minecraft.block.Block; import net.minecraft.block.BlockState; diff --git a/src/main/java/com/simibubi/create/modules/logistics/block/FlexcrateContainer.java b/src/main/java/com/simibubi/create/modules/logistics/block/inventories/FlexcrateContainer.java similarity index 97% rename from src/main/java/com/simibubi/create/modules/logistics/block/FlexcrateContainer.java rename to src/main/java/com/simibubi/create/modules/logistics/block/inventories/FlexcrateContainer.java index 0f1d05eef..55fd0d0eb 100644 --- a/src/main/java/com/simibubi/create/modules/logistics/block/FlexcrateContainer.java +++ b/src/main/java/com/simibubi/create/modules/logistics/block/inventories/FlexcrateContainer.java @@ -1,4 +1,4 @@ -package com.simibubi.create.modules.logistics.block; +package com.simibubi.create.modules.logistics.block.inventories; import com.simibubi.create.AllContainers; diff --git a/src/main/java/com/simibubi/create/modules/logistics/block/FlexcrateScreen.java b/src/main/java/com/simibubi/create/modules/logistics/block/inventories/FlexcrateScreen.java similarity index 98% rename from src/main/java/com/simibubi/create/modules/logistics/block/FlexcrateScreen.java rename to src/main/java/com/simibubi/create/modules/logistics/block/inventories/FlexcrateScreen.java index d148a057b..602b04fc7 100644 --- a/src/main/java/com/simibubi/create/modules/logistics/block/FlexcrateScreen.java +++ b/src/main/java/com/simibubi/create/modules/logistics/block/inventories/FlexcrateScreen.java @@ -1,4 +1,4 @@ -package com.simibubi.create.modules.logistics.block; +package com.simibubi.create.modules.logistics.block.inventories; import static com.simibubi.create.ScreenResources.FLEXCRATE; import static com.simibubi.create.ScreenResources.PLAYER_INVENTORY; diff --git a/src/main/java/com/simibubi/create/modules/logistics/block/FlexcrateTileEntity.java b/src/main/java/com/simibubi/create/modules/logistics/block/inventories/FlexcrateTileEntity.java similarity index 98% rename from src/main/java/com/simibubi/create/modules/logistics/block/FlexcrateTileEntity.java rename to src/main/java/com/simibubi/create/modules/logistics/block/inventories/FlexcrateTileEntity.java index 320223d0c..3deb8380b 100644 --- a/src/main/java/com/simibubi/create/modules/logistics/block/FlexcrateTileEntity.java +++ b/src/main/java/com/simibubi/create/modules/logistics/block/inventories/FlexcrateTileEntity.java @@ -1,4 +1,4 @@ -package com.simibubi.create.modules.logistics.block; +package com.simibubi.create.modules.logistics.block.inventories; import com.simibubi.create.AllTileEntities; import com.simibubi.create.foundation.block.SyncedTileEntity; diff --git a/src/main/java/com/simibubi/create/modules/logistics/entity/CardboardBoxEntity.java b/src/main/java/com/simibubi/create/modules/logistics/entity/CardboardBoxEntity.java new file mode 100644 index 000000000..10534d495 --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/logistics/entity/CardboardBoxEntity.java @@ -0,0 +1,291 @@ +package com.simibubi.create.modules.logistics.entity; + +import java.util.Collections; + +import javax.annotation.Nullable; + +import com.simibubi.create.AllEntities; +import com.simibubi.create.AllItems; +import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.modules.contraptions.receivers.DrillTileEntity; +import com.simibubi.create.modules.logistics.item.CardboardBoxItem; + +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntitySize; +import net.minecraft.entity.EntityType; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.Pose; +import net.minecraft.entity.SharedMonsterAttributes; +import net.minecraft.entity.item.ItemEntity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.entity.projectile.AbstractArrowEntity; +import net.minecraft.inventory.EquipmentSlotType; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.CompoundNBT; +import net.minecraft.network.IPacket; +import net.minecraft.network.PacketBuffer; +import net.minecraft.particles.ItemParticleData; +import net.minecraft.particles.ParticleTypes; +import net.minecraft.util.DamageSource; +import net.minecraft.util.Direction; +import net.minecraft.util.HandSide; +import net.minecraft.util.SoundEvent; +import net.minecraft.util.SoundEvents; +import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; +import net.minecraftforge.fml.common.registry.IEntityAdditionalSpawnData; +import net.minecraftforge.fml.network.FMLPlayMessages.SpawnEntity; +import net.minecraftforge.fml.network.NetworkHooks; + +public class CardboardBoxEntity extends LivingEntity implements IEntityAdditionalSpawnData { + + public ItemStack box; + + public int extractorAnimationProgress; + public Direction extractorSide; + + @SuppressWarnings("unchecked") + public CardboardBoxEntity(EntityType entityTypeIn, World worldIn) { + super((EntityType) entityTypeIn, worldIn); + } + + protected CardboardBoxEntity(World worldIn, double x, double y, double z) { + this(AllEntities.CARDBOARD_BOX.type, worldIn); + this.setPosition(x, y, z); + this.recalculateSize(); + this.rotationYaw = this.rand.nextFloat() * 360.0F; + } + + public CardboardBoxEntity(World worldIn, Vec3d pos, ItemStack stack, Direction extractionDirection) { + this(worldIn, pos.x, pos.y, pos.z); + this.setBox(stack); + this.extractedFrom(extractionDirection); + } + + public static EntityType.Builder build(EntityType.Builder builder) { + @SuppressWarnings("unchecked") + EntityType.Builder boxBuilder = (EntityType.Builder) builder; + return boxBuilder.setCustomClientFactory(CardboardBoxEntity::spawn).size(1, 1); + } + + protected void registerAttributes() { + super.registerAttributes(); + this.getAttribute(SharedMonsterAttributes.MAX_HEALTH).setBaseValue(5.0D); + } + + private void extractedFrom(Direction side) { + extractorSide = side; + extractorAnimationProgress = 20; + } + + @Override + public void tick() { + if (extractorAnimationProgress > -1) { + extractorAnimationProgress--; + return; + } + super.tick(); + } + + @Override + public EntitySize getSize(Pose poseIn) { + if (box == null) + return super.getSize(poseIn); + if (AllItems.CARDBOARD_BOX_1410.typeOf(box)) + return new EntitySize(14 / 16f, 10 / 16f, true); + if (AllItems.CARDBOARD_BOX_1416.typeOf(box)) + return new EntitySize(14 / 16f, 1f, true); + if (AllItems.CARDBOARD_BOX_1612.typeOf(box)) + return new EntitySize(1f, 12 / 16f, true); + if (AllItems.CARDBOARD_BOX_1616.typeOf(box)) + return new EntitySize(1f, 1f, true); + + return super.getSize(poseIn); + } + + public static CardboardBoxEntity spawn(SpawnEntity spawnEntity, World world) { + return new CardboardBoxEntity(world, 0, 0, 0); + } + + public ItemStack getBox() { + return box; + } + + public void setBox(ItemStack box) { + this.box = box.copy(); + recalculateSize(); + } + + public AxisAlignedBB getCollisionBoundingBox() { + return this.getBoundingBox(); + } + + public boolean attackEntityFrom(DamageSource source, float amount) { + if (world.isRemote || !this.isAlive()) + return false; + + if (DamageSource.OUT_OF_WORLD.equals(source)) { + this.remove(); + return false; + } + + if (DamageSource.FALL.equals(source)) + return false; + + if (this.isInvulnerableTo(source)) + return false; + + if (source.isExplosion()) { + this.destroy(source); + this.remove(); + return false; + } + + if (DamageSource.IN_FIRE.equals(source)) { + if (this.isBurning()) { + this.takeDamage(source, 0.15F); + } else { + this.setFire(5); + } + return false; + } + + if (DamageSource.ON_FIRE.equals(source) && this.getHealth() > 0.5F) { + this.takeDamage(source, 4.0F); + return false; + } + + boolean wasShot = source.getImmediateSource() instanceof AbstractArrowEntity; + boolean shotCanPierce = wasShot && ((AbstractArrowEntity) source.getImmediateSource()).getPierceLevel() > 0; + + if (source.getTrueSource() instanceof PlayerEntity + && !((PlayerEntity) source.getTrueSource()).abilities.allowEdit) + return false; + + this.destroy(source); + this.remove(); + return shotCanPierce; + } + + private void takeDamage(DamageSource source, float amount) { + float hp = this.getHealth(); + hp = hp - amount; + if (hp <= 0.5F) { + this.destroy(source); + this.remove(); + } else { + this.setHealth(hp); + } + } + + private void destroy(DamageSource source) { + this.world.playSound((PlayerEntity) null, this.posX, this.posY, this.posZ, SoundEvents.ENTITY_ARMOR_STAND_BREAK, + this.getSoundCategory(), 1.0F, 1.0F); + this.spawnDrops(source); + } + + @Override + protected void spawnDrops(DamageSource source) { + super.spawnDrops(source); + for (ItemStack stack : CardboardBoxItem.getContents(box)) { + ItemEntity entityIn = new ItemEntity(world, posX, posY, posZ, stack); + world.addEntity(entityIn); + if (DrillTileEntity.damageSourceDrill.equals(source)) + entityIn.setMotion(Vec3d.ZERO); + } + } + + @Override + public void remove(boolean keepData) { + if (world.isRemote) { + for (int i = 0; i < 20; i++) { + Vec3d pos = VecHelper.offsetRandomly(this.getPositionVector(), world.rand, .5f); + Vec3d motion = Vec3d.ZERO; + world.addParticle(new ItemParticleData(ParticleTypes.ITEM, box), pos.x, pos.y, pos.z, motion.x, + motion.y, motion.z); + } + } + super.remove(keepData); + } + + @Override + protected void registerData() { + super.registerData(); + } + + @Override + public void readAdditional(CompoundNBT compound) { + super.readAdditional(compound); + box = ItemStack.read(compound.getCompound("Box")); + if (compound.contains("Direction")) + extractedFrom(Direction.byIndex(compound.getInt("Direction"))); + } + + @Override + public void writeAdditional(CompoundNBT compound) { + super.writeAdditional(compound); + compound.put("Box", box.serializeNBT()); + if (extractorSide != null) + compound.putInt("Direction", extractorSide.getIndex()); + } + + @Override + public IPacket createSpawnPacket() { + return NetworkHooks.getEntitySpawningPacket(this); + } + + @Override + public Iterable getArmorInventoryList() { + return Collections.emptyList(); + } + + @Override + public ItemStack getItemStackFromSlot(EquipmentSlotType slotIn) { + if (slotIn == EquipmentSlotType.MAINHAND) + return getBox(); + return ItemStack.EMPTY; + } + + @Override + public void setItemStackToSlot(EquipmentSlotType slotIn, ItemStack stack) { + if (slotIn == EquipmentSlotType.MAINHAND) + setBox(stack); + } + + @Override + public HandSide getPrimaryHand() { + return HandSide.LEFT; + } + + @Override + public void writeSpawnData(PacketBuffer buffer) { + buffer.writeItemStack(getBox()); + boolean sidePresent = extractorSide != null; + buffer.writeBoolean(sidePresent); + if (sidePresent) + buffer.writeInt(extractorSide.getIndex()); + } + + @Override + public void readSpawnData(PacketBuffer additionalData) { + setBox(additionalData.readItemStack()); + if (additionalData.readBoolean()) + extractedFrom(Direction.byIndex(additionalData.readInt())); + } + + protected SoundEvent getFallSound(int heightIn) { + return SoundEvents.ENTITY_ARMOR_STAND_FALL; + } + + @Nullable + protected SoundEvent getHurtSound(DamageSource damageSourceIn) { + return SoundEvents.ENTITY_ARMOR_STAND_HIT; + } + + @Nullable + protected SoundEvent getDeathSound() { + return SoundEvents.ENTITY_ARMOR_STAND_BREAK; + } + +} diff --git a/src/main/java/com/simibubi/create/modules/logistics/entity/CardboardBoxEntityRenderer.java b/src/main/java/com/simibubi/create/modules/logistics/entity/CardboardBoxEntityRenderer.java new file mode 100644 index 000000000..395e352d5 --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/logistics/entity/CardboardBoxEntityRenderer.java @@ -0,0 +1,76 @@ +package com.simibubi.create.modules.logistics.entity; + +import com.mojang.blaze3d.platform.GlStateManager; + +import net.minecraft.block.Blocks; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.culling.ICamera; +import net.minecraft.client.renderer.entity.EntityRenderer; +import net.minecraft.client.renderer.entity.EntityRendererManager; +import net.minecraft.client.renderer.model.IBakedModel; +import net.minecraft.client.renderer.texture.AtlasTexture; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.math.MathHelper; + +public class CardboardBoxEntityRenderer extends EntityRenderer { + + public CardboardBoxEntityRenderer(EntityRendererManager renderManager) { + super(renderManager); + } + + @Override + protected ResourceLocation getEntityTexture(CardboardBoxEntity entity) { + return null; + } + + @Override + public boolean shouldRender(CardboardBoxEntity livingEntity, ICamera camera, double camX, double camY, + double camZ) { + return super.shouldRender(livingEntity, camera, camX, camY, camZ); + } + + @Override + public void renderMultipass(CardboardBoxEntity entityIn, double x, double y, double z, float entityYaw, + float partialTicks) { + super.renderMultipass(entityIn, x, y, z, entityYaw, partialTicks); + } + + @Override + public void doRender(CardboardBoxEntity entity, double x, double y, double z, float entityYaw, float partialTicks) { + IBakedModel model = getModelForBox(entity); + if (model == null) + return; + + bindTexture(AtlasTexture.LOCATION_BLOCKS_TEXTURE); + GlStateManager.pushMatrix(); + GlStateManager.translated(x, y, z); + + if (entity.extractorSide != null && entity.extractorAnimationProgress > 0) { + float time = entity.extractorAnimationProgress - partialTicks; + float scale = 1; + if (time > 5) { + scale = MathHelper.lerp(((time - 10) / 10), .3f, .25f); + } else { + float step = time / 5; + scale = MathHelper.lerp(step * step * step, 1, .3f); + } + GlStateManager.scaled(scale, scale, scale); + } + + GlStateManager.rotated(entity.rotationYaw, 0, 1, 0); + GlStateManager.translated(-.5, 0, .5); + + Minecraft.getInstance().getBlockRendererDispatcher().getBlockModelRenderer().renderModelBrightness(model, + Blocks.AIR.getDefaultState(), 1, false); + GlStateManager.popMatrix(); + + super.doRender(entity, x, y, z, entityYaw, partialTicks); + } + + public IBakedModel getModelForBox(CardboardBoxEntity entity) { + if (entity.getBox() == null || entity.getBox().isEmpty()) + return null; + return Minecraft.getInstance().getItemRenderer().getModelWithOverrides(entity.getBox()); + } + +} diff --git a/src/main/java/com/simibubi/create/modules/logistics/item/CardboardBoxItem.java b/src/main/java/com/simibubi/create/modules/logistics/item/CardboardBoxItem.java new file mode 100644 index 000000000..4f0c78616 --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/logistics/item/CardboardBoxItem.java @@ -0,0 +1,128 @@ +package com.simibubi.create.modules.logistics.item; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +import net.minecraft.client.util.ITooltipFlag; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.inventory.ItemStackHelper; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.CompoundNBT; +import net.minecraft.util.ActionResult; +import net.minecraft.util.ActionResultType; +import net.minecraft.util.Hand; +import net.minecraft.util.NonNullList; +import net.minecraft.util.text.ITextComponent; +import net.minecraft.util.text.StringTextComponent; +import net.minecraft.util.text.TextFormatting; +import net.minecraft.util.text.TranslationTextComponent; +import net.minecraft.world.World; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.common.util.Constants; + +public class CardboardBoxItem extends Item { + + static final int SLOTS = 9; + static final List ALL_BOXES = new ArrayList<>(); + + public CardboardBoxItem(Properties properties) { + super(properties); + ALL_BOXES.add(this); + } + + @Override + public ActionResult onItemRightClick(World worldIn, PlayerEntity playerIn, Hand handIn) { + if (!playerIn.isSneaking()) + return super.onItemRightClick(worldIn, playerIn, handIn); + + ItemStack box = playerIn.getHeldItem(handIn); + for (ItemStack stack : getContents(box)) + playerIn.inventory.placeItemBackInInventory(worldIn, stack); + + if (!playerIn.isCreative()) { + box.shrink(1); + } + return new ActionResult<>(ActionResultType.SUCCESS, box); + } + + public static ItemStack containing(List stacks) { + ItemStack box = new ItemStack(randomBox()); + CompoundNBT compound = new CompoundNBT(); + + NonNullList list = NonNullList.create(); + list.addAll(stacks); + ItemStackHelper.saveAllItems(compound, list); + + box.setTag(compound); + return box; + } + + public static void addAddress(ItemStack box, String address) { + box.getOrCreateTag().putString("Address", address); + } + + public static boolean matchAddress(ItemStack box, String other) { + String address = box.getTag().getString("Address"); + if (address == null || address.isEmpty()) + return false; + if (address.equals("*")) + return true; + if (address.equals(other)) + return true; + if (address.endsWith("*") && other.startsWith(address.substring(0, address.length() - 1))) + return true; + + return false; + } + + public static List getContents(ItemStack box) { + NonNullList list = NonNullList.withSize(SLOTS, ItemStack.EMPTY); + ItemStackHelper.loadAllItems(box.getOrCreateTag(), list); + return list; + } + + public static CardboardBoxItem randomBox() { + return ALL_BOXES.get(new Random().nextInt(ALL_BOXES.size())); + } + + @Override + @OnlyIn(value = Dist.CLIENT) + public void addInformation(ItemStack stack, World worldIn, List tooltip, ITooltipFlag flagIn) { + super.addInformation(stack, worldIn, tooltip, flagIn); + CompoundNBT compoundnbt = stack.getOrCreateTag(); + + if (compoundnbt.contains("Address", Constants.NBT.TAG_STRING)) { + tooltip.add(new StringTextComponent("-> " + compoundnbt.getString("Address")) + .applyTextStyle(TextFormatting.GOLD)); + } + + if (!compoundnbt.contains("Items", Constants.NBT.TAG_LIST)) + return; + + int i = 0; + int j = 0; + + for (ItemStack itemstack : getContents(stack)) { + if (itemstack.isEmpty()) + continue; + + ++j; + if (i <= 4) { + ++i; + ITextComponent itextcomponent = itemstack.getDisplayName().deepCopy(); + itextcomponent.appendText(" x").appendText(String.valueOf(itemstack.getCount())) + .applyTextStyle(TextFormatting.GRAY); + tooltip.add(itextcomponent); + } + } + + if (j - i > 0) { + tooltip.add((new TranslationTextComponent("container.shulkerBox.more", j - i)) + .applyTextStyle(TextFormatting.ITALIC)); + } + } + +} diff --git a/src/main/java/com/simibubi/create/modules/logistics/management/LogisticalDialItem.java b/src/main/java/com/simibubi/create/modules/logistics/management/LogisticalDialItem.java new file mode 100644 index 000000000..daecb8a8f --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/logistics/management/LogisticalDialItem.java @@ -0,0 +1,89 @@ +package com.simibubi.create.modules.logistics.management; + +import static com.simibubi.create.AllBlocks.LOGISTICAL_CONTROLLER; +import static com.simibubi.create.AllBlocks.LOGISTICAL_INDEX; + +import java.util.UUID; + +import com.simibubi.create.foundation.item.IItemWithColorHandler; +import com.simibubi.create.modules.logistics.management.base.LogisticalControllerTileEntity; + +import net.minecraft.block.BlockState; +import net.minecraft.client.renderer.color.IItemColor; +import net.minecraft.entity.Entity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.item.ItemUseContext; +import net.minecraft.util.ActionResult; +import net.minecraft.util.ActionResultType; +import net.minecraft.util.Hand; +import net.minecraft.world.World; + +public class LogisticalDialItem extends Item implements IItemWithColorHandler { + + public LogisticalDialItem(Properties properties) { + super(properties); + } + + @Override + public IItemColor getColorHandler() { + return (stack, layer) -> { + if (layer == 1 && stack.getOrCreateTag().contains("NetworkIDLeast")) + return LogisticalControllerTileEntity.colorFromUUID(stack.getTag().getUniqueId("NetworkID")); + return 0xFFFFFF; + }; + } + + @Override + public void inventoryTick(ItemStack stack, World worldIn, Entity entityIn, int itemSlot, boolean isSelected) { + if (worldIn.isRemote && !stack.hasTag()) + stack.getOrCreateTag().putUniqueId("NetworkID", UUID.randomUUID()); + } + + @Override + public ActionResultType onItemUse(ItemUseContext context) { + ItemStack heldItem = context.getItem(); + boolean isRemote = context.getWorld().isRemote; + + if (!context.getPlayer().isAllowEdit()) + return super.onItemUse(context); + BlockState blockState = context.getWorld().getBlockState(context.getPos()); + if (!LOGISTICAL_CONTROLLER.typeOf(blockState) && !LOGISTICAL_INDEX.typeOf(blockState)) { + if (context.isPlacerSneaking()) { + if (!isRemote) + heldItem.getTag().putUniqueId("NetworkID", UUID.randomUUID()); + context.getPlayer().getCooldownTracker().setCooldown(heldItem.getItem(), 5); + return ActionResultType.SUCCESS; + } + return super.onItemUse(context); + } + + LogisticalControllerTileEntity tileEntity = (LogisticalControllerTileEntity) context.getWorld() + .getTileEntity(context.getPos()); + if (context.isPlacerSneaking()) { + if (!isRemote) + heldItem.getTag().putUniqueId("NetworkID", tileEntity.getNetworkId()); + context.getPlayer().getCooldownTracker().setCooldown(heldItem.getItem(), 5); + return ActionResultType.SUCCESS; + } + + tileEntity.setNetworkId(heldItem.getTag().getUniqueId("NetworkID")); + return ActionResultType.SUCCESS; + } + + @Override + public ActionResult onItemRightClick(World worldIn, PlayerEntity playerIn, Hand handIn) { + if (!playerIn.isSneaking()) + return super.onItemRightClick(worldIn, playerIn, handIn); + + ItemStack heldItem = playerIn.getHeldItem(handIn); + if (!worldIn.isRemote) { + heldItem.getTag().putUniqueId("NetworkID", UUID.randomUUID()); + playerIn.inventory.markDirty(); + } + playerIn.getCooldownTracker().setCooldown(heldItem.getItem(), 5); + return new ActionResult<>(ActionResultType.SUCCESS, heldItem); + } + +} diff --git a/src/main/java/com/simibubi/create/modules/logistics/management/LogisticalNetwork.java b/src/main/java/com/simibubi/create/modules/logistics/management/LogisticalNetwork.java new file mode 100644 index 000000000..7091c7d94 --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/logistics/management/LogisticalNetwork.java @@ -0,0 +1,79 @@ +package com.simibubi.create.modules.logistics.management; + +import java.util.ArrayList; +import java.util.List; +import java.util.PriorityQueue; + +import com.simibubi.create.modules.logistics.management.base.LogisticalControllerTileEntity; +import com.simibubi.create.modules.logistics.management.base.LogisticalTask; +import com.simibubi.create.modules.logistics.management.base.LogisticalTask.DepositTask; +import com.simibubi.create.modules.logistics.management.base.LogisticalTask.SupplyTask; +import com.simibubi.create.modules.logistics.management.controller.TransactionsTileEntity; +import com.simibubi.create.modules.logistics.management.index.LogisticalIndexTileEntity; + +public class LogisticalNetwork { + + public List taskQueues = new ArrayList<>(); + public List indexers = new ArrayList<>(); + public PriorityQueue internalTaskQueue = new PriorityQueue<>(); + public PriorityQueue suppliers = new PriorityQueue<>(); + public PriorityQueue receivers = new PriorityQueue<>(); + public int participants = 0; + public boolean tasksUpdated; + + public void addController(LogisticalControllerTileEntity te) { + if (te instanceof TransactionsTileEntity) { + if (taskQueues.contains(te)) + return; + taskQueues.add((TransactionsTileEntity) te); + } + if (te instanceof LogisticalIndexTileEntity) { + if (indexers.contains(te)) + return; + indexers.add((LogisticalIndexTileEntity) te); + } + if (te.isSupplier()) { + if (suppliers.contains(te)) + return; + suppliers.add(te); + } + if (te.isReceiver()) { + if (receivers.contains(te)) + return; + receivers.add(te); + indexers.forEach(LogisticalIndexTileEntity::syncReceivers); + } + participants++; + } + + public void removeController(LogisticalControllerTileEntity te) { + if (te instanceof TransactionsTileEntity) + if (!taskQueues.remove((TransactionsTileEntity) te)) + return; + if (te instanceof LogisticalIndexTileEntity) + if (!indexers.remove((LogisticalIndexTileEntity) te)) + return; + if (te.isSupplier()) + if (!suppliers.remove(te)) + return; + if (te.isReceiver()) { + if (!receivers.remove(te)) + return; + indexers.forEach(LogisticalIndexTileEntity::syncReceivers); + } + participants--; + } + + public boolean isEmpty() { + return participants == 0; + } + + public void enqueueTask(LogisticalTask task) { + internalTaskQueue.add(task); + if (task instanceof SupplyTask) + suppliers.forEach(LogisticalControllerTileEntity::notifyTaskUpdate); + if (task instanceof DepositTask) + receivers.forEach(LogisticalControllerTileEntity::notifyTaskUpdate); + } + +} diff --git a/src/main/java/com/simibubi/create/modules/logistics/management/LogisticalNetworkHandler.java b/src/main/java/com/simibubi/create/modules/logistics/management/LogisticalNetworkHandler.java new file mode 100644 index 000000000..8a12becd0 --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/logistics/management/LogisticalNetworkHandler.java @@ -0,0 +1,50 @@ +package com.simibubi.create.modules.logistics.management; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +import com.simibubi.create.Create; +import com.simibubi.create.modules.logistics.management.base.LogisticalControllerTileEntity; + +import net.minecraft.world.IWorld; + +public class LogisticalNetworkHandler { + + static Map> networks = new HashMap<>(); + + public void onLoadWorld(IWorld world) { + networks.put(world, new HashMap<>()); + Create.logger.debug("Prepared Logistical Network Map for " + world.getDimension().getType().getRegistryName()); + } + + public void onUnloadWorld(IWorld world) { + networks.remove(world); + Create.logger.debug("Removed Logistical Network Map for " + world.getDimension().getType().getRegistryName()); + } + + public LogisticalNetwork handleAdded(LogisticalControllerTileEntity te) { + LogisticalNetwork networkByID = getNetworkByID(te.getWorld(), te.getNetworkId()); + networkByID.addController(te); + return networkByID; + } + + public void handleRemoved(LogisticalControllerTileEntity te) { + getNetworkByID(te.getWorld(), te.getNetworkId()).removeController(te); + removeIfEmpty(te.getWorld(), te.getNetworkId()); + } + + public LogisticalNetwork getNetworkByID(IWorld world, UUID id) { + Map worldNets = networks.get(world); + if (!worldNets.containsKey(id)) + worldNets.put(id, new LogisticalNetwork()); + return worldNets.get(id); + } + + private void removeIfEmpty(IWorld world, UUID id) { + Map worldNets = networks.get(world); + if (worldNets.get(id).isEmpty()) + worldNets.remove(id); + } + +} diff --git a/src/main/java/com/simibubi/create/modules/logistics/management/base/IncrementalInventoryUpdate.java b/src/main/java/com/simibubi/create/modules/logistics/management/base/IncrementalInventoryUpdate.java new file mode 100644 index 000000000..7f4bebaef --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/logistics/management/base/IncrementalInventoryUpdate.java @@ -0,0 +1,11 @@ +package com.simibubi.create.modules.logistics.management.base; + +import net.minecraft.item.ItemStack; + +public class IncrementalInventoryUpdate { + + public ItemStack item; + public int newAmount; + + +} diff --git a/src/main/java/com/simibubi/create/modules/logistics/management/base/LogisticalActor.java b/src/main/java/com/simibubi/create/modules/logistics/management/base/LogisticalActor.java new file mode 100644 index 000000000..6a3b8b7ff --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/logistics/management/base/LogisticalActor.java @@ -0,0 +1,36 @@ +package com.simibubi.create.modules.logistics.management.base; + +public abstract class LogisticalActor { + + public enum Actors { + SUPPLY(new Supply()), + STORAGE(new Storage()), + DEMAND(new Demand()), + + ; + + private LogisticalActor actor; + + public LogisticalActor get() { + return this.actor; + } + + private Actors(LogisticalActor actor) { + this.actor = actor; + } + } + + public static class Supply extends LogisticalActor { + + } + + public static class Storage extends LogisticalActor { + + } + + public static class Demand extends LogisticalActor { + + } + + +} diff --git a/src/main/java/com/simibubi/create/modules/logistics/management/base/LogisticalCasingBlock.java b/src/main/java/com/simibubi/create/modules/logistics/management/base/LogisticalCasingBlock.java new file mode 100644 index 000000000..e5e3a9ffc --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/logistics/management/base/LogisticalCasingBlock.java @@ -0,0 +1,261 @@ +package com.simibubi.create.modules.logistics.management.base; + +import static net.minecraft.util.Direction.AxisDirection.POSITIVE; + +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Random; +import java.util.Set; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.foundation.block.IWithTileEntity; + +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.BlockItemUseContext; +import net.minecraft.state.BooleanProperty; +import net.minecraft.state.EnumProperty; +import net.minecraft.state.IProperty; +import net.minecraft.state.StateContainer.Builder; +import net.minecraft.state.properties.BlockStateProperties; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.Direction; +import net.minecraft.util.Hand; +import net.minecraft.util.Direction.Axis; +import net.minecraft.util.Direction.AxisDirection; +import net.minecraft.util.IStringSerializable; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.BlockRayTraceResult; +import net.minecraft.util.math.shapes.ISelectionContext; +import net.minecraft.util.math.shapes.VoxelShape; +import net.minecraft.util.math.shapes.VoxelShapes; +import net.minecraft.util.text.StringTextComponent; +import net.minecraft.util.text.TextFormatting; +import net.minecraft.world.IBlockReader; +import net.minecraft.world.IWorld; +import net.minecraft.world.IWorldReader; +import net.minecraft.world.World; +import net.minecraftforge.common.util.LazyOptional; +import net.minecraftforge.items.CapabilityItemHandler; +import net.minecraftforge.items.IItemHandler; + +public class LogisticalCasingBlock extends Block implements IWithTileEntity { + + public static final EnumProperty AXIS = BlockStateProperties.AXIS; + public static final IProperty PART = EnumProperty.create("part", Part.class); + public static final BooleanProperty ACTIVE = BooleanProperty.create("active"); + + public static final VoxelShape SINGLE_SHAPE = VoxelShapes.or(makeCuboidShape(0, 0, 0, 16, 2, 16), + makeCuboidShape(1, 1, 1, 15, 15, 15), makeCuboidShape(0, 14, 0, 16, 16, 16)); + + public LogisticalCasingBlock() { + super(Properties.from(Blocks.DARK_OAK_PLANKS)); + setDefaultState(getDefaultState().with(PART, Part.NONE).with(AXIS, Axis.Y).with(ACTIVE, false)); + } + + @Override + public BlockState getStateForPlacement(BlockItemUseContext context) { + BlockState state = getDefaultState(); + for (Direction face : Direction.values()) { + BlockState neighbour = context.getWorld().getBlockState(context.getPos().offset(face)); + if (!AllBlocks.LOGISTICAL_CASING.typeOf(neighbour)) + continue; + if (neighbour.get(PART) != Part.NONE && face.getAxis() != neighbour.get(AXIS)) + continue; + state = state.with(PART, face.getAxisDirection() == AxisDirection.POSITIVE ? Part.START : Part.END); + state = state.with(AXIS, face.getAxis()); + } + + return state; + } + + @Override + public void onNeighborChange(BlockState state, IWorldReader world, BlockPos pos, BlockPos neighbor) { + BlockState invState = world.getBlockState(neighbor); + + if (!invState.hasTileEntity()) + return; + TileEntity invTE = world.getTileEntity(neighbor); + + LazyOptional inventory = invTE.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY); + if (inventory.isPresent() && world instanceof IWorld) { + withTileEntityDo((IWorld) world, pos, te -> te.neighbourChanged(neighbor)); + } + } + + @Override + public void onReplaced(BlockState state, World worldIn, BlockPos pos, BlockState newState, boolean isMoving) { + boolean blockChanged = state.getBlock() != newState.getBlock(); + if (state.hasTileEntity() && (blockChanged || !newState.hasTileEntity())) { + worldIn.removeTileEntity(pos); + return; + } + if (blockChanged) { + Part part = state.get(PART); + Direction facing = Direction.getFacingFromAxis(POSITIVE, state.get(AXIS)); + if (part == Part.END || part == Part.MIDDLE) + worldIn.getPendingBlockTicks().scheduleTick(pos.offset(facing.getOpposite()), state.getBlock(), 1); + if (part == Part.START || part == Part.MIDDLE) + worldIn.getPendingBlockTicks().scheduleTick(pos.offset(facing), state.getBlock(), 1); + } + } + + @Override + public boolean hasTileEntity(BlockState state) { + return state.get(ACTIVE); + } + + @Override + public TileEntity createTileEntity(BlockState state, IBlockReader world) { + return new LogisticalCasingTileEntity(); + } + + @Override + public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) { + return state.get(PART) == Part.NONE ? SINGLE_SHAPE : VoxelShapes.fullCube(); + } + + @Override + public BlockState updatePostPlacement(BlockState state, Direction face, BlockState facingState, IWorld worldIn, + BlockPos currentPos, BlockPos facingPos) { + Part part = state.get(PART); + boolean neighbourPresent = AllBlocks.LOGISTICAL_CASING.typeOf(facingState); + boolean alongAxis = face.getAxis() == state.get(AXIS); + boolean positive = face.getAxisDirection() == AxisDirection.POSITIVE; + boolean neighbourAlongAxis = neighbourPresent + && (facingState.get(PART) == Part.NONE || facingState.get(AXIS) == face.getAxis()); + + if (part == Part.NONE && neighbourPresent && neighbourAlongAxis) { + state = state.with(PART, positive ? Part.START : Part.END); + return state.with(AXIS, face.getAxis()); + } + + if (!alongAxis) + return state; + + if (part == Part.END) { + if (positive && neighbourPresent && neighbourAlongAxis) + return state.with(PART, Part.MIDDLE); + if (!positive && !neighbourPresent) + return state.with(PART, Part.NONE).with(AXIS, Axis.Y); + } + + if (part == Part.START) { + if (!positive && neighbourPresent && neighbourAlongAxis) + return state.with(PART, Part.MIDDLE); + if (positive && !neighbourPresent) + return state.with(PART, Part.NONE).with(AXIS, Axis.Y); + } + + if (part == Part.MIDDLE) { + if (!positive && !neighbourPresent) + return state.with(PART, Part.START); + if (positive && !neighbourPresent) + return state.with(PART, Part.END); + } + + return state; + } + + @Override + public boolean onBlockActivated(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand handIn, + BlockRayTraceResult hit) { + if (!player.getHeldItem(handIn).isEmpty()) + return false; + if (worldIn.isRemote) + return true; + if (!state.get(ACTIVE)) + player.sendStatusMessage(new StringTextComponent("Not Active").applyTextStyle(TextFormatting.RED), false); + else { + LogisticalCasingTileEntity tileEntity = (LogisticalCasingTileEntity) worldIn.getTileEntity(pos); + player.sendStatusMessage(new StringTextComponent("Controllers: " + tileEntity.controllers.toString()) + .applyTextStyle(TextFormatting.GREEN), false); + } + + return true; + } + + @Override + public void onBlockAdded(BlockState state, World worldIn, BlockPos pos, BlockState oldState, boolean isMoving) { + boolean blockChanged = state.getBlock() != oldState.getBlock(); + if (blockChanged) + worldIn.getPendingBlockTicks().scheduleTick(pos, state.getBlock(), 1); + } + + @Override + public void tick(BlockState state, World worldIn, BlockPos pos, Random random) { + synchronizeCasingGroup(worldIn, pos); + } + + protected void synchronizeCasingGroup(World world, BlockPos start) { + List chain = LogisticalControllerBlock.collectCasings(world, start); + Set controllers = new HashSet<>(); + + // Collect all Controllers + for (BlockPos pos : chain) { + BlockState casing = world.getBlockState(pos); + if (!casing.get(ACTIVE)) + continue; + LogisticalCasingTileEntity te = (LogisticalCasingTileEntity) world.getTileEntity(pos); + if (te == null) + continue; + for (BlockPos controller : te.controllers) { + if (controller.withinDistance(te.getPos(), 1 + 1 / 512f)) + controllers.add(controller); + } + } + + // Advertise all Controllers + for (BlockPos pos : chain) { + BlockState state = world.getBlockState(pos); + boolean shouldBeActive = !controllers.isEmpty(); + if (state.get(ACTIVE) != shouldBeActive) { + if (!shouldBeActive) { + LogisticalCasingTileEntity te = (LogisticalCasingTileEntity) world.getTileEntity(pos); + te.controllers.forEach(te::detachController); + } + world.setBlockState(pos, state.with(ACTIVE, shouldBeActive)); + } + if (!shouldBeActive) + continue; + + LogisticalCasingTileEntity te = (LogisticalCasingTileEntity) world.getTileEntity(pos); + if (te == null) + continue; + + // detach missing + for (Iterator iterator = te.controllers.iterator(); iterator.hasNext();) { + BlockPos controller = iterator.next(); + if (controllers.contains(controller)) + continue; + iterator.remove(); + te.detachController(controller); + } + + // attach new + for (BlockPos controller : controllers) { + if (!te.controllers.contains(controller)) + te.addController(controller); + } + } + } + + @Override + protected void fillStateContainer(Builder builder) { + builder.add(AXIS, PART, ACTIVE); + super.fillStateContainer(builder); + } + + public enum Part implements IStringSerializable { + START, MIDDLE, END, NONE; + + @Override + public String getName() { + return name().toLowerCase(); + } + } + +} diff --git a/src/main/java/com/simibubi/create/modules/logistics/management/base/LogisticalCasingTileEntity.java b/src/main/java/com/simibubi/create/modules/logistics/management/base/LogisticalCasingTileEntity.java new file mode 100644 index 000000000..d7613adb3 --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/logistics/management/base/LogisticalCasingTileEntity.java @@ -0,0 +1,131 @@ +package com.simibubi.create.modules.logistics.management.base; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +import com.google.common.base.Predicates; +import com.simibubi.create.AllTileEntities; +import com.simibubi.create.foundation.block.SyncedTileEntity; + +import net.minecraft.nbt.CompoundNBT; +import net.minecraft.nbt.ListNBT; +import net.minecraft.nbt.NBTUtil; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.Direction; +import net.minecraft.util.math.BlockPos; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.util.Constants.NBT; +import net.minecraftforge.common.util.LazyOptional; +import net.minecraftforge.items.IItemHandlerModifiable; +import net.minecraftforge.items.wrapper.CombinedInvWrapper; + +public class LogisticalCasingTileEntity extends SyncedTileEntity { + + Set controllers = new HashSet<>(); + + public LogisticalCasingTileEntity() { + super(AllTileEntities.LOGISTICAL_CASING.type); + } + + public boolean controllerPresent() { + if (controllers.isEmpty()) + return false; + for (BlockPos blockPos : controllers) { + if (world.isBlockPresent(blockPos)) + return true; + } + return false; + } + + @Override + public CompoundNBT write(CompoundNBT compound) { + ListNBT contollerNBT = new ListNBT(); + controllers.forEach(pos -> contollerNBT.add(NBTUtil.writeBlockPos(pos))); + compound.put("Controllers", contollerNBT); + return super.write(compound); + } + + @Override + public void read(CompoundNBT compound) { + controllers.clear(); + ListNBT controllerNBT = compound.getList("Controllers", NBT.TAG_COMPOUND); + controllerNBT.forEach(tag -> controllers.add(NBTUtil.readBlockPos((CompoundNBT) tag))); + super.read(compound); + } + + public void neighbourChanged(BlockPos neighbour) { + if (!controllerPresent()) + return; + for (LogisticalControllerTileEntity controller : getControllers()) { + if (!(controller instanceof LogisticalInventoryControllerTileEntity)) + continue; + ((LogisticalInventoryControllerTileEntity) controller).inventoryChanged(neighbour); + } + } + + public void addController(BlockPos pos) { + controllers.add(pos); + attachController(pos); + markDirty(); + } + + public void removeController(BlockPos pos) { + controllers.remove(pos); + detachController(pos); + markDirty(); + + if (controllers.isEmpty()) + world.setBlockState(getPos(), getBlockState().with(LogisticalCasingBlock.ACTIVE, false)); + } + + public void detachController(BlockPos pos) { + TileEntity tileEntity = world.getTileEntity(pos); + if (!(tileEntity instanceof LogisticalInventoryControllerTileEntity)) + return; + for (Direction facing : Direction.values()) + ((LogisticalInventoryControllerTileEntity) tileEntity).detachInventory(getPos().offset(facing)); + } + + public void attachController(BlockPos pos) { + TileEntity tileEntity = world.getTileEntity(pos); + if (!(tileEntity instanceof LogisticalControllerTileEntity)) + return; + for (Direction facing : Direction.values()) + ((LogisticalInventoryControllerTileEntity) tileEntity).inventoryChanged(getPos().offset(facing)); + } + + @Override + public void remove() { + controllers.forEach(this::detachController); + super.remove(); + } + + @Override + public LazyOptional getCapability(Capability cap, Direction side) { + if (!controllerPresent()) + return LazyOptional.empty(); + List TEs = getControllers(); + if (controllers.isEmpty()) + return LazyOptional.empty(); + List invs = TEs.stream().map(te -> te.getCasingCapability(cap, side).orElse(null)) + .filter(Predicates.notNull()).filter(inv -> inv instanceof IItemHandlerModifiable) + .collect(Collectors.toList()); + IItemHandlerModifiable[] params = new IItemHandlerModifiable[invs.size()]; + invs.toArray(params); + return LazyOptional.of(() -> new CombinedInvWrapper(params)).cast(); + } + + public List getControllers() { + List TEs = new ArrayList<>(controllers.size()); + for (BlockPos controllerPos : controllers) { + TileEntity tileEntity = world.getTileEntity(controllerPos); + if (tileEntity instanceof LogisticalControllerTileEntity) + TEs.add((LogisticalControllerTileEntity) tileEntity); + } + return TEs; + } + +} diff --git a/src/main/java/com/simibubi/create/modules/logistics/management/base/LogisticalControllerBlock.java b/src/main/java/com/simibubi/create/modules/logistics/management/base/LogisticalControllerBlock.java new file mode 100644 index 000000000..fb2630a9c --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/logistics/management/base/LogisticalControllerBlock.java @@ -0,0 +1,263 @@ +package com.simibubi.create.modules.logistics.management.base; + +import static com.simibubi.create.modules.logistics.management.base.LogisticalCasingBlock.ACTIVE; +import static com.simibubi.create.modules.logistics.management.base.LogisticalCasingBlock.PART; +import static net.minecraft.state.properties.BlockStateProperties.AXIS; +import static net.minecraft.util.Direction.AxisDirection.POSITIVE; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllItems; +import com.simibubi.create.foundation.block.IWithTileEntity; +import com.simibubi.create.foundation.block.IWithoutBlockItem; +import com.simibubi.create.foundation.block.RenderUtilityBlock; +import com.simibubi.create.modules.logistics.management.base.LogisticalCasingBlock.Part; +import com.simibubi.create.modules.logistics.management.controller.CalculationTileEntity; +import com.simibubi.create.modules.logistics.management.controller.RequestTileEntity; +import com.simibubi.create.modules.logistics.management.controller.StorageTileEntity; +import com.simibubi.create.modules.logistics.management.controller.SupplyTileEntity; +import com.simibubi.create.modules.logistics.management.controller.TransactionsTileEntity; + +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.block.DirectionalBlock; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.BlockItemUseContext; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.state.EnumProperty; +import net.minecraft.state.IProperty; +import net.minecraft.state.StateContainer.Builder; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.Direction; +import net.minecraft.util.Hand; +import net.minecraft.util.IStringSerializable; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.BlockRayTraceResult; +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.IWorldReader; +import net.minecraft.world.World; + +public class LogisticalControllerBlock extends DirectionalBlock + implements IWithoutBlockItem, IWithTileEntity { + + public static final IProperty TYPE = EnumProperty.create("type", Type.class); + + public static final VoxelShape UP_SHAPE = makeCuboidShape(2, -1, 2, 14, 3, 14), + DOWN_SHAPE = makeCuboidShape(2, 13, 2, 14, 17, 14), SOUTH_SHAPE = makeCuboidShape(2, 2, -1, 14, 14, 3), + NORTH_SHAPE = makeCuboidShape(2, 2, 13, 14, 14, 17), EAST_SHAPE = makeCuboidShape(-1, 2, 2, 3, 14, 14), + WEST_SHAPE = makeCuboidShape(13, 2, 2, 17, 14, 14); + + public LogisticalControllerBlock() { + super(Properties.from(Blocks.PISTON)); + } + + @Override + protected void fillStateContainer(Builder builder) { + builder.add(TYPE, FACING); + super.fillStateContainer(builder); + } + + @Override + public boolean hasTileEntity(BlockState state) { + return true; + } + + @Override + public TileEntity createTileEntity(BlockState state, IBlockReader world) { + Type type = state.get(TYPE); + + if (type == Type.SUPPLY) + return new SupplyTileEntity(); + if (type == Type.REQUEST) + return new RequestTileEntity(); + if (type == Type.STORAGE) + return new StorageTileEntity(); + if (type == Type.CALCULATION) + return new CalculationTileEntity(); + if (type == Type.TRANSACTIONS) + return new TransactionsTileEntity(); + + return null; + } + + @Override + public void onBlockPlacedBy(World worldIn, BlockPos pos, BlockState state, LivingEntity placer, ItemStack stack) { + if (!(placer instanceof PlayerEntity)) + return; + PlayerEntity player = (PlayerEntity) placer; + for (int slot = 0; slot < player.inventory.getSizeInventory(); slot++) { + ItemStack itemStack = player.inventory.getStackInSlot(slot); + if (!AllItems.LOGISTICAL_DIAL.typeOf(itemStack)) + continue; + if (!itemStack.hasTag()) + continue; + withTileEntityDo(worldIn, pos, te -> te.setNetworkId(itemStack.getTag().getUniqueId("NetworkID"))); + return; + } + } + + @Override + public BlockState getStateForPlacement(BlockItemUseContext context) { + BlockState state = getDefaultState().with(FACING, context.getFace()); + + Item item = context.getItem().getItem(); + if (item instanceof LogisticalControllerItem) + state = state.with(TYPE, ((LogisticalControllerItem) item).getType()); + + return state; + } + + @Override + public boolean isValidPosition(BlockState state, IWorldReader worldIn, BlockPos pos) { + Direction facing = state.get(FACING); + BlockPos offset = pos.offset(facing.getOpposite()); + BlockState blockState = worldIn.getBlockState(offset); + boolean isCasing = AllBlocks.LOGISTICAL_CASING.typeOf(blockState); + + return isCasing; + } + + @Override + public boolean onBlockActivated(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand handIn, + BlockRayTraceResult hit) { + if (player.isSneaking() || !player.isAllowEdit()) + return false; + ItemStack held = player.getHeldItem(handIn); + if (held.getItem() != Items.NAME_TAG) + return false; + if (!held.hasDisplayName()) + return false; + + withTileEntityDo(worldIn, pos, te -> { + te.setName(held.getDisplayName().getUnformattedComponentText()); + }); + + return true; + } + + @Override + public void onBlockAdded(BlockState state, World worldIn, BlockPos pos, BlockState oldState, boolean isMoving) { + BlockPos start = pos.offset(state.get(FACING).getOpposite()); + List toUpdate = collectCasings(worldIn, start); + + for (BlockPos blockPos : toUpdate) { + worldIn.setBlockState(blockPos, worldIn.getBlockState(blockPos).with(ACTIVE, true)); + LogisticalCasingTileEntity tileEntity = (LogisticalCasingTileEntity) worldIn.getTileEntity(blockPos); + tileEntity.addController(pos); + } + } + + @Override + public void onReplaced(BlockState state, World worldIn, BlockPos pos, BlockState newState, boolean isMoving) { + boolean blockChanged = state.getBlock() != newState.getBlock() || state.get(TYPE) != newState.get(TYPE); + + if (blockChanged) { + BlockPos start = pos.offset(state.get(FACING).getOpposite()); + List toUpdate = collectCasings(worldIn, start); + + for (BlockPos blockPos : toUpdate) { + if (!worldIn.getBlockState(blockPos).get(ACTIVE)) + continue; + LogisticalCasingTileEntity tileEntity = (LogisticalCasingTileEntity) worldIn.getTileEntity(blockPos); + tileEntity.removeController(pos); + } + } + + if (state.hasTileEntity() && blockChanged) { + worldIn.removeTileEntity(pos); + } + } + + public static List collectCasings(World worldIn, BlockPos start) { + BlockState casing = worldIn.getBlockState(start); + if (!AllBlocks.LOGISTICAL_CASING.typeOf(casing)) + return Collections.emptyList(); + List casings = new ArrayList<>(); + casings.add(start); + if (casing.get(PART) != Part.NONE) { + Direction casingDirection = Direction.getFacingFromAxis(POSITIVE, casing.get(AXIS)); + BlockPos search = start; + + for (int i = 0; i < 1000; i++) { + if (worldIn.getBlockState(search).get(PART) == Part.START) + break; + search = search.offset(casingDirection.getOpposite()); + if (!AllBlocks.LOGISTICAL_CASING.typeOf(worldIn.getBlockState(search))) + break; + casings.add(search); + } + search = start; + for (int i = 0; i < 1000; i++) { + if (worldIn.getBlockState(search).get(PART) == Part.END) + break; + search = search.offset(casingDirection); + if (!AllBlocks.LOGISTICAL_CASING.typeOf(worldIn.getBlockState(search))) + break; + casings.add(search); + } + } + return casings; + } + + @Override + public void neighborChanged(BlockState state, World worldIn, BlockPos pos, Block blockIn, BlockPos fromPos, + boolean isMoving) { + if (state.isValidPosition(worldIn, pos)) + return; + + TileEntity tileentity = state.hasTileEntity() ? worldIn.getTileEntity(pos) : null; + spawnDrops(state, worldIn, pos, tileentity); + worldIn.removeBlock(pos, false); + + for (Direction direction : Direction.values()) + worldIn.notifyNeighborsOfStateChange(pos.offset(direction), this); + } + + @Override + public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) { + Direction facing = state.get(FACING); + + if (facing == Direction.UP) + return UP_SHAPE; + if (facing == Direction.DOWN) + return DOWN_SHAPE; + if (facing == Direction.EAST) + return EAST_SHAPE; + if (facing == Direction.WEST) + return WEST_SHAPE; + if (facing == Direction.NORTH) + return NORTH_SHAPE; + if (facing == Direction.SOUTH) + return SOUTH_SHAPE; + + return VoxelShapes.empty(); + } + + public static class LogisticalControllerIndicatorBlock extends RenderUtilityBlock { + @Override + protected void fillStateContainer(Builder builder) { + builder.add(TYPE, FACING); + super.fillStateContainer(builder); + } + } + + public enum Type implements IStringSerializable { + SUPPLY, REQUEST, STORAGE, CALCULATION, TRANSACTIONS; + + @Override + public String getName() { + return name().toLowerCase(); + } + } + +} diff --git a/src/main/java/com/simibubi/create/modules/logistics/management/base/LogisticalControllerItem.java b/src/main/java/com/simibubi/create/modules/logistics/management/base/LogisticalControllerItem.java new file mode 100644 index 000000000..748e81ae0 --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/logistics/management/base/LogisticalControllerItem.java @@ -0,0 +1,31 @@ +package com.simibubi.create.modules.logistics.management.base; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.modules.logistics.management.base.LogisticalControllerBlock.Type; + +import net.minecraft.item.BlockItem; +import net.minecraft.item.ItemGroup; +import net.minecraft.item.ItemStack; +import net.minecraft.util.NonNullList; + +public class LogisticalControllerItem extends BlockItem { + + private Type type; + + public LogisticalControllerItem(Properties builder, Type type) { + super(AllBlocks.LOGISTICAL_CONTROLLER.get(), builder); + this.type = type; + } + + @Override + public void fillItemGroup(ItemGroup group, NonNullList items) { + if (this.isInGroup(group)) { + items.add(new ItemStack(this)); + } + } + + public Type getType() { + return type; + } + +} diff --git a/src/main/java/com/simibubi/create/modules/logistics/management/base/LogisticalControllerTileEntity.java b/src/main/java/com/simibubi/create/modules/logistics/management/base/LogisticalControllerTileEntity.java new file mode 100644 index 000000000..7fcf580ca --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/logistics/management/base/LogisticalControllerTileEntity.java @@ -0,0 +1,156 @@ +package com.simibubi.create.modules.logistics.management.base; + +import java.util.UUID; + +import com.simibubi.create.Create; +import com.simibubi.create.foundation.block.SyncedTileEntity; +import com.simibubi.create.foundation.utility.ColorHelper; +import com.simibubi.create.modules.logistics.management.LogisticalNetwork; + +import net.minecraft.nbt.CompoundNBT; +import net.minecraft.tileentity.ITickableTileEntity; +import net.minecraft.tileentity.TileEntityType; +import net.minecraft.util.Direction; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.util.LazyOptional; + +public abstract class LogisticalControllerTileEntity extends SyncedTileEntity + implements Comparable, ITickableTileEntity { + + public static final int COOLDOWN = 20; + + protected Priority priority = Priority.LOW; + protected LogisticalNetwork network; + protected String name = ""; + protected UUID networkId; + protected boolean initialize; + protected boolean checkTasks; + protected int taskCooldown; + + public LogisticalControllerTileEntity(TileEntityType tileEntityTypeIn) { + super(tileEntityTypeIn); + initialize = true; + } + + @Override + public void tick() { + if (initialize) { + initialize = false; + initialize(); + return; + } + + if (taskCooldown > 0) + taskCooldown--; + } + + protected void initialize() { + if (networkId != null) + handleAdded(); + } + + @Override + public void remove() { + if (networkId != null) + handleRemoved(); + super.remove(); + } + + public void setName(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + @Override + public boolean hasFastRenderer() { + return true; + } + + public void notifyTaskUpdate() { + checkTasks = true; + } + + @Override + public CompoundNBT write(CompoundNBT compound) { + if (networkId != null) + compound.putUniqueId("NetworkID", networkId); + compound.putString("Address", name); + return super.write(compound); + } + + public UUID getNetworkId() { + return networkId; + } + + @Override + public void read(CompoundNBT compound) { + if (compound.contains("NetworkIDLeast")) + networkId = compound.getUniqueId("NetworkID"); + name = compound.getString("Address"); + super.read(compound); + } + + public int getColor() { + return colorFromUUID(networkId); + } + + public static int colorFromUUID(UUID uuid) { + if (uuid == null) + return 0x333333; + int rainbowColor = ColorHelper.rainbowColor((int) uuid.getLeastSignificantBits()); + return ColorHelper.mixColors(rainbowColor, 0xFFFFFF, .5f); + } + + public LazyOptional getCasingCapability(Capability cap, Direction side) { + return LazyOptional.empty(); + } + + public void setNetworkId(UUID uniqueId) { + if (getNetwork() != null) + handleRemoved(); + networkId = uniqueId; + handleAdded(); + markDirty(); + sendData(); + } + + public void handleAdded() { + if (world.isRemote) + return; + if (getNetwork() != null) + return; + network = Create.logisticalNetworkHandler.handleAdded(this); + } + + public void handleRemoved() { + if (world.isRemote) + return; + Create.logisticalNetworkHandler.handleRemoved(this); + network = null; + } + + public boolean isSupplier() { + return false; + } + + public boolean isReceiver() { + return false; + } + + @Override + public int compareTo(LogisticalControllerTileEntity o) { + return this.priority.compareTo(o.priority); + } + + public LogisticalNetwork getNetwork() { + return network; + } + + public static enum Priority { + LOWEST, LOW, MEDIUM, HIGH, HIGHEST; + } + +} diff --git a/src/main/java/com/simibubi/create/modules/logistics/management/base/LogisticalControllerTileEntityRenderer.java b/src/main/java/com/simibubi/create/modules/logistics/management/base/LogisticalControllerTileEntityRenderer.java new file mode 100644 index 000000000..f2b9492fa --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/logistics/management/base/LogisticalControllerTileEntityRenderer.java @@ -0,0 +1,94 @@ +package com.simibubi.create.modules.logistics.management.base; + +import static com.simibubi.create.modules.logistics.management.base.LogisticalControllerBlock.TYPE; +import static net.minecraft.state.properties.BlockStateProperties.FACING; + +import java.nio.ByteBuffer; +import java.util.HashMap; +import java.util.Map; +import java.util.Random; + +import org.lwjgl.opengl.GL11; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.foundation.utility.BufferManipulator; + +import net.minecraft.block.BlockState; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.BlockModelRenderer; +import net.minecraft.client.renderer.BlockRendererDispatcher; +import net.minecraft.client.renderer.BufferBuilder; +import net.minecraft.client.renderer.model.IBakedModel; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.util.math.BlockPos; +import net.minecraftforge.client.model.animation.TileEntityRendererFast; +import net.minecraftforge.client.model.data.EmptyModelData; + +public class LogisticalControllerTileEntityRenderer extends TileEntityRendererFast { + + protected class LogisticalControllerIndicatorRenderer extends BufferManipulator { + + public LogisticalControllerIndicatorRenderer(ByteBuffer original) { + super(original); + } + + public ByteBuffer getTransformed(float xIn, float yIn, float zIn, int color, int packedLightCoords) { + original.rewind(); + mutable.rewind(); + + byte r = (byte) (color >> 16); + byte g = (byte) ((color >> 8) & 0xFF); + byte b = (byte) (color & 0xFF); + byte a = (byte) 255; + + for (int vertex = 0; vertex < vertexCount(original); vertex++) { + putColor(mutable, vertex, r, g, b, a); + putPos(mutable, vertex, getX(original, vertex) + xIn, getY(original, vertex) + yIn, + getZ(original, vertex) + zIn); + putLight(mutable, vertex, packedLightCoords); + } + + return mutable; + } + } + + protected static Map cachedBuffers = new HashMap<>(); + + @Override + public void renderTileEntityFast(LogisticalControllerTileEntity te, double x, double y, double z, + float partialTicks, int destroyStage, BufferBuilder buffer) { + BlockPos pos = te.getPos(); + BlockState blockState = te.getBlockState(); + + if (AllBlocks.LOGISTICAL_INDEX.typeOf(blockState)) + return; + + BlockState renderedState = AllBlocks.LOGISTICAL_CONTROLLER_INDICATOR.get().getDefaultState() + .with(FACING, blockState.get(FACING)).with(TYPE, blockState.get(TYPE)); + + if (!cachedBuffers.containsKey(renderedState)) { + BlockRendererDispatcher dispatcher = Minecraft.getInstance().getBlockRendererDispatcher(); + BlockModelRenderer blockRenderer = dispatcher.getBlockModelRenderer(); + IBakedModel originalModel = dispatcher.getModelForState(renderedState); + BufferBuilder builder = new BufferBuilder(0); + Random random = new Random(); + + builder.setTranslation(0, 1, 0); + builder.begin(GL11.GL_QUADS, DefaultVertexFormats.BLOCK); + blockRenderer.renderModelFlat(getWorld(), originalModel, renderedState, BlockPos.ZERO.down(), builder, true, + random, 42, EmptyModelData.INSTANCE); + builder.finishDrawing(); + + cachedBuffers.put(renderedState, new LogisticalControllerIndicatorRenderer(builder.getByteBuffer())); + } + + int packedLightmapCoords = blockState.getPackedLightmapCoords(getWorld(), pos); + buffer.putBulkData(cachedBuffers.get(renderedState).getTransformed((float) x, (float) y, (float) z, + te.getColor(), packedLightmapCoords)); + } + + public static void invalidateCache() { + cachedBuffers.clear(); + } + +} diff --git a/src/main/java/com/simibubi/create/modules/logistics/management/base/LogisticalInventoryControllerTileEntity.java b/src/main/java/com/simibubi/create/modules/logistics/management/base/LogisticalInventoryControllerTileEntity.java new file mode 100644 index 000000000..9a66b17c5 --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/logistics/management/base/LogisticalInventoryControllerTileEntity.java @@ -0,0 +1,402 @@ +package com.simibubi.create.modules.logistics.management.base; + +import static net.minecraft.state.properties.BlockStateProperties.FACING; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import org.apache.commons.lang3.tuple.Pair; + +import com.simibubi.create.foundation.type.CombinedCountedItemsList; +import com.simibubi.create.foundation.type.CountedItemsList; +import com.simibubi.create.foundation.type.CountedItemsList.ItemStackEntry; +import com.simibubi.create.foundation.utility.ItemHelper; +import com.simibubi.create.modules.logistics.item.CardboardBoxItem; +import com.simibubi.create.modules.logistics.management.base.LogisticalTask.DepositTask; +import com.simibubi.create.modules.logistics.management.base.LogisticalTask.SupplyTask; + +import net.minecraft.block.BlockState; +import net.minecraft.item.ItemStack; +import net.minecraft.item.crafting.Ingredient; +import net.minecraft.nbt.CompoundNBT; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.tileentity.TileEntityType; +import net.minecraft.util.Direction; +import net.minecraft.util.math.BlockPos; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.util.LazyOptional; +import net.minecraftforge.items.CapabilityItemHandler; +import net.minecraftforge.items.IItemHandler; +import net.minecraftforge.items.ItemStackHandler; + +public abstract class LogisticalInventoryControllerTileEntity extends LogisticalControllerTileEntity { + + protected Map observedInventories = new HashMap<>(); + protected Map inventoryByHandler = new HashMap<>(); + protected CombinedCountedItemsList allItems = new CombinedCountedItemsList<>(); + protected boolean inventorySetDirty; + + protected LazyOptional shippingInventory; + protected boolean tryInsertBox; + + public LogisticalInventoryControllerTileEntity(TileEntityType tileEntityTypeIn) { + super(tileEntityTypeIn); + this.shippingInventory = LazyOptional.of(this::createInventory); + } + + @Override + public void read(CompoundNBT compound) { + super.read(compound); + if (compound.contains("ShippingInventory")) { + ShippingInventory inv = (ShippingInventory) shippingInventory.orElse(null); + inv.deserializeNBT(compound.getCompound("ShippingInventory")); + } + } + + public void inventoryChanged(BlockPos pos) { + removeInvalidatedInventories(); + TileEntity invTE = world.getTileEntity(pos); + if (invTE == null) + return; + if (invTE instanceof LogisticalCasingTileEntity) + return; + + LazyOptional inventory = invTE.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY); + if (!observedInventories.containsKey(pos)) { + addInventory(pos, inventory); + notifyIndexers(observedInventories.get(pos).countedItems); + } else { + if (inventoryByHandler.containsKey(inventory.orElse(null))) { + List localChanges = observedInventories.get(pos).refresh(); + CountedItemsList changes = new CountedItemsList(); + for (ItemStackEntry entry : localChanges) + changes.add(entry.stack, allItems.get().getItemCount(entry.stack)); + notifyIndexers(changes); + } + } + checkTasks = true; + tryInsertBox = true; + } + + public void detachInventory(BlockPos pos) { + observedInventories.remove(pos); + inventorySetDirty = true; + } + + public void addInventory(BlockPos pos, LazyOptional inventory) { + observedInventories.put(pos, new ConnectedInventory(inventory)); + inventorySetDirty = true; + } + + protected void notifyIndexers(CountedItemsList updates) { + if (network == null) + return; + network.indexers.forEach(indexer -> indexer.handleUpdatedController(getName(), updates)); + } + + @Override + public void tick() { + super.tick(); + + if (taskCooldown > 0 || world.isRemote) + return; + + if (tryInsertBox) { + tryInsertBox = false; + tryInsertBox(); + } + + if (checkTasks) { + checkTasks = false; + if (getNetwork() == null) + return; + checkTasks(); + } + + taskCooldown = COOLDOWN; + } + + private void tryInsertBox() { + if (!canReceive()) + return; + + ShippingInventory inventory = getInventory(); + ItemStack box = inventory.getStackInSlot(ShippingInventory.RECEIVING); + if (box.isEmpty()) + return; + List contents = CardboardBoxItem.getContents(box); + if (InsertAll(contents, true)) { + ItemStack copy = box.copy(); + copy.shrink(1); + inventory.setStackInSlot(ShippingInventory.RECEIVING, copy); + InsertAll(contents, false); + } + } + + public boolean InsertAll(List stacks, boolean simulate) { + removeInvalidatedInventories(); + for (ItemStack stack : stacks) { + ItemStack toInsert = stack.copy(); + + InventoryScan: for (IItemHandler inv : getObservedInventories()) { + for (int slot = 0; slot < inv.getSlots(); slot++) { + toInsert = inv.insertItem(slot, stack, simulate); + if (toInsert.isEmpty()) + break InventoryScan; + } + } + if (!toInsert.isEmpty()) + return false; + } + return true; + } + + private void removeInvalidatedInventories() { + observedInventories.keySet().stream().filter(key -> !observedInventories.get(key).itemHandler.isPresent()) + .collect(Collectors.toList()).forEach(this::detachInventory); + } + + @Override + protected void initialize() { + super.initialize(); + BlockPos start = pos.offset(getBlockState().get(FACING).getOpposite()); + List toUpdate = LogisticalControllerBlock.collectCasings(world, start); + for (BlockPos blockPos : toUpdate) { + world.updateComparatorOutputLevel(blockPos, world.getBlockState(blockPos).getBlock()); + + for (Direction face : Direction.values()) { + BlockPos neighbour = blockPos.offset(face); + BlockState invState = world.getBlockState(neighbour); + if (!invState.hasTileEntity()) + continue; + TileEntity invTE = world.getTileEntity(neighbour); + if (invTE instanceof LogisticalCasingTileEntity) + continue; + + LazyOptional inventory = invTE + .getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY); + if (!inventory.isPresent()) + continue; + addInventory(neighbour, inventory); + taskCooldown = COOLDOWN; + checkTasks = true; + } + } + } + + private void checkTasks() { + for (Iterator iterator = getNetwork().internalTaskQueue.iterator(); iterator.hasNext();) { + LogisticalTask task = iterator.next(); + + if (canSupply() && task instanceof SupplyTask) { + List> items = ((SupplyTask) task).items; + if (findItems(items, true) == null) + continue; + + List collectedStacks = findItems(items, false); + getInventory().createPackage(collectedStacks, task.targetAddress); + iterator.remove(); + checkTasks = true; + return; + } + + if (canReceive() && task instanceof DepositTask) { + + } + } + } + + public List findItems(List> items, boolean simulate) { + removeInvalidatedInventories(); + List foundItems = new ArrayList<>(); + + // Over Requested Ingredients + for (Pair pair : items) { + int amountLeft = pair.getValue(); + + // Over Attached inventories + InventoryScan: for (IItemHandler inv : getObservedInventories()) { + + // Over Slots + for (int slot = 0; slot < inv.getSlots(); slot++) { + ItemStack stackInSlot = inv.getStackInSlot(slot); + if (!pair.getKey().test(stackInSlot)) + continue; + + ItemStack extracted = inv.extractItem(slot, amountLeft, simulate); + amountLeft -= extracted.getCount(); + ItemHelper.addToList(extracted, foundItems); + + if (amountLeft == 0) + break InventoryScan; + } + } + if (amountLeft > 0) + return null; + } + return foundItems; + } + + public CountedItemsList getAllItems() { + if (inventorySetDirty) + refreshItemHandlerSet(); + return allItems.get(); + } + + public Collection getObservedInventories() { + if (inventorySetDirty) + refreshItemHandlerSet(); + return inventoryByHandler.keySet(); + } + + public void refreshItemHandlerSet() { + inventorySetDirty = false; + inventoryByHandler.clear(); + allItems.clear(); + observedInventories.forEach((pos, connectedInventory) -> { + if (connectedInventory.itemHandler.isPresent()) { + IItemHandler inv = connectedInventory.itemHandler.orElse(null); + for (IItemHandler iItemHandler : inventoryByHandler.keySet()) { + if (ItemHelper.isSameInventory(iItemHandler, inv)) + return; + } + inventoryByHandler.put(inv, connectedInventory); + allItems.add(inv, connectedInventory.countedItems); + } + }); + + } + + @Override + public CompoundNBT write(CompoundNBT compound) { + shippingInventory.ifPresent(inv -> compound.put("ShippingInventory", ((ShippingInventory) inv).serializeNBT())); + return super.write(compound); + } + + @Override + public void remove() { + shippingInventory.invalidate(); + super.remove(); + } + + public LazyOptional getCasingCapability(Capability cap, Direction side) { + if (cap == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) + return shippingInventory.cast(); + return LazyOptional.empty(); + } + + protected boolean canSupply() { + return isSupplier() && getInventory().canCreatePackage(); + } + + protected boolean canReceive() { + return isReceiver(); + } + + public ShippingInventory getInventory() { + return (ShippingInventory) shippingInventory.orElse(null); + } + + public class ConnectedInventory { + LazyOptional itemHandler; + CountedItemsList countedItems; + + public ConnectedInventory(LazyOptional inv) { + itemHandler = inv; + countedItems = makeList(inv); + } + + public CountedItemsList makeList(LazyOptional inv) { + return inv.isPresent() ? new CountedItemsList(inv.orElse(null)) : new CountedItemsList(); + } + + public List refresh() { + CountedItemsList newList = makeList(itemHandler); + List stacksToUpdate = countedItems.getStacksToUpdate(newList); + countedItems = newList; + allItems.add(itemHandler.orElse(null), countedItems); + return stacksToUpdate; + } + } + + protected abstract ShippingInventory createInventory(); + + public class ShippingInventory extends ItemStackHandler { + + static final int SHIPPING = 0; + static final int RECEIVING = 1; + boolean ships; + boolean receives; + + public ShippingInventory(boolean ships, boolean receives) { + super(2); + this.ships = ships; + this.receives = receives; + } + + @Override + public boolean isItemValid(int slot, ItemStack stack) { + if (slot == RECEIVING && receives) + return stack.getItem() instanceof CardboardBoxItem && CardboardBoxItem.matchAddress(stack, name); + return false; + } + + public boolean canCreatePackage() { + return getStackInSlot(SHIPPING).isEmpty() && ships; + } + + @Override + public ItemStack extractItem(int slot, int amount, boolean simulate) { + if (slot == RECEIVING) + return ItemStack.EMPTY; + return super.extractItem(slot, amount, simulate); + } + + public void createPackage(List contents, String address) { + ItemStack box = CardboardBoxItem.containing(contents); + CardboardBoxItem.addAddress(box, address); + setStackInSlot(SHIPPING, box); + } + + @Override + protected void onContentsChanged(int slot) { + super.onContentsChanged(slot); + markDirty(); + + if (slot == RECEIVING && !getStackInSlot(slot).isEmpty()) + tryInsertBox = true; + if (slot == SHIPPING && getStackInSlot(slot).isEmpty()) + checkTasks = true; + + BlockPos start = pos.offset(getBlockState().get(FACING).getOpposite()); + List toUpdate = LogisticalControllerBlock.collectCasings(world, start); + for (BlockPos blockPos : toUpdate) { + TileEntity tileEntity = world.getTileEntity(blockPos); + if (tileEntity == null) + continue; + tileEntity.getWorld().updateComparatorOutputLevel(blockPos, tileEntity.getBlockState().getBlock()); + } + } + + @Override + public CompoundNBT serializeNBT() { + CompoundNBT tag = super.serializeNBT(); + tag.putBoolean("Ships", ships); + tag.putBoolean("Receives", receives); + return tag; + } + + @Override + public void deserializeNBT(CompoundNBT nbt) { + ships = nbt.getBoolean("Ships"); + receives = nbt.getBoolean("Receives"); + super.deserializeNBT(nbt); + } + } + +} diff --git a/src/main/java/com/simibubi/create/modules/logistics/management/base/LogisticalTask.java b/src/main/java/com/simibubi/create/modules/logistics/management/base/LogisticalTask.java new file mode 100644 index 000000000..e18e3f265 --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/logistics/management/base/LogisticalTask.java @@ -0,0 +1,45 @@ +package com.simibubi.create.modules.logistics.management.base; + +import java.util.Arrays; +import java.util.List; + +import org.apache.commons.lang3.tuple.Pair; + +import com.simibubi.create.foundation.type.CountedItemsList.ItemStackEntry; + +import net.minecraft.item.ItemStack; +import net.minecraft.item.crafting.Ingredient; + +public abstract class LogisticalTask implements Comparable { + + public enum Priority { + HIGH, MEDIUM, LOW + } + + Priority priority = Priority.LOW; + public String targetAddress; + + @Override + public int compareTo(LogisticalTask o) { + return priority.compareTo(o.priority); + } + + public static class SupplyTask extends LogisticalTask { + public List> items; + + public SupplyTask(ItemStackEntry requested, String address) { + items = Arrays.asList(Pair.of(Ingredient.fromStacks(requested.stack), requested.amount)); + targetAddress = address; + } + + } + + public static class DepositTask extends LogisticalTask { + public ItemStack stack; + + public DepositTask(ItemStack stack) { + this.stack = stack.copy(); + } + } + +} diff --git a/src/main/java/com/simibubi/create/modules/logistics/management/base/LogisticalTileEntityExtension.java b/src/main/java/com/simibubi/create/modules/logistics/management/base/LogisticalTileEntityExtension.java new file mode 100644 index 000000000..a36ce42fb --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/logistics/management/base/LogisticalTileEntityExtension.java @@ -0,0 +1,13 @@ +package com.simibubi.create.modules.logistics.management.base; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +public class LogisticalTileEntityExtension { + + List tags = new ArrayList<>(); + UUID networkId; + LogisticalActor actor; + +} diff --git a/src/main/java/com/simibubi/create/modules/logistics/management/controller/CalculationTileEntity.java b/src/main/java/com/simibubi/create/modules/logistics/management/controller/CalculationTileEntity.java new file mode 100644 index 000000000..576bf50ce --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/logistics/management/controller/CalculationTileEntity.java @@ -0,0 +1,17 @@ +package com.simibubi.create.modules.logistics.management.controller; + +import com.simibubi.create.AllTileEntities; +import com.simibubi.create.modules.logistics.management.base.LogisticalInventoryControllerTileEntity; + +public class CalculationTileEntity extends LogisticalInventoryControllerTileEntity { + + public CalculationTileEntity() { + super(AllTileEntities.LOGISTICAL_CALCULATION_CONTROLLER.type); + } + + @Override + protected ShippingInventory createInventory() { + return new ShippingInventory(false, false); + } + +} diff --git a/src/main/java/com/simibubi/create/modules/logistics/management/controller/RequestTileEntity.java b/src/main/java/com/simibubi/create/modules/logistics/management/controller/RequestTileEntity.java new file mode 100644 index 000000000..6270e04d8 --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/logistics/management/controller/RequestTileEntity.java @@ -0,0 +1,31 @@ +package com.simibubi.create.modules.logistics.management.controller; + +import com.simibubi.create.AllTileEntities; +import com.simibubi.create.modules.logistics.management.base.LogisticalInventoryControllerTileEntity; + +public class RequestTileEntity extends LogisticalInventoryControllerTileEntity { + + public RequestTileEntity() { + super(AllTileEntities.LOGISTICAL_REQUEST_CONTROLLER.type); + } + + @Override + protected ShippingInventory createInventory() { + return new ShippingInventory(false, true); + } + + @Override + public void handleAdded() { + if (world.isRemote) + return; + if (getNetwork() != null) + return; + super.handleAdded(); + } + + @Override + public boolean isReceiver() { + return true; + } + +} diff --git a/src/main/java/com/simibubi/create/modules/logistics/management/controller/StorageTileEntity.java b/src/main/java/com/simibubi/create/modules/logistics/management/controller/StorageTileEntity.java new file mode 100644 index 000000000..8f4b445e8 --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/logistics/management/controller/StorageTileEntity.java @@ -0,0 +1,27 @@ +package com.simibubi.create.modules.logistics.management.controller; + +import com.simibubi.create.AllTileEntities; +import com.simibubi.create.modules.logistics.management.base.LogisticalInventoryControllerTileEntity; + +public class StorageTileEntity extends LogisticalInventoryControllerTileEntity { + + public StorageTileEntity() { + super(AllTileEntities.LOGISTICAL_STORAGE_CONTROLLER.type); + } + + @Override + protected ShippingInventory createInventory() { + return new ShippingInventory(true, true); + } + + @Override + public boolean isSupplier() { + return true; + } + + @Override + public boolean isReceiver() { + return true; + } + +} diff --git a/src/main/java/com/simibubi/create/modules/logistics/management/controller/SupplyTileEntity.java b/src/main/java/com/simibubi/create/modules/logistics/management/controller/SupplyTileEntity.java new file mode 100644 index 000000000..3b69dda1c --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/logistics/management/controller/SupplyTileEntity.java @@ -0,0 +1,22 @@ +package com.simibubi.create.modules.logistics.management.controller; + +import com.simibubi.create.AllTileEntities; +import com.simibubi.create.modules.logistics.management.base.LogisticalInventoryControllerTileEntity; + +public class SupplyTileEntity extends LogisticalInventoryControllerTileEntity { + + public SupplyTileEntity() { + super(AllTileEntities.LOGISTICAL_SUPPLY_CONTROLLER.type); + } + + @Override + protected ShippingInventory createInventory() { + return new ShippingInventory(true, false); + } + + @Override + public boolean isSupplier() { + return true; + } + +} diff --git a/src/main/java/com/simibubi/create/modules/logistics/management/controller/TransactionsTileEntity.java b/src/main/java/com/simibubi/create/modules/logistics/management/controller/TransactionsTileEntity.java new file mode 100644 index 000000000..da1f21090 --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/logistics/management/controller/TransactionsTileEntity.java @@ -0,0 +1,12 @@ +package com.simibubi.create.modules.logistics.management.controller; + +import com.simibubi.create.AllTileEntities; +import com.simibubi.create.modules.logistics.management.base.LogisticalControllerTileEntity; + +public class TransactionsTileEntity extends LogisticalControllerTileEntity { + + public TransactionsTileEntity() { + super(AllTileEntities.LOGISTICAL_TRANSATIONS_CONTROLLER.type); + } + +} diff --git a/src/main/java/com/simibubi/create/modules/logistics/management/index/IndexContainerUpdatePacket.java b/src/main/java/com/simibubi/create/modules/logistics/management/index/IndexContainerUpdatePacket.java new file mode 100644 index 000000000..6d6a9469c --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/logistics/management/index/IndexContainerUpdatePacket.java @@ -0,0 +1,95 @@ +package com.simibubi.create.modules.logistics.management.index; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.function.Supplier; + +import org.apache.commons.lang3.tuple.Pair; + +import com.simibubi.create.foundation.packet.SimplePacketBase; +import com.simibubi.create.foundation.type.CountedItemsList; +import com.simibubi.create.foundation.type.CountedItemsList.ItemStackEntry; + +import net.minecraft.client.Minecraft; +import net.minecraft.inventory.container.Container; +import net.minecraft.network.PacketBuffer; +import net.minecraft.util.math.BlockPos; +import net.minecraftforge.fml.network.NetworkEvent.Context; + +public class IndexContainerUpdatePacket extends SimplePacketBase { + + public enum Type { + INITIAL, UPDATE + } + + Type type; + List> items; + BlockPos pos; + + public IndexContainerUpdatePacket(Type type, String address, CountedItemsList items, BlockPos pos) { + this(type, Arrays.asList(Pair.of(address, items)), pos); + } + + public IndexContainerUpdatePacket(Type type, List> items, BlockPos pos) { + this.type = type; + this.items = items; + this.pos = pos; + } + + public IndexContainerUpdatePacket(PacketBuffer buffer) { + type = Type.values()[buffer.readInt()]; + int numControllers = buffer.readInt(); + items = new ArrayList<>(numControllers); + for (int i = 0; i < numControllers; i++) { + String address = buffer.readString(4096); + CountedItemsList itemList = new CountedItemsList(); + int numEntries = buffer.readInt(); + for (int j = 0; j < numEntries; j++) + itemList.add(buffer.readItemStack(), buffer.readInt()); + items.add(Pair.of(address, itemList)); + } + pos = buffer.readBlockPos(); + } + + @Override + public void write(PacketBuffer buffer) { + buffer.writeInt(type.ordinal()); + buffer.writeInt(items.size()); + for (Pair pair : items) { + buffer.writeString(pair.getKey(), 4096); + Collection entries = pair.getValue().getFlattenedList(); + buffer.writeInt(entries.size()); + for (ItemStackEntry entry : entries) { + buffer.writeItemStack(entry.stack); + buffer.writeInt(entry.amount); + } + } + buffer.writeBlockPos(pos); + } + + @Override + public void handle(Supplier context) { + context.get().enqueueWork(() -> { + Minecraft mc = Minecraft.getInstance(); + Container openContainer = mc.player.openContainer; + if (openContainer == null) + return; + if (!(openContainer instanceof LogisticalIndexContainer)) + return; + LogisticalIndexTileEntity te = (LogisticalIndexTileEntity) mc.world.getTileEntity(pos); + if (te == null) + return; + + if (type == Type.INITIAL) + te.index(items); + if (type == Type.UPDATE) + te.update(items); + + ((LogisticalIndexContainer) openContainer).refresh(); + }); + context.get().setPacketHandled(true); + } + +} diff --git a/src/main/java/com/simibubi/create/modules/logistics/management/index/IndexOrderRequest.java b/src/main/java/com/simibubi/create/modules/logistics/management/index/IndexOrderRequest.java new file mode 100644 index 000000000..d6e3aaaec --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/logistics/management/index/IndexOrderRequest.java @@ -0,0 +1,72 @@ +package com.simibubi.create.modules.logistics.management.index; + +import java.util.Collection; +import java.util.UUID; +import java.util.function.Supplier; + +import com.simibubi.create.Create; +import com.simibubi.create.foundation.packet.SimplePacketBase; +import com.simibubi.create.foundation.type.CountedItemsList; +import com.simibubi.create.foundation.type.CountedItemsList.ItemStackEntry; +import com.simibubi.create.modules.logistics.management.LogisticalNetwork; +import com.simibubi.create.modules.logistics.management.base.LogisticalTask.SupplyTask; + +import net.minecraft.entity.player.ServerPlayerEntity; +import net.minecraft.network.PacketBuffer; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.math.BlockPos; +import net.minecraftforge.fml.network.NetworkEvent.Context; + +public class IndexOrderRequest extends SimplePacketBase { + + String targetAddress; + UUID networkID; + CountedItemsList items; + BlockPos indexPos; + + public IndexOrderRequest(BlockPos indexPos, String targetAddress, CountedItemsList list, UUID networkID) { + this.targetAddress = targetAddress; + items = list; + this.networkID = networkID; + this.indexPos = indexPos; + } + + public IndexOrderRequest(PacketBuffer buffer) { + indexPos = buffer.readBlockPos(); + networkID = new UUID(buffer.readLong(), buffer.readLong()); + targetAddress = buffer.readString(4096); + items = new CountedItemsList(); + int numEntries = buffer.readInt(); + for (int j = 0; j < numEntries; j++) + items.add(buffer.readItemStack(), buffer.readInt()); + } + + @Override + public void write(PacketBuffer buffer) { + buffer.writeBlockPos(indexPos); + buffer.writeLong(networkID.getMostSignificantBits()); + buffer.writeLong(networkID.getLeastSignificantBits()); + buffer.writeString(targetAddress, 4096); + Collection entries = items.getFlattenedList(); + buffer.writeInt(entries.size()); + for (ItemStackEntry entry : entries) { + buffer.writeItemStack(entry.stack); + buffer.writeInt(entry.amount); + } + } + + @Override + public void handle(Supplier context) { + context.get().enqueueWork(() -> { + ServerPlayerEntity player = context.get().getSender(); + TileEntity tileEntity = player.getEntityWorld().getTileEntity(indexPos); + if (tileEntity != null && tileEntity instanceof LogisticalIndexTileEntity) + ((LogisticalIndexTileEntity) tileEntity).lastOrderAddress = targetAddress; + LogisticalNetwork networkByID = Create.logisticalNetworkHandler.getNetworkByID(player.getEntityWorld(), + networkID); + items.getFlattenedList().forEach(entry -> networkByID.enqueueTask(new SupplyTask(entry, targetAddress))); + }); + context.get().setPacketHandled(true); + } + +} diff --git a/src/main/java/com/simibubi/create/modules/logistics/management/index/LogisticalIndexBlock.java b/src/main/java/com/simibubi/create/modules/logistics/management/index/LogisticalIndexBlock.java new file mode 100644 index 000000000..6a48ae56d --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/logistics/management/index/LogisticalIndexBlock.java @@ -0,0 +1,157 @@ +package com.simibubi.create.modules.logistics.management.index; + +import com.simibubi.create.AllItems; +import com.simibubi.create.foundation.block.IBlockWithColorHandler; +import com.simibubi.create.foundation.block.IWithTileEntity; + +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.block.HorizontalBlock; +import net.minecraft.client.renderer.color.IBlockColor; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.entity.player.ServerPlayerEntity; +import net.minecraft.item.BlockItemUseContext; +import net.minecraft.item.ItemStack; +import net.minecraft.state.StateContainer.Builder; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.BlockRenderLayer; +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.ISelectionContext; +import net.minecraft.util.math.shapes.VoxelShape; +import net.minecraft.util.math.shapes.VoxelShapes; +import net.minecraft.world.IBlockReader; +import net.minecraft.world.IWorldReader; +import net.minecraft.world.World; +import net.minecraftforge.fml.network.NetworkHooks; + +public class LogisticalIndexBlock extends HorizontalBlock + implements IBlockWithColorHandler, IWithTileEntity { + + public static final VoxelShape SOUTH_SHAPE = makeCuboidShape(3, 1, -1, 13, 15, 3), + NORTH_SHAPE = makeCuboidShape(3, 1, 13, 13, 15, 17), EAST_SHAPE = makeCuboidShape(-1, 1, 3, 3, 15, 13), + WEST_SHAPE = makeCuboidShape(13, 1, 3, 17, 15, 13); + + public LogisticalIndexBlock() { + super(Properties.from(Blocks.GRANITE)); + } + + @Override + public boolean isValidPosition(BlockState state, IWorldReader worldIn, BlockPos pos) { + Direction facing = state.get(HORIZONTAL_FACING); + BlockPos offset = pos.offset(facing.getOpposite()); + BlockState blockState = worldIn.getBlockState(offset); + return !blockState.getMaterial().isReplaceable(); + } + + @Override + protected void fillStateContainer(Builder builder) { + builder.add(HORIZONTAL_FACING); + super.fillStateContainer(builder); + } + + @Override + public BlockRenderLayer getRenderLayer() { + return BlockRenderLayer.CUTOUT_MIPPED; + } + + @Override + public BlockState getStateForPlacement(BlockItemUseContext context) { + BlockState defaultState = getDefaultState(); + if (context.getFace().getAxis().isHorizontal()) + return defaultState.with(HORIZONTAL_FACING, context.getFace()); + return defaultState; + } + + @Override + public void neighborChanged(BlockState state, World worldIn, BlockPos pos, Block blockIn, BlockPos fromPos, + boolean isMoving) { + if (state.isValidPosition(worldIn, pos)) + return; + + TileEntity tileentity = state.hasTileEntity() ? worldIn.getTileEntity(pos) : null; + spawnDrops(state, worldIn, pos, tileentity); + worldIn.removeBlock(pos, false); + + for (Direction direction : Direction.values()) + worldIn.notifyNeighborsOfStateChange(pos.offset(direction), this); + } + + @Override + public boolean hasTileEntity(BlockState state) { + return true; + } + + @Override + public TileEntity createTileEntity(BlockState state, IBlockReader world) { + return new LogisticalIndexTileEntity(); + } + + @Override + public boolean onBlockActivated(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand handIn, + BlockRayTraceResult hit) { + if (AllItems.LOGISTICAL_DIAL.typeOf(player.getHeldItem(handIn))) { + return false; + } + + if (worldIn.isRemote) { + return true; + } else { + withTileEntityDo(worldIn, pos, te -> { + NetworkHooks.openGui((ServerPlayerEntity) player, te, te::sendToContainer); + }); + return true; + } + } + + @Override + public void onBlockPlacedBy(World worldIn, BlockPos pos, BlockState state, LivingEntity placer, ItemStack stack) { + if (!(placer instanceof PlayerEntity)) + return; + PlayerEntity player = (PlayerEntity) placer; + for (int slot = 0; slot < player.inventory.getSizeInventory(); slot++) { + ItemStack itemStack = player.inventory.getStackInSlot(slot); + if (!AllItems.LOGISTICAL_DIAL.typeOf(itemStack)) + continue; + if (!itemStack.hasTag()) + continue; + withTileEntityDo(worldIn, pos, te -> te.setNetworkId(itemStack.getTag().getUniqueId("NetworkID"))); + return; + } + } + + @Override + public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) { + Direction facing = state.get(HORIZONTAL_FACING); + + if (facing == Direction.EAST) + return EAST_SHAPE; + if (facing == Direction.WEST) + return WEST_SHAPE; + if (facing == Direction.NORTH) + return NORTH_SHAPE; + if (facing == Direction.SOUTH) + return SOUTH_SHAPE; + + return VoxelShapes.empty(); + } + + @Override + public IBlockColor getColorHandler() { + return (state, world, pos, layer) -> { + if (layer == 0) { + LogisticalIndexTileEntity tileEntity = getTileEntity(world, pos); + if (tileEntity == null) + return 0; + return tileEntity.getColor(); + } + + return 0; + }; + } + +} diff --git a/src/main/java/com/simibubi/create/modules/logistics/management/index/LogisticalIndexContainer.java b/src/main/java/com/simibubi/create/modules/logistics/management/index/LogisticalIndexContainer.java new file mode 100644 index 000000000..e0ddcf8c3 --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/logistics/management/index/LogisticalIndexContainer.java @@ -0,0 +1,63 @@ +package com.simibubi.create.modules.logistics.management.index; + +import com.simibubi.create.AllContainers; +import com.simibubi.create.foundation.type.CombinedCountedItemsList; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.world.ClientWorld; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.entity.player.PlayerInventory; +import net.minecraft.entity.player.ServerPlayerEntity; +import net.minecraft.inventory.container.Container; +import net.minecraft.item.ItemStack; +import net.minecraft.network.PacketBuffer; + +public class LogisticalIndexContainer extends Container { + + public LogisticalIndexTileEntity te; + public CombinedCountedItemsList allItems = new CombinedCountedItemsList<>(); + + public LogisticalIndexContainer(int id, PlayerInventory inv, PacketBuffer extraData) { + super(AllContainers.LOGISTICAL_INDEX.type, id); + ClientWorld world = Minecraft.getInstance().world; + this.te = (LogisticalIndexTileEntity) world.getTileEntity(extraData.readBlockPos()); + this.te.handleUpdateTag(extraData.readCompoundTag()); + init(); + } + + public LogisticalIndexContainer(int id, PlayerInventory inv, LogisticalIndexTileEntity te) { + super(AllContainers.LOGISTICAL_INDEX.type, id); + this.te = te; + init(); + te.addPlayer((ServerPlayerEntity) inv.player); + } + + private void init() { + detectAndSendChanges(); + } + + @Override + public void onContainerClosed(PlayerEntity playerIn) { + if (!te.getWorld().isRemote) + te.removePlayer((ServerPlayerEntity) playerIn); + else + te.controllers.clear(); + super.onContainerClosed(playerIn); + } + + @Override + public ItemStack transferStackInSlot(PlayerEntity playerIn, int index) { + return ItemStack.EMPTY; + } + + @Override + public boolean canInteractWith(PlayerEntity playerIn) { + return true; + } + + public void refresh() { + allItems.clear(); + te.controllers.forEach(allItems::add); + } + +} diff --git a/src/main/java/com/simibubi/create/modules/logistics/management/index/LogisticalIndexScreen.java b/src/main/java/com/simibubi/create/modules/logistics/management/index/LogisticalIndexScreen.java new file mode 100644 index 000000000..0137bb0c0 --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/logistics/management/index/LogisticalIndexScreen.java @@ -0,0 +1,645 @@ +package com.simibubi.create.modules.logistics.management.index; + +import static com.simibubi.create.ScreenResources.DISABLED_SLOT_FRAME; +import static com.simibubi.create.ScreenResources.DISABLED_SLOT_INNER; +import static com.simibubi.create.ScreenResources.ICON_CONFIRM; +import static com.simibubi.create.ScreenResources.INDEX_BOTTOM; +import static com.simibubi.create.ScreenResources.INDEX_BOTTOM_TRIM; +import static com.simibubi.create.ScreenResources.INDEX_MIDDLE; +import static com.simibubi.create.ScreenResources.INDEX_SCROLLER_BOTTOM; +import static com.simibubi.create.ScreenResources.INDEX_SCROLLER_MIDDLE; +import static com.simibubi.create.ScreenResources.INDEX_SCROLLER_TOP; +import static com.simibubi.create.ScreenResources.INDEX_SEARCH; +import static com.simibubi.create.ScreenResources.INDEX_SEARCH_OVERLAY; +import static com.simibubi.create.ScreenResources.INDEX_TAB; +import static com.simibubi.create.ScreenResources.INDEX_TAB_ACTIVE; +import static com.simibubi.create.ScreenResources.INDEX_TOP; +import static com.simibubi.create.ScreenResources.INDEX_TOP_TRIM; +import static com.simibubi.create.ScreenResources.SLOT_FRAME; +import static com.simibubi.create.ScreenResources.SLOT_INNER; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.UUID; +import java.util.stream.Collectors; + +import javax.annotation.Nullable; + +import org.lwjgl.glfw.GLFW; + +import com.mojang.blaze3d.platform.GlStateManager; +import com.simibubi.create.AllPackets; +import com.simibubi.create.ScreenResources; +import com.simibubi.create.foundation.gui.AbstractSimiContainerScreen; +import com.simibubi.create.foundation.gui.ScreenElementRenderer; +import com.simibubi.create.foundation.gui.widgets.IconButton; +import com.simibubi.create.foundation.gui.widgets.InterpolatedChasingValue; +import com.simibubi.create.foundation.gui.widgets.ScrollInput; +import com.simibubi.create.foundation.gui.widgets.SelectionScrollInput; +import com.simibubi.create.foundation.type.CountedItemsList; +import com.simibubi.create.foundation.type.CountedItemsList.ItemStackEntry; +import com.simibubi.create.foundation.utility.ColorHelper; +import com.simibubi.create.foundation.utility.Lang; + +import net.minecraft.block.Blocks; +import net.minecraft.client.GameSettings; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.widget.TextFieldWidget; +import net.minecraft.client.renderer.BufferBuilder; +import net.minecraft.client.renderer.RenderHelper; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.client.util.InputMappings; +import net.minecraft.entity.player.PlayerInventory; +import net.minecraft.item.ItemStack; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.text.ITextComponent; + +public class LogisticalIndexScreen extends AbstractSimiContainerScreen { + + protected LogisticalIndexContainer container; + protected IconButton orderButton; + + boolean searchActive = false; + boolean searchHovered = false; + InterpolatedChasingValue searchButtonOffset; + TextFieldWidget searchTextField; + String searchKey = ""; + + TextFieldWidget receiverTextField; + ScrollInput receiverScrollInput; + List receivers = new ArrayList<>(); + + int cursorPos = 0; + boolean cursorActive = false; + InterpolatedChasingValue cursorLight; + + List displayedItems = new ArrayList<>(); + CountedItemsList order = new CountedItemsList(); + String initialTargetAddress; + + String title = Lang.translate("gui.index.title"); + String receiverScrollInputTitle = Lang.translate("gui.index.targetAddressSelect"); + String orderButtonTooltip = Lang.translate("gui.index.confirmOrder"); + String keyNumberInventories = "gui.index.numberIndexedInventories"; + ItemStack chestIcon = new ItemStack(Blocks.CHEST); + + public LogisticalIndexScreen(LogisticalIndexContainer container, PlayerInventory inv, ITextComponent title) { + super(container, inv, title); + this.container = container; + cursorLight = new InterpolatedChasingValue().withSpeed(.25f); + searchButtonOffset = new InterpolatedChasingValue().withSpeed(.5f); + receivers = container.te.availableReceivers; + initialTargetAddress = container.te.lastOrderAddress; + buildDisplayedItems(); + } + + @Override + protected void init() { + int height = INDEX_TOP.height + INDEX_TOP_TRIM.height + INDEX_MIDDLE.height + INDEX_BOTTOM_TRIM.height + + INDEX_BOTTOM.height; + int width = INDEX_MIDDLE.width; + setWindowSize(width, height); + super.init(); + widgets.clear(); + + searchTextField = new TextFieldWidget(font, guiLeft + 23, guiTop + 8, 128, 8, ""); + searchTextField.setTextColor(0xFFFFFF); + searchTextField.setDisabledTextColour(-1); + searchTextField.setEnableBackgroundDrawing(false); + searchTextField.setMaxStringLength(256); + searchTextField.func_212954_a(this::onSearchKeyChanged); + searchTextField.setFocused2(false); + + receiverTextField = new TextFieldWidget(font, guiLeft + 29, guiTop + 240, 116, 8, ""); + receiverTextField.setTextColor(0xFFFFFF); + receiverTextField.setDisabledTextColour(-1); + receiverTextField.setEnableBackgroundDrawing(false); + receiverTextField.setMaxStringLength(256); + receiverTextField.func_212954_a(this::onReceiverTextChanged); + if (initialTargetAddress != null) + receiverTextField.setText(initialTargetAddress); + receiverTextField.setFocused2(false); + + receiverScrollInput = new SelectionScrollInput(guiLeft + 24, guiTop + 235, 126, 18).forOptions(receivers) + .titled(receiverScrollInputTitle).calling(this::onReceiverScrollInputChanged); + + orderButton = new IconButton(guiLeft + 152, guiTop + 235, ICON_CONFIRM); + orderButton.active = false; + orderButton.setToolTip(orderButtonTooltip); + + widgets.add(receiverTextField); + widgets.add(receiverScrollInput); + widgets.add(orderButton); + + if (searchActive) + widgets.add(searchTextField); + } + + @Override + public void tick() { + super.tick(); + + float targetOffset = 0.75f; + if (searchTextField.isFocused()) + targetOffset = 1.5f; + else if (searchHovered || searchActive) + targetOffset = 1f; + searchButtonOffset.target(targetOffset); + searchButtonOffset.tick(); + + if (cursorActive) { + cursorLight.target(1); + cursorLight.tick(); + } else { + cursorLight.set(0); + } + + if (!searchActive && searchTextField.isFocused()) + searchTextField.changeFocus(false); + + if (container.te.update) { + buildDisplayedItems(); + container.te.update = false; + } + + } + + private void updateSubmitButton() { + orderButton.active = canSubmit(); + } + + public boolean canSubmit() { + return !order.getFlattenedList().isEmpty() + && container.te.availableReceivers.contains(receiverTextField.getText()); + } + + private void onSearchKeyChanged(String newSearch) { + if (searchKey.equals(newSearch)) + return; + searchKey = new String(newSearch); + buildDisplayedItems(); + } + + private void sendRequest() { + String address = receiverTextField.getText(); + UUID id = container.te.getNetworkId(); + AllPackets.channel.sendToServer(new IndexOrderRequest(container.te.getPos(), address, order, id)); + order = new CountedItemsList(); + updateSubmitButton(); + } + + private void onReceiverTextChanged(String newSearch) { + if (!receiverTextField.isFocused()) + return; + receiverScrollInput.setState(0); + receivers = container.te.availableReceivers.stream() + .filter(str -> str.toLowerCase().startsWith(newSearch.toLowerCase())).collect(Collectors.toList()); + ((SelectionScrollInput) receiverScrollInput).forOptions(receivers); + receiverScrollInput.active = !receivers.isEmpty(); + if (receivers.isEmpty() || newSearch.isEmpty()) + receiverTextField.setSuggestion(null); + else + receiverTextField.setSuggestion(receivers.get(0).substring(newSearch.length())); + updateSubmitButton(); + } + + private void onReceiverScrollInputChanged(int index) { + String address = receivers.get(index); + receiverTextField.func_212954_a(null); + receiverTextField.setSuggestion(null); + receiverTextField.setText(address); + receiverTextField.func_212954_a(this::onReceiverTextChanged); + updateSubmitButton(); + } + + public void buildDisplayedItems() { + if (searchKey.isEmpty()) { + displayedItems = container.allItems.get().getFlattenedList().stream().collect(Collectors.toList()); + } else { + displayedItems = container.allItems + .get().getFlattenedList().parallelStream().filter(entry -> entry.stack.getDisplayName() + .getUnformattedComponentText().toLowerCase().startsWith(searchKey.toLowerCase())) + .collect(Collectors.toList()); + } + if (cursorActive) + moveCursor(cursorPos); + } + + @Override + public boolean mouseClicked(double x, double y, int button) { + if (searchHovered && button == 0) { + setSearchActive(!searchActive); + return true; + } + + if (orderButton.isHovered() && orderButton.active) { + sendRequest(); + return true; + } + + return super.mouseClicked(x, y, button); + } + + @Override + public void mouseMoved(double xPos, double yPos) { + + super.mouseMoved(xPos, yPos); + } + + private void setSearchActive(boolean searchActive) { + this.searchActive = searchActive; + if (searchActive) { + cursorActive = false; + searchTextField.setSelectionPos(0); + searchTextField.changeFocus(true); + widgets.add(searchTextField); + } else { + widgets.remove(searchTextField); + onSearchKeyChanged(""); + } + } + + @Override + public boolean keyPressed(int code, int p_keyPressed_2_, int p_keyPressed_3_) { + InputMappings.Input mouseKey = InputMappings.getInputByCode(code, p_keyPressed_2_); + boolean receiverFocused = receiverTextField.isFocused(); + boolean searchFocused = searchTextField.isFocused(); + boolean space = code == GLFW.GLFW_KEY_SPACE; + boolean enter = code == GLFW.GLFW_KEY_ENTER; + boolean writingText = receiverFocused || searchFocused; + boolean closingScreen = this.minecraft.gameSettings.keyBindInventory.isActiveAndMatches(mouseKey); + + if (closingScreen && writingText) { + return true; + } + + if (canSubmit() && hasShiftDown() && enter) { + sendRequest(); + return true; + } + + if (enter && searchActive && searchFocused) { + searchTextField.changeFocus(false); + searchTextField.setCursorPositionEnd(); + searchTextField.setSelectionPos(searchTextField.getCursorPosition()); + + cursorActive = true; + cursorPos = 0; + + if (searchTextField.getText().isEmpty()) + setSearchActive(false); + + return true; + } + + if (enter && !writingText && cursorActive) { + ItemStackEntry entry = displayedItems.get(cursorPos); + if (!order.contains(entry.stack)) { + if (order.getFlattenedList().size() > 4) + return true; + order.add(entry); + } else + order.remove(entry.stack); + updateSubmitButton(); + return true; + } + + if (space && !writingText) { + setSearchActive(true); + return true; + } + + boolean up = code == GLFW.GLFW_KEY_UP; + boolean left = code == GLFW.GLFW_KEY_LEFT; + boolean down = code == GLFW.GLFW_KEY_DOWN; + boolean right = code == GLFW.GLFW_KEY_RIGHT; + boolean tab = code == GLFW.GLFW_KEY_TAB; + + if (!writingText && tab) { + receiverTextField.setCursorPositionEnd(); + receiverTextField.setSelectionPos(0); + receiverTextField.changeFocus(true); + } + + if (receiverFocused) { + if (enter) { + receiverTextField.changeFocus(false); + } + if (tab) { + if (receivers.isEmpty()) + return false; + receiverTextField.setText(receivers.get(0)); + return true; + } + if (up || down) { + receiverScrollInput.setState(receiverScrollInput.getState() + (up ? -1 : 1)); + receiverScrollInput.onChanged(); + return true; + } + } + + if (!writingText) { + GameSettings keys = minecraft.gameSettings; + boolean w = keys.keyBindForward.getKey().getKeyCode() == code || up; + boolean a = keys.keyBindLeft.getKey().getKeyCode() == code || left; + boolean s = keys.keyBindBack.getKey().getKeyCode() == code || down; + boolean d = keys.keyBindRight.getKey().getKeyCode() == code || right; + boolean any = w || a || s || d; + + if (any && !cursorActive) { + cursorActive = true; + return true; + } + + if (any) { + int offset = w ? -8 : a ? -1 : s ? 8 : d ? 1 : 0; + if (hasShiftDown()) { + offset *= 4; + if (a || d) { + int col = cursorPos % 8; + offset = MathHelper.clamp(offset, -col, 7 - col); + } + } + moveCursor(cursorPos + offset); + return true; + } + + } + + return super.keyPressed(code, p_keyPressed_2_, p_keyPressed_3_); + } + + protected void moveCursor(int slot) { + int clamp = MathHelper.clamp(slot, 0, slotsVisible() - 1); + if (cursorPos != clamp) + cursorLight.set(0).set(0); + cursorPos = clamp; + } + + protected int slotsVisible() { + return displayedItems.size(); + } + + @Override + protected void renderWindow(int mouseX, int mouseY, float partialTicks) { + applyNetworkColor(); + + // Search bar + searchHovered = (mouseX > guiLeft - 25 && mouseX < guiLeft && mouseY > guiTop + 6 && mouseY < guiTop + 31); + GlStateManager.pushMatrix(); + GlStateManager.translatef(searchButtonOffset.get(partialTicks) * -14, 0, 0); + INDEX_SEARCH.draw(this, guiLeft - 5, guiTop + 8); + GlStateManager.popMatrix(); + + INDEX_MIDDLE.draw(this, guiLeft, guiTop + INDEX_TOP.height + 6); + renderScrollbar(); + renderTabs(); + resetColor(); + renderSlots(); + } + + @Override + public boolean charTyped(char character, int code) { + if (!searchActive && !receiverTextField.isFocused()) + return false; + if (character == ' ' && (searchTextField.getText().isEmpty() + || searchTextField.getSelectedText().equals(searchTextField.getText()))) + return false; + return super.charTyped(character, code); + } + + @Override + protected void renderWindowForeground(int mouseX, int mouseY, float partialTicks) { + resetColor(); + INDEX_TOP_TRIM.draw(this, guiLeft, guiTop + INDEX_TOP.height); + INDEX_BOTTOM_TRIM.draw(this, guiLeft, guiTop + INDEX_TOP.height + INDEX_MIDDLE.height + 6); + applyNetworkColor(); + INDEX_TOP.draw(this, guiLeft, guiTop); + INDEX_BOTTOM.draw(this, guiLeft, guiTop + INDEX_TOP.height + INDEX_MIDDLE.height + 12); + + if (searchActive) { + INDEX_SEARCH_OVERLAY.draw(this, guiLeft - 1, guiTop + 2); + resetColor(); + + } else { + resetColor(); + int offset = (INDEX_TOP.width - font.getStringWidth(title)) / 2; + font.drawStringWithShadow(title, guiLeft + offset, guiTop + 8, + ColorHelper.mixColors(0xFFFFFF, container.te.getColor(), .25f)); + } + + orderButton.render(mouseX, mouseY, partialTicks); + if (searchActive) + searchTextField.render(mouseX, mouseY, partialTicks); + receiverTextField.render(mouseX, mouseY, partialTicks); + + renderOrderedItems(); + ScreenElementRenderer.render3DItem(() -> { + GlStateManager.translated(guiLeft + 6.5, guiTop + 235, 0); + return chestIcon; + }); + + super.renderWindowForeground(mouseX, mouseY, partialTicks); + } + + private void renderOrderedItems() { + Collection flattenedList = order.getFlattenedList(); + + int slotX = guiLeft + (getXSize() - flattenedList.size() * 18) / 2; + int slotY = guiTop + 215; + + for (ItemStackEntry entry : flattenedList) { + RenderHelper.enableGUIStandardItemLighting(); + GlStateManager.enableDepthTest(); + GlStateManager.pushMatrix(); + GlStateManager.translatef(0.0F, 0.0F, 32.0F); + this.blitOffset = 200; + this.itemRenderer.zLevel = 200.0F; + net.minecraft.client.gui.FontRenderer font = entry.stack.getItem().getFontRenderer(entry.stack); + if (font == null) + font = this.font; + this.itemRenderer.renderItemAndEffectIntoGUI(entry.stack, slotX, slotY); + this.renderItemOverlayIntoGUI(font, entry.stack, slotX, slotY, + entry.amount > 1 ? String.valueOf(entry.amount) : null, 0xFFFFFF); + this.blitOffset = 0; + this.itemRenderer.zLevel = 0.0F; + GlStateManager.popMatrix(); + slotX += 18; + } + } + + private void renderSlots() { + int slot = 0; + for (ItemStackEntry entry : displayedItems) { + resetColor(); + RenderHelper.enableGUIStandardItemLighting(); + renderSlot(slot, entry.stack, entry.amount); + slot++; + } + } + + private void renderSlot(int slot, ItemStack stack, int count) { + int slotX = getSlotX(slot); + int slotY = getSlotY(slot); + +// boolean ordered = order.contains(stack); + boolean orderedFully = order.getItemCount(stack) == count; + + if (orderedFully) { + DISABLED_SLOT_FRAME.draw(this, slotX, slotY); + DISABLED_SLOT_INNER.draw(this, slotX, slotY); + } else { + SLOT_FRAME.draw(this, slotX, slotY); + SLOT_INNER.draw(this, slotX, slotY); + } + + if (cursorActive && slot == cursorPos) { + renderCursor(); + } + + slotX++; + slotY++; + + GlStateManager.pushMatrix(); + GlStateManager.translatef(0.0F, 0.0F, 32.0F); + this.blitOffset = 200; + this.itemRenderer.zLevel = 200.0F; + net.minecraft.client.gui.FontRenderer font = stack.getItem().getFontRenderer(stack); + if (font == null) + font = this.font; + this.itemRenderer.renderItemAndEffectIntoGUI(stack, slotX, slotY); + + String text = count > 1 ? String.valueOf(count) : null; + int color = 0xFFFFFF; + if (orderedFully) { + color = ColorHelper.mixColors(container.te.getColor(), 0, 0.5f); + text = "0"; + } + + this.renderItemOverlayIntoGUI(font, stack, slotX, slotY, text, color); + this.blitOffset = 0; + this.itemRenderer.zLevel = 0.0F; + GlStateManager.popMatrix(); + } + + public int getSlotY(int slot) { + return guiTop + 28 + 18 * (slot / 8); + } + + public int getSlotX(int slot) { + return guiLeft + 15 + 18 * (slot % 8); + } + + private void renderScrollbar() { + INDEX_SCROLLER_TOP.draw(this, guiLeft + 173, guiTop + 31); + INDEX_SCROLLER_MIDDLE.draw(this, guiLeft + 173, guiTop + 37); + INDEX_SCROLLER_BOTTOM.draw(this, guiLeft + 173, guiTop + 43); + } + + private void renderTabs() { + INDEX_TAB.draw(this, guiLeft - 19, guiTop + 40); + INDEX_TAB_ACTIVE.draw(this, guiLeft - 19, guiTop + 61); + INDEX_TAB.draw(this, guiLeft - 19, guiTop + 82); + INDEX_TAB.draw(this, guiLeft - 19, guiTop + 103); + } + + public void resetColor() { + ColorHelper.glResetColor(); + } + + public void applyNetworkColor() { + ColorHelper.glColor(container.te.getColor()); + } + + private void renderCursor() { + if (!cursorActive) + return; + int x = getSlotX(cursorPos); + int y = getSlotY(cursorPos); + + float pt = minecraft.getRenderPartialTicks(); + GlStateManager.enableBlend(); + GlStateManager.color4f(1, 1, 1, cursorLight.get(pt)); + ScreenResources.SELECTED_SLOT_INNER.draw(this, x, y); + resetColor(); + } + + public void renderItemOverlayIntoGUI(FontRenderer fr, ItemStack stack, int xPosition, int yPosition, + @Nullable String text, int textColor) { + if (!stack.isEmpty()) { + if (stack.getItem().showDurabilityBar(stack)) { + GlStateManager.disableLighting(); + GlStateManager.disableDepthTest(); + GlStateManager.disableTexture(); + GlStateManager.disableAlphaTest(); + GlStateManager.disableBlend(); + Tessellator tessellator = Tessellator.getInstance(); + BufferBuilder bufferbuilder = tessellator.getBuffer(); + double health = stack.getItem().getDurabilityForDisplay(stack); + int i = Math.round(13.0F - (float) health * 13.0F); + int j = stack.getItem().getRGBDurabilityForDisplay(stack); + this.draw(bufferbuilder, xPosition + 2, yPosition + 13, 13, 2, 0, 0, 0, 255); + this.draw(bufferbuilder, xPosition + 2, yPosition + 13, i, 1, j >> 16 & 255, j >> 8 & 255, j & 255, + 255); + GlStateManager.enableBlend(); + GlStateManager.enableAlphaTest(); + GlStateManager.enableTexture(); + GlStateManager.enableLighting(); + GlStateManager.enableDepthTest(); + } + + if (stack.getCount() != 1 || text != null) { + String s = text == null ? String.valueOf(stack.getCount()) : text; + GlStateManager.disableLighting(); + GlStateManager.disableDepthTest(); + GlStateManager.disableBlend(); + GlStateManager.pushMatrix(); + + int guiScaleFactor = (int) minecraft.mainWindow.getGuiScaleFactor(); + GlStateManager.translated((float) (xPosition + 16.5f), (float) (yPosition + 16.5f), 0); + + double scale = 1; + switch (guiScaleFactor) { + case 1: + scale = 2060 / 2048d; + break; + case 2: + scale = .5; + break; + case 3: + scale = .675; + break; + case 4: + scale = .75; + break; + default: + scale = ((float) guiScaleFactor - 1) / guiScaleFactor; + } + + GlStateManager.scaled(scale, scale, 0); + GlStateManager.translated(-fr.getStringWidth(s) - (guiScaleFactor > 1 ? 0 : -.5f), + -font.FONT_HEIGHT + (guiScaleFactor > 1 ? 1 : 1.75f), 0); + fr.drawStringWithShadow(s, 0, 0, textColor); + + GlStateManager.popMatrix(); + GlStateManager.enableBlend(); + GlStateManager.enableLighting(); + GlStateManager.enableDepthTest(); + GlStateManager.enableBlend(); + } + } + } + + private void draw(BufferBuilder renderer, int x, int y, int width, int height, int red, int green, int blue, + int alpha) { + renderer.begin(7, DefaultVertexFormats.POSITION_COLOR); + renderer.pos((double) (x + 0), (double) (y + 0), 0.0D).color(red, green, blue, alpha).endVertex(); + renderer.pos((double) (x + 0), (double) (y + height), 0.0D).color(red, green, blue, alpha).endVertex(); + renderer.pos((double) (x + width), (double) (y + height), 0.0D).color(red, green, blue, alpha).endVertex(); + renderer.pos((double) (x + width), (double) (y + 0), 0.0D).color(red, green, blue, alpha).endVertex(); + Tessellator.getInstance().draw(); + } + +} diff --git a/src/main/java/com/simibubi/create/modules/logistics/management/index/LogisticalIndexTileEntity.java b/src/main/java/com/simibubi/create/modules/logistics/management/index/LogisticalIndexTileEntity.java new file mode 100644 index 000000000..0c66c77d3 --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/logistics/management/index/LogisticalIndexTileEntity.java @@ -0,0 +1,214 @@ +package com.simibubi.create.modules.logistics.management.index; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.commons.lang3.tuple.Pair; + +import com.simibubi.create.AllPackets; +import com.simibubi.create.AllTileEntities; +import com.simibubi.create.foundation.type.CountedItemsList; +import com.simibubi.create.foundation.type.CountedItemsList.ItemStackEntry; +import com.simibubi.create.modules.logistics.management.LogisticalNetwork; +import com.simibubi.create.modules.logistics.management.base.LogisticalControllerTileEntity; +import com.simibubi.create.modules.logistics.management.base.LogisticalInventoryControllerTileEntity; +import com.simibubi.create.modules.logistics.management.index.IndexContainerUpdatePacket.Type; + +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.entity.player.PlayerInventory; +import net.minecraft.entity.player.ServerPlayerEntity; +import net.minecraft.inventory.container.Container; +import net.minecraft.inventory.container.INamedContainerProvider; +import net.minecraft.nbt.CompoundNBT; +import net.minecraft.nbt.INBT; +import net.minecraft.nbt.ListNBT; +import net.minecraft.nbt.StringNBT; +import net.minecraft.network.PacketBuffer; +import net.minecraft.util.text.ITextComponent; +import net.minecraft.util.text.StringTextComponent; +import net.minecraftforge.common.util.Constants.NBT; +import net.minecraftforge.fml.network.PacketDistributor; + +public class LogisticalIndexTileEntity extends LogisticalControllerTileEntity implements INamedContainerProvider { + + // Server + public int nextPush; + public Set playersEntered = new HashSet<>(); + protected Set playersUsing = new HashSet<>(); + protected List> controllersToUpdate = new LinkedList<>(); + + // Both + public String lastOrderAddress = null; + protected Map controllers = new HashMap<>(); + + // Client + public boolean update = false; + public List availableReceivers = new ArrayList<>(); + + public LogisticalIndexTileEntity() { + super(AllTileEntities.LOGISTICAL_INDEX.type); + nextPush = 0; + } + + @Override + public CompoundNBT write(CompoundNBT compound) { + if (lastOrderAddress != null) + compound.putString("LastAdress", lastOrderAddress); + return super.write(compound); + } + + @Override + public void read(CompoundNBT compound) { + if (compound.contains("LastAdress")) + lastOrderAddress = compound.getString("LastAdress"); + super.read(compound); + } + + @Override + public CompoundNBT writeToClient(CompoundNBT tag) { + ListNBT receivers = new ListNBT(); + availableReceivers.forEach(s -> receivers.add(new StringNBT(s))); + tag.put("Receivers", receivers); + return super.writeToClient(tag); + } + + @Override + public void readClientUpdate(CompoundNBT tag) { + availableReceivers.clear(); + for (INBT inbt : tag.getList("Receivers", NBT.TAG_STRING)) + availableReceivers.add(((StringNBT) inbt).getString()); + update = true; + super.readClientUpdate(tag); + } + + public void syncReceivers() { + if (network == null) + return; + availableReceivers.clear(); + for (LogisticalControllerTileEntity logisticalControllerTileEntity : network.receivers) + availableReceivers.add(logisticalControllerTileEntity.getName()); + sendData(); + } + + @Override + protected void initialize() { + super.initialize(); + syncReceivers(); + } + + @Override + public void tick() { + super.tick(); + + if (nextPush == 1) + pushItems(); + + if (nextPush > 0) + nextPush--; + } + + @Override + // Prevents the inherited TESR + public double getMaxRenderDistanceSquared() { + return 0; + } + + @Override + public Container createMenu(int id, PlayerInventory inv, PlayerEntity player) { + return new LogisticalIndexContainer(id, inv, this); + } + + @Override + public ITextComponent getDisplayName() { + return new StringTextComponent(getType().getRegistryName().toString()); + } + + public void sendToContainer(PacketBuffer buffer) { + buffer.writeBlockPos(getPos()); + buffer.writeCompoundTag(getUpdateTag()); + } + + public void addPlayer(ServerPlayerEntity player) { + nextPush = 5; + playersEntered.add(player); + playersUsing.add(player); + } + + public void removePlayer(ServerPlayerEntity player) { + playersUsing.remove(player); + if (playersUsing.isEmpty()) + controllers.clear(); + } + + public void handleUpdatedController(String address, CountedItemsList updates) { + if (playersUsing.isEmpty()) + return; + controllersToUpdate.add(Pair.of(address, updates)); + if (nextPush == 0) + nextPush = 5; + } + + private void pushItems() { + LogisticalNetwork network = this.getNetwork(); + if (network == null) + return; + + // First player to open + if (!playersEntered.isEmpty() && playersUsing.size() == playersEntered.size()) { + controllers.clear(); + for (LogisticalControllerTileEntity te : network.suppliers) { + if (!(te instanceof LogisticalInventoryControllerTileEntity)) + continue; + CountedItemsList allItems = ((LogisticalInventoryControllerTileEntity) te).getAllItems(); + controllers.put(te.getName(), allItems); + } + } + + // Initial Packets + if (!playersEntered.isEmpty()) { + controllers.forEach((address, items) -> { + for (ServerPlayerEntity player : playersUsing) + AllPackets.channel.send(PacketDistributor.PLAYER.with(() -> player), + new IndexContainerUpdatePacket(Type.INITIAL, address, items, pos)); + }); + playersEntered.clear(); + } + + // pending Incremental Updates + if (!playersUsing.isEmpty() && !controllersToUpdate.isEmpty()) { + for (Pair pair : controllersToUpdate) { + CountedItemsList list = controllers.getOrDefault(pair.getKey(), new CountedItemsList()); + pair.getValue().getFlattenedList().forEach(list::add); + } + for (ServerPlayerEntity player : playersUsing) + AllPackets.channel.send(PacketDistributor.PLAYER.with(() -> player), + new IndexContainerUpdatePacket(Type.UPDATE, controllersToUpdate, pos)); + controllersToUpdate.clear(); + } + } + + public void index(List> items) { + items.forEach(pair -> { + controllers.put(pair.getKey(), pair.getValue()); + }); + update = true; + } + + public void update(List> items) { + for (Pair pair : items) { + if (!controllers.containsKey(pair.getKey())) + return; + CountedItemsList list = controllers.get(pair.getKey()); + for (ItemStackEntry entry : pair.getValue().getFlattenedList()) { + list.setItemCount(entry.stack, entry.amount); + } + } + update = true; + } + +} diff --git a/src/main/java/com/simibubi/create/modules/logistics/packet/ConfigureFlexcratePacket.java b/src/main/java/com/simibubi/create/modules/logistics/packet/ConfigureFlexcratePacket.java index a865a46b8..27b6aecc9 100644 --- a/src/main/java/com/simibubi/create/modules/logistics/packet/ConfigureFlexcratePacket.java +++ b/src/main/java/com/simibubi/create/modules/logistics/packet/ConfigureFlexcratePacket.java @@ -1,7 +1,7 @@ package com.simibubi.create.modules.logistics.packet; import com.simibubi.create.foundation.packet.TileEntityConfigurationPacket; -import com.simibubi.create.modules.logistics.block.FlexcrateTileEntity; +import com.simibubi.create.modules.logistics.block.inventories.FlexcrateTileEntity; import net.minecraft.network.PacketBuffer; import net.minecraft.util.math.BlockPos; diff --git a/src/main/resources/assets/create/blockstates/logistical_casing.json b/src/main/resources/assets/create/blockstates/logistical_casing.json new file mode 100644 index 000000000..79f130362 --- /dev/null +++ b/src/main/resources/assets/create/blockstates/logistical_casing.json @@ -0,0 +1,20 @@ +{ + "forge_marker": 1, + "variants": { + "active": { + "true": {}, + "false": {} + }, + "part": { + "none": { "model": "create:block/logistical_casing" }, + "start": { "model": "create:block/logistical_casing_start" }, + "middle": { "model": "create:block/logistical_casing_middle" }, + "end": { "model": "create:block/logistical_casing_end" } + }, + "axis": { + "y": {}, + "x": { "x": 90, "y": 90 }, + "z": { "x": 270 } + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/create/blockstates/logistical_controller.json b/src/main/resources/assets/create/blockstates/logistical_controller.json new file mode 100644 index 000000000..be2a52a7d --- /dev/null +++ b/src/main/resources/assets/create/blockstates/logistical_controller.json @@ -0,0 +1,23 @@ +{ + "forge_marker": 1, + "defaults": { + "model": "create:block/logistical_controller" + }, + "variants": { + "type": { + "storage": { }, + "calculation": { }, + "supply": { }, + "transactions": { }, + "request": { } + }, + "facing": { + "north": { "y": 180 }, + "south": { }, + "west": { "y": 90 }, + "up": { "x": 90 }, + "down": { "x": 270 }, + "east": { "y": 270 } + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/create/blockstates/logistical_controller_indicator.json b/src/main/resources/assets/create/blockstates/logistical_controller_indicator.json new file mode 100644 index 000000000..58ee7dab8 --- /dev/null +++ b/src/main/resources/assets/create/blockstates/logistical_controller_indicator.json @@ -0,0 +1,20 @@ +{ + "forge_marker": 1, + "variants": { + "type": { + "storage": { "model": "create:block/logistical_controller_icon_storage" }, + "calculation": { "model": "create:block/logistical_controller_icon_calculation" }, + "supply": { "model": "create:block/logistical_controller_icon_supply" }, + "transactions": { "model": "create:block/logistical_controller_icon_transactions" }, + "request": { "model": "create:block/logistical_controller_icon_request" } + }, + "facing": { + "north": { "y": 180 }, + "south": { }, + "west": { "y": 90 }, + "up": { "x": 90 }, + "down": { "x": 270 }, + "east": { "y": 270 } + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/create/blockstates/logistical_index.json b/src/main/resources/assets/create/blockstates/logistical_index.json new file mode 100644 index 000000000..e4e136932 --- /dev/null +++ b/src/main/resources/assets/create/blockstates/logistical_index.json @@ -0,0 +1,14 @@ +{ + "forge_marker": 1, + "defaults": { + "model": "create:block/logistical_index" + }, + "variants": { + "facing": { + "north": { "y": 180 }, + "south": { }, + "east": { "y": 270 }, + "west": { "y": 90 } + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/create/lang/en_us.json b/src/main/resources/assets/create/lang/en_us.json index a1d85e7c8..45775892c 100644 --- a/src/main/resources/assets/create/lang/en_us.json +++ b/src/main/resources/assets/create/lang/en_us.json @@ -340,6 +340,10 @@ "create.schematicannon.status.schematicNotPlaced": "Schematic not Deployed", "create.schematicannon.status.schematicExpired": "Schematic File Expired", + "create.gui.index.title": "Logistical Index", + "create.gui.index.targetAddressSelect": "Destination Address", + "create.gui.index.confirmOrder": "Confirm Order", + "create.tooltip.holdKey": "Hold [%1$s]", "create.tooltip.holdKeyOrKey": "Hold [%1$s] or [%2$s]", "create.tooltip.keyShift": "Shift", diff --git a/src/main/resources/assets/create/models/block/logistical_casing.json b/src/main/resources/assets/create/models/block/logistical_casing.json new file mode 100644 index 000000000..5ac07276b --- /dev/null +++ b/src/main/resources/assets/create/models/block/logistical_casing.json @@ -0,0 +1,50 @@ +{ + "__comment": "Model generated using MrCrayfish's Model Creator (https://mrcrayfish.com/tools?id=mc)", + "parent": "block/block", + "textures": { + "particle": "create:block/brass_casing_side", + "brass_casing_side": "create:block/brass_casing_side", + "brass_casing": "create:block/brass_casing" + }, + "elements": [ + { + "name": "Center", + "from": [ 1, 2, 1 ], + "to": [ 15, 14, 15 ], + "faces": { + "north": { "texture": "#brass_casing_side", "uv": [ 2, 1, 14, 15 ], "rotation": 90 }, + "east": { "texture": "#brass_casing_side", "uv": [ 2, 1, 14, 15 ], "rotation": 90 }, + "south": { "texture": "#brass_casing_side", "uv": [ 2, 1, 14, 15 ], "rotation": 90 }, + "west": { "texture": "#brass_casing_side", "uv": [ 2, 1, 14, 15 ], "rotation": 270 }, + "up": { "texture": "#brass_casing", "uv": [ 1, 1, 15, 15 ] }, + "down": { "texture": "#brass_casing", "uv": [ 1, 1, 15, 15 ] } + } + }, + { + "name": "Cube", + "from": [ 0, 0, 0 ], + "to": [ 16, 2, 16 ], + "faces": { + "north": { "texture": "#brass_casing_side", "uv": [ 0, 14, 16, 16 ] }, + "east": { "texture": "#brass_casing_side", "uv": [ 0, 14, 16, 16 ] }, + "south": { "texture": "#brass_casing_side", "uv": [ 0, 14, 16, 16 ] }, + "west": { "texture": "#brass_casing_side", "uv": [ 0, 14, 16, 16 ] }, + "up": { "texture": "#brass_casing", "uv": [ 0, 0, 16, 16 ] }, + "down": { "texture": "#brass_casing", "uv": [ 0, 0, 16, 16 ] } + } + }, + { + "name": "Cube", + "from": [ 0, 14, 0 ], + "to": [ 16, 16, 16 ], + "faces": { + "north": { "texture": "#brass_casing_side", "uv": [ 0, 0, 16, 2 ] }, + "east": { "texture": "#brass_casing_side", "uv": [ 0, 0, 16, 2 ] }, + "south": { "texture": "#brass_casing_side", "uv": [ 0, 0, 16, 2 ] }, + "west": { "texture": "#brass_casing_side", "uv": [ 0, 0, 16, 2 ] }, + "up": { "texture": "#brass_casing", "uv": [ 0, 0, 16, 16 ] }, + "down": { "texture": "#brass_casing", "uv": [ 0, 0, 16, 16 ] } + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/create/models/block/logistical_casing_end.json b/src/main/resources/assets/create/models/block/logistical_casing_end.json new file mode 100644 index 000000000..891562165 --- /dev/null +++ b/src/main/resources/assets/create/models/block/logistical_casing_end.json @@ -0,0 +1,89 @@ +{ + "__comment": "Model generated using MrCrayfish's Model Creator (https://mrcrayfish.com/tools?id=mc)", + "parent": "block/block", + "textures": { + "particle": "create:block/brass_casing_side", + "brass_casing_side": "create:block/brass_casing_side", + "brass_casing": "create:block/brass_casing" + }, + "elements": [ + { + "name": "Center", + "from": [ 1, 0, 1 ], + "to": [ 15, 14, 15 ], + "faces": { + "north": { "texture": "#brass_casing_side", "uv": [ 2, 1, 16, 15 ], "rotation": 90 }, + "east": { "texture": "#brass_casing_side", "uv": [ 2, 1, 16, 15 ], "rotation": 90 }, + "south": { "texture": "#brass_casing_side", "uv": [ 2, 1, 16, 15 ], "rotation": 90 }, + "west": { "texture": "#brass_casing_side", "uv": [ 0, 1, 14, 15 ], "rotation": 270 }, + "up": { "texture": "#brass_casing", "uv": [ 1, 1, 15, 15 ] }, + "down": { "texture": "#brass_casing", "uv": [ 1, 1, 15, 15 ] } + } + }, + { + "name": "Cube", + "from": [ 0, 0, 0 ], + "to": [ 2, 14, 2 ], + "faces": { + "north": { "texture": "#brass_casing_side", "uv": [ 0, 0, 14, 2 ], "rotation": 90 }, + "east": { "texture": "#brass_casing_side", "uv": [ 2, 0, 16, 2 ], "rotation": 90 }, + "south": { "texture": "#brass_casing_side", "uv": [ 2, 0, 16, 2 ], "rotation": 270 }, + "west": { "texture": "#brass_casing_side", "uv": [ 2, 0, 16, 2 ], "rotation": 270 }, + "up": { "texture": "#brass_casing", "uv": [ 0, 0, 2, 2 ] }, + "down": { "texture": "#brass_casing", "uv": [ 0, 14, 2, 16 ] } + } + }, + { + "name": "Cube", + "from": [ 14, 0, 0 ], + "to": [ 16, 14, 2 ], + "faces": { + "north": { "texture": "#brass_casing_side", "uv": [ 0, 14, 14, 16 ], "rotation": 90 }, + "east": { "texture": "#brass_casing_side", "uv": [ 0, 0, 14, 2 ], "rotation": 90 }, + "south": { "texture": "#brass_casing_side", "uv": [ 0, 14, 14, 16 ], "rotation": 270 }, + "west": { "texture": "#brass_casing_side", "uv": [ 0, 0, 14, 2 ], "rotation": 270 }, + "up": { "texture": "#brass_casing", "uv": [ 14, 0, 16, 2 ] }, + "down": { "texture": "#brass_casing", "uv": [ 14, 14, 16, 16 ] } + } + }, + { + "name": "Cube", + "from": [ 14, 0, 14 ], + "to": [ 16, 14, 16 ], + "faces": { + "north": { "texture": "#brass_casing_side", "uv": [ 0, 14, 14, 16 ], "rotation": 90 }, + "east": { "texture": "#brass_casing_side", "uv": [ 0, 14, 14, 16 ], "rotation": 90 }, + "south": { "texture": "#brass_casing_side", "uv": [ 0, 14, 14, 16 ], "rotation": 270 }, + "west": { "texture": "#brass_casing_side", "uv": [ 0, 14, 14, 16 ], "rotation": 270 }, + "up": { "texture": "#brass_casing", "uv": [ 14, 14, 16, 16 ] }, + "down": { "texture": "#brass_casing", "uv": [ 14, 0, 16, 2 ] } + } + }, + { + "name": "Cube", + "from": [ 0, 0, 14 ], + "to": [ 2, 14, 16 ], + "faces": { + "north": { "texture": "#brass_casing_side", "uv": [ 0, 0, 14, 2 ], "rotation": 90 }, + "east": { "texture": "#brass_casing_side", "uv": [ 0, 14, 14, 16 ], "rotation": 90 }, + "south": { "texture": "#brass_casing_side", "uv": [ 0, 0, 14, 2 ], "rotation": 270 }, + "west": { "texture": "#brass_casing_side", "uv": [ 0, 14, 14, 16 ], "rotation": 270 }, + "up": { "texture": "#brass_casing", "uv": [ 0, 14, 2, 16 ] }, + "down": { "texture": "#brass_casing", "uv": [ 0, 0, 2, 2 ] } + } + }, + { + "name": "Cube", + "from": [ 0, 14, 0 ], + "to": [ 16, 16, 16 ], + "faces": { + "north": { "texture": "#brass_casing", "uv": [ 0, 0, 16, 2 ] }, + "east": { "texture": "#brass_casing", "uv": [ 0, 0, 16, 2 ] }, + "south": { "texture": "#brass_casing", "uv": [ 0, 0, 16, 2 ] }, + "west": { "texture": "#brass_casing", "uv": [ 0, 0, 16, 2 ] }, + "up": { "texture": "#brass_casing", "uv": [ 0, 0, 16, 16 ] }, + "down": { "texture": "#brass_casing", "uv": [ 0, 0, 16, 16 ] } + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/create/models/block/logistical_casing_middle.json b/src/main/resources/assets/create/models/block/logistical_casing_middle.json new file mode 100644 index 000000000..89fcafe43 --- /dev/null +++ b/src/main/resources/assets/create/models/block/logistical_casing_middle.json @@ -0,0 +1,76 @@ +{ + "__comment": "Model generated using MrCrayfish's Model Creator (https://mrcrayfish.com/tools?id=mc)", + "parent": "block/block", + "textures": { + "particle": "create:block/brass_casing_side", + "brass_casing_side": "create:block/brass_casing_side", + "brass_casing": "create:block/brass_casing" + }, + "elements": [ + { + "name": "Center", + "from": [ 1, 0, 1 ], + "to": [ 15, 16, 15 ], + "faces": { + "north": { "texture": "#brass_casing_side", "uv": [ 0, 1, 16, 15 ], "rotation": 90 }, + "east": { "texture": "#brass_casing_side", "uv": [ 0, 1, 16, 15 ], "rotation": 90 }, + "south": { "texture": "#brass_casing_side", "uv": [ 0, 1, 16, 15 ], "rotation": 90 }, + "west": { "texture": "#brass_casing_side", "uv": [ 0, 1, 16, 15 ], "rotation": 270 }, + "up": { "texture": "#brass_casing", "uv": [ 1, 1, 15, 15 ] }, + "down": { "texture": "#brass_casing", "uv": [ 1, 1, 15, 15 ] } + } + }, + { + "name": "Cube", + "from": [ 0, 0, 0 ], + "to": [ 2, 16, 2 ], + "faces": { + "north": { "texture": "#brass_casing_side", "uv": [ 0, 0, 16, 2 ], "rotation": 90 }, + "east": { "texture": "#brass_casing_side", "uv": [ 0, 0, 16, 2 ], "rotation": 90 }, + "south": { "texture": "#brass_casing_side", "uv": [ 0, 0, 16, 2 ], "rotation": 270 }, + "west": { "texture": "#brass_casing_side", "uv": [ 0, 0, 16, 2 ], "rotation": 270 }, + "up": { "texture": "#brass_casing", "uv": [ 0, 0, 2, 2 ] }, + "down": { "texture": "#brass_casing", "uv": [ 0, 14, 2, 16 ] } + } + }, + { + "name": "Cube", + "from": [ 14, 0, 0 ], + "to": [ 16, 16, 2 ], + "faces": { + "north": { "texture": "#brass_casing_side", "uv": [ 0, 14, 16, 16 ], "rotation": 90 }, + "east": { "texture": "#brass_casing_side", "uv": [ 0, 0, 16, 2 ], "rotation": 90 }, + "south": { "texture": "#brass_casing_side", "uv": [ 0, 14, 16, 16 ], "rotation": 270 }, + "west": { "texture": "#brass_casing_side", "uv": [ 0, 0, 16, 2 ], "rotation": 270 }, + "up": { "texture": "#brass_casing", "uv": [ 14, 0, 16, 2 ] }, + "down": { "texture": "#brass_casing", "uv": [ 14, 14, 16, 16 ] } + } + }, + { + "name": "Cube", + "from": [ 14, 0, 14 ], + "to": [ 16, 16, 16 ], + "faces": { + "north": { "texture": "#brass_casing_side", "uv": [ 0, 14, 16, 16 ], "rotation": 90 }, + "east": { "texture": "#brass_casing_side", "uv": [ 0, 14, 16, 16 ], "rotation": 90 }, + "south": { "texture": "#brass_casing_side", "uv": [ 0, 14, 16, 16 ], "rotation": 270 }, + "west": { "texture": "#brass_casing_side", "uv": [ 0, 14, 16, 16 ], "rotation": 270 }, + "up": { "texture": "#brass_casing", "uv": [ 14, 14, 16, 16 ] }, + "down": { "texture": "#brass_casing", "uv": [ 14, 0, 16, 2 ] } + } + }, + { + "name": "Cube", + "from": [ 0, 0, 14 ], + "to": [ 2, 16, 16 ], + "faces": { + "north": { "texture": "#brass_casing_side", "uv": [ 0, 0, 16, 2 ], "rotation": 90 }, + "east": { "texture": "#brass_casing_side", "uv": [ 0, 14, 16, 16 ], "rotation": 90 }, + "south": { "texture": "#brass_casing_side", "uv": [ 0, 0, 16, 2 ], "rotation": 270 }, + "west": { "texture": "#brass_casing_side", "uv": [ 0, 14, 16, 16 ], "rotation": 270 }, + "up": { "texture": "#brass_casing", "uv": [ 0, 14, 2, 16 ] }, + "down": { "texture": "#brass_casing", "uv": [ 0, 0, 2, 2 ] } + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/create/models/block/logistical_casing_start.json b/src/main/resources/assets/create/models/block/logistical_casing_start.json new file mode 100644 index 000000000..5a9f7e9c8 --- /dev/null +++ b/src/main/resources/assets/create/models/block/logistical_casing_start.json @@ -0,0 +1,89 @@ +{ + "__comment": "Model generated using MrCrayfish's Model Creator (https://mrcrayfish.com/tools?id=mc)", + "parent": "block/block", + "textures": { + "particle": "create:block/brass_casing_side", + "brass_casing_side": "create:block/brass_casing_side", + "brass_casing": "create:block/brass_casing" + }, + "elements": [ + { + "name": "Center", + "from": [ 1, 2, 1 ], + "to": [ 15, 16, 15 ], + "faces": { + "north": { "texture": "#brass_casing_side", "uv": [ 0, 1, 14, 15 ], "rotation": 90 }, + "east": { "texture": "#brass_casing_side", "uv": [ 0, 1, 14, 15 ], "rotation": 90 }, + "south": { "texture": "#brass_casing_side", "uv": [ 0, 1, 14, 15 ], "rotation": 90 }, + "west": { "texture": "#brass_casing_side", "uv": [ 2, 1, 16, 15 ], "rotation": 270 }, + "up": { "texture": "#brass_casing", "uv": [ 1, 1, 15, 15 ] }, + "down": { "texture": "#brass_casing", "uv": [ 1, 1, 15, 15 ] } + } + }, + { + "name": "Cube", + "from": [ 0, 2, 0 ], + "to": [ 2, 16, 2 ], + "faces": { + "north": { "texture": "#brass_casing_side", "uv": [ 0, 0, 14, 2 ], "rotation": 90 }, + "east": { "texture": "#brass_casing_side", "uv": [ 2, 0, 16, 2 ], "rotation": 90 }, + "south": { "texture": "#brass_casing_side", "uv": [ 2, 0, 16, 2 ], "rotation": 270 }, + "west": { "texture": "#brass_casing_side", "uv": [ 2, 0, 16, 2 ], "rotation": 270 }, + "up": { "texture": "#brass_casing", "uv": [ 0, 0, 2, 2 ] }, + "down": { "texture": "#brass_casing", "uv": [ 0, 14, 2, 16 ] } + } + }, + { + "name": "Cube", + "from": [ 14, 2, 0 ], + "to": [ 16, 16, 2 ], + "faces": { + "north": { "texture": "#brass_casing_side", "uv": [ 0, 14, 14, 16 ], "rotation": 90 }, + "east": { "texture": "#brass_casing_side", "uv": [ 0, 0, 14, 2 ], "rotation": 90 }, + "south": { "texture": "#brass_casing_side", "uv": [ 0, 14, 14, 16 ], "rotation": 270 }, + "west": { "texture": "#brass_casing_side", "uv": [ 0, 0, 14, 2 ], "rotation": 270 }, + "up": { "texture": "#brass_casing", "uv": [ 14, 0, 16, 2 ] }, + "down": { "texture": "#brass_casing", "uv": [ 14, 14, 16, 16 ] } + } + }, + { + "name": "Cube", + "from": [ 14, 2, 14 ], + "to": [ 16, 16, 16 ], + "faces": { + "north": { "texture": "#brass_casing_side", "uv": [ 0, 14, 14, 16 ], "rotation": 90 }, + "east": { "texture": "#brass_casing_side", "uv": [ 0, 14, 14, 16 ], "rotation": 90 }, + "south": { "texture": "#brass_casing_side", "uv": [ 0, 14, 14, 16 ], "rotation": 270 }, + "west": { "texture": "#brass_casing_side", "uv": [ 0, 14, 14, 16 ], "rotation": 270 }, + "up": { "texture": "#brass_casing", "uv": [ 14, 14, 16, 16 ] }, + "down": { "texture": "#brass_casing", "uv": [ 14, 0, 16, 2 ] } + } + }, + { + "name": "Cube", + "from": [ 0, 2, 14 ], + "to": [ 2, 16, 16 ], + "faces": { + "north": { "texture": "#brass_casing_side", "uv": [ 0, 0, 14, 2 ], "rotation": 90 }, + "east": { "texture": "#brass_casing_side", "uv": [ 0, 14, 14, 16 ], "rotation": 90 }, + "south": { "texture": "#brass_casing_side", "uv": [ 0, 0, 14, 2 ], "rotation": 270 }, + "west": { "texture": "#brass_casing_side", "uv": [ 0, 14, 14, 16 ], "rotation": 270 }, + "up": { "texture": "#brass_casing", "uv": [ 0, 14, 2, 16 ] }, + "down": { "texture": "#brass_casing", "uv": [ 0, 0, 2, 2 ] } + } + }, + { + "name": "Cube", + "from": [ 0, 0, 0 ], + "to": [ 16, 2, 16 ], + "faces": { + "north": { "texture": "#brass_casing", "uv": [ 0, 14, 16, 16 ] }, + "east": { "texture": "#brass_casing", "uv": [ 0, 14, 16, 16 ] }, + "south": { "texture": "#brass_casing", "uv": [ 0, 14, 16, 16 ] }, + "west": { "texture": "#brass_casing", "uv": [ 0, 14, 16, 16 ] }, + "up": { "texture": "#brass_casing", "uv": [ 0, 0, 16, 16 ] }, + "down": { "texture": "#brass_casing", "uv": [ 0, 0, 16, 16 ] } + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/create/models/block/logistical_controller.json b/src/main/resources/assets/create/models/block/logistical_controller.json new file mode 100644 index 000000000..10bda8ea8 --- /dev/null +++ b/src/main/resources/assets/create/models/block/logistical_controller.json @@ -0,0 +1,22 @@ +{ + "__comment": "Model generated using MrCrayfish's Model Creator (https://mrcrayfish.com/tools?id=mc)", + "textures": { + "particle": "create:block/logistical_controller", + "logistical_controller": "create:block/logistical_controller" + }, + "elements": [ + { + "name": "Body", + "from": [ 2, 2, -1 ], + "to": [ 14, 14, 3 ], + "faces": { + "north": { "texture": "#logistical_controller", "uv": [ 0, 0, 12, 12 ] }, + "east": { "texture": "#logistical_controller", "uv": [ 12, 0, 16, 12 ] }, + "south": { "texture": "#logistical_controller", "uv": [ 0, 0, 12, 12 ] }, + "west": { "texture": "#logistical_controller", "uv": [ 12, 0, 16, 12 ], "rotation": 180 }, + "up": { "texture": "#logistical_controller", "uv": [ 0, 12, 12, 16 ], "rotation": 180 }, + "down": { "texture": "#logistical_controller", "uv": [ 0, 12, 12, 16 ] } + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/create/models/block/logistical_controller_icon_calculation.json b/src/main/resources/assets/create/models/block/logistical_controller_icon_calculation.json new file mode 100644 index 000000000..e05641b3c --- /dev/null +++ b/src/main/resources/assets/create/models/block/logistical_controller_icon_calculation.json @@ -0,0 +1,28 @@ +{ + "__comment": "Model generated using MrCrayfish's Model Creator (https://mrcrayfish.com/tools?id=mc)", + "textures": { + "logistical_controller": "create:block/logistical_controller", + "logistical_icons_1": "create:block/logistical_icons_1" + }, + "elements": [ + { + "name": "Indicator", + "from": [ 1.99, 3, 0 ], + "to": [ 14.01, 13, 2 ], + "shade": false, + "faces": { + "east": { "texture": "#logistical_controller", "uv": [ 13, 1, 15, 11 ], "tintindex": 0 }, + "west": { "texture": "#logistical_controller", "uv": [ 13, 1, 15, 11 ], "rotation": 180, "tintindex": 0 } + } + }, + { + "name": "Icon", + "from": [ 5, 5, 2.5 ], + "to": [ 11, 11, 3.5 ], + "shade": false, + "faces": { + "south": { "texture": "#logistical_icons_1", "uv": [ 9, 2, 14, 7 ], "tintindex": 1 } + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/create/models/block/logistical_controller_icon_request.json b/src/main/resources/assets/create/models/block/logistical_controller_icon_request.json new file mode 100644 index 000000000..bd2e4022c --- /dev/null +++ b/src/main/resources/assets/create/models/block/logistical_controller_icon_request.json @@ -0,0 +1,28 @@ +{ + "__comment": "Model generated using MrCrayfish's Model Creator (https://mrcrayfish.com/tools?id=mc)", + "textures": { + "logistical_controller": "create:block/logistical_controller", + "logistical_icons_1": "create:block/logistical_icons_1" + }, + "elements": [ + { + "name": "Indicator", + "from": [ 1.99, 3, 0 ], + "to": [ 14.01, 13, 2 ], + "shade": false, + "faces": { + "east": { "texture": "#logistical_controller", "uv": [ 13, 1, 15, 11 ], "tintindex": 0 }, + "west": { "texture": "#logistical_controller", "uv": [ 13, 1, 15, 11 ], "rotation": 180, "tintindex": 0 } + } + }, + { + "name": "Icon", + "from": [ 5, 5, 2.5 ], + "to": [ 11, 11, 3.5 ], + "shade": false, + "faces": { + "south": { "texture": "#logistical_icons_1", "uv": [ 9, 9, 14, 14 ], "tintindex": 1 } + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/create/models/block/logistical_controller_icon_storage.json b/src/main/resources/assets/create/models/block/logistical_controller_icon_storage.json new file mode 100644 index 000000000..55257391f --- /dev/null +++ b/src/main/resources/assets/create/models/block/logistical_controller_icon_storage.json @@ -0,0 +1,28 @@ +{ + "__comment": "Model generated using MrCrayfish's Model Creator (https://mrcrayfish.com/tools?id=mc)", + "textures": { + "logistical_controller": "create:block/logistical_controller", + "logistical_icons_1": "create:block/logistical_icons_1" + }, + "elements": [ + { + "name": "Indicator", + "from": [ 1.99, 3, 0 ], + "to": [ 14.01, 13, 2 ], + "shade": false, + "faces": { + "east": { "texture": "#logistical_controller", "uv": [ 13, 1, 15, 11 ], "tintindex": 0 }, + "west": { "texture": "#logistical_controller", "uv": [ 13, 1, 15, 11 ], "rotation": 180, "tintindex": 0 } + } + }, + { + "name": "Icon", + "from": [ 5, 5, 2.5 ], + "to": [ 11, 11, 3.5 ], + "shade": false, + "faces": { + "south": { "texture": "#logistical_icons_1", "uv": [ 2, 2, 7, 7 ], "tintindex": 1 } + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/create/models/block/logistical_controller_icon_supply.json b/src/main/resources/assets/create/models/block/logistical_controller_icon_supply.json new file mode 100644 index 000000000..82ff249cc --- /dev/null +++ b/src/main/resources/assets/create/models/block/logistical_controller_icon_supply.json @@ -0,0 +1,28 @@ +{ + "__comment": "Model generated using MrCrayfish's Model Creator (https://mrcrayfish.com/tools?id=mc)", + "textures": { + "logistical_controller": "create:block/logistical_controller", + "logistical_icons_1": "create:block/logistical_icons_1" + }, + "elements": [ + { + "name": "Indicator", + "from": [ 1.99, 3, 0 ], + "to": [ 14.01, 13, 2 ], + "shade": false, + "faces": { + "east": { "texture": "#logistical_controller", "uv": [ 13, 1, 15, 11 ], "tintindex": 0 }, + "west": { "texture": "#logistical_controller", "uv": [ 13, 1, 15, 11 ], "rotation": 180, "tintindex": 0 } + } + }, + { + "name": "Icon", + "from": [ 5, 5, 2.5 ], + "to": [ 11, 11, 3.5 ], + "shade": false, + "faces": { + "south": { "texture": "#logistical_icons_1", "uv": [ 2, 9, 7, 14 ], "tintindex": 1 } + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/create/models/block/logistical_controller_icon_transactions.json b/src/main/resources/assets/create/models/block/logistical_controller_icon_transactions.json new file mode 100644 index 000000000..6db45a02b --- /dev/null +++ b/src/main/resources/assets/create/models/block/logistical_controller_icon_transactions.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/logistical_controller_icon_storage", + "textures": { + "logistical_icons_1": "create:block/logistical_icons_2" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/create/models/block/logistical_index.json b/src/main/resources/assets/create/models/block/logistical_index.json new file mode 100644 index 000000000..2c3632661 --- /dev/null +++ b/src/main/resources/assets/create/models/block/logistical_index.json @@ -0,0 +1,77 @@ +{ + "__comment": "Model generated using MrCrayfish's Model Creator (https://mrcrayfish.com/tools?id=mc)", + "parent": "block/block", + "textures": { + "redstone_antenna": "create:block/redstone_antenna_powered", + "logistical_index_side_overlay": "create:block/logistical_index_side_overlay", + "logistical_index_side": "create:block/logistical_index_side", + "particle": "create:block/logistical_index_side" + }, + "elements": [ + { + "name": "Inner", + "from": [ 3, 1, -1 ], + "to": [ 13, 15, 3 ], + "faces": { + "north": { "texture": "#logistical_index_side", "uv": [ 0, 0, 10, 14 ] }, + "east": { "texture": "#logistical_index_side", "uv": [ 10, 0, 14, 14 ] }, + "south": { "texture": "#logistical_index_side", "uv": [ 0, 0, 10, 14 ] }, + "west": { "texture": "#logistical_index_side", "uv": [ 10, 0, 14, 14 ], "rotation": 180 }, + "up": { "texture": "#logistical_index_side", "uv": [ 12, 2, 16, 12 ], "rotation": 270 }, + "down": { "texture": "#logistical_index_side", "uv": [ 12, 2, 16, 12 ], "rotation": 90 } + } + }, + { + "name": "Overlay", + "from": [ 2.99, 1, -1 ], + "to": [ 13.01, 15, 3.01 ], + "shade": false, + "faces": { + "east": { "texture": "#logistical_index_side_overlay", "uv": [ 10, 0, 14.01, 14 ], "tintindex": 0 }, + "south": { "texture": "#logistical_index_side_overlay", "uv": [ 0, 0, 10.02, 14 ], "tintindex": 0 }, + "west": { "texture": "#logistical_index_side_overlay", "uv": [ 10, 0, 14.01, 14 ], "rotation": 180, "tintindex": 0 } + } + }, + { + "name": "Antenna stick", + "from": [ 2, 11, 1 ], + "to": [ 3, 18, 2 ], + "faces": { + "north": { "texture": "#redstone_antenna", "uv": [ 11, 3, 12, 10 ] }, + "east": { "texture": "#redstone_antenna", "uv": [ 11, 3, 12, 10 ] }, + "south": { "texture": "#redstone_antenna", "uv": [ 11, 3, 12, 10 ] }, + "west": { "texture": "#redstone_antenna", "uv": [ 11, 3, 12, 10 ] }, + "down": { "texture": "#redstone_antenna", "uv": [ 11, 9, 12, 10 ] } + } + }, + { + "name": "Antenna Top", + "from": [ 1, 18, 1 ], + "to": [ 4, 21, 2 ], + "shade": false, + "faces": { + "north": { "texture": "#redstone_antenna", "uv": [ 10, 0, 13, 3 ], "tintindex": 0 }, + "south": { "texture": "#redstone_antenna", "uv": [ 10, 0, 13, 3 ], "tintindex": 0 } + } + }, + { + "name": "Antenna Top2", + "from": [ 2, 18, 0 ], + "to": [ 3, 21, 3 ], + "shade": false, + "faces": { + "east": { "texture": "#redstone_antenna", "uv": [ 10, 0, 13, 3 ], "tintindex": 0 }, + "west": { "texture": "#redstone_antenna", "uv": [ 10, 0, 13, 3 ], "tintindex": 0 } + } + }, + { + "name": "Antenna TopFace", + "from": [ 2, 19, 1 ], + "to": [ 3, 20, 2 ], + "shade": false, + "faces": { + "up": { "texture": "#redstone_antenna", "uv": [ 11, 1, 12, 2 ], "tintindex": 0 } + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/create/models/item/cardboard_box_1410.json b/src/main/resources/assets/create/models/item/cardboard_box_1410.json new file mode 100644 index 000000000..b708c67a7 --- /dev/null +++ b/src/main/resources/assets/create/models/item/cardboard_box_1410.json @@ -0,0 +1,23 @@ +{ + "__comment": "Model generated using MrCrayfish's Model Creator (https://mrcrayfish.com/tools?id=mc)", + "parent": "block/block", + "textures": { + "particle": "create:item/cardboard_box_particle", + "cardboard_box_1410": "create:item/cardboard_box_1410" + }, + "elements": [ + { + "name": "Box", + "from": [ 1, 0, 1 ], + "to": [ 15, 10, 15 ], + "faces": { + "north": { "texture": "#cardboard_box_1410", "uv": [ 8, 8, 15, 13 ] }, + "east": { "texture": "#cardboard_box_1410", "uv": [ 1, 3, 8, 8 ] }, + "south": { "texture": "#cardboard_box_1410", "uv": [ 8, 8, 15, 13 ] }, + "west": { "texture": "#cardboard_box_1410", "uv": [ 1, 3, 8, 8 ] }, + "up": { "texture": "#cardboard_box_1410", "uv": [ 8, 1, 15, 8 ] }, + "down": { "texture": "#cardboard_box_1410", "uv": [ 1, 8, 8, 15 ] } + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/create/models/item/cardboard_box_1416.json b/src/main/resources/assets/create/models/item/cardboard_box_1416.json new file mode 100644 index 000000000..4c3c99178 --- /dev/null +++ b/src/main/resources/assets/create/models/item/cardboard_box_1416.json @@ -0,0 +1,23 @@ +{ + "__comment": "Model generated using MrCrayfish's Model Creator (https://mrcrayfish.com/tools?id=mc)", + "parent": "block/block", + "textures": { + "particle": "create:item/cardboard_box_particle", + "cardboard_box_1416": "create:item/cardboard_box_1416" + }, + "elements": [ + { + "name": "Box", + "from": [ 1, 0, 1 ], + "to": [ 15, 16, 15 ], + "faces": { + "north": { "texture": "#cardboard_box_1416", "uv": [ 8, 8, 15, 16 ] }, + "east": { "texture": "#cardboard_box_1416", "uv": [ 1, 0, 8, 8 ] }, + "south": { "texture": "#cardboard_box_1416", "uv": [ 8, 8, 15, 16 ] }, + "west": { "texture": "#cardboard_box_1416", "uv": [ 1, 0, 8, 8 ] }, + "up": { "texture": "#cardboard_box_1416", "uv": [ 8, 1, 15, 8 ] }, + "down": { "texture": "#cardboard_box_1416", "uv": [ 1, 8, 8, 15 ] } + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/create/models/item/cardboard_box_1612.json b/src/main/resources/assets/create/models/item/cardboard_box_1612.json new file mode 100644 index 000000000..35225b651 --- /dev/null +++ b/src/main/resources/assets/create/models/item/cardboard_box_1612.json @@ -0,0 +1,23 @@ +{ + "__comment": "Model generated using MrCrayfish's Model Creator (https://mrcrayfish.com/tools?id=mc)", + "parent": "block/block", + "textures": { + "particle": "create:item/cardboard_box_particle", + "cardboard_box_1612": "create:item/cardboard_box_1612" + }, + "elements": [ + { + "name": "Box", + "from": [ 0, 0, 0 ], + "to": [ 16, 12, 16 ], + "faces": { + "north": { "texture": "#cardboard_box_1612", "uv": [ 8, 8, 16, 14 ] }, + "east": { "texture": "#cardboard_box_1612", "uv": [ 0, 2, 8, 8 ] }, + "south": { "texture": "#cardboard_box_1612", "uv": [ 8, 8, 16, 14 ] }, + "west": { "texture": "#cardboard_box_1612", "uv": [ 0, 2, 8, 8 ] }, + "up": { "texture": "#cardboard_box_1612", "uv": [ 8, 0, 16, 8 ] }, + "down": { "texture": "#cardboard_box_1612", "uv": [ 0, 8, 8, 16 ] } + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/create/models/item/cardboard_box_1616.json b/src/main/resources/assets/create/models/item/cardboard_box_1616.json new file mode 100644 index 000000000..ae58faa6f --- /dev/null +++ b/src/main/resources/assets/create/models/item/cardboard_box_1616.json @@ -0,0 +1,23 @@ +{ + "__comment": "Model generated using MrCrayfish's Model Creator (https://mrcrayfish.com/tools?id=mc)", + "parent": "block/block", + "textures": { + "particle": "create:item/cardboard_box_particle", + "cardboard_box_1616": "create:item/cardboard_box_1616" + }, + "elements": [ + { + "name": "Box", + "from": [ 0, 0, 0 ], + "to": [ 16, 16, 16 ], + "faces": { + "north": { "texture": "#cardboard_box_1616", "uv": [ 8, 8, 16, 16 ] }, + "east": { "texture": "#cardboard_box_1616", "uv": [ 0, 0, 8, 8 ] }, + "south": { "texture": "#cardboard_box_1616", "uv": [ 8, 8, 16, 16 ] }, + "west": { "texture": "#cardboard_box_1616", "uv": [ 0, 0, 8, 8 ] }, + "up": { "texture": "#cardboard_box_1616", "uv": [ 8, 0, 16, 8 ] }, + "down": { "texture": "#cardboard_box_1616", "uv": [ 0, 8, 8, 16 ] } + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/create/models/item/logistical_casing.json b/src/main/resources/assets/create/models/item/logistical_casing.json new file mode 100644 index 000000000..9c287f452 --- /dev/null +++ b/src/main/resources/assets/create/models/item/logistical_casing.json @@ -0,0 +1,3 @@ +{ + "parent": "create:block/logistical_casing" +} \ No newline at end of file diff --git a/src/main/resources/assets/create/models/item/logistical_controller.json b/src/main/resources/assets/create/models/item/logistical_controller.json new file mode 100644 index 000000000..c8bfaadc5 --- /dev/null +++ b/src/main/resources/assets/create/models/item/logistical_controller.json @@ -0,0 +1,26 @@ +{ + "__comment": "Model generated using MrCrayfish's Model Creator (https://mrcrayfish.com/tools?id=mc)", + "parent": "block/block", + "textures": { + "particle": "create:block/logistical_controller", + "logistical_controller": "create:block/logistical_controller", + "logistical_icons_1": "create:block/logistical_icons_1" + }, + "display": { + "gui": { + "rotation": [ 30, 45, 0 ], + "translation": [ 2.6, -1, 0 ], + "scale": [ 0.625, 0.625, 0.625 ] + }, + "ground": { + "rotation": [ 0, 0, 0 ], + "translation": [ 0, 3, 2 ], + "scale": [ 0.25, 0.25, 0.25 ] + }, + "fixed": { + "rotation": [ 0, 180, 0 ], + "translation": [ 0, 0, -7 ], + "scale": [ 0.625, 0.625, 0.625 ] + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/create/models/item/logistical_controller_calculation.json b/src/main/resources/assets/create/models/item/logistical_controller_calculation.json new file mode 100644 index 000000000..9bb9d4ae4 --- /dev/null +++ b/src/main/resources/assets/create/models/item/logistical_controller_calculation.json @@ -0,0 +1,38 @@ +{ + "__comment": "Model generated using MrCrayfish's Model Creator (https://mrcrayfish.com/tools?id=mc)", + "parent": "create:item/logistical_controller", + "elements": [ + { + "name": "Body", + "from": [ 2, 2, -1 ], + "to": [ 14, 14, 3 ], + "faces": { + "north": { "texture": "#logistical_controller", "uv": [ 0, 0, 12, 12 ] }, + "east": { "texture": "#logistical_controller", "uv": [ 12, 0, 16, 12 ] }, + "south": { "texture": "#logistical_controller", "uv": [ 0, 0, 12, 12 ] }, + "west": { "texture": "#logistical_controller", "uv": [ 12, 0, 16, 12 ], "rotation": 180 }, + "up": { "texture": "#logistical_controller", "uv": [ 0, 12, 12, 16 ], "rotation": 180 }, + "down": { "texture": "#logistical_controller", "uv": [ 0, 12, 12, 16 ] } + } + }, + { + "name": "Indicator", + "from": [ 1.99, 3, 0 ], + "to": [ 14.01, 13, 2 ], + "shade": false, + "faces": { + "east": { "texture": "#logistical_controller", "uv": [ 13, 1, 15, 11 ], "tintindex": 0 }, + "west": { "texture": "#logistical_controller", "uv": [ 13, 1, 15, 11 ], "rotation": 180, "tintindex": 0 } + } + }, + { + "name": "Icon", + "from": [ 5, 5, 2.5 ], + "to": [ 11, 11, 3.5 ], + "shade": false, + "faces": { + "south": { "texture": "#logistical_icons_1", "uv": [ 9, 2, 14, 7 ], "tintindex": 1 } + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/create/models/item/logistical_controller_request.json b/src/main/resources/assets/create/models/item/logistical_controller_request.json new file mode 100644 index 000000000..67bb689c8 --- /dev/null +++ b/src/main/resources/assets/create/models/item/logistical_controller_request.json @@ -0,0 +1,38 @@ +{ + "__comment": "Model generated using MrCrayfish's Model Creator (https://mrcrayfish.com/tools?id=mc)", + "parent": "create:item/logistical_controller", + "elements": [ + { + "name": "Body", + "from": [ 2, 2, -1 ], + "to": [ 14, 14, 3 ], + "faces": { + "north": { "texture": "#logistical_controller", "uv": [ 0, 0, 12, 12 ] }, + "east": { "texture": "#logistical_controller", "uv": [ 12, 0, 16, 12 ] }, + "south": { "texture": "#logistical_controller", "uv": [ 0, 0, 12, 12 ] }, + "west": { "texture": "#logistical_controller", "uv": [ 12, 0, 16, 12 ], "rotation": 180 }, + "up": { "texture": "#logistical_controller", "uv": [ 0, 12, 12, 16 ], "rotation": 180 }, + "down": { "texture": "#logistical_controller", "uv": [ 0, 12, 12, 16 ] } + } + }, + { + "name": "Indicator", + "from": [ 1.99, 3, 0 ], + "to": [ 14.01, 13, 2 ], + "shade": false, + "faces": { + "east": { "texture": "#logistical_controller", "uv": [ 13, 1, 15, 11 ], "tintindex": 0 }, + "west": { "texture": "#logistical_controller", "uv": [ 13, 1, 15, 11 ], "rotation": 180, "tintindex": 0 } + } + }, + { + "name": "Icon", + "from": [ 5, 5, 2.5 ], + "to": [ 11, 11, 3.5 ], + "shade": false, + "faces": { + "south": { "texture": "#logistical_icons_1", "uv": [ 9, 9, 14, 14 ], "tintindex": 1 } + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/create/models/item/logistical_controller_storage.json b/src/main/resources/assets/create/models/item/logistical_controller_storage.json new file mode 100644 index 000000000..f9279f0e4 --- /dev/null +++ b/src/main/resources/assets/create/models/item/logistical_controller_storage.json @@ -0,0 +1,38 @@ +{ + "__comment": "Model generated using MrCrayfish's Model Creator (https://mrcrayfish.com/tools?id=mc)", + "parent": "create:item/logistical_controller", + "elements": [ + { + "name": "Body", + "from": [ 2, 2, -1 ], + "to": [ 14, 14, 3 ], + "faces": { + "north": { "texture": "#logistical_controller", "uv": [ 0, 0, 12, 12 ] }, + "east": { "texture": "#logistical_controller", "uv": [ 12, 0, 16, 12 ] }, + "south": { "texture": "#logistical_controller", "uv": [ 0, 0, 12, 12 ] }, + "west": { "texture": "#logistical_controller", "uv": [ 12, 0, 16, 12 ], "rotation": 180 }, + "up": { "texture": "#logistical_controller", "uv": [ 0, 12, 12, 16 ], "rotation": 180 }, + "down": { "texture": "#logistical_controller", "uv": [ 0, 12, 12, 16 ] } + } + }, + { + "name": "Indicator", + "from": [ 1.99, 3, 0 ], + "to": [ 14.01, 13, 2 ], + "shade": false, + "faces": { + "east": { "texture": "#logistical_controller", "uv": [ 13, 1, 15, 11 ], "tintindex": 0 }, + "west": { "texture": "#logistical_controller", "uv": [ 13, 1, 15, 11 ], "rotation": 180, "tintindex": 0 } + } + }, + { + "name": "Icon", + "from": [ 5, 5, 2.5 ], + "to": [ 11, 11, 3.5 ], + "shade": false, + "faces": { + "south": { "texture": "#logistical_icons_1", "uv": [ 2, 2, 7, 7 ], "tintindex": 1 } + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/create/models/item/logistical_controller_supply.json b/src/main/resources/assets/create/models/item/logistical_controller_supply.json new file mode 100644 index 000000000..7b2c305cf --- /dev/null +++ b/src/main/resources/assets/create/models/item/logistical_controller_supply.json @@ -0,0 +1,38 @@ +{ + "__comment": "Model generated using MrCrayfish's Model Creator (https://mrcrayfish.com/tools?id=mc)", + "parent": "create:item/logistical_controller", + "elements": [ + { + "name": "Body", + "from": [ 2, 2, -1 ], + "to": [ 14, 14, 3 ], + "faces": { + "north": { "texture": "#logistical_controller", "uv": [ 0, 0, 12, 12 ] }, + "east": { "texture": "#logistical_controller", "uv": [ 12, 0, 16, 12 ] }, + "south": { "texture": "#logistical_controller", "uv": [ 0, 0, 12, 12 ] }, + "west": { "texture": "#logistical_controller", "uv": [ 12, 0, 16, 12 ], "rotation": 180 }, + "up": { "texture": "#logistical_controller", "uv": [ 0, 12, 12, 16 ], "rotation": 180 }, + "down": { "texture": "#logistical_controller", "uv": [ 0, 12, 12, 16 ] } + } + }, + { + "name": "Indicator", + "from": [ 1.99, 3, 0 ], + "to": [ 14.01, 13, 2 ], + "shade": false, + "faces": { + "east": { "texture": "#logistical_controller", "uv": [ 13, 1, 15, 11 ], "tintindex": 0 }, + "west": { "texture": "#logistical_controller", "uv": [ 13, 1, 15, 11 ], "rotation": 180, "tintindex": 0 } + } + }, + { + "name": "Icon", + "from": [ 5, 5, 2.5 ], + "to": [ 11, 11, 3.5 ], + "shade": false, + "faces": { + "south": { "texture": "#logistical_icons_1", "uv": [ 2, 9, 7, 14 ], "tintindex": 1 } + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/create/models/item/logistical_controller_transactions.json b/src/main/resources/assets/create/models/item/logistical_controller_transactions.json new file mode 100644 index 000000000..f7c9c725b --- /dev/null +++ b/src/main/resources/assets/create/models/item/logistical_controller_transactions.json @@ -0,0 +1,6 @@ +{ + "parent": "create:item/logistical_controller_storage", + "textures": { + "logistical_icons_1": "create:block/logistical_icons_2" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/create/models/item/logistical_dial.json b/src/main/resources/assets/create/models/item/logistical_dial.json new file mode 100644 index 000000000..a31bb13a8 --- /dev/null +++ b/src/main/resources/assets/create/models/item/logistical_dial.json @@ -0,0 +1,7 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "create:item/logistical_dial", + "layer1": "create:item/logistical_dial_overlay" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/create/models/item/logistical_index.json b/src/main/resources/assets/create/models/item/logistical_index.json new file mode 100644 index 000000000..593ef575a --- /dev/null +++ b/src/main/resources/assets/create/models/item/logistical_index.json @@ -0,0 +1,20 @@ +{ + "parent": "create:block/logistical_index", + "display": { + "gui": { + "rotation": [ 30, 45, 0 ], + "translation": [ 2.6, -1, 0 ], + "scale": [ 0.625, 0.625, 0.625 ] + }, + "ground": { + "rotation": [ 0, 0, 0 ], + "translation": [ 0, 3, 2 ], + "scale": [ 0.25, 0.25, 0.25 ] + }, + "fixed": { + "rotation": [ 0, 180, 0 ], + "translation": [ 0, 0, -7 ], + "scale": [ 0.625, 0.625, 0.625 ] + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/create/textures/block/CONCEPT_logistical_transaction_controller.pdn b/src/main/resources/assets/create/textures/block/CONCEPT_logistical_transaction_controller.pdn new file mode 100644 index 000000000..b0a5ba795 Binary files /dev/null and b/src/main/resources/assets/create/textures/block/CONCEPT_logistical_transaction_controller.pdn differ diff --git a/src/main/resources/assets/create/textures/block/logistical_controller.png b/src/main/resources/assets/create/textures/block/logistical_controller.png new file mode 100644 index 000000000..6dbc79bc2 Binary files /dev/null and b/src/main/resources/assets/create/textures/block/logistical_controller.png differ diff --git a/src/main/resources/assets/create/textures/block/logistical_icons_1.png b/src/main/resources/assets/create/textures/block/logistical_icons_1.png new file mode 100644 index 000000000..48bca3161 Binary files /dev/null and b/src/main/resources/assets/create/textures/block/logistical_icons_1.png differ diff --git a/src/main/resources/assets/create/textures/block/logistical_icons_2.png b/src/main/resources/assets/create/textures/block/logistical_icons_2.png new file mode 100644 index 000000000..02f695d60 Binary files /dev/null and b/src/main/resources/assets/create/textures/block/logistical_icons_2.png differ diff --git a/src/main/resources/assets/create/textures/block/logistical_index_side.png b/src/main/resources/assets/create/textures/block/logistical_index_side.png new file mode 100644 index 000000000..8adfcb545 Binary files /dev/null and b/src/main/resources/assets/create/textures/block/logistical_index_side.png differ diff --git a/src/main/resources/assets/create/textures/block/logistical_index_side_overlay.png b/src/main/resources/assets/create/textures/block/logistical_index_side_overlay.png new file mode 100644 index 000000000..e4cb74f29 Binary files /dev/null and b/src/main/resources/assets/create/textures/block/logistical_index_side_overlay.png differ diff --git a/src/main/resources/assets/create/textures/block/redstone_antenna.png b/src/main/resources/assets/create/textures/block/redstone_antenna.png index 8719db70b..31bc50188 100644 Binary files a/src/main/resources/assets/create/textures/block/redstone_antenna.png and b/src/main/resources/assets/create/textures/block/redstone_antenna.png differ diff --git a/src/main/resources/assets/create/textures/block/redstone_antenna_powered.png b/src/main/resources/assets/create/textures/block/redstone_antenna_powered.png index 6c3d5b696..2e883a28d 100644 Binary files a/src/main/resources/assets/create/textures/block/redstone_antenna_powered.png and b/src/main/resources/assets/create/textures/block/redstone_antenna_powered.png differ diff --git a/src/main/resources/assets/create/textures/gui/index.pdn b/src/main/resources/assets/create/textures/gui/index.pdn new file mode 100644 index 000000000..d9c63a53f Binary files /dev/null and b/src/main/resources/assets/create/textures/gui/index.pdn differ diff --git a/src/main/resources/assets/create/textures/gui/index.png b/src/main/resources/assets/create/textures/gui/index.png new file mode 100644 index 000000000..9a8c423fb Binary files /dev/null and b/src/main/resources/assets/create/textures/gui/index.png differ diff --git a/src/main/resources/assets/create/textures/gui/widgets.png b/src/main/resources/assets/create/textures/gui/widgets.png index 1c4f897f6..8ae74f83d 100644 Binary files a/src/main/resources/assets/create/textures/gui/widgets.png and b/src/main/resources/assets/create/textures/gui/widgets.png differ diff --git a/src/main/resources/assets/create/textures/item/cardboard_box_1410.png b/src/main/resources/assets/create/textures/item/cardboard_box_1410.png new file mode 100644 index 000000000..6ba4fffaf Binary files /dev/null and b/src/main/resources/assets/create/textures/item/cardboard_box_1410.png differ diff --git a/src/main/resources/assets/create/textures/item/cardboard_box_1416.png b/src/main/resources/assets/create/textures/item/cardboard_box_1416.png new file mode 100644 index 000000000..557a39a9c Binary files /dev/null and b/src/main/resources/assets/create/textures/item/cardboard_box_1416.png differ diff --git a/src/main/resources/assets/create/textures/item/cardboard_box_1612.png b/src/main/resources/assets/create/textures/item/cardboard_box_1612.png new file mode 100644 index 000000000..629f10cc3 Binary files /dev/null and b/src/main/resources/assets/create/textures/item/cardboard_box_1612.png differ diff --git a/src/main/resources/assets/create/textures/item/cardboard_box_1616.png b/src/main/resources/assets/create/textures/item/cardboard_box_1616.png new file mode 100644 index 000000000..f54db54c6 Binary files /dev/null and b/src/main/resources/assets/create/textures/item/cardboard_box_1616.png differ diff --git a/src/main/resources/assets/create/textures/item/cardboard_box_particle.png b/src/main/resources/assets/create/textures/item/cardboard_box_particle.png new file mode 100644 index 000000000..86e078106 Binary files /dev/null and b/src/main/resources/assets/create/textures/item/cardboard_box_particle.png differ diff --git a/src/main/resources/assets/create/textures/item/logistical_dial.png b/src/main/resources/assets/create/textures/item/logistical_dial.png new file mode 100644 index 000000000..f8074d857 Binary files /dev/null and b/src/main/resources/assets/create/textures/item/logistical_dial.png differ diff --git a/src/main/resources/assets/create/textures/item/logistical_dial_overlay.png b/src/main/resources/assets/create/textures/item/logistical_dial_overlay.png new file mode 100644 index 000000000..28c08005b Binary files /dev/null and b/src/main/resources/assets/create/textures/item/logistical_dial_overlay.png differ