Skip to content

Commit

Permalink
Added golden oak trees
Browse files Browse the repository at this point in the history
  • Loading branch information
Sollace committed Jan 18, 2024
1 parent c7a161e commit ae6e7a0
Show file tree
Hide file tree
Showing 42 changed files with 569 additions and 18 deletions.
Original file line number Diff line number Diff line change
@@ -1,20 +1,26 @@
package com.minelittlepony.unicopia.ability;

import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.function.DoubleSupplier;
import java.util.function.Supplier;

import com.minelittlepony.unicopia.Race;
import com.minelittlepony.unicopia.USounds;
import com.minelittlepony.unicopia.UTags;
import com.minelittlepony.unicopia.ability.data.Hit;
import com.minelittlepony.unicopia.ability.data.Pos;
import com.minelittlepony.unicopia.block.UBlocks;
import com.minelittlepony.unicopia.entity.player.Pony;
import com.minelittlepony.unicopia.particle.MagicParticleEffect;
import com.minelittlepony.unicopia.particle.ParticleUtils;
import com.minelittlepony.unicopia.server.world.BlockDestructionManager;
import com.minelittlepony.unicopia.server.world.UTreeGen;
import com.minelittlepony.unicopia.util.TraceHelper;
import com.minelittlepony.unicopia.util.VecHelper;

import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.CarrotsBlock;
Expand All @@ -23,10 +29,13 @@
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.particle.ParticleTypes;
import net.minecraft.state.property.Property;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.random.Random;
import net.minecraft.world.World;
import net.minecraft.world.WorldEvents;

