Skip to content

Commit

Permalink
Cage, Bottle, + Bowl basic implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
crispytwig committed Oct 22, 2024
1 parent e6ed1ec commit 088d9a3
Show file tree
Hide file tree
Showing 401 changed files with 8,469 additions and 966 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.starfish_studios.hamsters;

import com.starfish_studios.hamsters.block.CagePanelBlock;
import com.starfish_studios.hamsters.client.renderer.*;
import com.starfish_studios.hamsters.registry.HamstersBlocks;
import com.starfish_studios.hamsters.registry.HamstersEntityType;
Expand Down Expand Up @@ -37,15 +38,45 @@ private static void registerModelLayers() {
EntityRendererRegistry.register(HamstersEntityType.HAMSTER, HamsterRenderer::new);
EntityRendererRegistry.register(HamstersEntityType.HAMSTER_NEW, HamsterNewRenderer::new);
EntityRendererRegistry.register(HamstersEntityType.HAMSTER_BALL, HamsterBallRenderer::new);
EntityRendererRegistry.register(HamstersEntityType.FRANK, FrankRenderer::new);
}

private static void registerBlockRenderLayers() {
// BlockRenderLayerMap.INSTANCE.putBlock(HamstersBlocks.TUNNEL, RenderType.translucent());
BlockRenderLayerMap.INSTANCE.putBlock(

BlockRenderLayerMap.INSTANCE.putBlocks(RenderType.cutout(),
HamstersBlocks.CAGE_PANEL,
HamstersBlocks.RED_CAGE_PANEL,
HamstersBlocks.ORANGE_CAGE_PANEL,
HamstersBlocks.YELLOW_CAGE_PANEL,
HamstersBlocks.LIME_CAGE_PANEL,
HamstersBlocks.GREEN_CAGE_PANEL,
HamstersBlocks.CYAN_CAGE_PANEL,
HamstersBlocks.BLUE_CAGE_PANEL,
HamstersBlocks.LIGHT_BLUE_CAGE_PANEL,
HamstersBlocks.PINK_CAGE_PANEL,
HamstersBlocks.MAGENTA_CAGE_PANEL,
HamstersBlocks.PURPLE_CAGE_PANEL,
HamstersBlocks.WHITE_CAGE_PANEL,
HamstersBlocks.LIGHT_GRAY_CAGE_PANEL,
HamstersBlocks.GRAY_CAGE_PANEL,
HamstersBlocks.BLACK_CAGE_PANEL,
HamstersBlocks.BROWN_CAGE_PANEL,
HamstersBlocks.RED_HAMSTER_BOWL,
HamstersBlocks.ORANGE_HAMSTER_BOWL,
HamstersBlocks.YELLOW_HAMSTER_BOWL,
HamstersBlocks.LIME_HAMSTER_BOWL,
HamstersBlocks.GREEN_HAMSTER_BOWL,
HamstersBlocks.CYAN_HAMSTER_BOWL,
HamstersBlocks.BLUE_HAMSTER_BOWL,

RenderType.cutout());
HamstersBlocks.LIGHT_BLUE_HAMSTER_BOWL,
HamstersBlocks.PINK_HAMSTER_BOWL,
HamstersBlocks.MAGENTA_HAMSTER_BOWL,
HamstersBlocks.PURPLE_HAMSTER_BOWL,
HamstersBlocks.WHITE_HAMSTER_BOWL,
HamstersBlocks.LIGHT_GRAY_HAMSTER_BOWL,
HamstersBlocks.GRAY_HAMSTER_BOWL,
HamstersBlocks.BLACK_HAMSTER_BOWL,
HamstersBlocks.BROWN_HAMSTER_BOWL
);
}
}

Expand Down
157 changes: 157 additions & 0 deletions src/main/java/com/starfish_studios/hamsters/block/CagePanelBlock.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
package com.starfish_studios.hamsters.block;

