Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Falling Anvils #5114

Draft
wants to merge 2 commits into
base: 1.18.2
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import slimeknights.tconstruct.library.client.model.block.TableModel;
import slimeknights.tconstruct.shared.block.entity.TableBlockEntity;
import slimeknights.tconstruct.tables.block.entity.chest.TinkersChestBlockEntity;
import slimeknights.tconstruct.tables.client.FallingAnvilEntityRenderer;
import slimeknights.tconstruct.tables.client.TableTileEntityRenderer;
import slimeknights.tconstruct.tables.client.inventory.CraftingStationScreen;
import slimeknights.tconstruct.tables.client.inventory.ModifierWorktableScreen;
Expand All @@ -40,6 +41,8 @@ static void registerRenderers(EntityRenderersEvent.RegisterRenderers event) {
event.registerBlockEntityRenderer(TinkerTables.tinkerStationTile.get(), tableRenderer);
event.registerBlockEntityRenderer(TinkerTables.modifierWorktableTile.get(), tableRenderer);
event.registerBlockEntityRenderer(TinkerTables.partBuilderTile.get(), tableRenderer);

event.registerEntityRenderer(TinkerTables.fallingAnvil.get(), FallingAnvilEntityRenderer::new);
}

@SubscribeEvent
Expand Down
14 changes: 14 additions & 0 deletions src/main/java/slimeknights/tconstruct/tables/TinkerTables.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import net.minecraft.data.DataGenerator;
import net.minecraft.tags.ItemTags;
import net.minecraft.tags.TagKey;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.MobCategory;
import net.minecraft.world.inventory.MenuType;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.crafting.SimpleRecipeSerializer;
Expand Down Expand Up @@ -35,6 +37,7 @@
import slimeknights.tconstruct.tables.block.TinkerStationBlock;
import slimeknights.tconstruct.tables.block.TinkersAnvilBlock;
import slimeknights.tconstruct.tables.block.TinkersChestBlock;
import slimeknights.tconstruct.tables.entity.FallingAnvilEntity;
import slimeknights.tconstruct.tables.block.entity.chest.CastChestBlockEntity;
import slimeknights.tconstruct.tables.block.entity.chest.PartChestBlockEntity;
import slimeknights.tconstruct.tables.block.entity.chest.TinkersChestBlockEntity;
Expand Down Expand Up @@ -106,6 +109,17 @@ public final class TinkerTables extends TinkerModule {
public static final RegistryObject<BlockEntityType<PartChestBlockEntity>> partChestTile = BLOCK_ENTITIES.register("part_chest", PartChestBlockEntity::new, partChest);
public static final RegistryObject<BlockEntityType<CastChestBlockEntity>> castChestTile = BLOCK_ENTITIES.register("cast_chest", CastChestBlockEntity::new, castChest);

/*
* Entities
*/

public static final RegistryObject<EntityType<FallingAnvilEntity>> fallingAnvil = ENTITIES.register("falling_anvil", () ->
EntityType.Builder.<FallingAnvilEntity>of(FallingAnvilEntity::new, MobCategory.MISC)
.sized(0.98F, 0.98F)
.clientTrackingRange(10)
.updateInterval(20)
);

/*
* Containers
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,24 @@

import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.entity.item.FallingBlockEntity;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Fallable;
import net.minecraft.world.level.block.FallingBlock;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.phys.shapes.VoxelShape;
import slimeknights.tconstruct.tables.entity.FallingAnvilEntity;

public class ScorchedAnvilBlock extends TinkerStationBlock {
import java.util.Random;

public class ScorchedAnvilBlock extends TinkerStationBlock implements Fallable {
private static final VoxelShape PART_BASE = Block.box(2.0D, 0.0D, 2.0D, 14.0D, 4.0D, 14.0D);
private static final VoxelShape X_AXIS_AABB = Shapes.or(
PART_BASE,
Expand All @@ -34,4 +44,58 @@ public VoxelShape getShape(BlockState state, BlockGetter worldIn, BlockPos pos,
Direction direction = state.getValue(FACING);
return direction.getAxis() == Direction.Axis.X ? X_AXIS_AABB : Z_AXIS_AABB;
}

@Override
public void onPlace(BlockState pState, Level pLevel, BlockPos pPos, BlockState pOldState, boolean pIsMoving) {
pLevel.scheduleTick(pPos, this, this.getDelayAfterPlace());
}

@Override
public BlockState updateShape(BlockState pState, Direction pFacing, BlockState pFacingState, LevelAccessor pLevel, BlockPos pCurrentPos, BlockPos pFacingPos) {
pLevel.scheduleTick(pCurrentPos, this, this.getDelayAfterPlace());
return super.updateShape(pState, pFacing, pFacingState, pLevel, pCurrentPos, pFacingPos);
}

@Override
public void tick(BlockState pState, ServerLevel pLevel, BlockPos pPos, Random pRand) {
if (FallingBlock.isFree(pLevel.getBlockState(pPos.below())) && pPos.getY() >= pLevel.getMinBuildHeight()) {
FallingAnvilEntity fallingblockentity = FallingAnvilEntity.fall(pLevel, pPos, pState);
fallingblockentity.setHurtsEntities(2.0F, 40);
}
}

public int getDelayAfterPlace() {
return 2;
}

@Override
public void onLand(Level p_48793_, BlockPos p_48794_, BlockState p_48795_, BlockState p_48796_, FallingBlockEntity p_48797_) {
if (!p_48797_.isSilent()) {
p_48793_.levelEvent(1031, p_48794_, 0);
}

}

@Override
public void onBrokenAfterFall(Level pLevel, BlockPos pPos, FallingBlockEntity pFallingBlock) {
if (!pFallingBlock.isSilent()) {
pLevel.levelEvent(1029, pPos, 0);
}

}

@Override
public DamageSource getFallDamageSource() {
return DamageSource.ANVIL;
}

@Override
public void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
if (!isMoving) {
super.onRemove(state, level, pos, newState, isMoving);
}
if (state.hasBlockEntity() && (!state.is(newState.getBlock()) || !newState.hasBlockEntity())) {
level.removeBlockEntity(pos);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,24 @@

import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.entity.item.FallingBlockEntity;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Fallable;
import net.minecraft.world.level.block.FallingBlock;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.phys.shapes.VoxelShape;
import slimeknights.tconstruct.tables.entity.FallingAnvilEntity;

public class TinkersAnvilBlock extends TinkerStationBlock {
import java.util.Random;

public class TinkersAnvilBlock extends TinkerStationBlock implements Fallable {
private static final VoxelShape PART_BASE = Block.box(2.0D, 0.0D, 2.0D, 14.0D, 4.0D, 14.0D);
private static final VoxelShape X_AXIS_AABB = Shapes.or(
PART_BASE,
Expand All @@ -31,4 +41,58 @@ public VoxelShape getShape(BlockState state, BlockGetter worldIn, BlockPos pos,
Direction direction = state.getValue(FACING);
return direction.getAxis() == Direction.Axis.X ? X_AXIS_AABB : Z_AXIS_AABB;
}

@Override
public void onPlace(BlockState pState, Level pLevel, BlockPos pPos, BlockState pOldState, boolean pIsMoving) {
pLevel.scheduleTick(pPos, this, this.getDelayAfterPlace());
}

@Override
public BlockState updateShape(BlockState pState, Direction pFacing, BlockState pFacingState, LevelAccessor pLevel, BlockPos pCurrentPos, BlockPos pFacingPos) {
pLevel.scheduleTick(pCurrentPos, this, this.getDelayAfterPlace());
return super.updateShape(pState, pFacing, pFacingState, pLevel, pCurrentPos, pFacingPos);
}

@Override
public void tick(BlockState pState, ServerLevel pLevel, BlockPos pPos, Random pRand) {
if (FallingBlock.isFree(pLevel.getBlockState(pPos.below())) && pPos.getY() >= pLevel.getMinBuildHeight()) {
FallingAnvilEntity fallingblockentity = FallingAnvilEntity.fall(pLevel, pPos, pState);
fallingblockentity.setHurtsEntities(2.0F, 40);
}
}

public int getDelayAfterPlace() {
return 2;
}

@Override
public void onLand(Level p_48793_, BlockPos p_48794_, BlockState p_48795_, BlockState p_48796_, FallingBlockEntity p_48797_) {
if (!p_48797_.isSilent()) {
p_48793_.levelEvent(1031, p_48794_, 0);
}

}

@Override
public void onBrokenAfterFall(Level pLevel, BlockPos pPos, FallingBlockEntity pFallingBlock) {
if (!pFallingBlock.isSilent()) {
pLevel.levelEvent(1029, pPos, 0);
}

}

@Override
public DamageSource getFallDamageSource() {
return DamageSource.ANVIL;
}

@Override
public void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
if (!isMoving) {
super.onRemove(state, level, pos, newState, isMoving);
}
if (state.hasBlockEntity() && (!state.is(newState.getBlock()) || !newState.hasBlockEntity())) {
level.removeBlockEntity(pos);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package slimeknights.tconstruct.tables.client;

import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.ItemBlockRenderTypes;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.block.BlockRenderDispatcher;
import net.minecraft.client.renderer.entity.EntityRenderer;
import net.minecraft.client.renderer.entity.EntityRendererProvider;
import net.minecraft.client.renderer.texture.OverlayTexture;
import net.minecraft.client.renderer.texture.TextureAtlas;
import net.minecraft.core.BlockPos;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraftforge.client.model.data.IModelData;
import slimeknights.tconstruct.tables.entity.FallingAnvilEntity;

import java.util.Random;

public class FallingAnvilEntityRenderer extends EntityRenderer<FallingAnvilEntity> {

public FallingAnvilEntityRenderer(EntityRendererProvider.Context p_174008_) {
super(p_174008_);
}

@Override
public void render(FallingAnvilEntity pEntity, float pEntityYaw, float pPartialTicks, PoseStack pMatrixStack, MultiBufferSource pBuffer, int pPackedLight) {
BlockState blockstate = pEntity.getBlockState();
Level level = pEntity.getLevel();
pMatrixStack.pushPose();
BlockPos blockpos = new BlockPos(pEntity.getX(), pEntity.getBoundingBox().maxY, pEntity.getZ());
pMatrixStack.translate(-0.5D, 0.0D, -0.5D);
IModelData modelData = pEntity.getModelData();
BlockRenderDispatcher blockrenderdispatcher = Minecraft.getInstance().getBlockRenderer();
for (net.minecraft.client.renderer.RenderType type : net.minecraft.client.renderer.RenderType.chunkBufferLayers()) {
if (ItemBlockRenderTypes.canRenderInLayer(blockstate, type)) {
net.minecraftforge.client.ForgeHooksClient.setRenderType(type);
blockrenderdispatcher.getModelRenderer().tesselateBlock(level, blockrenderdispatcher.getBlockModel(blockstate), blockstate, blockpos, pMatrixStack, pBuffer.getBuffer(type), false, new Random(), blockstate.getSeed(pEntity.getStartPos()), OverlayTexture.NO_OVERLAY, modelData);
}
}
net.minecraftforge.client.ForgeHooksClient.setRenderType(null);
pMatrixStack.popPose();
super.render(pEntity, pEntityYaw, pPartialTicks, pMatrixStack, pBuffer, pPackedLight);
}

@Override
public ResourceLocation getTextureLocation(FallingAnvilEntity pEntity) {
return TextureAtlas.LOCATION_BLOCKS;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
package slimeknights.tconstruct.tables.entity;

import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.game.ClientboundAddEntityPacket;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.item.FallingBlockEntity;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.client.model.data.IModelData;
import net.minecraftforge.entity.IEntityAdditionalSpawnData;
import net.minecraftforge.network.NetworkHooks;
import slimeknights.mantle.client.model.data.SinglePropertyData;
import slimeknights.mantle.util.RetexturedHelper;
import slimeknights.tconstruct.tables.TinkerTables;
import slimeknights.tconstruct.tables.block.entity.table.RetexturedTableBlockEntity;

public class FallingAnvilEntity extends FallingBlockEntity implements IEntityAdditionalSpawnData {

private String textureName;

public FallingAnvilEntity(EntityType<FallingAnvilEntity> entityType, Level level) {
super(TinkerTables.fallingAnvil.get(), level);
}

public FallingAnvilEntity(Level level, double x, double y, double z, BlockState state, BlockPos pos) {
super(TinkerTables.fallingAnvil.get(), level);
this.blockState = state;
this.blocksBuilding = true;
this.setPos(x, y, z);
this.setDeltaMovement(Vec3.ZERO);
this.xo = x;
this.yo = y;
this.zo = z;
this.setStartPos(this.blockPosition());
if (level.getBlockEntity(pos) instanceof RetexturedTableBlockEntity entity) {
this.textureName = entity.getTextureName();
this.blockData = entity.saveWithFullMetadata();
}
}


public static FallingAnvilEntity fall(Level level, BlockPos pos, BlockState state) {
FallingAnvilEntity anvil = new FallingAnvilEntity(level, pos.getX() + 0.5D, pos.getY(), pos.getZ() + 0.5D, state.hasProperty(BlockStateProperties.WATERLOGGED) ? state.setValue(BlockStateProperties.WATERLOGGED, false) : state, pos);
level.setBlock(pos, state.getFluidState().createLegacyBlock(), 67);
level.addFreshEntity(anvil);
return anvil;
}

@Override
public BlockState getBlockState() {
return blockState;
}

public IModelData getModelData() {
return getRetexturedModelData();
}

public IModelData getRetexturedModelData() {
// texture not loaded
Block block = RetexturedHelper.getBlock(this.textureName);
// cannot support air, saves a conditional on usage
if (block == Blocks.AIR) {
block = null;
}
return new SinglePropertyData<>(RetexturedHelper.BLOCK_PROPERTY, block);
}

@Override
protected void addAdditionalSaveData(CompoundTag pCompound) {
pCompound.putString("textureName", textureName);
super.addAdditionalSaveData(pCompound);
}

@Override
public void readAdditionalSaveData(CompoundTag pCompound) {
this.textureName = pCompound.getString("textureName");
super.load(pCompound);
}

public Packet<?> getAddEntityPacket() {
return NetworkHooks.getEntitySpawningPacket(this);
}

@Override
public void recreateFromPacket(ClientboundAddEntityPacket pPacket) {
super.recreateFromPacket(pPacket);
this.blocksBuilding = true;
double d0 = pPacket.getX();
double d1 = pPacket.getY();
double d2 = pPacket.getZ();
this.setPos(d0, d1, d2);
this.setStartPos(this.blockPosition());
}

@Override
public void writeSpawnData(FriendlyByteBuf buffer) {
buffer.writeInt(Block.getId(this.blockState));
buffer.writeUtf(this.textureName);
//buffer.writeNbt(blockData);
}

@Override
public void readSpawnData(FriendlyByteBuf additionalData) {
this.blockState = Block.stateById(additionalData.readInt());
this.textureName = additionalData.readUtf();
//this.blockData = additionalData.readNbt();
}
}
3 changes: 3 additions & 0 deletions src/main/resources/META-INF/accesstransformer.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -233,3 +233,6 @@ public net.minecraft.world.item.alchemy.PotionBrewing f_43495_ # CONTAINER_MIXES

# Mojang added a private getter for text fields private variable
public net.minecraft.client.gui.components.EditBox m_94222_()Z # isEditable

# Falling Block Entity
public net.minecraft.world.entity.item.FallingBlockEntity f_31946_ # blockState