/**
* Earth Pony ability to grow crops
Expand Down Expand Up @@ -67,10 +76,14 @@ public double getCostEstimate(Pony player) {
public boolean apply(Pony player, Pos data) {
int count = 0;

for (BlockPos pos : BlockPos.iterate(
data.pos().add(-2, -2, -2),
data.pos().add( 2, 2, 2))) {
count += applySingle(player, player.asWorld(), player.asWorld().getBlockState(pos), pos);
if (!applyDirectly(player, data.pos())) {
for (BlockPos pos : BlockPos.iterate(
data.pos().add(-2, -2, -2),
data.pos().add( 2, 2, 2))) {
count += applySingle(player, player.asWorld(), player.asWorld().getBlockState(pos), pos);
}
} else {
count = 1;
}

if (count > 0) {
Expand All @@ -90,16 +103,7 @@ protected int applySingle(Pony player, World w, BlockState state, BlockPos pos)
if (state.isOf(Blocks.CARROTS)) {
if (state.get(CarrotsBlock.AGE) == CarrotsBlock.MAX_AGE) {
boolean transform = w.random.nextInt(3) == 0;
DoubleSupplier vecComponentFactory = () -> w.random.nextTriangular(0, 0.5);
Supplier<Vec3d> posSupplier = () -> pos.toCenterPos().add(VecHelper.supply(vecComponentFactory));

for (int i = 0; i < 25; i++) {
ParticleUtils.spawnParticle(w, new MagicParticleEffect(0xFFFF00), posSupplier.get(), Vec3d.ZERO);
if (transform) {
ParticleUtils.spawnParticle(w, ParticleTypes.CLOUD, posSupplier.get(), Vec3d.ZERO);
}
}

spawnConversionParticles(w, pos, transform);
if (transform) {
w.setBlockState(pos, UBlocks.GOLD_ROOT.getDefaultState().with(CarrotsBlock.AGE, CarrotsBlock.MAX_AGE));
}
Expand Down Expand Up @@ -134,6 +138,55 @@ protected int applySingle(Pony player, World w, BlockState state, BlockPos pos)
return 0;
}

private boolean applyDirectly(Pony player, BlockPos pos) {
return TransmutationRecipe.RECIPES.stream()
.filter(recipe -> recipe.matches(player.asWorld(), pos))
.map(recipe -> recipe.checkPattern(player.asWorld(), pos))
.filter(result -> result.matchedLocations().size() + 1 >= TransmutationRecipe.MINIMUM_INPUT)
.filter(result -> {
boolean transform = result.shoudTransform(player.asWorld().random);

player.playSound(USounds.ENTITY_CRYSTAL_SHARDS_AMBIENT, 1);

result.matchedLocations().forEach(cell -> {
spawnConversionParticles(player.asWorld(), cell.up(), false);
BlockDestructionManager manager = BlockDestructionManager.of(player.asWorld());
if (transform) {
if (manager.damageBlock(cell, 8) >= BlockDestructionManager.MAX_DAMAGE || player.asWorld().random.nextInt(20) == 0) {
player.asWorld().setBlockState(cell, Blocks.DIRT.getDefaultState());
player.asWorld().syncWorldEvent(WorldEvents.BLOCK_BROKEN, cell, Block.getRawIdFromState(player.asWorld().getBlockState(cell)));
}
} else {
if (manager.damageBlock(cell, 4) >= BlockDestructionManager.MAX_DAMAGE || player.asWorld().random.nextInt(20) == 0) {
player.asWorld().setBlockState(cell, Blocks.DIRT.getDefaultState());
player.asWorld().syncWorldEvent(WorldEvents.BLOCK_BROKEN, cell, Block.getRawIdFromState(player.asWorld().getBlockState(cell)));
}
}
});

spawnConversionParticles(player.asWorld(), pos, transform);
if (transform) {
player.asWorld().setBlockState(pos, result.recipe().getResult(player.asWorld(), pos));
}

return true;
})
.findFirst()
.isPresent();
}

private static void spawnConversionParticles(World w, BlockPos pos, boolean success) {
DoubleSupplier vecComponentFactory = () -> w.random.nextTriangular(0, 0.5);
Supplier<Vec3d> posSupplier = () -> pos.toCenterPos().add(VecHelper.supply(vecComponentFactory));

for (int i = 0; i < 25; i++) {
ParticleUtils.spawnParticle(w, new MagicParticleEffect(0xFFFF00), posSupplier.get(), Vec3d.ZERO);
if (success) {
ParticleUtils.spawnParticle(w, ParticleTypes.CLOUD, posSupplier.get(), Vec3d.ZERO);
}
}
}

@Override
public void warmUp(Pony player, AbilitySlot slot) {
player.getMagicalReserves().getExertion().addPercent(30);
Expand All @@ -148,6 +201,57 @@ public void coolDown(Pony player, AbilitySlot slot) {

}

private static record TransmutationRecipe(Block input, BlockState output, BlockState material) {
static final List<TransmutationRecipe> RECIPES = List.of(
new TransmutationRecipe(Blocks.OAK_SAPLING, UTreeGen.GOLDEN_APPLE_TREE.sapling().get().getDefaultState(), Blocks.RAW_GOLD_BLOCK.getDefaultState()),
new TransmutationRecipe(Blocks.CARROTS, UBlocks.GOLD_ROOT.getDefaultState(), Blocks.RAW_GOLD_BLOCK.getDefaultState()),
new TransmutationRecipe(Blocks.CORNFLOWER, UBlocks.CURING_JOKE.getDefaultState(), Blocks.LAPIS_BLOCK.getDefaultState()),
new TransmutationRecipe(Blocks.WITHER_ROSE, UBlocks.PLUNDER_VINE_BUD.getDefaultState(), Blocks.NETHERRACK.getDefaultState())
);
static final int RADIUS = 3;
static final int SIDE_LENGTH = (2 * RADIUS) + 1;
static final int AREA = (SIDE_LENGTH * SIDE_LENGTH) - 1;
static final int MINIMUM_INPUT = 9;

public boolean matches(World world, BlockPos pos) {
return world.getBlockState(pos).isOf(input);
}

public Result checkPattern(World world, BlockPos pos) {
BlockPos center = pos.down();
Set<BlockPos> matches = new HashSet<>();
for (BlockPos cell : BlockPos.iterateInSquare(center, RADIUS, Direction.EAST, Direction.NORTH)) {
if (cell.equals(center)) {
continue;
}
if (!world.getBlockState(cell).equals(material)) {
break;
}
matches.add(cell.toImmutable());
}
return new Result(this, matches);
}

public BlockState getResult(World world, BlockPos pos) {
BlockState input = world.getBlockState(pos);
BlockState output = this.output;
for (var property : input.getProperties()) {
output = copyProperty(input, output, property);
}
return output;
}

private <T extends Comparable<T>> BlockState copyProperty(BlockState from, BlockState to, Property<T> property) {
return to.withIfExists(property, from.get(property));
}

record Result (TransmutationRecipe recipe, Set<BlockPos> matchedLocations) {
public boolean shoudTransform(Random random) {
return random.nextInt(TransmutationRecipe.AREA) < matchedLocations().size();
}
}
}

public interface Growable {
boolean grow(World world, BlockState state, BlockPos pos);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.minelittlepony.unicopia.block;

import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.state.StateManager;
import net.minecraft.state.property.BooleanProperty;
import net.minecraft.util.math.Direction;
import net.minecraft.util.shape.VoxelShape;

public class EnchantedFruitBlock extends FruitBlock {
static final BooleanProperty ENCHANTED = BooleanProperty.of("enchanted");

public EnchantedFruitBlock(Settings settings, Direction attachmentFace, Block stem, VoxelShape shape) {
super(settings, attachmentFace, stem, shape);
setDefaultState(getDefaultState().with(ENCHANTED, false));
}

@Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
super.appendProperties(builder);
builder.add(ENCHANTED);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,14 @@ public boolean hasRandomTicks(BlockState state) {
return true;
}

protected boolean shouldAdvance(Random random) {
return true;
}

protected BlockState getPlacedFruitState(Random random) {
return fruit.get().getDefaultState();
}

@Override
public void randomTick(BlockState state, ServerWorld world, BlockPos pos, Random random) {
super.randomTick(state, world, pos, random);
Expand All @@ -74,6 +82,10 @@ public void randomTick(BlockState state, ServerWorld world, BlockPos pos, Random
BlockSoundGroup group = getSoundGroup(state);
int steps = FertilizableUtil.getGrowthSteps(world, pos, state, random);
while (steps-- > 0) {
if (!shouldAdvance(random)) {
continue;
}

if (state.get(STAGE) == Stage.FRUITING) {
state = state.cycle(AGE);
if (state.get(AGE) > 20) {
Expand All @@ -89,7 +101,7 @@ public void randomTick(BlockState state, ServerWorld world, BlockPos pos, Random

if (stage == Stage.FRUITING && isPositionValidForFruit(state, pos)) {
if (world.isAir(fruitPosition)) {
world.setBlockState(fruitPosition, fruit.get().getDefaultState(), Block.NOTIFY_ALL);
world.setBlockState(fruitPosition, getPlacedFruitState(random), Block.NOTIFY_ALL);
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.minelittlepony.unicopia.block;

import java.util.function.Supplier;

import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.item.ItemStack;
import net.minecraft.util.math.random.Random;

public class GoldenOakLeavesBlock extends FruitBearingBlock {

public GoldenOakLeavesBlock(Settings settings, int overlay, Supplier<Block> fruit,
Supplier<ItemStack> rottenFruitSupplier) {
super(settings, overlay, fruit, rottenFruitSupplier);
}

@Override
protected boolean shouldAdvance(Random random) {
return random.nextInt(1000) == 0;
}

@Override
protected BlockState getPlacedFruitState(Random random) {
return super.getPlacedFruitState(random).with(EnchantedFruitBlock.ENCHANTED, random.nextInt(1000) == 0);
}
}
14 changes: 13 additions & 1 deletion src/main/java/com/minelittlepony/unicopia/block/UBlocks.java
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ public interface UBlocks {
Block PALM_STAIRS = register("palm_stairs", new StairsBlock(PALM_PLANKS.getDefaultState(), Settings.copy(PALM_PLANKS).pistonBehavior(PistonBehavior.NORMAL)), ItemGroups.BUILDING_BLOCKS);
Block PALM_SLAB = register("palm_slab", new SlabBlock(Settings.create().mapColor(PALM_PLANKS.getDefaultMapColor()).strength(2, 3).sounds(BlockSoundGroup.WOOD).pistonBehavior(PistonBehavior.NORMAL)), ItemGroups.BUILDING_BLOCKS);
Block PALM_FENCE = register("palm_fence", new FenceBlock(Settings.create().mapColor(PALM_PLANKS.getDefaultMapColor()).strength(2, 3).sounds(BlockSoundGroup.WOOD).pistonBehavior(PistonBehavior.NORMAL)), ItemGroups.BUILDING_BLOCKS);
Block PALM_FENCE_GATE = register("palm_fence_gate", new FenceGateBlock(Settings.create().mapColor(PALM_PLANKS.getDefaultMapColor()).strength(2, 3).sounds(BlockSoundGroup.WOOD).pistonBehavior(PistonBehavior.NORMAL), WoodType.OAK), ItemGroups.BUILDING_BLOCKS);
Block PALM_FENCE_GATE = register("palm_fence_gate", new FenceGateBlock(Settings.create().mapColor(PALM_PLANKS.getDefaultMapColor()).strength(2, 3).sounds(BlockSoundGroup.WOOD).pistonBehavior(PistonBehavior.NORMAL), UWoodTypes.PALM), ItemGroups.BUILDING_BLOCKS);
Block PALM_DOOR = register("palm_door", new DoorBlock(Settings.create().mapColor(PALM_PLANKS.getDefaultMapColor()).instrument(Instrument.BASS).strength(3.0f).nonOpaque().burnable().pistonBehavior(PistonBehavior.DESTROY), UWoodTypes.PALM.setType()), ItemGroups.FUNCTIONAL);
Block PALM_TRAPDOOR = register("palm_trapdoor", new TrapdoorBlock(Settings.create().mapColor(PALM_PLANKS.getDefaultMapColor()).instrument(Instrument.BASS).strength(3).nonOpaque().allowsSpawning(BlockConstructionUtils::never).burnable(), UWoodTypes.PALM.setType()), ItemGroups.FUNCTIONAL);
Block PALM_PRESSURE_PLATE = register("palm_pressure_plate", new PressurePlateBlock(PressurePlateBlock.ActivationRule.EVERYTHING, Settings.create().mapColor(PALM_PLANKS.getDefaultMapColor()).noCollision().strength(0.5f).sounds(BlockSoundGroup.WOOD).pistonBehavior(PistonBehavior.DESTROY), BlockSetType.OAK), ItemGroups.BUILDING_BLOCKS);
Expand Down Expand Up @@ -127,6 +127,16 @@ public interface UBlocks {
Block SOUR_APPLE = register("sour_apple", new FruitBlock(Settings.create().mapColor(MapColor.GREEN), Direction.DOWN, SOUR_APPLE_LEAVES, FruitBlock.DEFAULT_SHAPE));
Block SOUR_APPLE_SPROUT = register("sour_apple_sprout", new SproutBlock(0xE5FFCC88, () -> UItems.SOUR_APPLE_SEEDS, () -> UTreeGen.SOUR_APPLE_TREE.sapling().map(Block::getDefaultState).get()));

Block GOLDEN_OAK_LEAVES = register("golden_oak_leaves", new GoldenOakLeavesBlock(FabricBlockSettings.copy(Blocks.OAK_LEAVES),
MapColor.GOLD.color,
() -> UBlocks.GOLDEN_APPLE,
() -> Items.GOLDEN_APPLE.getDefaultStack()
), ItemGroups.NATURAL);
Block GOLDEN_APPLE = register("golden_apple", new EnchantedFruitBlock(Settings.create().mapColor(MapColor.GOLD), Direction.DOWN, GOLDEN_OAK_LEAVES, FruitBlock.DEFAULT_SHAPE));
Block GOLDEN_OAK_SPROUT = register("golden_oak_sprout", new SproutBlock(0xE5FFCC88, () -> UItems.GOLDEN_OAK_SEEDS, () -> UTreeGen.GOLDEN_APPLE_TREE.sapling().map(Block::getDefaultState).get()));

Block GOLDEN_OAK_LOG = register("golden_oak_log", BlockConstructionUtils.createLogBlock(MapColor.OFF_WHITE, MapColor.GOLD), ItemGroups.BUILDING_BLOCKS);

Block APPLE_PIE = register("apple_pie", new PieBlock(Settings.create().solid().mapColor(MapColor.ORANGE).strength(0.5F).sounds(BlockSoundGroup.WOOL).pistonBehavior(PistonBehavior.DESTROY),
() -> UItems.APPLE_PIE_SLICE,
() -> UItems.APPLE_PIE,
Expand Down Expand Up @@ -254,10 +264,12 @@ static void bootstrap() {
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(GOLDEN_OAK_LEAVES, 60, 120);
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);
FlammableBlockRegistry.getDefaultInstance().add(GOLDEN_OAK_LOG, 15, 15);
FlammableBlockRegistry.getDefaultInstance().add(STRIPPED_PALM_LOG, 5, 5);
FlammableBlockRegistry.getDefaultInstance().add(STRIPPED_PALM_WOOD, 5, 5);
FlammableBlockRegistry.getDefaultInstance().add(PALM_PLANKS, 5, 20);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

public interface UWoodTypes {
WoodType PALM = register("palm");
WoodType GOLDEN_OAK = register("golden_oak");
RegistryKey<TerraformBoatType> PALM_BOAT_TYPE = TerraformBoatTypeRegistry.createKey(Unicopia.id("palm"));

BlockSetType CLOUD = new BlockSetTypeBuilder()
Expand Down
1 change: 1 addition & 0 deletions src/main/java/com/minelittlepony/unicopia/item/UItems.java
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ EntityAttributes.GENERIC_KNOCKBACK_RESISTANCE, new EntityAttributeModifier(Blunt
Item GREEN_APPLE_SEEDS = register("green_apple_seeds", new AliasedBlockItem(UBlocks.GREEN_APPLE_SPROUT, new Item.Settings()), ItemGroups.NATURAL);
Item SWEET_APPLE_SEEDS = register("sweet_apple_seeds", new AliasedBlockItem(UBlocks.SWEET_APPLE_SPROUT, new Item.Settings()), ItemGroups.NATURAL);
Item SOUR_APPLE_SEEDS = register("sour_apple_seeds", new AliasedBlockItem(UBlocks.SOUR_APPLE_SPROUT, new Item.Settings()), ItemGroups.NATURAL);
Item GOLDEN_OAK_SEEDS = register("golden_oak_seeds", new AliasedBlockItem(UBlocks.GOLDEN_OAK_SPROUT, new Item.Settings()), ItemGroups.NATURAL);

Item MUG = register("mug", new Item(new Settings().maxCount(16)), ItemGroups.TOOLS);
Item CIDER = register("cider", new DrinkableItem(new Item.Settings().food(UFoodComponents.CIDER).maxCount(1).recipeRemainder(MUG)), ItemGroups.FOOD_AND_DRINK);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,16 @@ public interface UTreeGen {
Tree GREEN_APPLE_TREE = createAppleTree("green_apple", UBlocks.GREEN_APPLE_LEAVES, 2);
Tree SWEET_APPLE_TREE = createAppleTree("sweet_apple", UBlocks.SWEET_APPLE_LEAVES, 3);
Tree SOUR_APPLE_TREE = createAppleTree("sour_apple", UBlocks.SOUR_APPLE_LEAVES, 5);
Tree GOLDEN_APPLE_TREE = Tree.Builder.create(Unicopia.id("golden_oak_tree"),
new StraightTrunkPlacer(6, 7, 3),
new BlobFoliagePlacer(ConstantIntProvider.create(3), ConstantIntProvider.create(0), 3)
)
.configure(TreeFeatureConfig.Builder::forceDirt)
.farmingCondition(1, 3, 5)
.log(UBlocks.GOLDEN_OAK_LOG)
.leaves(UBlocks.GOLDEN_OAK_LEAVES)
.sapling(Unicopia.id("golden_oak_sapling"))
.build();
Tree BANANA_TREE = Tree.Builder.create(Unicopia.id("banana_tree"),
new StraightTrunkPlacer(4, 5, 3),
new FernFoliagePlacer(ConstantIntProvider.create(4), ConstantIntProvider.create(0))
Expand Down Expand Up @@ -84,6 +94,8 @@ static Tree createAppleTree(String name, Block leaves, int preferredDensity) {
new BlobFoliagePlacer(ConstantIntProvider.create(3), ConstantIntProvider.create(0), 3)
)
.configure(TreeFeatureConfig.Builder::forceDirt)
.biomes(selector -> selector.hasTag(BiomeTags.IS_FOREST))
.count(2, 0.01F, 1)
.farmingCondition(1, preferredDensity - 2, preferredDensity)
.log(Blocks.OAK_LOG)
.leaves(leaves)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "unicopia:block/golden_apple"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "unicopia:block/golden_oak_leaves"
}
}
}
Loading

0 comments on commit ae6e7a0

Please sign in to comment.