diff --git a/modules/base/src/main/java/io/github/fabricators_of_create/porting_lib/block/NeighborChangeListeningBlock.java b/modules/base/src/main/java/io/github/fabricators_of_create/porting_lib/block/NeighborChangeListeningBlock.java index cd8f1b03..83c5aa66 100644 --- a/modules/base/src/main/java/io/github/fabricators_of_create/porting_lib/block/NeighborChangeListeningBlock.java +++ b/modules/base/src/main/java/io/github/fabricators_of_create/porting_lib/block/NeighborChangeListeningBlock.java @@ -5,5 +5,24 @@ import net.minecraft.world.level.block.state.BlockState; public interface NeighborChangeListeningBlock { + + /** + * Used by the neighbouring blocks to notify this block that that neighbour updated + * @param state Block state at position pos + * @param world The world + * @param pos Block position + * @param neighbor Neighbour position + */ void onNeighborChange(BlockState state, LevelReader world, BlockPos pos, BlockPos neighbor); + + /** + * Check if this block should be notified of weak changes.
+ * Weak changes are changes 1 block away through a solid block. Similar to comparators. + * @param level The world + * @param pos Block position + * @return true if there are weak changes to check. False otherwise + */ + default boolean getWeakChanges(BlockState state, LevelReader level, BlockPos pos) { + return false; + } } diff --git a/modules/base/src/main/java/io/github/fabricators_of_create/porting_lib/extensions/ComparatorBlockExtension.java b/modules/base/src/main/java/io/github/fabricators_of_create/porting_lib/extensions/ComparatorBlockExtension.java new file mode 100644 index 00000000..b0ba46b2 --- /dev/null +++ b/modules/base/src/main/java/io/github/fabricators_of_create/porting_lib/extensions/ComparatorBlockExtension.java @@ -0,0 +1,6 @@ +package io.github.fabricators_of_create.porting_lib.extensions; + +import io.github.fabricators_of_create.porting_lib.block.NeighborChangeListeningBlock; + +public interface ComparatorBlockExtension extends NeighborChangeListeningBlock { +} diff --git a/modules/base/src/main/java/io/github/fabricators_of_create/porting_lib/mixin/common/ComparatorBlockMixin.java b/modules/base/src/main/java/io/github/fabricators_of_create/porting_lib/mixin/common/ComparatorBlockMixin.java new file mode 100644 index 00000000..ceefca5e --- /dev/null +++ b/modules/base/src/main/java/io/github/fabricators_of_create/porting_lib/mixin/common/ComparatorBlockMixin.java @@ -0,0 +1,27 @@ +package io.github.fabricators_of_create.porting_lib.mixin.common; + +import io.github.fabricators_of_create.porting_lib.extensions.ComparatorBlockExtension; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelReader; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.ComparatorBlock; + +import net.minecraft.world.level.block.state.BlockState; + +import org.spongepowered.asm.mixin.Mixin; + +@Mixin(ComparatorBlock.class) +public class ComparatorBlockMixin implements ComparatorBlockExtension { + @Override + public void onNeighborChange(BlockState state, LevelReader world, BlockPos pos, BlockPos neighbor) { + if (pos.getY() == neighbor.getY() && world instanceof Level && !world.isClientSide()) { + state.neighborChanged((Level)world, pos, world.getBlockState(neighbor).getBlock(), neighbor, false); + } + } + + @Override + public boolean getWeakChanges(BlockState state, LevelReader level, BlockPos pos) { + return state.is(Blocks.COMPARATOR); + } +} diff --git a/modules/base/src/main/java/io/github/fabricators_of_create/porting_lib/mixin/common/LevelMixin.java b/modules/base/src/main/java/io/github/fabricators_of_create/porting_lib/mixin/common/LevelMixin.java index f693515c..5a1ee202 100644 --- a/modules/base/src/main/java/io/github/fabricators_of_create/porting_lib/mixin/common/LevelMixin.java +++ b/modules/base/src/main/java/io/github/fabricators_of_create/porting_lib/mixin/common/LevelMixin.java @@ -7,25 +7,22 @@ import java.util.LinkedList; import java.util.List; -import com.llamalad7.mixinextras.injector.wrapoperation.Operation; -import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.llamalad7.mixinextras.sugar.Local; -import io.github.fabricators_of_create.porting_lib.block.LightEmissiveBlock; import io.github.fabricators_of_create.porting_lib.core.PortingLib; import io.github.fabricators_of_create.porting_lib.event.common.BlockEvents; import io.github.fabricators_of_create.porting_lib.event.common.ExplosionEvents; import io.github.fabricators_of_create.porting_lib.extensions.extensions.BlockEntityExtensions; import io.github.fabricators_of_create.porting_lib.extensions.extensions.LevelExtensions; import net.fabricmc.fabric.api.transfer.v1.transaction.base.SnapshotParticipant; -import net.minecraft.server.level.ChunkHolder; import net.minecraft.server.level.FullChunkStatus; import net.minecraft.util.profiling.ProfilerFiller; import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.Entity; -import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.Explosion; import net.minecraft.world.level.ExplosionDamageCalculator; +import net.minecraft.world.level.LevelReader; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.chunk.LevelChunk; @@ -43,7 +40,6 @@ import org.spongepowered.asm.mixin.injection.callback.LocalCapture; import io.github.fabricators_of_create.porting_lib.block.NeighborChangeListeningBlock; -import io.github.fabricators_of_create.porting_lib.block.WeakPowerCheckingBlock; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -155,25 +151,45 @@ public SnapshotParticipant snapshotParticipant() { } } - @Inject( - method = "updateNeighbourForOutputSignal", - at = @At( - value = "INVOKE", - target = "Lnet/minecraft/world/level/Level;getBlockState(Lnet/minecraft/core/BlockPos;)Lnet/minecraft/world/level/block/state/BlockState;", - shift = Shift.BY, - by = 2, - ordinal = 0 - ), - locals = LocalCapture.CAPTURE_FAILHARD + /** Force cancel check for comparator and always say it is not. The comparator now implements + * NeighborChangeListeningBlock so code specific for comparators in {@link Level#updateNeighbourForOutputSignal(BlockPos, Block)} + * should be unreachable and instead handled via {@link LevelMixin#port_lib$updateNeighbourForOutputSignal(BlockPos, Block, CallbackInfo, BlockPos, BlockState)} + * and {@link LevelMixin#port_lib$updateNeighbourForOutputSignal2(BlockPos, Block, CallbackInfo, BlockPos, BlockState)} + * which call {@link NeighborChangeListeningBlock#onNeighborChange(BlockState, LevelReader, BlockPos, BlockPos)} + */ + @Redirect(method = "updateNeighbourForOutputSignal", + at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/state/BlockState;is(Lnet/minecraft/world/level/block/Block;)Z") ) - public void port_lib$updateNeighbourForOutputSignal(BlockPos pos, Block block, CallbackInfo ci, - Iterator var3, Direction direction, BlockPos offset, - BlockState state) { + public boolean port_lib$updateNeighbourForOutputSignalCancelCompChk(BlockState instance, Block block) { + return false; + } + + /** Runs on first invocation of {@link Level#getBlockState(BlockPos)} in {@link Level#updateNeighbourForOutputSignal(BlockPos, Block)} + */ + @Inject(method = "updateNeighbourForOutputSignal", + at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;getBlockState(Lnet/minecraft/core/BlockPos;)Lnet/minecraft/world/level/block/state/BlockState;", + shift = Shift.BY, by = 2, ordinal = 0) + ) + public void port_lib$updateNeighbourForOutputSignal(BlockPos pos, Block block, CallbackInfo ci, @Local(ordinal = 1) BlockPos offset, @Local BlockState state) { if (state.getBlock() instanceof NeighborChangeListeningBlock listener) { listener.onNeighborChange(state, this, offset, pos); } } + /** Runs on second invocation of {@link Level#getBlockState(BlockPos)} in {@link Level#updateNeighbourForOutputSignal(BlockPos, Block)} + * (i.e. the one checking for changes through a block. So should only update for weak change listeners only + * (see {@link NeighborChangeListeningBlock#getWeakChanges(BlockState, LevelReader, BlockPos)})) + */ + @Inject(method = "updateNeighbourForOutputSignal", + at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;getBlockState(Lnet/minecraft/core/BlockPos;)Lnet/minecraft/world/level/block/state/BlockState;", + shift = Shift.BY, by = 2, ordinal = 1) + ) + public void port_lib$updateNeighbourForOutputSignal2(BlockPos pos, Block block, CallbackInfo ci, @Local(ordinal = 1) BlockPos offset, @Local BlockState state) { + if (state.getBlock() instanceof NeighborChangeListeningBlock listener && listener.getWeakChanges(state, this, pos)) { + listener.onNeighborChange(state, this, offset, pos); + } + } + @Inject( method = "explode(Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/damagesource/DamageSource;Lnet/minecraft/world/level/ExplosionDamageCalculator;DDDFZLnet/minecraft/world/level/Level$ExplosionInteraction;Z)Lnet/minecraft/world/level/Explosion;", at = @At( diff --git a/modules/base/src/main/resources/fabric.mod.json b/modules/base/src/main/resources/fabric.mod.json index 0838ac7c..f708abe7 100644 --- a/modules/base/src/main/resources/fabric.mod.json +++ b/modules/base/src/main/resources/fabric.mod.json @@ -15,7 +15,8 @@ "custom": { "loom:injected_interfaces": { "net/minecraft/class_3283": ["io/github/fabricators_of_create/porting_lib/extensions/PackRepositoryExtension"], - "net/minecraft/class_2680": ["io/github/fabricators_of_create/porting_lib/extensions/BaseBlockStateExtension"] + "net/minecraft/class_2680": ["io/github/fabricators_of_create/porting_lib/extensions/BaseBlockStateExtension"], + "net/minecraft/class_2286": ["io/github/fabricators_of_create/porting_lib/extensions/ComparatorBlockExtension"] } } } diff --git a/modules/base/src/main/resources/porting_lib_base.mixins.json b/modules/base/src/main/resources/porting_lib_base.mixins.json index 6910643a..73102334 100644 --- a/modules/base/src/main/resources/porting_lib_base.mixins.json +++ b/modules/base/src/main/resources/porting_lib_base.mixins.json @@ -29,6 +29,7 @@ "common.ChunkMapMixin", "common.ChunkStatusMixin", "common.ClipContextMixin", + "common.ComparatorBlockMixin", "common.ConnectionMixin", "common.DeadBushBlockMixin", "common.DiodeBlockMixin", diff --git a/modules/entity/build.gradle b/modules/entity/build.gradle index efb9d82b..3d034ba6 100644 --- a/modules/entity/build.gradle +++ b/modules/entity/build.gradle @@ -1,4 +1,5 @@ portingLib { addModuleDependency("mixin_extensions") + addModuleDependency("fluids") enableTestMod() } diff --git a/modules/entity/src/main/java/io/github/fabricators_of_create/porting_lib/entity/extensions/EntityExtensions.java b/modules/entity/src/main/java/io/github/fabricators_of_create/porting_lib/entity/extensions/EntityExtensions.java index 48c6a0f7..933beccd 100644 --- a/modules/entity/src/main/java/io/github/fabricators_of_create/porting_lib/entity/extensions/EntityExtensions.java +++ b/modules/entity/src/main/java/io/github/fabricators_of_create/porting_lib/entity/extensions/EntityExtensions.java @@ -1,6 +1,8 @@ package io.github.fabricators_of_create.porting_lib.entity.extensions; import io.github.fabricators_of_create.porting_lib.entity.ITeleporter; +import io.github.fabricators_of_create.porting_lib.fluids.FluidType; +import io.github.fabricators_of_create.porting_lib.fluids.PortingLibFluids; import net.minecraft.nbt.CompoundTag; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.Entity; @@ -34,4 +36,12 @@ default boolean canRiderInteract() { default Entity changeDimension(ServerLevel p_20118_, ITeleporter teleporter) { throw new RuntimeException("this should be overridden via mixin. what?"); } + + default FluidType getEyeInFluidType() { + throw new RuntimeException("This should be overridden in the EntityMixin"); + } + + default boolean isEyeInFluidType(FluidType type) { + return type == this.getEyeInFluidType(); + } } diff --git a/modules/entity/src/main/java/io/github/fabricators_of_create/porting_lib/entity/extensions/LivingEntityExtensions.java b/modules/entity/src/main/java/io/github/fabricators_of_create/porting_lib/entity/extensions/LivingEntityExtensions.java new file mode 100644 index 00000000..eb048961 --- /dev/null +++ b/modules/entity/src/main/java/io/github/fabricators_of_create/porting_lib/entity/extensions/LivingEntityExtensions.java @@ -0,0 +1,24 @@ +package io.github.fabricators_of_create.porting_lib.entity.extensions; + +import io.github.fabricators_of_create.porting_lib.fluids.FluidType; +import net.minecraft.world.entity.LivingEntity; + +import io.github.fabricators_of_create.porting_lib.fluids.PortingLibFluids; + +public interface LivingEntityExtensions { + default LivingEntity self() { + return (LivingEntity) this; + } + + /** + * Returns whether the entity can drown in the fluid. + * + * @param type the type of the fluid + * @return {@code true} if the entity can drown in the fluid, {@code false} otherwise + */ + default boolean canDrownInFluidType(FluidType type) { + if (type == PortingLibFluids.WATER_TYPE) return !self().canBreatheUnderwater(); + return type.canDrownIn(self()); + } +} + diff --git a/modules/entity/src/main/java/io/github/fabricators_of_create/porting_lib/entity/mixin/common/EntityMixin.java b/modules/entity/src/main/java/io/github/fabricators_of_create/porting_lib/entity/mixin/common/EntityMixin.java index 14a9e013..d378571b 100644 --- a/modules/entity/src/main/java/io/github/fabricators_of_create/porting_lib/entity/mixin/common/EntityMixin.java +++ b/modules/entity/src/main/java/io/github/fabricators_of_create/porting_lib/entity/mixin/common/EntityMixin.java @@ -2,6 +2,13 @@ import java.util.Collection; +import io.github.fabricators_of_create.porting_lib.fluids.FluidType; +import io.github.fabricators_of_create.porting_lib.fluids.PortingLibFluids; +import net.minecraft.core.BlockPos; +import net.minecraft.tags.FluidTags; +import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.level.material.FluidState; + import org.jetbrains.annotations.Nullable; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -41,6 +48,8 @@ import net.minecraft.world.level.Level; import net.minecraft.world.level.portal.PortalInfo; +import org.spongepowered.asm.mixin.injection.callback.LocalCapture; + @Mixin(Entity.class) public abstract class EntityMixin implements EntityExtensions { @Unique @@ -124,6 +133,9 @@ public Collection captureDrops(Collection value) { @Shadow private Level level; + @Shadow + protected boolean wasEyeInWater; + @Shadow public abstract void unRide(); @@ -158,6 +170,24 @@ public Collection captureDrops(Collection value) { @Shadow public abstract float getEyeHeight(); + @Shadow + public abstract double getX(); + + @Shadow + public abstract double getY(); + + @Shadow + public abstract double getZ(); + + @Shadow + public abstract double getEyeY(); + + @Shadow + public abstract Entity getVehicle(); + + @Shadow + public abstract Level level(); + @Inject( method = "startRiding(Lnet/minecraft/world/entity/Entity;Z)Z", at = @At( @@ -275,4 +305,22 @@ public void afterSave(CompoundTag nbt, CallbackInfoReturnable cir) public void afterLoad(CompoundTag nbt, CallbackInfo ci) { EntityDataEvents.LOAD.invoker().onLoad((Entity) (Object) this, nbt); } + + @Unique + private FluidType fluidTypeOnEyes = PortingLibFluids.EMPTY_TYPE; + + @Inject(method = "updateFluidOnEyes", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/material/FluidState;getTags()Ljava/util/stream/Stream;")) + private void updateFluidOnEyesSetFluidTypeOnEyes(CallbackInfo ci, @Local FluidState fluidState) { + this.fluidTypeOnEyes = fluidState.getFluidType(); + } + + @Inject(method = "updateFluidOnEyes", at = @At("HEAD")) + private void updateFluidOnEyesResetFluidTypeOnEyes(CallbackInfo ci) { + this.fluidTypeOnEyes = PortingLibFluids.EMPTY_TYPE; + } + + @Override + public FluidType getEyeInFluidType() { + return this.fluidTypeOnEyes; + } } diff --git a/modules/entity/src/main/java/io/github/fabricators_of_create/porting_lib/entity/mixin/common/LivingEntityMixin.java b/modules/entity/src/main/java/io/github/fabricators_of_create/porting_lib/entity/mixin/common/LivingEntityMixin.java index 6c3ad5b2..5f79ec49 100644 --- a/modules/entity/src/main/java/io/github/fabricators_of_create/porting_lib/entity/mixin/common/LivingEntityMixin.java +++ b/modules/entity/src/main/java/io/github/fabricators_of_create/porting_lib/entity/mixin/common/LivingEntityMixin.java @@ -21,6 +21,7 @@ import io.github.fabricators_of_create.porting_lib.entity.events.living.LivingHurtEvent; import io.github.fabricators_of_create.porting_lib.entity.events.living.MobEffectEvent; +import io.github.fabricators_of_create.porting_lib.entity.extensions.LivingEntityExtensions; import net.minecraft.world.effect.MobEffect; import net.minecraft.world.effect.MobEffectInstance; @@ -57,7 +58,7 @@ import net.minecraft.world.level.Level; @Mixin(LivingEntity.class) -public abstract class LivingEntityMixin extends Entity implements EntityExtensions { +public abstract class LivingEntityMixin extends Entity implements LivingEntityExtensions { @Shadow protected int lastHurtByPlayerTime; @Shadow diff --git a/modules/entity/src/main/resources/fabric.mod.json b/modules/entity/src/main/resources/fabric.mod.json index a425bca1..8a790e64 100644 --- a/modules/entity/src/main/resources/fabric.mod.json +++ b/modules/entity/src/main/resources/fabric.mod.json @@ -20,7 +20,8 @@ "net/minecraft/class_1657": ["io/github/fabricators_of_create/porting_lib/entity/extensions/PlayerExtension"], "net/minecraft/class_1688": ["io/github/fabricators_of_create/porting_lib/entity/extensions/AbstractMinecartExtensions"], "net/minecraft/class_1792": ["io/github/fabricators_of_create/porting_lib/entity/extensions/ItemExtensions"], - "net/minecraft/class_1937": ["io/github/fabricators_of_create/porting_lib/entity/extensions/LevelExtensions"] + "net/minecraft/class_1937": ["io/github/fabricators_of_create/porting_lib/entity/extensions/LevelExtensions"], + "net/minecraft/class_1309": ["io/github/fabricators_of_create/porting_lib/entity/extensions/LivingEntityExtensions"] } } }