diff --git a/src/main/java/io/wispforest/affinity/block/impl/SunshineMonolithBlock.java b/src/main/java/io/wispforest/affinity/block/impl/SunshineMonolithBlock.java index 3831b471..09071905 100644 --- a/src/main/java/io/wispforest/affinity/block/impl/SunshineMonolithBlock.java +++ b/src/main/java/io/wispforest/affinity/block/impl/SunshineMonolithBlock.java @@ -5,15 +5,13 @@ import io.wispforest.affinity.blockentity.template.TickedBlockEntity; import io.wispforest.affinity.object.AffinityBlocks; import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; -import net.minecraft.block.Block; -import net.minecraft.block.BlockState; -import net.minecraft.block.Blocks; -import net.minecraft.block.ShapeContext; +import net.minecraft.block.*; import net.minecraft.block.entity.BlockEntity; import net.minecraft.block.entity.BlockEntityTicker; import net.minecraft.block.entity.BlockEntityType; import net.minecraft.block.enums.DoubleBlockHalf; import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.ItemPlacementContext; import net.minecraft.item.ItemStack; import net.minecraft.state.StateManager; @@ -33,6 +31,7 @@ public class SunshineMonolithBlock extends AethumNetworkMemberBlock { public static final BooleanProperty ENABLED = Properties.ENABLED; + public static final BooleanProperty POWERED = Properties.POWERED; public static final EnumProperty HALF = Properties.DOUBLE_BLOCK_HALF; public static final VoxelShape LOWER_SHAPE = VoxelShapes.union( @@ -43,8 +42,25 @@ public class SunshineMonolithBlock extends AethumNetworkMemberBlock { public static final VoxelShape UPPER_SHAPE = Block.createCuboidShape(2, 0, 2, 14, 16, 14); public SunshineMonolithBlock() { - super(FabricBlockSettings.copyOf(Blocks.SMOOTH_STONE), CONSUMER_TOOLTIP); - this.setDefaultState(this.getDefaultState().with(Properties.ENABLED, false).with(HALF, DoubleBlockHalf.LOWER)); + super(Settings.copy(Blocks.SMOOTH_STONE), CONSUMER_TOOLTIP); + this.setDefaultState(this.getDefaultState().with(ENABLED, false).with(HALF, DoubleBlockHalf.LOWER).with(POWERED, false)); + } + + @Override + protected void neighborUpdate(BlockState state, World world, BlockPos pos, Block sourceBlock, BlockPos sourcePos, boolean notify) { + var otherHalfPos = pos.offset(state.get(HALF) == DoubleBlockHalf.LOWER ? Direction.UP : Direction.DOWN); + var powered = world.isReceivingRedstonePower(pos) | world.isReceivingRedstonePower(otherHalfPos); + + if (state.get(POWERED) != powered) { + world.setBlockState(pos, state.with(POWERED, powered), 2); + + var otherState = world.getBlockState(otherHalfPos); + if (otherState.isOf(this) && otherState.get(POWERED) != powered) { + world.setBlockState(otherHalfPos, otherState.with(POWERED, powered)); + } + } + + super.neighborUpdate(state, world, pos, sourceBlock, sourcePos, notify); } @Override @@ -75,9 +91,10 @@ public BlockState getStateForNeighborUpdate(BlockState state, Direction directio public BlockState getPlacementState(ItemPlacementContext context) { var pos = context.getBlockPos(); var world = context.getWorld(); + var powered = world.isReceivingRedstonePower(pos); return pos.getY() < world.getTopY() - 1 && world.getBlockState(pos.up()).canReplace(context) - ? super.getPlacementState(context) + ? super.getPlacementState(context).with(POWERED, powered) : null; } @@ -94,6 +111,17 @@ public boolean canPlaceAt(BlockState state, WorldView world, BlockPos pos) { return downState.isOf(this) && downState.get(HALF) == DoubleBlockHalf.LOWER; } + @Override + public BlockState onBreak(World world, BlockPos pos, BlockState state, PlayerEntity player) { + // This is how vanilla doors handle preventing unwanted drops + if (!world.isClient && (player.isCreative() || !player.canHarvest(state))) { + TallPlantBlock.onBreakInCreative(world, pos, state, player); + } + + return super.onBreak(world, pos, state, player); + } + + @Override public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) { return state.get(HALF) == DoubleBlockHalf.LOWER ? LOWER_SHAPE : UPPER_SHAPE; @@ -101,7 +129,7 @@ public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos po @Override protected void appendProperties(StateManager.Builder builder) { - builder.add(Properties.ENABLED).add(HALF); + builder.add(ENABLED).add(HALF).add(POWERED); } @Nullable diff --git a/src/main/java/io/wispforest/affinity/blockentity/impl/SunshineMonolithBlockEntity.java b/src/main/java/io/wispforest/affinity/blockentity/impl/SunshineMonolithBlockEntity.java index 9b356157..ed6ecf91 100644 --- a/src/main/java/io/wispforest/affinity/blockentity/impl/SunshineMonolithBlockEntity.java +++ b/src/main/java/io/wispforest/affinity/blockentity/impl/SunshineMonolithBlockEntity.java @@ -1,14 +1,21 @@ package io.wispforest.affinity.blockentity.impl; +import io.wispforest.affinity.aethumflux.net.AethumNetworkMember; +import io.wispforest.affinity.aethumflux.net.MultiblockAethumNetworkMember; import io.wispforest.affinity.block.impl.SunshineMonolithBlock; import io.wispforest.affinity.blockentity.template.AethumNetworkMemberBlockEntity; import io.wispforest.affinity.blockentity.template.TickedBlockEntity; import io.wispforest.affinity.component.AffinityComponents; import io.wispforest.affinity.object.AffinityBlocks; import net.minecraft.block.BlockState; +import net.minecraft.state.property.Properties; +import net.minecraft.text.Text; import net.minecraft.util.math.BlockPos; -public class SunshineMonolithBlockEntity extends AethumNetworkMemberBlockEntity implements TickedBlockEntity { +import java.util.Collection; +import java.util.List; + +public class SunshineMonolithBlockEntity extends AethumNetworkMemberBlockEntity implements TickedBlockEntity, MultiblockAethumNetworkMember { public SunshineMonolithBlockEntity(BlockPos pos, BlockState state) { super(AffinityBlocks.Entities.SUNSHINE_MONOLITH, pos, state); @@ -19,7 +26,7 @@ public SunshineMonolithBlockEntity(BlockPos pos, BlockState state) { @Override public void tickServer() { long flux = flux(); - boolean shouldBeEnabled = flux >= 1; + boolean shouldBeEnabled = flux >= 1 && !this.getCachedState().get(SunshineMonolithBlock.POWERED); if (shouldBeEnabled != this.getCachedState().get(SunshineMonolithBlock.ENABLED)) { this.world.setBlockState(this.pos, this.getCachedState().with(SunshineMonolithBlock.ENABLED, shouldBeEnabled)); @@ -66,4 +73,28 @@ private void removeMonolithFromChunks() { } } } + + @Override + public void appendTooltipEntries(List entries) { + super.appendTooltipEntries(entries); + + if (getCachedState().get(Properties.POWERED)) { + entries.add(Entry.icon(Text.translatable("text.affinity.tooltip.disabled_by_redstone"), 24, 8)); + } + } + + @Override + public Collection memberBlocks() { + return List.of(this.getPos(), this.getPos().up()); + } + + @Override + public boolean isParent() { + return true; + } + + @Override + public AethumNetworkMember parent() { + return this; + } } diff --git a/src/main/java/io/wispforest/affinity/mixin/ServerWorldMixin.java b/src/main/java/io/wispforest/affinity/mixin/ServerWorldMixin.java index 98ead23b..cd69e3c8 100644 --- a/src/main/java/io/wispforest/affinity/mixin/ServerWorldMixin.java +++ b/src/main/java/io/wispforest/affinity/mixin/ServerWorldMixin.java @@ -1,6 +1,8 @@ package io.wispforest.affinity.mixin; import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import com.llamalad7.mixinextras.sugar.Local; import io.wispforest.affinity.Affinity; import io.wispforest.affinity.component.AffinityComponents; @@ -93,4 +95,17 @@ private BlockPos makeSunshineMonolithsStopThunder(BlockPos pos) { return pos; } + + // tickIceAndSnow doesn't use the position-aware hasRain call hooked in WorldMixin + // Ice is still permitted to form, only precipitation is blocked + @WrapOperation(method = "tickIceAndSnow", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/world/ServerWorld;isRaining()Z")) + private boolean makeSunshineMonolithPreventSnow(ServerWorld instance, Operation original, BlockPos pos) { + var chunk = getWorldChunk(pos); + if (chunk instanceof EmptyChunk) { + return original.call(instance); + } + + var component = chunk.getComponent(AffinityComponents.LOCAL_WEATHER); + return component.getRainGradient() > 0.2; + } } diff --git a/src/main/resources/affinity.accesswidener b/src/main/resources/affinity.accesswidener index 2e9fca7b..886ae23a 100644 --- a/src/main/resources/affinity.accesswidener +++ b/src/main/resources/affinity.accesswidener @@ -32,4 +32,6 @@ accessible field net/minecraft/block/CandleBlock CANDLES_TO_PARTICLE_OFFSETS Lit accessible class net/minecraft/server/world/ServerChunkLoadingManager$TicketManager -accessible class net/minecraft/datafixer/fix/ItemStackComponentizationFix$StackData \ No newline at end of file +accessible class net/minecraft/datafixer/fix/ItemStackComponentizationFix$StackData + +accessible method net/minecraft/block/TallPlantBlock onBreakInCreative (Lnet/minecraft/world/World;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/BlockState;Lnet/minecraft/entity/player/PlayerEntity;)V \ No newline at end of file diff --git a/src/main/resources/assets/affinity/lang/en_us.json b/src/main/resources/assets/affinity/lang/en_us.json index 33030713..4df0a5c5 100644 --- a/src/main/resources/assets/affinity/lang/en_us.json +++ b/src/main/resources/assets/affinity/lang/en_us.json @@ -798,6 +798,7 @@ "text.affinity.tooltip.aethum_storage": "Flux: %d/%d", "text.affinity.tooltip.creative_flux_cache_flux_level": "All of it, really", + "text.affinity.tooltip.disabled_by_redstone": "Disabled by redstone", "death.attack.asteroid": "%s was expunged by an Asteroid", "death.attack.asteroid.player": "%s was expunged by %s's Asteroid", diff --git a/src/main/resources/assets/affinity/textures/gui/tooltip_icons.png b/src/main/resources/assets/affinity/textures/gui/tooltip_icons.png index f936befa..90dd79af 100644 Binary files a/src/main/resources/assets/affinity/textures/gui/tooltip_icons.png and b/src/main/resources/assets/affinity/textures/gui/tooltip_icons.png differ