From 476d779b3d670ee9a8606ed6b5cfcc31b67bfb3b Mon Sep 17 00:00:00 2001 From: LingVarr Date: Thu, 8 Feb 2024 00:15:58 +1100 Subject: [PATCH 01/13] Update ru_ru.json --- src/main/resources/assets/unicopia/lang/ru_ru.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/resources/assets/unicopia/lang/ru_ru.json b/src/main/resources/assets/unicopia/lang/ru_ru.json index 5c289ae3..27e4b38a 100644 --- a/src/main/resources/assets/unicopia/lang/ru_ru.json +++ b/src/main/resources/assets/unicopia/lang/ru_ru.json @@ -1447,6 +1447,8 @@ "death.attack.unicopia.horseshoe.self": "%1$s зарядил подковой в себя", "death.attack.unicopia.horseshoe.item": "%2$s зарядил подковой в %1$s используя %3$s", "death.attack.unicopia.horseshoe.player": "%2$s зарядил подковой в %1$s", + "death.attack.unicopia.spikes": "%1$s был заколот до смерти", + "death.attack.unicopia.spikes.player": "%1$s упал на шипы, пытаясь спастись от %2$s", "death.fell.accident.ladder.pegasus": "%1$s забыл, что умеет летать, и упал с лестницы", "death.fell.accident.vines.pegasus": "%1$s забыл, что умеет летать, и упал с лозы", From 1b688ac9f4a1443eb185b75421c66134c59f3fba Mon Sep 17 00:00:00 2001 From: Sollace Date: Thu, 8 Feb 2024 22:16:50 +0000 Subject: [PATCH 02/13] Only load these if the mod is present --- .../data/unicopia/loot_tables/blocks/rice_block.json | 8 ++++++++ .../data/unicopia/loot_tables/blocks/straw_block.json | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/src/main/resources/data/unicopia/loot_tables/blocks/rice_block.json b/src/main/resources/data/unicopia/loot_tables/blocks/rice_block.json index 20a3852d..e79c51d7 100644 --- a/src/main/resources/data/unicopia/loot_tables/blocks/rice_block.json +++ b/src/main/resources/data/unicopia/loot_tables/blocks/rice_block.json @@ -1,5 +1,13 @@ { "type": "minecraft:block", + "fabric:load_conditions": [ + { + "condition": "fabric:all_mods_loaded", + "values": [ + "farmersdelight" + ] + } + ], "pools": [ { "bonus_rolls": 0.0, diff --git a/src/main/resources/data/unicopia/loot_tables/blocks/straw_block.json b/src/main/resources/data/unicopia/loot_tables/blocks/straw_block.json index ab4fa683..ca46ba50 100644 --- a/src/main/resources/data/unicopia/loot_tables/blocks/straw_block.json +++ b/src/main/resources/data/unicopia/loot_tables/blocks/straw_block.json @@ -1,5 +1,13 @@ { "type": "minecraft:block", + "fabric:load_conditions": [ + { + "condition": "fabric:all_mods_loaded", + "values": [ + "farmersdelight" + ] + } + ], "pools": [ { "bonus_rolls": 0.0, From 5e099aeea5f0569714088d701be3500983659cc7 Mon Sep 17 00:00:00 2001 From: Sollace Date: Thu, 8 Feb 2024 22:16:50 +0000 Subject: [PATCH 03/13] Only load these if the mod is present --- .../data/unicopia/loot_tables/blocks/rice_block.json | 8 ++++++++ .../data/unicopia/loot_tables/blocks/straw_block.json | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/src/main/resources/data/unicopia/loot_tables/blocks/rice_block.json b/src/main/resources/data/unicopia/loot_tables/blocks/rice_block.json index 20a3852d..e79c51d7 100644 --- a/src/main/resources/data/unicopia/loot_tables/blocks/rice_block.json +++ b/src/main/resources/data/unicopia/loot_tables/blocks/rice_block.json @@ -1,5 +1,13 @@ { "type": "minecraft:block", + "fabric:load_conditions": [ + { + "condition": "fabric:all_mods_loaded", + "values": [ + "farmersdelight" + ] + } + ], "pools": [ { "bonus_rolls": 0.0, diff --git a/src/main/resources/data/unicopia/loot_tables/blocks/straw_block.json b/src/main/resources/data/unicopia/loot_tables/blocks/straw_block.json index ab4fa683..ca46ba50 100644 --- a/src/main/resources/data/unicopia/loot_tables/blocks/straw_block.json +++ b/src/main/resources/data/unicopia/loot_tables/blocks/straw_block.json @@ -1,5 +1,13 @@ { "type": "minecraft:block", + "fabric:load_conditions": [ + { + "condition": "fabric:all_mods_loaded", + "values": [ + "farmersdelight" + ] + } + ], "pools": [ { "bonus_rolls": 0.0, From 34566b560e0b439afa1dc87bb49f75fbd0431853 Mon Sep 17 00:00:00 2001 From: Sollace Date: Thu, 8 Feb 2024 22:59:21 +0000 Subject: [PATCH 04/13] Add dev dependencies --- build.gradle | 14 ++++++++------ gradle.properties | 6 ++++++ 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/build.gradle b/build.gradle index b3d2c2b2..a31e3671 100644 --- a/build.gradle +++ b/build.gradle @@ -44,6 +44,8 @@ repositories { maven { name 'minelp-snapshot'; url 'https://repo.minelittlepony-mod.com/maven/snapshot' } maven { name 'minelp-releases'; url 'https://repo.minelittlepony-mod.com/maven/release' } maven { name 'TerraformersMC'; url 'https://maven.terraformersmc.com/' } + maven { name 'Modrinth'; url 'https://api.modrinth.com/maven' } + maven { name 'JitPack'; url 'https://jitpack.io'; content { includeGroup "com.github.Virtuoel" } } } dependencies { @@ -72,17 +74,17 @@ dependencies { modImplementation "com.terraformersmc.terraform-api:terraform-wood-api-v1:${project.terraformer_api_version}" include "com.terraformersmc.terraform-api:terraform-wood-api-v1:${project.terraformer_api_version}" + modCompileOnly "maven.modrinth:farmers-delight-fabric:${project.farmers_delight_version}", { exclude group: "net.fabricmc.fabric-api" } + modCompileOnly "maven.modrinth:iris:${project.iris_version}", { exclude group: "net.fabricmc.fabric-api" } + modCompileOnly "maven.modrinth:sodium:${project.sodium_version}", { exclude group: "net.fabricmc.fabric-api" } + modCompileOnly "maven.modrinth:pehkui:${project.pehkui_version}", { exclude group: "net.fabricmc.fabric-api" } + modCompileOnly "com.github.Virtuoel:KanosConfig:0.4.1", { exclude group: "net.fabricmc.fabric-api" } + if (project.tmi_type == 'emi') { modCompileOnly "dev.emi:emi-fabric:${project.emi_version}" } else { modCompileOnly "dev.emi:emi-fabric-dummy:${project.emi_version}" } - - if (project.tmi_type == 'rei') { - // TODO: - } else { - // TODO: - } } processResources { diff --git a/gradle.properties b/gradle.properties index d0bb613b..31bb681e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -28,6 +28,12 @@ org.gradle.daemon=false trinkets_version=3.7.1 terraformer_api_version=7.0.0-beta.1 +# Testing + farmers_delight_version=1.4.3 + pehkui_version=3.7.8+1.14.4-1.20.1 + iris_version=1.6.8+1.20.1 + sodium_version=mc1.20.1-0.5.2 + # TMI Testing tmi_type=emi emi_version=1.0.19+1.20.1 From 6586e7625d05e5e52eaa1b371e3e684f6367f445 Mon Sep 17 00:00:00 2001 From: LingVarr Date: Fri, 9 Feb 2024 19:12:09 +1100 Subject: [PATCH 05/13] Update ru_ru.json --- src/main/resources/assets/unicopia/lang/ru_ru.json | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/main/resources/assets/unicopia/lang/ru_ru.json b/src/main/resources/assets/unicopia/lang/ru_ru.json index 27e4b38a..c03f94db 100644 --- a/src/main/resources/assets/unicopia/lang/ru_ru.json +++ b/src/main/resources/assets/unicopia/lang/ru_ru.json @@ -232,6 +232,20 @@ "block.unicopia.zap_wood": "Зап-яблоня", "block.unicopia.stripped_zap_log": "Бревно обтёсанной зап-яблони", "block.unicopia.stripped_zap_wood": "Обтёсанная древесина зап-яблони", + "block.unicopia.zap_planks": "Зап-яблочные доски", + "block.unicopia.zap_stairs": "Зап-яблочные ступеньки", + "block.unicopia.zap_slab": "Зап-яблочная плита", + "block.unicopia.zap_fence": "Зап-яблочный забор", + "block.unicopia.zap_fence_gate": "Зап-яблочная калитка", + "block.unicopia.waxed_zap_log": "Вощёное бревно зап-яблони", + "block.unicopia.waxed_zap_wood": "Вощёная древесина зап-яблони", + "block.unicopia.waxed_stripped_zap_log": "Вощёное бревно обтёсанной зап-яблони", + "block.unicopia.waxed_stripped_zap_wood": "Вощёная древесина обтёсанной зап-яблони", + "block.unicopia.waxed_zap_planks": "Вощёные доски зап-яблони", + "block.unicopia.waxed_zap_stairs": "Вощёные ступеньки зап-яблони", + "block.unicopia.waxed_zap_slab": "Вощёная плита зап-яблони", + "block.unicopia.waxed_zap_fence": "Вощёный зап-яблочный забор", + "block.unicopia.waxed_zap_fence_gate": "Вощёная зап-яблочная калитка", "block.unicopia.zap_leaves": "Листья зап-яблони", "block.unicopia.flowering_zap_leaves": "Листья цветущей зап-яблони", "block.unicopia.zap_apple": "Зап-яблоня", From 9599d0044baf6a3d33a30a434d5cc38cfaf0ebf9 Mon Sep 17 00:00:00 2001 From: Sollace Date: Sat, 10 Feb 2024 01:10:10 +0000 Subject: [PATCH 06/13] Update minelp --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 31bb681e..68f968c9 100644 --- a/gradle.properties +++ b/gradle.properties @@ -22,7 +22,7 @@ org.gradle.daemon=false # Dependencies fabwork_version=1.2.0 modmenu_version=7.0.0-beta.2 - minelp_version=4.10.1+1.20 + minelp_version=4.10.4+1.20.1 kirin_version=1.15.4+1.20 reach_attributes_version=2.3.3 trinkets_version=3.7.1 From ded8499e9f7537008c79a192683d0431cefb20e0 Mon Sep 17 00:00:00 2001 From: Sollace Date: Sat, 10 Feb 2024 18:16:15 +0000 Subject: [PATCH 07/13] Adjust tree spawn rate and add a sweet apple orchard biome --- .../unicopia/block/FruitBearingBlock.java | 6 +- .../unicopia/block/GoldenOakLeavesBlock.java | 2 +- .../mixin/MixinVanillaBiomeParameters.java | 23 ++ .../unicopia/server/world/Tree.java | 62 +++--- .../unicopia/server/world/UTreeGen.java | 42 ++-- .../unicopia/server/world/UWorldGen.java | 11 + .../world/gen/BiomeSelectionContext.java | 31 +++ .../world/gen/BiomeSelectionInjector.java | 185 ++++++++++++++++ .../world/gen/FruitBlobFoliagePlacer.java | 51 +++++ .../gen/OverworldBiomeSelectionCallback.java | 23 ++ .../textures/block/sweet_apple_leaves.png | Bin 2369 -> 7105 bytes .../tags/worldgen/biome/is_forest.json | 6 + .../worldgen/biome/sweet_apple_orchard.json | 199 ++++++++++++++++++ src/main/resources/unicopia.mixin.json | 1 + 14 files changed, 592 insertions(+), 50 deletions(-) create mode 100644 src/main/java/com/minelittlepony/unicopia/mixin/MixinVanillaBiomeParameters.java create mode 100644 src/main/java/com/minelittlepony/unicopia/server/world/gen/BiomeSelectionContext.java create mode 100644 src/main/java/com/minelittlepony/unicopia/server/world/gen/BiomeSelectionInjector.java create mode 100644 src/main/java/com/minelittlepony/unicopia/server/world/gen/FruitBlobFoliagePlacer.java create mode 100644 src/main/java/com/minelittlepony/unicopia/server/world/gen/OverworldBiomeSelectionCallback.java create mode 100644 src/main/resources/data/minecraft/tags/worldgen/biome/is_forest.json create mode 100644 src/main/resources/data/unicopia/worldgen/biome/sweet_apple_orchard.json diff --git a/src/main/java/com/minelittlepony/unicopia/block/FruitBearingBlock.java b/src/main/java/com/minelittlepony/unicopia/block/FruitBearingBlock.java index b9741cef..54e64851 100644 --- a/src/main/java/com/minelittlepony/unicopia/block/FruitBearingBlock.java +++ b/src/main/java/com/minelittlepony/unicopia/block/FruitBearingBlock.java @@ -66,7 +66,7 @@ public class FruitBearingBlock extends LeavesBlock implements TintedBlock, Bucka return true; } - protected BlockState getPlacedFruitState(Random random) { + public BlockState getPlacedFruitState(Random random) { return fruit.get().getDefaultState(); } @@ -107,7 +107,7 @@ public class FruitBearingBlock extends LeavesBlock implements TintedBlock, Bucka BlockState fruitState = world.getBlockState(fruitPosition); - if (stage == Stage.WITHERING && fruitState.isOf(fruit.get())) { + if (stage == Stage.WITHERING && fruitState.isOf(fruit.get()) && world.isPlayerInRange(pos.getX(), pos.getY(), pos.getZ(), 25)) { if (world.random.nextInt(2) == 0) { Block.dropStack(world, fruitPosition, rottenFruitSupplier.get()); } else { @@ -141,7 +141,7 @@ public class FruitBearingBlock extends LeavesBlock implements TintedBlock, Bucka return TintedBlock.blend(foliageColor, overlay); } - private boolean isPositionValidForFruit(BlockState state, BlockPos pos) { + public boolean isPositionValidForFruit(BlockState state, BlockPos pos) { return state.getRenderingSeed(pos) % 3 == 1; } diff --git a/src/main/java/com/minelittlepony/unicopia/block/GoldenOakLeavesBlock.java b/src/main/java/com/minelittlepony/unicopia/block/GoldenOakLeavesBlock.java index 1ae9ed61..fe09f0bd 100644 --- a/src/main/java/com/minelittlepony/unicopia/block/GoldenOakLeavesBlock.java +++ b/src/main/java/com/minelittlepony/unicopia/block/GoldenOakLeavesBlock.java @@ -20,7 +20,7 @@ public class GoldenOakLeavesBlock extends FruitBearingBlock { } @Override - protected BlockState getPlacedFruitState(Random random) { + public BlockState getPlacedFruitState(Random random) { return super.getPlacedFruitState(random).with(EnchantedFruitBlock.ENCHANTED, random.nextInt(1000) == 0); } } diff --git a/src/main/java/com/minelittlepony/unicopia/mixin/MixinVanillaBiomeParameters.java b/src/main/java/com/minelittlepony/unicopia/mixin/MixinVanillaBiomeParameters.java new file mode 100644 index 00000000..5a1c0a72 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/mixin/MixinVanillaBiomeParameters.java @@ -0,0 +1,23 @@ +package com.minelittlepony.unicopia.mixin; + +import java.util.function.Consumer; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.ModifyVariable; + +import com.minelittlepony.unicopia.server.world.gen.BiomeSelectionInjector; +import com.mojang.datafixers.util.Pair; + +import net.minecraft.registry.RegistryKey; +import net.minecraft.world.biome.Biome; +import net.minecraft.world.biome.source.util.MultiNoiseUtil; +import net.minecraft.world.biome.source.util.VanillaBiomeParameters; + +@Mixin(VanillaBiomeParameters.class) +abstract class MixinVanillaBiomeParameters { + @ModifyVariable(method = "writeOverworldBiomeParameters", at = @At("HEAD")) + private Consumer>> onWriteOverworldBiomeParameters(Consumer>> parametersCollector) { + return new BiomeSelectionInjector(parametersCollector); + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/server/world/Tree.java b/src/main/java/com/minelittlepony/unicopia/server/world/Tree.java index 885effb5..7128f919 100644 --- a/src/main/java/com/minelittlepony/unicopia/server/world/Tree.java +++ b/src/main/java/com/minelittlepony/unicopia/server/world/Tree.java @@ -4,6 +4,7 @@ import java.util.*; import java.util.function.BiFunction; import java.util.function.Function; import java.util.function.Predicate; +import java.util.stream.Collectors; import com.minelittlepony.unicopia.block.UBlocks; @@ -17,10 +18,11 @@ import net.minecraft.util.Identifier; import net.minecraft.util.math.random.Random; import net.minecraft.registry.*; import net.minecraft.registry.tag.BiomeTags; -import net.minecraft.world.gen.GenerationStep; +import net.minecraft.world.biome.BiomeKeys; import net.minecraft.world.gen.feature.*; import net.minecraft.world.gen.feature.size.TwoLayersFeatureSize; import net.minecraft.world.gen.foliage.FoliagePlacer; +import net.minecraft.world.gen.GenerationStep; import net.minecraft.world.gen.placementmodifier.PlacementModifier; import net.minecraft.world.gen.stateprovider.BlockStateProvider; import net.minecraft.world.gen.trunk.TrunkPlacer; @@ -29,9 +31,8 @@ public record Tree ( Identifier id, TreeFeatureConfig.Builder config, RegistryKey> configuredFeatureId, - Optional> placedFeatureId, - Optional sapling, - Optional placement + Set placements, + Optional sapling ) { public static final List REGISTRY = new ArrayList<>(); @@ -44,20 +45,22 @@ public record Tree ( }); registries.getOptional(RegistryKeys.PLACED_FEATURE).ifPresent(registry -> { var reg = registries.asDynamicRegistryManager().createRegistryLookup().getOrThrow(RegistryKeys.CONFIGURED_FEATURE); - REGISTRY.stream().filter(tree -> tree.placedFeatureId().isPresent()).forEach(tree -> { - var placedFeature = new PlacedFeature(reg.getOrThrow(tree.configuredFeatureId()), - VegetationPlacedFeatures.treeModifiersWithWouldSurvive(tree.placement().orElseThrow(), tree.sapling().orElse(Blocks.OAK_SAPLING)) - ); - - Registry.register(registry, tree.id, placedFeature); + REGISTRY.stream().forEach(tree -> { + tree.placements().forEach(placement -> { + Registry.register(registry, placement.id(), new PlacedFeature(reg.getOrThrow(tree.configuredFeatureId()), + VegetationPlacedFeatures.treeModifiersWithWouldSurvive(placement.count(), tree.sapling().orElse(Blocks.OAK_SAPLING)) + )); + }); }); }); }); - } public static class Builder { public static final Predicate IS_FOREST = BiomeSelectors.foundInOverworld().and(BiomeSelectors.tag(BiomeTags.IS_FOREST)); + public static final Predicate IS_OAK_FOREST = IS_FOREST + .and(BiomeSelectors.excludeByKey(BiomeKeys.BIRCH_FOREST, BiomeKeys.OLD_GROWTH_BIRCH_FOREST, BiomeKeys.DARK_FOREST)) + .and(BiomeSelectors.tag(BiomeTags.IS_TAIGA).negate()); public static Builder create(Identifier id, TrunkPlacer trunkPlacer, FoliagePlacer foliagePlacer) { return new Builder(id, trunkPlacer, foliagePlacer); @@ -73,8 +76,7 @@ public record Tree ( private final Identifier id; - private Optional> selector = Optional.empty(); - private Optional countModifier = Optional.empty(); + private Map placements = new HashMap<>(); private Function configParameters = Function.identity(); private Optional size = Optional.empty(); @@ -104,13 +106,18 @@ public record Tree ( return this; } - public Builder count(int count, float extraChance, int extraCount) { - countModifier = Optional.of(PlacedFeatures.createCountExtraModifier(count, extraChance, extraCount)); - return this; + public Builder placement(int count, float extraChance, int extraCount, Predicate selector) { + return placement("", count, extraChance, extraCount, selector); } - public Builder biomes(Predicate selector) { - this.selector = Optional.of(selector); + public Builder placement(String suffex, int count, float extraChance, int extraCount, Predicate selector) { + Identifier id = this.id.withSuffixedPath("/placed" + (suffex.isEmpty() ? "" : "/") + suffex); + placements.put(id, new Placement( + id, + PlacedFeatures.createCountExtraModifier(count, extraChance, extraCount), + RegistryKey.of(RegistryKeys.PLACED_FEATURE, id), + selector + )); return this; } @@ -119,7 +126,7 @@ public record Tree ( return this; } - public Builder farmingCondition(int yLevel, int sizeBelowY, int sizeAboveY) { + public Builder dimensions(int yLevel, int sizeBelowY, int sizeAboveY) { this.size = Optional.of(new TwoLayersFeatureSize(yLevel, Math.max(0, sizeBelowY), Math.max(0, sizeAboveY))); return this; } @@ -132,23 +139,28 @@ public record Tree ( BlockStateProvider.of(leavesType), foliagePlacer, size.get() - )), configuredFeatureId, selector.map(selector -> { - RegistryKey i = RegistryKey.of(RegistryKeys.PLACED_FEATURE, id); - BiomeModifications.addFeature(selector, GenerationStep.Feature.VEGETAL_DECORATION, i); - return i; - }), saplingId.map(id -> UBlocks.register(id, saplingConstructor.apply(new SaplingGenerator() { + )), configuredFeatureId, placements.values().stream() + .collect(Collectors.toUnmodifiableSet()), + saplingId.map(id -> UBlocks.register(id, saplingConstructor.apply(new SaplingGenerator() { @Override protected RegistryKey> getTreeFeature(Random rng, boolean flowersNearby) { return configuredFeatureId; } - }, FabricBlockSettings.copy(Blocks.OAK_SAPLING)), ItemGroups.NATURAL)), countModifier); + }, FabricBlockSettings.copy(Blocks.OAK_SAPLING)), ItemGroups.NATURAL))); if (REGISTRY.isEmpty()) { bootstrap(); } REGISTRY.add(tree); + tree.placements().forEach(placement -> { + BiomeModifications.addFeature(placement.selector(), GenerationStep.Feature.VEGETAL_DECORATION, placement.feature()); + }); return tree; } } + + public record Placement(Identifier id, PlacementModifier count, RegistryKey feature, Predicate selector) { + + } } diff --git a/src/main/java/com/minelittlepony/unicopia/server/world/UTreeGen.java b/src/main/java/com/minelittlepony/unicopia/server/world/UTreeGen.java index 0d456e02..7ad5aa26 100644 --- a/src/main/java/com/minelittlepony/unicopia/server/world/UTreeGen.java +++ b/src/main/java/com/minelittlepony/unicopia/server/world/UTreeGen.java @@ -3,7 +3,9 @@ package com.minelittlepony.unicopia.server.world; import com.google.common.collect.ImmutableList; import com.minelittlepony.unicopia.Unicopia; import com.minelittlepony.unicopia.block.UBlocks; +import com.minelittlepony.unicopia.server.world.gen.FruitBlobFoliagePlacer; +import net.fabricmc.fabric.api.biome.v1.BiomeSelectors; import net.minecraft.block.*; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.intprovider.ConstantIntProvider; @@ -39,19 +41,20 @@ public interface UTreeGen { .log(UBlocks.ZAP_LOG) .leaves(UBlocks.ZAP_LEAVES) .sapling(Unicopia.id("zapling")) - .biomes(Tree.Builder.IS_FOREST) - .count(0, 0.01F, 1) - .farmingCondition(6, 0, 8) + .placement(0, 0.01F, 1, Tree.Builder.IS_FOREST) + .dimensions(6, 0, 8) .build(); - 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 GREEN_APPLE_TREE = createAppleTree("green_apple", UBlocks.GREEN_APPLE_LEAVES, 2, 0.2F).build(); + Tree SWEET_APPLE_TREE = createAppleTree("sweet_apple", UBlocks.SWEET_APPLE_LEAVES, 3, 0.1F) + .placement("orchard", 6, 0.1F, 3, BiomeSelectors.includeByKey(UWorldGen.SWEET_APPLE_ORCHARD)) + .build(); + Tree SOUR_APPLE_TREE = createAppleTree("sour_apple", UBlocks.SOUR_APPLE_LEAVES, 5, 0.2F).build(); Tree GOLDEN_APPLE_TREE = Tree.Builder.create(Unicopia.id("golden_oak_tree"), new StraightTrunkPlacer(6, 1, 3), new BlobFoliagePlacer(ConstantIntProvider.create(3), ConstantIntProvider.create(0), 3) ) .configure(TreeFeatureConfig.Builder::forceDirt) - .farmingCondition(1, 3, 5) + .dimensions(1, 3, 5) .log(UBlocks.GOLDEN_OAK_LOG) .leaves(UBlocks.GOLDEN_OAK_LEAVES) .sapling(Unicopia.id("golden_oak_sapling")) @@ -60,7 +63,7 @@ public interface UTreeGen { new StraightTrunkPlacer(4, 5, 3), new FernFoliagePlacer(ConstantIntProvider.create(4), ConstantIntProvider.create(0)) ) - .farmingCondition(6, 0, 8) + .dimensions(6, 0, 8) .log(UBlocks.PALM_LOG) .leaves(UBlocks.PALM_LEAVES) .sapling(Unicopia.id("palm_sapling")).sapling((generator, settings) -> { @@ -72,36 +75,33 @@ public interface UTreeGen { }; }) .configure(builder -> builder.dirtProvider(BlockStateProvider.of(Blocks.SAND))) - .biomes(selector -> selector.hasTag(BiomeTags.IS_BEACH) || selector.hasTag(BiomeTags.IS_JUNGLE)) - .count(2, 0.01F, 1) + .placement(2, 0.01F, 1, selector -> selector.hasTag(BiomeTags.IS_BEACH) || selector.hasTag(BiomeTags.IS_JUNGLE)) .build(); Tree MANGO_TREE = Tree.Builder.create(Unicopia.id("mango_tree"), new StraightTrunkPlacer(4, 7, 3), new BlobFoliagePlacer(ConstantIntProvider.create(3), ConstantIntProvider.create(0), 3) ) - .farmingCondition(9, 0, 4) + .dimensions(9, 0, 4) .log(Blocks.JUNGLE_LOG) .leaves(UBlocks.MANGO_LEAVES) - .biomes(selector -> selector.hasTag(BiomeTags.IS_JUNGLE) && selector.getBiomeKey() != BiomeKeys.SPARSE_JUNGLE) .sapling(Unicopia.id("mango_sapling")) - .count(1, 1, 2) + .placement(1, 1, 2, selector -> selector.hasTag(BiomeTags.IS_JUNGLE) && selector.getBiomeKey() != BiomeKeys.SPARSE_JUNGLE) .configure(builder -> builder.decorators(ImmutableList.of(TrunkVineTreeDecorator.INSTANCE, new LeavesVineTreeDecorator(0.25f)))) .build(); - static Tree createAppleTree(String name, Block leaves, int preferredDensity) { + static Tree.Builder createAppleTree(String name, Block leaves, int preferredDensity, float spawnRate) { return Tree.Builder.create(Unicopia.id(name + "_tree"), new StraightTrunkPlacer(4, 3, 2), - new BlobFoliagePlacer(ConstantIntProvider.create(3), ConstantIntProvider.create(0), 3) + new FruitBlobFoliagePlacer(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) + .placement(0, spawnRate, 4, Tree.Builder.IS_OAK_FOREST) + .dimensions(1, preferredDensity - 2, preferredDensity) .log(Blocks.OAK_LOG) .leaves(leaves) - .sapling(Unicopia.id(name + "_sapling")) - .build(); + .sapling(Unicopia.id(name + "_sapling")); } - static void bootstrap() { } + static void bootstrap() { + } } diff --git a/src/main/java/com/minelittlepony/unicopia/server/world/UWorldGen.java b/src/main/java/com/minelittlepony/unicopia/server/world/UWorldGen.java index 097fdc9f..69a7991e 100644 --- a/src/main/java/com/minelittlepony/unicopia/server/world/UWorldGen.java +++ b/src/main/java/com/minelittlepony/unicopia/server/world/UWorldGen.java @@ -5,6 +5,7 @@ import java.util.List; import com.minelittlepony.unicopia.Unicopia; import com.minelittlepony.unicopia.block.ShellsBlock; import com.minelittlepony.unicopia.block.UBlocks; +import com.minelittlepony.unicopia.server.world.gen.OverworldBiomeSelectionCallback; import net.fabricmc.fabric.api.biome.v1.BiomeModifications; import net.fabricmc.fabric.api.biome.v1.BiomeSelectors; @@ -13,11 +14,13 @@ import net.minecraft.block.Blocks; import net.minecraft.registry.Registries; import net.minecraft.registry.Registry; import net.minecraft.registry.RegistryKey; +import net.minecraft.registry.RegistryKeys; import net.minecraft.registry.tag.BiomeTags; import net.minecraft.util.collection.DataPool; import net.minecraft.util.math.Direction; import net.minecraft.util.math.Vec3i; import net.minecraft.util.math.intprovider.UniformIntProvider; +import net.minecraft.world.biome.Biome; import net.minecraft.world.biome.BiomeKeys; import net.minecraft.world.gen.GenerationStep; import net.minecraft.world.gen.blockpredicate.BlockPredicate; @@ -66,6 +69,8 @@ public interface UWorldGen { BiomePlacementModifier.of() )); + RegistryKey SWEET_APPLE_ORCHARD = RegistryKey.of(RegistryKeys.BIOME, Unicopia.id("sweet_apple_orchard")); + static void bootstrap() { BiomeModifications.addFeature(BiomeSelectors.tag(BiomeTags.IS_JUNGLE), GenerationStep.Feature.VEGETAL_DECORATION, PINEAPPLE_PLANT_PLACED_FEATURE); BiomeModifications.addFeature( @@ -75,5 +80,11 @@ public interface UWorldGen { .or(BiomeSelectors.includeByKey(BiomeKeys.STONY_SHORE)) ), GenerationStep.Feature.VEGETAL_DECORATION, SHELLS_PLACED_FEATURE); UTreeGen.bootstrap(); + + OverworldBiomeSelectionCallback.EVENT.register(context -> { + if (context.biomeKey() == BiomeKeys.FOREST) { + context.addOverride(context.referenceFrame().temperature().splitAbove(0.9F), SWEET_APPLE_ORCHARD); + } + }); } } diff --git a/src/main/java/com/minelittlepony/unicopia/server/world/gen/BiomeSelectionContext.java b/src/main/java/com/minelittlepony/unicopia/server/world/gen/BiomeSelectionContext.java new file mode 100644 index 00000000..1ee71b66 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/server/world/gen/BiomeSelectionContext.java @@ -0,0 +1,31 @@ +package com.minelittlepony.unicopia.server.world.gen; + +import org.jetbrains.annotations.Nullable; + +import net.minecraft.registry.RegistryKey; +import net.minecraft.world.biome.Biome; + +public interface BiomeSelectionContext { + RegistryKey biomeKey(); + + SplittableBiomeCoordinate referenceFrame(); + + @Nullable + RegistryKey addOverride(SplittableBiomeCoordinate coordinate, RegistryKey biome); + + public record SplittableBiomeCoordinate( + SplitableParameterRange temperature, + SplitableParameterRange humidity, + SplitableParameterRange continentalness, + SplitableParameterRange erosion, + SplitableParameterRange depth, + SplitableParameterRange weirdness, + long offset) { + } + + public interface SplitableParameterRange { + SplittableBiomeCoordinate splitAbove(float midpoint); + + SplittableBiomeCoordinate splitBelow(float midpoint); + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/server/world/gen/BiomeSelectionInjector.java b/src/main/java/com/minelittlepony/unicopia/server/world/gen/BiomeSelectionInjector.java new file mode 100644 index 00000000..1b94b690 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/server/world/gen/BiomeSelectionInjector.java @@ -0,0 +1,185 @@ +package com.minelittlepony.unicopia.server.world.gen; + +import java.util.Comparator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.stream.Stream; + +import org.jetbrains.annotations.Nullable; +import org.spongepowered.include.com.google.common.base.Objects; + +import com.minelittlepony.unicopia.server.world.gen.BiomeSelectionContext.SplittableBiomeCoordinate; +import com.mojang.datafixers.util.Pair; + +import net.minecraft.registry.RegistryKey; +import net.minecraft.util.math.MathHelper; +import net.minecraft.world.biome.Biome; +import net.minecraft.world.biome.source.util.MultiNoiseUtil; +import net.minecraft.world.biome.source.util.MultiNoiseUtil.NoiseHypercube; +import net.minecraft.world.biome.source.util.MultiNoiseUtil.ParameterRange; + +public final class BiomeSelectionInjector implements Consumer>> { + + private final Consumer>> parameterConsumer; + + public BiomeSelectionInjector(Consumer>> parameterConsumer) { + this.parameterConsumer = parameterConsumer; + } + + @Override + public void accept(Pair> parameter) { + Context context = new Context(parameter); + OverworldBiomeSelectionCallback.EVENT.invoker().onSelectingBiome(context); + if (!context.overrides.isEmpty()) { + List>> subSections = List.of(parameter); + // sort splits from largest to smallest + var divisions = context.overrides.entrySet() + .stream() + .sorted(Comparator.>, Float>comparing(entry -> Context.getVolume(entry.getKey())).reversed()) + .toList(); + // recursively sub-divide into parts so every split gets a (kinda) fair share + for (Map.Entry> division : divisions) { + subSections = subSections.stream().flatMap(par -> Stream.of( + Pair.of(Context.write(division.getKey(), par.getFirst()), division.getValue()), + par + )).toList(); + } + // output the result + subSections.forEach(parameterConsumer); + } else { + parameterConsumer.accept(parameter); + } + } + + class Context implements BiomeSelectionContext { + private final Pair> parameter; + private final Map> overrides = new LinkedHashMap<>(); + + public Context(Pair> parameter) { + this.parameter = parameter; + } + + @Override + public RegistryKey biomeKey() { + return parameter.getSecond(); + } + + @Override + public SplittableBiomeCoordinate referenceFrame() { + return createStart(parameter.getFirst()); + } + + @Override + @Nullable + public RegistryKey addOverride(SplittableBiomeCoordinate coordinate, RegistryKey biome) { + return overrides.put(coordinate, biome); + } + + static float getVolume(SplittableBiomeCoordinate coordinate) { + return ((SplitableParameterRangeImpl)coordinate.temperature()).length() + * ((SplitableParameterRangeImpl)coordinate.humidity()).length() + * ((SplitableParameterRangeImpl)coordinate.continentalness()).length() + * ((SplitableParameterRangeImpl)coordinate.erosion()).length() + * ((SplitableParameterRangeImpl)coordinate.depth()).length() + * ((SplitableParameterRangeImpl)coordinate.weirdness()).length(); + } + + static NoiseHypercube write(SplittableBiomeCoordinate coordinate, NoiseHypercube referenceFrame) { + return new NoiseHypercube( + ((SplitableParameterRangeImpl)coordinate.temperature()).write(referenceFrame.temperature()), + ((SplitableParameterRangeImpl)coordinate.humidity()).write(referenceFrame.humidity()), + ((SplitableParameterRangeImpl)coordinate.continentalness()).write(referenceFrame.continentalness()), + ((SplitableParameterRangeImpl)coordinate.erosion()).write(referenceFrame.erosion()), + ((SplitableParameterRangeImpl)coordinate.depth()).write(referenceFrame.depth()), + ((SplitableParameterRangeImpl)coordinate.weirdness()).write(referenceFrame.weirdness()), + coordinate.offset() + ); + } + + static SplittableBiomeCoordinate createStart(NoiseHypercube referenceFrame) { + final SplittableBiomeCoordinate[] self = new SplittableBiomeCoordinate[1]; + return self[0] = new SplittableBiomeCoordinate( + new SplitableParameterRangeImpl(self, SplittableBiomeCoordinate::temperature, 0, 1), + new SplitableParameterRangeImpl(self, SplittableBiomeCoordinate::humidity, 0, 1), + new SplitableParameterRangeImpl(self, SplittableBiomeCoordinate::continentalness, 0, 1), + new SplitableParameterRangeImpl(self, SplittableBiomeCoordinate::erosion, 0, 1), + new SplitableParameterRangeImpl(self, SplittableBiomeCoordinate::depth, 0, 1), + new SplitableParameterRangeImpl(self, SplittableBiomeCoordinate::weirdness, 0, 1), + referenceFrame.offset() + ); + } + + static SplittableBiomeCoordinate createCopy(SplittableBiomeCoordinate old) { + final SplittableBiomeCoordinate[] self = new SplittableBiomeCoordinate[1]; + return self[0] = new SplittableBiomeCoordinate( + new SplitableParameterRangeImpl(self, (SplitableParameterRangeImpl)old.temperature()), + new SplitableParameterRangeImpl(self, (SplitableParameterRangeImpl)old.humidity()), + new SplitableParameterRangeImpl(self, (SplitableParameterRangeImpl)old.continentalness()), + new SplitableParameterRangeImpl(self, (SplitableParameterRangeImpl)old.erosion()), + new SplitableParameterRangeImpl(self, (SplitableParameterRangeImpl)old.depth()), + new SplitableParameterRangeImpl(self, (SplitableParameterRangeImpl)old.weirdness()), + old.offset() + ); + } + + private static final class SplitableParameterRangeImpl implements SplitableParameterRange { + private final SplittableBiomeCoordinate[] coordinate; + private final Function dimension; + private float min; + private float max; + + SplitableParameterRangeImpl(SplittableBiomeCoordinate[] coordinate, SplitableParameterRangeImpl original) { + this(coordinate, original.dimension, original.min, original.max); + } + + SplitableParameterRangeImpl(SplittableBiomeCoordinate[] coordinate, Function dimension, float min, float max) { + this.coordinate = coordinate; + this.dimension = dimension; + this.min = min; + this.max = max; + } + + @Override + public SplittableBiomeCoordinate splitAbove(float midpoint) { + return copyWithDifference(o -> o.min = MathHelper.lerp(midpoint, o.min, o.max)); + } + + @Override + public SplittableBiomeCoordinate splitBelow(float midpoint) { + return copyWithDifference(o -> o.max = MathHelper.lerp(midpoint, o.min, o.max)); + } + + private SplittableBiomeCoordinate copyWithDifference(Consumer mutator) { + SplittableBiomeCoordinate copy = createCopy(coordinate[0]); + mutator.accept((SplitableParameterRangeImpl)dimension.apply(copy)); + return copy; + } + + public ParameterRange write(ParameterRange range) { + return ParameterRange.of( + MultiNoiseUtil.toFloat(range.min()) * (1 + min), + MultiNoiseUtil.toFloat(range.max()) * max + ); + } + + public float length() { + return max - min; + } + + @Override + public boolean equals(Object o) { + return o instanceof SplitableParameterRangeImpl i + && MathHelper.approximatelyEquals(i.min, min) + && MathHelper.approximatelyEquals(i.max, max); + } + + @Override + public int hashCode() { + return Objects.hashCode(min, max); + } + } + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/server/world/gen/FruitBlobFoliagePlacer.java b/src/main/java/com/minelittlepony/unicopia/server/world/gen/FruitBlobFoliagePlacer.java new file mode 100644 index 00000000..db32594e --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/server/world/gen/FruitBlobFoliagePlacer.java @@ -0,0 +1,51 @@ +package com.minelittlepony.unicopia.server.world.gen; + +import java.util.HashMap; +import java.util.Map; + +import org.joml.Vector2i; + +import com.minelittlepony.unicopia.block.FruitBearingBlock; +import com.mojang.datafixers.util.Pair; + +import net.minecraft.block.BlockState; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.intprovider.IntProvider; +import net.minecraft.util.math.random.Random; +import net.minecraft.world.TestableWorld; +import net.minecraft.world.gen.feature.TreeFeatureConfig; +import net.minecraft.world.gen.foliage.BlobFoliagePlacer; + +public class FruitBlobFoliagePlacer extends BlobFoliagePlacer { + + public FruitBlobFoliagePlacer(IntProvider radius, IntProvider offset, int height) { + super(radius, offset, height); + } + + @Override + public void generate(TestableWorld world, BlockPlacer placer, Random random, TreeFeatureConfig config, int trunkHeight, TreeNode treeNode, int foliageHeight, int radius) { + final Map> leafPositions = new HashMap<>(); + super.generate(world, new BlockPlacer() { + @Override + public void placeBlock(BlockPos pos, BlockState state) { + placer.placeBlock(pos, state); + if (state.getBlock() instanceof FruitBearingBlock block + && block.isPositionValidForFruit(state, pos)) { + leafPositions.compute(new Vector2i(pos.getX(), pos.getZ()), (col, original) -> original == null || original.getSecond() > pos.getY() ? Pair.of(block, pos.getY()) : original); + } + } + + @Override + public boolean hasPlacedBlock(BlockPos pos) { + return placer.hasPlacedBlock(pos); + } + }, random, config, trunkHeight, treeNode, foliageHeight, radius); + BlockPos.Mutable mutable = new BlockPos.Mutable(); + leafPositions.entrySet().forEach(pos -> { + mutable.set(pos.getKey().x(), pos.getValue().getSecond() - 1, pos.getKey().y()); + if (!placer.hasPlacedBlock(mutable) && random.nextInt(12) == 0) { + placer.placeBlock(mutable, pos.getValue().getFirst().getPlacedFruitState(random)); + } + }); + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/server/world/gen/OverworldBiomeSelectionCallback.java b/src/main/java/com/minelittlepony/unicopia/server/world/gen/OverworldBiomeSelectionCallback.java new file mode 100644 index 00000000..b98f6826 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/server/world/gen/OverworldBiomeSelectionCallback.java @@ -0,0 +1,23 @@ +package com.minelittlepony.unicopia.server.world.gen; + +import net.fabricmc.fabric.api.event.Event; +import net.fabricmc.fabric.api.event.EventFactory; + +/** + * Provides a basic event for mods to inject their own biomes in place of vanilla overworld biomes. + *

+ * Mods are able to insert entries for their biomes into the ranges for existing ones by + * sub-dividing the provided section into pieces and assigning a new biome to one of the create + * segments. + */ +public interface OverworldBiomeSelectionCallback { + Event EVENT = EventFactory.createArrayBacked(OverworldBiomeSelectionCallback.class, delegates -> { + return context -> { + for (OverworldBiomeSelectionCallback delegate : delegates) { + delegate.onSelectingBiome(context); + } + }; + }); + + void onSelectingBiome(BiomeSelectionContext context); +} diff --git a/src/main/resources/assets/unicopia/textures/block/sweet_apple_leaves.png b/src/main/resources/assets/unicopia/textures/block/sweet_apple_leaves.png index 2f7822b4ea7d0ce836251ebd11b14f26541159cb..46bad15f8f6f64c0f642471141859960ec4bddb3 100644 GIT binary patch literal 7105 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 delta 2359 zcmV-73CQ-rH^CB+BYy?KdQ@0+Qek%>aB^>EX>4U6ba`-PAZ2)IW&i+q+O1dFvF)%8 z`&ShyK_s=7qje@7r2IfOsdKl{FXke_xrR1Zqh!wqsV=GVJ*V-S3lz^c*@&(_mi`be1Dmc?vwuNr}(2^?l$}_ zqGAg%t}p$m`s}~{%IDsDmW`a<868?kz$a-^mdew@zz$&KnU-*6+!5{kToqUG%@0Sx zPd|LeHK-Dk_)UQ(HQKbE=b(WQ124{aG7pxguSn*~L%fg#CqV*j&QfJc5thMA1igG? zp=aOvY&WQ2<9|sQ$%MrSGoH&?*o)|Vv&GR2j+qVoA2)uJ<_MP#63g{21Y!?J2_8X01#pCh+s&-fKMcm68X%WiGX7P zKMj$yxWFA0P>ehgB?plNatfclF(=bAmLtF2kPwK7l7A$Fnko%kg%Cq>A%}t*YEfc{ zF{YSfi8Zz)DWsTE%IRpaWyvAOoN~@3*W8MfP-00Xmr`nJu5uMp z?Q}>|nL&S&4x&-RR(XV%32rgNyJu5&d>i8y|8#}zl zIXP;xs8Q*bUw!w3?-qUSwMwvw73_HH)PH@!)kEz@L$`4_Y>mn;7Bh5faA+AoBD-od zIOmgQfbW2!E0wX8zM9_veF(Pp)ynp+8vHvKTP0s*_{Hz+b9MwaWG9)(R4~jg6pbw% zzxk=yTdOp-_0@XCRI$)#2+;&!!0Rv_^aX?s3-OI{|EOZ{4zwg(RR{6Nd z3mz=JbN)Y&2`Rs&Tp3XNtWo2FbVrR{uc8?Fz7(H-o?!D2?{?qx?^t<(d=UbAP7urxvDa z%}ycga9?WcXwJ$5HgiwbwYDXv4vjCi$@c#4Jle(CiURUA#Miu*zr_UXXf68bcWW3W zVQD9BGXy{OEfBI??Ck%_XSjIjRD3!rj^v6L7r{s~N-F zmZ6p1{C>_I>Mf~|u5aXU53&zYv}U|tWX{+P{nmB2q|~NR&iG!$-~I02qyoNNJPlC@ z0009!Nkl%J?64-d4Zkn9d&S+ zUzjHyq-;Ll)a5J7^5oYiIG3(m!Wg52!GOv{h4*jYQyeMcc^(L&R;f0sc!5WAyGgs< zrdTWzwIV#n!|4rrG-etEeju4EUJ9jmluJYpX2BV*iN>~fY@=Q%; zi1s2}*G1OX*R>tB`S{OAE-qh`?WfzCJ2~aCGN-Gj34#E%O0(Id-|J&jD?u?(_n3?0 z2u_kDAh2|GiGQdSVX@--KDm=)GmEtrfZ=dRnxvp83WZXE`nd+q?$$1qiHcnR>bgwL zPN`q=H7EvTS;oP^0lV9~7-Oi{>zq7!62IWn>-I>Jg!Wz=XJl-IcGT7zU*FLEzxJ7( zpCvUZi;IhNKXoYvMcjhR&L2C(am?JsIhL+22|zdQ;(zq}eKb?XzZhq-Hp%{<`%KSF z%i-Z6iWgqsV`6Ac^-L|V+MwYKRgr>(Y@V0 z1qf>)aepVK;1$^TZ9~srI4=%BX|zOd&|`9T5_`-N_hXLYBUY}hU@}9cTETG~3Vwh( zN@`M)VZ!F~O?7U6dt1|fN^QE%%cn0ncm5o{?{hpjjyh; Date: Sat, 10 Feb 2024 21:09:36 +0000 Subject: [PATCH 08/13] Revert the player range check when dropping fruit from trees --- .../com/minelittlepony/unicopia/block/FruitBearingBlock.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/minelittlepony/unicopia/block/FruitBearingBlock.java b/src/main/java/com/minelittlepony/unicopia/block/FruitBearingBlock.java index 54e64851..2009d87a 100644 --- a/src/main/java/com/minelittlepony/unicopia/block/FruitBearingBlock.java +++ b/src/main/java/com/minelittlepony/unicopia/block/FruitBearingBlock.java @@ -107,7 +107,7 @@ public class FruitBearingBlock extends LeavesBlock implements TintedBlock, Bucka BlockState fruitState = world.getBlockState(fruitPosition); - if (stage == Stage.WITHERING && fruitState.isOf(fruit.get()) && world.isPlayerInRange(pos.getX(), pos.getY(), pos.getZ(), 25)) { + if (stage == Stage.WITHERING && fruitState.isOf(fruit.get())) { if (world.random.nextInt(2) == 0) { Block.dropStack(world, fruitPosition, rottenFruitSupplier.get()); } else { From 65b468507cda38c5fc759b4852df130add072a94 Mon Sep 17 00:00:00 2001 From: Sollace Date: Sat, 10 Feb 2024 21:56:36 +0000 Subject: [PATCH 09/13] Added flowers to apple tree leaves when they are flowing --- .../blockstates/green_apple_leaves.json | 11 ++++++- .../blockstates/sour_apple_leaves.json | 11 ++++++- .../blockstates/sweet_apple_leaves.json | 11 ++++++- .../block/green_apple_leaves_flowering.json | 7 ++++ .../block/sour_apple_leaves_flowering.json | 7 ++++ .../block/sweet_apple_leaves_flowering.json | 31 ++++++++++++++++++ .../block/green_apple_leaves_flowering.png | Bin 0 -> 6770 bytes .../block/sour_apple_leaves_flowering.png | Bin 0 -> 7009 bytes .../block/sweet_apple_leaves_flowering.png | Bin 0 -> 6694 bytes 9 files changed, 75 insertions(+), 3 deletions(-) create mode 100644 src/main/resources/assets/unicopia/models/block/green_apple_leaves_flowering.json create mode 100644 src/main/resources/assets/unicopia/models/block/sour_apple_leaves_flowering.json create mode 100644 src/main/resources/assets/unicopia/models/block/sweet_apple_leaves_flowering.json create mode 100644 src/main/resources/assets/unicopia/textures/block/green_apple_leaves_flowering.png create mode 100644 src/main/resources/assets/unicopia/textures/block/sour_apple_leaves_flowering.png create mode 100644 src/main/resources/assets/unicopia/textures/block/sweet_apple_leaves_flowering.png diff --git a/src/main/resources/assets/unicopia/blockstates/green_apple_leaves.json b/src/main/resources/assets/unicopia/blockstates/green_apple_leaves.json index 9b6325d5..635befb5 100644 --- a/src/main/resources/assets/unicopia/blockstates/green_apple_leaves.json +++ b/src/main/resources/assets/unicopia/blockstates/green_apple_leaves.json @@ -1,6 +1,15 @@ { "variants": { - "": { + "stage=flowering": { + "model": "unicopia:block/green_apple_leaves_flowering" + }, + "stage=idle": { + "model": "unicopia:block/green_apple_leaves" + }, + "stage=fruiting": { + "model": "unicopia:block/green_apple_leaves" + }, + "stage=withering": { "model": "unicopia:block/green_apple_leaves" } } diff --git a/src/main/resources/assets/unicopia/blockstates/sour_apple_leaves.json b/src/main/resources/assets/unicopia/blockstates/sour_apple_leaves.json index f9d40dd7..e15d3600 100644 --- a/src/main/resources/assets/unicopia/blockstates/sour_apple_leaves.json +++ b/src/main/resources/assets/unicopia/blockstates/sour_apple_leaves.json @@ -1,6 +1,15 @@ { "variants": { - "": { + "stage=flowering": { + "model": "unicopia:block/sour_apple_leaves_flowering" + }, + "stage=idle": { + "model": "unicopia:block/sour_apple_leaves" + }, + "stage=fruiting": { + "model": "unicopia:block/sour_apple_leaves" + }, + "stage=withering": { "model": "unicopia:block/sour_apple_leaves" } } diff --git a/src/main/resources/assets/unicopia/blockstates/sweet_apple_leaves.json b/src/main/resources/assets/unicopia/blockstates/sweet_apple_leaves.json index c6e7da22..e09ef0b9 100644 --- a/src/main/resources/assets/unicopia/blockstates/sweet_apple_leaves.json +++ b/src/main/resources/assets/unicopia/blockstates/sweet_apple_leaves.json @@ -1,6 +1,15 @@ { "variants": { - "": { + "stage=flowering": { + "model": "unicopia:block/sweet_apple_leaves_flowering" + }, + "stage=idle": { + "model": "unicopia:block/sweet_apple_leaves" + }, + "stage=fruiting": { + "model": "unicopia:block/sweet_apple_leaves" + }, + "stage=withering": { "model": "unicopia:block/sweet_apple_leaves" } } diff --git a/src/main/resources/assets/unicopia/models/block/green_apple_leaves_flowering.json b/src/main/resources/assets/unicopia/models/block/green_apple_leaves_flowering.json new file mode 100644 index 00000000..1ab7bd8c --- /dev/null +++ b/src/main/resources/assets/unicopia/models/block/green_apple_leaves_flowering.json @@ -0,0 +1,7 @@ +{ + "parent": "unicopia:block/sweet_apple_leaves_flowering", + "textures": { + "all": "unicopia:block/green_apple_leaves", + "overlay": "unicopia:block/green_apple_leaves_flowering" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/unicopia/models/block/sour_apple_leaves_flowering.json b/src/main/resources/assets/unicopia/models/block/sour_apple_leaves_flowering.json new file mode 100644 index 00000000..42924cd9 --- /dev/null +++ b/src/main/resources/assets/unicopia/models/block/sour_apple_leaves_flowering.json @@ -0,0 +1,7 @@ +{ + "parent": "unicopia:block/sweet_apple_leaves_flowering", + "textures": { + "all": "unicopia:block/sour_apple_leaves", + "overlay": "unicopia:block/sour_apple_leaves_flowering" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/unicopia/models/block/sweet_apple_leaves_flowering.json b/src/main/resources/assets/unicopia/models/block/sweet_apple_leaves_flowering.json new file mode 100644 index 00000000..3d04aabc --- /dev/null +++ b/src/main/resources/assets/unicopia/models/block/sweet_apple_leaves_flowering.json @@ -0,0 +1,31 @@ +{ "parent": "minecraft:block/block", + "textures": { + "all": "unicopia:block/sweet_apple_leaves", + "particle": "#all", + "overlay": "unicopia:block/sweet_apple_leaves_flowering" + }, + "elements": [ + { "from": [ 0, 0, 0 ], + "to": [ 16, 16, 16 ], + "faces": { + "down": { "uv": [ 0, 0, 16, 16 ], "texture": "#all", "tintindex": 0, "cullface": "down" }, + "up": { "uv": [ 0, 0, 16, 16 ], "texture": "#all", "tintindex": 0, "cullface": "up" }, + "north": { "uv": [ 0, 0, 16, 16 ], "texture": "#all", "tintindex": 0, "cullface": "north" }, + "south": { "uv": [ 0, 0, 16, 16 ], "texture": "#all", "tintindex": 0, "cullface": "south" }, + "west": { "uv": [ 0, 0, 16, 16 ], "texture": "#all", "tintindex": 0, "cullface": "west" }, + "east": { "uv": [ 0, 0, 16, 16 ], "texture": "#all", "tintindex": 0, "cullface": "east" } + } + }, + { "from": [ 0, 0, 0 ], + "to": [ 16, 16, 16 ], + "faces": { + "down": { "uv": [ 0, 0, 16, 16 ], "texture": "#overlay", "cullface": "down" }, + "up": { "uv": [ 0, 0, 16, 16 ], "texture": "#overlay", "cullface": "up" }, + "north": { "uv": [ 0, 0, 16, 16 ], "texture": "#overlay", "cullface": "north" }, + "south": { "uv": [ 0, 0, 16, 16 ], "texture": "#overlay", "cullface": "south" }, + "west": { "uv": [ 0, 0, 16, 16 ], "texture": "#overlay", "cullface": "west" }, + "east": { "uv": [ 0, 0, 16, 16 ], "texture": "#overlay", "cullface": "east" } + } + } + ] +} diff --git a/src/main/resources/assets/unicopia/textures/block/green_apple_leaves_flowering.png b/src/main/resources/assets/unicopia/textures/block/green_apple_leaves_flowering.png new file mode 100644 index 0000000000000000000000000000000000000000..f9975552f361224234ec456112bd4c6991b9236c GIT binary patch literal 6770 zcmeHM3v?9K8J>M)Ur8V#4`Lc%GXY6}*`1l4-FY-i$dfE(XU)oKAbJ@SZ(&>qq|vzwRoh-tyvb22%1 z=AV22``!Qh?tf?IZd%J`O^-LFn;-~^ca;`ZfNO$W3_5Tg*WJTHkRes5afvS1B**~j zfTv0esiJGZl7gI=#U8V#nnjL5!P7J1IQZVk2-FL}fG@<6`5|;^Wis%#2KY$VbnsP@+MO zNuz=xb)rg>sOs4djRSGUsFWi@1>CDO+8CYQU^K-7hwTZnQW~{Z6BDD=g4QLV9nvPo zjLO9FbxGx{9$u7;FJJqFA**2PzLbi0FOIi)0xOKB)X{0TrBAqhVs_3X!tNj`nkg(Q zE}35Hno(IbyZVlrIdeH)5NqqCyMm#{rsi-#(3IPm5l559Ng==;aIj-NRB(O*CQ3dsw(c`#*(xrkcmnU5QpXb?O}HdeQVk`b5W_`r^d7XsfG%7H8nnWlM>SnS# zmYIH_#raxW_VZKzIq%}N?2bK!UoPut%Z7$nG^esV+AbgJJT$VSZSv8)x?2GGLsjqp zF|J!MJvV^-dV+kLYD0v&f%|t!<)K9PZIS;k+VXl%Ky7#Lt_F|$l~Q40nX9nS><{=v zsa}AfaQl+A&eGSXWpv(I`BcTE5!DIhZcOSZLMkaFFN-AzS#-dylL%Y+LPyR-rqA}bt*PCr8d$;mO)n*s??e{^A3)YsS9jdroJ)+O>;1bUE+J*>khIQ#ES%(iGdwN5d<_ zi;p;{3rW-GxT;$ZwH|Q4V!o8smGX~ z7MAyU1WUNVue{)L^TK|XTPTFg9-&t9I^heu_QGa~cfxnr-Kg7NDAY-%ivvRC;#pPP z;)NW|!+BFpxnTwXGzcNq9B!!h2AQxER&W_$%hgucthj_0I^i1dF;?gc2xh`USWu)m zEH&ZqRFgS3z>7>pQArd6+&SU8P{_|%tzQzD26gLUpP}V>Qp6l!HZw%Bcba>7x)CH3&w< z1`R2Hw)XXqC8(7e{7Nq%_8`xYB=(CnC^or8p))WL(7g|LkasV4#Tj_H-As{>Ym~!t z6**yfe1`XN63-|mhtr}RC255Bpg2O16ot?f#vwQ<&@67}1dbvHK)JlZ5bNax847?~ zB!ELx4%Q>!D8h=Oh!8ZzB9uVb5CP*Tk>zNIO%Mk_{4^ketYqs4MkPb>0Lo5rBqiW9 z!V=&_IP53_kV%9faMH%wIo8gi3KY*VCB8rd3#Lr7E(bDuqRnyU1<5q%0+~Sy>be%S9*z*(QNk z;sjWcCa#Y4)(YV15lz?Ldg&WdfoBDQBvAn&coLil2Z_)q%_6vm^zfXG7bwy*7(M6{ zL(ObJ$gc%D0DB ziHHsn6&$Rcwo$g5O%bOVJNo@m6mb?q9VmyOB+JS?34}sX0wD!XU7OZS8w&M>Ai3Ki%(8GWGBK1uytqZw9;ijk9+j1HTFAJU^LU1T6)> z6~A!*#@+Rx#^^7d6NI4HB)O=dP3>u*QXg`;i}mN!rW82mRArw0kD5$ZQGONmCvHL7 xsSlTavGkz5vh$ba=;n@x(vBGK8rx#jL#B!`TT17xS^}IQSMjW(=L#0A_!qW)y7vG8 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/unicopia/textures/block/sour_apple_leaves_flowering.png b/src/main/resources/assets/unicopia/textures/block/sour_apple_leaves_flowering.png new file mode 100644 index 0000000000000000000000000000000000000000..f741873edeebeccff2c6e397df84aceea35aa4ab GIT binary patch literal 7009 zcmeHL3v?9K8J>M4yV<|hotbTxkSAHnVn_l84%E!f%qCm14|X@n zl8VYxllnN6P!&@j0TFD`1A>UCNF`#aRTLyZ!D^v^oE~}EBJ`B>pV>`Fs7IR?DCab@ z=id3}-v9sZ|NZyBckfI~`LxN2y5TwmK@#m{#T9T*k%~4J>X8?_IRw$7Vzu36w~s@# z&<2_cHKK^>Df-Atg$hwY`*J8lK$di*GF%ZO-yZ?_2T{2VF?uQ~{y$$j{C|dbPD-l_v=RVo)DA$t)0ymf}V2_iO6(_9(t|tkriMHY<7+>++ zHID!Yi9@a;5p2oF9!`>@J)9)Dhf^WQs;IwGWMccs8GU#tlo8A_$u=qj1q)zG^T`Vn<% z%#duNAU16}r$OhZlZ#e7ugxjkv@4_H<8z}-&cNb0UFOhXcMKnW*O=U~<0!L*W>{-c zaY^aqGW(Rusu?rysh%~P7erTWo%<)jP(x!=ctP`$rOTE-^l(e-&sVms`o$AZKDD}I z&Ds~%y|{kEOPgQavh}rXuWx_jH}CH5d~eVDzuo)E{sW&L>^gM#$QOS)e&Ww3Po4hq z%=rr!zy9mrE`4+Pio{Fe*>gphUB@dGcq!Ftm0Bb5QYf1w;;HJGY$A3@!E_BbKMf@p zY10c=JilpIT#l*YT!u67u`Y8I^~LD(5;d9GzejBGf5fbp*fm~9kOY+iCQp@$ z7T%^2yj^GZyZrj!%=-0d@?A6fy&hf<_J5yq$=!#M#`Ue6Ve4PwE-EUw7ZvIK0iVlV zFCs{|ec=jQ*}IdnI`6G~p<-Op%#`Wxm;drF9q41Tm!VbKt%bizy6cJi3sx>4)!8}S zk1^kDs&4SlKltgc87b=gN$n%r)90?;-936)CUIxhrQ^rm+H>rOlj^FTbT#~5x!U{m zmqOtOCuer<8?RnUJeaB_UwwqNPubOU-?5x`x^^%hUC6(5>hz3@nJOiEeu8Q0)8QrI z=KU7tY}({m_L(gowd`@cp+BF~mGSr=nW1wt!>$7#tUcATX18 zJ?(PgL4MW6%-W3={KlVN7+QMa%3iX|os`p3GNE9xHpbjGebJ-LM(fzjPqsXJ?tJq0 z`&;Jdw(qSuQ9UVRxX_h+RkL%)R^7_9A6JZ0gmy9??#WF#60^Et&*h1Y?I+_>?u&i- z>(_Q3L0l8i1gP-umj|SI>O-*;U*AGiNon&cKR$+qbX?lB#xBRfnn_Q?0zu zW8egzQ#6DNA z*xg8?6LtE$fZ(!L6qiOJ;K_#8g+hL-(b&|~WN0!Oe1Tdc!LqCoCygYDfd&>_;0`MoLs970_xR`WI~=|6-e5Ee5D#OR^BV~RZuEGJ zeJz5al12cDI`pj;!Kwv*(O4k{eGLI#ENK+Ip`5-D0^e)zZwS=ObOhcg){7oc4Z^5I zzaga~Y_EkBf?Bu7FIz#d`)P*Uu4}>S=bO|c)9LF7nD^rL)9&FeD}$E9VJ-IY4U&8I zVjC)rZxwvJTd>L^PqHpEPP3Tc#7T^z83tn+g2zZ&WI58zi#$X3fwFspAS1TI*-deds3b?hP+-^fjLqt_> zDX-^3E-!Yl6=C;?rfW~T`&&{$;6#z8aS@{g8Y;>{V=T^c80n;)0&fyThIaNx z5Bgl8CN3Zr)IuB~R*;@@tn|6^M2+pQ-Bc$^vj73ZAX^E%ilD6&4QUe%nDORQq-dPy zOq2@~7#D$2PJzQ!*Wc;?k|N{;L0Ku&t)mE3oMx63U;;U)NLYm| z$XJ$=|=|)o|S*sbpbrfABN8lEm$8ehCB%Tz;;5dcRA`kl)fm1ALxzQ9& zFpI>kqsXxwFXCns#&fW#!(J+2ECDIYnmO3?NegW;@i&~J^i`%m#XO_*|J}3u8?6oCOL4`$b3 zxCRt~0Vxk=*9{Ao?%Jmf(F<=RP4M9&)Le1`K6}JEe>Axmc>q3*Z+`fxH|wD#&R;ew zh#>K4Qc)nQ+lN7;CS-S%Xih728KYHY8)_bfrfhq0K^5~mzGm3b&(C&ux6NDEn!To` jtOO(0r5(t-FeC{=3U6&@{?WO>I6#5Ews2E;Pb%xGlIsFuMi7Dd$9f*1}ojAlmm6l+0}Z9zlA zp4cZ1hXPGP+$@IBgcfp0AV44`G&rP`CL|CHG^9zBfWzUiIW0@i!F@B5Y}v67c7gu# z=)9RX_uc#5``ve+o}L=ZXHH8{XR09xO0bp{SAb`-&{PU=AKlSOLy+o^T$R;nwN8Xo zKn64=a!3-^lSK8U5*Z`|^0lB11ARe9Xql22@%aqs|0LYs2>RNvj$ngHq)-BQHiL$P zej0dg2aSI!_%TT#Q6uu4X0?@Ta2_V`iK(8&Tk2 z@=A9^00@eO?m{7KA;t(NAP;cyh3IaQT_BN9ujE?vrMoJ_Zg+&AQF4$ zna;1EQs78P5V&>z9V&uU3WZV;qf#oBv9T(3d|E<$TwMGk!%~ydMrMv4H8L|R zOOvA;uYo6LXJu(k6DFe=K@g+IQx+1>(-{a{0FlJT#>U6Rk4Q)ufse@=gAe-Zd>=|t z2{FkeFeFWp$WkPoN1)Ll&KQY!g{XjcsZ1WDP^x0paX?{DvXCj6R4$8&k;}p8GB6Iw zQ(}gV!3q?qvuGu}I1OL1{#8|W;jY8!6`x+qF*tlHW7QeMM?8`_cHDUFgo%VP*F;k0 zqT-U$X=T>wmG;?l9<7=?k6}4ybq)VZf1s|uA-H7es?}@OKJ|2C({DCx-1OV$o_}F; z%a*OLZTtP}Z)|_-?cICc*}HH5yMO-RNb843Kl;nD&rY8D{B+xyv**74=QrPecj03D z_m{5U==kAZ|Gs(a_8ozjz%z1%nDye70(eQ~a+zEy@RCRy1mY?3m@$}QSivkMy*L%d zSE$ko*T1^!aBQ}r;##`H_o+G~hxmHzb%C15Y+%Gz{!h%hh;{Qi2gS=IVDe-s&=lzQ z-6riT(g)Czwzs!5-CVaO-`>(R>2Q9#wxtQ`tKHezqm{9r)Gn}CE zmL@F(nyjA+AE>JVz(t_c+Lq-)>uc@xF>MjEzSN@%qdy|O&HM1s-*ogg?VZX&K=tS1 zUh<^Qv(WKzYe#`iXcb>nRBkOQ(s+FyCtu4!P_TK~dP~^{Q?ptht9-3uV&a_SSs#`E z?s5zK?7TIwUA3q14~gTRd!k^&+ML$bSzd&^wX3SmyZH3yhi50tr%Y`g*_^gu>ygf} zYcjA=SvS8q|K8E_Kb=}*f8JU5H|b{gi{G<_$1lujJuykX8e5*C!ry*|vQ9tT@c8-c z_uCGTpWK*o^J4q#jtrR;zCPJ7MD{wEsetM?yU_-)nH^h~xb>8|q7fj#OCslTYm zkpvErA0O2wpNrXCcl36Cee;Fbb8Sl&ifC!48l*%zN8>Y`G-v#-@DRr<)x3mylXjm z>8jGw>RbO<^KJ@)lJa?bRiMf?!_0VGI-2!3I9<@?6}R2IDM2sIEaCzh2UpFzE%4O? zhhPoQTHr^GHq_=V;%fM^r9Q55=}bGbbP+?b@RWRYUeF8xTwH+G1YNamzd2}uMO-uJ z3t~O25mf?Vn*EcjY z=o$<OGZ-Do>H3BB>@YDq?Fbu{u zk@#F*o2?7p?GI-GRm2`U=kPsq-;hNj>Kd zWJg1=Oqad4&Q~kaVHrJF%ejE6A9%%jxD(F!EHhh~6xb|>f|81@1af zbq(9Va$@NKT}%f!0NQoLvPX_slTg%*hQb%%Y#x?(F1eSsuy{0iKp#wb8Se-Fmx!X! zimK!mhu%W3wY<2LG#YVHm}w?N!B5w7tQaT23Jozew7Z%E-yY#|jmY^vN`a+0&SXM4 zPz5G%BXUg$g;F$vJ4~Pw3@k^Q96izf9%rC|_HhN(AdetdpghIHr$#GI)P$be4KaE94w81uQMltQbaCe%yqChLH7*$ zJ}H8lzz8#8`2SG^R2)VMXTb#0;D&=$Na2(TappQvE|)e^2Ga1LDT@Cr^rV=l7ryx; zb(^REQDuh|qP7Y!`ymS0UUYvaR*-q2WExiXVZ$IC&AylZ$16O!CD}R z^_I=`Lr`3*&?M02<`F=s3|MU?%66$beI%aP{>2O+f~~~`cJi;x!V#x5UtR9#Ok1?A nY0Q>|WhDr Date: Sun, 11 Feb 2024 00:28:39 +0000 Subject: [PATCH 10/13] Add toggles for pehkui and sodium --- build.gradle | 13 +++++++++---- gradle.properties | 5 ++++- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/build.gradle b/build.gradle index a31e3671..5d45804e 100644 --- a/build.gradle +++ b/build.gradle @@ -75,10 +75,15 @@ dependencies { include "com.terraformersmc.terraform-api:terraform-wood-api-v1:${project.terraformer_api_version}" modCompileOnly "maven.modrinth:farmers-delight-fabric:${project.farmers_delight_version}", { exclude group: "net.fabricmc.fabric-api" } - modCompileOnly "maven.modrinth:iris:${project.iris_version}", { exclude group: "net.fabricmc.fabric-api" } - modCompileOnly "maven.modrinth:sodium:${project.sodium_version}", { exclude group: "net.fabricmc.fabric-api" } - modCompileOnly "maven.modrinth:pehkui:${project.pehkui_version}", { exclude group: "net.fabricmc.fabric-api" } - modCompileOnly "com.github.Virtuoel:KanosConfig:0.4.1", { exclude group: "net.fabricmc.fabric-api" } + if (project.use_pehkui == '1') { + modCompileOnly "maven.modrinth:pehkui:${project.pehkui_version}", { exclude group: "net.fabricmc.fabric-api" } + modCompileOnly "com.github.Virtuoel:KanosConfig:0.4.1", { exclude group: "net.fabricmc.fabric-api" } + } + + if (project.use_sodium == '1') { + modCompileOnly "maven.modrinth:sodium:${project.sodium_version}", { exclude group: "net.fabricmc.fabric-api" } + modCompileOnly "maven.modrinth:iris:${project.iris_version}", { exclude group: "net.fabricmc.fabric-api" } + } if (project.tmi_type == 'emi') { modCompileOnly "dev.emi:emi-fabric:${project.emi_version}" diff --git a/gradle.properties b/gradle.properties index 68f968c9..14c41bd3 100644 --- a/gradle.properties +++ b/gradle.properties @@ -15,7 +15,7 @@ org.gradle.daemon=false description=Magical Abilities for Mine Little Pony! # Publishing - minecraft_version_range=>=1.20.1 + minecraft_version_range=1.20.1 modrinth_loader_type=fabric modrinth_project_id=9K7RJlvM @@ -29,6 +29,9 @@ org.gradle.daemon=false terraformer_api_version=7.0.0-beta.1 # Testing + use_pehkui=0 + use_sodium=1 + farmers_delight_version=1.4.3 pehkui_version=3.7.8+1.14.4-1.20.1 iris_version=1.6.8+1.20.1 From 18f28652642499bad2a34268da4ef4a2829c5f64 Mon Sep 17 00:00:00 2001 From: Sollace Date: Sun, 11 Feb 2024 11:01:35 +0000 Subject: [PATCH 11/13] Add an option to disable the post-effect shader --- .../java/com/minelittlepony/unicopia/Config.java | 3 +++ .../client/render/shader/ViewportShader.java | 16 +++++++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/minelittlepony/unicopia/Config.java b/src/main/java/com/minelittlepony/unicopia/Config.java index 3a128a0e..8ccae93c 100644 --- a/src/main/java/com/minelittlepony/unicopia/Config.java +++ b/src/main/java/com/minelittlepony/unicopia/Config.java @@ -48,6 +48,9 @@ public class Config extends com.minelittlepony.common.util.settings.Config { public final Setting simplifiedPortals = value("compatibility", "simplifiedPortals", false) .addComment("Disables dynamic portal rendering"); + public final Setting disableShaders = value("compatibility", "disableShaders", false) + .addComment("Disables post-effect shaders used by the corruption mechanic"); + public final Setting fancyPortalRefreshRate = value("client", "fancyPortalRefreshRate", -1L) .addComment("Sets the refresh rate of portals when using fancy portal rendering") .addComment("Set to -1 (default) for unlimited"); diff --git a/src/main/java/com/minelittlepony/unicopia/client/render/shader/ViewportShader.java b/src/main/java/com/minelittlepony/unicopia/client/render/shader/ViewportShader.java index d0ca24e9..ebef6c6a 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/render/shader/ViewportShader.java +++ b/src/main/java/com/minelittlepony/unicopia/client/render/shader/ViewportShader.java @@ -43,14 +43,24 @@ public class ViewportShader implements SynchronousResourceReloader, Identifiable } public void loadShader(@Nullable Identifier shaderId) { + if (shader != null) { - shader.close(); + try { + shader.close(); + } catch (Throwable ignored) { + } finally { + shader = null; + } } if (shaderId == null) { return; } + if (Unicopia.getConfig().disableShaders.get()) { + return; + } + try { shader = new LoadedShader(client, shaderId); } catch (IOException e) { @@ -67,6 +77,10 @@ public class ViewportShader implements SynchronousResourceReloader, Identifiable } public void render(float tickDelta) { + if (Unicopia.getConfig().disableShaders.get()) { + return; + } + if (shader != null && client.player != null) { RenderSystem.disableBlend(); RenderSystem.disableDepthTest(); From ae0179be8f6e314f00b6c740ddb60107e0e5108d Mon Sep 17 00:00:00 2001 From: Sollace Date: Sun, 11 Feb 2024 14:01:07 +0000 Subject: [PATCH 12/13] Fix compatibility with Synatra Connector / Froge --- gradle.properties | 2 +- lib/reach-entity-attributes-2.3.3.jar | Bin 23920 -> 0 bytes lib/reach-entity-attributes-2.3.4.jar | Bin 0 -> 25242 bytes .../unicopia/UnicopiaMixinPlugin.java | 3 + .../entity/collision/EntityCollisions.java | 4 +- .../unicopia/mixin/MixinBoatEntity.java | 7 ++- .../unicopia/mixin/MixinEntityView.java | 32 +++++++++++ .../unicopia/mixin/MixinWorld.java | 21 ------- .../mixin/forgified/MixinIForgeBoat.java | 54 ++++++++++++++++++ src/main/resources/unicopia.mixin.json | 4 +- 10 files changed, 101 insertions(+), 26 deletions(-) delete mode 100644 lib/reach-entity-attributes-2.3.3.jar create mode 100644 lib/reach-entity-attributes-2.3.4.jar create mode 100644 src/main/java/com/minelittlepony/unicopia/mixin/MixinEntityView.java create mode 100644 src/main/java/com/minelittlepony/unicopia/mixin/forgified/MixinIForgeBoat.java diff --git a/gradle.properties b/gradle.properties index 14c41bd3..950040b3 100644 --- a/gradle.properties +++ b/gradle.properties @@ -24,7 +24,7 @@ org.gradle.daemon=false modmenu_version=7.0.0-beta.2 minelp_version=4.10.4+1.20.1 kirin_version=1.15.4+1.20 - reach_attributes_version=2.3.3 + reach_attributes_version=2.3.4 trinkets_version=3.7.1 terraformer_api_version=7.0.0-beta.1 diff --git a/lib/reach-entity-attributes-2.3.3.jar b/lib/reach-entity-attributes-2.3.3.jar deleted file mode 100644 index 40ddce2185dccbe38e21947af9a73a1dce125160..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 23920 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 GfByp}IYv?d literal 0 HcmV?d00001 diff --git a/src/main/java/com/minelittlepony/unicopia/UnicopiaMixinPlugin.java b/src/main/java/com/minelittlepony/unicopia/UnicopiaMixinPlugin.java index df5394d9..8f33d14a 100644 --- a/src/main/java/com/minelittlepony/unicopia/UnicopiaMixinPlugin.java +++ b/src/main/java/com/minelittlepony/unicopia/UnicopiaMixinPlugin.java @@ -38,6 +38,9 @@ public class UnicopiaMixinPlugin implements IMixinConfigPlugin { if (mixinClassName.indexOf("minelp") != -1) { return FabricLoader.getInstance().isModLoaded("minelp"); } + if (mixinClassName.indexOf("forgified") != -1) { + return FabricLoader.getInstance().isModLoaded("connectormod"); + } } return true; } diff --git a/src/main/java/com/minelittlepony/unicopia/entity/collision/EntityCollisions.java b/src/main/java/com/minelittlepony/unicopia/entity/collision/EntityCollisions.java index 9bad7931..d2d65f3e 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/collision/EntityCollisions.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/collision/EntityCollisions.java @@ -17,7 +17,7 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Box; import net.minecraft.util.shape.VoxelShape; import net.minecraft.util.shape.VoxelShapes; -import net.minecraft.world.WorldAccess; +import net.minecraft.world.EntityView; public class EntityCollisions { @@ -40,7 +40,7 @@ public class EntityCollisions { } } - public static List getColissonShapes(@Nullable Entity entity, WorldAccess world, Box box) { + public static List getColissonShapes(@Nullable Entity entity, EntityView world, Box box) { ShapeContext ctx = entity == null ? ShapeContext.absent() : ShapeContext.of(entity); return collectCollisionBoxes(box, collector -> { world.getOtherEntities(entity, box.expand(50), e -> { diff --git a/src/main/java/com/minelittlepony/unicopia/mixin/MixinBoatEntity.java b/src/main/java/com/minelittlepony/unicopia/mixin/MixinBoatEntity.java index 392cf967..76ba1b29 100644 --- a/src/main/java/com/minelittlepony/unicopia/mixin/MixinBoatEntity.java +++ b/src/main/java/com/minelittlepony/unicopia/mixin/MixinBoatEntity.java @@ -31,7 +31,12 @@ abstract class MixinBoatEntity extends Entity implements LavaAffine { "fall", "canAddPassenger" }, - at = @At(value = "FIELD", target = "net/minecraft/registry/tag/FluidTags.WATER:Lnet/minecraft/registry/tag/TagKey;", opcode = Opcodes.GETSTATIC) + at = @At( + value = "FIELD", + target = "net/minecraft/registry/tag/FluidTags.WATER:Lnet/minecraft/registry/tag/TagKey;", + opcode = Opcodes.GETSTATIC + ), + require = 0 // Forge ) private TagKey redirectFluidTag() { return isLavaAffine() ? FluidTags.LAVA : FluidTags.WATER; diff --git a/src/main/java/com/minelittlepony/unicopia/mixin/MixinEntityView.java b/src/main/java/com/minelittlepony/unicopia/mixin/MixinEntityView.java new file mode 100644 index 00000000..c2de6378 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/mixin/MixinEntityView.java @@ -0,0 +1,32 @@ +package com.minelittlepony.unicopia.mixin; + +import java.util.List; +import java.util.stream.Stream; + +import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import com.minelittlepony.unicopia.entity.collision.EntityCollisions; + +import net.minecraft.entity.Entity; +import net.minecraft.util.math.Box; +import net.minecraft.util.shape.VoxelShape; +import net.minecraft.world.EntityView; + +@Mixin(EntityView.class) +interface MixinEntityView { + @Inject(method = "getEntityCollisions(Lnet/minecraft/entity/Entity;Lnet/minecraft/util/math/Box;)Ljava/util/List;", at = @At("RETURN"), cancellable = true) + private void onGetEntityCollisions(@Nullable Entity entity, Box box, CallbackInfoReturnable> info) { + if (box.getAverageSideLength() < 1.0E-7D) { + return; + } + + List shapes = EntityCollisions.getColissonShapes(entity, (EntityView)this, box); + if (!shapes.isEmpty()) { + info.setReturnValue(Stream.concat(shapes.stream(), info.getReturnValue().stream()).toList()); + } + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/mixin/MixinWorld.java b/src/main/java/com/minelittlepony/unicopia/mixin/MixinWorld.java index d3237ca4..eda9c5b4 100644 --- a/src/main/java/com/minelittlepony/unicopia/mixin/MixinWorld.java +++ b/src/main/java/com/minelittlepony/unicopia/mixin/MixinWorld.java @@ -1,26 +1,17 @@ package com.minelittlepony.unicopia.mixin; -import java.util.List; import java.util.Stack; import java.util.function.Supplier; -import java.util.stream.Stream; - -import org.jetbrains.annotations.Nullable; - import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.ModifyVariable; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import com.minelittlepony.unicopia.entity.collision.EntityCollisions; import com.minelittlepony.unicopia.entity.duck.RotatedView; import com.minelittlepony.unicopia.server.world.BlockDestructionManager; import net.minecraft.block.BlockState; -import net.minecraft.entity.Entity; import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Box; -import net.minecraft.util.shape.VoxelShape; import net.minecraft.world.World; import net.minecraft.world.WorldAccess; @@ -47,18 +38,6 @@ abstract class MixinWorld implements WorldAccess, BlockDestructionManager.Source return destructions.get(); } - @Override - public List getEntityCollisions(@Nullable Entity entity, Box box) { - if (box.getAverageSideLength() >= 1.0E-7D) { - List shapes = EntityCollisions.getColissonShapes(entity, this, box); - if (!shapes.isEmpty()) { - return Stream.concat(shapes.stream(), WorldAccess.super.getEntityCollisions(entity, box).stream()).toList(); - } - } - - return WorldAccess.super.getEntityCollisions(entity, box); - } - @ModifyVariable(method = "setBlockState(Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/BlockState;II)Z", at = @At("HEAD")) private BlockPos modifyBlockPos(BlockPos pos) { pos = applyRotation(pos); diff --git a/src/main/java/com/minelittlepony/unicopia/mixin/forgified/MixinIForgeBoat.java b/src/main/java/com/minelittlepony/unicopia/mixin/forgified/MixinIForgeBoat.java new file mode 100644 index 00000000..dd7abfe8 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/mixin/forgified/MixinIForgeBoat.java @@ -0,0 +1,54 @@ +package com.minelittlepony.unicopia.mixin.forgified; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Pseudo; +import org.spongepowered.asm.mixin.injection.*; +import com.minelittlepony.unicopia.entity.duck.LavaAffine; +import net.minecraft.fluid.Fluid; +import net.minecraft.fluid.FluidState; +import net.minecraft.fluid.Fluids; +import net.minecraft.registry.tag.FluidTags; + +@Pseudo +@Mixin(targets = "net.minecraftforge.common.extensions.IForgeBoat") +interface MixinIForgeBoat { + @ModifyVariable( + method = "canBoatInFluid(Lnet/minecraft/fluid/FluidState;)Z", + at = @At("HEAD"), + ordinal = 0, + argsOnly = true, + require = 0 + ) + private FluidState modifyFluidState(FluidState incoming) { + if (this instanceof LavaAffine a && a.isLavaAffine()) { + if (incoming.isIn(FluidTags.WATER)) { + return Fluids.LAVA.getDefaultState(); + } + if (incoming.isIn(FluidTags.LAVA)) { + return Fluids.WATER.getDefaultState(); + } + } + + return incoming; + } + @SuppressWarnings("deprecation") + @ModifyVariable( + method = "canBoatInFluid(Lnet/minecraft/fluid/Fluid;)Z", + at = @At("HEAD"), + ordinal = 0, + argsOnly = true, + require = 0 + ) + private Fluid modifyFluid(Fluid incoming) { + if (this instanceof LavaAffine a && a.isLavaAffine()) { + if (incoming.isIn(FluidTags.WATER)) { + return Fluids.LAVA; + } + if (incoming.isIn(FluidTags.LAVA)) { + return Fluids.WATER; + } + } + + return incoming; + } +} diff --git a/src/main/resources/unicopia.mixin.json b/src/main/resources/unicopia.mixin.json index 81c55c34..549625a7 100644 --- a/src/main/resources/unicopia.mixin.json +++ b/src/main/resources/unicopia.mixin.json @@ -20,6 +20,7 @@ "MixinEnchantmentHelper", "MixinFallLocation", "MixinEntity", + "MixinEntityView", "MixinEntityShapeContext", "MixinFallingBlock", "MixinFallingBlockEntity", @@ -57,7 +58,8 @@ "trinkets.MixinTrinketInventory", "trinkets.MixinScreenHandler", "seasons.MixinFertilizableUtil", - "ad_astra.MixinOxygenUtils" + "ad_astra.MixinOxygenUtils", + "forgified.MixinIForgeBoat" ], "client": [ "client.MixinAnimalModel", From 623d231f2f858e186debc57543f68d01d40561eb Mon Sep 17 00:00:00 2001 From: Sollace Date: Sun, 11 Feb 2024 14:51:29 +0000 Subject: [PATCH 13/13] Fix the mimic spell recipe --- src/main/resources/data/unicopia/recipes/spells/mimic.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/resources/data/unicopia/recipes/spells/mimic.json b/src/main/resources/data/unicopia/recipes/spells/mimic.json index eca1681a..546c0908 100644 --- a/src/main/resources/data/unicopia/recipes/spells/mimic.json +++ b/src/main/resources/data/unicopia/recipes/spells/mimic.json @@ -4,7 +4,9 @@ "traits": { "knowledge": 19, "life": 10, "chaos": 4 }, - "ingredients": [], + "ingredients": [ + { "item": "unicopia:gemstone", "spell": "unicopia:transformation" } + ], "result": { "item": "unicopia:gemstone", "spell": "unicopia:mimic"