import com.starfish_studios.hamsters.block.properties.CageType;
import com.starfish_studios.hamsters.registry.HamstersTags;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.sounds.SoundSource;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.level.block.state.properties.DirectionProperty;
import net.minecraft.world.level.block.state.properties.EnumProperty;
import net.minecraft.world.level.pathfinder.PathComputationType;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

public class CagePanelBlock extends Block {
public static final DirectionProperty FACING = BlockStateProperties.HORIZONTAL_FACING;
public static final EnumProperty<CageType> TYPE = EnumProperty.create("type", CageType.class);

public static final VoxelShape NORTH_AABB = Block.box(0, 0, 15, 16, 16, 16);
public static final VoxelShape EAST_AABB = Block.box(0, 0, 0, 1, 16, 16);
public static final VoxelShape SOUTH_AABB = Block.box(0, 0, 0, 16, 16, 1);
public static final VoxelShape WEST_AABB = Block.box(15, 0, 0, 16, 16, 16);

public static final VoxelShape NORTH_COLLISION_AABB = Block.box(0, 0, 15, 16, 24, 16);
public static final VoxelShape EAST_COLLISION_AABB = Block.box(0, 0, 0, 1, 24, 16);
public static final VoxelShape SOUTH_COLLISION_AABB = Block.box(0, 0, 0, 16, 24, 1);
public static final VoxelShape WEST_COLLISION_AABB = Block.box(15, 0, 0, 16, 24, 16);

public CagePanelBlock(Properties properties) {
super(properties);
this.registerDefaultState(this.stateDefinition.any()
.setValue(TYPE, CageType.NONE));
}

@Override
public @NotNull VoxelShape getShape(BlockState state, BlockGetter world, BlockPos pos, CollisionContext context) {
Direction direction = state.getValue(FACING);
return switch (direction) {
case EAST -> EAST_AABB;
case SOUTH -> SOUTH_AABB;
case WEST -> WEST_AABB;
default -> NORTH_AABB;
};
}

//getCollisionShape
@Override
public @NotNull VoxelShape getCollisionShape(BlockState state, BlockGetter world, BlockPos pos, CollisionContext context) {
Direction direction = state.getValue(FACING);
return switch (direction) {
case EAST -> EAST_COLLISION_AABB;
case SOUTH -> SOUTH_COLLISION_AABB;
case WEST -> WEST_COLLISION_AABB;
default -> NORTH_COLLISION_AABB;
};
}

@Override
public @NotNull InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) {
if (player.getItemInHand(hand).is(HamstersTags.CAGE_PANELS)) {
BlockPos above = pos.above();
if (level.isEmptyBlock(above)) {
BlockItem blockItem = (BlockItem) player.getItemInHand(hand).getItem();
// level.setBlock(above, state, 3);
level.setBlock(above, blockItem.getBlock().defaultBlockState().setValue(FACING, state.getValue(FACING)), 3);
level.playSound(null, pos, this.getSoundType(state).getPlaceSound(), SoundSource.BLOCKS, level.random.nextFloat() * 0.25F + 0.7F, level.random.nextFloat() * 0.1F + 0.9F);
return InteractionResult.SUCCESS;
}
}
return InteractionResult.PASS;
}


public float getShadeBrightness(BlockState blockState, BlockGetter blockGetter, BlockPos blockPos) {
return 1.0F;
}

public boolean propagatesSkylightDown(BlockState blockState, BlockGetter blockGetter, BlockPos blockPos) {
return true;
}

@Override
public boolean isPathfindable(BlockState state, BlockGetter reader, BlockPos pos, PathComputationType type) {
return false;
}

@Nullable
@Override
public BlockState getStateForPlacement(BlockPlaceContext context) {
Level level = context.getLevel();
BlockPos pos = context.getClickedPos();
Direction direction = context.getHorizontalDirection().getOpposite();

BlockState state = this.defaultBlockState().setValue(FACING, direction);
state = state.setValue(TYPE, getType(state, getRelativeTop(level, pos, direction), getRelativeBottom(level, pos, direction)));
return state;
}


