From 4da92fd505c1a9e5b46256fe2b668edfbc0c8af5 Mon Sep 17 00:00:00 2001 From: Michael Hillcox Date: Sun, 3 Jan 2021 11:12:30 +0000 Subject: [PATCH] Feeder block mostly implemented --- src/generated/resources/.cache/cache | 2 +- .../assets/actuallyadditions/lang/en_us.json | 4 + .../actuallyadditions/client/ClientSetup.java | 2 + .../client/screens/FeederScreen.java | 69 +++++++++ .../common/ActuallyAdditions.java | 2 + .../common/blocks/functional/FeederBlock.java | 38 ++++- .../blocks/functional/package-info.java | 7 + .../common/config/GeneralConfig.java | 6 + .../common/container/ActuallyContainers.java | 3 + .../common/container/FeederContainer.java | 63 ++++++++ .../common/items/useables/DrillItem.java | 24 ++- .../common/tiles/ActuallyTile.java | 49 ++++++ .../common/tiles/ActuallyTiles.java | 14 ++ .../common/tiles/FeederTileEntity.java | 142 ++++++++++++++++++ .../common/tiles/package-info.java | 7 + .../data/GeneratorLanguage.java | 5 + 16 files changed, 422 insertions(+), 15 deletions(-) create mode 100644 src/main/java/de/ellpeck/actuallyadditions/client/screens/FeederScreen.java create mode 100644 src/main/java/de/ellpeck/actuallyadditions/common/blocks/functional/package-info.java create mode 100644 src/main/java/de/ellpeck/actuallyadditions/common/container/FeederContainer.java create mode 100644 src/main/java/de/ellpeck/actuallyadditions/common/tiles/ActuallyTile.java create mode 100644 src/main/java/de/ellpeck/actuallyadditions/common/tiles/ActuallyTiles.java create mode 100644 src/main/java/de/ellpeck/actuallyadditions/common/tiles/FeederTileEntity.java create mode 100644 src/main/java/de/ellpeck/actuallyadditions/common/tiles/package-info.java diff --git a/src/generated/resources/.cache/cache b/src/generated/resources/.cache/cache index 4301dbc95..37a8e6fc4 100644 --- a/src/generated/resources/.cache/cache +++ b/src/generated/resources/.cache/cache @@ -122,7 +122,7 @@ e2c81adfe240117fa0ce2e3dfcfd04f4e1034153 assets/actuallyadditions/blockstates/wh 3670535838b4c26d01afe7ee4807c53a6cbaba12 assets/actuallyadditions/blockstates/white_wall_block.json 78e89628e3c6e891f2994b2a1794672f69826516 assets/actuallyadditions/blockstates/wood_casing_block.json 207adf3d139369e983100a6002f6f77d36d40916 assets/actuallyadditions/blockstates/xp_solidifier_block.json -57f188ff4295a701102e0f7084a59d8b01a79112 assets/actuallyadditions/lang/en_us.json +05c5a950e54b4a1640a8afc2f596b6a636577761 assets/actuallyadditions/lang/en_us.json 997ea09e934d491608895093fc7ba8d2022a50f5 assets/actuallyadditions/models/block/black_brick_quartz_slab_block.json fa8ed5a44ee7475368eaa6c8afcd2fdcc0342a4f assets/actuallyadditions/models/block/black_brick_quartz_slab_block_top.json 00fe865b4ff89f2a82cc40bf11c806fd5ef22130 assets/actuallyadditions/models/block/black_brick_quartz_stair_block.json diff --git a/src/generated/resources/assets/actuallyadditions/lang/en_us.json b/src/generated/resources/assets/actuallyadditions/lang/en_us.json index 5e870069d..6c97185ea 100644 --- a/src/generated/resources/assets/actuallyadditions/lang/en_us.json +++ b/src/generated/resources/assets/actuallyadditions/lang/en_us.json @@ -1,5 +1,9 @@ { "actuallyadditions.gui.name.drill": "Drill", + "actuallyadditions.info.gui.animals": "%s Animals", + "actuallyadditions.info.gui.enoughToBreed": "Enough to breed!", + "actuallyadditions.info.gui.notEnough": "Not enough to breed!", + "actuallyadditions.info.gui.tooMany": "Too many to breed!", "actuallyadditions.storage.crystal-flux": "%s/%s Crystal Flux", "actuallyadditions.tooltip.battery.charge-help": "Sneak-right-click to toggle", "actuallyadditions.tooltip.battery.charging": "Charging other item in inventory", diff --git a/src/main/java/de/ellpeck/actuallyadditions/client/ClientSetup.java b/src/main/java/de/ellpeck/actuallyadditions/client/ClientSetup.java index 655804935..9e49a30e6 100644 --- a/src/main/java/de/ellpeck/actuallyadditions/client/ClientSetup.java +++ b/src/main/java/de/ellpeck/actuallyadditions/client/ClientSetup.java @@ -1,6 +1,7 @@ package de.ellpeck.actuallyadditions.client; import de.ellpeck.actuallyadditions.client.screens.DrillScreen; +import de.ellpeck.actuallyadditions.client.screens.FeederScreen; import de.ellpeck.actuallyadditions.common.container.ActuallyContainers; import net.minecraft.client.gui.ScreenManager; @@ -11,5 +12,6 @@ public class ClientSetup { private static void setupScreens() { ScreenManager.registerFactory(ActuallyContainers.DRILL_CONTAINER.get(), DrillScreen::new); + ScreenManager.registerFactory(ActuallyContainers.FEEDER_CONTAINER.get(), FeederScreen::new); } } diff --git a/src/main/java/de/ellpeck/actuallyadditions/client/screens/FeederScreen.java b/src/main/java/de/ellpeck/actuallyadditions/client/screens/FeederScreen.java new file mode 100644 index 000000000..eae1f9743 --- /dev/null +++ b/src/main/java/de/ellpeck/actuallyadditions/client/screens/FeederScreen.java @@ -0,0 +1,69 @@ +package de.ellpeck.actuallyadditions.client.screens; + +import com.mojang.blaze3d.matrix.MatrixStack; +import de.ellpeck.actuallyadditions.common.container.FeederContainer; +import de.ellpeck.actuallyadditions.common.tiles.FeederTileEntity; +import de.ellpeck.actuallyadditions.common.utilities.Help; +import de.ellpeck.actuallyadditions.common.utilities.ScreenHelper; +import net.minecraft.entity.player.PlayerInventory; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.text.ITextComponent; +import net.minecraft.util.text.ITextProperties; +import net.minecraft.util.text.LanguageMap; + +import java.util.ArrayList; +import java.util.List; + +public class FeederScreen extends WtfMojangScreen { + private static final ResourceLocation background = ScreenHelper.getGuiLocation("gui_feeder"); + public final FeederTileEntity tileFeeder; + + public FeederScreen(FeederContainer screenContainer, PlayerInventory inv, ITextComponent titleIn) { + super(screenContainer, inv, titleIn); + + this.xSize = 176; + this.ySize = 70 + 86; + + this.titleY += 90; + this.tileFeeder = (FeederTileEntity) inv.player.world.getTileEntity(screenContainer.tile.getPos()); + } + + @Override + protected void drawGuiContainerBackgroundLayer(MatrixStack matrixStack, float partialTicks, int x, int y) { + getMinecraft().getTextureManager().bindTexture(ScreenHelper.INVENTORY_GUI); + blit(matrixStack, this.guiLeft, this.guiTop + 70, 0, 0, 176, 86); + + getMinecraft().getTextureManager().bindTexture(background); + blit(matrixStack, this.guiLeft, this.guiTop, 0, 0, 176, 70); + + if (this.tileFeeder.currentTimer > 0) { + int i = this.tileFeeder.getCurrentTimerToScale(20); + this.blit(matrixStack, this.guiLeft + 85, this.guiTop + 42 - i, 181, 19 + 19 - i, 6, 20); + } + + if (this.tileFeeder.currentAnimalAmount >= 2 && this.tileFeeder.currentAnimalAmount < FeederTileEntity.THRESHOLD) { + this.blit(matrixStack, this.guiLeft + 70, this.guiTop + 31, 192, 16, 8, 8); + } + + if (this.tileFeeder.currentAnimalAmount >= FeederTileEntity.THRESHOLD) { + this.blit(matrixStack, this.guiLeft + 70, this.guiTop + 31, 192, 24, 8, 8); + } + } + + @Override + public void render(MatrixStack matrixStack, int x, int y, float partialTicks) { + super.render(matrixStack, x, y, partialTicks); + + if (x >= this.guiLeft + 69 && y >= this.guiTop + 30 && x <= this.guiLeft + 69 + 10 && y <= this.guiTop + 30 + 10) { + List array = new ArrayList<>(); + array.add(Help.trans("info.gui.animals", this.tileFeeder.currentAnimalAmount)); + array.add(tileFeeder.currentAnimalAmount >= 2 && tileFeeder.currentAnimalAmount < FeederTileEntity.THRESHOLD + ? Help.trans("info.gui.enoughToBreed") + : tileFeeder.currentAnimalAmount >= FeederTileEntity.THRESHOLD + ? Help.trans("info.gui.tooMany") + : Help.trans("info.gui.notEnough")); + + this.renderToolTip(matrixStack, LanguageMap.getInstance().func_244260_a(array), x, y, font); + } + } +} diff --git a/src/main/java/de/ellpeck/actuallyadditions/common/ActuallyAdditions.java b/src/main/java/de/ellpeck/actuallyadditions/common/ActuallyAdditions.java index 4da7d128b..5b68fea82 100644 --- a/src/main/java/de/ellpeck/actuallyadditions/common/ActuallyAdditions.java +++ b/src/main/java/de/ellpeck/actuallyadditions/common/ActuallyAdditions.java @@ -6,6 +6,7 @@ import de.ellpeck.actuallyadditions.common.commands.DebugCommand; import de.ellpeck.actuallyadditions.common.config.Config; import de.ellpeck.actuallyadditions.common.container.ActuallyContainers; import de.ellpeck.actuallyadditions.common.items.ActuallyItems; +import de.ellpeck.actuallyadditions.common.tiles.ActuallyTiles; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.RenderTypeLookup; import net.minecraft.command.Commands; @@ -46,6 +47,7 @@ public class ActuallyAdditions { ActuallyBlocks.BLOCKS.register(eventBus); ActuallyItems.ITEMS.register(eventBus); ActuallyContainers.CONTAINERS.register(eventBus); + ActuallyTiles.TILES.register(eventBus); eventBus.addListener(this::setup); eventBus.addListener(this::clientSetup); diff --git a/src/main/java/de/ellpeck/actuallyadditions/common/blocks/functional/FeederBlock.java b/src/main/java/de/ellpeck/actuallyadditions/common/blocks/functional/FeederBlock.java index 7a856c7f2..3997f0ccf 100644 --- a/src/main/java/de/ellpeck/actuallyadditions/common/blocks/functional/FeederBlock.java +++ b/src/main/java/de/ellpeck/actuallyadditions/common/blocks/functional/FeederBlock.java @@ -1,16 +1,27 @@ package de.ellpeck.actuallyadditions.common.blocks.functional; import de.ellpeck.actuallyadditions.common.blocks.ActuallyBlock; +import de.ellpeck.actuallyadditions.common.tiles.ActuallyTiles; +import de.ellpeck.actuallyadditions.common.tiles.FeederTileEntity; import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.block.material.Material; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.entity.player.ServerPlayerEntity; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.ActionResultType; +import net.minecraft.util.Hand; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.BlockRayTraceResult; import net.minecraft.util.math.shapes.IBooleanFunction; import net.minecraft.util.math.shapes.ISelectionContext; import net.minecraft.util.math.shapes.VoxelShape; import net.minecraft.util.math.shapes.VoxelShapes; import net.minecraft.world.IBlockReader; +import net.minecraft.world.World; +import net.minecraftforge.fml.network.NetworkHooks; +import javax.annotation.Nullable; import java.util.stream.Stream; public class FeederBlock extends ActuallyBlock { @@ -33,8 +44,33 @@ public class FeederBlock extends ActuallyBlock { Block.makeCuboidShape(12, 14, 1, 15, 15, 15), Block.makeCuboidShape(1, 1, 1, 15, 2, 15), Block.makeCuboidShape(14, 2, 1, 15, 14, 15), Block.makeCuboidShape(1, 2, 1, 2, 14, 15), Block.makeCuboidShape(2, 2, 14, 14, 14, 15), Block.makeCuboidShape(2, 2, 1, 14, 14, 2) - ).reduce((v1, v2) -> {return VoxelShapes.combineAndSimplify(v1, v2, IBooleanFunction.OR);}).get(); + ).reduce((v1, v2) -> VoxelShapes.combineAndSimplify(v1, v2, IBooleanFunction.OR)).get(); + @Nullable + @Override + public TileEntity createTileEntity(BlockState state, IBlockReader world) { + return ActuallyTiles.FEEDER_TILE.get().create(); + } + + @Override + public boolean hasTileEntity(BlockState state) { + return true; + } + + @Override + public ActionResultType onBlockActivated(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand handIn, BlockRayTraceResult hit) { + if (worldIn.isRemote) { + return ActionResultType.SUCCESS; + } + + TileEntity te = worldIn.getTileEntity(pos); + if (! (te instanceof FeederTileEntity)) { + return ActionResultType.FAIL; + } + + NetworkHooks.openGui((ServerPlayerEntity) player, (FeederTileEntity) te, pos); + return ActionResultType.SUCCESS; + } @Override public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) { diff --git a/src/main/java/de/ellpeck/actuallyadditions/common/blocks/functional/package-info.java b/src/main/java/de/ellpeck/actuallyadditions/common/blocks/functional/package-info.java new file mode 100644 index 000000000..9994bd744 --- /dev/null +++ b/src/main/java/de/ellpeck/actuallyadditions/common/blocks/functional/package-info.java @@ -0,0 +1,7 @@ +@ParametersAreNonnullByDefault +@MethodsReturnNonnullByDefault +package de.ellpeck.actuallyadditions.common.blocks.functional; + +import mcp.MethodsReturnNonnullByDefault; + +import javax.annotation.ParametersAreNonnullByDefault; \ No newline at end of file diff --git a/src/main/java/de/ellpeck/actuallyadditions/common/config/GeneralConfig.java b/src/main/java/de/ellpeck/actuallyadditions/common/config/GeneralConfig.java index c0e05b2e0..d0c544cb5 100644 --- a/src/main/java/de/ellpeck/actuallyadditions/common/config/GeneralConfig.java +++ b/src/main/java/de/ellpeck/actuallyadditions/common/config/GeneralConfig.java @@ -5,14 +5,20 @@ import static net.minecraftforge.common.ForgeConfigSpec.*; public class GeneralConfig { public final BooleanValue advancedInfo; + public final IntValue tileEntityUpdateInterval; public GeneralConfig() { CLIENT_BUILDER.comment("Actually Additions General Config").push("general"); + SERVER_BUILDER.comment("Actually Additions General Config").push("general"); advancedInfo = CLIENT_BUILDER .comment("Shows advanced item info when holding control on every item") .define("Advanced Info", true); + tileEntityUpdateInterval = CLIENT_BUILDER + .comment("The amount of ticks waited before a TileEntity sends an additional update to the client") + .defineInRange("Tile Entities Update Interval", 5, 1, 100); + CLIENT_BUILDER.pop(); } } diff --git a/src/main/java/de/ellpeck/actuallyadditions/common/container/ActuallyContainers.java b/src/main/java/de/ellpeck/actuallyadditions/common/container/ActuallyContainers.java index e87be7273..0a85fc0e8 100644 --- a/src/main/java/de/ellpeck/actuallyadditions/common/container/ActuallyContainers.java +++ b/src/main/java/de/ellpeck/actuallyadditions/common/container/ActuallyContainers.java @@ -12,4 +12,7 @@ public final class ActuallyContainers { public static final RegistryObject> DRILL_CONTAINER = CONTAINERS.register("drill_container", () -> IForgeContainerType.create(DrillContainer::fromNetwork)); + + public static final RegistryObject> FEEDER_CONTAINER + = CONTAINERS.register("feeder_container", () -> IForgeContainerType.create(FeederContainer::fromNetwork)); } diff --git a/src/main/java/de/ellpeck/actuallyadditions/common/container/FeederContainer.java b/src/main/java/de/ellpeck/actuallyadditions/common/container/FeederContainer.java new file mode 100644 index 000000000..4620138d6 --- /dev/null +++ b/src/main/java/de/ellpeck/actuallyadditions/common/container/FeederContainer.java @@ -0,0 +1,63 @@ +package de.ellpeck.actuallyadditions.common.container; + +import de.ellpeck.actuallyadditions.common.tiles.FeederTileEntity; +import de.ellpeck.actuallyadditions.common.utilities.ContainerHelper; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.entity.player.PlayerInventory; +import net.minecraft.inventory.container.Container; +import net.minecraft.inventory.container.Slot; +import net.minecraft.item.ItemStack; +import net.minecraft.network.PacketBuffer; +import net.minecraftforge.items.CapabilityItemHandler; +import net.minecraftforge.items.SlotItemHandler; +import net.minecraftforge.items.wrapper.InvWrapper; + +import java.util.Objects; + +public class FeederContainer extends Container { + private final PlayerInventory inv; + public final FeederTileEntity tile; + + public static FeederContainer fromNetwork(int windowId, PlayerInventory inv, PacketBuffer data) { + return new FeederContainer(windowId, inv, (FeederTileEntity) Objects.requireNonNull(inv.player.world.getTileEntity(data.readBlockPos()))); + } + + public FeederContainer(int windowId, PlayerInventory inv, FeederTileEntity tile) { + super(ActuallyContainers.FEEDER_CONTAINER.get(), windowId); + + this.inv = inv; + this.tile = tile; + + ContainerHelper.setupPlayerInventory(new InvWrapper(inv), 0, ContainerHelper.DEFAULT_SLOTS_X, 132, this::addSlot); + + this.tile.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY).ifPresent(e -> addSlot(new SlotItemHandler(e, 0, 80, 45))); + } + + @Override + public boolean canInteractWith(PlayerEntity playerIn) { + return true; + } + + @Override + public ItemStack transferStackInSlot(PlayerEntity playerIn, int index) { + Slot fromSlot = this.inventorySlots.get(index); + + if (fromSlot == null || !fromSlot.getHasStack()) { + return ItemStack.EMPTY; + } + + ItemStack fromStack = fromSlot.getStack(); + + if (index > ContainerHelper.PLAYER_INVENTORY_END_SLOT) { + if (!this.mergeItemStack(fromStack, 0, ContainerHelper.PLAYER_INVENTORY_END_SLOT, false)) { + return ItemStack.EMPTY; + } + } else { + if (!this.mergeItemStack(fromStack, ContainerHelper.PLAYER_INVENTORY_END_SLOT + 1, ContainerHelper.PLAYER_INVENTORY_END_SLOT + 2, false)) { + return ItemStack.EMPTY; + } + } + + return fromStack; + } +} diff --git a/src/main/java/de/ellpeck/actuallyadditions/common/items/useables/DrillItem.java b/src/main/java/de/ellpeck/actuallyadditions/common/items/useables/DrillItem.java index 23fe04127..1de457a07 100644 --- a/src/main/java/de/ellpeck/actuallyadditions/common/items/useables/DrillItem.java +++ b/src/main/java/de/ellpeck/actuallyadditions/common/items/useables/DrillItem.java @@ -56,15 +56,13 @@ public class DrillItem extends CrystalFluxItem { private static final int BASE_ENERGY_USE = 100; public DrillItem() { - super( - baseProps() + super(baseProps() .maxDamage(0) .setNoRepair() .addToolType(ToolType.PICKAXE, 4) .addToolType(ToolType.SHOVEL, 4), Config.ITEM_CONFIG.drillMaxEnergy::get, - 1000 - ); + 1000); } @Override @@ -98,7 +96,7 @@ public class DrillItem extends CrystalFluxItem { int crystalFlux = getCrystalFlux(stack).map(IEnergyStorage::getEnergyStored).orElse(0); int fluxPerBlock = this.getFluxPerBlock(stack); - if (crystalFlux < fluxPerBlock) { + if (crystalFlux < fluxPerBlock && !player.isCreative()) { return false; } @@ -140,9 +138,10 @@ public class DrillItem extends CrystalFluxItem { Set posSet = new HashSet<>(); + int y = radius == 2 ? pos.getY() + 1 : pos.getY(); // Uses the facing axis to move around the X,Y,Z to allow for multiple faces in 2 for loops - int a = axis != Direction.Axis.X ? pos.getX() : pos.getY(); // Z & Y plane both use X - int b = axis != Direction.Axis.Z ? pos.getZ() : pos.getY(); // X & Y plane both use Z + int a = axis != Direction.Axis.X ? pos.getX() : y; // Z & Y plane both use X + int b = axis != Direction.Axis.Z ? pos.getZ() : y; // X & Y plane both use Z for (int i = (a - radius); i < (a + radius) + 1; i++) { for (int j = (b - radius); j < (b + radius) + 1; j++) { @@ -156,11 +155,11 @@ public class DrillItem extends CrystalFluxItem { } Set failed = new HashSet<>(); - posSet.forEach(e -> { + for (BlockPos e : posSet) { if (!destroyBlock(e, pick.getFace(), player, world, drill, drillEnchanted, fluxPerBlock, (cost) -> getCrystalFlux(drill).ifPresent(x -> x.extractEnergy(cost, false)))) { failed.add(e); } - }); + } return failed.contains(pick.getPos()); } @@ -180,14 +179,14 @@ public class DrillItem extends CrystalFluxItem { * * @return returns false if the block gets blocked by another mod */ - // Todo: if we ever need this again, move to world helper + // TODO: if we ever need this again, move to world helper private boolean destroyBlock(BlockPos pos, Direction face, PlayerEntity player, World world, ItemStack drill, ItemStack drillEnchanted, int fluxPerBlock, Consumer onBreak) { BlockState state = world.getBlockState(pos); int flux = this.getCrystalFlux(drill).map(IEnergyStorage::getEnergyStored).orElse(0); if (world.isAirBlock(pos) - || flux < fluxPerBlock - || state.getBlockHardness(world, pos) <= 0f + || (flux < fluxPerBlock && !player.isCreative()) + || state.getBlockHardness(world, pos) <= 0 || !ForgeHooks.canHarvestBlock(state, player, world, pos)) { return false; } @@ -207,7 +206,6 @@ public class DrillItem extends CrystalFluxItem { ((ServerPlayerEntity) player).connection.sendPacket(new SChangeBlockPacket(world, pos)); } - onBreak.accept(fluxPerBlock); return true; } diff --git a/src/main/java/de/ellpeck/actuallyadditions/common/tiles/ActuallyTile.java b/src/main/java/de/ellpeck/actuallyadditions/common/tiles/ActuallyTile.java new file mode 100644 index 000000000..bcf5e9a02 --- /dev/null +++ b/src/main/java/de/ellpeck/actuallyadditions/common/tiles/ActuallyTile.java @@ -0,0 +1,49 @@ +package de.ellpeck.actuallyadditions.common.tiles; + +import net.minecraft.block.BlockState; +import net.minecraft.entity.player.ServerPlayerEntity; +import net.minecraft.nbt.CompoundNBT; +import net.minecraft.network.NetworkManager; +import net.minecraft.network.play.server.SUpdateTileEntityPacket; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.tileentity.TileEntityType; +import net.minecraft.util.math.ChunkPos; +import net.minecraft.world.server.ServerWorld; + +import javax.annotation.Nullable; +import java.util.Objects; +import java.util.stream.Stream; + +public class ActuallyTile extends TileEntity { + public ActuallyTile(TileEntityType tileEntityTypeIn) { + super(tileEntityTypeIn); + } + + @Override + public CompoundNBT getUpdateTag() { + return this.write(new CompoundNBT()); + } + + @Override + public void handleUpdateTag(BlockState state, CompoundNBT tag) { + this.read(state, tag); + } + + @Override + public void onDataPacket(NetworkManager net, SUpdateTileEntityPacket pkt) { + this.read(this.getBlockState(), pkt.getNbtCompound()); + } + + @Nullable + @Override + public SUpdateTileEntityPacket getUpdatePacket() { + return new SUpdateTileEntityPacket(this.pos, -1, this.serializeNBT()); + } + + public void sendTileEntityToClients() { + ServerWorld world = (ServerWorld) this.getWorld(); + Stream entities = world.getChunkProvider().chunkManager.getTrackingPlayers(new ChunkPos(this.getPos()), false); + SUpdateTileEntityPacket packet = this.getUpdatePacket(); + entities.forEach(e -> e.connection.sendPacket(Objects.requireNonNull(packet))); + } +} diff --git a/src/main/java/de/ellpeck/actuallyadditions/common/tiles/ActuallyTiles.java b/src/main/java/de/ellpeck/actuallyadditions/common/tiles/ActuallyTiles.java new file mode 100644 index 000000000..c8ef28287 --- /dev/null +++ b/src/main/java/de/ellpeck/actuallyadditions/common/tiles/ActuallyTiles.java @@ -0,0 +1,14 @@ +package de.ellpeck.actuallyadditions.common.tiles; + +import de.ellpeck.actuallyadditions.common.ActuallyAdditions; +import de.ellpeck.actuallyadditions.common.blocks.ActuallyBlocks; +import net.minecraft.tileentity.TileEntityType; +import net.minecraftforge.fml.RegistryObject; +import net.minecraftforge.registries.DeferredRegister; +import net.minecraftforge.registries.ForgeRegistries; + +public final class ActuallyTiles { + public static final DeferredRegister> TILES = DeferredRegister.create(ForgeRegistries.TILE_ENTITIES, ActuallyAdditions.MOD_ID); + + public static final RegistryObject> FEEDER_TILE = TILES.register("feeder_tile", () -> TileEntityType.Builder.create(FeederTileEntity::new, ActuallyBlocks.FEEDER.get()).build(null)); +} diff --git a/src/main/java/de/ellpeck/actuallyadditions/common/tiles/FeederTileEntity.java b/src/main/java/de/ellpeck/actuallyadditions/common/tiles/FeederTileEntity.java new file mode 100644 index 000000000..13ca61e08 --- /dev/null +++ b/src/main/java/de/ellpeck/actuallyadditions/common/tiles/FeederTileEntity.java @@ -0,0 +1,142 @@ +package de.ellpeck.actuallyadditions.common.tiles; + +import de.ellpeck.actuallyadditions.common.container.FeederContainer; +import net.minecraft.block.BlockState; +import net.minecraft.entity.passive.AnimalEntity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.entity.player.PlayerInventory; +import net.minecraft.inventory.container.Container; +import net.minecraft.inventory.container.INamedContainerProvider; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.CompoundNBT; +import net.minecraft.particles.ParticleTypes; +import net.minecraft.tileentity.ITickableTileEntity; +import net.minecraft.util.Direction; +import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.text.ITextComponent; +import net.minecraft.util.text.StringTextComponent; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.util.LazyOptional; +import net.minecraftforge.items.CapabilityItemHandler; +import net.minecraftforge.items.IItemHandler; +import net.minecraftforge.items.ItemStackHandler; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.List; + +public class FeederTileEntity extends ActuallyTile implements INamedContainerProvider, ITickableTileEntity { + public static final int THRESHOLD = 30; + private static final int TIME = 100; + private final ItemStackHandler itemStackHandler = new ItemStackHandler(1) { + @Override + protected void onContentsChanged(int slot) { + FeederTileEntity.this.markDirty(); + } + }; + private final LazyOptional handler = LazyOptional.of(() -> itemStackHandler); + public int currentTimer; + public int currentAnimalAmount; + + public FeederTileEntity() { + super(ActuallyTiles.FEEDER_TILE.get()); + } + + @Override + public void tick() { + int last = this.currentTimer; + this.currentTimer = MathHelper.clamp(this.currentTimer + 1, 0, 100); + + if (this.world == null || this.world.isRemote) { + return; + } + + ItemStack stack = this.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY).map(e -> e.getStackInSlot(0)).orElse(ItemStack.EMPTY); + if (stack.isEmpty()) { + return; + } + + List animals = this.world.getEntitiesWithinAABB(AnimalEntity.class, new AxisAlignedBB(pos).grow(5)); + this.currentAnimalAmount = animals.size(); + + if (last != this.currentTimer) { + System.out.println(this.currentAnimalAmount); + this.sendTileEntityToClients(); + } + + if (this.currentAnimalAmount < 2 || this.currentAnimalAmount > THRESHOLD || this.currentTimer < TIME) { + return; + } + + for (AnimalEntity animal : animals) { + if (animal.getGrowingAge() != 0 || animal.isInLove() || !animal.isBreedingItem(stack)) { + continue; + } + + animal.setInLove(null); + for (int i = 0; i < 7; i++) { + double d = animal.world.rand.nextGaussian() * 0.02D; + double d1 = animal.world.rand.nextGaussian() * 0.02D; + double d2 = animal.world.rand.nextGaussian() * 0.02D; + animal.world.addParticle(ParticleTypes.HEART, animal.getPosX() + animal.world.rand.nextFloat() * animal.getWidth() * 2.0F - animal.getWidth(), animal.getPosY() + 0.5D + animal.world.rand.nextFloat() * animal.getHealth(), animal.getPosZ() + animal.world.rand.nextFloat() * animal.getWidth() * 2.0F - animal.getWidth(), d, d1, d2); + } + + stack.shrink(1); + this.currentTimer = 0; + this.markDirty(); + this.sendTileEntityToClients(); + + break; + } + } + + public int getCurrentTimerToScale(int i) { + return this.currentTimer * i / TIME; + } + + @Override + public ITextComponent getDisplayName() { + return StringTextComponent.EMPTY; + } + + @Nullable + @Override + public Container createMenu(int windowId, PlayerInventory playerInventory, PlayerEntity playerEntity) { + return new FeederContainer(windowId, playerInventory, this); + } + + @Override + public void read(BlockState state, CompoundNBT nbt) { + super.read(state, nbt); + + this.currentTimer = nbt.getInt("timer"); + this.currentAnimalAmount = nbt.getInt("animals"); + if (nbt.contains("items")) { + itemStackHandler.deserializeNBT(nbt.getCompound("items")); + } + } + + @Override + public CompoundNBT write(CompoundNBT compound) { + compound.put("items", itemStackHandler.serializeNBT()); + compound.putInt("timer", this.currentTimer); + compound.putInt("animals", this.currentAnimalAmount); + return super.write(compound); + } + + @Nonnull + @Override + public LazyOptional getCapability(@Nonnull Capability cap, @Nullable Direction side) { + if (cap == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) { + return handler.cast(); + } + return super.getCapability(cap, side); + } + + @Override + public void remove() { + super.remove(); + handler.invalidate(); + } +} diff --git a/src/main/java/de/ellpeck/actuallyadditions/common/tiles/package-info.java b/src/main/java/de/ellpeck/actuallyadditions/common/tiles/package-info.java new file mode 100644 index 000000000..0c9a07c3a --- /dev/null +++ b/src/main/java/de/ellpeck/actuallyadditions/common/tiles/package-info.java @@ -0,0 +1,7 @@ +@ParametersAreNonnullByDefault +@MethodsReturnNonnullByDefault +package de.ellpeck.actuallyadditions.common.tiles; + +import mcp.MethodsReturnNonnullByDefault; + +import javax.annotation.ParametersAreNonnullByDefault; \ No newline at end of file diff --git a/src/main/java/de/ellpeck/actuallyadditions/data/GeneratorLanguage.java b/src/main/java/de/ellpeck/actuallyadditions/data/GeneratorLanguage.java index 4e6f3895d..3952c03b3 100644 --- a/src/main/java/de/ellpeck/actuallyadditions/data/GeneratorLanguage.java +++ b/src/main/java/de/ellpeck/actuallyadditions/data/GeneratorLanguage.java @@ -341,6 +341,11 @@ public class GeneratorLanguage extends LanguageProvider { // Screen names addPrefixed("gui.name.drill", "Drill"); + addPrefixed("info.gui.animals","%s Animals"); + addPrefixed("info.gui.enoughToBreed","Enough to breed!"); + addPrefixed("info.gui.tooMany","Too many to breed!"); + addPrefixed("info.gui.notEnough","Not enough to breed!"); + // Storage addPrefixed("storage.crystal-flux", "%s/%s Crystal Flux");