diff --git a/src/generated/resources/.cache/cache b/src/generated/resources/.cache/cache index 86b31cce9..207cf10bb 100644 --- a/src/generated/resources/.cache/cache +++ b/src/generated/resources/.cache/cache @@ -5259,6 +5259,7 @@ d063e12c9ef75f39518c6d129ea35d833464d547 data/create/tags/items/toolboxes.json 6eec92869baa44d3ac53aec6a7a92c15147b59f0 data/forge/tags/blocks/ores/zinc.json 9fc688d8fac1033c7b8f4b8de1138e56d2faf527 data/forge/tags/blocks/ores_in_ground/deepslate.json d5ea262a0f5fb210612d22521818e26cf08e591a data/forge/tags/blocks/ores_in_ground/stone.json +ad8fa04f7bbbafd70d0ce158af78a35e899301e2 data/forge/tags/blocks/relocation_not_supported.json 66065a698fca917446a0fb766593dbcc77fabeac data/forge/tags/blocks/storage_blocks.json ff1900963bc4cd8ceffa78d58ef1952ceacb2fb7 data/forge/tags/blocks/storage_blocks/brass.json 823d05187626797205381d4620a84abda3bc8f89 data/forge/tags/blocks/storage_blocks/raw_zinc.json diff --git a/src/generated/resources/data/forge/tags/blocks/relocation_not_supported.json b/src/generated/resources/data/forge/tags/blocks/relocation_not_supported.json new file mode 100644 index 000000000..ef33e72ef --- /dev/null +++ b/src/generated/resources/data/forge/tags/blocks/relocation_not_supported.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "create:track" + ] +} \ No newline at end of file diff --git a/src/main/java/com/simibubi/create/AllBlocks.java b/src/main/java/com/simibubi/create/AllBlocks.java index 6bee716a9..004b4da7a 100644 --- a/src/main/java/com/simibubi/create/AllBlocks.java +++ b/src/main/java/com/simibubi/create/AllBlocks.java @@ -1344,6 +1344,7 @@ public class AllBlocks { .addLayer(() -> RenderType::cutoutMipped) .transform(pickaxeOnly()) .blockstate(new TrackBlockStateGenerator()::generate) + .tag(AllBlockTags.RELOCATION_NOT_SUPPORTED.tag) .lang("Train Track") .item(TrackBlockItem::new) .model((c, p) -> p.generated(c, Create.asResource("item/" + c.getName()))) diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/BezierConnection.java b/src/main/java/com/simibubi/create/content/logistics/trains/BezierConnection.java index 2ddf685bd..ad5dcdacb 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/BezierConnection.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/BezierConnection.java @@ -5,6 +5,7 @@ import java.util.Iterator; import com.jozufozu.flywheel.util.transform.TransformStack; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack.Pose; +import com.simibubi.create.AllBlocks; import com.simibubi.create.content.logistics.trains.track.TrackRenderer; import com.simibubi.create.foundation.utility.Couple; import com.simibubi.create.foundation.utility.Iterate; @@ -12,11 +13,19 @@ import com.simibubi.create.foundation.utility.VecHelper; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction.Axis; +import net.minecraft.core.particles.BlockParticleOption; +import net.minecraft.core.particles.ParticleTypes; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.NbtUtils; import net.minecraft.nbt.Tag; import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.server.level.ServerLevel; import net.minecraft.util.Mth; +import net.minecraft.world.entity.item.ItemEntity; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.GameRules; +import net.minecraft.world.level.Level; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; import net.minecraftforge.api.distmarker.Dist; @@ -57,7 +66,8 @@ public class BezierConnection implements Iterable { } public BezierConnection secondary() { - return new BezierConnection(tePositions.swap(), starts.swap(), axes.swap(), normals.swap(), !primary, hasGirder); + return new BezierConnection(tePositions.swap(), starts.swap(), axes.swap(), normals.swap(), !primary, + hasGirder); } public BezierConnection(CompoundTag compound, BlockPos localTo) { @@ -151,7 +161,7 @@ public class BezierConnection implements Iterable { return currentT + distance / dx; } - + public AABB getBounds() { resolve(); return bounds; @@ -286,6 +296,62 @@ public class BezierConnection implements Iterable { return new Bezierator(this, offset); } + public void addItemsToPlayer(Player player) { + Inventory inv = player.getInventory(); + int tracks = (getSegmentCount() + 1) / 2; + while (tracks > 0) { + inv.placeItemBackInInventory(AllBlocks.TRACK.asStack(Math.min(64, tracks))); + tracks -= 64; + } + int girders = hasGirder ? ((getSegmentCount() + 1) / 2) * 2 : 0; + while (girders > 0) { + inv.placeItemBackInInventory(AllBlocks.METAL_GIRDER.asStack(Math.min(64, girders))); + girders -= 64; + } + } + + public void spawnItems(Level level) { + if (!level.getGameRules() + .getBoolean(GameRules.RULE_DOBLOCKDROPS)) + return; + Vec3 origin = Vec3.atLowerCornerOf(tePositions.getFirst()); + for (Segment segment : this) { + if (segment.index % 2 != 0 || segment.index == getSegmentCount()) + continue; + Vec3 v = VecHelper.offsetRandomly(segment.position, level.random, .125f) + .add(origin); + ItemEntity entity = new ItemEntity(level, v.x, v.y, v.z, AllBlocks.TRACK.asStack()); + entity.setDefaultPickUpDelay(); + level.addFreshEntity(entity); + if (!hasGirder) + continue; + for (int i = 0; i < 2; i++) { + entity = new ItemEntity(level, v.x, v.y, v.z, AllBlocks.METAL_GIRDER.asStack()); + entity.setDefaultPickUpDelay(); + level.addFreshEntity(entity); + } + } + } + + public void spawnDestroyParticles(Level level) { + BlockParticleOption data = new BlockParticleOption(ParticleTypes.BLOCK, AllBlocks.TRACK.getDefaultState()); + BlockParticleOption girderData = + new BlockParticleOption(ParticleTypes.BLOCK, AllBlocks.METAL_GIRDER.getDefaultState()); + if (!(level instanceof ServerLevel slevel)) + return; + Vec3 origin = Vec3.atLowerCornerOf(tePositions.getFirst()); + for (Segment segment : this) { + for (int offset : Iterate.positiveAndNegative) { + Vec3 v = segment.position.add(segment.normal.scale(14 / 16f * offset)) + .add(origin); + slevel.sendParticles(data, v.x, v.y, v.z, 1, 0, 0, 0, 0); + if (!hasGirder) + continue; + slevel.sendParticles(girderData, v.x, v.y - .5f, v.z, 1, 0, 0, 0, 0); + } + } + } + public static class Segment { public int index; diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/ScheduleItemRetrieval.java b/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/ScheduleItemRetrieval.java index 99611319e..4518dbc16 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/ScheduleItemRetrieval.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/ScheduleItemRetrieval.java @@ -1,5 +1,6 @@ package com.simibubi.create.content.logistics.trains.management.schedule; +import com.simibubi.create.AllItems; import com.simibubi.create.AllSoundEvents; import com.simibubi.create.content.contraptions.components.structureMovement.Contraption; import com.simibubi.create.content.logistics.trains.entity.CarriageContraption; @@ -11,6 +12,7 @@ import com.simibubi.create.foundation.utility.Lang; import net.minecraft.core.BlockPos; import net.minecraft.world.InteractionHand; import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.animal.Wolf; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraftforge.event.entity.player.PlayerInteractEvent.EntityInteract; @@ -30,6 +32,14 @@ public class ScheduleItemRetrieval { Entity rootVehicle = entity.getRootVehicle(); if (!(rootVehicle instanceof CarriageContraptionEntity)) return; + + ItemStack itemStack = event.getItemStack(); + if (AllItems.SCHEDULE.isIn(itemStack) && entity instanceof Wolf wolf) { + itemStack.getItem() + .interactLivingEntity(itemStack, player, wolf, event.getHand()); + return; + } + if (player.level.isClientSide) return; if (event.getHand() == InteractionHand.OFF_HAND) @@ -70,7 +80,8 @@ public class ScheduleItemRetrieval { train.runtime.isAutoSchedule ? "schedule.auto_removed_from_train" : "schedule.removed_from_train"), true); - player.getInventory().placeItemBackInInventory(train.runtime.returnSchedule()); + player.getInventory() + .placeItemBackInInventory(train.runtime.returnSchedule()); // player.setItemInHand(event.getHand(), train.runtime.returnSchedule()); event.setCanceled(true); return; diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/track/CurvedTrackDestroyPacket.java b/src/main/java/com/simibubi/create/content/logistics/trains/track/CurvedTrackDestroyPacket.java index 5cc721ca6..ab4b2ddce 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/track/CurvedTrackDestroyPacket.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/track/CurvedTrackDestroyPacket.java @@ -1,6 +1,8 @@ package com.simibubi.create.content.logistics.trains.track; +import com.simibubi.create.AllSoundEvents; import com.simibubi.create.Create; +import com.simibubi.create.content.logistics.trains.BezierConnection; import com.simibubi.create.content.logistics.trains.TrackPropagator; import com.simibubi.create.foundation.networking.TileEntityConfigurationPacket; @@ -16,11 +18,13 @@ public class CurvedTrackDestroyPacket extends TileEntityConfigurationPacket= 1) { AllPackets.channel.sendToServer(new CurvedTrackDestroyPacket(breakPos, result.loc() - .curveTarget(), new BlockPos(result.vec()))); + .curveTarget(), new BlockPos(result.vec()), false)); resetBreakProgress(); } @@ -111,13 +116,24 @@ public class CurvedTrackInteraction { if (event.isUseItem()) { ItemStack heldItem = player.getMainHandItem(); + Item item = heldItem.getItem(); if (AllBlocks.TRACK.isIn(heldItem)) { player.displayClientMessage(Lang.translate("track.turn_start") .withStyle(ChatFormatting.RED), true); player.swing(InteractionHand.MAIN_HAND); return true; } - if (heldItem.getItem() instanceof TrackTargetingBlockItem ttbi && ttbi.useOnCurve(result, heldItem)) { + if (item instanceof TrackTargetingBlockItem ttbi && ttbi.useOnCurve(result, heldItem)) { + player.swing(InteractionHand.MAIN_HAND); + return true; + } + if (AllItems.WRENCH.isIn(heldItem) && player.isSteppingCarefully()) { + AllPackets.channel.sendToServer(new CurvedTrackDestroyPacket(result.te() + .getBlockPos(), + result.loc() + .curveTarget(), + new BlockPos(result.vec()), true)); + resetBreakProgress(); player.swing(InteractionHand.MAIN_HAND); return true; } diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/track/TrackBlock.java b/src/main/java/com/simibubi/create/content/logistics/trains/track/TrackBlock.java index 5bd9ad99e..6a9979349 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/track/TrackBlock.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/track/TrackBlock.java @@ -347,15 +347,22 @@ public class TrackBlock extends Block implements EntityBlock, IWrenchable, ITrac @Override public InteractionResult onWrenched(BlockState state, UseOnContext context) { -// if (context.getLevel().isClientSide) -// TrackRemoval.wrenched(context.getClickedPos()); return InteractionResult.SUCCESS; } @Override public InteractionResult onSneakWrenched(BlockState state, UseOnContext context) { -// if (context.getLevel().isClientSide) -// TrackRemoval.sneakWrenched(context.getClickedPos()); + Player player = context.getPlayer(); + Level level = context.getLevel(); + if (!level.isClientSide && !player.isCreative() && state.getValue(HAS_TURN)) { + BlockEntity blockEntity = level.getBlockEntity(context.getClickedPos()); + if (blockEntity instanceof TrackTileEntity trackTE) { + trackTE.cancelDrops = true; + trackTE.connections.values() + .forEach(bc -> bc.addItemsToPlayer(player)); + } + } + return IWrenchable.super.onSneakWrenched(state, context); } @@ -492,7 +499,7 @@ public class TrackBlock extends Block implements EntityBlock, IWrenchable, ITrac BlockEntity blockEntity = level.getBlockEntity(pos); if (blockEntity instanceof TrackTileEntity track) for (BlockPos trackPos : track.connections.keySet()) - renderer.destroyBlockProgress(trackPos.hashCode(), trackPos, progress); + renderer.destroyBlockProgress(pos.hashCode(), trackPos, progress); return false; } } diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/track/TrackPaver.java b/src/main/java/com/simibubi/create/content/logistics/trains/track/TrackPaver.java index 299e6bad1..5fb7a96ef 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/track/TrackPaver.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/track/TrackPaver.java @@ -90,8 +90,11 @@ public class TrackPaver { boolean slabLike = defaultBlockState.hasProperty(SlabBlock.TYPE); if (slabLike) defaultBlockState = defaultBlockState.setValue(SlabBlock.TYPE, SlabType.DOUBLE); - if (isWallLike(defaultBlockState)) + if (isWallLike(defaultBlockState)) { + if (AllBlocks.METAL_GIRDER.has(defaultBlockState)) + return ((bc.getSegmentCount() + 1) / 2) * 2; return 0; + } Map, Double> yLevels = new HashMap<>(); BlockPos tePosition = bc.tePositions.getFirst(); diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/track/TrackTileEntity.java b/src/main/java/com/simibubi/create/content/logistics/trains/track/TrackTileEntity.java index 016e0667c..284359632 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/track/TrackTileEntity.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/track/TrackTileEntity.java @@ -36,6 +36,7 @@ public class TrackTileEntity extends SmartTileEntity implements ITransformableTE Map connections; boolean connectionsValidated; + boolean cancelDrops; public TrackTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { super(type, pos, state); @@ -86,7 +87,7 @@ public class TrackTileEntity extends SmartTileEntity implements ITransformableTE if (!connections.isEmpty()) return; - BlockState blockState = getBlockState(); + BlockState blockState = level.getBlockState(worldPosition); if (blockState.hasProperty(TrackBlock.HAS_TURN)) level.setBlockAndUpdate(worldPosition, blockState.setValue(TrackBlock.HAS_TURN, false)); AllPackets.channel.send(packetTarget(), new RemoveTileEntityPacket(worldPosition)); @@ -99,6 +100,10 @@ public class TrackTileEntity extends SmartTileEntity implements ITransformableTE return; TrackTileEntity other = (TrackTileEntity) blockEntity; other.removeConnection(bezierConnection.tePositions.getFirst()); + + if (!cancelDrops) + bezierConnection.spawnItems(level); + bezierConnection.spawnDestroyParticles(level); } AllPackets.channel.send(packetTarget(), new RemoveTileEntityPacket(worldPosition)); } diff --git a/src/main/java/com/simibubi/create/foundation/mixin/DestroyProgressMixin.java b/src/main/java/com/simibubi/create/foundation/mixin/DestroyProgressMixin.java index 1dde3aa35..cfad69339 100644 --- a/src/main/java/com/simibubi/create/foundation/mixin/DestroyProgressMixin.java +++ b/src/main/java/com/simibubi/create/foundation/mixin/DestroyProgressMixin.java @@ -31,6 +31,7 @@ public class DestroyProgressMixin { if (handler.renderDestroyProgress(self, levelRenderer, breakerId, pos, progress, state)) { ci.cancel(); } - } + } else if (progress == -1) + levelRenderer.destroyBlockProgress(pos.hashCode(), pos, -1); } }