added palm tree
Some checks failed
build / build (21) (push) Has been cancelled

added quicksand
This commit is contained in:
paisc 2025-01-24 18:57:36 +01:00
parent b4c75acaec
commit d8400a3552
25 changed files with 678 additions and 58 deletions

View File

@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "voltexdesertupdate:block/quicksand_block"
}
}
}

View File

@ -0,0 +1,6 @@
{
"parent": "minecraft:block/cube_all",
"textures": {
"all": "voltexdesertupdate:block/quicksand_block"
}
}

View File

@ -0,0 +1,3 @@
{
"parent": "voltexdesertupdate:block/quicksand_block"
}

View File

@ -3,8 +3,12 @@ package net.voltexstudios;
import net.fabricmc.api.ModInitializer;
import net.fabricmc.fabric.api.object.builder.v1.entity.FabricDefaultAttributeRegistry;
import net.fabricmc.fabric.api.registry.FlammableBlockRegistry;
import net.minecraft.block.FireBlock;
import net.voltexstudios.blocks.ModBlocks;
import net.voltexstudios.entity.ModEntities;
import net.voltexstudios.entity.custom.VultureEntity;
import net.voltexstudios.item.ModItemGroups;
import net.voltexstudios.item.ModItems;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -17,12 +21,18 @@ public class VoltexDesertUpdate implements ModInitializer {
@Override
public void onInitialize() {
LOGGER.info("Hello Fabric world!");
ModItemGroups.registerItemGroups();
ModItems.registerModItems();
ModBlocks.registerModBlocks();
ModEntities.registerModEntities();
FabricDefaultAttributeRegistry.register(ModEntities.VULTURE_ENTITY, VultureEntity.createAttributes());
FabricDefaultAttributeRegistry.register(ModEntities.VULTURE_ENTITY, VultureEntity.createVultureAttributes());
FlammableBlockRegistry.getDefaultInstance().add(ModBlocks.PALM_LOG, 5, 5);
FlammableBlockRegistry.getDefaultInstance().add(ModBlocks.PALM_WOOD, 5, 5);
FlammableBlockRegistry.getDefaultInstance().add(ModBlocks.PALM_PLANKS, 5, 20);
FlammableBlockRegistry.getDefaultInstance().add(ModBlocks.PALM_LEAVES, 30, 60);
}
}

View File

