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 beanstalk #89

Open
wants to merge 7 commits into
base: dev
Choose a base branch
from
Open
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
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
17 changes: 17 additions & 0 deletions src/main/java/fr/hugman/mubble/MubbleClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,40 @@

import fr.hugman.mubble.client.gui.screen.BumpableBlockScreen;
import fr.hugman.mubble.client.render.BumpableBlockEntityRenderer;
import fr.hugman.mubble.entity.BeanstalkEntityModel;
import fr.hugman.mubble.entity.BeanstalkEntityRenderer;
import fr.hugman.mubble.registry.SuperMario;
import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.blockrenderlayer.v1.BlockRenderLayerMap;
import net.fabricmc.fabric.api.client.rendering.v1.EntityModelLayerRegistry;
import net.fabricmc.fabric.api.client.rendering.v1.EntityRendererRegistry;
import net.minecraft.client.gui.screen.ingame.HandledScreens;
import net.minecraft.client.render.RenderLayer;
import net.minecraft.client.render.block.entity.BlockEntityRendererFactories;
import net.minecraft.client.render.entity.model.EntityModelLayer;
import net.minecraft.util.Identifier;

@Environment(EnvType.CLIENT)
public class MubbleClient implements ClientModInitializer {
public static final EntityModelLayer MODEL_CUBE_LAYER = new EntityModelLayer(
new Identifier("mubble", "beanstalk"), "main"
);

@Override
public void onInitializeClient() {
BlockRenderLayerMap.INSTANCE.putBlock(SuperMario.RED_BEEP_BLOCK, RenderLayer.getCutout());
BlockRenderLayerMap.INSTANCE.putBlock(SuperMario.BLUE_BEEP_BLOCK, RenderLayer.getCutout());
BlockRenderLayerMap.INSTANCE.putBlock(SuperMario.BEANSTALK, RenderLayer.getCutout());

HandledScreens.register(SuperMario.BUMPABLE_BLOCK_SCREEN_HANDLER, BumpableBlockScreen::new);
BlockEntityRendererFactories.register(SuperMario.BUMPABLE_BLOCK_ENTITY_TYPE, BumpableBlockEntityRenderer::new);

EntityRendererRegistry.register(SuperMario.BEANSTALK_ENTITY, BeanstalkEntityRenderer::new);

EntityRendererRegistry.register(SuperMario.BEANSTALK_ENTITY, BeanstalkEntityRenderer::new);

EntityModelLayerRegistry.registerModelLayer(MODEL_CUBE_LAYER, BeanstalkEntityModel::getTexturedModelData);
}
}
102 changes: 102 additions & 0 deletions src/main/java/fr/hugman/mubble/block/BeanstalkBlock.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
package fr.hugman.mubble.block;

import fr.hugman.mubble.registry.SuperMario;
import fr.hugman.mubble.tag.MubbleBlockTags;
import net.minecraft.block.*;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.random.Random;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.util.shape.VoxelShapes;
import net.minecraft.world.*;

/**
* Most of the functions of this code were
* essentially copied from BambooBlock.
*
* @author MaxBrick
* @since v4.0.0
*/

public class BeanstalkBlock extends Block implements Fertilizable {
public BeanstalkBlock(AbstractBlock.Settings settings) {
super(settings);
}

public boolean isTransparent(BlockState state, BlockView world, BlockPos pos) {
return true;
}

public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
return VoxelShapes.fullCube();
}

public VoxelShape getCollisionShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
return VoxelShapes.empty();
}

public void scheduledTick(BlockState state, ServerWorld world, BlockPos pos, Random random) {
if (!state.canPlaceAt(world, pos)) {
world.breakBlock(pos, true);
}
}

public boolean canPlaceAt(BlockState state, WorldView world, BlockPos pos) {
return world.getBlockState(pos.down()).isIn(MubbleBlockTags.BEANSTALK_PLANTABLE_ON);
}


protected int countBeanstalksAbove(BlockView world, BlockPos pos) {
int i;
for(i = 0; i < 16 && world.getBlockState(pos.up(i + 1)).isOf(SuperMario.BEANSTALK); ++i) {
}

return i;
}
protected int countBeanstalksBelow(BlockView world, BlockPos pos) {
int i;
for(i = 0; i < 16 && world.getBlockState(pos.down(i + 1)).isOf(SuperMario.BEANSTALK); ++i) {
}

return i;
}

public BlockState getStateForNeighborUpdate(BlockState state, Direction direction, BlockState neighborState, WorldAccess world, BlockPos pos, BlockPos neighborPos) {
if (!state.canPlaceAt(world, pos)) {
world.scheduleBlockTick(pos, this, 1);
}
return super.getStateForNeighborUpdate(state, direction, neighborState, world, pos, neighborPos);
}

