How the turns have loot-tabled

- Track curves now drop items when destroyed
- Track curves now spawn particles when destroyed
- Fixed tamed wolves not accepting schedules when driving a train
- Fixed girders not being consumed when placing girder tracks
- Fixed break-overlay of connected tracks not going away after track is destroyed
This commit is contained in:
simibubi 2022-05-04 14:59:55 +02:00
parent 0f2b28a2ad
commit 70bbf94e00
11 changed files with 151 additions and 16 deletions

View file

@ -5259,6 +5259,7 @@ d063e12c9ef75f39518c6d129ea35d833464d547 data/create/tags/items/toolboxes.json
6eec92869baa44d3ac53aec6a7a92c15147b59f0 data/forge/tags/blocks/ores/zinc.json 6eec92869baa44d3ac53aec6a7a92c15147b59f0 data/forge/tags/blocks/ores/zinc.json
9fc688d8fac1033c7b8f4b8de1138e56d2faf527 data/forge/tags/blocks/ores_in_ground/deepslate.json 9fc688d8fac1033c7b8f4b8de1138e56d2faf527 data/forge/tags/blocks/ores_in_ground/deepslate.json
d5ea262a0f5fb210612d22521818e26cf08e591a data/forge/tags/blocks/ores_in_ground/stone.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 66065a698fca917446a0fb766593dbcc77fabeac data/forge/tags/blocks/storage_blocks.json
ff1900963bc4cd8ceffa78d58ef1952ceacb2fb7 data/forge/tags/blocks/storage_blocks/brass.json ff1900963bc4cd8ceffa78d58ef1952ceacb2fb7 data/forge/tags/blocks/storage_blocks/brass.json
823d05187626797205381d4620a84abda3bc8f89 data/forge/tags/blocks/storage_blocks/raw_zinc.json 823d05187626797205381d4620a84abda3bc8f89 data/forge/tags/blocks/storage_blocks/raw_zinc.json

View file

@ -0,0 +1,6 @@
{
"replace": false,
"values": [
"create:track"
]
}

View file