@ -1,8 +1,11 @@
package net.voltexstudios;
import net.fabricmc.api.ClientModInitializer;
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.render.RenderLayer;
import net.voltexstudios.blocks.ModBlocks;
import net.voltexstudios.entity.ModEntities;
import net.voltexstudios.entity.client.VultureModel;
import net.voltexstudios.entity.client.VultureRenderer;
@ -13,6 +16,8 @@ public class VoltexDesertUpdateClient implements ClientModInitializer {
public void onInitializeClient() {
VoltexDesertUpdate.LOGGER.info("Initializing Desert Update Client");
BlockRenderLayerMap.INSTANCE.putBlock(ModBlocks.PALM_SAPLING, RenderLayer.getCutout());
EntityModelLayerRegistry.registerModelLayer(VultureModel.VULTURE, VultureModel::getTexturedModelData);
EntityRendererRegistry.register(ModEntities.VULTURE_ENTITY, VultureRenderer::new);
}

View File

@ -2,10 +2,32 @@ package net.voltexstudios;
import net.fabricmc.fabric.api.datagen.v1.DataGeneratorEntrypoint;
import net.fabricmc.fabric.api.datagen.v1.FabricDataGenerator;
import net.minecraft.registry.RegistryBuilder;
import net.minecraft.registry.RegistryKeys;
import net.voltexstudios.datagen.ModBlockTagProvider;
import net.voltexstudios.datagen.ModItemTagProvider;
import net.voltexstudios.datagen.ModLootTableProvider;
import net.voltexstudios.datagen.ModModelProvider;
import net.voltexstudios.world.ModConfiguredFeatures;
import net.voltexstudios.world.ModPlacedFeatures;
public class VoltexDesertUpdateDataGenerator implements DataGeneratorEntrypoint {
@Override
public void onInitializeDataGenerator(FabricDataGenerator fabricDataGenerator) {
FabricDataGenerator.Pack pack = fabricDataGenerator.createPack();
pack.addProvider(ModBlockTagProvider::new);
pack.addProvider(ModItemTagProvider::new);
pack.addProvider(ModLootTableProvider::new);
pack.addProvider(ModModelProvider::new);
}
@Override
public void buildRegistry(RegistryBuilder registryBuilder) {
registryBuilder.addRegistry(RegistryKeys.CONFIGURED_FEATURE, ModConfiguredFeatures::bootstrap);
registryBuilder.addRegistry(RegistryKeys.PLACED_FEATURE, ModPlacedFeatures::bootstrap);
}
}

View File

@ -0,0 +1,60 @@
package net.voltexstudios.blocks;
import net.fabricmc.fabric.api.itemgroup.v1.ItemGroupEvents;
import net.minecraft.block.*;
import net.minecraft.block.piston.PistonBehavior;
import net.minecraft.item.BlockItem;
import net.minecraft.item.Item;
import net.minecraft.item.ItemGroups;
import net.minecraft.registry.Registries;
import net.minecraft.registry.Registry;
import net.minecraft.sound.BlockSoundGroup;
import net.minecraft.util.Identifier;
import net.voltexstudios.VoltexDesertUpdate;
import net.voltexstudios.blocks.custom.QuicksandBlock;
import net.voltexstudios.world.tree.ModSaplingGenerators;
public class ModBlocks {
public static final Block QUICKSAND_BLOCK = registerBlock("quicksand_block",
new QuicksandBlock(AbstractBlock.Settings.copy(Blocks.POWDER_SNOW)));
public static final Block PALM_LOG = registerBlock("palm_log",
new PillarBlock(AbstractBlock.Settings.copy(Blocks.OAK_LOG)));
public static final Block PALM_WOOD = registerBlock("palm_wood",
new PillarBlock(AbstractBlock.Settings.copy(Blocks.OAK_WOOD)));
public static final Block PALM_PLANKS = registerBlock("palm_planks",
new Block(AbstractBlock.Settings.copy(Blocks.OAK_PLANKS)));
public static final Block PALM_LEAVES = registerBlock("palm_leaves",
new LeavesBlock(AbstractBlock.Settings.copy(Blocks.OAK_LEAVES)));
public static final Block PALM_SAPLING = registerBlock("palm_sapling",
new SaplingBlock(ModSaplingGenerators.PALM, AbstractBlock.Settings.create()
.mapColor(MapColor.PALE_YELLOW)
.noCollision()
.ticksRandomly()
.breakInstantly()
.sounds(BlockSoundGroup.SAND)
.pistonBehavior(PistonBehavior.DESTROY)));
private static Block registerBlockWithoutBlockItem(String name, Block block) {
return Registry.register(Registries.BLOCK, Identifier.of(VoltexDesertUpdate.MOD_ID, name), block);
}
private static Block registerBlock(String name, Block block) {
registerBlockItem(name, block);
return Registry.register(Registries.BLOCK, Identifier.of(VoltexDesertUpdate.MOD_ID, name), block);
}
private static void registerBlockItem(String name, Block block) {
Registry.register(Registries.ITEM, Identifier.of(VoltexDesertUpdate.MOD_ID, name),
new BlockItem(block, new Item.Settings()));
}
public static void registerModBlocks() {
VoltexDesertUpdate.LOGGER.info("Registering Mod Blocks for " + VoltexDesertUpdate.MOD_ID);
ItemGroupEvents.modifyEntriesEvent(ItemGroups.BUILDING_BLOCKS).register(entries -> {
});
}
}

View File

@ -0,0 +1,129 @@
package net.voltexstudios.blocks.custom;
import com.mojang.serialization.MapCodec;
import net.minecraft.block.*;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EquipmentSlot;
import net.minecraft.entity.FallingBlockEntity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.ai.pathing.NavigationType;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.particle.DustParticleEffect;
import net.minecraft.registry.tag.EntityTypeTags;
import net.minecraft.sound.SoundEvent;
import net.minecraft.sound.SoundEvents;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.random.Random;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.util.shape.VoxelShapes;
import net.minecraft.world.*;
import org.jetbrains.annotations.Nullable;
import java.util.Optional;
public class QuicksandBlock extends Block implements FluidDrainable {
private static final float DAMAGE = 0.25f;
public static final MapCodec<PowderSnowBlock> CODEC = createCodec(PowderSnowBlock::new);
private static final VoxelShape FALLING_SHAPE = VoxelShapes.cuboid(0.0, 0.0, 0.0, 1.0, 0.8999999761581421, 1.0);
public QuicksandBlock(Settings settings) {
super(settings);
}
@Override
protected MapCodec<? extends Block> getCodec() {
return CODEC;
}
protected boolean isSideInvisible(BlockState state, BlockState stateFrom, Direction direction) {
return stateFrom.isOf(this) || super.isSideInvisible(state, stateFrom, direction);
}
protected VoxelShape getCullingShape(BlockState state, BlockView world, BlockPos pos) {
return VoxelShapes.empty();
}
protected void onEntityCollision(BlockState state, World world, BlockPos pos, Entity entity) {
if (!(entity instanceof LivingEntity) || entity.getBlockStateAtPos().isOf(this)) {
entity.slowMovement(state, new Vec3d(0.8999999761581421, 1.5, 0.8999999761581421));
entity.damage(world.getDamageSources().inWall(), DAMAGE);
if (world.isClient) {
Random random = world.getRandom();
boolean bl = entity.lastRenderX != entity.getX() || entity.lastRenderZ != entity.getZ();
if (bl && random.nextBoolean()) {
world.addParticle(new DustParticleEffect(new Vec3d(1.0, 1.0, 1.0).toVector3f(), 1.0F), entity.getX(), pos.getY() + 1, entity.getZ(), (double)(MathHelper.nextBetween(random, -1.0F, 1.0F) * 0.083333336F), 0.05000000074505806, (double)(MathHelper.nextBetween(random, -1.0F, 1.0F) * 0.083333336F));
}
}
}
}
public void onLandedUpon(World world, BlockState state, BlockPos pos, Entity entity, float fallDistance) {
if (!((double)fallDistance < 4.0) && entity instanceof LivingEntity livingEntity) {
LivingEntity.FallSounds fallSounds = livingEntity.getFallSounds();
SoundEvent soundEvent = (double)fallDistance < 7.0 ? fallSounds.small() : fallSounds.big();
entity.playSound(soundEvent, 1.0F, 1.0F);
}
}
protected VoxelShape getCollisionShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
if (context instanceof EntityShapeContext entityShapeContext) {
Entity entity = entityShapeContext.getEntity();
if (entity != null) {
if (entity.fallDistance > 2.5F) {
return FALLING_SHAPE;
}
boolean bl = entity instanceof FallingBlockEntity;
if (bl || canWalkOnQuicksand(entity) && context.isAbove(VoxelShapes.fullCube(), pos, false) && !context.isDescending()) {
return super.getCollisionShape(state, world, pos, context);
}
}
}
return VoxelShapes.empty();
}
protected VoxelShape getCameraCollisionShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
return VoxelShapes.empty();
}
public static boolean canWalkOnQuicksand(Entity entity) {
if (entity.getType().isIn(EntityTypeTags.POWDER_SNOW_WALKABLE_MOBS)) {
return true;
} else {
return entity instanceof LivingEntity && ((LivingEntity) entity).getEquippedStack(EquipmentSlot.FEET).isOf(Items.LEATHER_BOOTS);
}
}
public ItemStack tryDrainFluid(@Nullable PlayerEntity player, WorldAccess world, BlockPos pos, BlockState state) {
world.setBlockState(pos, Blocks.AIR.getDefaultState(), Block.NOTIFY_ALL_AND_REDRAW);
if (!world.isClient()) {
world.syncWorldEvent(WorldEvents.BLOCK_BROKEN, pos, Block.getRawIdFromState(state));
}
return new ItemStack(Items.POWDER_SNOW_BUCKET);
}
public Optional<SoundEvent> getBucketFillSound() {
return Optional.of(SoundEvents.ITEM_BUCKET_FILL_POWDER_SNOW);
}
protected boolean canPathfindThrough(BlockState state, NavigationType type) {
return true;
}
@Override
public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
return VoxelShapes.empty(); // Optional: also prevents outline rendering
}
}

