From 488a9f63a971d77740bcf3de5150db43fd2dff3e Mon Sep 17 00:00:00 2001 From: simibubi <31564874+simibubi@users.noreply.github.com> Date: Fri, 11 Oct 2019 05:56:32 +0200 Subject: [PATCH] Lazy Logisticians - Added a new Villager type for delivering packages - Added the Logisticians Table - Added Package Funnels - Added a generic colorable indicator tileentityrenderer --- build.gradle | 4 +- .../java/com/simibubi/create/AllBlocks.java | 5 + .../java/com/simibubi/create/AllEntities.java | 4 +- .../com/simibubi/create/AllTileEntities.java | 12 +- src/main/java/com/simibubi/create/Create.java | 18 ++- .../utility/ColoredIndicatorRenderer.java | 77 +++++++++ .../contraptions/CachedBufferReloader.java | 6 +- .../modules/logistics/block/IExtractor.java | 2 +- .../block/belts/BeltFunnelBlock.java | 3 +- .../block/belts/BeltFunnelTileEntity.java | 30 ++-- .../diodes/FlexpeaterTileEntityRenderer.java | 69 +------- .../management/LogisticalDialItem.java | 17 +- .../management/LogisticalNetwork.java | 54 +++++-- .../management/LogisticalNetworkHandler.java | 6 +- .../base/ILogisticalCasingAttachment.java | 12 ++ .../management/base/LogisticalActor.java | 36 ----- .../base/LogisticalActorTileEntity.java | 150 +++++++++++++++++ .../base/LogisticalCasingTileEntity.java | 32 ++-- .../base/LogisticalControllerBlock.java | 30 +++- .../base/LogisticalControllerTileEntity.java | 143 +---------------- ...ogisticalControllerTileEntityRenderer.java | 74 +-------- .../management/base/LogisticalTask.java | 7 + .../base/LogisticalTileEntityExtension.java | 13 -- ...gisticalControllerConfigurationPacket.java | 2 +- .../LogisticalInventoryControllerScreen.java | 2 +- ...gisticalInventoryControllerTileEntity.java | 23 ++- .../controller/TransactionsTileEntity.java | 4 +- .../index/LogisticalIndexScreen.java | 13 +- .../index/LogisticalIndexTileEntity.java | 14 +- .../CardboardBoxEntity.java | 147 ++++++++++++++++- .../CardboardBoxEntityRenderer.java | 23 ++- .../villager/CollectPackageTask.java | 40 +++++ .../DeliverPackageToDestinationTask.java | 37 +++++ .../DropPackageAtDestinationTask.java | 37 +++++ .../villager/ExpireWorkstationTask.java | 38 +++++ .../villager/LogisticianHandler.java | 146 +++++++++++++++++ .../villager/LogisticiansTableBlock.java | 146 +++++++++++++++++ .../villager/LogisticiansTableTileEntity.java | 12 ++ .../LogisticiansTableTileEntityRenderer.java | 67 ++++++++ .../transport/villager/LookupAddressTask.java | 55 +++++++ .../villager/PackageDeliveryTask.java | 36 +++++ .../villager/PackageFunnelBlock.java | 111 +++++++++++++ .../villager/PackageFunnelTileEntity.java | 151 ++++++++++++++++++ .../transport/villager/WalkToPackageTask.java | 51 ++++++ .../villager/WalkToWorkstationTask.java | 45 ++++++ .../blockstates/logisticians_table.json | 14 ++ .../logisticians_table_indicator.json | 5 + .../assets/create/blockstates/motor.json | 12 +- .../create/blockstates/package_funnel.json | 16 ++ .../resources/assets/create/lang/en_us.json | 2 + .../models/block/logisticians_table.json | 58 +++++++ .../block/logisticians_table_indicator.json | 24 +++ .../create/models/block/package_funnel.json | 86 ++++++++++ .../models/block/package_funnel_vertical.json | 7 + .../models/item/logisticians_table.json | 3 + .../create/models/item/package_funnel.json | 3 + .../create/textures/block/belt_funnel.png | Bin 418 -> 531 bytes .../block/package_funnel_horizontal.png | Bin 0 -> 419 bytes .../block/package_funnel_vertical.png | Bin 0 -> 600 bytes .../villager/profession/logistician.png | Bin 0 -> 1180 bytes .../profession/logistician.png.mcmeta | 5 + .../create/textures/item/TEMPLATE_crushed.png | Bin 0 -> 395 bytes .../create/textures/item/crushed_gold.png | Bin 0 -> 432 bytes .../create/textures/item/crushed_iron.png | Bin 0 -> 409 bytes 64 files changed, 1810 insertions(+), 429 deletions(-) create mode 100644 src/main/java/com/simibubi/create/foundation/utility/ColoredIndicatorRenderer.java create mode 100644 src/main/java/com/simibubi/create/modules/logistics/management/base/ILogisticalCasingAttachment.java delete mode 100644 src/main/java/com/simibubi/create/modules/logistics/management/base/LogisticalActor.java create mode 100644 src/main/java/com/simibubi/create/modules/logistics/management/base/LogisticalActorTileEntity.java delete mode 100644 src/main/java/com/simibubi/create/modules/logistics/management/base/LogisticalTileEntityExtension.java rename src/main/java/com/simibubi/create/modules/logistics/{entity => transport}/CardboardBoxEntity.java (67%) rename src/main/java/com/simibubi/create/modules/logistics/{entity => transport}/CardboardBoxEntityRenderer.java (80%) create mode 100644 src/main/java/com/simibubi/create/modules/logistics/transport/villager/CollectPackageTask.java create mode 100644 src/main/java/com/simibubi/create/modules/logistics/transport/villager/DeliverPackageToDestinationTask.java create mode 100644 src/main/java/com/simibubi/create/modules/logistics/transport/villager/DropPackageAtDestinationTask.java create mode 100644 src/main/java/com/simibubi/create/modules/logistics/transport/villager/ExpireWorkstationTask.java create mode 100644 src/main/java/com/simibubi/create/modules/logistics/transport/villager/LogisticianHandler.java create mode 100644 src/main/java/com/simibubi/create/modules/logistics/transport/villager/LogisticiansTableBlock.java create mode 100644 src/main/java/com/simibubi/create/modules/logistics/transport/villager/LogisticiansTableTileEntity.java create mode 100644 src/main/java/com/simibubi/create/modules/logistics/transport/villager/LogisticiansTableTileEntityRenderer.java create mode 100644 src/main/java/com/simibubi/create/modules/logistics/transport/villager/LookupAddressTask.java create mode 100644 src/main/java/com/simibubi/create/modules/logistics/transport/villager/PackageDeliveryTask.java create mode 100644 src/main/java/com/simibubi/create/modules/logistics/transport/villager/PackageFunnelBlock.java create mode 100644 src/main/java/com/simibubi/create/modules/logistics/transport/villager/PackageFunnelTileEntity.java create mode 100644 src/main/java/com/simibubi/create/modules/logistics/transport/villager/WalkToPackageTask.java create mode 100644 src/main/java/com/simibubi/create/modules/logistics/transport/villager/WalkToWorkstationTask.java create mode 100644 src/main/resources/assets/create/blockstates/logisticians_table.json create mode 100644 src/main/resources/assets/create/blockstates/logisticians_table_indicator.json create mode 100644 src/main/resources/assets/create/blockstates/package_funnel.json create mode 100644 src/main/resources/assets/create/models/block/logisticians_table.json create mode 100644 src/main/resources/assets/create/models/block/logisticians_table_indicator.json create mode 100644 src/main/resources/assets/create/models/block/package_funnel.json create mode 100644 src/main/resources/assets/create/models/block/package_funnel_vertical.json create mode 100644 src/main/resources/assets/create/models/item/logisticians_table.json create mode 100644 src/main/resources/assets/create/models/item/package_funnel.json create mode 100644 src/main/resources/assets/create/textures/block/package_funnel_horizontal.png create mode 100644 src/main/resources/assets/create/textures/block/package_funnel_vertical.png create mode 100644 src/main/resources/assets/create/textures/entity/villager/profession/logistician.png create mode 100644 src/main/resources/assets/create/textures/entity/villager/profession/logistician.png.mcmeta create mode 100644 src/main/resources/assets/create/textures/item/TEMPLATE_crushed.png create mode 100644 src/main/resources/assets/create/textures/item/crushed_gold.png create mode 100644 src/main/resources/assets/create/textures/item/crushed_iron.png diff --git a/build.gradle b/build.gradle index 415ead953..afa8a08c3 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: '20190927-1.14.3' + mappings channel: 'snapshot', version: '20191008-1.14.3' runs { client { @@ -71,7 +71,7 @@ repositories { } dependencies { - minecraft 'net.minecraftforge:forge:1.14.4-28.1.22' + minecraft 'net.minecraftforge:forge:1.14.4-28.1.40' // 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") diff --git a/src/main/java/com/simibubi/create/AllBlocks.java b/src/main/java/com/simibubi/create/AllBlocks.java index 04795b8b5..6e1a9d412 100644 --- a/src/main/java/com/simibubi/create/AllBlocks.java +++ b/src/main/java/com/simibubi/create/AllBlocks.java @@ -50,6 +50,8 @@ import com.simibubi.create.modules.logistics.management.base.LogisticalCasingBlo 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.logistics.transport.villager.LogisticiansTableBlock; +import com.simibubi.create.modules.logistics.transport.villager.PackageFunnelBlock; import com.simibubi.create.modules.palettes.GlassPaneBlock; import com.simibubi.create.modules.schematics.block.CreativeCrateBlock; import com.simibubi.create.modules.schematics.block.SchematicTableBlock; @@ -133,6 +135,9 @@ public enum AllBlocks { LOGISTICAL_CONTROLLER(new LogisticalControllerBlock()), LOGISTICAL_CONTROLLER_INDICATOR(new LogisticalControllerIndicatorBlock()), LOGISTICAL_INDEX(new LogisticalIndexBlock()), + PACKAGE_FUNNEL(new PackageFunnelBlock()), + LOGISTICIANS_TABLE(new LogisticiansTableBlock()), + LOGISTICIANS_TABLE_INDICATOR(new RenderUtilityBlock()), __CURIOSITIES__(), SYMMETRY_PLANE(new PlaneSymmetryBlock()), diff --git a/src/main/java/com/simibubi/create/AllEntities.java b/src/main/java/com/simibubi/create/AllEntities.java index 8cb707c2a..74bd8d7bf 100644 --- a/src/main/java/com/simibubi/create/AllEntities.java +++ b/src/main/java/com/simibubi/create/AllEntities.java @@ -2,8 +2,8 @@ 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 com.simibubi.create.modules.logistics.transport.CardboardBoxEntity; +import com.simibubi.create.modules.logistics.transport.CardboardBoxEntityRenderer; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityClassification; diff --git a/src/main/java/com/simibubi/create/AllTileEntities.java b/src/main/java/com/simibubi/create/AllTileEntities.java index 82ae2d708..3133c98ef 100644 --- a/src/main/java/com/simibubi/create/AllTileEntities.java +++ b/src/main/java/com/simibubi/create/AllTileEntities.java @@ -52,6 +52,9 @@ import com.simibubi.create.modules.logistics.management.controller.StorageTileEn 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.logistics.transport.villager.LogisticiansTableTileEntity; +import com.simibubi.create.modules.logistics.transport.villager.LogisticiansTableTileEntityRenderer; +import com.simibubi.create.modules.logistics.transport.villager.PackageFunnelTileEntity; import com.simibubi.create.modules.schematics.block.SchematicTableTileEntity; import com.simibubi.create.modules.schematics.block.SchematicannonRenderer; import com.simibubi.create.modules.schematics.block.SchematicannonTileEntity; @@ -111,7 +114,9 @@ public enum AllTileEntities { LOGISTICAL_CALCULATION_CONTROLLER(CalculationTileEntity::new, AllBlocks.LOGISTICAL_CONTROLLER), LOGISTICAL_TRANSATIONS_CONTROLLER(TransactionsTileEntity::new, AllBlocks.LOGISTICAL_CONTROLLER), LOGISTICAL_INDEX(LogisticalIndexTileEntity::new, AllBlocks.LOGISTICAL_INDEX), - + LOGISTICIANS_TABLE(LogisticiansTableTileEntity::new, AllBlocks.LOGISTICIANS_TABLE), + PACKAGE_FUNNEL(PackageFunnelTileEntity::new, AllBlocks.PACKAGE_FUNNEL), + // Curiosities WINDOW_IN_A_BLOCK(WindowInABlockTileEntity::new, AllBlocks.WINDOW_IN_A_BLOCK), @@ -125,6 +130,10 @@ public enum AllTileEntities { this.supplier = supplier; this.blocks = blocks; } + + public boolean typeOf(TileEntity te) { + return te.getType().equals(type); + } @SubscribeEvent public static void onTileEntityRegistry(final RegistryEvent.Register> event) { @@ -165,6 +174,7 @@ public enum AllTileEntities { bind(MechanicalPressTileEntity.class, new MechanicalPressTileEntityRenderer()); bind(FlexpeaterTileEntity.class, new FlexpeaterTileEntityRenderer()); bind(LogisticalControllerTileEntity.class, new LogisticalControllerTileEntityRenderer()); + bind(LogisticiansTableTileEntity.class, new LogisticiansTableTileEntityRenderer()); } @OnlyIn(Dist.CLIENT) diff --git a/src/main/java/com/simibubi/create/Create.java b/src/main/java/com/simibubi/create/Create.java index c22e66c3e..c352363b5 100644 --- a/src/main/java/com/simibubi/create/Create.java +++ b/src/main/java/com/simibubi/create/Create.java @@ -7,13 +7,16 @@ 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.logistics.transport.villager.LogisticianHandler; import com.simibubi.create.modules.schematics.ServerSchematicLoader; import net.minecraft.block.Block; import net.minecraft.entity.EntityType; +import net.minecraft.entity.merchant.villager.VillagerProfession; import net.minecraft.item.Item; import net.minecraft.item.ItemGroup; import net.minecraft.item.crafting.IRecipeSerializer; +import net.minecraft.village.PointOfInterestType; import net.minecraftforge.common.crafting.CraftingHelper; import net.minecraftforge.event.RegistryEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; @@ -38,6 +41,7 @@ public class Create { public static FrequencyHandler frequencyHandler; public static MovingConstructHandler constructHandler; public static LogisticalNetworkHandler logisticalNetworkHandler; + public static LogisticianHandler logisticianHandler; public static ModConfig config; @@ -52,7 +56,7 @@ public class Create { frequencyHandler = new FrequencyHandler(); constructHandler = new MovingConstructHandler(); logisticalNetworkHandler = new LogisticalNetworkHandler(); - + CraftingHelper.register(new ModuleLoadedCondition.Serializer()); AllPackets.registerPackets(); } @@ -72,12 +76,22 @@ 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 registerVillagerProfessions(RegistryEvent.Register event) { + LogisticianHandler.registerVillagerProfessions(event); + } + + @SubscribeEvent + public static void registerPointsOfInterest(RegistryEvent.Register event) { + LogisticianHandler.registerPointsOfInterest(event); + } + @SubscribeEvent public static void createConfigs(ModConfig.ModConfigEvent event) { if (event.getConfig().getSpec() == CreateClientConfig.specification) diff --git a/src/main/java/com/simibubi/create/foundation/utility/ColoredIndicatorRenderer.java b/src/main/java/com/simibubi/create/foundation/utility/ColoredIndicatorRenderer.java new file mode 100644 index 000000000..921e13973 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/utility/ColoredIndicatorRenderer.java @@ -0,0 +1,77 @@ +package com.simibubi.create.foundation.utility; + +import java.nio.ByteBuffer; +import java.util.HashMap; +import java.util.Map; +import java.util.Random; +import java.util.function.Function; + +import org.lwjgl.opengl.GL11; + +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.data.EmptyModelData; + +public class ColoredIndicatorRenderer extends BufferManipulator { + + protected static Map cachedBuffers = new HashMap<>(); + + public ColoredIndicatorRenderer(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; + } + + public static void cacheIfMissing(BlockState renderedState, + Function factory) { + 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(Minecraft.getInstance().world, originalModel, renderedState, + BlockPos.ZERO.down(), builder, true, random, 42, EmptyModelData.INSTANCE); + builder.finishDrawing(); + + cachedBuffers.put(renderedState, factory.apply(builder.getByteBuffer())); + } + } + + public static ColoredIndicatorRenderer get(BlockState state) { + cacheIfMissing(state, ColoredIndicatorRenderer::new); + return cachedBuffers.get(state); + } + + + public static void invalidateCache() { + cachedBuffers.clear(); + } + +} 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 6f1fb9c9a..04914c81f 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/CachedBufferReloader.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/CachedBufferReloader.java @@ -1,10 +1,9 @@ package com.simibubi.create.modules.contraptions; +import com.simibubi.create.foundation.utility.ColoredIndicatorRenderer; 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,8 +21,7 @@ public class CachedBufferReloader extends ReloadListener { KineticTileEntityRenderer.invalidateCache(); MechanicalPistonTileEntityRenderer.invalidateCache(); MechanicalBearingTileEntityRenderer.invalidateCache(); - FlexpeaterTileEntityRenderer.invalidateCache(); - LogisticalControllerTileEntityRenderer.invalidateCache(); + ColoredIndicatorRenderer.invalidateCache(); } 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 bcb69d095..e0dd32aae 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 @@ -4,8 +4,8 @@ import static net.minecraft.state.properties.BlockStateProperties.HORIZONTAL_FAC 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 com.simibubi.create.modules.logistics.transport.CardboardBoxEntity; import net.minecraft.entity.Entity; import net.minecraft.entity.item.ItemEntity; diff --git a/src/main/java/com/simibubi/create/modules/logistics/block/belts/BeltFunnelBlock.java b/src/main/java/com/simibubi/create/modules/logistics/block/belts/BeltFunnelBlock.java index c3b32e0f3..8f5b014f0 100644 --- a/src/main/java/com/simibubi/create/modules/logistics/block/belts/BeltFunnelBlock.java +++ b/src/main/java/com/simibubi/create/modules/logistics/block/belts/BeltFunnelBlock.java @@ -12,7 +12,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.Slope; import com.simibubi.create.modules.logistics.block.IInventoryManipulator; -import com.simibubi.create.modules.logistics.entity.CardboardBoxEntity; +import com.simibubi.create.modules.logistics.transport.CardboardBoxEntity; import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntity; import net.minecraft.block.Block; @@ -141,7 +141,6 @@ public class BeltFunnelBlock extends HorizontalBlock implements IBeltAttachment, boolean slope = te.getBlockState().get(BeltBlock.SLOPE) != Slope.HORIZONTAL; 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(entity); diff --git a/src/main/java/com/simibubi/create/modules/logistics/block/belts/BeltFunnelTileEntity.java b/src/main/java/com/simibubi/create/modules/logistics/block/belts/BeltFunnelTileEntity.java index 9e1e2f16c..dfbf5e4e6 100644 --- a/src/main/java/com/simibubi/create/modules/logistics/block/belts/BeltFunnelTileEntity.java +++ b/src/main/java/com/simibubi/create/modules/logistics/block/belts/BeltFunnelTileEntity.java @@ -3,7 +3,7 @@ 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 com.simibubi.create.modules.logistics.transport.CardboardBoxEntity; import net.minecraft.entity.Entity; import net.minecraft.entity.item.ItemEntity; @@ -19,6 +19,7 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3i; import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.items.IItemHandler; +import net.minecraftforge.items.ItemHandlerHelper; public class BeltFunnelTileEntity extends SyncedTileEntity implements ITickableTileEntity, IInventoryManipulator { @@ -99,21 +100,20 @@ public class BeltFunnelTileEntity extends SyncedTileEntity implements ITickableT 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); - if (stack.isEmpty()) { - if (!world.isRemote) { - entity.remove(); - world.playSound(null, pos, SoundEvents.ENTITY_GENERIC_EAT, SoundCategory.BLOCKS, .125f, 1f); - } 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, stack), entity.posX, - entity.posY, entity.posZ, xSpeed, 1 / 6f, zSpeed); - } - return; + stack = ItemHandlerHelper.insertItemStacked(inv, stack, false); + + if (stack.isEmpty()) { + if (!world.isRemote) { + entity.remove(); + world.playSound(null, pos, SoundEvents.ENTITY_GENERIC_EAT, SoundCategory.BLOCKS, .125f, 1f); + } 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, stack), entity.posX, + entity.posY, entity.posZ, xSpeed, 1 / 6f, zSpeed); } + return; } waitingForInventorySpace = true; diff --git a/src/main/java/com/simibubi/create/modules/logistics/block/diodes/FlexpeaterTileEntityRenderer.java b/src/main/java/com/simibubi/create/modules/logistics/block/diodes/FlexpeaterTileEntityRenderer.java index 619ed0638..23e6ad7b1 100644 --- a/src/main/java/com/simibubi/create/modules/logistics/block/diodes/FlexpeaterTileEntityRenderer.java +++ b/src/main/java/com/simibubi/create/modules/logistics/block/diodes/FlexpeaterTileEntityRenderer.java @@ -1,87 +1,28 @@ package com.simibubi.create.modules.logistics.block.diodes; -import java.nio.ByteBuffer; -import java.util.Random; - -import org.lwjgl.opengl.GL11; - import com.simibubi.create.AllBlocks; -import com.simibubi.create.foundation.utility.BufferManipulator; import com.simibubi.create.foundation.utility.ColorHelper; +import com.simibubi.create.foundation.utility.ColoredIndicatorRenderer; 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 FlexpeaterTileEntityRenderer extends TileEntityRendererFast { - protected class FlexpeaterIndicatorRenderer extends BufferManipulator { - - public FlexpeaterIndicatorRenderer(ByteBuffer original) { - super(original); - } - - public ByteBuffer getTransformed(float xIn, float yIn, float zIn, float colorModifier, int packedLightCoords) { - original.rewind(); - mutable.rewind(); - - int color = ColorHelper.mixColors(0x2C0300, 0xCD0000, colorModifier); - - 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 FlexpeaterIndicatorRenderer cachedIndicator; - @Override public void renderTileEntityFast(FlexpeaterTileEntity te, double x, double y, double z, float partialTicks, int destroyStage, BufferBuilder buffer) { BlockPos pos = te.getPos(); - if (cachedIndicator == null) { - BlockState renderedState = AllBlocks.FLEXPEATER_INDICATOR.get().getDefaultState(); - 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(); - - cachedIndicator = new FlexpeaterIndicatorRenderer(builder.getByteBuffer()); - } - + BlockState renderedState = AllBlocks.FLEXPEATER_INDICATOR.get().getDefaultState(); BlockState blockState = te.getBlockState(); + int color = ColorHelper.mixColors(0x2C0300, 0xCD0000, te.state / (float) te.maxState); int packedLightmapCoords = blockState.getPackedLightmapCoords(getWorld(), pos); - buffer.putBulkData(cachedIndicator.getTransformed((float) x, (float) y, (float) z, - te.state / (float) te.maxState, packedLightmapCoords)); - } - public static void invalidateCache() { - cachedIndicator = null; + buffer.putBulkData(ColoredIndicatorRenderer.get(renderedState).getTransformed((float) x, (float) y, (float) z, + color, packedLightmapCoords)); } } 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 index daecb8a8f..6f18d9d19 100644 --- a/src/main/java/com/simibubi/create/modules/logistics/management/LogisticalDialItem.java +++ b/src/main/java/com/simibubi/create/modules/logistics/management/LogisticalDialItem.java @@ -1,20 +1,17 @@ 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 com.simibubi.create.modules.logistics.management.base.LogisticalActorTileEntity; -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.tileentity.TileEntity; import net.minecraft.util.ActionResult; import net.minecraft.util.ActionResultType; import net.minecraft.util.Hand; @@ -30,7 +27,7 @@ public class LogisticalDialItem extends Item implements IItemWithColorHandler { public IItemColor getColorHandler() { return (stack, layer) -> { if (layer == 1 && stack.getOrCreateTag().contains("NetworkIDLeast")) - return LogisticalControllerTileEntity.colorFromUUID(stack.getTag().getUniqueId("NetworkID")); + return LogisticalActorTileEntity.colorFromUUID(stack.getTag().getUniqueId("NetworkID")); return 0xFFFFFF; }; } @@ -48,8 +45,9 @@ public class LogisticalDialItem extends Item implements IItemWithColorHandler { if (!context.getPlayer().isAllowEdit()) return super.onItemUse(context); - BlockState blockState = context.getWorld().getBlockState(context.getPos()); - if (!LOGISTICAL_CONTROLLER.typeOf(blockState) && !LOGISTICAL_INDEX.typeOf(blockState)) { + + TileEntity te = context.getWorld().getTileEntity(context.getPos()); + if (!(te instanceof LogisticalActorTileEntity)) { if (context.isPlacerSneaking()) { if (!isRemote) heldItem.getTag().putUniqueId("NetworkID", UUID.randomUUID()); @@ -59,8 +57,7 @@ public class LogisticalDialItem extends Item implements IItemWithColorHandler { return super.onItemUse(context); } - LogisticalControllerTileEntity tileEntity = (LogisticalControllerTileEntity) context.getWorld() - .getTileEntity(context.getPos()); + LogisticalActorTileEntity tileEntity = (LogisticalActorTileEntity) te; if (context.isPlacerSneaking()) { if (!isRemote) heldItem.getTag().putUniqueId("NetworkID", tileEntity.getNetworkId()); 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 index 8e66ac355..fef1793b0 100644 --- a/src/main/java/com/simibubi/create/modules/logistics/management/LogisticalNetwork.java +++ b/src/main/java/com/simibubi/create/modules/logistics/management/LogisticalNetwork.java @@ -2,29 +2,36 @@ package com.simibubi.create.modules.logistics.management; import java.util.ArrayList; import java.util.Collection; +import java.util.HashSet; import java.util.List; import java.util.PriorityQueue; +import java.util.Set; import java.util.function.Predicate; -import com.simibubi.create.modules.logistics.management.base.LogisticalControllerTileEntity; +import com.simibubi.create.modules.logistics.management.base.LogisticalActorTileEntity; 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.StorageTileEntity; import com.simibubi.create.modules.logistics.management.controller.TransactionsTileEntity; import com.simibubi.create.modules.logistics.management.index.LogisticalIndexTileEntity; +import com.simibubi.create.modules.logistics.transport.villager.PackageFunnelTileEntity; + +import net.minecraft.client.Minecraft; +import net.minecraft.util.text.StringTextComponent; public class LogisticalNetwork { public List taskQueues = new ArrayList<>(); public List indexers = new ArrayList<>(); + public Set packageTargets = new HashSet<>(); public PriorityQueue internalTaskQueue = new PriorityQueue<>(); - public PriorityQueue suppliers = new PriorityQueue<>(); - public PriorityQueue receivers = new PriorityQueue<>(); + public PriorityQueue suppliers = new PriorityQueue<>(); + public PriorityQueue receivers = new PriorityQueue<>(); public int participants = 0; public boolean tasksUpdated; - public void addController(LogisticalControllerTileEntity te) { + public void addController(LogisticalActorTileEntity te) { if (te instanceof TransactionsTileEntity) { if (taskQueues.contains(te)) return; @@ -49,11 +56,19 @@ public class LogisticalNetwork { participants++; } + public void addPackageTarget(PackageFunnelTileEntity te) { + packageTargets.add(te); + } + + public void removePackageTarget(PackageFunnelTileEntity te) { + packageTargets.remove(te); + } + public void reAdvertiseReceivers() { indexers.forEach(LogisticalIndexTileEntity::syncReceivers); } - public void removeController(LogisticalControllerTileEntity te) { + public void removeController(LogisticalActorTileEntity te) { if (te instanceof TransactionsTileEntity) if (!taskQueues.remove((TransactionsTileEntity) te)) return; @@ -77,56 +92,63 @@ public class LogisticalNetwork { public void enqueueTask(LogisticalTask task) { internalTaskQueue.add(task); + + Minecraft.getInstance().player.sendMessage(new StringTextComponent(internalTaskQueue.toString())); + if (task instanceof SupplyTask) - suppliers.forEach(LogisticalControllerTileEntity::notifyTaskUpdate); + suppliers.forEach(LogisticalActorTileEntity::notifyTaskUpdate); if (task instanceof DepositTask) - receivers.forEach(LogisticalControllerTileEntity::notifyTaskUpdate); + receivers.forEach(LogisticalActorTileEntity::notifyTaskUpdate); } - public String getNextAvailableAddress(LogisticalControllerTileEntity te) { + public String getNextAvailableAddress(LogisticalActorTileEntity te) { Predicate isTaken = s -> false; String prefix = ""; if (te instanceof TransactionsTileEntity) { - prefix = "Task Manager "; + prefix = "Task Manager"; isTaken = s -> isNameTaken(taskQueues, s); } else if (te instanceof LogisticalIndexTileEntity) { - prefix = "Index "; + prefix = "Index"; isTaken = s -> isNameTaken(indexers, s); } else if (te instanceof StorageTileEntity) { - prefix = "Storage "; + prefix = "Storage"; isTaken = s -> isNameTaken(suppliers, s); } - + else if (te.isSupplier()) { - prefix = "Supply "; + prefix = "Supply"; isTaken = s -> isNameTaken(suppliers, s); } else if (te.isReceiver()) { - prefix = "Request "; + prefix = "Request"; isTaken = s -> isNameTaken(receivers, s); } int i = 0; String name; do { - name = prefix + (i == 0 ? "" : i); + name = prefix + (i == 0 ? "" : " " + i); i++; } while (isTaken.test(name)); return name; } - private static boolean isNameTaken(Collection list, String name) { + private static boolean isNameTaken(Collection list, String name) { for (T controller : list) if (controller.address.equals(name)) return true; return false; } + + public static boolean matchAddresses(String addr1, String addr2) { + return addr1.toLowerCase().equals(addr2.toLowerCase()); + } } 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 index c812c6a28..0da1cba99 100644 --- a/src/main/java/com/simibubi/create/modules/logistics/management/LogisticalNetworkHandler.java +++ b/src/main/java/com/simibubi/create/modules/logistics/management/LogisticalNetworkHandler.java @@ -5,7 +5,7 @@ import java.util.Map; import java.util.UUID; import com.simibubi.create.Create; -import com.simibubi.create.modules.logistics.management.base.LogisticalControllerTileEntity; +import com.simibubi.create.modules.logistics.management.base.LogisticalActorTileEntity; import net.minecraft.world.IWorld; @@ -23,7 +23,7 @@ public class LogisticalNetworkHandler { Create.logger.debug("Removed Logistical Network Map for " + world.getDimension().getType().getRegistryName()); } - public LogisticalNetwork handleAdded(LogisticalControllerTileEntity te) { + public LogisticalNetwork handleAdded(LogisticalActorTileEntity te) { LogisticalNetwork networkByID = getNetworkByID(te.getWorld(), te.getNetworkId()); if (te.address == null || te.address.isEmpty()) { te.address = networkByID.getNextAvailableAddress(te); @@ -33,7 +33,7 @@ public class LogisticalNetworkHandler { return networkByID; } - public void handleRemoved(LogisticalControllerTileEntity te) { + public void handleRemoved(LogisticalActorTileEntity te) { getNetworkByID(te.getWorld(), te.getNetworkId()).removeController(te); removeIfEmpty(te.getWorld(), te.getNetworkId()); } diff --git a/src/main/java/com/simibubi/create/modules/logistics/management/base/ILogisticalCasingAttachment.java b/src/main/java/com/simibubi/create/modules/logistics/management/base/ILogisticalCasingAttachment.java new file mode 100644 index 000000000..734b6d4c4 --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/logistics/management/base/ILogisticalCasingAttachment.java @@ -0,0 +1,12 @@ +package com.simibubi.create.modules.logistics.management.base; + +import javax.annotation.Nullable; + +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.IWorld; + +public interface ILogisticalCasingAttachment { + + public void onCasingUpdated(IWorld world, BlockPos pos, @Nullable LogisticalCasingTileEntity te); + +} 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 deleted file mode 100644 index 6a3b8b7ff..000000000 --- a/src/main/java/com/simibubi/create/modules/logistics/management/base/LogisticalActor.java +++ /dev/null @@ -1,36 +0,0 @@ -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/LogisticalActorTileEntity.java b/src/main/java/com/simibubi/create/modules/logistics/management/base/LogisticalActorTileEntity.java new file mode 100644 index 000000000..b248dbb91 --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/logistics/management/base/LogisticalActorTileEntity.java @@ -0,0 +1,150 @@ +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 LogisticalActorTileEntity extends SyncedTileEntity + implements Comparable, ITickableTileEntity { + + public static final int COOLDOWN = 20; + + public Priority priority = Priority.LOW; + public String address = ""; + + protected LogisticalNetwork network; + protected UUID networkId; + protected boolean initialize; + protected boolean checkTasks; + protected int taskCooldown; + + public LogisticalActorTileEntity(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 notifyTaskUpdate() { + checkTasks = true; + } + + @Override + public CompoundNBT write(CompoundNBT compound) { + if (networkId != null) + compound.putUniqueId("NetworkID", networkId); + compound.putString("Address", address); + compound.putInt("Priority", priority.ordinal()); + return super.write(compound); + } + + public UUID getNetworkId() { + return networkId; + } + + @Override + public void read(CompoundNBT compound) { + if (compound.contains("NetworkIDLeast")) + networkId = compound.getUniqueId("NetworkID"); + address = compound.getString("Address"); + priority = Priority.values()[compound.getInt("Priority")]; + 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(LogisticalActorTileEntity o) { + return this.priority.compareTo(o.priority); + } + + public LogisticalNetwork getNetwork() { + return network; + } + + public Priority getPriority() { + return priority; + } + + public static enum Priority { + HIGHEST, HIGH, LOWEST, LOW; + } + +} 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 index 663872368..c370113c9 100644 --- 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 @@ -11,6 +11,7 @@ import com.simibubi.create.AllTileEntities; import com.simibubi.create.foundation.block.SyncedTileEntity; import com.simibubi.create.modules.logistics.management.controller.LogisticalInventoryControllerTileEntity; +import net.minecraft.block.Block; import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.ListNBT; import net.minecraft.nbt.NBTUtil; @@ -60,7 +61,7 @@ public class LogisticalCasingTileEntity extends SyncedTileEntity { public void neighbourChanged(BlockPos neighbour) { if (!controllerPresent()) return; - for (LogisticalControllerTileEntity controller : getControllers()) { + for (LogisticalActorTileEntity controller : getControllers()) { if (!(controller instanceof LogisticalInventoryControllerTileEntity)) continue; ((LogisticalInventoryControllerTileEntity) controller).inventoryChanged(neighbour); @@ -86,18 +87,29 @@ public class LogisticalCasingTileEntity extends SyncedTileEntity { TileEntity tileEntity = world.getTileEntity(pos); if (!(tileEntity instanceof LogisticalInventoryControllerTileEntity)) return; - for (Direction facing : Direction.values()) + for (Direction facing : Direction.values()) { ((LogisticalInventoryControllerTileEntity) tileEntity).detachInventory(getPos().offset(facing)); + notifyAttachments(facing); + } } public void attachController(BlockPos pos) { TileEntity tileEntity = world.getTileEntity(pos); - if (!(tileEntity instanceof LogisticalControllerTileEntity)) + if (!(tileEntity instanceof LogisticalInventoryControllerTileEntity)) return; - for (Direction facing : Direction.values()) + for (Direction facing : Direction.values()) { ((LogisticalInventoryControllerTileEntity) tileEntity).inventoryChanged(getPos().offset(facing)); + notifyAttachments(facing); + } } - + + private void notifyAttachments(Direction d) { + BlockPos offset = pos.offset(d); + Block block = world.getBlockState(offset).getBlock(); + if (block instanceof ILogisticalCasingAttachment) + ((ILogisticalCasingAttachment) block).onCasingUpdated(world, offset, this); + } + @Override public void remove() { controllers.forEach(this::detachController); @@ -108,7 +120,7 @@ public class LogisticalCasingTileEntity extends SyncedTileEntity { public LazyOptional getCapability(Capability cap, Direction side) { if (!controllerPresent()) return LazyOptional.empty(); - List TEs = getControllers(); + List TEs = getControllers(); if (controllers.isEmpty()) return LazyOptional.empty(); List invs = TEs.stream().map(te -> te.getCasingCapability(cap, side).orElse(null)) @@ -119,12 +131,12 @@ public class LogisticalCasingTileEntity extends SyncedTileEntity { return LazyOptional.of(() -> new CombinedInvWrapper(params)).cast(); } - public List getControllers() { - List TEs = new ArrayList<>(controllers.size()); + 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); + if (tileEntity instanceof LogisticalActorTileEntity) + TEs.add((LogisticalActorTileEntity) 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 index bb58623b9..32e6149cf 100644 --- 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 @@ -1,11 +1,17 @@ package com.simibubi.create.modules.logistics.management.base; +import static com.simibubi.create.AllItems.LOGISTICAL_CONTROLLER_CALCULATION; +import static com.simibubi.create.AllItems.LOGISTICAL_CONTROLLER_REQUEST; +import static com.simibubi.create.AllItems.LOGISTICAL_CONTROLLER_STORAGE; +import static com.simibubi.create.AllItems.LOGISTICAL_CONTROLLER_SUPPLY; +import static com.simibubi.create.AllItems.LOGISTICAL_CONTROLLER_TRANSACTIONS; 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.Arrays; import java.util.Collections; import java.util.List; @@ -43,6 +49,7 @@ 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.RayTraceResult; import net.minecraft.util.math.shapes.ISelectionContext; import net.minecraft.util.math.shapes.VoxelShape; import net.minecraft.util.math.shapes.VoxelShapes; @@ -52,7 +59,7 @@ import net.minecraft.world.World; import net.minecraftforge.fml.network.NetworkHooks; public class LogisticalControllerBlock extends DirectionalBlock - implements IWithoutBlockItem, IWithTileEntity { + implements IWithoutBlockItem, IWithTileEntity { public static final IProperty TYPE = EnumProperty.create("type", Type.class); @@ -121,6 +128,27 @@ public class LogisticalControllerBlock extends DirectionalBlock return state; } + @Override + public ItemStack getPickBlock(BlockState state, RayTraceResult target, IBlockReader world, BlockPos pos, + PlayerEntity player) { + return getItem(world, pos, state); + } + + @Override + public List getDrops(BlockState state, net.minecraft.world.storage.loot.LootContext.Builder builder) { + return Arrays.asList(getItem(builder.getWorld(), BlockPos.ZERO, state)); + } + + @Override + public ItemStack getItem(IBlockReader worldIn, BlockPos pos, BlockState state) { + for (AllItems item : Arrays.asList(LOGISTICAL_CONTROLLER_CALCULATION, LOGISTICAL_CONTROLLER_REQUEST, + LOGISTICAL_CONTROLLER_STORAGE, LOGISTICAL_CONTROLLER_SUPPLY, LOGISTICAL_CONTROLLER_TRANSACTIONS)) { + if (((LogisticalControllerItem) item.get()).getType() == state.get(TYPE)) + return item.asStack(); + } + return ItemStack.EMPTY; + } + @Override public boolean isValidPosition(BlockState state, IWorldReader worldIn, BlockPos pos) { Direction facing = state.get(FACING); 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 index d23812466..c2b8c74ca 100644 --- 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 @@ -1,155 +1,16 @@ 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; - - public Priority priority = Priority.LOW; - public String address = ""; - - protected LogisticalNetwork network; - protected UUID networkId; - protected boolean initialize; - protected boolean checkTasks; - protected int taskCooldown; +public abstract class LogisticalControllerTileEntity extends LogisticalActorTileEntity { 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(); - } - + @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", address); - compound.putInt("Priority", priority.ordinal()); - return super.write(compound); - } - - public UUID getNetworkId() { - return networkId; - } - - @Override - public void read(CompoundNBT compound) { - if (compound.contains("NetworkIDLeast")) - networkId = compound.getUniqueId("NetworkID"); - address = compound.getString("Address"); - priority = Priority.values()[compound.getInt("Priority")]; - 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 Priority getPriority() { - return priority; - } - - public static enum Priority { - HIGHEST, HIGH, LOWEST, LOW; - } - } 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 index f2b9492fa..84ff6c9ff 100644 --- 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 @@ -3,92 +3,26 @@ 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 com.simibubi.create.foundation.utility.ColoredIndicatorRenderer; 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<>(); +public class LogisticalControllerTileEntityRenderer extends TileEntityRendererFast { @Override - public void renderTileEntityFast(LogisticalControllerTileEntity te, double x, double y, double z, + public void renderTileEntityFast(LogisticalActorTileEntity 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, + buffer.putBulkData(ColoredIndicatorRenderer.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/LogisticalTask.java b/src/main/java/com/simibubi/create/modules/logistics/management/base/LogisticalTask.java index e18e3f265..e614f3839 100644 --- 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 @@ -26,12 +26,19 @@ public abstract class LogisticalTask implements Comparable { public static class SupplyTask extends LogisticalTask { public List> items; + private String display; public SupplyTask(ItemStackEntry requested, String address) { items = Arrays.asList(Pair.of(Ingredient.fromStacks(requested.stack), requested.amount)); targetAddress = address; + display = "Supply " + requested.amount + "x " + requested.stack.getItem().getName().getFormattedText() + + " -> " + address; } + @Override + public String toString() { + return display; + } } public static class DepositTask extends LogisticalTask { 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 deleted file mode 100644 index a36ce42fb..000000000 --- a/src/main/java/com/simibubi/create/modules/logistics/management/base/LogisticalTileEntityExtension.java +++ /dev/null @@ -1,13 +0,0 @@ -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/LogisticalControllerConfigurationPacket.java b/src/main/java/com/simibubi/create/modules/logistics/management/controller/LogisticalControllerConfigurationPacket.java index c75341a42..1d59f9440 100644 --- a/src/main/java/com/simibubi/create/modules/logistics/management/controller/LogisticalControllerConfigurationPacket.java +++ b/src/main/java/com/simibubi/create/modules/logistics/management/controller/LogisticalControllerConfigurationPacket.java @@ -1,7 +1,7 @@ package com.simibubi.create.modules.logistics.management.controller; import com.simibubi.create.foundation.packet.TileEntityConfigurationPacket; -import com.simibubi.create.modules.logistics.management.base.LogisticalControllerTileEntity.Priority; +import com.simibubi.create.modules.logistics.management.base.LogisticalActorTileEntity.Priority; import com.simibubi.create.modules.logistics.management.controller.LogisticalInventoryControllerTileEntity.ShippingInventory; import net.minecraft.network.PacketBuffer; diff --git a/src/main/java/com/simibubi/create/modules/logistics/management/controller/LogisticalInventoryControllerScreen.java b/src/main/java/com/simibubi/create/modules/logistics/management/controller/LogisticalInventoryControllerScreen.java index 38644624c..7e82a9ce5 100644 --- a/src/main/java/com/simibubi/create/modules/logistics/management/controller/LogisticalInventoryControllerScreen.java +++ b/src/main/java/com/simibubi/create/modules/logistics/management/controller/LogisticalInventoryControllerScreen.java @@ -31,7 +31,7 @@ import com.simibubi.create.foundation.utility.ColorHelper; import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.modules.logistics.management.base.LogisticalControllerBlock; import com.simibubi.create.modules.logistics.management.base.LogisticalControllerBlock.Type; -import com.simibubi.create.modules.logistics.management.base.LogisticalControllerTileEntity.Priority; +import com.simibubi.create.modules.logistics.management.base.LogisticalActorTileEntity.Priority; import net.minecraft.block.BlockState; import net.minecraft.client.gui.widget.TextFieldWidget; diff --git a/src/main/java/com/simibubi/create/modules/logistics/management/controller/LogisticalInventoryControllerTileEntity.java b/src/main/java/com/simibubi/create/modules/logistics/management/controller/LogisticalInventoryControllerTileEntity.java index 0b3839524..7ab1491b1 100644 --- a/src/main/java/com/simibubi/create/modules/logistics/management/controller/LogisticalInventoryControllerTileEntity.java +++ b/src/main/java/com/simibubi/create/modules/logistics/management/controller/LogisticalInventoryControllerTileEntity.java @@ -18,6 +18,7 @@ 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.LogisticalNetwork; import com.simibubi.create.modules.logistics.management.base.LogisticalCasingTileEntity; import com.simibubi.create.modules.logistics.management.base.LogisticalControllerBlock; import com.simibubi.create.modules.logistics.management.base.LogisticalControllerTileEntity; @@ -349,9 +350,9 @@ public abstract class LogisticalInventoryControllerTileEntity extends Logistical public class ShippingInventory extends ItemStackHandler { - static final int SHIPPING = 0; - static final int RECEIVING = 1; - static final int FILTER = 2; + public static final int SHIPPING = 0; + public static final int RECEIVING = 1; + public static final int FILTER = 2; int filterAmount = 0; boolean ships; @@ -402,10 +403,22 @@ public abstract class LogisticalInventoryControllerTileEntity extends Logistical protected void onContentsChanged(int slot) { super.onContentsChanged(slot); markDirty(); + boolean empty = getStackInSlot(slot).isEmpty(); - if (slot == RECEIVING && !getStackInSlot(slot).isEmpty()) + if (slot == RECEIVING && !empty) tryInsertBox = true; - if (slot == SHIPPING && getStackInSlot(slot).isEmpty()) + + if (slot == RECEIVING && empty) { + if (getNetwork() != null) { + getNetwork().packageTargets.forEach(target -> { + if (target.getAddressList().stream() + .anyMatch(e -> LogisticalNetwork.matchAddresses(e, address))) + target.slotOpened(); + }); + } + } + + if (slot == SHIPPING && empty) checkTasks = true; BlockPos start = pos.offset(getBlockState().get(FACING).getOpposite()); 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 index da1f21090..3d6f20043 100644 --- 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 @@ -1,9 +1,9 @@ package com.simibubi.create.modules.logistics.management.controller; import com.simibubi.create.AllTileEntities; -import com.simibubi.create.modules.logistics.management.base.LogisticalControllerTileEntity; +import com.simibubi.create.modules.logistics.management.base.LogisticalActorTileEntity; -public class TransactionsTileEntity extends LogisticalControllerTileEntity { +public class TransactionsTileEntity extends LogisticalActorTileEntity { public TransactionsTileEntity() { super(AllTileEntities.LOGISTICAL_TRANSATIONS_CONTROLLER.type); 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 index 1a1f89551..b8f9163ce 100644 --- 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 @@ -49,6 +49,7 @@ import net.minecraft.entity.player.PlayerInventory; import net.minecraft.item.ItemStack; import net.minecraft.util.math.MathHelper; import net.minecraft.util.text.ITextComponent; +import net.minecraft.util.text.StringTextComponent; public class LogisticalIndexScreen extends AbstractSimiContainerScreen { @@ -201,6 +202,8 @@ public class LogisticalIndexScreen extends AbstractSimiContainerScreen 1 ? String.valueOf(count) : null; int color = 0xFFFFFF; if (orderedFully) { - color = ColorHelper.mixColors(container.te.getColor(), 0, 0.5f); - text = "\\u2714"; + color = ColorHelper.mixColors(container.te.getColor(), 0xFFFFFF, 0.5f); + text = new StringTextComponent("\u2714").getFormattedText(); } this.renderItemOverlayIntoGUI(font, stack, slotX, slotY, text, color); 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 index 63dca8e9d..ff645e5f7 100644 --- 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 @@ -15,7 +15,7 @@ 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.LogisticalActorTileEntity; import com.simibubi.create.modules.logistics.management.controller.LogisticalInventoryControllerTileEntity; import com.simibubi.create.modules.logistics.management.index.IndexContainerUpdatePacket.Type; @@ -34,7 +34,7 @@ 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 { +public class LogisticalIndexTileEntity extends LogisticalActorTileEntity implements INamedContainerProvider { // Server public int nextPush; @@ -90,7 +90,7 @@ public class LogisticalIndexTileEntity extends LogisticalControllerTileEntity im if (network == null) return; availableReceivers.clear(); - for (LogisticalControllerTileEntity logisticalControllerTileEntity : network.receivers) + for (LogisticalActorTileEntity logisticalControllerTileEntity : network.receivers) availableReceivers.add(logisticalControllerTileEntity.address); sendData(); } @@ -112,12 +112,6 @@ public class LogisticalIndexTileEntity extends LogisticalControllerTileEntity im 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); @@ -161,7 +155,7 @@ public class LogisticalIndexTileEntity extends LogisticalControllerTileEntity im // First player to open if (!playersEntered.isEmpty() && playersUsing.size() == playersEntered.size()) { controllers.clear(); - for (LogisticalControllerTileEntity te : network.suppliers) { + for (LogisticalActorTileEntity te : network.suppliers) { if (!(te instanceof LogisticalInventoryControllerTileEntity)) continue; CountedItemsList allItems = ((LogisticalInventoryControllerTileEntity) te).getAllItems(); diff --git a/src/main/java/com/simibubi/create/modules/logistics/entity/CardboardBoxEntity.java b/src/main/java/com/simibubi/create/modules/logistics/transport/CardboardBoxEntity.java similarity index 67% rename from src/main/java/com/simibubi/create/modules/logistics/entity/CardboardBoxEntity.java rename to src/main/java/com/simibubi/create/modules/logistics/transport/CardboardBoxEntity.java index 10534d495..f109ae2f3 100644 --- a/src/main/java/com/simibubi/create/modules/logistics/entity/CardboardBoxEntity.java +++ b/src/main/java/com/simibubi/create/modules/logistics/transport/CardboardBoxEntity.java @@ -1,4 +1,4 @@ -package com.simibubi.create.modules.logistics.entity; +package com.simibubi.create.modules.logistics.transport; import java.util.Collections; @@ -10,6 +10,8 @@ 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.block.BlockState; +import net.minecraft.block.Blocks; import net.minecraft.entity.Entity; import net.minecraft.entity.EntitySize; import net.minecraft.entity.EntityType; @@ -17,6 +19,7 @@ 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.item.minecart.MinecartEntity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.projectile.AbstractArrowEntity; import net.minecraft.inventory.EquipmentSlotType; @@ -26,8 +29,11 @@ import net.minecraft.network.IPacket; import net.minecraft.network.PacketBuffer; import net.minecraft.particles.ItemParticleData; import net.minecraft.particles.ParticleTypes; +import net.minecraft.util.ActionResultType; import net.minecraft.util.DamageSource; import net.minecraft.util.Direction; +import net.minecraft.util.Direction.Axis; +import net.minecraft.util.Hand; import net.minecraft.util.HandSide; import net.minecraft.util.SoundEvent; import net.minecraft.util.SoundEvents; @@ -79,8 +85,15 @@ public class CardboardBoxEntity extends LivingEntity implements IEntityAdditiona extractorAnimationProgress = 20; } + public String getAddress() { + return box.getTag().getString("Address"); + } + @Override public void tick() { + if (extractorAnimationProgress == 0) { + setMotion(new Vec3d(extractorSide.getDirectionVec()).scale(1 / 16f).add(0, 1 / 32f, 0)); + } if (extractorAnimationProgress > -1) { extractorAnimationProgress--; return; @@ -117,10 +130,137 @@ public class CardboardBoxEntity extends LivingEntity implements IEntityAdditiona recalculateSize(); } + @Override public AxisAlignedBB getCollisionBoundingBox() { - return this.getBoundingBox(); + return getBoundingBox(getPose()).grow(-.1f, 0, -.1f); } + @Override + public boolean canBePushed() { + return true; + } + + @Override + public AxisAlignedBB getCollisionBox(Entity entityIn) { + if (entityIn instanceof CardboardBoxEntity) + return getBoundingBox(); + if (entityIn instanceof MinecartEntity) + return null; + return super.getCollisionBox(entityIn); + } + + @Override + public boolean canBeCollidedWith() { + return isAlive(); + } + + @Override + public void applyEntityCollision(Entity entityIn) { + if (entityIn instanceof CardboardBoxEntity) { + if (entityIn.getBoundingBox().minY < this.getBoundingBox().maxY) { + super.applyEntityCollision(entityIn); + } + } else if (entityIn.getBoundingBox().minY <= this.getBoundingBox().minY) { + super.applyEntityCollision(entityIn); + } + } + + @Override + public ActionResultType applyPlayerInteraction(PlayerEntity player, Vec3d vec, Hand hand) { + return super.applyPlayerInteraction(player, vec, hand); + } + + @Override + public boolean processInitialInteract(PlayerEntity player, Hand hand) { + if (player.getPassengers().isEmpty()) { + startRiding(player); + return true; + } else { + for (Entity e : player.getPassengers()) { + while (e instanceof CardboardBoxEntity) { + if (e == this) + return false; + if (e.getPassengers().isEmpty()) { + startRiding(e); + return false; + } + e = e.getPassengers().get(0); + } + } + } + + return super.processInitialInteract(player, hand); + } + + @Override + public void updateRidden() { + super.updateRidden(); + Entity ridingEntity = getRidingEntity(); + if (ridingEntity instanceof LivingEntity) { + + if (!(ridingEntity instanceof CardboardBoxEntity)) { + Vec3d front = VecHelper.rotate(new Vec3d(1, 0, 0), -90 - ridingEntity.getRotationYawHead(), Axis.Y); + double x = ridingEntity.posX + front.x; + double y = ridingEntity.posY + ridingEntity.getMountedYOffset() / 2 + this.getYOffset(); + double z = ridingEntity.posZ + front.z; + + prevRotationYaw = rotationYaw; + setRotation(-ridingEntity.rotationYaw, 0); + + if (world.isRemote) + setPosition(x, y, z); + setPositionAndUpdate(x, y, z); + + if (ridingEntity.isSneaking()) { + stopRiding(); + return; + } + + } else { + prevRotationYaw = rotationYaw; + setRotation(rotationYaw + ridingEntity.rotationYaw - ridingEntity.prevRotationYaw, 0); + } + } + } + + @Override + public double getMountedYOffset() { + return this.getSize(getPose()).height; + } + + @Override + public void dismountEntity(Entity ridingEntity) { + boolean ridingBox = ridingEntity instanceof CardboardBoxEntity; + + if (ridingBox) { + super.dismountEntity(ridingEntity); + } + + if (ridingEntity instanceof LivingEntity && !ridingBox) { + Vec3d front = VecHelper.rotate(new Vec3d(1, 0, 0), -90 - ridingEntity.rotationYaw, Axis.Y); + double x = ridingEntity.posX + front.x; + double y = ridingEntity.posY + ridingEntity.getMountedYOffset() / 2 + this.getYOffset(); + double z = ridingEntity.posZ + front.z; + setRotation(-ridingEntity.rotationYaw, 0); + if (world.isRemote) + setPosition(x, y, z); + setPositionAndUpdate(x, y, z); + } + + getPassengers().forEach(x -> x.stopRiding()); + + } + + @Override + protected void onInsideBlock(BlockState state) { + if (state.getBlock() == Blocks.WATER) { + destroy(DamageSource.DROWN); + remove(); + } + super.onInsideBlock(state); + } + + @Override public boolean attackEntityFrom(DamageSource source, float amount) { if (world.isRemote || !this.isAlive()) return false; @@ -130,6 +270,9 @@ public class CardboardBoxEntity extends LivingEntity implements IEntityAdditiona return false; } + if (DamageSource.IN_WALL.equals(source) && isPassenger()) + return false; + if (DamageSource.FALL.equals(source)) return false; diff --git a/src/main/java/com/simibubi/create/modules/logistics/entity/CardboardBoxEntityRenderer.java b/src/main/java/com/simibubi/create/modules/logistics/transport/CardboardBoxEntityRenderer.java similarity index 80% rename from src/main/java/com/simibubi/create/modules/logistics/entity/CardboardBoxEntityRenderer.java rename to src/main/java/com/simibubi/create/modules/logistics/transport/CardboardBoxEntityRenderer.java index 395e352d5..d261bdadb 100644 --- a/src/main/java/com/simibubi/create/modules/logistics/entity/CardboardBoxEntityRenderer.java +++ b/src/main/java/com/simibubi/create/modules/logistics/transport/CardboardBoxEntityRenderer.java @@ -1,4 +1,4 @@ -package com.simibubi.create.modules.logistics.entity; +package com.simibubi.create.modules.logistics.transport; import com.mojang.blaze3d.platform.GlStateManager; @@ -11,6 +11,7 @@ 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; +import net.minecraft.util.math.Vec3i; public class CardboardBoxEntityRenderer extends EntityRenderer { @@ -44,22 +45,32 @@ public class CardboardBoxEntityRenderer extends EntityRenderer 0) { + float offset = 0; + float yOffset = 0.55f; float time = entity.extractorAnimationProgress - partialTicks; float scale = 1; if (time > 5) { - scale = MathHelper.lerp(((time - 10) / 10), .3f, .25f); + float step = (time - 10) / 10; + offset = MathHelper.lerp(step, -.5f, -1.5f); + scale = MathHelper.lerp(step, .3f, .3f); } else { float step = time / 5; - scale = MathHelper.lerp(step * step * step, 1, .3f); + float cubicStep = step * step * step; + offset = -cubicStep * .5f; + yOffset = step * .55f; + scale = MathHelper.lerp(cubicStep, 1, .3f); } + GlStateManager.scaled(scale, scale, scale); + Vec3i vec = entity.extractorSide.getDirectionVec(); + GlStateManager.translated(offset * vec.getX(), offset * vec.getY() + yOffset, offset * vec.getZ()); } - + 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(); diff --git a/src/main/java/com/simibubi/create/modules/logistics/transport/villager/CollectPackageTask.java b/src/main/java/com/simibubi/create/modules/logistics/transport/villager/CollectPackageTask.java new file mode 100644 index 000000000..10acf43df --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/logistics/transport/villager/CollectPackageTask.java @@ -0,0 +1,40 @@ +package com.simibubi.create.modules.logistics.transport.villager; + +import java.util.ArrayList; +import java.util.List; + +import com.google.common.collect.ImmutableMap; +import com.simibubi.create.modules.logistics.transport.CardboardBoxEntity; + +import net.minecraft.entity.Entity; +import net.minecraft.entity.ai.brain.memory.MemoryModuleStatus; +import net.minecraft.entity.ai.brain.memory.MemoryModuleType; +import net.minecraft.entity.ai.brain.task.Task; +import net.minecraft.entity.merchant.villager.VillagerEntity; +import net.minecraft.world.server.ServerWorld; + +public class CollectPackageTask extends Task { + private List foundPackages = new ArrayList<>(); + + public CollectPackageTask() { + super(ImmutableMap.of(MemoryModuleType.LOOK_TARGET, MemoryModuleStatus.VALUE_ABSENT, + MemoryModuleType.WALK_TARGET, MemoryModuleStatus.VALUE_ABSENT), 1); + } + + protected boolean shouldExecute(ServerWorld worldIn, VillagerEntity owner) { + this.foundPackages = worldIn.getEntitiesWithinAABB(CardboardBoxEntity.class, + owner.getBoundingBox().grow(1.0D, 0.5D, 1.0D), + e -> !e.isPassenger() && !e.getPersistentData().getBoolean("Delivered")); + return !this.foundPackages.isEmpty(); + } + + protected void startExecuting(ServerWorld worldIn, VillagerEntity entityIn, long gameTimeIn) { + LogisticianHandler.ponder(entityIn, "Yoink!"); + CardboardBoxEntity box = this.foundPackages.get(worldIn.rand.nextInt(this.foundPackages.size())); + Entity e = entityIn; + while (!e.getPassengers().isEmpty()) + e = e.getPassengers().get(0); + box.startRiding(e); + } + +} diff --git a/src/main/java/com/simibubi/create/modules/logistics/transport/villager/DeliverPackageToDestinationTask.java b/src/main/java/com/simibubi/create/modules/logistics/transport/villager/DeliverPackageToDestinationTask.java new file mode 100644 index 000000000..48e614f75 --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/logistics/transport/villager/DeliverPackageToDestinationTask.java @@ -0,0 +1,37 @@ +package com.simibubi.create.modules.logistics.transport.villager; + +import net.minecraft.entity.ai.brain.memory.MemoryModuleType; +import net.minecraft.entity.ai.brain.memory.WalkTarget; +import net.minecraft.entity.merchant.villager.VillagerEntity; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.BlockPosWrapper; +import net.minecraft.util.math.GlobalPos; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.server.ServerWorld; + +public class DeliverPackageToDestinationTask extends PackageDeliveryTask { + + private GlobalPos rememberedAddress; + + public DeliverPackageToDestinationTask() { + super(60); + } + + @Override + protected boolean shouldExecute(ServerWorld worldIn, VillagerEntity owner) { + if (!super.shouldExecute(worldIn, owner)) + return false; + rememberedAddress = LogisticianHandler.getRememberedAddress(owner, getBox(owner).getAddress()); + return rememberedAddress != null && !rememberedAddress.getPos().withinDistance(owner.getPosition(), 2); + } + + @Override + protected void startExecuting(ServerWorld worldIn, VillagerEntity entityIn, long gameTimeIn) { + LogisticianHandler.ponder(entityIn, "I know where this is!"); + BlockPos pos = rememberedAddress.getPos(); + Vec3d vec3d = new Vec3d(pos); + entityIn.getBrain().setMemory(MemoryModuleType.LOOK_TARGET, new BlockPosWrapper(new BlockPos(vec3d))); + entityIn.getBrain().setMemory(MemoryModuleType.WALK_TARGET, new WalkTarget(vec3d, 0.5F, 2)); + } + +} diff --git a/src/main/java/com/simibubi/create/modules/logistics/transport/villager/DropPackageAtDestinationTask.java b/src/main/java/com/simibubi/create/modules/logistics/transport/villager/DropPackageAtDestinationTask.java new file mode 100644 index 000000000..fbad320b7 --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/logistics/transport/villager/DropPackageAtDestinationTask.java @@ -0,0 +1,37 @@ +package com.simibubi.create.modules.logistics.transport.villager; + +import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.modules.logistics.transport.CardboardBoxEntity; + +import net.minecraft.entity.merchant.villager.VillagerEntity; +import net.minecraft.util.math.GlobalPos; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.server.ServerWorld; + +public class DropPackageAtDestinationTask extends PackageDeliveryTask { + + private GlobalPos rememberedAddress; + + public DropPackageAtDestinationTask() { + super(10); + } + + @Override + protected boolean shouldExecute(ServerWorld worldIn, VillagerEntity owner) { + if (!super.shouldExecute(worldIn, owner)) + return false; + rememberedAddress = LogisticianHandler.getRememberedAddress(owner, getBox(owner).getAddress()); + return rememberedAddress != null && rememberedAddress.getPos().withinDistance(owner.getPosition(), 2); + } + + @Override + protected void startExecuting(ServerWorld worldIn, VillagerEntity entityIn, long gameTimeIn) { + LogisticianHandler.ponder(entityIn, "You're welcome."); + CardboardBoxEntity box = getBox(entityIn); + box.stopRiding(); + Vec3d pos = VecHelper.getCenterOf(rememberedAddress.getPos()); + box.setPosition(pos.x, pos.y, pos.z); + box.getPersistentData().putBoolean("Delivered", true); + } + +} diff --git a/src/main/java/com/simibubi/create/modules/logistics/transport/villager/ExpireWorkstationTask.java b/src/main/java/com/simibubi/create/modules/logistics/transport/villager/ExpireWorkstationTask.java new file mode 100644 index 000000000..604e2fb05 --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/logistics/transport/villager/ExpireWorkstationTask.java @@ -0,0 +1,38 @@ +package com.simibubi.create.modules.logistics.transport.villager; + +import com.google.common.collect.ImmutableMap; +import com.simibubi.create.AllBlocks; + +import net.minecraft.entity.Entity; +import net.minecraft.entity.ai.brain.task.Task; +import net.minecraft.entity.merchant.villager.VillagerEntity; +import net.minecraft.entity.merchant.villager.VillagerProfession; +import net.minecraft.util.math.GlobalPos; +import net.minecraft.world.server.ServerWorld; + +public class ExpireWorkstationTask extends Task { + + private GlobalPos workstationPos; + + public ExpireWorkstationTask() { + super(ImmutableMap.of(), 20); + } + + @Override + protected boolean shouldExecute(ServerWorld worldIn, VillagerEntity owner) { + workstationPos = LogisticianHandler.getJobSite(owner); + return workstationPos.getPos().withinDistance(owner.getPosition(), 5); + } + + @Override + protected void startExecuting(ServerWorld worldIn, VillagerEntity entityIn, long gameTimeIn) { + ServerWorld serverworld = worldIn.getServer().getWorld(workstationPos.getDimension()); + if (!AllBlocks.LOGISTICIANS_TABLE.typeOf(serverworld.getBlockState(workstationPos.getPos()))) { + LogisticianHandler.ponder(entityIn, "Oh no! My workstation!"); + entityIn.setVillagerData(entityIn.getVillagerData().withProfession(VillagerProfession.NONE).withLevel(1)); + entityIn.resetBrain(serverworld); + entityIn.getPassengers().forEach(Entity::stopRiding); + } + } + +} diff --git a/src/main/java/com/simibubi/create/modules/logistics/transport/villager/LogisticianHandler.java b/src/main/java/com/simibubi/create/modules/logistics/transport/villager/LogisticianHandler.java new file mode 100644 index 000000000..788636426 --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/logistics/transport/villager/LogisticianHandler.java @@ -0,0 +1,146 @@ +package com.simibubi.create.modules.logistics.transport.villager; + +import java.util.Iterator; + +import javax.annotation.Nullable; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import com.mojang.datafixers.Dynamic; +import com.mojang.datafixers.util.Pair; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.Create; + +import net.minecraft.block.BlockState; +import net.minecraft.client.Minecraft; +import net.minecraft.entity.EntityType; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.ai.brain.memory.MemoryModuleType; +import net.minecraft.entity.ai.brain.task.DummyTask; +import net.minecraft.entity.ai.brain.task.FindInteractionAndLookTargetTask; +import net.minecraft.entity.ai.brain.task.FirstShuffledTask; +import net.minecraft.entity.ai.brain.task.LookAtEntityTask; +import net.minecraft.entity.ai.brain.task.StayNearPointTask; +import net.minecraft.entity.ai.brain.task.Task; +import net.minecraft.entity.ai.brain.task.UpdateActivityTask; +import net.minecraft.entity.ai.brain.task.WalkTowardsPosTask; +import net.minecraft.entity.merchant.villager.VillagerEntity; +import net.minecraft.entity.merchant.villager.VillagerProfession; +import net.minecraft.nbt.CompoundNBT; +import net.minecraft.nbt.INBT; +import net.minecraft.nbt.ListNBT; +import net.minecraft.nbt.NBTDynamicOps; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.SoundEvents; +import net.minecraft.util.math.GlobalPos; +import net.minecraft.util.text.StringTextComponent; +import net.minecraft.village.PointOfInterestType; +import net.minecraftforge.common.util.Constants.NBT; +import net.minecraftforge.event.RegistryEvent; + +public class LogisticianHandler { + + public static VillagerProfession LOGISTICIAN; + public static PointOfInterestType LOGISTICIANS_TABLE; + + public static void registerPointsOfInterest(RegistryEvent.Register event) { + ImmutableList validStates = AllBlocks.LOGISTICIANS_TABLE.get().getStateContainer().getValidStates(); + LOGISTICIANS_TABLE = new PointOfInterestType("logistician_table", ImmutableSet.copyOf(validStates), 1, + SoundEvents.ENTITY_VILLAGER_WORK_LIBRARIAN, 1) + .setRegistryName(new ResourceLocation(Create.ID, "logistician_table")); + event.getRegistry().register(LOGISTICIANS_TABLE); + } + + public static void registerVillagerProfessions(RegistryEvent.Register event) { + LOGISTICIAN = new VillagerProfession("logistician", LOGISTICIANS_TABLE, ImmutableSet.of(), ImmutableSet.of()) + .setRegistryName(new ResourceLocation(Create.ID, "logistician")); + event.getRegistry().register(LOGISTICIAN); + } + + public static ImmutableList>> work(float p_220639_1_) { + return ImmutableList.of(uselessTasks(), actualWorkTasks(), + Pair.of(10, new FindInteractionAndLookTargetTask(EntityType.PLAYER, 4)), + Pair.of(2, new StayNearPointTask(MemoryModuleType.JOB_SITE, p_220639_1_, 9, 100, 1200)), + Pair.of(3, new ExpireWorkstationTask()), Pair.of(99, new UpdateActivityTask())); + } + + public static Pair> actualWorkTasks() { + return Pair.of(5, + new FirstShuffledTask<>(ImmutableList.of( + Pair.of(new WalkToPackageTask(), 1), + Pair.of(new CollectPackageTask(), 1), + Pair.of(new WalkToWorkstationTask(), 1), + Pair.of(new LookupAddressTask(), 1), + Pair.of(new DeliverPackageToDestinationTask(), 1), + Pair.of(new DropPackageAtDestinationTask(), 1), + Pair.of(new WalkTowardsPosTask(MemoryModuleType.JOB_SITE, 1, 10), 5)))); + } + + private static Pair> uselessTasks() { + return Pair.of(6, + new FirstShuffledTask<>(ImmutableList.of(Pair.of(new LookAtEntityTask(EntityType.VILLAGER, 8.0F), 2), + Pair.of(new LookAtEntityTask(EntityType.PLAYER, 8.0F), 2), Pair.of(new DummyTask(30, 60), 8)))); + } + + public static GlobalPos getJobSite(VillagerEntity villager) { + CompoundNBT nbt = villager.getPersistentData(); + String jobSiteKey = "JobSite"; + if (!nbt.contains(jobSiteKey)) + return null; + return GlobalPos.deserialize(new Dynamic<>(NBTDynamicOps.INSTANCE, nbt.getCompound(jobSiteKey))); + } + + public static void setJobSite(VillagerEntity villager, GlobalPos pos) { + CompoundNBT nbt = villager.getPersistentData(); + String jobSiteKey = "JobSite"; + nbt.put(jobSiteKey, pos.serialize(NBTDynamicOps.INSTANCE)); + } + + public static void rememberAddress(VillagerEntity villager, String address, GlobalPos pos) { + ListNBT list = getAddressList(villager); + + for (Iterator iterator = list.iterator(); iterator.hasNext();) { + INBT inbt = iterator.next(); + if (((CompoundNBT) inbt).getString("Address").equals(address)) { + iterator.remove(); + } + } + + if (list.size() > 5) + list.remove(0); + + CompoundNBT addedNBT = new CompoundNBT(); + addedNBT.putString("Address", address); + addedNBT.put("Pos", pos.serialize(NBTDynamicOps.INSTANCE)); + list.add(addedNBT); + } + + public static ListNBT getAddressList(VillagerEntity villager) { + CompoundNBT nbt = villager.getPersistentData(); + String listKey = "MemorizedAddresses"; + if (!nbt.contains(listKey)) + nbt.put(listKey, new ListNBT()); + ListNBT list = nbt.getList(listKey, NBT.TAG_COMPOUND); + return list; + } + + @Nullable + public static GlobalPos getRememberedAddress(VillagerEntity villager, String address) { + ListNBT list = getAddressList(villager); + + for (INBT inbt : list) { + if (((CompoundNBT) inbt).getString("Address").equals(address)) { + Dynamic dynamic = new Dynamic<>(NBTDynamicOps.INSTANCE, ((CompoundNBT) inbt).getCompound("Pos")); + return GlobalPos.deserialize(dynamic); + } + } + + return null; + } + + public static void ponder(VillagerEntity entityIn, String thought) { + Minecraft.getInstance().player.sendMessage( + new StringTextComponent("<" + entityIn.getDisplayName().getFormattedText() + "> " + thought)); + } + +} diff --git a/src/main/java/com/simibubi/create/modules/logistics/transport/villager/LogisticiansTableBlock.java b/src/main/java/com/simibubi/create/modules/logistics/transport/villager/LogisticiansTableBlock.java new file mode 100644 index 000000000..5f083f3cd --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/logistics/transport/villager/LogisticiansTableBlock.java @@ -0,0 +1,146 @@ +package com.simibubi.create.modules.logistics.transport.villager; + +import java.util.Random; + +import com.simibubi.create.AllItems; +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.entity.Entity; +import net.minecraft.entity.EntityType; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.SharedMonsterAttributes; +import net.minecraft.entity.ai.brain.memory.MemoryModuleType; +import net.minecraft.entity.ai.brain.schedule.Activity; +import net.minecraft.entity.merchant.villager.VillagerEntity; +import net.minecraft.entity.merchant.villager.VillagerProfession; +import net.minecraft.entity.player.PlayerEntity; +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.math.AxisAlignedBB; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.GlobalPos; +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.World; + +public class LogisticiansTableBlock extends HorizontalBlock implements IWithTileEntity { + + private static final VoxelShape BASE_SHAPE = Block.makeCuboidShape(4.0D, 0.0D, 4.0D, 12.0D, 2.0D, 12.0D); + private static final VoxelShape POLE_SHAPE = Block.makeCuboidShape(5.0D, 2.0D, 5.0D, 11.0D, 14.0D, 11.0D); + private static final VoxelShape RENDER_SHAPE = VoxelShapes.or(BASE_SHAPE, POLE_SHAPE); + private static final VoxelShape TOP_COLLISION_SHAPE = Block.makeCuboidShape(0.0D, 15.0D, 0.0D, 16.0D, 15.0D, 16.0D); + private static final VoxelShape COLLISION_SHAPE = VoxelShapes.or(RENDER_SHAPE, TOP_COLLISION_SHAPE); + + private static final VoxelShape WEST_SHAPE = VoxelShapes.or( + Block.makeCuboidShape(1.0D, 10.0D, 0.0D, 5.333333D, 14.0D, 16.0D), + Block.makeCuboidShape(5.333333D, 12.0D, 0.0D, 9.666667D, 16.0D, 16.0D), + Block.makeCuboidShape(9.666667D, 14.0D, 0.0D, 14.0D, 18.0D, 16.0D), RENDER_SHAPE); + private static final VoxelShape NORTH_SHAPE = VoxelShapes.or( + Block.makeCuboidShape(0.0D, 10.0D, 1.0D, 16.0D, 14.0D, 5.333333D), + Block.makeCuboidShape(0.0D, 12.0D, 5.333333D, 16.0D, 16.0D, 9.666667D), + Block.makeCuboidShape(0.0D, 14.0D, 9.666667D, 16.0D, 18.0D, 14.0D), RENDER_SHAPE); + private static final VoxelShape EAST_SHAPE = VoxelShapes.or( + Block.makeCuboidShape(15.0D, 10.0D, 0.0D, 10.666667D, 14.0D, 16.0D), + Block.makeCuboidShape(10.666667D, 12.0D, 0.0D, 6.333333D, 16.0D, 16.0D), + Block.makeCuboidShape(6.333333D, 14.0D, 0.0D, 2.0D, 18.0D, 16.0D), RENDER_SHAPE); + private static final VoxelShape SOUTH_SHAPE = VoxelShapes.or( + Block.makeCuboidShape(0.0D, 10.0D, 15.0D, 16.0D, 14.0D, 10.666667D), + Block.makeCuboidShape(0.0D, 12.0D, 10.666667D, 16.0D, 16.0D, 6.333333D), + Block.makeCuboidShape(0.0D, 14.0D, 6.333333D, 16.0D, 18.0D, 2.0D), RENDER_SHAPE); + + public LogisticiansTableBlock() { + super(Properties.from(Blocks.SPRUCE_LOG)); + } + + @Override + public boolean hasTileEntity(BlockState state) { + return true; + } + + @Override + public TileEntity createTileEntity(BlockState state, IBlockReader world) { + return new LogisticiansTableTileEntity(); + } + + @Override + public boolean ticksRandomly(BlockState state) { + return true; + } + + @Override + public void tick(BlockState state, World worldIn, BlockPos pos, Random random) { + for (Entity entity : worldIn.getEntitiesWithinAABB(EntityType.VILLAGER, new AxisAlignedBB(pos).grow(10), + e -> ((VillagerEntity) e).getVillagerData().getProfession() == VillagerProfession.NONE)) { + + VillagerEntity e = (VillagerEntity) entity; + float f = (float) e.getAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).getValue(); + e.setVillagerData(e.getVillagerData().withProfession(LogisticianHandler.LOGISTICIAN).withLevel(2)); + e.getBrain().registerActivity(Activity.WORK, LogisticianHandler.work(f)); + e.getBrain().setMemory(MemoryModuleType.JOB_SITE, GlobalPos.of(worldIn.getDimension().getType(), pos)); + LogisticianHandler.setJobSite(e, GlobalPos.of(worldIn.getDimension().getType(), pos)); + } + } + + @Override + protected void fillStateContainer(Builder builder) { + builder.add(HORIZONTAL_FACING); + super.fillStateContainer(builder); + } + + public VoxelShape getRenderShape(BlockState state, IBlockReader worldIn, BlockPos pos) { + return RENDER_SHAPE; + } + + public boolean func_220074_n(BlockState state) { + 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; + } + } + + public BlockState getStateForPlacement(BlockItemUseContext context) { + return this.getDefaultState().with(HORIZONTAL_FACING, context.getPlacementHorizontalFacing().getOpposite()); + } + + public VoxelShape getCollisionShape(BlockState state, IBlockReader worldIn, BlockPos pos, + ISelectionContext context) { + return COLLISION_SHAPE; + } + + public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) { + switch (state.get(HORIZONTAL_FACING)) { + case NORTH: + return NORTH_SHAPE; + case SOUTH: + return SOUTH_SHAPE; + case EAST: + return EAST_SHAPE; + case WEST: + return WEST_SHAPE; + default: + return RENDER_SHAPE; + } + } + +} diff --git a/src/main/java/com/simibubi/create/modules/logistics/transport/villager/LogisticiansTableTileEntity.java b/src/main/java/com/simibubi/create/modules/logistics/transport/villager/LogisticiansTableTileEntity.java new file mode 100644 index 000000000..1e439161e --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/logistics/transport/villager/LogisticiansTableTileEntity.java @@ -0,0 +1,12 @@ +package com.simibubi.create.modules.logistics.transport.villager; + +import com.simibubi.create.AllTileEntities; +import com.simibubi.create.modules.logistics.management.base.LogisticalActorTileEntity; + +public class LogisticiansTableTileEntity extends LogisticalActorTileEntity { + + public LogisticiansTableTileEntity() { + super(AllTileEntities.LOGISTICIANS_TABLE.type); + } + +} diff --git a/src/main/java/com/simibubi/create/modules/logistics/transport/villager/LogisticiansTableTileEntityRenderer.java b/src/main/java/com/simibubi/create/modules/logistics/transport/villager/LogisticiansTableTileEntityRenderer.java new file mode 100644 index 000000000..1d4cf4411 --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/logistics/transport/villager/LogisticiansTableTileEntityRenderer.java @@ -0,0 +1,67 @@ +package com.simibubi.create.modules.logistics.transport.villager; + +import org.lwjgl.opengl.GL11; + +import com.mojang.blaze3d.platform.GlStateManager; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.foundation.utility.ColoredIndicatorRenderer; + +import net.minecraft.block.BlockState; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.RenderHelper; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.entity.model.BookModel; +import net.minecraft.client.renderer.texture.AtlasTexture; +import net.minecraft.client.renderer.tileentity.TileEntityRenderer; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.state.properties.BlockStateProperties; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.math.BlockPos; + +public class LogisticiansTableTileEntityRenderer extends TileEntityRenderer { + private static final ResourceLocation bookLocation = new ResourceLocation( + "textures/entity/enchanting_table_book.png"); + private final BookModel bookModel = new BookModel(); + + public void render(LogisticiansTableTileEntity tileEntityIn, double x, double y, double z, float partialTicks, + int destroyStage) { + Minecraft.getInstance().textureManager + .bindTexture(AtlasTexture.LOCATION_BLOCKS_TEXTURE); + net.minecraft.client.renderer.RenderHelper.disableStandardItemLighting(); + GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.enableBlend(); + GlStateManager.disableCull(); + + if (net.minecraft.client.Minecraft.isAmbientOcclusionEnabled()) + GlStateManager.shadeModel(GL11.GL_SMOOTH); + else + GlStateManager.shadeModel(GL11.GL_FLAT); + + GlStateManager.color3f(1, 1, 1); + BlockPos pos = tileEntityIn.getPos(); + BlockState blockState = tileEntityIn.getBlockState(); + BlockState renderedState = AllBlocks.LOGISTICIANS_TABLE_INDICATOR.get().getDefaultState(); + int packedLightmapCoords = blockState.getPackedLightmapCoords(getWorld(), pos); + Tessellator.getInstance().getBuffer().begin(GL11.GL_QUADS, DefaultVertexFormats.BLOCK); + int color = tileEntityIn.getColor(); + Tessellator.getInstance().getBuffer().putBulkData(ColoredIndicatorRenderer.get(renderedState) + .getTransformed((float) x, (float) y, (float) z, color, packedLightmapCoords)); + Tessellator.getInstance().draw(); + RenderHelper.enableStandardItemLighting(); + + BlockState blockstate = tileEntityIn.getBlockState(); + GlStateManager.pushMatrix(); + GlStateManager.translatef((float) x + 0.5F, (float) y + 1.0F + 0.0625F, (float) z + 0.5F); + float f = blockstate.get(BlockStateProperties.HORIZONTAL_FACING).rotateY().getHorizontalAngle(); + GlStateManager.rotatef(-f, 0.0F, 1.0F, 0.0F); + GlStateManager.rotatef(67.5F, 0.0F, 0.0F, 1.0F); + GlStateManager.translatef(0.0F, -0.125F, 0.0F); + this.bindTexture(bookLocation); + GlStateManager.enableCull(); + this.bookModel.render(0.0F, 0.1F, 0.9F, 1.2F, 0.0F, 0.0625F); + GlStateManager.disableCull(); + GlStateManager.popMatrix(); + + } + +} diff --git a/src/main/java/com/simibubi/create/modules/logistics/transport/villager/LookupAddressTask.java b/src/main/java/com/simibubi/create/modules/logistics/transport/villager/LookupAddressTask.java new file mode 100644 index 000000000..de219def0 --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/logistics/transport/villager/LookupAddressTask.java @@ -0,0 +1,55 @@ +package com.simibubi.create.modules.logistics.transport.villager; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.modules.logistics.transport.CardboardBoxEntity; + +import net.minecraft.entity.merchant.villager.VillagerEntity; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.GlobalPos; +import net.minecraft.world.server.ServerWorld; + +public class LookupAddressTask extends PackageDeliveryTask { + + public LookupAddressTask() { + super(10); + } + + @Override + protected boolean shouldExecute(ServerWorld worldIn, VillagerEntity owner) { + if (!super.shouldExecute(worldIn, owner)) + return false; + CardboardBoxEntity box = getBox(owner); + GlobalPos rememberedAddress = LogisticianHandler.getRememberedAddress(owner, box.getAddress()); + if (rememberedAddress != null) + return false; + return LogisticianHandler.getJobSite(owner).getPos().withinDistance(owner.getPosition(), 1.5); + } + + @Override + protected void startExecuting(ServerWorld worldIn, VillagerEntity entityIn, long gameTimeIn) { + LogisticianHandler.ponder(entityIn, "Let's have a look..."); + BlockPos tablePos = LogisticianHandler.getJobSite(entityIn).getPos(); + if (!AllBlocks.LOGISTICIANS_TABLE.typeOf(worldIn.getBlockState(tablePos))) + return; + TileEntity te = worldIn.getTileEntity(tablePos); + if (te == null || !(te instanceof LogisticiansTableTileEntity)) + return; + LogisticiansTableTileEntity lte = (LogisticiansTableTileEntity) te; + String address = getBox(entityIn).getAddress(); + if (lte.getNetwork() == null) + return; + for (PackageFunnelTileEntity packageFunnelTileEntity : lte.getNetwork().packageTargets) { + for (String string : packageFunnelTileEntity.addresses) { + if (string.toLowerCase().equals(address.toLowerCase())) { + GlobalPos globalPos = GlobalPos.of(worldIn.getDimension().getType(), packageFunnelTileEntity.getPos()); + LogisticianHandler.rememberAddress(entityIn, address, globalPos); + LogisticianHandler.ponder(entityIn, "I see!"); + return; + } + } + } + LogisticianHandler.ponder(entityIn, "Hmm. Can't find that one"); + } + +} diff --git a/src/main/java/com/simibubi/create/modules/logistics/transport/villager/PackageDeliveryTask.java b/src/main/java/com/simibubi/create/modules/logistics/transport/villager/PackageDeliveryTask.java new file mode 100644 index 000000000..05503b63d --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/logistics/transport/villager/PackageDeliveryTask.java @@ -0,0 +1,36 @@ +package com.simibubi.create.modules.logistics.transport.villager; + +import java.util.List; + +import com.google.common.collect.ImmutableMap; +import com.simibubi.create.modules.logistics.transport.CardboardBoxEntity; + +import net.minecraft.entity.Entity; +import net.minecraft.entity.ai.brain.memory.MemoryModuleStatus; +import net.minecraft.entity.ai.brain.memory.MemoryModuleType; +import net.minecraft.entity.ai.brain.task.Task; +import net.minecraft.entity.merchant.villager.VillagerEntity; +import net.minecraft.world.server.ServerWorld; + +public class PackageDeliveryTask extends Task { + + public PackageDeliveryTask(int timeout) { + super(ImmutableMap.of(MemoryModuleType.LOOK_TARGET, MemoryModuleStatus.VALUE_ABSENT, + MemoryModuleType.WALK_TARGET, MemoryModuleStatus.VALUE_ABSENT), timeout); + } + + protected boolean shouldExecute(ServerWorld worldIn, VillagerEntity owner) { + return getBox(owner) != null; + } + + protected CardboardBoxEntity getBox(VillagerEntity owner) { + List passengers = owner.getPassengers(); + if (passengers.isEmpty()) + return null; + Entity entity = passengers.get(0); + if (!(entity instanceof CardboardBoxEntity)) + return null; + return (CardboardBoxEntity) entity; + } + +} diff --git a/src/main/java/com/simibubi/create/modules/logistics/transport/villager/PackageFunnelBlock.java b/src/main/java/com/simibubi/create/modules/logistics/transport/villager/PackageFunnelBlock.java new file mode 100644 index 000000000..cda8e4c51 --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/logistics/transport/villager/PackageFunnelBlock.java @@ -0,0 +1,111 @@ +package com.simibubi.create.modules.logistics.transport.villager; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.foundation.block.IWithTileEntity; +import com.simibubi.create.foundation.block.ProperDirectionalBlock; +import com.simibubi.create.modules.logistics.management.base.ILogisticalCasingAttachment; +import com.simibubi.create.modules.logistics.management.base.LogisticalCasingTileEntity; +import com.simibubi.create.modules.logistics.transport.CardboardBoxEntity; + +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.item.BlockItemUseContext; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.Direction; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.shapes.ISelectionContext; +import net.minecraft.util.math.shapes.VoxelShape; +import net.minecraft.util.math.shapes.VoxelShapes; +import net.minecraft.world.IBlockReader; +import net.minecraft.world.IWorld; +import net.minecraft.world.IWorldReader; +import net.minecraft.world.World; + +public class PackageFunnelBlock extends ProperDirectionalBlock + implements IWithTileEntity, ILogisticalCasingAttachment { + + public static final VoxelShape UP_SHAPE = makeCuboidShape(1, -1, 1, 15, 3, 15), + DOWN_SHAPE = makeCuboidShape(1, 13, 1, 15, 17, 15), SOUTH_SHAPE = makeCuboidShape(1, 1, -1, 15, 15, 3), + NORTH_SHAPE = makeCuboidShape(1, 1, 13, 15, 15, 17), EAST_SHAPE = makeCuboidShape(-1, 1, 1, 3, 15, 15), + WEST_SHAPE = makeCuboidShape(13, 1, 1, 17, 15, 15); + + public PackageFunnelBlock() { + super(Properties.from(Blocks.PISTON)); + } + + @Override + public boolean hasTileEntity(BlockState state) { + return true; + } + + @Override + public TileEntity createTileEntity(BlockState state, IBlockReader world) { + return new PackageFunnelTileEntity(); + } + + @Override + public BlockState getStateForPlacement(BlockItemUseContext context) { + return getDefaultState().with(FACING, context.getFace()); + } + + @Override + public VoxelShape getCollisionShape(BlockState state, IBlockReader worldIn, BlockPos pos, + ISelectionContext context) { + if (context.getEntity() instanceof CardboardBoxEntity) + return VoxelShapes.empty(); + return getShape(state, worldIn, pos, context); + } + + @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 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(); + } + + @Override + public void onCasingUpdated(IWorld world, BlockPos pos, LogisticalCasingTileEntity te) { + Direction facing = world.getBlockState(pos).get(FACING).getOpposite(); + if (!te.getPos().equals(pos.offset(facing))) + return; + withTileEntityDo(world, pos, PackageFunnelTileEntity::refreshAddressList); + } + +} diff --git a/src/main/java/com/simibubi/create/modules/logistics/transport/villager/PackageFunnelTileEntity.java b/src/main/java/com/simibubi/create/modules/logistics/transport/villager/PackageFunnelTileEntity.java new file mode 100644 index 000000000..28514378d --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/logistics/transport/villager/PackageFunnelTileEntity.java @@ -0,0 +1,151 @@ +package com.simibubi.create.modules.logistics.transport.villager; + +import static com.simibubi.create.modules.logistics.management.controller.LogisticalInventoryControllerTileEntity.ShippingInventory.RECEIVING; + +import java.util.ArrayList; +import java.util.List; + +import com.simibubi.create.AllTileEntities; +import com.simibubi.create.foundation.block.SyncedTileEntity; +import com.simibubi.create.modules.logistics.management.LogisticalNetwork; +import com.simibubi.create.modules.logistics.management.base.LogisticalActorTileEntity; +import com.simibubi.create.modules.logistics.management.base.LogisticalCasingTileEntity; +import com.simibubi.create.modules.logistics.management.controller.LogisticalInventoryControllerTileEntity; +import com.simibubi.create.modules.logistics.management.controller.LogisticalInventoryControllerTileEntity.ShippingInventory; +import com.simibubi.create.modules.logistics.transport.CardboardBoxEntity; + +import net.minecraft.state.properties.BlockStateProperties; +import net.minecraft.tileentity.ITickableTileEntity; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.util.math.BlockPos; + +public class PackageFunnelTileEntity extends SyncedTileEntity implements ITickableTileEntity { + + public static final int INSERTION_DELAY = 10; + + protected int initialize; + protected List addresses; + protected boolean waitingForSpace; + protected int cooldown; + protected AxisAlignedBB bb; + + public PackageFunnelTileEntity() { + super(AllTileEntities.PACKAGE_FUNNEL.type); + addresses = new ArrayList(); + waitingForSpace = false; + cooldown = 10; + } + + public void slotOpened() { + waitingForSpace = false; + } + + @Override + public void onLoad() { + super.onLoad(); + initialize = 2; + bb = new AxisAlignedBB(getPos()); + } + + @Override + public void tick() { + + // Initialize AFTER the actors to get a working network reference + if (initialize > -1) + initialize--; + if (initialize == 0) { + initialize(); + return; + } + + if (cooldown > 0) { + cooldown--; + return; + } + + if (waitingForSpace) + return; + + tryInsert(); + cooldown = INSERTION_DELAY; + } + + protected void initialize() { + initialize = -1; + refreshAddressList(); + } + + public void refreshAddressList() { + addresses.clear(); + LogisticalCasingTileEntity casingTE = getCasingTE(); + if (casingTE == null) + return; + for (LogisticalActorTileEntity actor : casingTE.getControllers()) { + addresses.add(actor.address); + if (actor.getNetwork() != null) + actor.getNetwork().addPackageTarget(this); + } + } + + public LogisticalCasingTileEntity getCasingTE() { + BlockPos casingPos = pos.offset(getBlockState().get(BlockStateProperties.FACING).getOpposite()); + TileEntity te = world.getTileEntity(casingPos); + if (te == null || !AllTileEntities.LOGISTICAL_CASING.typeOf(te)) + return null; + LogisticalCasingTileEntity casingTE = (LogisticalCasingTileEntity) te; + return casingTE; + } + + private void tryInsert() { + for (CardboardBoxEntity e : world.getEntitiesWithinAABB(CardboardBoxEntity.class, bb, e -> { + if (e.isPassenger()) + return false; + for (String address : addresses) + if (LogisticalNetwork.matchAddresses(address, e.getAddress())) + return true; + return false; + })) { + LogisticalCasingTileEntity casingTE = getCasingTE(); + if (casingTE == null) + return; + for (LogisticalActorTileEntity actor : casingTE.getControllers()) { + if (!(actor instanceof LogisticalInventoryControllerTileEntity)) + continue; + if (LogisticalNetwork.matchAddresses(actor.address, e.getAddress())) { + LogisticalInventoryControllerTileEntity invTe = (LogisticalInventoryControllerTileEntity) actor; + if (!invTe.isReceiver()) + continue; + ShippingInventory inventory = invTe.getInventory(); + if (!inventory.getStackInSlot(RECEIVING).isEmpty()) { + waitingForSpace = true; + return; + } + inventory.insertItem(RECEIVING, e.getBox(), false); + e.remove(); + return; + } + } + return; + } + } + + @Override + public void remove() { + BlockPos casingPos = pos.offset(getBlockState().get(BlockStateProperties.FACING).getOpposite()); + TileEntity te = world.getTileEntity(casingPos); + if (te == null || !AllTileEntities.LOGISTICAL_CASING.typeOf(te)) + return; + LogisticalCasingTileEntity casingTE = (LogisticalCasingTileEntity) te; + for (LogisticalActorTileEntity actor : casingTE.getControllers()) { + if (actor.getNetwork() != null) + actor.getNetwork().removePackageTarget(this); + } + super.remove(); + } + + public List getAddressList() { + return addresses; + } + +} diff --git a/src/main/java/com/simibubi/create/modules/logistics/transport/villager/WalkToPackageTask.java b/src/main/java/com/simibubi/create/modules/logistics/transport/villager/WalkToPackageTask.java new file mode 100644 index 000000000..cb69ed76a --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/logistics/transport/villager/WalkToPackageTask.java @@ -0,0 +1,51 @@ +package com.simibubi.create.modules.logistics.transport.villager; + +import java.util.ArrayList; +import java.util.List; + +import com.google.common.collect.ImmutableMap; +import com.simibubi.create.modules.logistics.transport.CardboardBoxEntity; + +import net.minecraft.entity.ai.brain.memory.MemoryModuleStatus; +import net.minecraft.entity.ai.brain.memory.MemoryModuleType; +import net.minecraft.entity.ai.brain.memory.WalkTarget; +import net.minecraft.entity.ai.brain.task.Task; +import net.minecraft.entity.merchant.villager.VillagerEntity; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.BlockPosWrapper; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.server.ServerWorld; + +public class WalkToPackageTask extends Task { + private List foundPackages = new ArrayList<>(); + private CardboardBoxEntity targetedPackage; + + public WalkToPackageTask() { + super(ImmutableMap.of(MemoryModuleType.LOOK_TARGET, MemoryModuleStatus.VALUE_ABSENT, + MemoryModuleType.WALK_TARGET, MemoryModuleStatus.VALUE_ABSENT), 20); + } + + protected boolean shouldExecute(ServerWorld worldIn, VillagerEntity owner) { + if (!worldIn.getEntitiesWithinAABB(CardboardBoxEntity.class, owner.getBoundingBox().grow(1.0D, 0.5D, 1.0D), + e -> !e.isPassenger() && !e.getPersistentData().getBoolean("Delivered")).isEmpty()) + return false; + this.foundPackages = worldIn.getEntitiesWithinAABB(CardboardBoxEntity.class, + owner.getBoundingBox().grow(50.0D, 10.0D, 50.0D), + e -> !e.isPassenger() && !e.getPersistentData().getBoolean("Delivered")); + return !this.foundPackages.isEmpty(); + } + + protected void startExecuting(ServerWorld worldIn, VillagerEntity entityIn, long gameTimeIn) { + LogisticianHandler.ponder(entityIn, "Let's go to that package over there"); + targetedPackage = this.foundPackages.get(worldIn.rand.nextInt(this.foundPackages.size())); + Vec3d vec3d = targetedPackage.getPositionVec(); + entityIn.getBrain().setMemory(MemoryModuleType.LOOK_TARGET, new BlockPosWrapper(new BlockPos(vec3d))); + entityIn.getBrain().setMemory(MemoryModuleType.WALK_TARGET, new WalkTarget(vec3d, 0.5F, 0)); + } + + @Override + protected boolean shouldContinueExecuting(ServerWorld worldIn, VillagerEntity entityIn, long gameTimeIn) { + return !entityIn.getPosition().withinDistance(targetedPackage.getPosition(), 2); + } + +} diff --git a/src/main/java/com/simibubi/create/modules/logistics/transport/villager/WalkToWorkstationTask.java b/src/main/java/com/simibubi/create/modules/logistics/transport/villager/WalkToWorkstationTask.java new file mode 100644 index 000000000..aa1cc4193 --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/logistics/transport/villager/WalkToWorkstationTask.java @@ -0,0 +1,45 @@ +package com.simibubi.create.modules.logistics.transport.villager; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.modules.logistics.transport.CardboardBoxEntity; + +import net.minecraft.block.BlockState; +import net.minecraft.entity.ai.brain.memory.MemoryModuleType; +import net.minecraft.entity.ai.brain.memory.WalkTarget; +import net.minecraft.entity.merchant.villager.VillagerEntity; +import net.minecraft.state.properties.BlockStateProperties; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.GlobalPos; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.server.ServerWorld; + +public class WalkToWorkstationTask extends PackageDeliveryTask { + + public WalkToWorkstationTask() { + super(60); + } + + protected boolean shouldExecute(ServerWorld worldIn, VillagerEntity owner) { + if (!super.shouldExecute(worldIn, owner)) + return false; + CardboardBoxEntity box = getBox(owner); + GlobalPos rememberedAddress = LogisticianHandler.getRememberedAddress(owner, box.getAddress()); + return rememberedAddress == null; + } + + protected void startExecuting(ServerWorld worldIn, VillagerEntity entityIn, long gameTimeIn) { + LogisticianHandler.ponder(entityIn, "I forgot where this address is at"); + GlobalPos workstation = LogisticianHandler.getJobSite(entityIn); + if (workstation != null) { + BlockPos pos = workstation.getPos(); + if (worldIn.isBlockPresent(pos)) { + BlockState blockState = worldIn.getBlockState(pos); + if (AllBlocks.LOGISTICIANS_TABLE.typeOf(blockState)) + pos = pos.offset(blockState.get(BlockStateProperties.HORIZONTAL_FACING)); + } + Vec3d vec = new Vec3d(pos); + entityIn.getBrain().setMemory(MemoryModuleType.WALK_TARGET, new WalkTarget(vec, 0.5F, 0)); + } + } + +} diff --git a/src/main/resources/assets/create/blockstates/logisticians_table.json b/src/main/resources/assets/create/blockstates/logisticians_table.json new file mode 100644 index 000000000..92f089689 --- /dev/null +++ b/src/main/resources/assets/create/blockstates/logisticians_table.json @@ -0,0 +1,14 @@ +{ + "forge_marker": 1, + "defaults": { + "model": "create:block/logisticians_table" + }, + "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/blockstates/logisticians_table_indicator.json b/src/main/resources/assets/create/blockstates/logisticians_table_indicator.json new file mode 100644 index 000000000..a35102a36 --- /dev/null +++ b/src/main/resources/assets/create/blockstates/logisticians_table_indicator.json @@ -0,0 +1,5 @@ +{ + "variants": { + "": { "model": "create:block/logisticians_table_indicator" } + } +} diff --git a/src/main/resources/assets/create/blockstates/motor.json b/src/main/resources/assets/create/blockstates/motor.json index 848b34a19..205bc2114 100644 --- a/src/main/resources/assets/create/blockstates/motor.json +++ b/src/main/resources/assets/create/blockstates/motor.json @@ -1,12 +1,14 @@ { - "forgemarker": 1, + "forge_marker": 1, "defaults": { "model": "create:block/motor" }, "variants": { - "facing=north": { "model": "create:block/motor", "y": 180 }, - "facing=south": { "model": "create:block/motor" }, - "facing=east": { "model": "create:block/motor", "y": 270 }, - "facing=west": { "model": "create:block/motor", "y": 90 } + "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/blockstates/package_funnel.json b/src/main/resources/assets/create/blockstates/package_funnel.json new file mode 100644 index 000000000..d27dbcaba --- /dev/null +++ b/src/main/resources/assets/create/blockstates/package_funnel.json @@ -0,0 +1,16 @@ +{ + "forge_marker": 1, + "defaults": { + "model": "create:block/package_funnel" + }, + "variants": { + "facing": { + "north": { "y": 180 }, + "south": { }, + "west": { "y": 90 }, + "up": { "model": "create:block/package_funnel_vertical", "x": 90 }, + "down": { "model": "create:block/package_funnel_vertical", "x": 270 }, + "east": { "y": 270 } + } + } +} \ 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 7d6e5df00..a35709602 100644 --- a/src/main/resources/assets/create/lang/en_us.json +++ b/src/main/resources/assets/create/lang/en_us.json @@ -85,6 +85,8 @@ "block.create.logistical_casing": "Logistical Casing", "block.create.logistical_controller": "Logistical Controller", "block.create.logistical_index": "Logistical Index", + "block.create.logisticians_table": "Logisticians Table", + "block.create.package_funnel": "Package Funnel", "block.create.tiled_glass": "Tiled Glass", "block.create.tiled_glass_pane": "Tiled Glass Pane", diff --git a/src/main/resources/assets/create/models/block/logisticians_table.json b/src/main/resources/assets/create/models/block/logisticians_table.json new file mode 100644 index 000000000..6a8636b72 --- /dev/null +++ b/src/main/resources/assets/create/models/block/logisticians_table.json @@ -0,0 +1,58 @@ +{ + "__comment": "Model generated using MrCrayfish's Model Creator (https://mrcrayfish.com/tools?id=mc)", + "parent": "block/block", + "textures": { + "particle": "create:block/brass_casing_side", + "smooth_stone_slab_side": "minecraft:block/smooth_stone_slab_side", + "brass_casing_side": "create:block/brass_casing_side", + "brass_casing": "create:block/brass_casing", + "spruce_log": "minecraft:block/spruce_log" + }, + "display": { + "gui": { + "rotation": [ 30, 45, 0 ], + "translation": [ 0, -1.5, 0], + "scale":[ 0.625, 0.625, 0.625 ] + } + }, + "elements": [ + { + "name": "Cube", + "from": [ 4, 0, 4 ], + "to": [ 12, 2, 12 ], + "faces": { + "north": { "texture": "#smooth_stone_slab_side", "uv": [ 3, 14, 11, 16 ] }, + "east": { "texture": "#smooth_stone_slab_side", "uv": [ 8, 0, 16, 2 ] }, + "south": { "texture": "#smooth_stone_slab_side", "uv": [ 3, 0, 11, 2 ] }, + "west": { "texture": "#smooth_stone_slab_side", "uv": [ 16, 0, 8, 2 ] }, + "up": { "texture": "#smooth_stone_slab_side", "uv": [ 4, 0, 12, 8 ], "rotation": 180 }, + "down": { "texture": "#smooth_stone_slab_side", "uv": [ 4, 0, 12, 8 ] } + } + }, + { + "name": "Cube", + "from": [ 5, 2, 5 ], + "to": [ 11, 15, 11 ], + "faces": { + "north": { "texture": "#spruce_log", "uv": [ 4, 1, 10, 15 ] }, + "east": { "texture": "#spruce_log", "uv": [ 6, 2, 12, 15 ] }, + "south": { "texture": "#spruce_log", "uv": [ 7, 1, 14, 14 ] }, + "west": { "texture": "#spruce_log", "uv": [ 4, 1, 10, 14 ] } + } + }, + { + "name": "Top", + "from": [ 0, 12, 0 ], + "to": [ 16, 16, 13 ], + "rotation": { "origin": [ 8, 8, 8 ], "axis": "x", "angle": 22.5 }, + "faces": { + "north": { "texture": "#brass_casing_side", "uv": [ 0, 10, 16, 14 ] }, + "east": { "texture": "#brass_casing_side", "uv": [ 12, 3, 16, 16 ], "rotation": 90 }, + "south": { "texture": "#brass_casing", "uv": [ 0, 0, 16, 4 ] }, + "west": { "texture": "#brass_casing_side", "uv": [ 0, 3, 4, 16 ], "rotation": 270 }, + "up": { "texture": "#brass_casing_side", "uv": [ 0, 3, 16, 16 ] }, + "down": { "texture": "#brass_casing_side", "uv": [ 0, 3, 16, 16 ], "rotation": 180 } + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/create/models/block/logisticians_table_indicator.json b/src/main/resources/assets/create/models/block/logisticians_table_indicator.json new file mode 100644 index 000000000..3de946897 --- /dev/null +++ b/src/main/resources/assets/create/models/block/logisticians_table_indicator.json @@ -0,0 +1,24 @@ +{ + "__comment": "Model generated using MrCrayfish's Model Creator (https://mrcrayfish.com/tools?id=mc)", + "textures": { + "particle": "create:block/brass_casing_side", + "smooth_stone_slab_side": "minecraft:block/smooth_stone_slab_side", + "logistical_controller": "create:block/logistical_controller" + }, + "elements": [ + { + "name": "Cube", + "from": [ 4.75, 3, 4.75 ], + "to": [ 11.25, 5, 11.25 ], + "shade": false, + "faces": { + "north": { "texture": "#logistical_controller", "uv": [ 13, 3, 15, 10 ], "rotation": 270 }, + "east": { "texture": "#logistical_controller", "uv": [ 13, 3, 15, 10 ], "rotation": 90 }, + "south": { "texture": "#logistical_controller", "uv": [ 13, 3, 15, 10 ], "rotation": 90 }, + "west": { "texture": "#logistical_controller", "uv": [ 13, 3, 15, 10 ], "rotation": 90 }, + "up": { "texture": "#smooth_stone_slab_side", "uv": [ 4, 9, 10, 15 ], "rotation": 180 }, + "down": { "texture": "#smooth_stone_slab_side", "uv": [ 4, 1, 10, 7 ] } + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/create/models/block/package_funnel.json b/src/main/resources/assets/create/models/block/package_funnel.json new file mode 100644 index 000000000..4c2cc92e8 --- /dev/null +++ b/src/main/resources/assets/create/models/block/package_funnel.json @@ -0,0 +1,86 @@ +{ + "__comment": "Model generated using MrCrayfish's Model Creator (https://mrcrayfish.com/tools?id=mc)", + "parent": "block/block", + "textures": { + "particle": "create:block/package_funnel_horizontal", + "brass_casing": "create:block/brass_casing", + "belt_funnel": "create:block/belt_funnel", + "package_funnel_horizontal": "create:block/package_funnel_horizontal" + }, + "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 ] + } + }, + "elements": [ + { + "name": "Cube", + "from": [ 1, 1, -1 ], + "to": [ 15, 2, 3 ], + "faces": { + "north": { "texture": "#brass_casing", "uv": [ 1, 14, 15, 15 ] }, + "east": { "texture": "#belt_funnel", "uv": [ 13, 12, 14, 16 ], "rotation": 90 }, + "south": { "texture": "#package_funnel_horizontal", "uv": [ 0, 13, 14, 14 ] }, + "west": { "texture": "#belt_funnel", "uv": [ 13, 12, 14, 16 ], "rotation": 270 }, + "up": { "texture": "#belt_funnel", "uv": [ 0, 12, 14, 16 ] }, + "down": { "texture": "#belt_funnel", "uv": [ 0, 12, 14, 16 ] } + } + }, + { + "name": "Cube", + "from": [ 1, 14, -1 ], + "to": [ 15, 15, 3 ], + "faces": { + "north": { "texture": "#brass_casing", "uv": [ 1, 1, 15, 2 ] }, + "east": { "texture": "#belt_funnel", "uv": [ 0, 12, 1, 16 ], "rotation": 90 }, + "south": { "texture": "#package_funnel_horizontal", "uv": [ 0, 0, 14, 1 ] }, + "west": { "texture": "#belt_funnel", "uv": [ 0, 12, 1, 16 ], "rotation": 270 }, + "up": { "texture": "#belt_funnel", "uv": [ 0, 12, 14, 16 ] }, + "down": { "texture": "#belt_funnel", "uv": [ 0, 12, 14, 16 ] } + } + }, + { + "name": "Cube", + "from": [ 1, 2, -1 ], + "to": [ 2, 14, 3 ], + "faces": { + "north": { "texture": "#brass_casing", "uv": [ 14, 2, 15, 14 ] }, + "east": { "texture": "#belt_funnel", "uv": [ 1, 12, 13, 16 ], "rotation": 270 }, + "south": { "texture": "#package_funnel_horizontal", "uv": [ 0, 1, 1, 13 ] }, + "west": { "texture": "#belt_funnel", "uv": [ 1, 12, 13, 16 ], "rotation": 90 } + } + }, + { + "name": "Cube", + "from": [ 14, 2, -1 ], + "to": [ 15, 14, 3 ], + "faces": { + "north": { "texture": "#brass_casing", "uv": [ 1, 2, 2, 14 ] }, + "east": { "texture": "#belt_funnel", "uv": [ 1, 12, 13, 16 ], "rotation": 270 }, + "south": { "texture": "#package_funnel_horizontal", "uv": [ 13, 1, 14, 13 ] }, + "west": { "texture": "#belt_funnel", "uv": [ 1, 12, 13, 16 ], "rotation": 90 } + } + }, + { + "name": "Inner", + "from": [ 2, 2, -1 ], + "to": [ 14, 14, 2 ], + "faces": { + "north": { "texture": "#brass_casing", "uv": [ 2, 2, 14, 14 ] }, + "south": { "texture": "#package_funnel_horizontal", "uv": [ 1, 1, 13, 13 ] } + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/create/models/block/package_funnel_vertical.json b/src/main/resources/assets/create/models/block/package_funnel_vertical.json new file mode 100644 index 000000000..d5e2b791b --- /dev/null +++ b/src/main/resources/assets/create/models/block/package_funnel_vertical.json @@ -0,0 +1,7 @@ +{ + "parent": "create:block/package_funnel", + "textures": { + "particle": "create:block/package_funnel_vertical", + "package_funnel_horizontal": "create:block/package_funnel_vertical" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/create/models/item/logisticians_table.json b/src/main/resources/assets/create/models/item/logisticians_table.json new file mode 100644 index 000000000..00a18489e --- /dev/null +++ b/src/main/resources/assets/create/models/item/logisticians_table.json @@ -0,0 +1,3 @@ +{ + "parent": "create:block/logisticians_table" +} \ No newline at end of file diff --git a/src/main/resources/assets/create/models/item/package_funnel.json b/src/main/resources/assets/create/models/item/package_funnel.json new file mode 100644 index 000000000..2a55220b0 --- /dev/null +++ b/src/main/resources/assets/create/models/item/package_funnel.json @@ -0,0 +1,3 @@ +{ + "parent": "create:block/package_funnel" +} \ No newline at end of file diff --git a/src/main/resources/assets/create/textures/block/belt_funnel.png b/src/main/resources/assets/create/textures/block/belt_funnel.png index ad263e88c68fe2a98280fc66cd0ab900d8e3c000..1e8742ea3140583a6fd051fc30edc13fd6ae723f 100644 GIT binary patch delta 468 zcmV;_0W1EZ1Cs=hNq@lr01m+cxRGn^0004~NklevH3<%mt~lTf zwOY*we%AZD8?c$dq<%uIEkYK+VyaRH%}m$%@H2v_j8dtLF>;8N1380|vff9|T2v~P zAB9K(N+ZoJoO1{ip9SnA`R{MgK`=;OJh*;hpm`g`_or1pKfUv-te}13rL`*5_SS+M71kh+{H6HN#UuU4T`5H4@Kg9Ph~6HaK6 zV8s=3o~|s4a4mSZMazBa1_>^%9|s9Oe?cZI&^q#3T7SpaF92`3OeK}oqt!mykmSZ7%Ya}Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0XRuSK~y+TrIR~O z#4r$sf7^LzA=x0Uau`}F#9^o?5Tc>m0*Q)(Ls4)6prqijk&`%ycWrEA2o$Uw_$15! zDDjMEJVVZo_w`OX!(wlNji%6Aff0qZB8cM{L)RclQ*?cgTC`{d$IuI0-rNybE=~?~ zS(chH7QA1bA8LaMra_A=caEk&Sn3r(BgT+r*`&py$R9TjwEjqC3MLJ&>#U&PcjOZ2U}+iWSN+by>B+y^aQuzI@x z`f;0`=VR~CrmcYL5otu+O5`iV^TV%pfj97)`{Tv|ZyP6OF$r3heh_ZAkmc!-=3<5U zZjO0YxHgr2>jp`h`X(l-9Uhp<+hDw|pp?Y&`qp_Pb|C)4_#S@(cnAKgi*5tilKuby N002ovPDHLkV1oIJvU&gj literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/create/textures/block/package_funnel_vertical.png b/src/main/resources/assets/create/textures/block/package_funnel_vertical.png new file mode 100644 index 0000000000000000000000000000000000000000..d43dfa2d6abda2a17b94d789d7a3aee3c4b428dc GIT binary patch literal 600 zcmV-e0;m0nP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0qsddK~y+TrBh38 z)Ibn@{j+B>+m<#0j!s%YqBA$yq?+B2f}2ZnxbZUbStQH9ToF>Zz}`Ua_Jl#*doM$8J%IZWdlnzqFl0$%-q!S|Sg$Cq!v6bRckdwhTR ziK|`1W5E=Q#47?X8Dn6rg|h~Y2404M5AWZt6@We;JG3k~XvLq#wN==a87@a=9gfc6 zXf-;g(UgKiW1&pDUT2Aw4rI1QA*Y$$G%el1SLBqynAe2sv)7Rf*C# zm_{-6B~w(gG!@XlLiY7UNU=2*XIJpTc)aic+|s~B z>$+|Ykid^U#y>TSl*mGX48YSck*~F-3dsTeYhUvME&DxDLeFX+XAIMfC$8&rh@6gi z0X$BLxr9gW;pd1j`Sm(m-ha9)y??^#(BX7E*EOBPP(LJ^j)to(ACDN-4{z-LOeHh! mzy7Flm2BPr;O{*C3BYf&9Nzy`S~Cd%0000Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!TI# z!HR-Pbs;W<2#W7jrM~FP)V7I^`R|-Ny_wD=6Z=Xs^TFYqIp@ygo^v0WkQqf)RhEk8 zP`%#3Q(VOL^h}Iv@FMa?Au}f_Ae|PGe7<430P?8kQ!z500YycHT;~h63y`m5T!2_C zPF8+ks{r!!cjOYl1}G<jr5g`1&QnECDMSqiJpKQF3P#WuM(-y$vDdwFQ zBaeLmNlZ`A@MAmR8ZzSC$lH(0S^#@XAkkSQjKu#ZdBCqBNw%QWtY2$u39PCJlBMx; zWQ?r&QN5;;tn_%j$;(hMIhpx#6xc2R@KXnV&Eo@&h-+F=7Vwc}&iF)>tp6kJkD+|W zy%QwuSlj}Tb}ViINIMp{0Hhs@TL99I#Vr77$Kn=%v}17#K-#gm1t9HM+yanxEN%fv zI~Kgy{DEL}a zrx}}|hrruUbTbw#X8or-`Ei+VcGHvX_Om^Vjm@zBi(ULUP?)%wC-G}9ajld0M_KQ_ za`W@DtN?SDfLD8@6`h6{N%B)$85H6ArLC;v&M0{_tga`sy}3zk35C>9{pKWr4>4-C zpcKfXuM=Y|e7uK`CIq7k5y#=fiCHrHyfX*az$ia>snzt%@m=iQkd`t0LQ;W8Xs2R{ z4=@1VVm)4~9Bka6SGKaMiY&$|=;`ng8&8G*7#=2zu}vFm*uF!n*@vMZd)6OGih;h! zXUipk(I(TB$eXtdzI^x|KsFy;u=kj@4-A~w_5mZ|Q`-6;xZ0(k12FwD1LWehHvHu_ zKsI_ zIis(8A@BjwMx2A>5XY!v89?NCwo+j1pco}}TuW5M<#r-wHlmpFb?c&B+IFlauRThN zXd0Q2DmEYV8GvMr35i5yj6QK5z9j^*oe6lW#4J(xjBlJQ6a{99%ZPZoc0*&yVmwbs zDtvw)^Oky8&>vs{pI6uLc}f;%1}Lvy-Q_#)=;)MwOACZuUS7hF5r>_sogA}jd+6e)KpD5=@i==p_-x_72D9mpitz58yfZ5bXWvamL2wK`@aRc? u7XV-ueE<55d5X1-q^x4)q9xB5WB&lykO33Fk?>^z0000Px#1ZP1_K>z@;j|==^1poj532;bRa{vGizW@LZzX3P}QzQTY0U$|4K~y+TWBmXB zKLaIz2}+X}Bv2sY!fThe{eSuN%>R;tC?FTYhsnV(3I~K?ieQ@W-`f5E z+==D?L3|J!W*7{kL?g(#ii(O1_wV0lu(5Mv`1bWZ!@0Ak!E#2%rVQ`jyrKYe@~tQn*cWa#y4SHN--5)us0pS}dE0RgZ9Fq>gE zf;53#as1>JxUHI6I$%SVt=P;^T%5vCS{My>I@|>y(_xxHnn0SPB7DIbK(>P9Ku!mV zfeeSa0&DPx#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0YynfK~y+TWBmXB zKLaIz2}+XD2Bid z0BHs(Vg%}a#}&jNCME{ftfZvG@K-zuWGGmjj7>P0h5@hvARA#e)YtQaHNATEia}fQ z7{iw@U%)QN?{;RGSh|-Xw)r)Kf_pPKT;K+Leew)NGe{FiGsrs+cGfavG}$sdp1X?S z^mBc1cz_Il_wF4?E5v~JU;i_d`YnPx8)PF$^OGYh8Lq$j3f3GsUx`6kSsASP?%lf# z_b%)O8vxG>E-o%$#-~r87%YXZfyF>z^O>&)YJ a0|NlvADT@cC=}xW0000x3eLOs+8lb zCr_VB%GuSNV7R=e=Ca}j8IRA?_2VV%YJMCj`1`B0Ep&C5VbhU^dJQ)+c%Ght{K6u4}U572`|Essv8yG)0loS>+8r#+WI+BpLfN4A9 zk_oNR6CR$w{+%c3P*XuKd*6Ik_D2)W`|$8EH1KYyj9AGl3=B>NPgg&ebxsLQ0N`?; AJ^%m! literal 0 HcmV?d00001