Pineapple plants now generate in jungle biomes

This commit is contained in:
Sollace 2023-09-09 14:32:27 +01:00
parent 09bd37ff4b
commit 1a3655d244
No known key found for this signature in database
GPG key ID: E52FACE7B5C773DB
6 changed files with 205 additions and 5 deletions

View file

@ -32,7 +32,7 @@ import com.minelittlepony.unicopia.particle.UParticles;
import com.minelittlepony.unicopia.server.world.BlockDestructionManager;
import com.minelittlepony.unicopia.server.world.NocturnalSleepManager;
import com.minelittlepony.unicopia.server.world.UGameRules;
import com.minelittlepony.unicopia.server.world.UTreeGen;
import com.minelittlepony.unicopia.server.world.UWorldGen;
import com.minelittlepony.unicopia.server.world.WeatherConditions;
import com.minelittlepony.unicopia.server.world.ZapAppleStageStore;
import com.minelittlepony.unicopia.trinkets.TrinketsDelegate;
@ -95,7 +95,7 @@ public class Unicopia implements ModInitializer {
SpellType.bootstrap();
Abilities.bootstrap();
UScreenHandlers.bootstrap();
UTreeGen.bootstrap();
UWorldGen.bootstrap();
UGameRules.bootstrap();
UDamageTypes.bootstrap();
}

View file