View File

@ -0,0 +1,23 @@
package net.voltexstudios.datagen;
import net.fabricmc.fabric.api.datagen.v1.FabricDataOutput;
import net.fabricmc.fabric.api.datagen.v1.provider.FabricTagProvider;
import net.minecraft.registry.RegistryWrapper;
import net.minecraft.registry.tag.BlockTags;
import net.voltexstudios.blocks.ModBlocks;
import java.util.concurrent.CompletableFuture;
public class ModBlockTagProvider extends FabricTagProvider.BlockTagProvider {
public ModBlockTagProvider(FabricDataOutput output, CompletableFuture<RegistryWrapper.WrapperLookup> registriesFuture) {
super(output, registriesFuture);
}
@Override
protected void configure(RegistryWrapper.WrapperLookup wrapperLookup) {
getOrCreateTagBuilder(BlockTags.LOGS_THAT_BURN)
.add(ModBlocks.PALM_LOG)
.add(ModBlocks.PALM_WOOD);
}
}

View File

@ -0,0 +1,26 @@
package net.voltexstudios.datagen;
import net.fabricmc.fabric.api.datagen.v1.FabricDataOutput;
import net.fabricmc.fabric.api.datagen.v1.provider.FabricTagProvider;
import net.minecraft.registry.RegistryWrapper;
import net.minecraft.registry.tag.ItemTags;
import net.voltexstudios.blocks.ModBlocks;
import java.util.concurrent.CompletableFuture;
public class ModItemTagProvider extends FabricTagProvider.ItemTagProvider {
public ModItemTagProvider(FabricDataOutput output, CompletableFuture<RegistryWrapper.WrapperLookup> completableFuture) {
super(output, completableFuture);
}
@Override
protected void configure(RegistryWrapper.WrapperLookup wrapperLookup) {
getOrCreateTagBuilder(ItemTags.LOGS_THAT_BURN)
.add(ModBlocks.PALM_WOOD.asItem())
.add(ModBlocks.PALM_LOG.asItem());
getOrCreateTagBuilder(ItemTags.PLANKS)
.add(ModBlocks.PALM_PLANKS.asItem());
}
}

