diff --git a/game/client/src/main/resources/assets/minecraft/models/block/piston_sticky/head.json b/game/client/src/main/resources/assets/minecraft/models/block/piston_sticky/head.json index f93b104ad..123f7756c 100644 --- a/game/client/src/main/resources/assets/minecraft/models/block/piston_sticky/head.json +++ b/game/client/src/main/resources/assets/minecraft/models/block/piston_sticky/head.json @@ -4,7 +4,7 @@ "textures": { "face": "block/piston_sticky/face", "back": "block/piston/face", - "head": "block/piston/head", + "head": "block/piston_sticky/head", "shaft": "block/piston/shaft", "overlay": "#face", "particle_up": "#head", diff --git a/game/client/src/main/resources/assets/minecraft/models/block/piston_sticky/head_half.json b/game/client/src/main/resources/assets/minecraft/models/block/piston_sticky/head_half.json index c7a3c402c..d37ae4c46 100644 --- a/game/client/src/main/resources/assets/minecraft/models/block/piston_sticky/head_half.json +++ b/game/client/src/main/resources/assets/minecraft/models/block/piston_sticky/head_half.json @@ -4,7 +4,7 @@ "textures": { "face": "block/piston_sticky/face", "back": "block/piston/face", - "head": "block/piston/head", + "head": "block/piston_sticky/head", "shaft": "block/piston/shaft", "overlay": "#face", "particle_up": "#head", diff --git a/game/client/src/main/resources/assets/minecraft/models/block/piston_sticky/head_short.json b/game/client/src/main/resources/assets/minecraft/models/block/piston_sticky/head_short.json index 5c43f0a00..bcb6ee0a7 100644 --- a/game/client/src/main/resources/assets/minecraft/models/block/piston_sticky/head_short.json +++ b/game/client/src/main/resources/assets/minecraft/models/block/piston_sticky/head_short.json @@ -4,7 +4,7 @@ "textures": { "face": "block/piston_sticky/face", "back": "block/piston/face", - "head": "block/piston/head", + "head": "block/piston_sticky/head", "shaft": "block/piston/shaft", "shaft_end": "block/piston/shaft_end", "overlay": "#face", diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/piston_sticky/head.png b/game/client/src/main/resources/assets/minecraft/textures/block/piston_sticky/head.png new file mode 100644 index 000000000..503c84138 Binary files /dev/null and b/game/client/src/main/resources/assets/minecraft/textures/block/piston_sticky/head.png differ diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/piston_sticky/side.png b/game/client/src/main/resources/assets/minecraft/textures/block/piston_sticky/side.png index f0778e711..cdc7573a2 100644 Binary files a/game/client/src/main/resources/assets/minecraft/textures/block/piston_sticky/side.png and b/game/client/src/main/resources/assets/minecraft/textures/block/piston_sticky/side.png differ diff --git a/game/core/src/main/java/net/minecraft/core/block/Block.java b/game/core/src/main/java/net/minecraft/core/block/Block.java index d983689be..eacadee31 100644 --- a/game/core/src/main/java/net/minecraft/core/block/Block.java +++ b/game/core/src/main/java/net/minecraft/core/block/Block.java @@ -5,6 +5,9 @@ import net.minecraft.core.block.entity.TileEntity; import net.minecraft.core.block.entity.TileEntityActivator; import net.minecraft.core.block.material.Material; import net.minecraft.core.block.material.MaterialColor; +import net.minecraft.core.block.motion.CarriedBlock; +import net.minecraft.core.block.piston.IMovingBlock; +import net.minecraft.core.block.piston.MovingLine; import net.minecraft.core.block.support.ISupport; import net.minecraft.core.data.tag.ITaggable; import net.minecraft.core.data.tag.Tag; @@ -563,6 +566,26 @@ public final class Block return this.logic.getPlacedData(player, itemStack, world, tilePos, side, xHit, yHit); } + @Override + public void onMoved(@NotNull World world, @NotNull TilePosc sourcePos, @NotNull TilePosc targetPos, @NotNull IMovingBlock block, int indexInLine, @NotNull MovingLine line) { + this.logic.onMoved(world, sourcePos, targetPos, block, indexInLine, line); + } + + @Override + public void onMovingNeighborChanged(@NotNull World world, @NotNull TilePosc targetPos, @NotNull IMovingBlock block, int indexInLine, @NotNull MovingLine line, @NotNull Block source) { + this.logic.onMovingNeighborChanged(world, targetPos, block, indexInLine, line, source); + } + + @Override + public void onMoveComplete(@NotNull World world, @NotNull TilePosc tilePos) { + this.logic.onMoveComplete(world, tilePos); + } + + @Override + public void onFlung(@NotNull World world, @NotNull TilePosc sourcePos, int data, @NotNull CarriedBlock block) { + this.logic.onFlung(world, sourcePos, data, block); + } + @Override public boolean isClimbable(final @NotNull World world, final @NotNull TilePosc tilePos) { return this.logic.isClimbable(world, tilePos); diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockInterface.java b/game/core/src/main/java/net/minecraft/core/block/BlockInterface.java index 1025fba80..b7e321b4a 100644 --- a/game/core/src/main/java/net/minecraft/core/block/BlockInterface.java +++ b/game/core/src/main/java/net/minecraft/core/block/BlockInterface.java @@ -2,6 +2,9 @@ package net.minecraft.core.block; import net.minecraft.core.block.entity.TileEntity; import net.minecraft.core.block.entity.TileEntityActivator; +import net.minecraft.core.block.motion.CarriedBlock; +import net.minecraft.core.block.piston.IMovingBlock; +import net.minecraft.core.block.piston.MovingLine; import net.minecraft.core.block.support.ISupport; import net.minecraft.core.entity.Entity; import net.minecraft.core.entity.EntityFallingBlock; @@ -167,6 +170,12 @@ interface BlockInterface { void onRemoved(final @NotNull World world, final @NotNull TilePosc tilePos, final int data); + void onMoved(@NotNull World world, @NotNull TilePosc sourcePos, @NotNull TilePosc targetPos, @NotNull IMovingBlock block, int indexInLine, @NotNull MovingLine line); + void onMovingNeighborChanged(@NotNull World world, @NotNull TilePosc targetPos, @NotNull IMovingBlock block, int indexInLine, @NotNull MovingLine line, @NotNull Block source); + void onMoveComplete(final @NotNull World world, final @NotNull TilePosc tilePos); + + void onFlung(@NotNull World world, @NotNull TilePosc sourcePos, int data, @NotNull CarriedBlock block); + /** * Always called when a block is removed by setBlock */ diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLogic.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogic.java index 62b5b9bcf..b4b393752 100644 --- a/game/core/src/main/java/net/minecraft/core/block/BlockLogic.java +++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogic.java @@ -5,12 +5,17 @@ import net.minecraft.core.block.entity.TileEntity; import net.minecraft.core.block.entity.TileEntityActivator; import net.minecraft.core.block.material.Material; import net.minecraft.core.block.material.MaterialColor; +import net.minecraft.core.block.motion.CarriedBlock; +import net.minecraft.core.block.piston.CarriedPistonHead; +import net.minecraft.core.block.piston.IMovingBlock; +import net.minecraft.core.block.piston.MovingLine; import net.minecraft.core.block.support.FullSupport; import net.minecraft.core.block.support.ISupport; import net.minecraft.core.block.tag.BlockTags; import net.minecraft.core.entity.Entity; import net.minecraft.core.entity.EntityItem; import net.minecraft.core.entity.Mob; +import net.minecraft.core.entity.monster.MobHuman; import net.minecraft.core.entity.player.Player; import net.minecraft.core.enums.EnumDropCause; import net.minecraft.core.item.IItemConvertible; @@ -18,6 +23,7 @@ import net.minecraft.core.item.Item; import net.minecraft.core.item.ItemStack; import net.minecraft.core.item.tool.ItemToolShears; import net.minecraft.core.util.collection.NamespaceID; +import net.minecraft.core.util.helper.DamageType; import net.minecraft.core.util.helper.Direction; import net.minecraft.core.util.helper.MathHelper; import net.minecraft.core.util.helper.Side; @@ -211,6 +217,20 @@ public class BlockLogic implements BlockInterface, IItemConvertible { } } + @Override + public void onMoved(@NotNull World world, @NotNull TilePosc sourcePos, @NotNull TilePosc targetPos, @NotNull IMovingBlock block, int indexInLine, @NotNull MovingLine line) {} + + @Override + public void onMovingNeighborChanged(@NotNull World world, @NotNull TilePosc targetPos, @NotNull IMovingBlock block, int indexInLine, @NotNull MovingLine line, @NotNull Block source) {} + + // this is currently asymmetrical to onMoved, as part of the line might not have being converted to normal blocks + // TODO: revisit with better abstraction in the future + @Override + public void onMoveComplete(@NotNull World world, @NotNull TilePosc tilePos) {} + + @Override + public void onFlung(@NotNull World world, @NotNull TilePosc sourcePos, int data, @NotNull CarriedBlock block) { } + @Override public void onPlacedByMob(final @NotNull World world, final @NotNull TilePosc tilePos, final @NotNull Side side, final @NotNull Mob mob, final double xHit, final double yHit) { this.onPlacedOnSide(world, tilePos, side, xHit, yHit); diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLogicActivator.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicActivator.java index 20dea1629..6999b675c 100644 --- a/game/core/src/main/java/net/minecraft/core/block/BlockLogicActivator.java +++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicActivator.java @@ -2,6 +2,9 @@ package net.minecraft.core.block; import net.minecraft.core.block.entity.TileEntityActivator; import net.minecraft.core.block.material.Materials; +import net.minecraft.core.block.motion.CarriedBlock; +import net.minecraft.core.block.piston.IMovingBlock; +import net.minecraft.core.block.piston.MovingLine; import net.minecraft.core.entity.player.Player; import net.minecraft.core.item.Item; import net.minecraft.core.item.ItemStack; @@ -74,17 +77,76 @@ public class BlockLogicActivator } } + @Override + public void onPlacedByWorld(@NotNull World world, @NotNull TilePosc tilePos) { + final int meta = world.getBlockData(tilePos); + final boolean hasSignal = this.getNeighborSignal(world, tilePos, BlockLogicRotatable.getDirectionFromMeta(meta)); + final boolean isPowered = (meta & MASK_POWERED) != 0; + if (hasSignal == isPowered) return; + + world.setBlockData(tilePos, meta ^ MASK_POWERED); + if (hasSignal) { + world.scheduleBlockUpdate(tilePos, this.block, this.tickDelay()); + } + } + @Override public void onNeighborChanged(final @NotNull World world, final @NotNull TilePosc tilePos, final @NotNull Block block) { final int meta = world.getBlockData(tilePos); final boolean hasSignal = this.getNeighborSignal(world, tilePos, BlockLogicRotatable.getDirectionFromMeta(meta)); final boolean isPowered = (meta & MASK_POWERED) != 0; + if (hasSignal == isPowered) return; + + world.setBlockDataNotify(tilePos, meta ^ MASK_POWERED); + if (hasSignal) { + world.scheduleBlockUpdate(tilePos, this.block, this.tickDelay()); + } + } + + @Override + public void onFlung(@NotNull World world, @NotNull TilePosc sourcePos, int data, @NotNull CarriedBlock block) { + block.metadata &= ~MASK_POWERED; + } + + @Override + public void onMoved(@NotNull World world, @NotNull TilePosc sourcePos, @NotNull TilePosc targetPos, @NotNull IMovingBlock block, int indexInLine, @NotNull MovingLine line) { + final int meta = block.getBlockData(); + final boolean hasSignal = line.hasNeighborSignal(indexInLine); + final boolean isPowered = (meta & MASK_POWERED) != 0; + if (hasSignal == isPowered) return; + + block.setBlockData(meta ^ MASK_POWERED); + line.notifyBlocksOfNeighborChange(indexInLine, this.block); + if (hasSignal) { + world.scheduleBlockUpdate(targetPos, this.block, this.tickDelay()); + } + } + + @Override + public void onMovingNeighborChanged(@NotNull World world, @NotNull TilePosc targetPos, @NotNull IMovingBlock block, int indexInLine, @NotNull MovingLine line, @NotNull Block source) { + final int meta = block.getBlockData(); + final boolean hasSignal = line.hasNeighborSignal(indexInLine); + final boolean isPowered = (meta & MASK_POWERED) != 0; + if (hasSignal == isPowered) return; + + block.setBlockData(meta ^ MASK_POWERED); + line.notifyBlocksOfNeighborChange(indexInLine, this.block); + if (hasSignal) { + world.scheduleBlockUpdate(targetPos, this.block, this.tickDelay()); + } + } + + @Override + public void onMoveComplete(@NotNull World world, @NotNull TilePosc tilePos) { + final int meta = world.getBlockData(tilePos); + final boolean isPowered = (meta & MASK_POWERED) != 0; + final boolean hasSignal = this.getNeighborSignal(world, tilePos, BlockLogicRotatable.getDirectionFromMeta(meta)); + + if (hasSignal == isPowered) return; - if (hasSignal && !isPowered) { + world.setBlockDataNotify(tilePos, meta ^ MASK_POWERED); + if (hasSignal) { world.scheduleBlockUpdate(tilePos, this.block, this.tickDelay()); - world.setBlockDataNotify(tilePos, meta | MASK_POWERED); - } else if (!hasSignal && isPowered) { - world.setBlockDataNotify(tilePos, meta & ~MASK_POWERED); } } diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLogicBasket.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicBasket.java index 0dfcb1aae..a911205ad 100644 --- a/game/core/src/main/java/net/minecraft/core/block/BlockLogicBasket.java +++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicBasket.java @@ -4,6 +4,9 @@ import net.minecraft.core.block.entity.TileEntityActivator; import net.minecraft.core.block.entity.TileEntity; import net.minecraft.core.block.entity.TileEntityBasket; import net.minecraft.core.block.material.Material; +import net.minecraft.core.block.motion.CarriedBlock; +import net.minecraft.core.block.piston.IMovingBlock; +import net.minecraft.core.block.piston.MovingLine; import net.minecraft.core.block.support.FullSupport; import net.minecraft.core.block.support.ISupport; import net.minecraft.core.block.support.PartialSupport; @@ -101,10 +104,34 @@ public class BlockLogicBasket extends BlockLogic { // world.notifyBlocksInRadiusOfNeighborChange(2, tilePos, this.block); } + @Override + public void onMoved(@NotNull World world, @NotNull TilePosc sourcePos, @NotNull TilePosc targetPos, @NotNull IMovingBlock block, int indexInLine, @NotNull MovingLine line) { + if (!(block.getTileEntity() instanceof TileEntityBasket basket)) return; + if (basket.getNumUnitsInside() >= basket.getMaxUnits()) { + world.notifyShellBlocksInRadiusOfNeighborChange(2, sourcePos, Blocks.AIR); + } + } + + @Override + public void onFlung(@NotNull World world, @NotNull TilePosc sourcePos, int data, @NotNull CarriedBlock block) { + if (!(block.entity instanceof TileEntityBasket basket)) return; + if (basket.getNumUnitsInside() >= basket.getMaxUnits()) { + world.notifyShellBlocksInRadiusOfNeighborChange(2, sourcePos, Blocks.AIR); + } + } + + @Override + public void onMoveComplete(@NotNull World world, @NotNull TilePosc tilePos) { + if (!(world.getTileEntity(tilePos) instanceof TileEntityBasket basket)) return; + if (basket.getNumUnitsInside() >= basket.getMaxUnits()) { + world.notifyShellBlocksInRadiusOfNeighborChange(2, tilePos, Blocks.AIR); + } + } + @Override public boolean isEmittingSignal(final @NotNull WorldSource source, final @NotNull TilePosc tilePos, final @NotNull Side side) { - final @NotNull TileEntityBasket tileEntity = (TileEntityBasket) Objects.requireNonNull(source.getTileEntity(tilePos)); - return tileEntity.getNumUnitsInside() >= tileEntity.getMaxUnits(); + if (!(source.getTileEntity(tilePos) instanceof TileEntityBasket basket)) return false; + return basket.getNumUnitsInside() >= basket.getMaxUnits(); } @Override diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLogicBedrock.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicBedrock.java index 166dc3ba5..f436e5c64 100644 --- a/game/core/src/main/java/net/minecraft/core/block/BlockLogicBedrock.java +++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicBedrock.java @@ -1,6 +1,10 @@ package net.minecraft.core.block; import net.minecraft.core.block.material.Material; +import net.minecraft.core.block.piston.IMovingBlock; +import net.minecraft.core.block.piston.MovingLine; +import net.minecraft.core.entity.monster.MobHuman; +import net.minecraft.core.util.helper.DamageType; import net.minecraft.core.util.helper.Direction; import net.minecraft.core.util.helper.DyeColor; import net.minecraft.core.world.World; @@ -20,4 +24,14 @@ public class BlockLogicBedrock Blocks.PORTAL_DRIFT.getLogic().tryToCreatePortal(world, tilePos, DyeColor.SILVER); } } + + @Override + public void onMoved(@NotNull World world, @NotNull TilePosc sourcePos, @NotNull TilePosc targetPos, @NotNull IMovingBlock block, int indexInLine, @NotNull MovingLine line) { + final var thisguy = new MobHuman(world); + thisguy.setNickname("kirisoup"); + thisguy.setPos(targetPos.x(), targetPos.y(), targetPos.z()); + world.entityJoinedWorld(thisguy); + final var thatguy = world.getClosestPlayerToEntity(thisguy, 16D); + if (thatguy != null) thisguy.hurt(thatguy, 1, DamageType.GENERIC); + } } diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLogicConduit.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicConduit.java index adad84a0d..ac1c40dad 100644 --- a/game/core/src/main/java/net/minecraft/core/block/BlockLogicConduit.java +++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicConduit.java @@ -108,6 +108,7 @@ public class BlockLogicConduit extends BlockLogic { } } + // TODO: onMoved and onFlung /** * Defines the placement and routing behavior of the conduit when placed into the world by an entity. diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLogicDispenser.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicDispenser.java index 47ef77a98..e94c41206 100644 --- a/game/core/src/main/java/net/minecraft/core/block/BlockLogicDispenser.java +++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicDispenser.java @@ -5,6 +5,9 @@ import java.util.Random; import net.minecraft.core.block.entity.TileEntityDispenser; import net.minecraft.core.block.material.Materials; +import net.minecraft.core.block.motion.CarriedBlock; +import net.minecraft.core.block.piston.IMovingBlock; +import net.minecraft.core.block.piston.MovingLine; import net.minecraft.core.entity.*; import net.minecraft.core.entity.player.Player; import net.minecraft.core.entity.projectile.*; @@ -106,16 +109,45 @@ public class BlockLogicDispenser extends BlockLogicVeryRotatable { @Override public void onNeighborChanged(final @NotNull World world, final @NotNull TilePosc tilePos, final @NotNull Block block) { - final boolean hasNeighborSignal = world.hasNeighborSignal(tilePos); final int data = world.getBlockData(tilePos); - if (hasNeighborSignal && (data & MASK_POWERED) == 0) { + final boolean hasSignal = world.hasNeighborSignal(tilePos); + final boolean isPowered = (data & MASK_POWERED) != 0; + if (hasSignal == isPowered) return; + world.setBlockData(tilePos, data ^ MASK_POWERED); + if (hasSignal) { world.scheduleBlockUpdate(tilePos, this.block, this.tickDelay()); - world.setBlockData(tilePos, data | MASK_POWERED); - } else if (!hasNeighborSignal) { - world.setBlockData(tilePos, data & ~MASK_POWERED); } } + @Override + public void onMoved(@NotNull World world, @NotNull TilePosc sourcePos, @NotNull TilePosc targetPos, @NotNull IMovingBlock block, int indexInLine, @NotNull MovingLine line) { + final int data = block.getBlockData(); + final boolean hasSignal = line.hasNeighborSignal(indexInLine); + final boolean isPowered = (data & MASK_POWERED) != 0; + if (hasSignal == isPowered) return; + block.setBlockData(data ^ MASK_POWERED); + if (hasSignal) { + world.scheduleBlockUpdate(targetPos, this.block, this.tickDelay()); + } + } + + @Override + public void onMoveComplete(@NotNull World world, @NotNull TilePosc tilePos) { + final int data = world.getBlockData(tilePos); + final boolean hasSignal = world.hasNeighborSignal(tilePos); + final boolean isPowered = (data & MASK_POWERED) != 0; + if (hasSignal == isPowered) return; + world.setBlockData(tilePos, data ^ MASK_POWERED); + if (hasSignal) { + world.scheduleBlockUpdate(tilePos, this.block, this.tickDelay()); + } + } + + @Override + public void onFlung(@NotNull World world, @NotNull TilePosc sourcePos, int data, @NotNull CarriedBlock block) { + block.metadata &= ~MASK_POWERED; + } + @Override public void updateTick(final @NotNull World world, final @NotNull TilePosc tilePos, final @NotNull Random rand, final boolean isRandomTick) { this.dispenseItem(world, tilePos, rand); diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLogicLamp.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicLamp.java index 01794530b..73b63fd20 100644 --- a/game/core/src/main/java/net/minecraft/core/block/BlockLogicLamp.java +++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicLamp.java @@ -3,6 +3,9 @@ package net.minecraft.core.block; import net.minecraft.core.block.entity.TileEntity; import net.minecraft.core.block.entity.TileEntityActivator; import net.minecraft.core.block.material.Materials; +import net.minecraft.core.block.motion.CarriedBlock; +import net.minecraft.core.block.piston.IMovingBlock; +import net.minecraft.core.block.piston.MovingLine; import net.minecraft.core.entity.player.Player; import net.minecraft.core.enums.EnumDropCause; import net.minecraft.core.item.ItemStack; @@ -62,23 +65,58 @@ public class BlockLogicLamp extends BlockLogic implements IPainted { @Override public void onNeighborChanged(@NotNull World world, @NotNull TilePosc tilePos, final @NotNull Block block) { + // what is the purpose of .hasDirectSignal? final boolean hasSignal = world.hasDirectSignal(tilePos) || world.hasNeighborSignal(tilePos); + final boolean isPowered = this.isInverted ^ this.isActive; + if (hasSignal == isPowered) return; - if (this.isInverted) { - if (hasSignal && this.isActive) { - world.setBlockTypeDataNotify(tilePos, Blocks.LAMP_INVERTED_IDLE, world.getBlockData(tilePos)); - } else if (!hasSignal && !this.isActive) { - world.setBlockTypeDataNotify(tilePos, Blocks.LAMP_INVERTED_ACTIVE, world.getBlockData(tilePos)); - } - } else { - if (hasSignal && !this.isActive) { - world.setBlockTypeDataNotify(tilePos, Blocks.LAMP_ACTIVE, world.getBlockData(tilePos)); - } else if (!hasSignal && this.isActive) { - world.setBlockTypeDataNotify(tilePos, Blocks.LAMP_IDLE, world.getBlockData(tilePos)); - } + world.setBlockTypeDataNotify(tilePos, this.getBlockForSignal(hasSignal), world.getBlockData(tilePos)); + } + + private @Nullable Block getBlockForSignal(boolean hasSignal) { + return switch (((hasSignal) ? 0b01 : 0b00) | ((this.isInverted) ? 0b10 : 0b00)) { + default -> null; + case 0b00 -> Blocks.LAMP_IDLE; + case 0b01 -> Blocks.LAMP_ACTIVE; + case 0b10 -> Blocks.LAMP_INVERTED_ACTIVE; + case 0b11 -> Blocks.LAMP_INVERTED_IDLE; + }; + } + + @Override + public void onMoved(@NotNull World world, @NotNull TilePosc sourcePos, @NotNull TilePosc targetPos, @NotNull IMovingBlock block, int indexInLine, @NotNull MovingLine line) { + final boolean hasSignal = line.hasNeighborSignal(indexInLine); + final var newBlock = this.getBlockForSignal(hasSignal); + block.setBlockType(newBlock); + if (hasSignal != (this.isInverted ^ this.isActive)) { + line.notifyBlocksOfNeighborChange(indexInLine, newBlock); } } + @Override + public void onMovingNeighborChanged(@NotNull World world, @NotNull TilePosc targetPos, @NotNull IMovingBlock block, int indexInLine, @NotNull MovingLine line, @NotNull Block source) { + final boolean hasSignal = line.hasNeighborSignal(indexInLine); + final var newBlock = this.getBlockForSignal(hasSignal); + block.setBlockType(newBlock); + if (hasSignal != (this.isInverted ^ this.isActive)) { + line.notifyBlocksOfNeighborChange(indexInLine, newBlock); + } + } + + @Override + public void onMoveComplete(@NotNull World world, @NotNull TilePosc tilePos) { + final boolean hasSignal = world.hasDirectSignal(tilePos) || world.hasNeighborSignal(tilePos); + final boolean isPowered = this.isInverted ^ this.isActive; + if (hasSignal == isPowered) return; + + world.setBlockTypeDataNotify(tilePos, this.getBlockForSignal(hasSignal), world.getBlockData(tilePos)); + } + + @Override + public void onFlung(@NotNull World world, @NotNull TilePosc sourcePos, int data, @NotNull CarriedBlock block) { + block.blockId = this.getBlockForSignal(false).id(); + } + @Override public boolean onInteracted(@NotNull World world, @NotNull TilePosc tilePos, @NotNull Player player, @Nullable Side side, double xHit, double yHit) { if (player.getHeldItem() == null) { diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLogicLog.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicLog.java index a0639d527..be61c32b0 100644 --- a/game/core/src/main/java/net/minecraft/core/block/BlockLogicLog.java +++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicLog.java @@ -19,8 +19,8 @@ public class BlockLogicLog extends BlockLogicAxisAligned { if (world.areBlocksLoaded(tilePos.add(-r2, -r2, -r2, new TilePos()), tilePos.add(r2, r2, r2, new TilePos()))) { TilePos queryPos = new TilePos(); for (queryPos.x = tilePos.x() - r; queryPos.x <= tilePos.x() + r; queryPos.x++) { - for (queryPos.y = tilePos.x() - r; queryPos.y <= tilePos.y() + r; queryPos.y++) { - for (queryPos.z = -tilePos.x() - r; queryPos.z <= tilePos.z() + r; queryPos.z++) { + for (queryPos.y = tilePos.y() - r; queryPos.y <= tilePos.y() + r; queryPos.y++) { + for (queryPos.z = tilePos.z() - r; queryPos.z <= tilePos.z() + r; queryPos.z++) { Block block = world.getBlockType(queryPos); if (!(block.getLogic() instanceof BlockLogicLeavesBase)) { continue; diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLogicMatcher.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicMatcher.java index d247ec354..283f3fa11 100644 --- a/game/core/src/main/java/net/minecraft/core/block/BlockLogicMatcher.java +++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicMatcher.java @@ -2,6 +2,8 @@ package net.minecraft.core.block; import net.minecraft.core.block.entity.TileEntity; import net.minecraft.core.block.material.Materials; +import net.minecraft.core.block.piston.IMovingBlock; +import net.minecraft.core.block.piston.MovingLine; import net.minecraft.core.entity.Mob; import net.minecraft.core.enums.EnumDropCause; import net.minecraft.core.enums.PlacementMode; @@ -64,6 +66,11 @@ public class BlockLogicMatcher extends BlockLogicAxisAligned { public void onNeighborChanged(@NotNull World world, @NotNull TilePosc tilePos, final @NotNull Block block) { world.scheduleBlockUpdate(tilePos, this.block, tickDelay()); } + + @Override + public void onMoved(@NotNull World world, @NotNull TilePosc sourcePos, @NotNull TilePosc targetPos, @NotNull IMovingBlock block, int indexInLine, @NotNull MovingLine line) { + world.scheduleBlockUpdate(targetPos, this.block, tickDelay()); + } public void updateState(@NotNull World world, @NotNull TilePosc tilePos) { Axis a = BlockLogicAxisAligned.metaToAxis(world.getBlockData(tilePos) & BlockLogicAxisAligned.MASK_DIRECTION); diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLogicMotionSensor.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicMotionSensor.java index 794d81e3e..f23bab145 100644 --- a/game/core/src/main/java/net/minecraft/core/block/BlockLogicMotionSensor.java +++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicMotionSensor.java @@ -80,4 +80,5 @@ public class BlockLogicMotionSensor extends BlockLogicVeryRotatable { return new ItemStack[]{new ItemStack(Blocks.MOTION_SENSOR_IDLE)}; } + // TODO: refactor tileEntity tick to work with moving block as well } diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLogicNote.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicNote.java index c45b67779..d889de532 100644 --- a/game/core/src/main/java/net/minecraft/core/block/BlockLogicNote.java +++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicNote.java @@ -5,6 +5,9 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import net.minecraft.core.block.entity.TileEntityActivator; import net.minecraft.core.block.material.Materials; +import net.minecraft.core.block.motion.CarriedBlock; +import net.minecraft.core.block.piston.IMovingBlock; +import net.minecraft.core.block.piston.MovingLine; import net.minecraft.core.entity.player.Player; import net.minecraft.core.sound.SoundCategory; import net.minecraft.core.util.helper.Direction; @@ -32,14 +35,47 @@ public class BlockLogicNote extends BlockLogic { @Override public void onNeighborChanged(@NotNull World world, @NotNull TilePosc tilePos, final @NotNull Block block) { - boolean powered = world.hasNeighborSignal(tilePos); - int data = world.getBlockData(tilePos); - if (isPowered(data) && !powered) { - world.setBlockData(tilePos, setPowered(data, false)); - } else if (!isPowered(data) && powered) { - triggerNote(world, tilePos); - world.setBlockData(tilePos, setPowered(data, true)); - } + final int data = world.getBlockData(tilePos); + final boolean hasSignal = world.hasNeighborSignal(tilePos); + final boolean isPowered = isPowered(data); + if (isPowered == hasSignal) return; + world.setBlockData(tilePos, data ^ MASK_POWERED); + if (hasSignal) triggerNote(world, tilePos); + } + + @Override + public void onMoved(@NotNull World world, @NotNull TilePosc sourcePos, @NotNull TilePosc targetPos, @NotNull IMovingBlock block, int indexInLine, @NotNull MovingLine line) { + final int data = block.getBlockData(); + final boolean hasSignal = line.hasNeighborSignal(indexInLine); + final boolean isPowered = isPowered(data); + if (isPowered == hasSignal) return; + block.setBlockData(data ^ MASK_POWERED); + if (hasSignal) triggerNote(world, targetPos); + } + + @Override + public void onMovingNeighborChanged(@NotNull World world, @NotNull TilePosc targetPos, @NotNull IMovingBlock block, int indexInLine, @NotNull MovingLine line, @NotNull Block source) { + final int data = block.getBlockData(); + final boolean hasSignal = line.hasNeighborSignal(indexInLine); + final boolean isPowered = isPowered(data); + if (isPowered == hasSignal) return; + block.setBlockData(data ^ MASK_POWERED); + if (hasSignal) triggerNote(world, targetPos); + } + + @Override + public void onMoveComplete(@NotNull World world, @NotNull TilePosc tilePos) { + final int data = world.getBlockData(tilePos); + final boolean hasSignal = world.hasNeighborSignal(tilePos); + final boolean isPowered = isPowered(data); + if (isPowered == hasSignal) return; + world.setBlockData(tilePos, data ^ MASK_POWERED); + if (hasSignal) triggerNote(world, tilePos); + } + + @Override + public void onFlung(@NotNull World world, @NotNull TilePosc sourcePos, int data, @NotNull CarriedBlock block) { + block.metadata &= ~MASK_POWERED; } @Override diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLogicOreRedstone.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicOreRedstone.java index 782117b85..1ba79015d 100644 --- a/game/core/src/main/java/net/minecraft/core/block/BlockLogicOreRedstone.java +++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicOreRedstone.java @@ -16,6 +16,9 @@ import net.minecraft.core.util.helper.Side; import net.minecraft.core.world.LevelListener; import net.minecraft.core.world.World; import net.minecraft.core.block.material.Material; +import net.minecraft.core.block.piston.IMovingBlock; +import net.minecraft.core.block.piston.MovingLine; +import net.minecraft.core.block.piston.MovingLine.LineDirection; import net.minecraft.core.world.WorldSource; import net.minecraft.core.world.pos.TilePos; import net.minecraft.core.world.pos.TilePosc; @@ -80,6 +83,13 @@ public class BlockLogicOreRedstone extends BlockLogic { lightRedstone(world, tilePos); } + @Override + public void onMoved(@NotNull World world, @NotNull TilePosc sourcePos, @NotNull TilePosc targetPos, @NotNull IMovingBlock block, int indexInLine, @NotNull MovingLine line) { + block.setBlockType(this.illuminatedBlock); + if (this.block != this.illuminatedBlock) line.updateSignal(indexInLine, LineDirection.BOTH, true); + world.scheduleBlockUpdate(targetPos, this.illuminatedBlock, 20 + world.rand.nextInt(9 * 20)); + } + private void lightRedstone(@NotNull World world, @NotNull TilePosc tilePos) { spawnParticles(world, tilePos); if (!this.illuminated) { diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLogicPumpkinRedstone.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicPumpkinRedstone.java index 3fe46ef80..be3126176 100644 --- a/game/core/src/main/java/net/minecraft/core/block/BlockLogicPumpkinRedstone.java +++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicPumpkinRedstone.java @@ -2,11 +2,11 @@ package net.minecraft.core.block; import net.minecraft.core.block.material.Material; import net.minecraft.core.block.material.Materials; -import net.minecraft.core.util.helper.Direction; +import net.minecraft.core.block.piston.IMovingBlock; +import net.minecraft.core.block.piston.MovingLine; import net.minecraft.core.util.helper.Side; import net.minecraft.core.world.World; import net.minecraft.core.world.WorldSource; -import net.minecraft.core.world.pos.TilePos; import net.minecraft.core.world.pos.TilePosc; import org.jetbrains.annotations.NotNull; @@ -20,13 +20,20 @@ public class BlockLogicPumpkinRedstone extends BlockLogicVeryRotatable { public void onPlacedByWorld(@NotNull World world, @NotNull TilePosc tilePos) { world.notifyShellBlocksInRadiusOfNeighborChange(2, tilePos, this.block); } - + @Override public void onRemoved(@NotNull World world, @NotNull TilePosc tilePos, int data) { - TilePos queryPos = new TilePos(); - for (final var dir : Direction.all){ - world.notifyBlocksOfNeighborChange(tilePos.add(dir, queryPos), this.block); - } + world.notifyShellBlocksInRadiusOfNeighborChange(2, tilePos, this.block); + } + + @Override + public void onMoved(@NotNull World world, @NotNull TilePosc sourcePos, @NotNull TilePosc targetPos, @NotNull IMovingBlock block, int indexInLine, @NotNull MovingLine line) { + world.notifyShellBlocksInRadiusOfNeighborChange(2, sourcePos, this.block); + } + + @Override + public void onMoveComplete(@NotNull World world, @NotNull TilePosc tilePos) { + world.notifyBlocksInRadiusOfNeighborChange(2, tilePos, this.block); } @Override diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLogicRail.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicRail.java index b55e3f37e..9784c72c7 100644 --- a/game/core/src/main/java/net/minecraft/core/block/BlockLogicRail.java +++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicRail.java @@ -160,6 +160,9 @@ public class BlockLogicRail extends BlockLogic implements ISupportable { performRailTurn(world, tilePos, false); } } + + // TODO: onMoved + // Checks that the rail is placed on top of a block and doesn't slope into the air private boolean isRailValid(@NotNull World world, @NotNull TilePosc tilePos) { diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLogicRedstone.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicRedstone.java index b5c8862f7..9a8bb162f 100644 --- a/game/core/src/main/java/net/minecraft/core/block/BlockLogicRedstone.java +++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicRedstone.java @@ -1,6 +1,8 @@ package net.minecraft.core.block; import net.minecraft.core.block.material.Material; +import net.minecraft.core.block.piston.IMovingBlock; +import net.minecraft.core.block.piston.MovingLine; import net.minecraft.core.util.helper.Direction; import net.minecraft.core.util.helper.Side; import net.minecraft.core.world.WorldSource; @@ -40,7 +42,16 @@ public class BlockLogicRedstone extends BlockLogic { public void onRemoved(@NotNull World world, @NotNull TilePosc tilePos, int data) { world.notifyBlocksInRadiusOfNeighborChange(2, tilePos, this.block); } - + + @Override + public void onMoved(@NotNull World world, @NotNull TilePosc sourcePos, @NotNull TilePosc targetPos, @NotNull IMovingBlock block, int indexInLine, @NotNull MovingLine line) { + world.notifyBlocksInRadiusOfNeighborChange(2, sourcePos, this.block); + } + + @Override + public void onMoveComplete(@NotNull World world, @NotNull TilePosc tilePos) { + world.notifyBlocksInRadiusOfNeighborChange(2, tilePos, this.block); + } @Override public void animationTick(@NotNull World world, @NotNull TilePosc tilePos, @NotNull Random rand) { diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLogicSpikes.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicSpikes.java index 8236bc71d..10f062f76 100644 --- a/game/core/src/main/java/net/minecraft/core/block/BlockLogicSpikes.java +++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicSpikes.java @@ -15,6 +15,9 @@ import net.minecraft.core.util.helper.Side; import net.minecraft.core.world.LevelListener; import net.minecraft.core.world.World; import net.minecraft.core.block.material.Material; +import net.minecraft.core.block.motion.CarriedBlock; +import net.minecraft.core.block.piston.IMovingBlock; +import net.minecraft.core.block.piston.MovingLine; import net.minecraft.core.util.helper.DamageType; import net.minecraft.core.world.WorldSource; import net.minecraft.core.world.pos.TilePosc; @@ -68,25 +71,47 @@ public class BlockLogicSpikes extends BlockLogic @Override public void onNeighborChanged(@NotNull World world, @NotNull TilePosc tilePos, final @NotNull Block block) { - if(world.isClientSide) { - return; - } + if(world.isClientSide) return; - int meta = world.getBlockData(tilePos); - boolean wasPowered = (meta & MASK_POWERED) != 0; - boolean isPowered = world.hasNeighborSignal(tilePos); + final int meta = world.getBlockData(tilePos); + final boolean wasPowered = (meta & MASK_POWERED) != 0; + final boolean isPowered = world.hasNeighborSignal(tilePos); + if (isPowered == wasPowered) return; + world.setBlockDataNotify(tilePos, meta ^ MASK_POWERED); - if(isPowered != wasPowered) { - if(isPowered) { - world.playBlockEvent(null, tilePos, LevelListener.EVENT_PISTON_RETRACT, 0); - world.setBlockDataNotify(tilePos, meta | MASK_POWERED); - }else { - world.playBlockEvent(null, tilePos, LevelListener.EVENT_PISTON_EXTEND, 0); - world.setBlockDataNotify(tilePos, meta & ~MASK_POWERED); - } - } + final var event = (isPowered) ? LevelListener.EVENT_PISTON_RETRACT : LevelListener.EVENT_PISTON_EXTEND; + world.playBlockEvent(null, tilePos, event, 0); } + @Override + public void onMoved(@NotNull World world, @NotNull TilePosc sourcePos, @NotNull TilePosc targetPos, @NotNull IMovingBlock block, int indexInLine, @NotNull MovingLine line) { + final int meta = block.getBlockData(); + final boolean wasPowered = (meta & MASK_POWERED) != 0; + final boolean isPowered = line.hasNeighborSignal(indexInLine); + if (isPowered == wasPowered) return; + block.setBlockData(meta ^ MASK_POWERED); + + final var event = (isPowered) ? LevelListener.EVENT_PISTON_RETRACT : LevelListener.EVENT_PISTON_EXTEND; + world.playBlockEvent(null, targetPos, event, 0); + } + + @Override + public void onMovingNeighborChanged(@NotNull World world, @NotNull TilePosc targetPos, @NotNull IMovingBlock block, int indexInLine, @NotNull MovingLine line, @NotNull Block source) { + final int meta = block.getBlockData(); + final boolean wasPowered = (meta & MASK_POWERED) != 0; + final boolean isPowered = line.hasNeighborSignal(indexInLine); + if (isPowered == wasPowered) return; + block.setBlockData(meta ^ MASK_POWERED); + + final var event = (isPowered) ? LevelListener.EVENT_PISTON_RETRACT : LevelListener.EVENT_PISTON_EXTEND; + world.playBlockEvent(null, targetPos, event, 0); + } + + @Override + public void onFlung(@NotNull World world, @NotNull TilePosc sourcePos, int data, @NotNull CarriedBlock block) { + block.metadata &= ~MASK_POWERED; + } + @Override public @NotNull AABBdc getBoundsFromState(@NotNull WorldSource source, @NotNull TilePosc tilePos) { double thickness = 3/16d; diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLogicTNT.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicTNT.java index 0ecdc1f33..9127650cd 100644 --- a/game/core/src/main/java/net/minecraft/core/block/BlockLogicTNT.java +++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicTNT.java @@ -2,6 +2,8 @@ package net.minecraft.core.block; import net.minecraft.core.block.entity.TileEntity; import net.minecraft.core.block.material.Materials; +import net.minecraft.core.block.piston.IMovingBlock; +import net.minecraft.core.block.piston.MovingLine; import net.minecraft.core.entity.player.Player; import net.minecraft.core.entity.EntityPrimedTNT; import net.minecraft.core.enums.EnumDropCause; @@ -34,6 +36,28 @@ public class BlockLogicTNT extends BlockLogic { } } + @Override + public void onMoved(@NotNull World world, @NotNull TilePosc sourcePos, @NotNull TilePosc targetPos, @NotNull IMovingBlock block, int indexInLine, @NotNull MovingLine line) { + if (line.hasNeighborSignal(indexInLine)) { + block.setBlockType(Blocks.AIR); + line.notifyBlocksOfNeighborChange(indexInLine, Blocks.AIR); + EntityPrimedTNT tnt = new EntityPrimedTNT(world, sourcePos.x() + 0.5F, sourcePos.y() + 0.5F, sourcePos.z() + 0.5F); + world.entityJoinedWorld(tnt); + world.playSoundAtEntity(null, tnt, "tile.tnt.fuse", 1.0F, 1.0F); + } + } + + @Override + public void onMovingNeighborChanged(@NotNull World world, @NotNull TilePosc targetPos, @NotNull IMovingBlock block, int indexInLine, @NotNull MovingLine line, @NotNull Block source) { + if (line.hasNeighborSignal(indexInLine)) { + block.setBlockType(Blocks.AIR); + line.notifyBlocksOfNeighborChange(indexInLine, Blocks.AIR); + EntityPrimedTNT tnt = new EntityPrimedTNT(world, line.sourcePos(indexInLine).x() + 0.5F, line.sourcePos(indexInLine).y() + 0.5F, line.sourcePos(indexInLine).z() + 0.5F); + world.entityJoinedWorld(tnt); + world.playSoundAtEntity(null, tnt, "tile.tnt.fuse", 1.0F, 1.0F); + } + } + @Override public ItemStack[] getBreakResult(@NotNull World world, @NotNull EnumDropCause dropCause, int data, @Nullable TileEntity tileEntity) { diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLogicTrapDoor.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicTrapDoor.java index c9d86983b..0855f0212 100644 --- a/game/core/src/main/java/net/minecraft/core/block/BlockLogicTrapDoor.java +++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicTrapDoor.java @@ -3,6 +3,8 @@ package net.minecraft.core.block; import net.minecraft.core.block.entity.TileEntityActivator; import net.minecraft.core.block.material.Material; import net.minecraft.core.block.material.Materials; +import net.minecraft.core.block.piston.IMovingBlock; +import net.minecraft.core.block.piston.MovingLine; import net.minecraft.core.block.support.FullSupport; import net.minecraft.core.block.support.ISupport; import net.minecraft.core.block.support.PartialSupport; @@ -132,20 +134,33 @@ public class BlockLogicTrapDoor extends BlockLogic implements IPaintable { @Override public void onNeighborChanged(@NotNull World world, @NotNull TilePosc tilePos, final @NotNull Block block) { - if (world.isClientSide) { - return; - } + if (world.isClientSide) return; + if (!block.isSignalSource()) return; - if (this.material != Materials.METAL && this.material != Materials.STEEL && block.isSignalSource() || (this.material == Materials.METAL || this.material == Materials.STEEL) && block.isSignalSource()) { - int meta = world.getBlockData(tilePos); - boolean isOpened = isTrapdoorOpen(meta); - boolean isPowered = world.hasNeighborSignal(tilePos); + final int meta = world.getBlockData(tilePos); + final boolean isOpened = isTrapdoorOpen(meta); + final boolean isPowered = world.hasNeighborSignal(tilePos); - if (isOpened != isPowered) { - world.setBlockDataNotify(tilePos, setTrapdoorOpen(meta, isPowered)); - world.playBlockEvent(null, tilePos, LevelListener.EVENT_DOOR_SOUND, 0); - } - } + if (isOpened == isPowered) return; + + world.setBlockDataNotify(tilePos, meta ^ MASK_OPEN); + world.playBlockEvent(null, tilePos, LevelListener.EVENT_DOOR_SOUND, 0); + } + + @Override + public void onMovingNeighborChanged(@NotNull World world, @NotNull TilePosc targetPos, @NotNull IMovingBlock block, int indexInLine, @NotNull MovingLine line, @NotNull Block source) { + if (world.isClientSide) return; + if (!source.isSignalSource()) return; + + final int meta = block.getBlockData(); + final boolean isOpened = isTrapdoorOpen(meta); + final boolean isPowered = line.hasNeighborSignal(indexInLine); + + if (isOpened == isPowered) return; + + block.setBlockData(meta ^ MASK_OPEN); + line.notifyBlocksOfNeighborChange(indexInLine, this.block); + world.playBlockEvent(null, targetPos, LevelListener.EVENT_DOOR_SOUND, 0); } @Override diff --git a/game/core/src/main/java/net/minecraft/core/block/Blocks.java b/game/core/src/main/java/net/minecraft/core/block/Blocks.java index f1c2b4de5..ba2da2dcf 100644 --- a/game/core/src/main/java/net/minecraft/core/block/Blocks.java +++ b/game/core/src/main/java/net/minecraft/core/block/Blocks.java @@ -813,7 +813,7 @@ public final class Blocks { public static final @NotNull Block PISTON_BASE_STICKY = register("piston.base.sticky", "minecraft:block/piston_base_sticky", 521, (BlockLogicSupplier)b -> new BlockLogicPistonBase( b, PistonCommon.TYPE_STICKY, - (byte)12, (byte)1, null, true, Double.NaN + (byte)12, (byte)1, EnumDropCause.SILK_TOUCH, true, Double.NaN )) .withSound(BlockSounds.STONE).withDisabledNeighborNotifyOnMetadataChange() .withTags(BlockTags.MINEABLE_BY_PICKAXE); diff --git a/game/core/src/main/java/net/minecraft/core/block/entity/TileEntitySensor.java b/game/core/src/main/java/net/minecraft/core/block/entity/TileEntitySensor.java index 81624ba86..e75903a14 100644 --- a/game/core/src/main/java/net/minecraft/core/block/entity/TileEntitySensor.java +++ b/game/core/src/main/java/net/minecraft/core/block/entity/TileEntitySensor.java @@ -18,6 +18,7 @@ import org.joml.primitives.AABBd; import org.joml.primitives.AABBdc; public class TileEntitySensor extends TileEntity { + private final AABBd detectionBox = new AABBd(); private int getSightRange(World world, double x, double y, double z, Direction facing) { if (facing == Direction.NONE) { @@ -60,7 +61,7 @@ public class TileEntitySensor extends TileEntity { double maxY = Math.max(y1, y2) + 1; double maxZ = Math.max(z1, z2) + 1; - return new AABBd(minX, minY, minZ, maxX, maxY, maxZ); + return this.detectionBox.setMin(minX, minY, minZ).setMax(maxX, maxY, maxZ); } @Override diff --git a/game/core/src/main/java/net/minecraft/core/block/motion/CarriedBlock.java b/game/core/src/main/java/net/minecraft/core/block/motion/CarriedBlock.java index f7a2ded33..66612a564 100644 --- a/game/core/src/main/java/net/minecraft/core/block/motion/CarriedBlock.java +++ b/game/core/src/main/java/net/minecraft/core/block/motion/CarriedBlock.java @@ -13,7 +13,6 @@ import net.minecraft.core.util.helper.MathHelper; import net.minecraft.core.util.helper.Side; import net.minecraft.core.world.ICarriable; import net.minecraft.core.world.World; -import net.minecraft.core.world.pos.TilePosc; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/game/core/src/main/java/net/minecraft/core/block/piston/BlockLogicPistonBase.java b/game/core/src/main/java/net/minecraft/core/block/piston/BlockLogicPistonBase.java index 762cb1c4d..5235ee1cb 100644 --- a/game/core/src/main/java/net/minecraft/core/block/piston/BlockLogicPistonBase.java +++ b/game/core/src/main/java/net/minecraft/core/block/piston/BlockLogicPistonBase.java @@ -54,6 +54,7 @@ public class BlockLogicPistonBase extends BlockLogic { this.typeId = typeId; assert typeId >= 0 && typeId < 3; + assert pushLimit <= 64; this.pushLimit = pushLimit; this.crushLimit = crushLimit; @@ -310,39 +311,55 @@ public class BlockLogicPistonBase extends BlockLogic { } private static void push(@NotNull World world, @NotNull TilePosc headPos, @NotNull Direction dir, int len) { - final var src = new TilePos(); - final var tar = new TilePos(); - - for (int i = len - 1; i >= 0; i--) { - src.set(headPos); - dir.offsetScaled(src, i); - tar.set(src); - dir.offset(tar); - - final @NotNull Block block; - final int data; - var entity = world.getTileEntity(src); - - if (entity instanceof TileEntityMovingPistonBlock moving && !moving.isSourcePiston) { - assert world.getBlockType(src) == Blocks.PISTON_MOVING; - block = moving.movingBlock; - data = moving.movingBlockData; - entity = moving.movingTileEntity; - } else { - block = world.getBlockType(src); - data = world.getBlockData(src); + if (len <= 0) return; + final TilePos pos1 = new TilePos(), pos2 = new TilePos(); + + final var line = new MovingLine(len, world, dir, headPos, true); + + /* block type,data,entity lookup */ { + final var queryPos = pos1.set(headPos); + for (int i = 0; i < len; i++, queryPos.add(dir)) { + line.blocks[i] = world.getBlockType(queryPos); + line.data[i] = (byte)world.getBlockData(queryPos); + line.entities[i] = world.getTileEntity(queryPos); + + // We DON'T handle moving piston, as it is ruled out in movability test + assert line.blocks[i] != Blocks.PISTON_MOVING; + assert !(line.entities[i] instanceof TileEntityMovingPistonBlock); } + } + + line.computeConductMask(); + line.computeSignalMask(); + + /* move */ { + final var tar = dir.offsetScaled(pos1.set(headPos), len); + final var src = dir.offsetScaled(pos2.set(headPos), len - 1); + + for (int i = len; i > 0; src.sub(dir), tar.sub(dir)) { + i--; + assert tar != headPos; - world.removeTileEntity(src); - final var moving = new TileEntityMovingPistonBlock( - MovingType.EXTENDING, - block, data, entity, dir); - world.setBlockTypeDataEntity(tar, Blocks.PISTON_MOVING, data, moving); + world.removeTileEntity(src); + world.setBlockTypeRaw(src, Blocks.AIR); - if (i >= 1) world.setBlockTypeRaw(src, Blocks.AIR); + world.setBlockTypeDataEntity(tar, Blocks.PISTON_MOVING, line.data[i], line.createMoving(i)); + } + } + + /* update data */ { + final var tar = dir.offsetScaled(pos1.set(headPos), len); + final var src = dir.offsetScaled(pos2.set(headPos), len - 1); + + for (int i = len; i > 0; src.sub(dir), tar.sub(dir)) { + i--; + assert tar != headPos; + line.blocks[i].onMoved(world, src, tar, line.movingBlocks[i], i, line); + } } } + private void breakTail( @NotNull EnumDropCause cause, @NotNull World world, @NotNull TilePosc headPos, @NotNull Direction dir, int off @@ -383,8 +400,9 @@ public class BlockLogicPistonBase extends BlockLogic { final int blockMeta = world.getBlockData(headPos); final var tileEntity = world.getTileEntity(headPos); world.removeTileEntity(headPos); - world.setBlockTypeNotify(headPos, Blocks.AIR); - + world.setBlockTypeRaw(headPos, Blocks.AIR); + world.notifyBlocksOfNeighborChange(headPos, Blocks.AIR); + if (world.isClientSide) return; var flungBlock = new EntityFallingBlock(world, @@ -399,6 +417,7 @@ public class BlockLogicPistonBase extends BlockLogic { world.entityJoinedWorld(flungBlock); flungBlock.fling(vx, vy, vz, 1f); + block.onFlung(world, headPos, blockMeta, flungBlock.carriedBlock); } private void retract(@NotNull World world, @NotNull TilePosc tilePos, int data) { @@ -406,13 +425,11 @@ public class BlockLogicPistonBase extends BlockLogic { final var dir = Direction.fromId(DIRECTION.get(data)); final var headPos = new TilePos(tilePos).add(dir); - if (world.getTileEntity(headPos) instanceof TileEntityMovingPistonBlock moving) { - if (!moving.isExtending) { - moving.finalTick(); - } else { - world.setBlockType(headPos, Blocks.AIR); - } + if (world.getTileEntity(headPos) instanceof TileEntityMovingPistonBlock moving && !moving.isExtending) { + moving.finalTick(); } + world.setBlockTypeRaw(headPos, Blocks.AIR); + world.removeTileEntity(headPos); final var moving = new TileEntityMovingPistonBlock( MovingType.RETRACTING_PISTON, @@ -420,12 +437,7 @@ public class BlockLogicPistonBase extends BlockLogic { world.setBlockTypeRaw(tilePos, Blocks.AIR); world.setBlockTypeDataEntity(tilePos, Blocks.PISTON_MOVING, data, moving); - if (this.canPull) { - pull(world, headPos, dir); - } else { - world.setBlockType(headPos, Blocks.AIR); - world.removeTileEntity(headPos); - } + if (this.canPull) pull(world, headPos, dir); // logically, retraction should only update head immediately, and base 3 ticks after // but this emulates the old behavior @@ -454,17 +466,21 @@ public class BlockLogicPistonBase extends BlockLogic { world.setBlockType(tar, Blocks.AIR); return; } - + final var block = world.getBlockType(src); final var data = world.getBlockData(src); - world.removeTileEntity(src); - final var moving = new TileEntityMovingPistonBlock( - MovingType.RETRACTING, - block, data, entity, dir); - world.setBlockTypeDataEntity(tar, Blocks.PISTON_MOVING, data, moving); - world.setBlockTypeNotify(src, Blocks.AIR); + final var line = new MovingLine(1, world, dir, headPos, false); + line.blocks[0] = block; + line.data[0] = (byte)data; + line.entities[0] = entity; + + world.setBlockTypeRaw(src, Blocks.AIR); + world.setBlockTypeDataEntity(tar, Blocks.PISTON_MOVING, data, line.createMoving(0)); + + block.onMoved(world, src, tar, line.movingBlocks[0], 0, line); + world.notifyBlocksOfNeighborChange(src, Blocks.AIR); } // BlockLogic impl: @@ -563,14 +579,14 @@ public class BlockLogicPistonBase extends BlockLogic { public int getPistonPushReaction(@NotNull World world, @NotNull TilePosc tilePos) { final var data = fixLegacyBaseData(world, tilePos); - return (IS_DETACHED_OR_EXTENDED.bool(data)) + return (IS_EXTENDED.bool(data)) ? Material.PISTON_CANT_PUSH : super.getPistonPushReaction(world, tilePos); } @Override public void onRemoved(@NotNull World world, @NotNull TilePosc tilePos, int data) { - data = validateBaseData(data, this); + data = fixLegacyBaseData(world, tilePos, this, data); if (IS_DETACHED.bool(data)) return; final var dir = Direction.fromId(DIRECTION.get(data)); diff --git a/game/core/src/main/java/net/minecraft/core/block/piston/BlockLogicPistonMoving.java b/game/core/src/main/java/net/minecraft/core/block/piston/BlockLogicPistonMoving.java index 67f43c127..d5d6fbc35 100644 --- a/game/core/src/main/java/net/minecraft/core/block/piston/BlockLogicPistonMoving.java +++ b/game/core/src/main/java/net/minecraft/core/block/piston/BlockLogicPistonMoving.java @@ -21,7 +21,6 @@ import java.util.List; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.joml.primitives.AABBd; import org.joml.primitives.AABBdc; public class BlockLogicPistonMoving extends BlockLogic { @@ -60,6 +59,30 @@ public class BlockLogicPistonMoving extends BlockLogic { return false; } + @Override + public boolean renderAsNormalBlockOnCondition(@NotNull WorldSource source, @NotNull TilePosc tilePos) { + if (!(source.getTileEntity(tilePos) instanceof TileEntityMovingPistonBlock moving)) return false; + if (!moving.isInFinalTick()) return false; + // TODO: purely data-based api + return moving.movingBlock.renderAsNormalBlockOnCondition(source, tilePos); + } + + @Override + public boolean isEmittingSignal(@NotNull WorldSource source, @NotNull TilePosc tilePos, @NotNull Side side) { + if (!(source.getTileEntity(tilePos) instanceof TileEntityMovingPistonBlock moving)) return false; + if (!moving.isInFinalTick()) return false; + // TODO: purely data-based api + return moving.movingBlock.isEmittingSignal(source, tilePos, side); + } + + @Override + public boolean isEmittingDirectSignal(@NotNull World world, @NotNull TilePosc tilePos, @NotNull Side side) { + if (!(world.getTileEntity(tilePos) instanceof TileEntityMovingPistonBlock moving)) return false; + if (!moving.isInFinalTick()) return false; + // TODO: purely data-based api + return moving.movingBlock.isEmittingDirectSignal(world, tilePos, side); + } + @Override public ItemStack[] getBreakResult(@NotNull World world, @NotNull EnumDropCause dropCause, int data, @Nullable TileEntity tileEntity) { return null; @@ -68,8 +91,8 @@ public class BlockLogicPistonMoving extends BlockLogic { @Override public void dropWithCause(@NotNull World world, @NotNull EnumDropCause dropCause, @NotNull TilePosc tilePos, int data, @Nullable TileEntity tileEntity, @Nullable Player player) { if (world.isClientSide) return; - if (world.getTileEntity(tilePos) instanceof TileEntityMovingPistonBlock piston) { - piston.movingBlock().dropWithCause(world, EnumDropCause.WORLD, tilePos, data, null, null); + if (world.getTileEntity(tilePos) instanceof TileEntityMovingPistonBlock moving) { + moving.movingBlock().dropWithCause(world, EnumDropCause.WORLD, tilePos, data, null, null); } } diff --git a/game/core/src/main/java/net/minecraft/core/block/piston/IMovingBlock.java b/game/core/src/main/java/net/minecraft/core/block/piston/IMovingBlock.java new file mode 100644 index 000000000..d35dca5bd --- /dev/null +++ b/game/core/src/main/java/net/minecraft/core/block/piston/IMovingBlock.java @@ -0,0 +1,17 @@ +package net.minecraft.core.block.piston; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import net.minecraft.core.block.Block; +import net.minecraft.core.block.entity.TileEntity; + +public interface IMovingBlock { + @NotNull Block getBlockType(); + int getBlockData(); + @Nullable TileEntity getTileEntity(); + + void setBlockType(@NotNull Block block); + void setBlockData(int data); + void setTileEntity(@Nullable TileEntity tileEntity); +} diff --git a/game/core/src/main/java/net/minecraft/core/block/piston/MovingLine.java b/game/core/src/main/java/net/minecraft/core/block/piston/MovingLine.java new file mode 100644 index 000000000..53312fb3c --- /dev/null +++ b/game/core/src/main/java/net/minecraft/core/block/piston/MovingLine.java @@ -0,0 +1,264 @@ +package net.minecraft.core.block.piston; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import net.minecraft.core.block.Block; +import net.minecraft.core.block.Blocks; +import net.minecraft.core.block.entity.TileEntity; +import net.minecraft.core.block.piston.PistonCommon.MovingType; +import net.minecraft.core.util.helper.Direction; +import net.minecraft.core.util.helper.Side; +import net.minecraft.core.world.World; +import net.minecraft.core.world.pos.TilePos; +import net.minecraft.core.world.pos.TilePosc; + +public final class MovingLine { + public final int len; + public final boolean isExtending; + + public final @NotNull Direction direction; + public final @NotNull TilePosc origin; + + final @NotNull World world; + + final @NotNull Block[] blocks; + final byte[] data; + final @Nullable TileEntity[] entities; + long conductMask = 0; + long signalMask = 0; + + final @Nullable TileEntityMovingPistonBlock[] movingBlocks; + + MovingLine(int len, @NotNull World world, @NotNull Direction dir, @NotNull TilePosc origin, boolean isExtending) { + assert len < 64; + this.len = len; + this.direction = dir; + this.origin = origin; + this.world = world; + this.isExtending = isExtending; + this.blocks = new Block[len]; + this.data = new byte[len]; + this.entities = new TileEntity[len]; + this.movingBlocks = new TileEntityMovingPistonBlock[len]; + } + + public @NotNull Direction movingDirection() { + return (this.isExtending) ? direction : direction.opposite(); + } + + public @NotNull Block blockType(int index) { + assert index >= 0 && index < this.len; + assert this.blocks.length >= this.len; + return this.blocks[index]; + } + + public byte blockData(int index) { + assert index >= 0 && index < this.len; + assert this.data.length >= this.len; + return this.data[index]; + } + + public boolean hasNeighborSignal(int index) { + assert index >= 0 && index < Math.min(this.len, 64); + + final long bitMask = 1L << index; + return (signalMask & bitMask) != 0; + } + + public static enum LineDirection { + NONE(0b00), + FORWARD(0b01), + BACKWARD(0b10), + BOTH(0b11); + + LineDirection(int mask) { + this.mask = (byte)mask; + } + + public static @NotNull LineDirection from(@NotNull MovingLine line, @NotNull Direction dir) { + if (dir == Direction.NONE) return NONE; + return switch (line.direction.id ^ dir.id) { + default -> NONE; + case 0 -> FORWARD; + case 1 -> BACKWARD; + }; + } + + public final byte mask; + public boolean isForward() { + return (this.mask & FORWARD.mask) != 0; + } + public boolean isBackward() { + return (this.mask & BACKWARD.mask) != 0; + } + } + + long computeConductMask() { + final var queryPos = new TilePos(); + long set; + + set = 0b1L; + queryPos.set(this.origin); + for (int i = 0; i < this.len; i++, set <<= 1, queryPos.add(this.direction)) { + if (!world.isBlockNormalCube(queryPos)) continue; + if (this.blocks[i] == Blocks.BLOCK_REDSTONE) continue; + if (this.blocks[i] == Blocks.PUMPKIN_REDSTONE) continue; + if (this.blocks[i] == Blocks.MATCHER_ACTIVE) continue; + this.conductMask |= set; + } + + return this.conductMask; + } + + // TODO: this can be far more efficient, but the pumpkin edgecase sucks + long computeSignalMask() { + final var p0 = new TilePos(); + final var p1 = new TilePos(); + long set; + + set = 0b10; + p0.set(this.origin); + for (int i = 0; i < this.len - 1; i++, set <<= 1, p0.add(this.direction)) { + var sig = this.hasSignal(this.world, p0, i, this.direction.opposite().side(), p1); + this.signalMask |= (sig) ? set : 0; + } + set = 0b01; + p0.set(this.origin).add(this.direction); + for (int i = 1; i < this.len; i++, set <<= 1, p0.add(this.direction)) { + var sig = this.hasSignal(this.world, p0, i, this.direction.side(), p1); + this.signalMask |= (sig) ? set : 0; + } + return this.signalMask; + } + + private boolean hasSignal( + @NotNull World world, @NotNull TilePosc tilePos, + int index, @NotNull Side side, @NotNull TilePos queryPos + ) { + final Direction d1, d2; + d1 = this.direction; + d2 = this.direction.opposite(); + final @NotNull Block block = this.blocks[index]; + if (world.isBlockNormalCube(tilePos)) direct_sig: { + if (block == Blocks.BLOCK_REDSTONE) break direct_sig; + if (block == Blocks.PUMPKIN_REDSTONE) break direct_sig; + if (block == Blocks.MATCHER_ACTIVE) break direct_sig; + if (world.hasDirectSignal(queryPos.set(tilePos).add(d1), d1.side())) return true; + if (world.hasDirectSignal(queryPos.set(tilePos).add(d2), d2.side())) return true; + } + if (block == Blocks.PUMPKIN_REDSTONE) { + final var pumpkinDir = Direction.fromId(this.data[index]); + if (pumpkinDir != d1 && world.hasDirectSignal(queryPos.set(tilePos).add(d1), d1.side())) return true; + if (pumpkinDir != d2 && world.hasDirectSignal(queryPos.set(tilePos).add(d2), d2.side())) return true; + } + return block.isEmittingSignal(world, tilePos, side); + } + + public void updateSignal(int index, @NotNull LineDirection direction, boolean isPowered) { + final var qpos = new TilePos(); + if (direction.isBackward()) { + this.setPowered(index - 1, isPowered); + this.notifyBlockOfNeighborChange(index - 1, qpos, this.blocks[index]); + } + if (direction.isForward()) { + this.setPowered(index + 1, isPowered); + this.notifyBlockOfNeighborChange(index + 1, qpos, this.blocks[index]); + } + } + + public void updateDirectSignal(int index, @NotNull LineDirection direction, boolean isPowered) { + final var qpos = new TilePos(); + for (int i = -1; i <= 1; i += 2) { + if (i < 0 && !direction.isBackward()) continue; + if (i > 0 && !direction.isForward()) continue; + + int j = index; + + j += i; + this.setPowered(j, isPowered); + this.notifyBlockOfNeighborChange(j, qpos, this.blocks[index]); + + if (!this.canBlockBePowered(j, qpos)) continue; + + j += i; + this.setPowered(j, isPowered); + this.notifyBlockOfNeighborChange(j, qpos, this.blocks[index]); + } + } + + public @NotNull TilePosc sourcePos(int index) { + return this.getSourcePos(index, new TilePos()); + } + + public @NotNull TilePosc targetPos(int index) { + return this.getTargetPos(index, new TilePos()); + } + + public @NotNull TilePos getSourcePos(int index, @NotNull TilePos qpos) { + assert index >= 0 && index < this.len; + qpos.set(this.origin); + this.direction.offsetScaled(qpos, index); + return qpos; + } + + public @NotNull TilePos getTargetPos(int index, @NotNull TilePos qpos) { + assert index >= 0 && index < this.len; + qpos.set(this.origin).add(this.movingDirection()); + this.direction.offsetScaled(qpos, index); + return qpos; + } + + private boolean canBlockBePowered(int i, @NotNull TilePos qpos) { + return this.blocks[i].getMaterial().isSolidBlocking() && + // the only implementers of this only reads block data + // TODO refactor this and world.isBlockNormalCube to use a dedicated method + this.blocks[i].renderAsNormalBlockOnCondition(this.world, this.getTargetPos(i, qpos)); +} + + private void setPowered(int i, boolean f) { + if (f) { + this.signalMask |= 1L << i; + this.signalMask &= (1L << this.len) - 1; + } else { + this.signalMask &= ~(1L << i); + } + } + + public void notifyBlocksOfNeighborChange(int index, @Nullable Block source) { + assert index >= 0 && index < this.len; + if (source == null) source = this.blocks[index]; + + final var qpos = new TilePos(); + this.notifyBlockOfNeighborChange(index - 1, qpos, this.blocks[index]); + this.notifyBlockOfNeighborChange(index + 1, qpos, this.blocks[index]); + } + + public void notifyBlocksInRadiusOfNeighborChange(int radius, int index, @NotNull Block source) { + assert index >= 0 && index < this.len; + if (radius <= 0) return; + if (source == null) source = this.blocks[index]; + + final var qpos = new TilePos(); + for (int i = Math.max(0, index - radius); i < index; i++) { + this.notifyBlockOfNeighborChange(i, qpos, source); + } + + for (int i = index + 1; i < Math.min(this.len, index + radius + 1); i++) { + this.notifyBlockOfNeighborChange(i, qpos, source); + } + } + + private void notifyBlockOfNeighborChange(int i, @NotNull TilePos qpos, @NotNull Block source) { + if (i < 0 || i >= this.len) return; + this.getTargetPos(i, qpos); + this.blocks[i].onMovingNeighborChanged(world, qpos, this.movingBlocks[i], i, this, source); + } + + @NotNull TileEntityMovingPistonBlock createMoving(int index) { + assert index >= 0 && index < this.len; + return this.movingBlocks[index] = new TileEntityMovingPistonBlock( + (this.isExtending) ? MovingType.EXTENDING : MovingType.RETRACTING, + this.blocks[index], this.data[index], this.entities[index], this.direction); + } +} diff --git a/game/core/src/main/java/net/minecraft/core/block/piston/PistonCommon.java b/game/core/src/main/java/net/minecraft/core/block/piston/PistonCommon.java index 568e7f29c..7c628eb80 100644 --- a/game/core/src/main/java/net/minecraft/core/block/piston/PistonCommon.java +++ b/game/core/src/main/java/net/minecraft/core/block/piston/PistonCommon.java @@ -72,13 +72,7 @@ public abstract class PistonCommon { public static final int DATA_INVALID = ~0; - public static int fixLegacyBaseData(@NotNull World world, @NotNull TilePosc basePos) { - final var baseBlock = world.getBlockType(basePos); - final BlockLogicPistonBase base; - assert baseBlock.getLogic() instanceof BlockLogicPistonBase; - base = (BlockLogicPistonBase) baseBlock.getLogic(); - - int baseData = world.getBlockData(basePos); + public static int fixLegacyBaseData(@NotNull World world, @NotNull TilePosc basePos, @NotNull BlockLogicPistonBase base, int baseData) { if (NEW_FORMAT_SIGNATURE.bool(baseData)) return baseData; baseData = TYPE.set(baseData, base.typeId); @@ -117,12 +111,26 @@ public abstract class PistonCommon { baseData = IS_EXTENDED.set(baseData, 1); } - world.setBlockData(basePos, baseData); + return baseData; + } + + public static int fixLegacyBaseData(@NotNull World world, @NotNull TilePosc basePos) { + final var baseBlock = world.getBlockType(basePos); + final BlockLogicPistonBase base; + assert baseBlock.getLogic() instanceof BlockLogicPistonBase; + base = (BlockLogicPistonBase) baseBlock.getLogic(); + + int baseData = world.getBlockData(basePos); + int newBaseData = fixLegacyBaseData(world, basePos, base, baseData); + if (newBaseData == baseData) return newBaseData; + + world.setBlockData(basePos, newBaseData); return baseData; } public static int validateBaseData(int data, @NotNull BlockLogicPistonBase base) { data = TYPE.set(data, base.typeId); + data = NEW_FORMAT_SIGNATURE.set(data, 1); if (DIRECTION.get(data) > 5) data = DIRECTION.set(data, 0); // if (IS_DETACHED.bool(data)) data = IS_EXTENDED.set(data, 1); return data; diff --git a/game/core/src/main/java/net/minecraft/core/block/piston/TileEntityMovingPistonBlock.java b/game/core/src/main/java/net/minecraft/core/block/piston/TileEntityMovingPistonBlock.java index cdde69de5..f45c1cad8 100644 --- a/game/core/src/main/java/net/minecraft/core/block/piston/TileEntityMovingPistonBlock.java +++ b/game/core/src/main/java/net/minecraft/core/block/piston/TileEntityMovingPistonBlock.java @@ -2,6 +2,7 @@ package net.minecraft.core.block.piston; import net.minecraft.core.block.entity.TileEntity; import net.minecraft.core.block.entity.TileEntityDispatcher; +import net.minecraft.core.block.piston.PistonCommon.MovingType; import net.minecraft.core.block.Block; import net.minecraft.core.block.Blocks; import net.minecraft.core.util.helper.Direction; @@ -19,10 +20,13 @@ import org.joml.primitives.AABBdc; import java.util.*; import static net.minecraft.core.block.piston.PistonCommon.*; -public class TileEntityMovingPistonBlock extends TileEntity -{ +/** + * TODO: make movingTileEntity tick the moving block + */ +public class TileEntityMovingPistonBlock extends TileEntity implements IMovingBlock { public static final int TICKS_TO_EXTEND = 2; private static final float PROGRESS_DELTA = 1f / TICKS_TO_EXTEND; + private static final float VPROGRESS_DELTA = 1f / (TICKS_TO_EXTEND + 1); @NotNull Block movingBlock; int movingBlockData; @@ -31,6 +35,8 @@ public class TileEntityMovingPistonBlock extends TileEntity @NotNull Direction direction; boolean isExtending; boolean isSourcePiston; + int lifetime = 0; + long lastTick; float progressCur = 0F, progressPrev = 0F; // these would otherwise be reallocated each tick, might as well store them here @@ -89,7 +95,7 @@ public class TileEntityMovingPistonBlock extends TileEntity this.initCollision(); } - private final void initCollision() { + private void initCollision() { assert this.worldObj != null; assert this.worldObj.isChunkLoaded(new ChunkPos(this.tilePos)); @@ -113,12 +119,10 @@ public class TileEntityMovingPistonBlock extends TileEntity @Override public void tick() { if (!this.isCollisionInited) this.initCollision(); - this.progressPrev = this.progressCur; - if (this.progressCur > (1.0F - 0x1p-12F)) { + this.lastTick = this.worldObj.getWorldTime(); + if (this.lifetime ++ >= TICKS_TO_EXTEND) { this.finalTick(); } else { - this.progressCur += PROGRESS_DELTA; - this.sweptCollision.set(this.collision); this.sweptCollision.translate(this.directionScaled); this.sweptCollision.union(this.collision); @@ -137,14 +141,18 @@ public class TileEntityMovingPistonBlock extends TileEntity public float progress(float partialTick) { partialTick = Math.min(partialTick, 1.0F); - return this.progressPrev + (this.progressCur - this.progressPrev) * partialTick; + final var progressPrev = this.lifetime * VPROGRESS_DELTA; + return progressPrev + VPROGRESS_DELTA * partialTick; } public float progressSigned(float partialTick) { final var p = this.progress(partialTick); - return (this.isExtending) - ? p - 1.0F - : 1.0F - p; + return (this.isExtending) ? p - 1.0F : 1.0F - p; + } + + public boolean isInFinalTick() { + if (this.lifetime < TICKS_TO_EXTEND) return false; + return this.lastTick + 1 >= this.worldObj.getWorldTime(); } public float xOffset(float partialTick) { @@ -173,10 +181,12 @@ public class TileEntityMovingPistonBlock extends TileEntity this.movingTileEntity.validate(); this.worldObj.replaceTileEntity(selfPos, this.movingTileEntity); } - - Block.disableNormalEntityLogic = true; - this.movingBlock.onPlacedByWorld(this.worldObj, selfPos); - Block.disableNormalEntityLogic = false; + + this.movingBlock.onMoveComplete(worldObj, selfPos); + + // Block.disableNormalEntityLogic = true; + // this.movingBlock.onPlacedByWorld(this.worldObj, selfPos); + // Block.disableNormalEntityLogic = false; assert this.movingTileEntity == null || this.worldObj.getTileEntity(selfPos) == this.movingTileEntity : "Piston failed to actually move entity!"; @@ -193,7 +203,8 @@ public class TileEntityMovingPistonBlock extends TileEntity this.movingTileEntity = TileEntityDispatcher.createAndLoadEntity(entityTag); } this.direction = Direction.fromId(compoundTag.getInteger("facing")); - this.progressPrev = this.progressCur = compoundTag.getFloat("progress"); + this.lifetime = compoundTag.getInteger("lifetime"); + // this.progressPrev = this.progressCur = compoundTag.getFloat("progress"); this.isExtending = compoundTag.getBoolean("extending"); } @@ -207,7 +218,37 @@ public class TileEntityMovingPistonBlock extends TileEntity compoundTag.put("tileEntity", entityTag); } compoundTag.putInt("facing", this.direction.id); - compoundTag.putFloat("progress", this.progressPrev); + compoundTag.putInt("lifetime", this.lifetime); compoundTag.putBoolean("extending", this.isExtending); } + @Override + public @NotNull Block getBlockType() { + return this.movingBlock; + } + + @Override + public int getBlockData() { + return this.movingBlockData; + } + + @Override + public @Nullable TileEntity getTileEntity() { + return this.movingTileEntity; + } + + @Override + public void setBlockType(@NotNull Block block) { + this.movingBlock = block; + } + + @Override + public void setBlockData(int data) { + this.movingBlockData = data; + this.worldObj.setBlockData(this.tilePos, data); + } + + @Override + public void setTileEntity(@Nullable TileEntity tileEntity) { + this.movingTileEntity = tileEntity; + } } diff --git a/game/core/src/main/java/net/minecraft/core/entity/EntityFallingBlock.java b/game/core/src/main/java/net/minecraft/core/entity/EntityFallingBlock.java index d6577933a..e4f2f14cd 100644 --- a/game/core/src/main/java/net/minecraft/core/entity/EntityFallingBlock.java +++ b/game/core/src/main/java/net/minecraft/core/entity/EntityFallingBlock.java @@ -181,15 +181,13 @@ public class EntityFallingBlock extends Entity !this.fallChecker.canFallInto(this.world, this.carriedBlock, blockPos.down(new TilePos())); final boolean isPlaced = shoudPlaceHere && - this.world.setBlockType(blockPos, Blocks.getBlock(this.carriedBlock.blockId)); + this.world.setBlockTypeData(blockPos, this.carriedBlock.block(), this.carriedBlock.metadata); if (!isPlaced) { this.drop(); break fall_or_drop; } - this.world.setBlockData(blockPos, this.carriedBlock.metadata); - final var tileEntity = this.carriedBlock.entity; if (tileEntity != null) { tileEntity.validate(); @@ -203,6 +201,11 @@ public class EntityFallingBlock extends Entity } } + // TODO there needs to be a smarter way of doing this :| + Block.disableNormalEntityLogic = true; + this.carriedBlock.block().onPlacedByWorld(world, blockPos); + Block.disableNormalEntityLogic = false; + this.world.notifyBlockChange(blockPos, this.carriedBlock.block()); } diff --git a/game/core/src/main/java/net/minecraft/core/world/World.java b/game/core/src/main/java/net/minecraft/core/world/World.java index ad34e9345..8677e4835 100644 --- a/game/core/src/main/java/net/minecraft/core/world/World.java +++ b/game/core/src/main/java/net/minecraft/core/world/World.java @@ -2537,15 +2537,16 @@ public abstract class World implements MutableWorldSource { public boolean hasSignal(final @NotNull TilePosc tilePos, final @NotNull Side side) { final @NotNull Block block = this.getBlockType(tilePos); - if (this.isBlockNormalCube(tilePos) && block != Blocks.BLOCK_REDSTONE && block != Blocks.PUMPKIN_REDSTONE && block != Blocks.MATCHER_ACTIVE) { - return this.hasDirectSignal(tilePos); + if (this.isBlockNormalCube(tilePos)) direct_sig: { + if (block == Blocks.BLOCK_REDSTONE) break direct_sig; + if (block == Blocks.PUMPKIN_REDSTONE) break direct_sig; + if (block == Blocks.MATCHER_ACTIVE) break direct_sig; + if (this.hasDirectSignal(tilePos)) return true; } - if (block == Blocks.PUMPKIN_REDSTONE) { - return this.pumpkinHasDirectSignal(tilePos) || block.isEmittingSignal(this, tilePos, side); - } else { - return block.isEmittingSignal(this, tilePos, side); + if (this.pumpkinHasDirectSignal(tilePos)) return true; } + return block.isEmittingSignal(this, tilePos, side); } @Deprecated @@ -2553,8 +2554,9 @@ public abstract class World implements MutableWorldSource { return this.hasSignal(new TilePos(x, y, z), side); } + // TODO: generalize direct signal face exclusion // Special version of hasDirectSignal that excludes the front side of the redstone lantern. - private boolean pumpkinHasDirectSignal(final @NotNull TilePosc tilePos) { + public boolean pumpkinHasDirectSignal(final @NotNull TilePosc tilePos) { for (final @NotNull Side side : Side.sides) { if (Side.fromId(this.getBlockData(tilePos)) == side) { continue;