-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Cage, Bottle, + Bowl basic implementation
- Loading branch information
1 parent
e6ed1ec
commit 088d9a3
Showing
401 changed files
with
8,469 additions
and
966 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
157 changes: 157 additions & 0 deletions
157
src/main/java/com/starfish_studios/hamsters/block/CagePanelBlock.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} | ||
} |
24 changes: 24 additions & 0 deletions
24
src/main/java/com/starfish_studios/hamsters/block/properties/CageType.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
157
src/main/java/com/starfish_studios/hamsters/entity/Frank.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} |
Oops, something went wrong.