//This function as well as the count functions are ripped from BambooBlock.class
public boolean isFertilizable(WorldView world, BlockPos pos, BlockState state, boolean isClient) {
int i = this.countBeanstalksAbove(world, pos);
int j = this.countBeanstalksBelow(world, pos);
return i + j + 1 < 16;
}

public boolean canGrow(World world, Random random, BlockPos pos, BlockState state) {
return true;
}

//Here I took the logic I needed from BambooBlock.class
public void grow(ServerWorld world, Random random, BlockPos pos, BlockState state) {
int i = this.countBeanstalksAbove(world, pos);
int j = this.countBeanstalksBelow(world, pos);
int k = i + j + 1;
int l = 1 + random.nextInt(2);


for(int m = 0; m < l; ++m) {
BlockPos blockPos = pos.up(i);
if (k >= 16 || !world.isAir(blockPos.up())) {
return;
}

world.setBlockState(blockPos.up(1), state);
++i;
++k;
}
}
}
35 changes: 31 additions & 4 deletions src/main/java/fr/hugman/mubble/block/BumpableBlock.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package fr.hugman.mubble.block;

import fr.hugman.mubble.block.entity.BumpableBlockEntity;
import fr.hugman.mubble.entity.BeanstalkEntity;
import fr.hugman.mubble.registry.MubbleSounds;
import fr.hugman.mubble.registry.SuperMario;
import net.fabricmc.api.EnvType;
Expand All @@ -16,6 +17,7 @@
import net.minecraft.client.MinecraftClient;
import net.minecraft.entity.Entity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.SpawnReason;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.inventory.Inventory;
import net.minecraft.item.ItemStack;
Expand All @@ -33,11 +35,13 @@
import net.minecraft.world.event.GameEvent;
import org.jetbrains.annotations.Nullable;

import java.util.Objects;
import java.util.Optional;

/**
* @author haykam
* @author Hugman
* @author MaxBrick
* @since v4.0.0
*/
public class BumpableBlock extends BlockWithEntity implements HittableBlock {
Expand Down Expand Up @@ -199,13 +203,15 @@ public void onBumpEnd(World world, BlockPos pos, BlockState state, BumpableBlock
return;
}
var newState = blockEntity.getBumpedState();
if(newState != null) {
world.setBlockState(pos, newState);

this.loot(world, pos, state, blockEntity);

if(newState != null) {
world.setBlockState(pos, newState);
}
else {
world.setBlockState(pos, state.with(BUMPING, false));
world.setBlockState(pos, state.with(BUMPING, false));
}
this.loot(world, pos, state, blockEntity);
}
}

Expand All @@ -230,15 +236,36 @@ public void loot(World world, BlockPos pos, BlockState state, BumpableBlockEntit
}
var actualState = world.getBlockState(pos);
var center = pos.toCenterPos();



if(actualState.isAir()) {
ItemScatterer.spawn(world, pos, blockEntity);
}
else {

var direction = blockEntity.getBumpDirection();
var x = center.getX() + direction.getOffsetX() * 0.75D;
var y = center.getY() + direction.getOffsetY() * 0.75D;
var z = center.getZ() + direction.getOffsetZ() * 0.75D;
for(int i = 0; i < blockEntity.size(); ++i) {
/*
This should check if the container holds beanstalks.
If it does, and blockEntity.getBumpedState() is not air,
it will spawn a beanstalk, setting its growth value
to the amount of beanstalks in the container,
and finally empties the blockEntity.
*/
if(
blockEntity.getStack(i).isOf(SuperMario.BEANSTALK.asItem()) && (blockEntity.getBumpedState() == null || !blockEntity.getBumpedState().isAir())
) {
Objects.requireNonNull(SuperMario.BEANSTALK_ENTITY.spawn(world.getServer().getWorld(world.getRegistryKey()), pos, SpawnReason.TRIGGERED)).growth = blockEntity.count(SuperMario.BEANSTALK.asItem());
//TODO: make custom sound for beanstalk
world.playSound(null, center.getX(), center.getY(), center.getZ(), MubbleSounds.BUMPABLE_BLOCK_LOOT, SoundCategory.BLOCKS, 1.0F, 1.0F);
blockEntity.clear();
return;
}

ItemScatterer.spawn(world, x, y, z, blockEntity.getStack(i));
}
}
Expand Down
76 changes: 76 additions & 0 deletions src/main/java/fr/hugman/mubble/entity/BeanstalkEntity.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package fr.hugman.mubble.entity;