@ -1344,6 +1344,7 @@ public class AllBlocks {
.addLayer(() -> RenderType::cutoutMipped) .addLayer(() -> RenderType::cutoutMipped)
.transform(pickaxeOnly()) .transform(pickaxeOnly())
.blockstate(new TrackBlockStateGenerator()::generate) .blockstate(new TrackBlockStateGenerator()::generate)
.tag(AllBlockTags.RELOCATION_NOT_SUPPORTED.tag)
.lang("Train Track") .lang("Train Track")
.item(TrackBlockItem::new) .item(TrackBlockItem::new)
.model((c, p) -> p.generated(c, Create.asResource("item/" + c.getName()))) .model((c, p) -> p.generated(c, Create.asResource("item/" + c.getName())))

View file

@ -5,6 +5,7 @@ import java.util.Iterator;
import com.jozufozu.flywheel.util.transform.TransformStack; import com.jozufozu.flywheel.util.transform.TransformStack;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.PoseStack.Pose; 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.content.logistics.trains.track.TrackRenderer;
import com.simibubi.create.foundation.utility.Couple; import com.simibubi.create.foundation.utility.Couple;
import com.simibubi.create.foundation.utility.Iterate; 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.BlockPos;
import net.minecraft.core.Direction.Axis; 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.CompoundTag;
import net.minecraft.nbt.NbtUtils; import net.minecraft.nbt.NbtUtils;
import net.minecraft.nbt.Tag; import net.minecraft.nbt.Tag;
import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.util.Mth; 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.AABB;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.Dist;
@ -57,7 +66,8 @@ public class BezierConnection implements Iterable<BezierConnection.Segment> {
} }
public BezierConnection secondary() { 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) { public BezierConnection(CompoundTag compound, BlockPos localTo) {
@ -286,6 +296,62 @@ public class BezierConnection implements Iterable<BezierConnection.Segment> {
return new Bezierator(this, offset); 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 static class Segment {
public int index; public int index;

View file

@ -1,5 +1,6 @@
package com.simibubi.create.content.logistics.trains.management.schedule; package com.simibubi.create.content.logistics.trains.management.schedule;
import com.simibubi.create.AllItems;
import com.simibubi.create.AllSoundEvents; import com.simibubi.create.AllSoundEvents;
import com.simibubi.create.content.contraptions.components.structureMovement.Contraption; import com.simibubi.create.content.contraptions.components.structureMovement.Contraption;
import com.simibubi.create.content.logistics.trains.entity.CarriageContraption; 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.core.BlockPos;
import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionHand;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.animal.Wolf;
import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraftforge.event.entity.player.PlayerInteractEvent.EntityInteract; import net.minecraftforge.event.entity.player.PlayerInteractEvent.EntityInteract;
@ -30,6 +32,14 @@ public class ScheduleItemRetrieval {
Entity rootVehicle = entity.getRootVehicle(); Entity rootVehicle = entity.getRootVehicle();
if (!(rootVehicle instanceof CarriageContraptionEntity)) if (!(rootVehicle instanceof CarriageContraptionEntity))
return; 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) if (player.level.isClientSide)
return; return;
if (event.getHand() == InteractionHand.OFF_HAND) 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"), train.runtime.isAutoSchedule ? "schedule.auto_removed_from_train" : "schedule.removed_from_train"),
true); true);
player.getInventory().placeItemBackInInventory(train.runtime.returnSchedule()); player.getInventory()
.placeItemBackInInventory(train.runtime.returnSchedule());
// player.setItemInHand(event.getHand(), train.runtime.returnSchedule()); // player.setItemInHand(event.getHand(), train.runtime.returnSchedule());
event.setCanceled(true); event.setCanceled(true);
return; return;

View file

@ -1,6 +1,8 @@
package com.simibubi.create.content.logistics.trains.track; package com.simibubi.create.content.logistics.trains.track;
import com.simibubi.create.AllSoundEvents;
import com.simibubi.create.Create; 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.content.logistics.trains.TrackPropagator;
import com.simibubi.create.foundation.networking.TileEntityConfigurationPacket; import com.simibubi.create.foundation.networking.TileEntityConfigurationPacket;
@ -16,11 +18,13 @@ public class CurvedTrackDestroyPacket extends TileEntityConfigurationPacket<Trac
private BlockPos targetPos; private BlockPos targetPos;
private BlockPos soundSource; private BlockPos soundSource;
private boolean wrench;
public CurvedTrackDestroyPacket(BlockPos pos, BlockPos targetPos, BlockPos soundSource) { public CurvedTrackDestroyPacket(BlockPos pos, BlockPos targetPos, BlockPos soundSource, boolean wrench) {
super(pos); super(pos);
this.targetPos = targetPos; this.targetPos = targetPos;
this.soundSource = soundSource; this.soundSource = soundSource;
this.wrench = wrench;
} }
public CurvedTrackDestroyPacket(FriendlyByteBuf buffer) { public CurvedTrackDestroyPacket(FriendlyByteBuf buffer) {
@ -31,12 +35,14 @@ public class CurvedTrackDestroyPacket extends TileEntityConfigurationPacket<Trac
protected void writeSettings(FriendlyByteBuf buffer) { protected void writeSettings(FriendlyByteBuf buffer) {
buffer.writeBlockPos(targetPos); buffer.writeBlockPos(targetPos);
buffer.writeBlockPos(soundSource); buffer.writeBlockPos(soundSource);
buffer.writeBoolean(wrench);
} }
@Override @Override
protected void readSettings(FriendlyByteBuf buffer) { protected void readSettings(FriendlyByteBuf buffer) {
targetPos = buffer.readBlockPos(); targetPos = buffer.readBlockPos();
soundSource = buffer.readBlockPos(); soundSource = buffer.readBlockPos();
wrench = buffer.readBoolean();
} }
@Override @Override
@ -48,6 +54,9 @@ public class CurvedTrackDestroyPacket extends TileEntityConfigurationPacket<Trac
} }
Level level = te.getLevel(); Level level = te.getLevel();
BezierConnection bezierConnection = te.getConnections()
.get(targetPos);
te.removeConnection(targetPos); te.removeConnection(targetPos);
if (level.getBlockEntity(targetPos)instanceof TrackTileEntity other) if (level.getBlockEntity(targetPos)instanceof TrackTileEntity other)
other.removeConnection(pos); other.removeConnection(pos);
@ -55,6 +64,15 @@ public class CurvedTrackDestroyPacket extends TileEntityConfigurationPacket<Trac
BlockState blockState = te.getBlockState(); BlockState blockState = te.getBlockState();
TrackPropagator.onRailRemoved(level, pos, blockState); TrackPropagator.onRailRemoved(level, pos, blockState);
if (wrench) {
AllSoundEvents.WRENCH_REMOVE.playOnServer(player.level, soundSource, 1,
Create.RANDOM.nextFloat() * .5f + .5f);
if (!player.isCreative() && bezierConnection != null)
bezierConnection.addItemsToPlayer(player);
} else if (!player.isCreative() && bezierConnection != null)
bezierConnection.spawnItems(level);
bezierConnection.spawnDestroyParticles(level);
SoundType soundtype = blockState.getSoundType(level, pos, player); SoundType soundtype = blockState.getSoundType(level, pos, player);
if (soundtype == null) if (soundtype == null)
return; return;

View file

@ -1,6 +1,7 @@
package com.simibubi.create.content.logistics.trains.track; package com.simibubi.create.content.logistics.trains.track;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllItems;
import com.simibubi.create.content.logistics.trains.management.edgePoint.TrackTargetingBlockItem; import com.simibubi.create.content.logistics.trains.management.edgePoint.TrackTargetingBlockItem;
import com.simibubi.create.content.logistics.trains.track.TrackBlockOutline.BezierPointSelection; import com.simibubi.create.content.logistics.trains.track.TrackBlockOutline.BezierPointSelection;
import com.simibubi.create.foundation.networking.AllPackets; import com.simibubi.create.foundation.networking.AllPackets;
@ -17,6 +18,7 @@ import net.minecraft.core.particles.BlockParticleOption;
import net.minecraft.core.particles.ParticleTypes; import net.minecraft.core.particles.ParticleTypes;
import net.minecraft.sounds.SoundSource; import net.minecraft.sounds.SoundSource;
import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionHand;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.SoundType; import net.minecraft.world.level.block.SoundType;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
@ -38,6 +40,9 @@ public class CurvedTrackInteraction {
LocalPlayer player = mc.player; LocalPlayer player = mc.player;
ClientLevel level = mc.level; ClientLevel level = mc.level;
if (!player.getAbilities().mayBuild)
return;
if (mc.options.keyAttack.isDown() && result != null) { if (mc.options.keyAttack.isDown() && result != null) {
breakPos = result.te() breakPos = result.te()
.getBlockPos(); .getBlockPos();
@ -70,7 +75,7 @@ public class CurvedTrackInteraction {
if (breakProgress >= 1) { if (breakProgress >= 1) {
AllPackets.channel.sendToServer(new CurvedTrackDestroyPacket(breakPos, result.loc() AllPackets.channel.sendToServer(new CurvedTrackDestroyPacket(breakPos, result.loc()
.curveTarget(), new BlockPos(result.vec()))); .curveTarget(), new BlockPos(result.vec()), false));
resetBreakProgress(); resetBreakProgress();
} }
@ -111,13 +116,24 @@ public class CurvedTrackInteraction {
if (event.isUseItem()) { if (event.isUseItem()) {
ItemStack heldItem = player.getMainHandItem(); ItemStack heldItem = player.getMainHandItem();
Item item = heldItem.getItem();
if (AllBlocks.TRACK.isIn(heldItem)) { if (AllBlocks.TRACK.isIn(heldItem)) {
player.displayClientMessage(Lang.translate("track.turn_start") player.displayClientMessage(Lang.translate("track.turn_start")
.withStyle(ChatFormatting.RED), true); .withStyle(ChatFormatting.RED), true);
player.swing(InteractionHand.MAIN_HAND); player.swing(InteractionHand.MAIN_HAND);
return true; 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); player.swing(InteractionHand.MAIN_HAND);
return true; return true;
} }

View file

@ -347,15 +347,22 @@ public class TrackBlock extends Block implements EntityBlock, IWrenchable, ITrac
@Override @Override
public InteractionResult onWrenched(BlockState state, UseOnContext context) { public InteractionResult onWrenched(BlockState state, UseOnContext context) {
// if (context.getLevel().isClientSide)
// TrackRemoval.wrenched(context.getClickedPos());
return InteractionResult.SUCCESS; return InteractionResult.SUCCESS;
} }
@Override @Override
public InteractionResult onSneakWrenched(BlockState state, UseOnContext context) { public InteractionResult onSneakWrenched(BlockState state, UseOnContext context) {
// if (context.getLevel().isClientSide) Player player = context.getPlayer();
// TrackRemoval.sneakWrenched(context.getClickedPos()); 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); return IWrenchable.super.onSneakWrenched(state, context);
} }
@ -492,7 +499,7 @@ public class TrackBlock extends Block implements EntityBlock, IWrenchable, ITrac
BlockEntity blockEntity = level.getBlockEntity(pos); BlockEntity blockEntity = level.getBlockEntity(pos);
if (blockEntity instanceof TrackTileEntity track) if (blockEntity instanceof TrackTileEntity track)
for (BlockPos trackPos : track.connections.keySet()) for (BlockPos trackPos : track.connections.keySet())
renderer.destroyBlockProgress(trackPos.hashCode(), trackPos, progress); renderer.destroyBlockProgress(pos.hashCode(), trackPos, progress);
return false; return false;
} }
} }

View file

@ -90,8 +90,11 @@ public class TrackPaver {
boolean slabLike = defaultBlockState.hasProperty(SlabBlock.TYPE); boolean slabLike = defaultBlockState.hasProperty(SlabBlock.TYPE);
if (slabLike) if (slabLike)
defaultBlockState = defaultBlockState.setValue(SlabBlock.TYPE, SlabType.DOUBLE); 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; return 0;
}
Map<Pair<Integer, Integer>, Double> yLevels = new HashMap<>(); Map<Pair<Integer, Integer>, Double> yLevels = new HashMap<>();
BlockPos tePosition = bc.tePositions.getFirst(); BlockPos tePosition = bc.tePositions.getFirst();

View file

@ -36,6 +36,7 @@ public class TrackTileEntity extends SmartTileEntity implements ITransformableTE
Map<BlockPos, BezierConnection> connections; Map<BlockPos, BezierConnection> connections;
boolean connectionsValidated; boolean connectionsValidated;
boolean cancelDrops;
public TrackTileEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) { public TrackTileEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) {
super(type, pos, state); super(type, pos, state);
@ -86,7 +87,7 @@ public class TrackTileEntity extends SmartTileEntity implements ITransformableTE
if (!connections.isEmpty()) if (!connections.isEmpty())
return; return;
BlockState blockState = getBlockState(); BlockState blockState = level.getBlockState(worldPosition);
if (blockState.hasProperty(TrackBlock.HAS_TURN)) if (blockState.hasProperty(TrackBlock.HAS_TURN))
level.setBlockAndUpdate(worldPosition, blockState.setValue(TrackBlock.HAS_TURN, false)); level.setBlockAndUpdate(worldPosition, blockState.setValue(TrackBlock.HAS_TURN, false));
AllPackets.channel.send(packetTarget(), new RemoveTileEntityPacket(worldPosition)); AllPackets.channel.send(packetTarget(), new RemoveTileEntityPacket(worldPosition));
@ -99,6 +100,10 @@ public class TrackTileEntity extends SmartTileEntity implements ITransformableTE
return; return;
TrackTileEntity other = (TrackTileEntity) blockEntity; TrackTileEntity other = (TrackTileEntity) blockEntity;
other.removeConnection(bezierConnection.tePositions.getFirst()); other.removeConnection(bezierConnection.tePositions.getFirst());
if (!cancelDrops)
bezierConnection.spawnItems(level);
bezierConnection.spawnDestroyParticles(level);
} }
AllPackets.channel.send(packetTarget(), new RemoveTileEntityPacket(worldPosition)); AllPackets.channel.send(packetTarget(), new RemoveTileEntityPacket(worldPosition));
} }

View file

@ -31,6 +31,7 @@ public class DestroyProgressMixin {
if (handler.renderDestroyProgress(self, levelRenderer, breakerId, pos, progress, state)) { if (handler.renderDestroyProgress(self, levelRenderer, breakerId, pos, progress, state)) {
ci.cancel(); ci.cancel();
} }
} } else if (progress == -1)
levelRenderer.destroyBlockProgress(pos.hashCode(), pos, -1);
} }
} }