View File

@ -0,0 +1,24 @@
package net.voltexstudios.datagen;
import net.fabricmc.fabric.api.datagen.v1.FabricDataOutput;
import net.fabricmc.fabric.api.datagen.v1.provider.FabricBlockLootTableProvider;
import net.minecraft.registry.RegistryWrapper;
import net.voltexstudios.blocks.ModBlocks;
import java.util.concurrent.CompletableFuture;
public class ModLootTableProvider extends FabricBlockLootTableProvider {
public ModLootTableProvider(FabricDataOutput dataOutput, CompletableFuture<RegistryWrapper.WrapperLookup> registryLookup) {
super(dataOutput, registryLookup);
}
@Override
public void generate() {
addDrop(ModBlocks.PALM_LOG);
addDrop(ModBlocks.PALM_WOOD);
addDrop(ModBlocks.PALM_PLANKS);
addDrop(ModBlocks.PALM_SAPLING);
addDrop(ModBlocks.PALM_LEAVES, leavesDrops(ModBlocks.PALM_LEAVES, ModBlocks.PALM_SAPLING, 0.0625F));
}
}

View File

@ -0,0 +1,31 @@
package net.voltexstudios.datagen;
import net.fabricmc.fabric.api.datagen.v1.FabricDataOutput;
import net.fabricmc.fabric.api.datagen.v1.provider.FabricModelProvider;
import net.minecraft.data.client.BlockStateModelGenerator;
import net.minecraft.data.client.ItemModelGenerator;
import net.minecraft.data.client.Models;
import net.minecraft.data.client.TexturedModel;
import net.voltexstudios.blocks.ModBlocks;
public class ModModelProvider extends FabricModelProvider {
public ModModelProvider(FabricDataOutput output) {
super(output);
}
@Override
public void generateBlockStateModels(BlockStateModelGenerator blockStateModelGenerator) {
blockStateModelGenerator.registerLog(ModBlocks.PALM_LOG).log(ModBlocks.PALM_LOG).wood(ModBlocks.PALM_WOOD);
blockStateModelGenerator.registerSimpleCubeAll(ModBlocks.QUICKSAND_BLOCK);
blockStateModelGenerator.registerSimpleCubeAll(ModBlocks.PALM_PLANKS);
blockStateModelGenerator.registerSingleton(ModBlocks.PALM_LEAVES, TexturedModel.LEAVES);
blockStateModelGenerator.registerTintableCrossBlockState(ModBlocks.PALM_SAPLING, BlockStateModelGenerator.TintType.NOT_TINTED);
}
@Override
public void generateItemModels(ItemModelGenerator itemModelGenerator) {
itemModelGenerator.register(ModBlocks.PALM_SAPLING.asItem(), Models.GENERATED);
}
}