import fr.hugman.mubble.registry.SuperMario;
import net.minecraft.block.Blocks;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.MovementType;
import net.minecraft.fluid.Fluids;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.world.World;

/**
* This class is made by copying and modifying
* methods from FallingBlockEntity
* Real creative, I know :)
*
* @author MaxBrick
* @since v4.0.0
*/

public class BeanstalkEntity extends Entity {

//This will determine how high the entity will grow. It should be set upon spawning
public int growth = 0;

//This should always be set to its y position when spawned
private final int spawnHeight = (int) this.getY();

private int travelDistance = 0;

public BeanstalkEntity(EntityType<? extends BeanstalkEntity> entityType, World world) {
super(entityType, world);
}

@Override
protected void initDataTracker() {

}

protected Entity.MoveEffect getMoveEffect() {
return MoveEffect.NONE;
}

public void tick() {
//I don't know why, but I have to use the move function to actually make it move
this.setVelocity(0.0D, 0.3D, 0.0D);
this.move(MovementType.SELF, this.getVelocity());

if(!this.getWorld().getBlockState(this.getBlockPos().up()).isAir() || growth < 1) {
this.discard();
}

//Checks if its current position is one block higher than where it previously was before placing block
if(this.getY() > spawnHeight + travelDistance + 1 && this.getWorld().getBlockState(this.getBlockPos()).isAir()) {
travelDistance++;

this.getWorld().setBlockState(this.getBlockPos(), SuperMario.BEANSTALK.getDefaultState());

growth--;
}
}

@Override
protected void writeCustomDataToNbt(NbtCompound nbt) {
nbt.putInt("Growth", this.growth);
}

@Override
protected void readCustomDataFromNbt(NbtCompound nbt) {
this.growth = nbt.getInt("Growth");
}

public boolean isAttackable() {
return false;
}
}
54 changes: 54 additions & 0 deletions src/main/java/fr/hugman/mubble/entity/BeanstalkEntityModel.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package fr.hugman.mubble.entity;

import com.google.common.collect.ImmutableList;
import net.minecraft.client.model.*;
import net.minecraft.client.render.VertexConsumer;
import net.minecraft.client.render.entity.model.EntityModel;
import net.minecraft.client.render.entity.model.EntityModelPartNames;
import net.minecraft.client.util.math.MatrixStack;

/**
* @author MaxBrick
* @since v4.0.0
*/

//I have no idea what I'm doing!
//TODO: fix the model so it's identical to BeanstalkBlock's model
public class BeanstalkEntityModel extends EntityModel<BeanstalkEntity>{
private final ModelPart base;

public BeanstalkEntityModel(ModelPart modelPart) {
this.base = modelPart.getChild(EntityModelPartNames.CUBE);
}

public static TexturedModelData getTexturedModelData() {
ModelData modelData = new ModelData();
ModelPartData modelPartData = modelData.getRoot();
modelPartData.addChild(
EntityModelPartNames.CUBE, ModelPartBuilder.create().uv(
0, 0
).cuboid(
-8F, 8F, -8F, 16F, 16F, 16F
), ModelTransform.pivot(8F, 0F, 8F)
);
modelPartData.addChild(
EntityModelPartNames.CUBE, ModelPartBuilder.create().uv(
0, 0
).cuboid(
-8F, 8F, -8F, 16F, 16F, 16F
), ModelTransform.pivot(-8F, 0F, -8F)
);
return TexturedModelData.of(modelData, 16, 16);
}

@Override
public void setAngles(BeanstalkEntity entity, float limbAngle, float limbDistance, float animationProgress, float headYaw, float headPitch) {
}

@Override
public void render(MatrixStack matrices, VertexConsumer vertices, int light, int overlay, float red, float green, float blue, float alpha) {
ImmutableList.of(this.base).forEach((modelRenderer) -> {
modelRenderer.render(matrices, vertices, light, overlay, red, green, blue, alpha);
});
}
}
17 changes: 17 additions & 0 deletions src/main/java/fr/hugman/mubble/entity/BeanstalkEntityRenderer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package fr.hugman.mubble.entity;

import net.minecraft.client.render.entity.EntityRenderer;
import net.minecraft.client.render.entity.EntityRendererFactory;
import net.minecraft.util.Identifier;

public class BeanstalkEntityRenderer extends EntityRenderer<BeanstalkEntity> {

public BeanstalkEntityRenderer(EntityRendererFactory.Context context) {
super(context);
}

@Override
public Identifier getTexture(BeanstalkEntity entity) {
return new Identifier("mubble", "textures/block/beanstalk.png");
}
}
Loading