@ -1,11 +1,13 @@
package com.minelittlepony.unicopia.block;
import com.minelittlepony.unicopia.item.UItems;
import com.minelittlepony.unicopia.seasons.FertilizableUtil;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.CropBlock;
import net.minecraft.block.enums.BlockHalf;
import net.minecraft.item.ItemStack;
import net.minecraft.registry.tag.BlockTags;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.state.StateManager;
@ -21,14 +23,23 @@ import net.minecraft.world.WorldAccess;
import net.minecraft.world.WorldView;
public class PineappleCropBlock extends CropBlock {
private static final EnumProperty<BlockHalf> HALF = Properties.BLOCK_HALF;
private static final BooleanProperty WILD = BooleanProperty.of("wild");
public static final EnumProperty<BlockHalf> HALF = Properties.BLOCK_HALF;
public static final BooleanProperty WILD = BooleanProperty.of("wild");
public PineappleCropBlock(Settings settings) {
super(settings);
setDefaultState(getDefaultState().with(HALF, BlockHalf.BOTTOM).with(WILD, false));
}
@Override
public ItemStack getPickStack(BlockView world, BlockPos pos, BlockState state) {
if (state.get(HALF) == BlockHalf.TOP) {
return UItems.PINEAPPLE.getDefaultStack();
}
return UItems.PINEAPPLE_CROWN.getDefaultStack();
}
@Override
protected boolean canPlantOnTop(BlockState floor, BlockView world, BlockPos pos) {
return floor.isOf(this) || super.canPlantOnTop(floor, world, pos);

View file

@ -72,7 +72,7 @@ public interface UBlocks {
Block PALM_LEAVES = register("palm_leaves", BlockConstructionUtils.createLeavesBlock(BlockSoundGroup.GRASS), ItemGroups.BUILDING_BLOCKS);
Block BANANAS = register("bananas", new FruitBlock(Settings.create().mapColor(MapColor.YELLOW).sounds(BlockSoundGroup.WOOD).noCollision().ticksRandomly().breakInstantly().pistonBehavior(PistonBehavior.DESTROY), Direction.DOWN, PALM_LEAVES, VoxelShapes.fullCube()));
Block PINEAPPLE = register("pineapple", new PineappleCropBlock(Settings.create().sounds(BlockSoundGroup.GRASS).noCollision().breakInstantly().pistonBehavior(PistonBehavior.DESTROY)));
PineappleCropBlock PINEAPPLE = register("pineapple", new PineappleCropBlock(Settings.create().sounds(BlockSoundGroup.GRASS).noCollision().breakInstantly().pistonBehavior(PistonBehavior.DESTROY)));
Block MANGO_LEAVES = register("mango_leaves", new FruitBearingBlock(FabricBlockSettings.copy(Blocks.JUNGLE_LEAVES),
0xCCFFAA00,
@ -151,6 +151,10 @@ public interface UBlocks {
TRANSLUCENT_BLOCKS.add(WEATHER_VANE);
TintedBlock.REGISTRY.add(PALM_LEAVES);
FlammableBlockRegistry.getDefaultInstance().add(GREEN_APPLE_LEAVES, 30, 60);
FlammableBlockRegistry.getDefaultInstance().add(SWEET_APPLE_LEAVES, 30, 60);
FlammableBlockRegistry.getDefaultInstance().add(SOUR_APPLE_LEAVES, 30, 60);
FlammableBlockRegistry.getDefaultInstance().add(MANGO_LEAVES, 30, 60);
FlammableBlockRegistry.getDefaultInstance().add(PALM_LEAVES, 30, 60);
FlammableBlockRegistry.getDefaultInstance().add(PALM_LOG, 5, 5);
FlammableBlockRegistry.getDefaultInstance().add(PALM_WOOD, 5, 5);

View file

@ -0,0 +1,58 @@
package com.minelittlepony.unicopia.server.world;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Supplier;
import java.util.function.Function;
import net.fabricmc.fabric.api.event.registry.DynamicRegistrySetupCallback;
import net.minecraft.registry.*;
import net.minecraft.world.gen.feature.*;
import net.minecraft.world.gen.placementmodifier.PlacementModifier;
import net.minecraft.registry.entry.*;
import net.minecraft.util.Identifier;
class FeatureRegistry {
private static final List<ConfiguredEntry> CONFIGURED_FEATURES = new ArrayList<>();
private static final List<PlacedEntry> PLACED_FEATURES = new ArrayList<>();
static {
DynamicRegistrySetupCallback.EVENT.register(registries -> {
registries.getOptional(RegistryKeys.CONFIGURED_FEATURE).ifPresent(registry -> {
CONFIGURED_FEATURES.forEach(entry -> {
Registry.register(registry, entry.key(), entry.factory().get());
});
});
registries.getOptional(RegistryKeys.PLACED_FEATURE).ifPresent(registry -> {
var lookup = registries.getOptional(RegistryKeys.CONFIGURED_FEATURE).orElseThrow();
PLACED_FEATURES.forEach(entry -> {
Registry.register(registry, entry.key(), entry.factory().apply(lookup.getEntry(entry.configuration()).orElseThrow()));
});
});
});
}
public static <F extends Feature<FC>, FC extends FeatureConfig> RegistryKey<PlacedFeature> registerPlaceableFeature(
Identifier id,
F feature, FC featureConfig,
List<PlacementModifier> placementModifiers) {
var configurationKey = RegistryKey.of(RegistryKeys.CONFIGURED_FEATURE, id);
var placementKey = RegistryKey.of(RegistryKeys.PLACED_FEATURE, id);
CONFIGURED_FEATURES.add(new ConfiguredEntry(configurationKey, () -> new ConfiguredFeature<>(feature, featureConfig)));
PLACED_FEATURES.add(new PlacedEntry(placementKey, configurationKey, config -> new PlacedFeature(config, placementModifiers)));
return placementKey;
}
record ConfiguredEntry (
RegistryKey<ConfiguredFeature<?, ?>> key,
Supplier<ConfiguredFeature<?, ?>> factory
) {}
record PlacedEntry (
RegistryKey<PlacedFeature> key,
RegistryKey<ConfiguredFeature<?, ?>> configuration,
Function<RegistryEntry<ConfiguredFeature<?, ?>>, PlacedFeature> factory
) {}
}

View file

@ -0,0 +1,94 @@
package com.minelittlepony.unicopia.server.world;
import com.minelittlepony.unicopia.block.PineappleCropBlock;
import com.minelittlepony.unicopia.block.UBlocks;
import com.mojang.serialization.Codec;
import net.minecraft.block.enums.BlockHalf;
import net.minecraft.registry.tag.BlockTags;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.random.Random;
import net.minecraft.world.StructureWorldAccess;
import net.minecraft.world.gen.feature.Feature;
import net.minecraft.world.gen.feature.FeatureConfig;
import net.minecraft.world.gen.feature.util.FeatureContext;
public class PineapplePlantFeature extends Feature<PineapplePlantFeature.Config> {
public PineapplePlantFeature() {
super(Config.CODEC);
}
@Override
public boolean generate(FeatureContext<Config> context) {
final StructureWorldAccess world = context.getWorld();
final Random random = context.getRandom();
int xOffset = 3;
int zOffset = 3;
BlockPos.Mutable mutablePos = context.getOrigin().mutableCopy();
boolean succeeded = false;
for (BlockPos position : BlockPos.iterateOutwards(context.getOrigin(), xOffset, 0, zOffset)) {
if (random.nextFloat() < 0.5) {
continue;
}
findTerrainLevel(world, mutablePos.set(position));
if (world.isOutOfHeightLimit(mutablePos)
|| (!world.isAir(mutablePos) && !isReplaceable(world, mutablePos))
|| !isSoil(world, mutablePos.move(Direction.DOWN))) {
continue;
}
mutablePos.move(Direction.UP);
int maxAge = UBlocks.PINEAPPLE.getMaxAge();
int age = random.nextBetween(maxAge - 3, maxAge);
succeeded = true;
setBlockState(world, mutablePos, UBlocks.PINEAPPLE.withAge(age).with(PineappleCropBlock.WILD, true));
if (age >= maxAge) {
mutablePos.move(Direction.UP);
if (isReplaceable(world, mutablePos)) {
setBlockState(world, mutablePos, UBlocks.PINEAPPLE
.withAge(random.nextBetween(maxAge / 2, maxAge))
.with(PineappleCropBlock.HALF, BlockHalf.TOP)
.with(PineappleCropBlock.WILD, true));
}
}
}
return succeeded;
}
static void findTerrainLevel(StructureWorldAccess world, BlockPos.Mutable mutablePos) {
if (isReplaceable(world, mutablePos)) {
do {
mutablePos.move(Direction.DOWN);
} while (isReplaceable(world, mutablePos) && !world.isOutOfHeightLimit(mutablePos));
mutablePos.move(Direction.UP);
}
if (!isReplaceable(world, mutablePos)) {
do {
mutablePos.move(Direction.UP);
} while (!isReplaceable(world, mutablePos) && !world.isOutOfHeightLimit(mutablePos));
}
}
static boolean isReplaceable(StructureWorldAccess world, BlockPos pos) {
return (world.isAir(pos) || world.getBlockState(pos).isIn(BlockTags.REPLACEABLE_BY_TREES)) && world.getBlockState(pos).getFluidState().isEmpty();
}
public static class Config implements FeatureConfig {
public static final Config INSTANCE = new Config();
public static final Codec<Config> CODEC = Codec.unit(INSTANCE);
}
}

View file

@ -0,0 +1,33 @@
package com.minelittlepony.unicopia.server.world;
import java.util.List;
import com.minelittlepony.unicopia.Unicopia;
import net.fabricmc.fabric.api.biome.v1.BiomeModifications;
import net.fabricmc.fabric.api.biome.v1.BiomeSelectors;
import net.minecraft.registry.Registries;
import net.minecraft.registry.Registry;
import net.minecraft.registry.RegistryKey;
import net.minecraft.registry.tag.BiomeTags;
import net.minecraft.world.gen.GenerationStep;
import net.minecraft.world.gen.feature.PlacedFeature;
import net.minecraft.world.gen.feature.PlacedFeatures;
import net.minecraft.world.gen.placementmodifier.BiomePlacementModifier;
import net.minecraft.world.gen.placementmodifier.RarityFilterPlacementModifier;
import net.minecraft.world.gen.placementmodifier.SquarePlacementModifier;
public interface UWorldGen {
PineapplePlantFeature PINEAPPLE_PLANT_FEATURE = Registry.register(Registries.FEATURE, Unicopia.id("pineapple_plant"), new PineapplePlantFeature());
RegistryKey<PlacedFeature> PINEAPPLE_PLANT_PLACED_FEATURE = FeatureRegistry.registerPlaceableFeature(Unicopia.id("pineapple_plant"), PINEAPPLE_PLANT_FEATURE, PineapplePlantFeature.Config.INSTANCE, List.of(
RarityFilterPlacementModifier.of(100),
SquarePlacementModifier.of(),
PlacedFeatures.MOTION_BLOCKING_HEIGHTMAP,
BiomePlacementModifier.of()
));
static void bootstrap() {
BiomeModifications.addFeature(BiomeSelectors.tag(BiomeTags.IS_JUNGLE), GenerationStep.Feature.VEGETAL_DECORATION, PINEAPPLE_PLANT_PLACED_FEATURE);
UTreeGen.bootstrap();
}
}