View File

@ -1,74 +1,201 @@
package net.voltexstudios.entity.custom;
import net.minecraft.entity.AnimationState;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.ai.goal.LookAroundGoal;
import net.minecraft.entity.ai.goal.LookAtEntityGoal;
import net.minecraft.entity.ai.goal.WanderAroundGoal;
import net.minecraft.entity.ai.TargetPredicate;
import net.minecraft.entity.ai.control.FlightMoveControl;
import net.minecraft.entity.ai.goal.*;
import net.minecraft.entity.ai.pathing.BirdNavigation;
import net.minecraft.entity.ai.pathing.EntityNavigation;
import net.minecraft.entity.attribute.DefaultAttributeContainer;
import net.minecraft.entity.attribute.EntityAttributes;
import net.minecraft.entity.mob.MobEntity;
import net.minecraft.entity.passive.AnimalEntity;
import net.minecraft.entity.passive.PassiveEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.entity.mob.HostileEntity;
import net.minecraft.entity.passive.RabbitEntity;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.Heightmap;
import net.minecraft.world.World;
import net.voltexstudios.entity.ModEntities;
import org.jetbrains.annotations.Nullable;
public class VultureEntity extends AnimalEntity {
import java.util.EnumSet;
import java.util.Random;
public final AnimationState idleAnimationState = new AnimationState();
private int idleAnimationTimeout;
public class VultureEntity extends HostileEntity {
public VultureEntity(EntityType<? extends AnimalEntity> entityType, World world) {
private static final double STANDARD_FLIGHT_HEIGHT = 20;
private static final double STANDARD_FLIGHT_SPEED = 1.5;
private static final double FORWARD_SPEED = 0.2;
public VultureEntity(EntityType<? extends HostileEntity> entityType, World world) {
super(entityType, world);
this.moveControl = new FlightMoveControl(this, 20, true);
}
@Override
protected EntityNavigation createNavigation(World world) {
BirdNavigation navigation = new BirdNavigation(this, world);
navigation.setCanPathThroughDoors(false);
navigation.setCanSwim(true);
return navigation;
}
@Override
protected void initGoals() {
this.goalSelector.add(0, new WanderAroundGoal(this, 1.0));
this.goalSelector.add(1, new LookAtEntityGoal(this, PlayerEntity.class, 6.0F));
this.goalSelector.add(2, new LookAroundGoal(this));
this.goalSelector.add(1, new SwimGoal(this));
this.goalSelector.add(2, new RabbitHunterGoal(this));
this.goalSelector.add(2, new FlyGoal(this, 2 * STANDARD_FLIGHT_SPEED));
this.goalSelector.add(3, new LookAroundGoal(this));
this.goalSelector.add(4, new ForwardFlightGoal(this));
this.goalSelector.add(4, new MaintainHeightGoal(this, STANDARD_FLIGHT_HEIGHT));
this.targetSelector.add(2, new ActiveTargetGoal<>(this, RabbitEntity.class, true));
}
private void setupAnimationStates() {
if (this.idleAnimationTimeout <= 0) {
this.idleAnimationTimeout = 40;
this.idleAnimationState.start(this.age);
} else {
--this.idleAnimationTimeout;
private static class ForwardFlightGoal extends Goal {
private final VultureEntity vulture;
public ForwardFlightGoal(VultureEntity vulture) {
this.vulture = vulture;
this.setControls(EnumSet.of(Goal.Control.MOVE));
}
@Override
public boolean canStart() {
return !vulture.isOnGround();
}
@Override
public void tick() {
super.tick();
Vec3d rotation = vulture.getRotationVector();
Vec3d movement = rotation.multiply(FORWARD_SPEED);
if (this.getWorld().isClient()) {
this.setupAnimationStates();
vulture.setVelocity(movement.x, vulture.getVelocity().y, movement.z);
}
}
//TODO alter attributes
public static DefaultAttributeContainer.Builder createAttributes() {
return MobEntity.createMobAttributes()
.add(EntityAttributes.GENERIC_MAX_HEALTH, 10.0)
.add(EntityAttributes.GENERIC_FLYING_SPEED, 1.5F)
.add(EntityAttributes.GENERIC_MOVEMENT_SPEED, 0.6F)
.add(EntityAttributes.GENERIC_ATTACK_DAMAGE, 10.0)
.add(EntityAttributes.GENERIC_FOLLOW_RANGE, 48.0);
private static class MaintainHeightGoal extends Goal {
private final VultureEntity vulture;
private final double targetHeight;
public MaintainHeightGoal(VultureEntity vulture, double height) {
this.vulture = vulture;
this.targetHeight = height;
}
@Override
public boolean isBreedingItem(ItemStack stack) {
return false;
public boolean canStart() {
return true;
}
@Nullable
@Override
public PassiveEntity createChild(ServerWorld world, PassiveEntity entity) {
return ModEntities.VULTURE_ENTITY.create(world);
public void tick() {
double currentY = vulture.getY();
double groundLevel = vulture.getWorld().getTopY(Heightmap.Type.WORLD_SURFACE, vulture.getBlockPos().getX(), vulture.getBlockPos().getZ());
double desiredY = groundLevel + targetHeight;
desiredY += new Random().nextDouble() * 5;
if (Math.abs(currentY - desiredY) > 1.0) {
vulture.getMoveControl().moveTo(
vulture.getX(),
desiredY,
vulture.getZ(),
STANDARD_FLIGHT_SPEED
);
}
}
}
@Override
public void fall(double heightDifference, boolean onGroundIn, net.minecraft.block.BlockState state, net.minecraft.util.math.BlockPos pos) {
// Kein Fallschaden für den Geier
}
public static DefaultAttributeContainer.Builder createVultureAttributes() {
return HostileEntity.createHostileAttributes()
.add(EntityAttributes.GENERIC_MAX_HEALTH, 20.0)
.add(EntityAttributes.GENERIC_MOVEMENT_SPEED, 0.3)
.add(EntityAttributes.GENERIC_FLYING_SPEED, STANDARD_FLIGHT_SPEED)
.add(EntityAttributes.GENERIC_ATTACK_DAMAGE, 4.0);
}
// Benutzerdefinierte Zielklasse zum Jagen von Hasen
private static class RabbitHunterGoal extends Goal {
private final VultureEntity vulture;
private RabbitEntity targetRabbit;
public RabbitHunterGoal(VultureEntity vulture) {
this.vulture = vulture;
}
@Override
public boolean canStart() {
this.targetRabbit = findNearestRabbit();
return this.targetRabbit != null;
}
@Override
public void tick() {
if (targetRabbit != null) {
// Luftangriff auf den Hasen
vulture.getNavigation().startMovingTo(
targetRabbit.getX(),
targetRabbit.getY() + 1.5,
targetRabbit.getZ(),
1.2
);
// Angriff, wenn nah genug
if (vulture.distanceTo(targetRabbit) < 2.0) {
vulture.tryAttack(targetRabbit);
}
}
}
private RabbitEntity findNearestRabbit() {
return vulture.getWorld().getClosestEntity(
RabbitEntity.class,
TargetPredicate.DEFAULT,
vulture,
vulture.getX(),
vulture.getY(),
vulture.getZ(),
vulture.getBoundingBox().expand(25.0)
);
}
}
// Benutzerdefinierte Zielklasse für Kreisflugverhalten
private static class CircularFlightGoal extends Goal {
private final VultureEntity vulture;
private double circleX, circleZ;
private double angle = 0;
public CircularFlightGoal(VultureEntity vulture) {
this.vulture = vulture;
this.setControls(EnumSet.of(Goal.Control.MOVE));
}
@Override
public boolean canStart() {
// Kreisflug, wenn nicht auf der Jagd
return !vulture.getNavigation().isIdle();
}
@Override
public void tick() {
// Kreisfluglogik
angle += 0.1;
double radius = 5.0;
circleX = vulture.getX() + Math.cos(angle) * radius;
circleZ = vulture.getZ() + Math.sin(angle) * radius;
vulture.getMoveControl().moveTo(
circleX,
vulture.getY() + 3,
circleZ,
STANDARD_FLIGHT_SPEED
);
}
}
}

View File

@ -0,0 +1,33 @@
package net.voltexstudios.item;
import net.fabricmc.fabric.api.itemgroup.v1.FabricItemGroup;
import net.minecraft.item.ItemGroup;
import net.minecraft.item.ItemStack;
import net.minecraft.registry.Registries;
import net.minecraft.registry.Registry;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;
import net.voltexstudios.VoltexDesertUpdate;
import net.voltexstudios.blocks.ModBlocks;
public class ModItemGroups {
public static final ItemGroup DESERT_UPDATE_GROUP = Registry.register(Registries.ITEM_GROUP,
Identifier.of(VoltexDesertUpdate.MOD_ID, "desert_update"),
FabricItemGroup.builder().icon(() -> new ItemStack(ModItems.DUNE_STAFF))
.displayName(Text.translatable("itemgroup.voltexdesertupdate.desert_update"))
.entries((displayContext, entries) -> {
entries.add(ModItems.DUNE_STAFF);
entries.add(ModBlocks.QUICKSAND_BLOCK);
entries.add(ModBlocks.PALM_WOOD);
entries.add(ModBlocks.PALM_PLANKS);
entries.add(ModBlocks.PALM_LEAVES);
entries.add(ModBlocks.PALM_SAPLING);
entries.add(ModBlocks.PALM_LOG);
}).build());
public static void registerItemGroups() {
VoltexDesertUpdate.LOGGER.info("Registering Item Groups for " + VoltexDesertUpdate.MOD_ID);
}
}

View File

@ -0,0 +1,44 @@
package net.voltexstudios.world;
import net.minecraft.block.Blocks;
import net.minecraft.registry.Registerable;
import net.minecraft.registry.RegistryKey;
import net.minecraft.registry.RegistryKeys;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.intprovider.ConstantIntProvider;
import net.minecraft.util.math.intprovider.UniformIntProvider;
import net.minecraft.world.gen.feature.*;
import net.minecraft.world.gen.feature.size.TwoLayersFeatureSize;
import net.minecraft.world.gen.foliage.AcaciaFoliagePlacer;
import net.minecraft.world.gen.stateprovider.BlockStateProvider;
import net.minecraft.world.gen.trunk.BendingTrunkPlacer;
import net.voltexstudios.VoltexDesertUpdate;
import net.voltexstudios.blocks.ModBlocks;
public class ModConfiguredFeatures {
public static final RegistryKey<ConfiguredFeature<?, ?>> PALM_KEY = registerKey("palm");
public static void bootstrap(Registerable<ConfiguredFeature<?, ?>> context) {
register(context, PALM_KEY, Feature.TREE, new TreeFeatureConfig.Builder(
BlockStateProvider.of(ModBlocks.PALM_LOG),
new BendingTrunkPlacer(3, 2, 0, 4, UniformIntProvider.create(1, 2)),
BlockStateProvider.of(ModBlocks.PALM_LEAVES),
new AcaciaFoliagePlacer(ConstantIntProvider.create(3), ConstantIntProvider.create(1)),
new TwoLayersFeatureSize(1, 0, 2))
.build()
);
}
public static RegistryKey<ConfiguredFeature<?, ?>> registerKey(String name) {
return RegistryKey.of(RegistryKeys.CONFIGURED_FEATURE, Identifier.of(VoltexDesertUpdate.MOD_ID, name));
}
private static <FC extends FeatureConfig, F extends Feature<FC>> void register(Registerable<ConfiguredFeature<?, ?>> context,
RegistryKey<ConfiguredFeature<?, ?>> key, F feature, FC configuration) {
context.register(key, new ConfiguredFeature<>(feature, configuration));
}
}

View File

@ -0,0 +1,43 @@
package net.voltexstudios.world;
import net.minecraft.registry.Registerable;
import net.minecraft.registry.RegistryKey;
import net.minecraft.registry.RegistryKeys;
import net.minecraft.registry.entry.RegistryEntry;
import net.minecraft.util.Identifier;
import net.minecraft.world.gen.feature.*;
import net.minecraft.world.gen.placementmodifier.*;
import net.voltexstudios.VoltexDesertUpdate;
import net.voltexstudios.blocks.ModBlocks;
import java.util.List;
public class ModPlacedFeatures {
public static final RegistryKey<PlacedFeature> PALM_PLACED_KEY = registerKey("palm_placed");
public static void bootstrap(Registerable<PlacedFeature> context) {
var configuredFeatures = context.getRegistryLookup(RegistryKeys.CONFIGURED_FEATURE);
register(context, PALM_PLACED_KEY, configuredFeatures.getOrThrow(ModConfiguredFeatures.PALM_KEY),
VegetationPlacedFeatures.treeModifiersWithWouldSurvive(
PlacedFeatures.createCountExtraModifier(2, 0.1f, 2), ModBlocks.PALM_SAPLING));
}
public static RegistryKey<PlacedFeature> registerKey(String name) {
return RegistryKey.of(RegistryKeys.PLACED_FEATURE, Identifier.of(VoltexDesertUpdate.MOD_ID, name));
}
private static void register(Registerable<PlacedFeature> context, RegistryKey<PlacedFeature> key, RegistryEntry<ConfiguredFeature<?, ?>> configuration,
List<PlacementModifier> modifiers) {
context.register(key, new PlacedFeature(configuration, List.copyOf(modifiers)));
}
private static <FC extends FeatureConfig, F extends Feature<FC>> void register(Registerable<PlacedFeature> context, RegistryKey<PlacedFeature> key,
RegistryEntry<ConfiguredFeature<?, ?>> configuration,
PlacementModifier... modifiers) {
register(context, key, configuration, List.of(modifiers));
}
}

View File

@ -0,0 +1,13 @@
package net.voltexstudios.world.tree;
import net.minecraft.block.SaplingGenerator;
import net.voltexstudios.VoltexDesertUpdate;
import net.voltexstudios.world.ModConfiguredFeatures;
import java.util.Optional;
public class ModSaplingGenerators {
public static final SaplingGenerator PALM = new SaplingGenerator(VoltexDesertUpdate.MOD_ID + ":palm",
Optional.empty(), Optional.of(ModConfiguredFeatures.PALM_KEY), Optional.empty());
}

View File

@ -1,5 +1,15 @@
{
"item.voltexdesertupdate.dune_staff": "Staff of the Dunes",
"entity.voltexdesertupdate.vulture": "Vulture"
"entity.voltexdesertupdate.vulture": "Vulture",
"itemgroup.voltexdesertupdate.desert_update": "Desert Update",
"block.voltexdesertupdate.quicksand_block": "Quicksand Block",
"block.voltexdesertupdate.palm_log": "Palm Log",
"block.voltexdesertupdate.palm_wood": "Palm Wood",
"block.voltexdesertupdate.palm_planks": "Palm Planks",
"block.voltexdesertupdate.palm_leaves": "Palm Leaves",
"block.voltexdesertupdate.palm_sapling": "Palm Sapling"
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 391 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 644 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 536 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 313 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 189 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 313 B

View File

@ -3,9 +3,13 @@
"package": "net.voltexstudios.mixin",
"compatibilityLevel": "JAVA_21",
"mixins": [
"ExampleMixin"
"ExampleMixin",
"LivingEntityAccessor"
],
"injectors": {
"defaultRequire": 1
}
},
"client": [
"EntityMixin"
]
}