public boolean skipRendering(BlockState blockState, BlockState blockState2, Direction direction) {
// return blockState2.is(this) && blockState2.getValue(FACING) == blockState.getValue(FACING);
return blockState2.getBlock() instanceof CagePanelBlock && blockState2.getValue(FACING) == blockState.getValue(FACING);
}

@Override
public void neighborChanged(BlockState state, Level level, BlockPos pos, Block block, BlockPos fromPos, boolean isMoving) {
if (level.isClientSide) return;

Direction direction = state.getValue(FACING);
CageType type = getType(state, getRelativeTop(level, pos, direction), getRelativeBottom(level, pos, direction));
if (state.getValue(TYPE) == type) return;

state = state.setValue(TYPE, type);
level.setBlock(pos, state, 3);
}

public BlockState getRelativeTop(Level level, BlockPos pos, Direction direction) {
return level.getBlockState(pos.above());
}

public BlockState getRelativeBottom(Level level, BlockPos pos, Direction direction) {
return level.getBlockState(pos.below());
}

public CageType getType(BlockState state, BlockState above, BlockState below) {
// boolean shape_above_same = above.is(state.getBlock()) && state.getValue(FACING) == above.getValue(FACING);
// boolean shape_below_same = below.is(state.getBlock()) && state.getValue(FACING) == below.getValue(FACING);

// Return the booleans the same as above but instead of state.getBlock, do it if they're an instanceof CagePanelBlock
boolean shape_above_same = above.getBlock() instanceof CagePanelBlock && state.getValue(FACING) == above.getValue(FACING);
boolean shape_below_same = below.getBlock() instanceof CagePanelBlock && state.getValue(FACING) == below.getValue(FACING);

if (shape_above_same && !shape_below_same) return CageType.BOTTOM;
else if (!shape_above_same && shape_below_same) return CageType.TOP;
else if (shape_above_same) return CageType.MIDDLE;
return CageType.NONE;
}

@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
builder.add(TYPE, FACING);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.starfish_studios.hamsters.block.properties;

import net.minecraft.util.StringRepresentable;

public enum CageType implements StringRepresentable {
TOP("top"),
MIDDLE("middle"),
BOTTOM("bottom"),
NONE("none");

private final String name;

private CageType(String type) {
this.name = type;
}

public String toString() {
return this.name;
}

public String getSerializedName() {
return this.name;
}
}
157 changes: 157 additions & 0 deletions src/main/java/com/starfish_studios/hamsters/entity/Frank.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
package com.starfish_studios.hamsters.entity;

import com.starfish_studios.hamsters.entity.common.HamstersGeoEntity;
import com.starfish_studios.hamsters.entity.common.MMPathNavigatorGround;
import com.starfish_studios.hamsters.entity.common.SmartBodyHelper;
import com.starfish_studios.hamsters.registry.HamstersEntityType;
import com.starfish_studios.hamsters.registry.HamstersItems;
import net.minecraft.core.NonNullList;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.sounds.SoundEvent;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.entity.*;
import net.minecraft.world.entity.ai.attributes.AttributeSupplier;
import net.minecraft.world.entity.ai.attributes.Attributes;
import net.minecraft.world.entity.ai.control.BodyRotationControl;
import net.minecraft.world.entity.ai.goal.*;
import net.minecraft.world.entity.ai.navigation.PathNavigation;
import net.minecraft.world.entity.monster.Monster;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import net.minecraft.world.phys.Vec3;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import software.bernie.geckolib.core.animatable.instance.AnimatableInstanceCache;
import software.bernie.geckolib.core.animation.AnimatableManager;
import software.bernie.geckolib.core.animation.AnimationController;
import software.bernie.geckolib.core.animation.AnimationState;
import software.bernie.geckolib.core.animation.RawAnimation;
import software.bernie.geckolib.core.object.PlayState;
import software.bernie.geckolib.util.GeckoLibUtil;

import java.util.Objects;

public class Frank extends Monster implements HamstersGeoEntity {
private final AnimatableInstanceCache geoCache = GeckoLibUtil.createInstanceCache(this);

protected static final RawAnimation IDLE = RawAnimation.begin().thenLoop("animation.frank.idle");
protected static final RawAnimation WALK = RawAnimation.begin().thenLoop("animation.frank.walk");
protected static final RawAnimation RUN = RawAnimation.begin().thenLoop("animation.frank.run");
protected static final RawAnimation BITE = RawAnimation.begin().thenLoop("animation.frank.bite");


public Frank(EntityType<? extends Monster> entityType, Level level) {
super(entityType, level);
}

public static AttributeSupplier.Builder createAttributes() {
return Mob.createMobAttributes()
.add(Attributes.MAX_HEALTH, 20.0)
.add(Attributes.MOVEMENT_SPEED, 0.27);
}

// Goals
@Override
protected void registerGoals() {
super.registerGoals();
this.goalSelector.addGoal(0, new FloatGoal(this));
this.goalSelector.addGoal(1, new PanicGoal(this, 1.5));
this.goalSelector.addGoal(2, new WaterAvoidingRandomStrollGoal(this, 1.0));
this.goalSelector.addGoal(3, new RandomLookAroundGoal(this));
}

@Override
public void customServerAiStep() {
this.setSprinting(this.getMoveControl().getSpeedModifier() >= 1.5F);
super.customServerAiStep();
}

@Override
protected @NotNull PathNavigation createNavigation(@NotNull Level level) {
return new MMPathNavigatorGround(this, level);
}

@Override
protected @NotNull BodyRotationControl createBodyControl() {
return new SmartBodyHelper(this);
}

// region MISC

@Override
protected void defineSynchedData() {
super.defineSynchedData();
}

@Override
public void readAdditionalSaveData(CompoundTag compoundTag) {
super.readAdditionalSaveData(compoundTag);
}

@Override
public void addAdditionalSaveData(CompoundTag compoundTag) {
super.addAdditionalSaveData(compoundTag);
}

@Override
public @NotNull ItemStack getItemBySlot(EquipmentSlot equipmentSlot) {
return ItemStack.EMPTY;
}

@Override
public void setItemSlot(EquipmentSlot equipmentSlot, ItemStack itemStack) {
this.verifyEquippedItem(itemStack);
}

@Override
public @NotNull HumanoidArm getMainArm() {
return HumanoidArm.RIGHT;
}

// endregion


// region GECKOLIB

@Override
public void registerControllers(AnimatableManager.ControllerRegistrar controllerRegistrar) {
controllerRegistrar.add(new AnimationController<>(this, "controller", 5, this::animController));
controllerRegistrar.add(new AnimationController<>(this, "attack_controller", 5, this::attackController));
}

protected <E extends Frank> PlayState attackController(final AnimationState<E> event) {
if (this.swinging && event.getController().getAnimationState().equals(AnimationController.State.STOPPED)) {
event.getController().forceAnimationReset();

event.getController().setAnimation(BITE);
this.swinging = false;
}
return PlayState.STOP;
}

protected <E extends Frank> PlayState animController(final AnimationState<E> event) {
if (event.isMoving()) {
event.setControllerSpeed(2.0F * event.getLimbSwingAmount());
if (this.isSprinting()) {
event.setAnimation(RUN);
} else {
event.setAnimation(WALK);
}
} else {
event.setAnimation(IDLE);
}
return PlayState.CONTINUE;
}

@Override
public AnimatableInstanceCache getAnimatableInstanceCache() {
return this.geoCache;
}

// endregion
}
Loading

0 comments on commit 088d9a3

Please sign in to comment.