1
0
Fork 0
mirror of https://github.com/Sollace/Unicopia.git synced 2025-04-03 09:45:29 +02:00

Merge branch 'Sollace:1.20.1' into 1.20.1

This commit is contained in:
LingVarr 2024-04-06 18:09:12 +11:00 committed by GitHub
commit f712d1ae1c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
253 changed files with 3100 additions and 4720 deletions
build.gradlegradle.properties
src/main/java/com/minelittlepony/unicopia
Debug.javaUConventionalTags.javaUTags.java
ability
block
client
compat/emi
container
datagen
diet
entity
item
mixin
projectile
recipe

View file

@ -44,13 +44,15 @@ reckon {
repositories {
mavenLocal()
flatDir { dirs 'lib' }
maven { name 'entity-reach-attributes'; url 'https://maven.jamieswhiteshirt.com/libs-release' }
maven { name 'entity-reach-attributes'; url 'https://maven.jamieswhiteshirt.com/libs-release'; content { includeGroup "com.jamieswhiteshirt" } }
maven { name 'trinkets'; url 'https://maven.ladysnake.org/releases' }
maven { name 'mod-menu'; url 'https://maven.terraformersmc.com/' }
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 'Nodium'; url 'https://maven.cafeteria.dev/releases/' }
maven { name 'Greenhouse Maven For Farmers delight'; url 'https://maven.greenhouseteam.dev/releases/' }
maven { name 'Porting Lib For Farmers delight'; url = 'https://mvn.devos.one/releases/' }
maven { name 'Modrinth'; url 'https://api.modrinth.com/maven' }
maven { name 'JitPack'; url 'https://jitpack.io'; content { includeGroup "com.github.Virtuoel" } }
}
@ -80,11 +82,13 @@ 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}"
modImplementation "me.luligabi:NoIndium:${project.nodium_version}"
include "me.luligabi:NoIndium:${project.nodium_version}"
modCompileOnly "maven.modrinth:farmers-delight-fabric:${project.farmers_delight_version}", { exclude group: "net.fabricmc.fabric-api" }
modImplementation "vectorwing:FarmersDelight-Refabricated:${project.farmers_delight_version}", {
exclude group: "net.fabricmc"
}
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" }
@ -103,6 +107,10 @@ dependencies {
}
}
remapJar {
addNestedDependencies = true
}
processResources {
inputs.property "version", project.version.toString()

View file

@ -5,7 +5,7 @@ org.gradle.daemon=false
# check these on https://fabricmc.net/develop
minecraft_version=1.20.1
yarn_mappings=1.20.1+build.10
loader_version=0.15.3
loader_version=0.15.7
fabric_version=0.91.0+1.20.1
# Mod Properties
@ -22,8 +22,8 @@ org.gradle.daemon=false
# Dependencies
fabwork_version=1.2.0
modmenu_version=7.0.0-beta.2
minelp_version=4.10.4+1.20.1
kirin_version=1.15.4+1.20
minelp_version=4.10.6+1.20.1
kirin_version=1.15.5-beta.1+1.20.1
reach_attributes_version=2.3.4
trinkets_version=3.7.1
terraformer_api_version=7.0.0-beta.1
@ -33,7 +33,7 @@ org.gradle.daemon=false
use_pehkui=0
use_sodium=1
farmers_delight_version=1.4.3
farmers_delight_version=1.20.1-2.0.9
pehkui_version=3.7.8+1.14.4-1.20.1
iris_version=1.6.17+1.20.1
sodium_version=mc1.20.1-0.5.8

View file

@ -51,7 +51,7 @@ public interface Debug {
)).forEach((namespace, entries) -> {
@SuppressWarnings("deprecation")
var unregistered = entries.stream()
.filter(entry -> !entry.getValue().getRegistryEntry().isIn(UTags.HAS_NO_TRAITS) && SpellTraits.of(entry.getValue()).isEmpty())
.filter(entry -> !entry.getValue().getRegistryEntry().isIn(UTags.Items.HAS_NO_TRAITS) && SpellTraits.of(entry.getValue()).isEmpty())
.map(entry -> {
String id = entry.getKey().getValue().toString();

View file

@ -7,32 +7,64 @@ import net.minecraft.registry.tag.TagKey;
import net.minecraft.util.Identifier;
public interface UConventionalTags {
TagKey<Item> APPLES = item("apples");
TagKey<Item> ACORNS = item("acorns");
TagKey<Item> PINECONES = item("pinecones");
TagKey<Item> PINEAPPLES = item("pineapples");
TagKey<Item> BANANAS = item("bananas");
TagKey<Item> STICKS = item("sticks");
TagKey<Item> SEEDS = item("seeds");
TagKey<Item> GRAIN = item("grain");
TagKey<Item> NUTS = item("nuts");
TagKey<Item> MUSHROOMS = item("mushrooms");
TagKey<Item> MUFFINS = item("muffins");
TagKey<Item> MANGOES = item("mangoes");
TagKey<Item> OATMEALS = item("oatmeals");
interface Blocks {
TagKey<Block> CONCRETE_POWDERS = block("concrete_powders");
TagKey<Block> CONCRETES = block("concretes");
TagKey<Block> GLAZED_TERRACOTTAS = block("glazed_terracottas");
TagKey<Block> CORAL_BLOCKS = block("coral_blocks");
TagKey<Block> CORAL_FANS = block("coral_fans");
TagKey<Block> CORALS = block("corals");
TagKey<Item> FRUITS = item("fruits");
TagKey<Item> COOKED_FISH = item("cooked_fish");
TagKey<Item> CROPS_PEANUTS = item("crops/peanuts");
TagKey<Item> TOOL_KNIVES = item("tools/knives");
static TagKey<Item> item(String name) {
return TagKey.of(RegistryKeys.ITEM, new Identifier("c", name));
private static TagKey<Block> block(String name) {
return TagKey.of(RegistryKeys.BLOCK, new Identifier("c", name));
}
}
static TagKey<Block> block(String name) {
return TagKey.of(RegistryKeys.BLOCK, new Identifier("c", name));
interface Items {
TagKey<Item> CONCRETE_POWDERS = item("concrete_powders");
TagKey<Item> CONCRETES = item("concretes");
TagKey<Item> GLAZED_TERRACOTTAS = item("glazed_terracottas");
TagKey<Item> CORAL_BLOCKS = item("coral_blocks");
TagKey<Item> CORAL_FANS = item("coral_fans");
TagKey<Item> CORALS = item("corals");
TagKey<Item> APPLES = item("apples");
TagKey<Item> ACORNS = item("acorns");
TagKey<Item> PINECONES = item("pinecones");
TagKey<Item> PINEAPPLES = item("pineapples");
TagKey<Item> BANANAS = item("bananas");
TagKey<Item> STICKS = item("sticks");
TagKey<Item> SEEDS = item("seeds");
TagKey<Item> GRAIN = item("grain");
TagKey<Item> NUTS = item("nuts");
TagKey<Item> MUSHROOMS = item("mushrooms");
TagKey<Item> MUFFINS = item("muffins");
TagKey<Item> MANGOES = item("mangoes");
TagKey<Item> OATMEALS = item("oatmeals");
TagKey<Item> COOKIES = item("cookies");
TagKey<Item> FRUITS = item("fruits");
TagKey<Item> WORMS = item("worms");
TagKey<Item> ROCKS = item("rocks");
TagKey<Item> RAW_INSECT = item("raw_insect");
TagKey<Item> COOKED_INSECT = item("cooked_insect");
TagKey<Item> ROTTEN_INSECT = item("rotten_insect");
TagKey<Item> RAW_FISH = item("raw_fish");
TagKey<Item> COOKED_FISH = item("cooked_fish");
TagKey<Item> ROTTEN_FISH = item("rotten_fish");
TagKey<Item> RAW_MEAT = item("raw_meat");
TagKey<Item> COOKED_MEAT = item("cooked_meat");
TagKey<Item> ROTTEN_MEAT = item("rotten_meat");
TagKey<Item> DESSERTS = item("desserts");
TagKey<Item> CANDY = item("candy");
TagKey<Item> CROPS_PEANUTS = item("crops/peanuts");
TagKey<Item> TOOL_KNIVES = item("tools/knives");
private static TagKey<Item> item(String name) {
return TagKey.of(RegistryKeys.ITEM, new Identifier("c", name));
}
}
}

View file

@ -11,58 +11,6 @@ import net.minecraft.util.Identifier;
import net.minecraft.world.dimension.DimensionType;
public interface UTags {
TagKey<Item> FRESH_APPLES = item("fresh_apples");
TagKey<Item> FALLS_SLOWLY = item("falls_slowly");
TagKey<Item> PIES = item("pies");
TagKey<Item> CAN_CUT_PIE = item("can_cut_pie");
TagKey<Item> MAGIC_FEATHERS = item("magic_feathers");
TagKey<Item> SHADES = item("shades");
TagKey<Item> CHANGELING_EDIBLE = item("food_types/changeling_edible");
TagKey<Item> SPOOKED_MOB_DROPS = item("spooked_mob_drops");
TagKey<Item> HAS_NO_TRAITS = item("has_no_traits");
TagKey<Item> IS_DELIVERED_AGGRESSIVELY = item("is_delivered_aggressively");
TagKey<Item> FLOATS_ON_CLOUDS = item("floats_on_clouds");
TagKey<Item> COOLS_OFF_KIRINS = item("cools_off_kirins");
TagKey<Item> LOOT_BUG_HIGH_VALUE_DROPS = item("loot_bug_high_value_drops");
TagKey<Item> SHELLS = item("food_types/shells");
TagKey<Item> POLEARMS = item("polearms");
TagKey<Item> HORSE_SHOES = item("horse_shoes");
TagKey<Item> APPLE_SEEDS = item("apple_seeds");
TagKey<Item> BASKETS = item("baskets");
TagKey<Item> BADGES = item("badges");
TagKey<Item> WOOL_BED_SHEETS = item("wool_bed_sheets");
TagKey<Item> BED_SHEETS = item("bed_sheets");
TagKey<Item> CLOUD_JARS = item("cloud_jars");
TagKey<Block> FRAGILE = block("fragile");
TagKey<Block> INTERESTING = block("interesting");
TagKey<Block> CATAPULT_IMMUNE = block("catapult_immune");
TagKey<Block> JARS = block("jars");
TagKey<Block> CRYSTAL_HEART_BASE = block("crystal_heart_base");
TagKey<Block> CRYSTAL_HEART_ORNAMENT = block("crystal_heart_ornament");
TagKey<Block> UNAFFECTED_BY_GROW_ABILITY = block("unaffected_by_grow_ability");
TagKey<Block> KICKS_UP_DUST = block("kicks_up_dust");
TagKey<Block> POLEARM_MINEABLE = block("mineable/polearm");
TagKey<EntityType<?>> TRANSFORMABLE_ENTITIES = entity("transformable");
TagKey<StatusEffect> PINEAPPLE_EFFECTS = effect("pineapple_effects");
TagKey<DamageType> BREAKS_SUNGLASSES = damage("breaks_sunglasses");
TagKey<DamageType> SPELLBOOK_IMMUNE_TO = damage("spellbook_immune_to");
TagKey<DamageType> FROM_ROCKS = damage("from_rocks");
TagKey<DamageType> FROM_HORSESHOES = damage("from_horseshoes");
TagKey<DimensionType> HAS_NO_ATMOSPHERE = dimension("has_no_atmosphere");
interface Items {
TagKey<Item> ZAP_LOGS = item("zap_logs");
TagKey<Item> WAXED_ZAP_LOGS = item("waxed_zap_logs");
@ -72,6 +20,67 @@ public interface UTags {
TagKey<Item> CLOUD_STAIRS = item("cloud_stairs");
TagKey<Item> CLOUD_BLOCKS = item("cloud_blocks");
TagKey<Item> CHITIN_BLOCKS = item("chitin_blocks");
TagKey<Item> FRESH_APPLES = item("fresh_apples");
TagKey<Item> FALLS_SLOWLY = item("falls_slowly");
TagKey<Item> PIES = item("pies");
TagKey<Item> CAN_CUT_PIE = item("can_cut_pie");
TagKey<Item> MAGIC_FEATHERS = item("magic_feathers");
TagKey<Item> SHADES = item("shades");
TagKey<Item> SPOOKED_MOB_DROPS = item("spooked_mob_drops");
TagKey<Item> HAS_NO_TRAITS = item("has_no_traits");
TagKey<Item> IS_DELIVERED_AGGRESSIVELY = item("is_delivered_aggressively");
TagKey<Item> CONTAINER_WITH_LOVE = item("container_with_love");
TagKey<Item> FLOATS_ON_CLOUDS = item("floats_on_clouds");
TagKey<Item> COOLS_OFF_KIRINS = item("cools_off_kirins");
TagKey<Item> LOOT_BUG_COMMON_DROPS = item("loot_bug_common_drops");
TagKey<Item> LOOT_BUG_RARE_DROPS = item("loot_bug_rare_drops");
TagKey<Item> LOOT_BUG_EPIC_DROPS = item("loot_bug_epic_drops");
TagKey<Item> SHELLS = item("shells");
TagKey<Item> SPECIAL_SHELLS = item("special_shells");
TagKey<Item> ROCK_STEWS = item("rock_stews");
TagKey<Item> BAKED_GOODS = item("baked_goods");
TagKey<Item> HIGH_QUALITY_SEA_VEGETABLES = item("food_types/high_quality_sea_vegetables");
TagKey<Item> LOW_QUALITY_SEA_VEGETABLES = item("food_types/low_quality_sea_vegetables");
TagKey<Item> POLEARMS = item("polearms");
TagKey<Item> HORSE_SHOES = item("horse_shoes");
TagKey<Item> APPLE_SEEDS = item("apple_seeds");
TagKey<Item> BASKETS = item("baskets");
TagKey<Item> BADGES = item("badges");
TagKey<Item> WOOL_BED_SHEETS = item("wool_bed_sheets");
TagKey<Item> BED_SHEETS = item("bed_sheets");
TagKey<Item> CLOUD_JARS = item("cloud_jars");
TagKey<Item> GROUP_FORAGING = item("groups/foraging");
TagKey<Item> GROUP_EARTH_PONY = item("groups/earth_pony");
TagKey<Item> GROUP_UNICORN = item("groups/unicorn");
TagKey<Item> GROUP_PEGASUS = item("groups/pegasus");
TagKey<Item> GROUP_BAT_PONY = item("groups/bat_pony");
TagKey<Item> GROUP_SEA_PONY = item("groups/sea_pony");
TagKey<Item> GROUP_CHANGELING = item("groups/changeling");
TagKey<Item> FORAGE_BLINDING = item("forage/blinding");
TagKey<Item> FORAGE_DANGEROUS = item("forage/dangerous");
TagKey<Item> FORAGE_FILLING = item("forage/filling");
TagKey<Item> FORAGE_SAFE = item("forage/safe");
TagKey<Item> FORAGE_NAUSEATING = item("forage/nauseating");
TagKey<Item> FORAGE_PRICKLY = item("forage/prickly");
TagKey<Item> FORAGE_GLOWING = item("forage/glowing");
TagKey<Item> FORAGE_RISKY = item("forage/risky");
TagKey<Item> FORAGE_STRENGHENING = item("forage/strenghtening");
TagKey<Item> FORAGE_SEVERE_NAUSEATING = item("forage/severe/nauseating");
TagKey<Item> FORAGE_SEVERE_PRICKLY = item("forage/severe/prickly");
private static TagKey<Item> item(String name) {
return TagKey.of(RegistryKeys.ITEM, Unicopia.id(name));
}
}
interface Blocks {
@ -83,29 +92,58 @@ public interface UTags {
TagKey<Block> CLOUD_STAIRS = block("cloud_stairs");
TagKey<Block> CLOUD_BLOCKS = block("cloud_blocks");
TagKey<Block> CHITIN_BLOCKS = block("chitin_blocks");
TagKey<Block> FRAGILE = block("fragile");
TagKey<Block> INTERESTING = block("interesting");
TagKey<Block> CATAPULT_IMMUNE = block("catapult_immune");
TagKey<Block> JARS = block("jars");
TagKey<Block> CRYSTAL_HEART_BASE = block("crystal_heart_base");
TagKey<Block> CRYSTAL_HEART_ORNAMENT = block("crystal_heart_ornament");
TagKey<Block> UNAFFECTED_BY_GROW_ABILITY = block("unaffected_by_grow_ability");
TagKey<Block> KICKS_UP_DUST = block("kicks_up_dust");
TagKey<Block> POLEARM_MINEABLE = block("mineable/polearm");
TagKey<Block> BUTTERFLIES_SPAWNABLE_ON = block("butterflies_spawn_on");
private static TagKey<Block> block(String name) {
return TagKey.of(RegistryKeys.BLOCK, Unicopia.id(name));
}
}
static TagKey<Item> item(String name) {
return TagKey.of(RegistryKeys.ITEM, Unicopia.id(name));
interface Entities {
TagKey<EntityType<?>> TRANSFORMABLE = entity("transformable");
private static TagKey<EntityType<?>> entity(String name) {
return TagKey.of(RegistryKeys.ENTITY_TYPE, Unicopia.id(name));
}
}
static TagKey<Block> block(String name) {
return TagKey.of(RegistryKeys.BLOCK, Unicopia.id(name));
interface DamageTypes {
TagKey<DamageType> BREAKS_SUNGLASSES = damage("breaks_sunglasses");
TagKey<DamageType> SPELLBOOK_IMMUNE_TO = damage("spellbook_immune_to");
TagKey<DamageType> FROM_ROCKS = damage("from_rocks");
TagKey<DamageType> FROM_HORSESHOES = damage("from_horseshoes");
private static TagKey<DamageType> damage(String name) {
return TagKey.of(RegistryKeys.DAMAGE_TYPE, Unicopia.id(name));
}
}
static TagKey<EntityType<?>> entity(String name) {
return TagKey.of(RegistryKeys.ENTITY_TYPE, Unicopia.id(name));
interface DimensionTypes {
TagKey<DimensionType> HAS_NO_ATMOSPHERE = dimension("has_no_atmosphere");
private static TagKey<DimensionType> dimension(String name) {
return TagKey.of(RegistryKeys.DIMENSION_TYPE, new Identifier("c", name));
}
}
static TagKey<StatusEffect> effect(String name) {
return TagKey.of(RegistryKeys.STATUS_EFFECT, Unicopia.id(name));
}
interface StatusEffects {
TagKey<StatusEffect> PINEAPPLE_EFFECTS = effect("pineapple_effects");
static TagKey<DamageType> damage(String name) {
return TagKey.of(RegistryKeys.DAMAGE_TYPE, Unicopia.id(name));
}
static TagKey<DimensionType> dimension(String name) {
return TagKey.of(RegistryKeys.DIMENSION_TYPE, new Identifier("c", name));
private static TagKey<StatusEffect> effect(String name) {
return TagKey.of(RegistryKeys.STATUS_EFFECT, Unicopia.id(name));
}
}
}

View file

@ -10,10 +10,10 @@ 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.item.TransformCropsRecipe;
import com.minelittlepony.unicopia.item.URecipes;
import com.minelittlepony.unicopia.particle.MagicParticleEffect;
import com.minelittlepony.unicopia.particle.ParticleUtils;
import com.minelittlepony.unicopia.recipe.TransformCropsRecipe;
import com.minelittlepony.unicopia.recipe.URecipes;
import com.minelittlepony.unicopia.server.world.BlockDestructionManager;
import com.minelittlepony.unicopia.util.TraceHelper;
import com.minelittlepony.unicopia.util.VecHelper;
@ -108,7 +108,7 @@ public class EarthPonyGrowAbility implements Ability<Pos> {
}
}
if (w.getBlockState(pos).isIn(UTags.UNAFFECTED_BY_GROW_ABILITY)) {
if (w.getBlockState(pos).isIn(UTags.Blocks.UNAFFECTED_BY_GROW_ABILITY)) {
return 0;
}

View file

@ -162,7 +162,7 @@ public class EarthPonyStompAbility implements Ability<Hit> {
ParticleUtils.spawnParticle(player.getWorld(), UParticles.GROUND_POUND, player.getX(), player.getY() - 1, player.getZ(), 0, 0, 0);
BlockState steppingState = player.getSteppingBlockState();
if (steppingState.isIn(UTags.KICKS_UP_DUST)) {
if (steppingState.isIn(UTags.Blocks.KICKS_UP_DUST)) {
ParticleUtils.spawnParticle(player.getWorld(), new BlockStateParticleEffect(UParticles.DUST_CLOUD, steppingState), player.getBlockPos().down().toCenterPos(), Vec3d.ZERO);
}
@ -227,7 +227,7 @@ public class EarthPonyStompAbility implements Ability<Hit> {
w.syncWorldEvent(WorldEvents.BLOCK_BROKEN, pos, Block.getRawIdFromState(state));
}
if (state.isIn(UTags.KICKS_UP_DUST)) {
if (state.isIn(UTags.Blocks.KICKS_UP_DUST)) {
if (w.random.nextInt(4) == 0 && w.isAir(pos.up()) && w.getFluidState(pos.up()).isEmpty()) {
ParticleUtils.spawnParticle(w, new BlockStateParticleEffect(UParticles.DUST_CLOUD, state), pos.up().toCenterPos(), VecHelper.supply(() -> w.random.nextTriangular(0, 0.1F)));
}

View file

@ -110,7 +110,7 @@ public class ScreechAbility implements Ability<Numeric> {
if (living.getWorld().random.nextInt(MOB_SPOOK_PROBABILITY) == 0) {
RegistryUtils.pickRandom(living.getWorld(), UTags.SPOOKED_MOB_DROPS).ifPresent(drop -> {
RegistryUtils.pickRandom(living.getWorld(), UTags.Items.SPOOKED_MOB_DROPS).ifPresent(drop -> {
living.dropStack(drop.getDefaultStack());
living.playSound(USounds.Vanilla.ENTITY_ITEM_PICKUP, 1, 0.1F);
UCriteria.SPOOK_MOB.trigger(player.asEntity());

View file

@ -64,7 +64,7 @@ public class RainboomAbilitySpell extends AbstractSpell {
});
EFFECT_RANGE.translate(source.getOrigin()).getBlockPositions().forEach(pos -> {
BlockState state = source.asWorld().getBlockState(pos);
if (state.isIn(UTags.FRAGILE) && source.canModifyAt(pos, ModificationType.PHYSICAL)) {
if (state.isIn(UTags.Blocks.FRAGILE) && source.canModifyAt(pos, ModificationType.PHYSICAL)) {
source.asWorld().breakBlock(pos, true);
}
});

View file

@ -9,7 +9,7 @@ import com.minelittlepony.unicopia.ability.magic.spell.effect.SpellType;
import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits;
import com.minelittlepony.unicopia.container.inventory.SpellbookInventory;
import com.minelittlepony.unicopia.item.EnchantableItem;
import com.minelittlepony.unicopia.item.URecipes;
import com.minelittlepony.unicopia.recipe.URecipes;
import com.minelittlepony.unicopia.util.InventoryUtil;
import com.mojang.datafixers.util.Pair;

View file

@ -4,6 +4,7 @@ import com.google.gson.JsonObject;
import com.minelittlepony.unicopia.ability.magic.spell.effect.SpellType;
import com.minelittlepony.unicopia.container.inventory.SpellbookInventory;
import com.minelittlepony.unicopia.item.*;
import com.minelittlepony.unicopia.recipe.URecipes;
import com.minelittlepony.unicopia.util.InventoryUtil;
import net.minecraft.item.ItemStack;

View file

@ -4,6 +4,7 @@ import com.google.gson.JsonObject;
import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits;
import com.minelittlepony.unicopia.container.inventory.SpellbookInventory;
import com.minelittlepony.unicopia.item.*;
import com.minelittlepony.unicopia.recipe.URecipes;
import net.minecraft.item.ItemStack;
import net.minecraft.network.PacketByteBuf;

View file

@ -2,7 +2,7 @@ package com.minelittlepony.unicopia.ability.magic.spell.crafting;
import com.google.gson.JsonObject;
import com.minelittlepony.unicopia.item.EnchantableItem;
import com.minelittlepony.unicopia.item.URecipes;
import com.minelittlepony.unicopia.recipe.URecipes;
import com.minelittlepony.unicopia.util.InventoryUtil;
import net.minecraft.inventory.RecipeInputInventory;

View file

@ -5,7 +5,7 @@ import java.util.List;
import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait;
import com.minelittlepony.unicopia.container.inventory.SpellbookInventory;
import com.minelittlepony.unicopia.item.UItems;
import com.minelittlepony.unicopia.item.URecipes;
import com.minelittlepony.unicopia.recipe.URecipes;
import net.minecraft.item.ItemStack;
import net.minecraft.recipe.Recipe;

View file

@ -86,7 +86,7 @@ public class CatapultSpell extends AbstractSpell implements ProjectileDelegate.B
}
BlockState state = world.getBlockState(bpos);
if (state.isIn(UTags.CATAPULT_IMMUNE)) {
if (state.isIn(UTags.Blocks.CATAPULT_IMMUNE)) {
return;
}

View file

@ -66,7 +66,7 @@ public class TransformationSpell extends AbstractSpell implements ProjectileDele
@SuppressWarnings("unchecked")
private <T extends MobEntity> Optional<EntityType<T>> pickType(EntityType<?> except, World world) {
Set<EntityType<?>> options = RegistryUtils.valuesForTag(world, UTags.TRANSFORMABLE_ENTITIES).collect(Collectors.toSet());
Set<EntityType<?>> options = RegistryUtils.valuesForTag(world, UTags.Entities.TRANSFORMABLE).collect(Collectors.toSet());
if (except.getSpawnGroup() == SpawnGroup.MONSTER) {
options.removeIf(t -> t.getSpawnGroup() == SpawnGroup.MONSTER);
} else {

View file

@ -8,7 +8,7 @@ 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 static final BooleanProperty ENCHANTED = BooleanProperty.of("enchanted");
public EnchantedFruitBlock(Settings settings, Direction attachmentFace, Block stem, VoxelShape shape) {
super(settings, attachmentFace, stem, shape);

View file

@ -1,9 +1,14 @@
package com.minelittlepony.unicopia.block;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.IntStream;
import org.jetbrains.annotations.Nullable;
import com.minelittlepony.unicopia.block.jar.EntityJarContents;
import com.minelittlepony.unicopia.block.jar.FluidOnlyJarContents;
import com.minelittlepony.unicopia.block.jar.ItemsJarContents;
import com.minelittlepony.unicopia.block.jar.FakeFluidJarContents;
import net.fabricmc.fabric.api.transfer.v1.fluid.FluidConstants;
import net.fabricmc.fabric.api.transfer.v1.fluid.FluidVariant;
import net.minecraft.block.BlockEntityProvider;
import net.minecraft.block.BlockRenderType;
import net.minecraft.block.BlockState;
@ -12,11 +17,18 @@ import net.minecraft.block.entity.BlockEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.inventory.SidedInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemUsage;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.nbt.NbtElement;
import net.minecraft.network.listener.ClientPlayPacketListener;
import net.minecraft.network.packet.Packet;
import net.minecraft.network.packet.s2c.play.BlockEntityUpdateS2CPacket;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.TypedActionResult;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.world.World;
import net.minecraft.world.WorldAccess;
@ -36,14 +48,7 @@ public class ItemJarBlock extends JarBlock implements BlockEntityProvider, Inven
if (hand == Hand.OFF_HAND) {
return ActionResult.PASS;
}
return world.getBlockEntity(pos, UBlockEntities.ITEM_JAR).map(data -> {
ItemStack stack = player.getStackInHand(hand);
if (stack.isEmpty()) {
return data.removeItem(world, pos);
}
return data.insertItem(world, pos, player.isCreative() ? stack.copyWithCount(1) : stack.split(1));
}).orElse(ActionResult.PASS);
return world.getBlockEntity(pos, UBlockEntities.ITEM_JAR).map(data -> data.interact(player, hand)).orElse(ActionResult.PASS);
}
@Deprecated
@ -51,9 +56,7 @@ public class ItemJarBlock extends JarBlock implements BlockEntityProvider, Inven
public void onStateReplaced(BlockState state, World world, BlockPos pos, BlockState newState, boolean moved) {
if (!moved && !state.isOf(newState.getBlock())) {
world.getBlockEntity(pos, UBlockEntities.ITEM_JAR).ifPresent(data -> {
data.getStacks().forEach(stack -> {
dropStack(world, pos, stack);
});
data.getContents().onDestroyed();
});
}
super.onStateReplaced(state, world, pos, newState, moved);
@ -66,7 +69,10 @@ public class ItemJarBlock extends JarBlock implements BlockEntityProvider, Inven
@Override
public int getComparatorOutput(BlockState state, World world, BlockPos pos) {
return world.getBlockEntity(pos, UBlockEntities.ITEM_JAR).map(data -> Math.min(16, data.getStacks().size())).orElse(0);
return world.getBlockEntity(pos, UBlockEntities.ITEM_JAR)
.map(TileData::getItems)
.map(data -> Math.min(16, data.stacks().size()))
.orElse(0);
}
@Deprecated
@ -82,135 +88,113 @@ public class ItemJarBlock extends JarBlock implements BlockEntityProvider, Inven
return new TileData(pos, state);
}
@Nullable
@Override
public SidedInventory getInventory(BlockState state, WorldAccess world, BlockPos pos) {
return world.getBlockEntity(pos, UBlockEntities.ITEM_JAR).orElse(null);
return world.getBlockEntity(pos, UBlockEntities.ITEM_JAR).map(TileData::getItems).orElse(null);
}
public static class TileData extends BlockEntity implements SidedInventory {
private static final int[] SLOTS = IntStream.range(0, 16).toArray();
private final List<ItemStack> stacks = new ArrayList<>();
public static class TileData extends BlockEntity {
private JarContents contents = new ItemsJarContents(this);
public TileData(BlockPos pos, BlockState state) {
super(UBlockEntities.ITEM_JAR, pos, state);
}
public ActionResult insertItem(World world, BlockPos pos, ItemStack stack) {
if (stacks.size() >= size()) {
return ActionResult.FAIL;
}
stacks.add(stack);
markDirty();
return ActionResult.SUCCESS;
public ActionResult interact(PlayerEntity player, Hand hand) {
TypedActionResult<JarContents> result = contents.interact(player, hand);
contents = result.getValue();
return result.getResult();
}
public ActionResult removeItem(World world, BlockPos pos) {
if (stacks.isEmpty()) {
return ActionResult.FAIL;
}
dropStack(world, pos, stacks.remove(0));
markDirty();
return ActionResult.SUCCESS;
public JarContents getContents() {
return contents;
}
public List<ItemStack> getStacks() {
return stacks;
@Nullable
public ItemsJarContents getItems() {
return getContents() instanceof ItemsJarContents c ? c : null;
}
@Nullable
public EntityJarContents getEntity() {
return getContents() instanceof EntityJarContents c ? c : null;
}
@Nullable
public FluidJarContents getFluid() {
return getContents() instanceof FluidJarContents c ? c : null;
}
@Nullable
public FakeFluidJarContents getFakeFluid() {
return getContents() instanceof FakeFluidJarContents c ? c : null;
}
@Override
public int size() {
return 15;
public Packet<ClientPlayPacketListener> toUpdatePacket() {
return BlockEntityUpdateS2CPacket.create(this);
}
@Override
public boolean isEmpty() {
return stacks.isEmpty();
public NbtCompound toInitialChunkDataNbt() {
return createNbt();
}
@Override
public ItemStack getStack(int slot) {
return slot < 0 || slot >= stacks.size() ? ItemStack.EMPTY : stacks.get(slot);
}
@Override
public ItemStack removeStack(int slot, int amount) {
if (slot < 0 || slot >= stacks.size()) {
try {
ItemStack stack = stacks.get(slot);
ItemStack removed = stack.split(1);
if (stack.isEmpty()) {
stacks.remove(slot);
}
return removed;
} finally {
markDirty();
}
}
return ItemStack.EMPTY;
}
@Override
public ItemStack removeStack(int slot) {
if (slot < 0 || slot >= stacks.size()) {
try {
return stacks.remove(slot);
} finally {
markDirty();
}
}
return ItemStack.EMPTY;
}
@Override
public void setStack(int slot, ItemStack stack) {
if (slot >= stacks.size()) {
if (stacks.size() >= size()) {
dropStack(getWorld(), getPos(), stack);
} else {
stacks.add(stack);
}
} else {
ItemStack existing = stacks.get(slot);
if (!ItemStack.canCombine(existing, stack)) {
dropStack(getWorld(), getPos(), stack);
} else {
existing.setCount(existing.getCount() + stack.split(Math.max(0, existing.getMaxCount() - existing.getCount())).getCount());
if (!stack.isEmpty()) {
dropStack(getWorld(), getPos(), stack);
}
}
public void markDirty() {
super.markDirty();
if (getWorld() instanceof ServerWorld sw) {
sw.getChunkManager().markForUpdate(getPos());
}
}
@Override
public boolean canPlayerUse(PlayerEntity player) {
return false;
public void readNbt(NbtCompound nbt) {
if (nbt.contains("items", NbtElement.COMPOUND_TYPE)) {
contents = new ItemsJarContents(this, nbt.getCompound("items"));
} else if (nbt.contains("entity", NbtElement.COMPOUND_TYPE)) {
contents = new EntityJarContents(this, nbt.getCompound("entity"));
} else if (nbt.contains("fluid", NbtElement.COMPOUND_TYPE)) {
contents = new FluidOnlyJarContents(this, nbt.getCompound("fluid"));
} else if (nbt.contains("fakeFluid", NbtElement.COMPOUND_TYPE)) {
contents = new FakeFluidJarContents(this, nbt.getCompound("fakeFluid"));
}
}
@Override
public void clear() {
stacks.clear();
markDirty();
protected void writeNbt(NbtCompound nbt) {
var items = getItems();
if (items != null) {
nbt.put("items", items.toNBT(new NbtCompound()));
} else if (getEntity() != null) {
nbt.put("entity", getEntity().toNBT(new NbtCompound()));
} else if (getFluid() != null) {
nbt.put("fluid", getFluid().toNBT(new NbtCompound()));
} else if (getFakeFluid() != null) {
nbt.put("fakeFluid", getFakeFluid().toNBT(new NbtCompound()));
}
}
}
@Override
public int[] getAvailableSlots(Direction side) {
return SLOTS;
public interface JarContents {
TypedActionResult<JarContents> interact(PlayerEntity player, Hand hand);
void onDestroyed();
NbtCompound toNBT(NbtCompound compound);
default void consumeAndSwap(PlayerEntity player, Hand hand, ItemStack output) {
player.setStackInHand(hand, ItemUsage.exchangeStack(player.getStackInHand(hand), player, output.copy()));
}
}
@Override
public boolean canInsert(int slot, ItemStack stack, Direction dir) {
return (slot >= 0 && slot < size()) && (slot >= stacks.size() || (
ItemStack.canCombine(stacks.get(slot), stack)
&& (stacks.get(slot).getCount() + stack.getCount()) <= Math.min(stacks.get(slot).getMaxCount(), stack.getMaxCount())
));
}
public interface FluidJarContents extends JarContents {
FluidVariant fluid();
@Override
public boolean canExtract(int slot, ItemStack stack, Direction dir) {
return true;
default long amount() {
return FluidConstants.BUCKET;
}
}
}

View file

@ -11,10 +11,17 @@ import net.minecraft.block.AbstractGlassBlock;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.ShapeContext;
import net.minecraft.block.Waterloggable;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.enchantment.EnchantmentHelper;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.fluid.FluidState;
import net.minecraft.fluid.Fluids;
import net.minecraft.item.ItemPlacementContext;
import net.minecraft.item.ItemStack;
import net.minecraft.state.StateManager;
import net.minecraft.state.property.BooleanProperty;
import net.minecraft.state.property.Properties;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.random.Random;
@ -22,17 +29,25 @@ import net.minecraft.util.shape.VoxelShape;
import net.minecraft.util.shape.VoxelShapes;
import net.minecraft.world.BlockView;
import net.minecraft.world.World;
import net.minecraft.world.WorldAccess;
import net.minecraft.world.explosion.Explosion;
public class JarBlock extends AbstractGlassBlock {
public class JarBlock extends AbstractGlassBlock implements Waterloggable {
private static final VoxelShape SHAPE = VoxelShapes.union(
Block.createCuboidShape(4, 0, 4, 12, 12, 12),
Block.createCuboidShape(6, 12, 6, 10, 16, 10),
Block.createCuboidShape(5, 13, 5, 11, 14, 11)
);
private static final BooleanProperty WATERLOGGED = Properties.WATERLOGGED;
public JarBlock(Settings settings) {
super(settings);
setDefaultState(getDefaultState().with(WATERLOGGED, false));
}
@Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
builder.add(WATERLOGGED);
}
@Override
@ -40,9 +55,26 @@ public class JarBlock extends AbstractGlassBlock {
return SHAPE;
}
@Deprecated
@Override
public boolean isSideInvisible(BlockState state, BlockState stateFrom, Direction direction) {
return super.isSideInvisible(state, stateFrom, direction);
public BlockState getStateForNeighborUpdate(BlockState state, Direction direction, BlockState neighborState, WorldAccess world, BlockPos pos, BlockPos neighborPos) {
if (state.get(WATERLOGGED)) {
world.scheduleFluidTick(pos, Fluids.WATER, Fluids.WATER.getTickRate(world));
}
return super.getStateForNeighborUpdate(state, direction, neighborState, world, pos, neighborPos);
}
@Nullable
@Override
public BlockState getPlacementState(ItemPlacementContext ctx) {
return getDefaultState().with(WATERLOGGED, ctx.getWorld().getFluidState(ctx.getBlockPos()).getFluid() == Fluids.WATER);
}
@Deprecated
@Override
public FluidState getFluidState(BlockState state) {
return state.get(WATERLOGGED) ? Fluids.WATER.getStill(false) : super.getFluidState(state);
}
@Override

View file

@ -71,7 +71,7 @@ public class PieBlock extends Block implements Waterloggable {
if (world.isClient) {
if (itemStack.isIn(UTags.CAN_CUT_PIE)) {
if (itemStack.isIn(UTags.Items.CAN_CUT_PIE)) {
return ActionResult.SUCCESS;
}
@ -84,7 +84,7 @@ public class PieBlock extends Block implements Waterloggable {
}
}
if (itemStack.isIn(UTags.CAN_CUT_PIE)) {
if (itemStack.isIn(UTags.Items.CAN_CUT_PIE)) {
SoundEmitter.playSoundAt(player, USounds.BLOCK_PIE_SLICE, SoundCategory.NEUTRAL, 1, 1);
removeSlice(world, pos, state, player);
itemStack.damage(1, player, p -> p.sendToolBreakStatus(hand));

View file

@ -41,7 +41,7 @@ public class PineappleCropBlock extends CropBlock {
}
@Override
protected boolean canPlantOnTop(BlockState floor, BlockView world, BlockPos pos) {
public boolean canPlantOnTop(BlockState floor, BlockView world, BlockPos pos) {
return floor.isOf(this) || super.canPlantOnTop(floor, world, pos);
}

View file

@ -97,7 +97,7 @@ public class SegmentedCropBlock extends CropBlock implements SegmentedBlock {
}
@Override
protected boolean canPlantOnTop(BlockState state, BlockView view, BlockPos pos) {
public boolean canPlantOnTop(BlockState state, BlockView view, BlockPos pos) {
return (state.getBlock() instanceof SegmentedCropBlock o && o.canSupportBlock(this, state, view, pos)) || super.canPlantOnTop(state, view, pos);
}
@ -204,4 +204,8 @@ public class SegmentedCropBlock extends CropBlock implements SegmentedBlock {
return state.getBlock() == this || (nextSegmentSupplier != null && nextSegmentSupplier.get().isNext(state));
}
@Nullable
public SegmentedCropBlock getNext() {
return nextSegmentSupplier == null ? null : nextSegmentSupplier.get();
}
}

View file

@ -199,7 +199,7 @@ public class SlimePustuleBlock extends Block {
public void onStateReplaced(BlockState state, World world, BlockPos pos, BlockState newState, boolean moved) {
super.onStateReplaced(state, world, pos, newState, moved);
if (state.isOf(this) && newState.isOf(this) && state.get(POWERED) != newState.get(POWERED)) {
world.updateNeighbor(pos.up(), this, pos);
world.updateNeighborsAlways(pos.up(), this);
}
}

View file

@ -0,0 +1,80 @@
package com.minelittlepony.unicopia.block.jar;
import java.util.function.Supplier;
import org.jetbrains.annotations.Nullable;
import com.google.common.base.Suppliers;
import com.minelittlepony.unicopia.block.ItemJarBlock.FluidJarContents;
import com.minelittlepony.unicopia.block.ItemJarBlock.JarContents;
import com.minelittlepony.unicopia.block.ItemJarBlock.TileData;
import net.fabricmc.fabric.api.transfer.v1.fluid.FluidVariant;
import net.minecraft.block.Blocks;
import net.minecraft.entity.Bucketable;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.fluid.Fluids;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.registry.Registries;
import net.minecraft.util.Hand;
import net.minecraft.util.Identifier;
import net.minecraft.util.TypedActionResult;
public record EntityJarContents (
TileData tile,
@Nullable EntityType<?> entityType,
Supplier<@Nullable Entity> entity
) implements FluidJarContents {
public EntityJarContents(TileData tile, NbtCompound compound) {
this(tile, Registries.ENTITY_TYPE.getOrEmpty(Identifier.tryParse(compound.getString("entity"))).orElse(null));
}
public EntityJarContents(TileData tile) {
this(tile, (EntityType<?>)null);
}
public EntityJarContents(TileData tile, EntityType<?> entityType) {
this(tile, entityType, Suppliers.memoize(() -> {
return entityType == null ? null : entityType.create(tile.getWorld());
}));
}
@Override
public TypedActionResult<JarContents> interact(PlayerEntity player, Hand hand) {
ItemStack stack = player.getStackInHand(hand);
if (stack.isOf(Items.BUCKET)) {
if (entity().get() instanceof Bucketable bucketable) {
consumeAndSwap(player, hand, bucketable.getBucketItem());
player.playSound(bucketable.getBucketFillSound(), 1, 1);
}
tile.markDirty();
return TypedActionResult.success(new ItemsJarContents(tile));
}
return TypedActionResult.pass(this);
}
@Override
public void onDestroyed() {
tile.getWorld().setBlockState(tile.getPos(), Blocks.WATER.getDefaultState());
Entity entity = entity().get();
if (entity != null) {
entity.refreshPositionAfterTeleport(tile.getPos().toCenterPos());
tile.getWorld().spawnEntity(entity);
}
}
@Override
public NbtCompound toNBT(NbtCompound compound) {
compound.putString("entity", EntityType.getId(entityType).toString());
return compound;
}
@Override
public FluidVariant fluid() {
return FluidVariant.of(Fluids.WATER);
}
}

View file

@ -0,0 +1,79 @@
package com.minelittlepony.unicopia.block.jar;
import java.util.Optional;
import com.minelittlepony.unicopia.USounds;
import com.minelittlepony.unicopia.block.ItemJarBlock.JarContents;
import com.minelittlepony.unicopia.block.ItemJarBlock.TileData;
import com.minelittlepony.unicopia.util.FluidHelper;
import net.fabricmc.fabric.api.transfer.v1.fluid.FluidConstants;
import net.fabricmc.fabric.api.transfer.v1.fluid.FluidVariant;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.fluid.Fluid;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.registry.Registries;
import net.minecraft.util.Hand;
import net.minecraft.util.Identifier;
import net.minecraft.util.TypedActionResult;
public record FakeFluidJarContents (
TileData tile,
String fluid,
int color,
Item empty,
Item filled
) implements JarContents {
public FakeFluidJarContents(TileData tile, NbtCompound compound) {
this(tile, compound.getString("fluid"), compound.getInt("color"),
Registries.ITEM.get(new Identifier(compound.getString("empty"))),
Registries.ITEM.get(new Identifier(compound.getString("filled"))));
}
@Override
public TypedActionResult<JarContents> interact(PlayerEntity player, Hand hand) {
ItemStack stack = player.getStackInHand(hand);
tile.markDirty();
return getRealFluid().map(FluidVariant::of).<TypedActionResult<JarContents>>map(fluid -> {
long remainder = FluidHelper.deposit(stack, player, hand, fluid, FluidConstants.BUCKET);
fluid.getFluid().getBucketFillSound().ifPresent(sound -> player.playSound(sound, 1, 1));
if (remainder > 0) {
return TypedActionResult.success(new FluidOnlyJarContents(tile, remainder, fluid));
}
return TypedActionResult.success(new ItemsJarContents(tile));
}).orElseGet(() -> {
if (!stack.isOf(empty)) {
return TypedActionResult.pass(this);
}
consumeAndSwap(player, hand, filled.getDefaultStack());
player.playSound("powder_snow".equalsIgnoreCase(fluid) ? USounds.Vanilla.ITEM_BUCKET_FILL_POWDER_SNOW : USounds.Vanilla.ITEM_BUCKET_FILL, 1, 1);
return TypedActionResult.success(new ItemsJarContents(tile));
});
}
@Override
public void onDestroyed() {
getRealFluid().ifPresent(fluid -> {
tile.getWorld().setBlockState(tile.getPos(), FluidHelper.getFullFluidState(FluidVariant.of(fluid)).getBlockState());
});
}
@Override
public NbtCompound toNBT(NbtCompound compound) {
compound.putString("fluid", fluid);
compound.putInt("color", color);
compound.putString("empty", Registries.ITEM.getId(empty).toString());
compound.putString("filled", Registries.ITEM.getId(filled).toString());
return compound;
}
private Optional<Fluid> getRealFluid() {
return Registries.FLUID.getIds().stream()
.filter(id -> id.getPath().equalsIgnoreCase(fluid))
.findFirst()
.map(Registries.FLUID::get);
}
}

View file

@ -0,0 +1,55 @@
package com.minelittlepony.unicopia.block.jar;
import com.minelittlepony.unicopia.block.ItemJarBlock.FluidJarContents;
import com.minelittlepony.unicopia.block.ItemJarBlock.JarContents;
import com.minelittlepony.unicopia.block.ItemJarBlock.TileData;
import com.minelittlepony.unicopia.util.FluidHelper;
import net.fabricmc.fabric.api.transfer.v1.fluid.FluidConstants;
import net.fabricmc.fabric.api.transfer.v1.fluid.FluidVariant;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.util.Hand;
import net.minecraft.util.TypedActionResult;
public record FluidOnlyJarContents (
TileData tile,
long amount,
FluidVariant fluid
) implements FluidJarContents {
public FluidOnlyJarContents(TileData tile, NbtCompound compound) {
this(tile, compound.getLong("amount"), FluidVariant.fromNbt(compound.getCompound("fluid")));
}
@Override
public TypedActionResult<JarContents> interact(PlayerEntity player, Hand hand) {
ItemStack stack = player.getStackInHand(hand);
if (stack.isOf(Items.BUCKET)) {
long remainder = FluidHelper.deposit(stack, player, hand, fluid, amount);
tile.markDirty();
fluid.getFluid().getBucketFillSound().ifPresent(sound -> player.playSound(sound, 1, 1));
if (remainder > 0) {
return TypedActionResult.success(new FluidOnlyJarContents(tile, remainder, fluid));
}
return TypedActionResult.success(new ItemsJarContents(tile));
}
return TypedActionResult.pass(this);
}
@Override
public void onDestroyed() {
if (amount >= FluidConstants.BUCKET) {
tile.getWorld().setBlockState(tile.getPos(), FluidHelper.getFullFluidState(fluid).getBlockState());
}
}
@Override
public NbtCompound toNBT(NbtCompound compound) {
compound.put("fluid", fluid.toNbt());
compound.putLong("amount", amount);
return compound;
}
}

View file

@ -0,0 +1,208 @@
package com.minelittlepony.unicopia.block.jar;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import com.minelittlepony.unicopia.USounds;
import com.minelittlepony.unicopia.block.ItemJarBlock.JarContents;
import com.minelittlepony.unicopia.block.ItemJarBlock.TileData;
import com.minelittlepony.unicopia.item.UItems;
import com.minelittlepony.unicopia.mixin.MixinEntityBucketItem;
import com.minelittlepony.unicopia.util.FluidHelper;
import com.minelittlepony.unicopia.util.NbtSerialisable;
import net.fabricmc.fabric.api.transfer.v1.fluid.FluidVariant;
import net.minecraft.block.Block;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.inventory.SidedInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.nbt.NbtElement;
import net.minecraft.util.Hand;
import net.minecraft.util.Pair;
import net.minecraft.util.TypedActionResult;
import net.minecraft.util.math.Direction;
public record ItemsJarContents (
TileData tile,
List<ItemStack> stacks
) implements JarContents, SidedInventory {
private static final int[] SLOTS = IntStream.range(0, 16).toArray();
public ItemsJarContents(TileData tile) {
this(tile, new ArrayList<>());
}
public ItemsJarContents(TileData tile, NbtCompound compound) {
this(tile, NbtSerialisable.ITEM_STACK.readAll(compound.getList("items", NbtElement.COMPOUND_TYPE))
.limit(15)
.collect(Collectors.toList()));
}
@Override
public TypedActionResult<JarContents> interact(PlayerEntity player, Hand hand) {
ItemStack handStack = player.getStackInHand(hand);
if (handStack.isEmpty()) {
if (stacks.isEmpty()) {
return TypedActionResult.fail(this);
}
Block.dropStack(tile.getWorld(), tile.getPos(), stacks.remove(0));
markDirty();
return TypedActionResult.success(this);
}
if (stacks.isEmpty()) {
if (handStack.getItem() instanceof MixinEntityBucketItem bucket) {
consumeAndSwap(player, hand, Items.BUCKET.getDefaultStack());
player.playSound(bucket.getEmptyingSound(), 1, 1);
markDirty();
return TypedActionResult.success(new EntityJarContents(tile, bucket.getEntityType()));
}
Pair<Long, FluidVariant> fluid = FluidHelper.extract(handStack, player, hand).orElse(null);
if (fluid != null) {
fluid.getRight().getFluid().getBucketFillSound().ifPresent(sound -> player.playSound(sound, 1, 1));
markDirty();
return TypedActionResult.success(new FluidOnlyJarContents(tile, fluid.getLeft(), fluid.getRight()));
}
if (handStack.isOf(Items.MILK_BUCKET)) {
consumeAndSwap(player, hand, handStack.getRecipeRemainder());
player.playSound(USounds.Vanilla.ITEM_BUCKET_EMPTY, 1, 1);
markDirty();
return TypedActionResult.success(new FakeFluidJarContents(tile, "milk", 0xFFFFFFFF, Items.BUCKET, Items.MILK_BUCKET));
}
if (handStack.isOf(Items.POWDER_SNOW_BUCKET)) {
consumeAndSwap(player, hand, Items.BUCKET.getDefaultStack());
player.playSound(USounds.Vanilla.ITEM_BUCKET_EMPTY_POWDER_SNOW, 1, 1);
markDirty();
return TypedActionResult.success(new FakeFluidJarContents(tile, "powder_snow", 0xFFFFFFFF, Items.BUCKET, Items.POWDER_SNOW_BUCKET));
}
if (handStack.isOf(UItems.LOVE_BUCKET)) {
consumeAndSwap(player, hand, handStack.getRecipeRemainder());
player.playSound(USounds.Vanilla.ITEM_BUCKET_EMPTY, 1, 1);
markDirty();
return TypedActionResult.success(new FakeFluidJarContents(tile, "love", 0xFF3030, Items.BUCKET, UItems.LOVE_BUCKET));
}
if (handStack.isOf(UItems.JUICE)) {
consumeAndSwap(player, hand, handStack.getRecipeRemainder());
player.playSound(USounds.Vanilla.ITEM_BUCKET_EMPTY, 1, 1);
markDirty();
return TypedActionResult.success(new FakeFluidJarContents(tile, "apple_juice", 0x30FF30, Items.GLASS_BOTTLE, UItems.JUICE));
}
}
if (stacks.size() >= size()) {
return TypedActionResult.fail(this);
}
stacks.add(player.isCreative() ? handStack.copyWithCount(1) : handStack.split(1));
markDirty();
return TypedActionResult.success(this);
}
@Override
public void onDestroyed() {
stacks.forEach(stack -> Block.dropStack(tile.getWorld(), tile.getPos(), stack));
}
@Override
public int size() {
return 15;
}
@Override
public boolean isEmpty() {
return stacks.isEmpty();
}
@Override
public ItemStack getStack(int slot) {
return slot < 0 || slot >= stacks.size() ? ItemStack.EMPTY : stacks.get(slot);
}
@Override
public ItemStack removeStack(int slot, int amount) {
if (slot < 0 || slot >= stacks.size()) {
return ItemStack.EMPTY;
}
try {
ItemStack stack = stacks.get(slot);
ItemStack removed = stack.split(1);
if (stack.isEmpty()) {
stacks.remove(slot);
}
return removed;
} finally {
markDirty();
}
}
@Override
public ItemStack removeStack(int slot) {
if (slot < 0 || slot >= stacks.size()) {
return ItemStack.EMPTY;
}
try {
return stacks.remove(slot);
} finally {
markDirty();
}
}
@Override
public void setStack(int slot, ItemStack stack) {
if (slot >= stacks.size()) {
stacks.add(stack);
} else {
stacks.set(slot, stack);
}
markDirty();
}
@Override
public boolean canPlayerUse(PlayerEntity player) {
return false;
}
@Override
public void clear() {
stacks.clear();
markDirty();
}
@Override
public int[] getAvailableSlots(Direction side) {
return SLOTS;
}
@Override
public boolean canInsert(int slot, ItemStack stack, Direction dir) {
return slot >= 0 && slot < size() && slot >= stacks.size();
}
@Override
public boolean canExtract(int slot, ItemStack stack, Direction dir) {
return slot >= 0 && slot < size() && slot < stacks.size();
}
@Override
public NbtCompound toNBT(NbtCompound compound) {
compound.put("items", NbtSerialisable.ITEM_STACK.writeAll(stacks));
return compound;
}
@Override
public void markDirty() {
tile.markDirty();
}
}

View file

@ -7,7 +7,7 @@ import com.minelittlepony.unicopia.ability.magic.spell.crafting.SpellbookRecipe;
import com.minelittlepony.unicopia.client.gui.DrawableUtil;
import com.minelittlepony.unicopia.client.gui.MagicText;
import com.minelittlepony.unicopia.container.SpellbookState;
import com.minelittlepony.unicopia.item.URecipes;
import com.minelittlepony.unicopia.recipe.URecipes;
import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.client.gui.DrawContext;

View file

@ -52,7 +52,7 @@ public class PlayerPoser {
float pitchChange = -0.5F;
float yawChange = 0.8F;
if (player.getStackInHand(rightHand).isIn(UTags.POLEARMS) && (!ponyRace.isEquine() || model.rightArm.pitch != 0)) {
if (player.getStackInHand(rightHand).isIn(UTags.Items.POLEARMS) && (!ponyRace.isEquine() || model.rightArm.pitch != 0)) {
model.rightArm.pitch += pitchChange;
model.rightArm.yaw += yawChange;
if (player.handSwingTicks > 0 && rightHand == Hand.MAIN_HAND) {
@ -61,7 +61,7 @@ public class PlayerPoser {
}
}
if (player.getStackInHand(leftHand).isIn(UTags.POLEARMS) && (!ponyRace.isEquine() || model.leftArm.pitch != 0)) {
if (player.getStackInHand(leftHand).isIn(UTags.Items.POLEARMS) && (!ponyRace.isEquine() || model.leftArm.pitch != 0)) {
model.leftArm.pitch += pitchChange;
model.leftArm.yaw -= yawChange;
if (player.handSwingTicks > 0 && leftHand == Hand.MAIN_HAND) {

View file

@ -12,7 +12,8 @@ import net.minecraft.client.util.math.MatrixStack;
public class RenderUtil {
public static final Vector4f TEMP_VECTOR = new Vector4f();
private static final Vector4f TEMP_UV_VECTOR = new Vector4f();
public static final Vector4f TEMP_UV_VECTOR = new Vector4f();
public static final Vector3f TEMP_NORMAL_VECTOR = new Vector3f();
public static final Vertex[] UNIT_FACE = new Vertex[] {
new Vertex(0, 0, 0, 1, 1),
new Vertex(0, 1, 0, 1, 0),
@ -26,6 +27,9 @@ public class RenderUtil {
new Vertex(0, 0, 0, 0, 1)
};
public static void renderFace(MatrixStack matrices, Tessellator te, BufferBuilder buffer, float r, float g, float b, float a, int light) {
renderFace(matrices, te, buffer, r, g, b, a, light, 1, 1);
}

View file

@ -1,29 +1,82 @@
package com.minelittlepony.unicopia.client.render.entity;
import java.util.List;
import java.util.Arrays;
import org.jetbrains.annotations.Nullable;
import com.minelittlepony.common.util.Color;
import com.minelittlepony.unicopia.block.ItemJarBlock;
import com.minelittlepony.unicopia.block.ItemJarBlock.FluidJarContents;
import com.minelittlepony.unicopia.block.jar.ItemsJarContents;
import com.minelittlepony.unicopia.block.jar.FakeFluidJarContents;
import com.minelittlepony.unicopia.block.jar.EntityJarContents;
import com.minelittlepony.unicopia.client.render.model.CubeModel;
import com.minelittlepony.unicopia.util.FluidHelper;
import com.minelittlepony.unicopia.util.PosHelper;
import net.fabricmc.fabric.api.client.render.fluid.v1.FluidRenderHandler;
import net.fabricmc.fabric.api.client.render.fluid.v1.FluidRenderHandlerRegistry;
import net.fabricmc.fabric.api.transfer.v1.fluid.FluidConstants;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.RenderLayer;
import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.render.block.entity.BlockEntityRenderer;
import net.minecraft.client.render.block.entity.BlockEntityRendererFactory;
import net.minecraft.client.render.entity.EntityRenderDispatcher;
import net.minecraft.client.render.item.ItemRenderer;
import net.minecraft.client.render.model.json.ModelTransformationMode;
import net.minecraft.client.texture.Sprite;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.command.argument.EntityAnchorArgumentType.EntityAnchor;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.fluid.Fluid;
import net.minecraft.fluid.FluidState;
import net.minecraft.fluid.Fluids;
import net.minecraft.item.ItemStack;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.RotationAxis;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.random.Random;
import net.minecraft.world.World;
public class ItemJarBlockEntityRenderer implements BlockEntityRenderer<ItemJarBlock.TileData> {
private static final Direction[] GLASS_SIDES = Arrays.stream(PosHelper.ALL).filter(i -> i != Direction.UP).toArray(Direction[]::new);
private final ItemRenderer itemRenderer;
private final EntityRenderDispatcher dispatcher;
public ItemJarBlockEntityRenderer(BlockEntityRendererFactory.Context ctx) {
itemRenderer = ctx.getItemRenderer();
dispatcher = ctx.getEntityRenderDispatcher();
}
@Override
public void render(ItemJarBlock.TileData entity, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertices, int light, int overlay) {
public void render(ItemJarBlock.TileData data, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertices, int light, int overlay) {
List<ItemStack> stacks = entity.getStacks();
ItemsJarContents items = data.getItems();
if (items != null) {
renderItemStacks(data, items, tickDelta, matrices, vertices, light, overlay);
}
EntityJarContents entity = data.getEntity();
if (entity != null) {
renderEntity(data, entity, tickDelta, matrices, vertices, light, overlay);
}
FluidJarContents fluid = data.getFluid();
if (fluid != null) {
renderFluid(data, fluid, tickDelta, matrices, vertices, light, overlay);
}
FakeFluidJarContents milk = data.getFakeFluid();
if (milk != null) {
renderFluid(data, Fluids.WATER.getDefaultState(), milk.color(), FluidConstants.BUCKET, tickDelta, matrices, vertices, light, overlay);
}
}
private void renderItemStacks(ItemJarBlock.TileData data, ItemsJarContents items, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertices, int light, int overlay) {
float itemScale = 0.35F;
matrices.push();
@ -31,19 +84,102 @@ public class ItemJarBlockEntityRenderer implements BlockEntityRenderer<ItemJarBl
matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(90));
matrices.scale(itemScale, itemScale, itemScale);
Random rng = Random.create(entity.getPos().asLong());
Random rng = Random.create(data.getPos().asLong());
float y = 0;
for (ItemStack stack : stacks) {
for (ItemStack stack : items.stacks()) {
matrices.push();
matrices.translate((rng.nextFloat() - 0.5F) * 0.5F, (rng.nextFloat() - 0.5F) * 0.8F, -0.05 + y);
matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees((rng.nextFloat() * 360) - 180));
matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees((rng.nextFloat() * 360) - 180));
y -= 0.1F;
MinecraftClient.getInstance().getItemRenderer().renderItem(stack, ModelTransformationMode.FIXED, light, overlay, matrices, vertices, entity.getWorld(), 0);
itemRenderer.renderItem(stack, ModelTransformationMode.FIXED, light, overlay, matrices, vertices, data.getWorld(), 0);
matrices.pop();
}
matrices.pop();
}
private void renderEntity(ItemJarBlock.TileData data, EntityJarContents entity, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertices, int light, int overlay) {
Entity e = entity.entity().get();
if (e != null) {
PlayerEntity player = MinecraftClient.getInstance().player;
int age = player == null ? 0 : player.age;
float fullTick = age + tickDelta;
float size = Math.max(e.getWidth(), e.getHeight());
float desiredSize = 0.25F;
float scale = desiredSize / size;
float eyePos = (e.getEyeHeight(e.getPose())) * scale;
float yaw = 0;
if (player != null) {
Vec3d center = data.getPos().toCenterPos();
Vec3d observerPos = MinecraftClient.getInstance().gameRenderer.getCamera().getPos();
e.setPosition(center);
e.lookAt(EntityAnchor.FEET, observerPos);
}
matrices.push();
matrices.translate(0.5, 0.48 + MathHelper.sin(fullTick / 19F) * 0.02F - eyePos, 0.5);
matrices.scale(scale, scale, scale);
matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(10 * MathHelper.sin(fullTick / 19F)));
dispatcher.render(e, 0, 0, 0, yaw * MathHelper.RADIANS_PER_DEGREE, tickDelta, matrices, vertices, light);
matrices.pop();
}
}
private void renderFluid(ItemJarBlock.TileData data, FluidJarContents fluid, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertices, int light, int overlay) {
FluidState state = FluidHelper.getFullFluidState(fluid.fluid());
int color = getFluidColor(data.getWorld(), data.getPos(), state);
renderFluid(data, state, color, fluid.amount(), tickDelta, matrices, vertices, light, overlay);
}
private void renderFluid(ItemJarBlock.TileData data, FluidState state, int color, long amount, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertices, int light, int overlay) {
Sprite[] sprite = getFluidSprite(data.getWorld(), data.getPos(), state);
matrices.push();
Sprite topSprite = sprite[0];
float height = 0.6F * (amount / (float)FluidConstants.BUCKET);
boolean opaque = Color.a(color) >= 1;
CubeModel.render(
matrices,
vertices.getBuffer(opaque ? RenderLayer.getEntitySolid(topSprite.getAtlasId()) : RenderLayer.getEntityTranslucent(topSprite.getAtlasId())),
topSprite.getMinU(), topSprite.getMinV(),
topSprite.getMaxU(), topSprite.getMaxV(),
0.28F, 0.01F, 0.28F,
0.73F, 0.01F + height, 0.73F,
color,
light, overlay, Direction.UP
);
Sprite sideSprite = sprite[sprite.length - 1];
CubeModel.render(
matrices,
vertices.getBuffer(opaque ? RenderLayer.getEntitySolid(sideSprite.getAtlasId()) : RenderLayer.getEntityTranslucent(sideSprite.getAtlasId())),
sideSprite.getMinU(), sideSprite.getMinV(),
sideSprite.getMaxU(), sideSprite.getMaxV(),
0.28F, 0.01F, 0.28F,
0.73F, 0.01F + height, 0.73F,
color,
light, overlay, GLASS_SIDES
);
matrices.pop();
}
private int getFluidColor(World world, BlockPos pos, FluidState state) {
return getFluidHandler(state.getFluid()).getFluidColor(world, pos, state);
}
private Sprite[] getFluidSprite(@Nullable World world, BlockPos pos, FluidState state) {
return getFluidHandler(state.getFluid()).getFluidSprites(world, pos, state);
}
private FluidRenderHandler getFluidHandler(Fluid fluid) {
FluidRenderHandler handler = FluidRenderHandlerRegistry.INSTANCE.get(fluid);
if (handler == null) {
return FluidRenderHandlerRegistry.INSTANCE.get(Fluids.WATER);
}
return handler;
}
}

View file

@ -0,0 +1,77 @@
package com.minelittlepony.unicopia.client.render.model;
import org.joml.Matrix3f;
import org.joml.Matrix4f;
import org.joml.Vector2f;
import org.joml.Vector3f;
import org.joml.Vector4f;
import com.minelittlepony.common.util.Color;
import com.minelittlepony.unicopia.client.render.RenderUtil;
import com.minelittlepony.unicopia.client.render.RenderUtil.Vertex;
import net.minecraft.client.render.VertexConsumer;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.util.math.Direction;
public class CubeModel {
private static final Vector2f TEMP_UV_VECTOR = new Vector2f();
private static final Vertex[][] CUBE_VERTICES = {
new Vertex[] {
new Vertex(0, 0, 0, 0, 0),
new Vertex(1, 0, 0, 1, 0),
new Vertex(1, 0, 1, 1, 1),
new Vertex(0, 0, 1, 0, 1)
},
new Vertex[] {
new Vertex(0, 1, 0, 0, 0),
new Vertex(0, 1, 1, 0, 1),
new Vertex(1, 1, 1, 1, 1),
new Vertex(1, 1, 0, 1, 0)
},
new Vertex[] {
new Vertex(0, 0, 0, 0, 0),
new Vertex(0, 1, 0, 0, 1),
new Vertex(1, 1, 0, 1, 1),
new Vertex(1, 0, 0, 1, 0)
},
new Vertex[] {
new Vertex(0, 0, 1, 0, 0),
new Vertex(1, 0, 1, 1, 0),
new Vertex(1, 1, 1, 1, 1),
new Vertex(0, 1, 1, 0, 1)
},
new Vertex[] {
new Vertex(0, 0, 0, 0, 0),
new Vertex(0, 0, 1, 1, 0),
new Vertex(0, 1, 1, 1, 1),
new Vertex(0, 1, 0, 0, 1)
},
new Vertex[] {
new Vertex(1, 0, 0, 0, 0),
new Vertex(1, 1, 0, 1, 0),
new Vertex(1, 1, 1, 1, 1),
new Vertex(1, 0, 1, 0, 1)
}
};
public static void render(MatrixStack matrices, VertexConsumer buffer,
float u0, float v0, float u1, float v1,
float x0, float y0, float z0, float x1, float y1, float z1,
int color, int light, int overlay,
Direction... directions) {
float r = Color.r(color), g = Color.g(color), b = Color.b(color);
float du = u1 - u0, dv = v1 - v0;
float dx = x1 - x0, dy = y1 - y0, dz = z1 - z0;
Matrix4f position = matrices.peek().getPositionMatrix();
Matrix3f normal = matrices.peek().getNormalMatrix();
for (Direction direction : directions) {
for (Vertex vertex : CUBE_VERTICES[direction.ordinal()]) {
Vector4f pos = position.transform(RenderUtil.TEMP_VECTOR.set(vertex.position(), 1).mul(dx, dy, dz, 1).add(x0, y0, z0, 0));
Vector2f tex = TEMP_UV_VECTOR.set(vertex.texture().x, vertex.texture().y).mul(du, dv).add(u0, v0);
Vector3f norm = normal.transform(RenderUtil.TEMP_NORMAL_VECTOR.set(direction.getOffsetX(), direction.getOffsetY(), direction.getOffsetZ()));
buffer.vertex(pos.x, pos.y, pos.z, r, g, b, 1, tex.x, tex.y, overlay, light, norm.x, norm.y, norm.z);
}
}
}
}

View file

@ -15,10 +15,10 @@ import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait;
import com.minelittlepony.unicopia.block.UBlocks;
import com.minelittlepony.unicopia.block.state.Schematic;
import com.minelittlepony.unicopia.item.EnchantableItem;
import com.minelittlepony.unicopia.item.TransformCropsRecipe;
import com.minelittlepony.unicopia.item.UItems;
import com.minelittlepony.unicopia.item.URecipes;
import com.minelittlepony.unicopia.item.group.MultiItem;
import com.minelittlepony.unicopia.recipe.TransformCropsRecipe;
import com.minelittlepony.unicopia.recipe.URecipes;
import dev.emi.emi.api.EmiPlugin;
import dev.emi.emi.api.EmiRegistry;

View file

@ -1,7 +1,7 @@
package com.minelittlepony.unicopia.container;
import com.minelittlepony.unicopia.block.UBlocks;
import com.minelittlepony.unicopia.item.URecipes;
import com.minelittlepony.unicopia.recipe.URecipes;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory;

View file

@ -10,7 +10,7 @@ import com.minelittlepony.unicopia.compat.trinkets.TrinketsDelegate;
import com.minelittlepony.unicopia.container.inventory.*;
import com.minelittlepony.unicopia.entity.player.Pony;
import com.minelittlepony.unicopia.item.UItems;
import com.minelittlepony.unicopia.item.URecipes;
import com.minelittlepony.unicopia.recipe.URecipes;
import com.mojang.datafixers.util.Pair;
import net.minecraft.enchantment.EnchantmentHelper;

View file

@ -22,6 +22,10 @@ public class DataCollector {
this.resolver = resolver;
}
public boolean isDefined(Identifier id) {
return values.containsKey(id);
}
public BiConsumer<Identifier, Supplier<JsonElement>> prime() {
values.clear();
return (Identifier id, Supplier<JsonElement> value) ->

View file

@ -3,39 +3,62 @@ package com.minelittlepony.unicopia.datagen;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import com.minelittlepony.unicopia.block.EdibleBlock;
import com.minelittlepony.unicopia.datagen.providers.DietsProvider;
import com.minelittlepony.unicopia.datagen.providers.SeasonsGrowthRatesProvider;
import com.minelittlepony.unicopia.datagen.providers.UAdvancementsProvider;
import com.minelittlepony.unicopia.datagen.providers.UBlockTagProvider;
import com.minelittlepony.unicopia.datagen.providers.UItemTagProvider;
import com.minelittlepony.unicopia.datagen.providers.UModelProvider;
import com.minelittlepony.unicopia.datagen.providers.loot.UBlockAdditionsLootTableProvider;
import com.minelittlepony.unicopia.datagen.providers.loot.UBlockLootTableProvider;
import com.minelittlepony.unicopia.datagen.providers.loot.UChestAdditionsLootTableProvider;
import com.minelittlepony.unicopia.datagen.providers.loot.UChestLootTableProvider;
import com.minelittlepony.unicopia.datagen.providers.loot.UEntityLootTableProvider;
import com.minelittlepony.unicopia.datagen.providers.recipe.URecipeProvider;
import com.minelittlepony.unicopia.datagen.providers.tag.UBlockTagProvider;
import com.minelittlepony.unicopia.datagen.providers.tag.UDamageTypeProvider;
import com.minelittlepony.unicopia.datagen.providers.tag.UItemTagProvider;
import com.minelittlepony.unicopia.entity.damage.UDamageTypes;
import com.minelittlepony.unicopia.server.world.UWorldGen;
import net.fabricmc.fabric.api.datagen.v1.DataGeneratorEntrypoint;
import net.fabricmc.fabric.api.datagen.v1.FabricDataGenerator;
import net.minecraft.block.Block;
import net.minecraft.item.Item;
import net.minecraft.registry.Registries;
import net.minecraft.registry.Registry;
import net.minecraft.registry.RegistryBuilder;
import net.minecraft.registry.RegistryEntryLookup;
import net.minecraft.registry.RegistryKeys;
import net.minecraft.util.Identifier;
import net.minecraft.world.biome.OverworldBiomeCreator;
import net.minecraft.world.gen.carver.ConfiguredCarver;
import net.minecraft.world.gen.feature.PlacedFeature;
public class Datagen implements DataGeneratorEntrypoint {
public static final Logger LOGGER = LogManager.getLogger();
public static Block getOrCreateBaleBlock(Identifier id) {
return Registries.BLOCK.getOrEmpty(id).orElseGet(() -> {
return Registry.register(Registries.BLOCK, id, new EdibleBlock(id, id, false));
});
}
public static Item getOrCreateItem(Identifier id) {
return Registries.ITEM.getOrEmpty(id).orElseGet(() -> {
return Registry.register(Registries.ITEM, id, new Item(new Item.Settings()));
});
}
@Override
public void onInitializeDataGenerator(FabricDataGenerator fabricDataGenerator) {
final FabricDataGenerator.Pack pack = fabricDataGenerator.createPack();
UBlockTagProvider blockTags = pack.addProvider(UBlockTagProvider::new);
pack.addProvider((output, registries) -> new UItemTagProvider(output, registries, blockTags));
final var pack = fabricDataGenerator.createPack();
final var blockTags = pack.addProvider(UBlockTagProvider::new);
final var itemTags = pack.addProvider((output, registries) -> new UItemTagProvider(output, registries, blockTags));
pack.addProvider((output, registries) -> new DietsProvider(output, itemTags));
pack.addProvider(UDamageTypeProvider::new);
pack.addProvider(UModelProvider::new);
pack.addProvider(URecipeProvider::new);
pack.addProvider(UBlockLootTableProvider::new);
pack.addProvider(UEntityLootTableProvider::new);
pack.addProvider(UChestLootTableProvider::new);
pack.addProvider(UBlockAdditionsLootTableProvider::new);
pack.addProvider(UChestAdditionsLootTableProvider::new);
pack.addProvider(SeasonsGrowthRatesProvider::new);
@ -45,9 +68,10 @@ public class Datagen implements DataGeneratorEntrypoint {
@Override
public void buildRegistry(RegistryBuilder builder) {
builder.addRegistry(RegistryKeys.BIOME, registerable -> {
RegistryEntryLookup<PlacedFeature> placedFeatureLookup = registerable.getRegistryLookup(RegistryKeys.PLACED_FEATURE);
RegistryEntryLookup<ConfiguredCarver<?>> carverLookup = registerable.getRegistryLookup(RegistryKeys.CONFIGURED_CARVER);
final var placedFeatureLookup = registerable.getRegistryLookup(RegistryKeys.PLACED_FEATURE);
final var carverLookup = registerable.getRegistryLookup(RegistryKeys.CONFIGURED_CARVER);
registerable.register(UWorldGen.SWEET_APPLE_ORCHARD, OverworldBiomeCreator.createNormalForest(placedFeatureLookup, carverLookup, false, false, false));
});
builder.addRegistry(RegistryKeys.DAMAGE_TYPE, UDamageTypes.REGISTRY);
}
}

View file

@ -0,0 +1,275 @@
package com.minelittlepony.unicopia.datagen.providers;
import java.util.List;
import java.util.Optional;
import java.util.function.BiConsumer;
import com.minelittlepony.unicopia.Race;
import com.minelittlepony.unicopia.Unicopia;
import com.minelittlepony.unicopia.diet.DietProfile;
import com.minelittlepony.unicopia.diet.DietProfile.Multiplier;
import com.minelittlepony.unicopia.diet.FoodGroupEffects;
import com.minelittlepony.unicopia.diet.affliction.ClearLoveSicknessAffliction;
import com.minelittlepony.unicopia.diet.affliction.CompoundAffliction;
import com.minelittlepony.unicopia.diet.affliction.HealingAffliction;
import com.minelittlepony.unicopia.diet.affliction.LoseHungerAffliction;
import com.minelittlepony.unicopia.diet.affliction.Range;
import com.minelittlepony.unicopia.diet.affliction.StatusEffectAffliction;
import com.minelittlepony.unicopia.entity.effect.UEffects;
import com.minelittlepony.unicopia.item.UFoodComponents;
import net.minecraft.entity.effect.StatusEffects;
import net.minecraft.item.FoodComponents;
public class DietProfileGenerator {
public void generate(BiConsumer<Race, DietProfile> exporter) {
// Pinecones are for everypony
var pineconeMultiplier = new Multiplier.Builder().tag(Unicopia.id("pinecone")).hunger(0.9F).saturation(0.9F).build();
var bakedGoodPreference = new Multiplier.Builder().tag(Unicopia.id("baked_goods")).build();
var bakedGoodExtremePreference = new Multiplier.Builder().tag(Unicopia.id("baked_goods")).hunger(1.2F).saturation(2).build();
var bakedGoodNonPreference = new Multiplier.Builder().tag(Unicopia.id("baked_goods")).hunger(0.4F).saturation(0.2F).build();
var properMeatStandards = new Multiplier.Builder().tag(Unicopia.id("love"))
.tag(Unicopia.id("meat/raw")).tag(Unicopia.id("insect/raw")).tag(Unicopia.id("fish/raw"))
.tag(Unicopia.id("meat/rotten")).tag(Unicopia.id("insect/rotten")).tag(Unicopia.id("fish/rotten"))
.hunger(0).saturation(0).build();
var avianMeatStandards = new Multiplier.Builder().tag(Unicopia.id("love"))
.tag(Unicopia.id("meat/raw")).tag(Unicopia.id("insect/raw"))
.tag(Unicopia.id("meat/rotten")).tag(Unicopia.id("insect/rotten"))
.hunger(0).saturation(0).build();
var loveSicknessEffects = CompoundAffliction.of(
new StatusEffectAffliction(UEffects.FOOD_POISONING, Range.of(100), Range.of(2), 95),
new StatusEffectAffliction(StatusEffects.WEAKNESS, Range.of(200), Range.of(1), 0),
new LoseHungerAffliction(0.5F));
var seaFoodExclusions = new Multiplier.Builder()
.tag(Unicopia.id("sea_vegetable/raw")).tag(Unicopia.id("sea_vegetable/cooked"))
.tag(Unicopia.id("shells")).tag(Unicopia.id("special_shells"))
.hunger(0).saturation(0).build();
exporter.accept(Race.HUMAN, new DietProfile(1, 0, List.of(), List.of(
new FoodGroupEffects.Builder()
.tag(Unicopia.id("fish/cooked")).tag(Unicopia.id("fish/raw")).tag(Unicopia.id("fish/rotten"))
.tag(Unicopia.id("meat/cooked")).tag(Unicopia.id("meat/raw")).tag(Unicopia.id("meat/rotten"))
.tag(Unicopia.id("sea_vegetable/cooked")).tag(Unicopia.id("sea_vegetable/raw"))
.tag(Unicopia.id("pinecone"))
.build()
), Optional.empty()));
// Alicorns are a mashup of unicorn, pegasus, and earth pony eating habits
exporter.accept(Race.ALICORN, new DietProfile(0.9F, 1, List.of(
// Pastries are their passion
bakedGoodExtremePreference, pineconeMultiplier, avianMeatStandards, seaFoodExclusions,
// They have a more of a sweet tooth than earth ponies
new Multiplier.Builder().tag(Unicopia.id("desserts")).hunger(2.5F).saturation(1.7F).build(),
new Multiplier.Builder().tag(Unicopia.id("candy")).tag(Unicopia.id("rocks")).hunger(1.5F).saturation(1.3F).build(),
// Cannot eat love, or raw/rotten meats and fish
// Can eat raw and rotten fish but still prefers if they are cooked
new Multiplier.Builder().tag(Unicopia.id("fish/cooked")).hunger(1.5F).saturation(1.5F).build(),
new Multiplier.Builder().tag(Unicopia.id("meat/cooked")).hunger(0.25F).saturation(0.16F).build(),
new Multiplier.Builder().tag(Unicopia.id("insect/cooked")).hunger(0.1F).saturation(0.7F).build(),
new Multiplier.Builder().tag(Unicopia.id("fish/raw")).hunger(0.5F).saturation(0.8F).build(),
new Multiplier.Builder().tag(Unicopia.id("fish/rotten")).hunger(0.25F).saturation(0.5F).build()
), List.of(
// Can safely eat fresh and cooked fish with no ill effects
new FoodGroupEffects.Builder().tag(Unicopia.id("fish/cooked")).tag(Unicopia.id("fish/raw")).build(),
// Is less affected when eating rotten fish
new FoodGroupEffects.Builder().tag(Unicopia.id("fish/rotten")).ailment(new StatusEffectAffliction(UEffects.FOOD_POISONING, Range.of(50), Range.of(2), 95)).build()
), Optional.empty()));
// Unicorns have a general even preference of foods
exporter.accept(Race.UNICORN, new DietProfile(1.1F, 1, List.of(
bakedGoodPreference, pineconeMultiplier, seaFoodExclusions,
new Multiplier.Builder().tag(Unicopia.id("love")).hunger(0).saturation(0).build(),
// Improved benefits from cooking their food
new Multiplier.Builder().tag(Unicopia.id("fish/cooked")).hunger(0.3F).saturation(0.2F).build(),
new Multiplier.Builder().tag(Unicopia.id("meat/cooked")).hunger(0.4F).saturation(0.4F).build(),
new Multiplier.Builder().tag(Unicopia.id("insect/cooked")).hunger(0.1F).saturation(0.1F).build(),
new Multiplier.Builder().tag(Unicopia.id("fish/raw")).hunger(0.25F).saturation(0.1F).build(),
new Multiplier.Builder().tag(Unicopia.id("meat/raw")).hunger(0.3F).saturation(0.1F).build(),
new Multiplier.Builder().tag(Unicopia.id("insect/raw")).hunger(0.15F).saturation(0.1F).build(),
// Can still eat raw and rotten but at a reduced yield
new Multiplier.Builder().tag(Unicopia.id("fish/rotten")).hunger(0.1F).saturation(0.1F).build(),
new Multiplier.Builder().tag(Unicopia.id("meat/rotten")).hunger(0.1F).saturation(0.1F).build(),
new Multiplier.Builder().tag(Unicopia.id("insect/rotten")).hunger(0).saturation(0.1F).build()
), List.of(), Optional.empty()));
// Bats prefer cooked foods over raw, and meat/insects over fish
exporter.accept(Race.BAT, new DietProfile(0.7F, 0.9F, List.of(
pineconeMultiplier, seaFoodExclusions,
// Doesn't like baked goods but really likes meats, fish, and insects
bakedGoodNonPreference,
new Multiplier.Builder().tag(Unicopia.id("fish/cooked")).hunger(0.75F).saturation(0.75F).build(),
new Multiplier.Builder().tag(Unicopia.id("meat/cooked")).hunger(1.15F).saturation(1.16F).build(),
new Multiplier.Builder().tag(Unicopia.id("insect/cooked")).hunger(1.75F).saturation(1.74F).build(),
new Multiplier.Builder().tag(Unicopia.id("fish/raw")).hunger(0.5F).saturation(0.6F).build(),
new Multiplier.Builder().tag(Unicopia.id("meat/raw")).hunger(0.25F).saturation(0.25F).build(),
new Multiplier.Builder().tag(Unicopia.id("insect/raw")).hunger(1).saturation(1).build(),
new Multiplier.Builder().tag(Unicopia.id("fish/rotten")).hunger(0.24F).saturation(0.25F).build(),
new Multiplier.Builder().tag(Unicopia.id("meat/rotten")).hunger(0.2F).saturation(0.2F).build(),
new Multiplier.Builder().tag(Unicopia.id("insect/rotten")).hunger(0.9F).saturation(0.9F).build()
), List.of(
// Gets food poisoning from eating rotten and raw meat
new FoodGroupEffects.Builder().tag(Unicopia.id("fish/rotten")).tag(Unicopia.id("meat/raw")).tag(Unicopia.id("meat/rotten")).ailment(new StatusEffectAffliction(UEffects.FOOD_POISONING, Range.of(100), Range.of(2), 5)).build(),
new FoodGroupEffects.Builder().tag(Unicopia.id("insect/rotten")).ailment(new StatusEffectAffliction(UEffects.FOOD_POISONING, Range.of(50), Range.of(1), 15)).build(),
// Can eat cooked meat and insects without negative effects
new FoodGroupEffects.Builder().tag(Unicopia.id("insect/cooked")).tag(Unicopia.id("meat/cooked")).build(),
// Becomes hyper when eating mangoes
new FoodGroupEffects.Builder().tag(Unicopia.id("bat_ponys_delight")).ailment(CompoundAffliction.of(
new StatusEffectAffliction(StatusEffects.HEALTH_BOOST, Range.of(30, 60), Range.of(2, 6), 0),
new StatusEffectAffliction(StatusEffects.JUMP_BOOST, Range.of(30, 60), Range.of(1, 6), 0),
new StatusEffectAffliction(StatusEffects.REGENERATION, Range.of(3, 30), Range.of(3, 6), 0)
)).build()
), Optional.empty()));
// Much like Earth Ponies, Kirins must cook their meat before they eat it
exporter.accept(Race.KIRIN, new DietProfile(0.6F, 0.9F, List.of(
// Cannot eat love, or raw/rotten meats and fish
bakedGoodPreference, properMeatStandards, pineconeMultiplier, seaFoodExclusions,
new Multiplier.Builder().tag(Unicopia.id("fish/cooked")).hunger(0.75F).saturation(0.35F).build(),
new Multiplier.Builder().tag(Unicopia.id("meat/cooked")).hunger(1.5F).saturation(1.6F).build(),
new Multiplier.Builder().tag(Unicopia.id("insect/cooked")).hunger(0.25F).saturation(0.74F).build()
), List.of(
// can eat these without negative effects
new FoodGroupEffects.Builder().tag(Unicopia.id("insect/cooked")).tag(Unicopia.id("meat/cooked")).food(FoodComponents.COOKED_BEEF).build(),
new FoodGroupEffects.Builder().tag(Unicopia.id("foraging/blinding")).food(4, 0.2F).build(),
new FoodGroupEffects.Builder().tag(Unicopia.id("foraging/prickly")).food(0, 1.5F).build(),
new FoodGroupEffects.Builder().tag(Unicopia.id("foraging/severely_prickly")).food(2, 0.9F).build(),
new FoodGroupEffects.Builder().tag(Unicopia.id("foraging/strengthening")).food(4, 0.2F).ailment(new StatusEffectAffliction(StatusEffects.STRENGTH, Range.of(1300), Range.of(0), 0)).build(),
new FoodGroupEffects.Builder().tag(Unicopia.id("foraging/glowing")).food(1, 1.6F).ailment(new StatusEffectAffliction(StatusEffects.GLOWING, Range.of(30), Range.of(0), 30)).build()
), Optional.empty()));
// Earth Ponies are vegans. They get the most from foraging
exporter.accept(Race.EARTH, new DietProfile(0.7F, 1.2F, List.of(
// Pastries are their passion
// If they must eat meat, they have to cook it and not let it spoil.
bakedGoodExtremePreference, pineconeMultiplier, properMeatStandards, seaFoodExclusions,
// They have a sweet tooth
new Multiplier.Builder().tag(Unicopia.id("candy")).tag(Unicopia.id("desserts")).tag(Unicopia.id("rocks")).hunger(2.5F).saturation(1.7F).build(),
new Multiplier.Builder().tag(Unicopia.id("fish/cooked")).hunger(0.2F).saturation(0.3F).build(),
new Multiplier.Builder().tag(Unicopia.id("insect/cooked")).hunger(0.1F).saturation(0.1F).build(),
new Multiplier.Builder().tag(Unicopia.id("meat/cooked")).hunger(0.1F).saturation(0.1F).build()
), List.of(
// Candy and rocks gives them a massive saturation boost. Maybe too much?
new FoodGroupEffects.Builder().tag(Unicopia.id("candy")).tag(Unicopia.id("rocks")).food(UFoodComponents.builder(5, 12).alwaysEdible()).build(),
new FoodGroupEffects.Builder().tag(Unicopia.id("desserts")).food(UFoodComponents.builder(12, 32).snack().alwaysEdible()).build()
), Optional.empty()));
// Pegasi prefer fish over other food sources
exporter.accept(Race.PEGASUS, new DietProfile(0.9F, 1, List.of(
bakedGoodPreference, pineconeMultiplier, avianMeatStandards, seaFoodExclusions,
// Cannot eat love, or raw/rotten meat
// Can eat raw and rotten fish but still prefers if they are cooked
new Multiplier.Builder().tag(Unicopia.id("fish/cooked")).hunger(1.5F).saturation(1.5F).build(),
new Multiplier.Builder().tag(Unicopia.id("meat/cooked")).hunger(0.25F).saturation(0.16F).build(),
new Multiplier.Builder().tag(Unicopia.id("insect/cooked")).hunger(0.1F).saturation(0.7F).build(),
new Multiplier.Builder().tag(Unicopia.id("fish/raw")).hunger(0.5F).saturation(0.8F).build(),
new Multiplier.Builder().tag(Unicopia.id("fish/rotten")).hunger(0.25F).saturation(0.5F).build()
), List.of(
// Can safely eat fresh and cooked fish with no ill effects
new FoodGroupEffects.Builder().tag(Unicopia.id("fish/cooked")).tag(Unicopia.id("fish/raw")).build(),
// Is less affected when eating rotten fish
new FoodGroupEffects.Builder().tag(Unicopia.id("fish/rotten")).ailment(new StatusEffectAffliction(UEffects.FOOD_POISONING, Range.of(50), Range.of(2), 95)).build()
), Optional.empty()));
// Changelings like meat and fish but really prefer feasting on ponies' love directly from the tap
exporter.accept(Race.CHANGELING, new DietProfile(0.15F, 0.1F, List.of(
// Doesn't like baked goods but really likes meats, fish, and insects
bakedGoodNonPreference, pineconeMultiplier, seaFoodExclusions,
new Multiplier.Builder().tag(Unicopia.id("fish/cooked")).hunger(0.5F).saturation(1.2F).build(),
new Multiplier.Builder().tag(Unicopia.id("meat/cooked")).hunger(0.9F).saturation(1.2F).build(),
new Multiplier.Builder().tag(Unicopia.id("insect/cooked")).hunger(1.2F).saturation(1.3F).build(),
new Multiplier.Builder().tag(Unicopia.id("fish/raw")).hunger(0.15F).saturation(0.25F).build(),
new Multiplier.Builder().tag(Unicopia.id("meat/raw")).hunger(1.25F).saturation(1.25F).build(),
new Multiplier.Builder().tag(Unicopia.id("insect/raw")).hunger(1).saturation(1).build(),
new Multiplier.Builder().tag(Unicopia.id("fish/rotten")).hunger(0.24F).saturation(0.25F).build(),
new Multiplier.Builder().tag(Unicopia.id("meat/rotten")).hunger(0.2F).saturation(0.2F).build(),
new Multiplier.Builder().tag(Unicopia.id("insect/rotten")).hunger(0.9F).saturation(0.9F).build(),
new Multiplier.Builder().tag(Unicopia.id("love")).hunger(1).saturation(1.5F).build()
), List.of(
// Can eat fish, meat, insects, and love without negative effects
new FoodGroupEffects.Builder()
.tag(Unicopia.id("fish/cooked")).tag(Unicopia.id("meat/cooked")).tag(Unicopia.id("insect/cooked"))
.tag(Unicopia.id("fish/rotten")).tag(Unicopia.id("meat/rotten")).tag(Unicopia.id("insect/rotten"))
.tag(Unicopia.id("fish/raw")).tag(Unicopia.id("meat/raw")).tag(Unicopia.id("insect/raw"))
.tag(Unicopia.id("baked_goods")).tag(Unicopia.id("pinecone"))
.tag(Unicopia.id("love")).ailment(ClearLoveSicknessAffliction.INSTANCE).build(),
new FoodGroupEffects.Builder()
.tag(Unicopia.id("foraging/blinding")).tag(Unicopia.id("foraging/dangerous")).tag(Unicopia.id("foraging/edible_filling"))
.tag(Unicopia.id("foraging/edible")).tag(Unicopia.id("foraging/leafy_greens")).tag(Unicopia.id("foraging/nauseating"))
.tag(Unicopia.id("foraging/prickly")).tag(Unicopia.id("foraging/glowing")).tag(Unicopia.id("foraging/risky"))
.tag(Unicopia.id("foraging/severely_nauseating")).tag(Unicopia.id("foraging/severely_prickly"))
.tag(Unicopia.id("foraging/strengthening"))
.ailment(loveSicknessEffects)
.build()
), Optional.empty()));
// Hippogriffs like fish, nuts, and seeds
exporter.accept(Race.HIPPOGRIFF, new DietProfile(0.5F, 0.8F, List.of(
bakedGoodPreference, pineconeMultiplier, seaFoodExclusions,
new Multiplier.Builder().tag(Unicopia.id("love"))
.tag(Unicopia.id("insect/cooked")).tag(Unicopia.id("insect/raw")).tag(Unicopia.id("insect/rotten"))
.hunger(0).saturation(0).build(),
new Multiplier.Builder().tag(Unicopia.id("fish/cooked")).hunger(1.5F).saturation(1.2F).build(),
new Multiplier.Builder().tag(Unicopia.id("meat/cooked")).hunger(1.9F).saturation(1.2F).build(),
new Multiplier.Builder().tag(Unicopia.id("fish/raw")).hunger(0.85F).saturation(0.95F).build(),
new Multiplier.Builder().tag(Unicopia.id("meat/raw")).hunger(0.75F).saturation(0.75F).build(),
new Multiplier.Builder().tag(Unicopia.id("fish/rotten")).hunger(0.24F).saturation(0.25F).build(),
new Multiplier.Builder().tag(Unicopia.id("meat/rotten")).hunger(0.3F).saturation(0.5F).build(),
new Multiplier.Builder().tag(Unicopia.id("nuts_and_seeds")).hunger(1.4F).saturation(1.4F).build()
), List.of(
// Can eat fish and prickly foods without negative effect
new FoodGroupEffects.Builder()
.tag(Unicopia.id("fish/cooked")).tag(Unicopia.id("fish/raw")).tag(Unicopia.id("fish/rotten"))
.tag(Unicopia.id("foraging/prickly")).tag(Unicopia.id("foraging/severely_prickly"))
.build(),
// Gains more health from pinecones
new FoodGroupEffects.Builder().tag(Unicopia.id("pinecone")).ailment(new HealingAffliction(3)).build()
), Optional.empty()));
// Seaponies can eat seaweed, kelp, shells, and other undersea foods
exporter.accept(Race.SEAPONY, new DietProfile(0.5F, 0.8F, List.of(
new Multiplier.Builder().tag(Unicopia.id("fish/cooked")).hunger(1.5F).saturation(1.2F).build(),
new Multiplier.Builder().tag(Unicopia.id("fish/raw")).hunger(0.85F).saturation(0.95F).build(),
new Multiplier.Builder().tag(Unicopia.id("fish/rotten")).hunger(0.24F).saturation(0.25F).build(),
new Multiplier.Builder()
.tag(Unicopia.id("sea_vegetable/raw"))
.tag(Unicopia.id("sea_vegetable/cooked"))
.tag(Unicopia.id("shells")).tag(Unicopia.id("special_shells"))
.hunger(1).saturation(1).build()
), List.of(
// Can eat fish without negative effect
new FoodGroupEffects.Builder()
.tag(Unicopia.id("fish/cooked")).tag(Unicopia.id("fish/raw")).tag(Unicopia.id("fish/rotten"))
.build(),
// Gains more health from pinecones
new FoodGroupEffects.Builder().tag(Unicopia.id("pinecone")).ailment(new HealingAffliction(3)).build()
), Optional.empty()));
}
}

View file

@ -0,0 +1,83 @@
package com.minelittlepony.unicopia.datagen.providers;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
import com.google.gson.JsonObject;
import com.minelittlepony.unicopia.Race;
import com.minelittlepony.unicopia.datagen.DataCollector;
import com.minelittlepony.unicopia.diet.DietProfile;
import com.minelittlepony.unicopia.diet.FoodGroup;
import com.mojang.serialization.JsonOps;
import net.fabricmc.fabric.api.datagen.v1.FabricDataOutput;
import net.minecraft.data.DataOutput;
import net.minecraft.data.DataProvider;
import net.minecraft.data.DataWriter;
import net.minecraft.data.server.tag.TagProvider;
import net.minecraft.data.server.tag.TagProvider.TagLookup;
import net.minecraft.item.Item;
import net.minecraft.registry.RegistryKeys;
import net.minecraft.registry.tag.TagKey;
import net.minecraft.util.Identifier;
public class DietsProvider implements DataProvider {
private final DataCollector dietsCollector;
private final DataCollector categoriesCollector;
private final CompletableFuture<TagLookup<Item>> itemTagLookup;
public DietsProvider(FabricDataOutput output, TagProvider<Item> tagProvider) {
this.dietsCollector = new DataCollector(output.getResolver(DataOutput.OutputType.DATA_PACK, "diet/races"));
this.categoriesCollector = new DataCollector(output.getResolver(DataOutput.OutputType.DATA_PACK, "diet/food_groups"));
itemTagLookup = tagProvider.getTagLookupFuture();
}
@Override
public String getName() {
return "Diets";
}
@Override
public CompletableFuture<?> run(DataWriter writer) {
return itemTagLookup.thenCompose(tagLookup -> {
var diets = categoriesCollector.prime();
Map<Identifier, Set<Identifier>> keyToGroupId = new HashMap<>();
new FoodGroupsGenerator().generate((id, builder) -> {
var attributes = builder.build();
attributes.tags().forEach(key -> {
if (!tagLookup.contains(TagKey.of(RegistryKeys.ITEM, key.id()))) {
throw new IllegalArgumentException("Food group " + id + " references unknown item tag " + key.id());
}
keyToGroupId.computeIfAbsent(key.id(), i -> new HashSet<>()).add(id);
});
diets.accept(id, () -> FoodGroup.CODEC.encode(attributes, JsonOps.INSTANCE, new JsonObject()).result().get());
});
var profiles = dietsCollector.prime();
new DietProfileGenerator().generate((race, profile) -> {
Identifier id = Race.REGISTRY.getId(race);
StringBuilder issues = new StringBuilder();
profile.validate(issue -> {
issues.append(System.lineSeparator()).append(issue);
}, categoriesCollector::isDefined);
if (!issues.isEmpty()) {
throw new IllegalArgumentException("Diet profile " + id + " failed validation: " + issues.toString());
}
profiles.accept(id, () -> DietProfile.CODEC.encode(profile, JsonOps.INSTANCE, new JsonObject()).result().get());
});
keyToGroupId.forEach((tag, groups) -> {
if (groups.size() > 1) {
throw new IllegalArgumentException("Multiple groups referenced the same tag " + tag + " held by "
+ groups.stream().map(Identifier::toString).collect(Collectors.joining())
);
}
});
return CompletableFuture.allOf(categoriesCollector.upload(writer), dietsCollector.upload(writer));
});
}
}

View file

@ -0,0 +1,115 @@
package com.minelittlepony.unicopia.datagen.providers;
import java.util.List;
import java.util.function.BiConsumer;
import com.minelittlepony.unicopia.UConventionalTags;
import com.minelittlepony.unicopia.UTags;
import com.minelittlepony.unicopia.Unicopia;
import com.minelittlepony.unicopia.diet.FoodGroupEffects;
import com.minelittlepony.unicopia.diet.affliction.Affliction;
import com.minelittlepony.unicopia.diet.affliction.CompoundAffliction;
import com.minelittlepony.unicopia.diet.affliction.HealingAffliction;
import com.minelittlepony.unicopia.diet.affliction.LoseHungerAffliction;
import com.minelittlepony.unicopia.diet.affliction.Range;
import com.minelittlepony.unicopia.diet.affliction.StatusEffectAffliction;
import com.minelittlepony.unicopia.entity.effect.UEffects;
import com.minelittlepony.unicopia.item.UFoodComponents;
import net.minecraft.entity.effect.StatusEffects;
import net.minecraft.item.FoodComponent;
import net.minecraft.item.FoodComponents;
import net.minecraft.item.Item;
import net.minecraft.registry.tag.ItemTags;
import net.minecraft.registry.tag.TagKey;
import net.minecraft.util.Identifier;
public class FoodGroupsGenerator {
public void generate(BiConsumer<Identifier, FoodGroupEffects.Builder> exporter) {
exporter.accept(Unicopia.id("baked_goods"), new FoodGroupEffects.Builder().tag(UTags.Items.BAKED_GOODS).food(FoodComponents.BREAD));
exporter.accept(Unicopia.id("bat_ponys_delight"), new FoodGroupEffects.Builder().tag(UConventionalTags.Items.MANGOES).food(UFoodComponents.MANGO));
exporter.accept(Unicopia.id("candy"), new FoodGroupEffects.Builder().tag(UConventionalTags.Items.CANDY).food(UFoodComponents.CANDY));
exporter.accept(Unicopia.id("desserts"), new FoodGroupEffects.Builder().tag(UConventionalTags.Items.DESSERTS).food(FoodComponents.COOKIE));
exporter.accept(Unicopia.id("fruit"), new FoodGroupEffects.Builder().tag(UConventionalTags.Items.FRUITS).food(UFoodComponents.BANANA));
exporter.accept(Unicopia.id("rocks"), new FoodGroupEffects.Builder().tag(UConventionalTags.Items.ROCKS).tag(UTags.Items.ROCK_STEWS).food(FoodComponents.MUSHROOM_STEW));
exporter.accept(Unicopia.id("shells"), new FoodGroupEffects.Builder().tag(UTags.Items.SHELLS).food(UFoodComponents.SHELL));
exporter.accept(Unicopia.id("special_shells"), new FoodGroupEffects.Builder().tag(UTags.Items.SPECIAL_SHELLS).food(UFoodComponents.SHELLY));
exporter.accept(Unicopia.id("love"), new FoodGroupEffects.Builder().tag(UTags.Items.CONTAINER_WITH_LOVE).food(UFoodComponents.LOVE_MUG).ailment(new CompoundAffliction(List.<Affliction>of(
new StatusEffectAffliction(UEffects.FOOD_POISONING, Range.of(50), Range.of(2), 0),
new LoseHungerAffliction(0.5F)
))));
exporter.accept(Unicopia.id("nuts_and_seeds"), new FoodGroupEffects.Builder()
.tag(UConventionalTags.Items.GRAIN).tag(UConventionalTags.Items.NUTS).tag(UConventionalTags.Items.SEEDS)
.food(UFoodComponents.BANANA)
);
exporter.accept(Unicopia.id("pinecone"), new FoodGroupEffects.Builder().tag(UConventionalTags.Items.PINECONES).food(UFoodComponents.PINECONE).ailment(new HealingAffliction(1)));
provideMeatCategory("fish",
UConventionalTags.Items.COOKED_FISH, UConventionalTags.Items.RAW_FISH, UConventionalTags.Items.ROTTEN_FISH,
FoodComponents.COOKED_COD, FoodComponents.COD, FoodComponents.ROTTEN_FLESH, exporter);
provideMeatCategory("meat",
UConventionalTags.Items.COOKED_MEAT, UConventionalTags.Items.RAW_MEAT, UConventionalTags.Items.ROTTEN_MEAT,
FoodComponents.COOKED_BEEF, FoodComponents.BEEF, FoodComponents.ROTTEN_FLESH, exporter);
provideMeatCategory("insect",
UConventionalTags.Items.COOKED_INSECT, UConventionalTags.Items.RAW_INSECT, UConventionalTags.Items.ROTTEN_INSECT,
FoodComponents.COOKED_BEEF, FoodComponents.BEEF, FoodComponents.ROTTEN_FLESH, exporter);
provideVegetableCategory("sea_vegetable",
UTags.Items.HIGH_QUALITY_SEA_VEGETABLES, UTags.Items.LOW_QUALITY_SEA_VEGETABLES,
FoodComponents.COOKED_BEEF, FoodComponents.BEEF, exporter);
exporter.accept(Unicopia.id("foraging/blinding"), new FoodGroupEffects.Builder().tag(UTags.Items.FORAGE_BLINDING).food(4, 0.2F).ailment(CompoundAffliction.of(
new StatusEffectAffliction(StatusEffects.BLINDNESS, Range.of(30), Range.of(0), 50),
new StatusEffectAffliction(UEffects.FOOD_POISONING, Range.of(100), Range.of(2), 12)
)));
exporter.accept(Unicopia.id("foraging/dangerous"), new FoodGroupEffects.Builder().tag(UTags.Items.FORAGE_DANGEROUS).food(3, 0.3F).ailment(new StatusEffectAffliction(UEffects.FOOD_POISONING, Range.of(250), Range.of(2), 4)));
exporter.accept(Unicopia.id("foraging/edible_filling"), new FoodGroupEffects.Builder().tag(UTags.Items.FORAGE_FILLING).food(17, 0.6F));
exporter.accept(Unicopia.id("foraging/edible"), new FoodGroupEffects.Builder().tag(UTags.Items.FORAGE_SAFE).food(2, 1));
exporter.accept(Unicopia.id("foraging/leafy_greens"), new FoodGroupEffects.Builder().tag(ItemTags.LEAVES).food(1, 1.4F));
exporter.accept(Unicopia.id("foraging/nauseating"), new FoodGroupEffects.Builder().tag(UTags.Items.FORAGE_NAUSEATING).food(5, 0.5F).ailment(CompoundAffliction.of(
new StatusEffectAffliction(StatusEffects.WEAKNESS, Range.of(200), Range.of(1), 30),
new StatusEffectAffliction(UEffects.FOOD_POISONING, Range.of(200), Range.of(2), 0)
)));
exporter.accept(Unicopia.id("foraging/prickly"), new FoodGroupEffects.Builder().tag(UTags.Items.FORAGE_PRICKLY).food(0, 1.5F).ailment(CompoundAffliction.of(
new StatusEffectAffliction(StatusEffects.INSTANT_DAMAGE, Range.of(1), Range.of(0), 30)
)));
exporter.accept(Unicopia.id("foraging/glowing"), new FoodGroupEffects.Builder().tag(UTags.Items.FORAGE_GLOWING).food(1, 1.6F).ailment(CompoundAffliction.of(
new StatusEffectAffliction(StatusEffects.GLOWING, Range.of(30), Range.of(0), 30),
new StatusEffectAffliction(UEffects.FOOD_POISONING, Range.of(100), Range.of(2), 0)
)));
exporter.accept(Unicopia.id("foraging/risky"), new FoodGroupEffects.Builder().tag(UTags.Items.FORAGE_RISKY).food(9, 1.1F).ailment(new StatusEffectAffliction(UEffects.FOOD_POISONING, Range.of(100), Range.of(2), 80)));
exporter.accept(Unicopia.id("foraging/severely_nauseating"), new FoodGroupEffects.Builder().tag(UTags.Items.FORAGE_SEVERE_NAUSEATING).food(3, 0.9F).ailment(CompoundAffliction.of(
new StatusEffectAffliction(StatusEffects.WEAKNESS, Range.of(200), Range.of(1), 0),
new StatusEffectAffliction(UEffects.FOOD_POISONING, Range.of(100), Range.of(2), 80)
)));
exporter.accept(Unicopia.id("foraging/severely_prickly"), new FoodGroupEffects.Builder().tag(UTags.Items.FORAGE_SEVERE_PRICKLY).food(2, 0.9F).ailment(CompoundAffliction.of(
new StatusEffectAffliction(StatusEffects.INSTANT_DAMAGE, Range.of(1), Range.of(0), 0),
new StatusEffectAffliction(UEffects.FOOD_POISONING, Range.of(100), Range.of(2), 80)
)));
exporter.accept(Unicopia.id("foraging/strengthening"), new FoodGroupEffects.Builder().tag(UTags.Items.FORAGE_STRENGHENING).food(4, 0.2F).ailment(CompoundAffliction.of(
new StatusEffectAffliction(StatusEffects.STRENGTH, Range.of(1300), Range.of(0), 0),
new StatusEffectAffliction(UEffects.FOOD_POISONING, Range.of(100), Range.of(2), 70)
)));
}
private void provideMeatCategory(String name,
TagKey<Item> cookedTag, TagKey<Item> rawTag, TagKey<Item> rottenTag,
FoodComponent cooked, FoodComponent raw, FoodComponent rotten,
BiConsumer<Identifier, FoodGroupEffects.Builder> exporter) {
exporter.accept(Unicopia.id(name + "/cooked"), new FoodGroupEffects.Builder().tag(cookedTag).food(cooked).ailment(new StatusEffectAffliction(UEffects.FOOD_POISONING, Range.of(100), Range.of(2), 25)));
exporter.accept(Unicopia.id(name + "/raw"), new FoodGroupEffects.Builder().tag(rawTag).food(raw).ailment(CompoundAffliction.of(
new StatusEffectAffliction(StatusEffects.POISON, Range.of(45), Range.of(2), 80),
new StatusEffectAffliction(UEffects.FOOD_POISONING, Range.of(100), Range.of(2), 65)
)));
exporter.accept(Unicopia.id(name + "/rotten"), new FoodGroupEffects.Builder().tag(rottenTag).food(rotten).ailment(CompoundAffliction.of(
new StatusEffectAffliction(StatusEffects.POISON, Range.of(45), Range.of(2), 80),
new StatusEffectAffliction(UEffects.FOOD_POISONING, Range.of(100), Range.of(2), 95)
)));
}
private void provideVegetableCategory(String name,
TagKey<Item> cookedTag, TagKey<Item> rawTag,
FoodComponent cooked, FoodComponent raw,
BiConsumer<Identifier, FoodGroupEffects.Builder> exporter) {
exporter.accept(Unicopia.id(name + "/cooked"), new FoodGroupEffects.Builder().tag(cookedTag).food(cooked));
exporter.accept(Unicopia.id(name + "/raw"), new FoodGroupEffects.Builder().tag(rawTag).food(raw));
}
}

View file

@ -12,17 +12,16 @@ import com.minelittlepony.unicopia.server.world.UTreeGen;
import net.fabricmc.fabric.api.datagen.v1.FabricDataOutput;
import net.minecraft.block.Block;
import net.minecraft.data.DataOutput;
import net.minecraft.data.DataOutput.PathResolver;
import net.minecraft.registry.Registries;
import net.minecraft.data.DataProvider;
import net.minecraft.data.DataWriter;
public class SeasonsGrowthRatesProvider implements DataProvider {
private final PathResolver pathResolver;
private final DataCollector collectedData;
public SeasonsGrowthRatesProvider(FabricDataOutput output) {
this.pathResolver = output.getResolver(DataOutput.OutputType.DATA_PACK, "seasons/crop");
this.collectedData = new DataCollector(output.getResolver(DataOutput.OutputType.DATA_PACK, "seasons/crop"));
}
@Override
@ -32,7 +31,6 @@ public class SeasonsGrowthRatesProvider implements DataProvider {
@Override
public CompletableFuture<?> run(DataWriter writer) {
DataCollector collectedData = new DataCollector(pathResolver);
var exporter = collectedData.prime();
generate((block, crop) -> {
exporter.accept(Registries.BLOCK.getId(block), crop::toJson);

View file

@ -73,27 +73,28 @@ public class UAdvancementsProvider extends FabricAdvancementProvider {
private void generateEarthTribeAdvancementsTree(Consumer<Advancement> consumer, AdvancementDisplayBuilder.Parent parent) {
parent.child(UItems.ROCK).criterion("has_rock", hasItems(UItems.ROCK)).build(consumer, "born_on_a_rock_farm").children(p -> {
p.child(UItems.PEBBLES).criterion("killed_entity_with_rock", killWithItems(UTags.FROM_ROCKS)).build(consumer, "sticks_and_stones");
p.child(UItems.PEBBLES).criterion("killed_entity_with_rock", killWithItems(UTags.DamageTypes.FROM_ROCKS)).build(consumer, "sticks_and_stones");
p.child(UItems.WEIRD_ROCK).hidden().criterion("has_rock", hasItems(UItems.WEIRD_ROCK)).build(consumer, "thats_unusual");
});
parent.child(UItems.FRIED_AXOLOTL).criterion("eaten_axolotl", ConsumeItemCriterion.Conditions.item(UItems.FRIED_AXOLOTL)).build(consumer, "tastes_like_chicken");
parent.child(UItems.OATS).criterion("has_oats", hasItems(UItems.OATS)).build(consumer, "oats_so_easy");
parent.child(Items.HAY_BLOCK).criterion("eat_hay", ConsumeItemCriterion.Conditions.item(Items.HAY_BLOCK)).build(consumer, "what_the_hay");
parent.child(UItems.COPPER_HORSE_SHOE).criterion("has_horseshoe", hasItems(UTags.HORSE_SHOES)).build(consumer, "blacksmith").children(p -> {
parent.child(UItems.COPPER_HORSE_SHOE).criterion("has_horseshoe", hasItems(UTags.Items.HORSE_SHOES)).build(consumer, "blacksmith").children(p -> {
p.child(UItems.IRON_HORSE_SHOE).criterion("has_iron_horseshoe", hasItems(UItems.IRON_HORSE_SHOE)).build(consumer, "change_of_shoes")
.child(UItems.GOLDEN_HORSE_SHOE).criterion("has_gold_horseshoe", hasItems(UItems.GOLDEN_HORSE_SHOE)).build(consumer, "fashionably_expensive")
.child(UItems.NETHERITE_HORSE_SHOE).criterion("has_netherite_horseshoe", hasItems(UItems.NETHERITE_HORSE_SHOE)).build(consumer, "overkill");
p.child(UItems.IRON_HORSE_SHOE).hidden().frame(AdvancementFrame.CHALLENGE).criterion("killed_entity_with_horseshoe", killWithItems(UTags.FROM_HORSESHOES)).build(consumer, "dead_ringer");
p.child(UItems.IRON_HORSE_SHOE).hidden().frame(AdvancementFrame.CHALLENGE).criterion("killed_entity_with_horseshoe", killWithItems(UTags.DamageTypes.FROM_HORSESHOES)).build(consumer, "dead_ringer");
});
parent.child(UItems.PINECONE).frame(AdvancementFrame.CHALLENGE).criterion("eat_pinecone", ConsumeItemCriterion.Conditions.item(UItems.PINECONE)).build(consumer, "eat_pinecone");
parent.child(UItems.OAK_BASKET).doNotAnnounce().criterion("has_basket", hasItems(UTags.BASKETS)).build(consumer, "basket_case")
parent.child(UItems.OAK_BASKET).doNotAnnounce().criterion("has_basket", hasItems(UTags.Items.BASKETS)).build(consumer, "basket_case")
.child(Items.LANTERN).criterion("construct_balloon", CustomEventCriterion.create("construct_balloon")).build(consumer, "aeronaut")
.child(UItems.GIANT_BALLOON).announce().frame(AdvancementFrame.CHALLENGE).criterion("ride_balloon", CustomEventCriterion.create("ride_balloon")).build(consumer, "travelling_in_style");
parent.child(UItems.MUFFIN).hidden().criterion("has_muffin", hasItems(UItems.MUFFIN)).build(consumer, "baked_bads");
parent.child(UItems.HORSE_SHOE_FRIES).criterion("has_horse_shoe_fries", hasItems(UItems.HORSE_SHOE_FRIES)).build(consumer, "lucky");
parent.child(UItems.TOAST).criterion("has_toast", hasItems(UItems.TOAST)).build(consumer, "toast")
.child(UItems.BURNED_TOAST).hidden().criterion("has_burned_toast", hasItems(UItems.BURNED_TOAST)).build(consumer, "burn_toast");
parent.child(UItems.GREEN_APPLE).criterion("has_apple", hasItems(UTags.FRESH_APPLES)).build(consumer, "apple_route").children(p -> {
parent.child(UItems.GREEN_APPLE).criterion("has_apple", hasItems(UTags.Items.FRESH_APPLES)).build(consumer, "apple_route").children(p -> {
p.child(UItems.SWEET_APPLE).criterion("has_all_apples", hasItems(Items.APPLE, UItems.GREEN_APPLE, UItems.SWEET_APPLE, UItems.SOUR_APPLE, UItems.ROTTEN_APPLE, UItems.ZAP_APPLE, UItems.COOKED_ZAP_APPLE, Items.GOLDEN_APPLE)).build(consumer, "sweet_apple_acres");
p.child(UItems.ZAP_BULB).criterion("has_zap_apple", hasItems(UItems.ZAP_APPLE)).build(consumer, "trick_apple").children(pp -> {
pp.child(UItems.ZAP_APPLE).hidden().criterion("eat_trick_apple", CustomEventCriterion.createFlying("eat_trick_apple")).build(consumer, "eat_trick_apple");
@ -110,7 +111,7 @@ public class UAdvancementsProvider extends FabricAdvancementProvider {
parent.child(Items.GLASS_PANE).criterion("break_window", CustomEventCriterion.createFlying("break_window")).rewards(AdvancementRewards.Builder.experience(10)).build(consumer, "rainbow_crash");
parent.child(UItems.PEGASUS_BADGE).criterion("fly_through_the_pain", CustomEventCriterion.createFlying("second_wind")).rewards(AdvancementRewards.Builder.experience(10)).build(consumer, "second_wind");
parent.child(UItems.EMPTY_JAR).criterion("has_empty_jar", hasItems(UItems.EMPTY_JAR)).build(consumer, "jar")
.child(UItems.RAIN_CLOUD_JAR).criterion("has_cloud_jar", hasItems(UTags.CLOUD_JARS)).rewards(AdvancementRewards.Builder.experience(55)).build(consumer, "gotcha");
.child(UItems.RAIN_CLOUD_JAR).criterion("has_cloud_jar", hasItems(UTags.Items.CLOUD_JARS)).rewards(AdvancementRewards.Builder.experience(55)).build(consumer, "gotcha");
parent.child(UItems.LIGHTNING_JAR).frame(AdvancementFrame.CHALLENGE).criterion("lightning_strike", CustomEventCriterion.createFlying("lightning_strike")).rewards(AdvancementRewards.Builder.experience(30)).build(consumer, "mid_flight_interruption").children(p -> {
p.child(UItems.LIGHTNING_JAR).hidden().frame(AdvancementFrame.CHALLENGE).apply(d -> applyLightningBugCriterions(d, RacePredicate.of(Set.of(Race.CHANGELING), Set.of()), 10, 90)).build(consumer, "lightning_bug");
p.child(UItems.LIGHTNING_JAR).hidden().frame(AdvancementFrame.CHALLENGE).apply(d -> applyLightningBugCriterions(d, RacePredicate.of(Set.of(), Set.of(Race.CHANGELING)), 10, 90)).build(consumer, "wonder_bolt");
@ -145,6 +146,7 @@ public class UAdvancementsProvider extends FabricAdvancementProvider {
private void generateUnicornTribeAdvancementsTree(Consumer<Advancement> consumer, AdvancementDisplayBuilder.Parent parent) {
parent.child(UItems.SPELLBOOK).criterion("has_spellbook", hasItems(UItems.SPELLBOOK)).build(consumer, "books").children(p -> {
// TODO:
//ItemPredicate bookPredicate = ItemPredicate.Builder.create().tag(ItemTags.BOOKSHELF_BOOKS).build();
//p.child(Items.BOOK).hidden().frame(AdvancementFrame.CHALLENGE).criterion("has_books", InventoryChangedCriterion.Conditions.items(IntStream.range(0, 9 * 4).mapToObj(i -> bookPredicate).toArray(ItemPredicate[]::new))).build(consumer, "books_books_books");
p.child(UItems.CRYSTAL_SHARD).criterion("has_shard", hasItems(UItems.CRYSTAL_SHARD)).build(consumer, "crystaline").children(pp -> {
@ -255,7 +257,7 @@ public class UAdvancementsProvider extends FabricAdvancementProvider {
static CriterionConditions dingCelestia(Set<Race> includeTribes, Set<Race> excludeTribes) {
return new SendViaDragonBreathScrollCriterion.Conditions(
LootContextPredicate.EMPTY,
ItemPredicate.Builder.create().tag(UTags.IS_DELIVERED_AGGRESSIVELY).build(), false,
ItemPredicate.Builder.create().tag(UTags.Items.IS_DELIVERED_AGGRESSIVELY).build(), false,
Optional.of("princess celestia"),
TriState.FALSE,
Optional.of("dings_on_celestias_head"),

View file

@ -16,6 +16,7 @@ import com.minelittlepony.unicopia.block.ShellsBlock;
import com.minelittlepony.unicopia.block.SlimePustuleBlock;
import com.minelittlepony.unicopia.block.UBlocks;
import com.minelittlepony.unicopia.block.zap.ZapAppleLeavesBlock;
import com.minelittlepony.unicopia.datagen.Datagen;
import com.minelittlepony.unicopia.datagen.UBlockFamilies;
import com.minelittlepony.unicopia.server.world.Tree;
@ -41,7 +42,6 @@ import net.minecraft.data.client.When;
import net.minecraft.item.Item;
import net.minecraft.item.Items;
import net.minecraft.registry.Registries;
import net.minecraft.registry.Registry;
import net.minecraft.state.property.BooleanProperty;
import net.minecraft.state.property.EnumProperty;
import net.minecraft.state.property.Properties;
@ -113,7 +113,7 @@ public class UBlockStateModelGenerator extends BlockStateModelGenerator {
registerHiveBlock(UBlocks.HIVE);
registerRotated(UBlocks.CHITIN_SPIKES, BlockModels.SPIKES);
registerHull(UBlocks.CHISELLED_CHITIN_HULL, UBlocks.CHITIN, UBlocks.CHISELLED_CHITIN);
registerParentedItemModel(UBlocks.SLIME_PUSTULE, ModelIds.getBlockSubModelId(UBlocks.SLIME_PUSTULE, "_pod"));
registerItemModel(UBlocks.SLIME_PUSTULE.asItem());
blockStateCollector.accept(VariantsBlockStateSupplier.create(UBlocks.SLIME_PUSTULE)
.coordinate(BlockStateVariantMap.create(SlimePustuleBlock.SHAPE)
.register(state -> BlockStateVariant.create().put(MODEL, ModelIds.getBlockSubModelId(UBlocks.SLIME_PUSTULE, "_" + state.asString())))));
@ -176,7 +176,7 @@ public class UBlockStateModelGenerator extends BlockStateModelGenerator {
registerWithStages(UBlocks.FROSTED_OBSIDIAN, Properties.AGE_3, BlockModels.CUBE_ALL, 0, 1, 2, 3);
registerWithStagesBuiltinModels(UBlocks.ROCKS, Properties.AGE_7, 0, 1, 2, 3, 4, 5, 6, 7);
registerWithStagesBuiltinModels(UBlocks.MYSTERIOUS_EGG, PileBlock.COUNT, 1, 2, 3);
excludeFromSimpleItemModelGeneration(UBlocks.MYSTERIOUS_EGG);
registerItemModel(UBlocks.MYSTERIOUS_EGG.asItem());
FireModels.registerSoulFire(this, UBlocks.SPECTRAL_FIRE, Blocks.SOUL_FIRE);
blockStateCollector.accept(createSingletonBlockState(UBlocks.JAR, BlockModels.TEMPLATE_JAR));
@ -429,9 +429,7 @@ public class UBlockStateModelGenerator extends BlockStateModelGenerator {
Identifier side = baseBlockId.withPath(p -> "block/" + p + "_side");
TextureMap textures = new TextureMap().put(TOP, top).put(SIDE, side);
MultipartBlockStateSupplier supplier = MultipartBlockStateSupplier.create(Registries.BLOCK.getOrEmpty(blockId).orElseGet(() -> {
return Registry.register(Registries.BLOCK, blockId, new EdibleBlock(blockId, blockId, false));
}));
MultipartBlockStateSupplier supplier = MultipartBlockStateSupplier.create(Datagen.getOrCreateBaleBlock(blockId));
Map<Integer, Identifier> uploadedModels = new HashMap<>();
for (Direction.Axis axis : Direction.Axis.VALUES) {

View file

@ -1,190 +0,0 @@
package com.minelittlepony.unicopia.datagen.providers;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import com.minelittlepony.unicopia.Race;
import com.minelittlepony.unicopia.UConventionalTags;
import com.minelittlepony.unicopia.UTags;
import com.minelittlepony.unicopia.block.UBlocks;
import com.minelittlepony.unicopia.datagen.Datagen;
import com.minelittlepony.unicopia.datagen.ItemFamilies;
import com.minelittlepony.unicopia.item.BedsheetsItem;
import com.minelittlepony.unicopia.item.UItems;
import net.fabricmc.fabric.api.datagen.v1.FabricDataOutput;
import net.fabricmc.fabric.api.datagen.v1.provider.FabricTagProvider;
import net.fabricmc.fabric.api.tag.convention.v1.ConventionalItemTags;
import net.minecraft.block.Block;
import net.minecraft.item.Item;
import net.minecraft.item.Items;
import net.minecraft.registry.Registries;
import net.minecraft.registry.RegistryKeys;
import net.minecraft.registry.RegistryWrapper;
import net.minecraft.registry.RegistryWrapper.WrapperLookup;
import net.minecraft.registry.tag.BlockTags;
import net.minecraft.registry.tag.ItemTags;
import net.minecraft.registry.tag.TagBuilder;
import net.minecraft.registry.tag.TagKey;
import net.minecraft.util.Identifier;
public class UItemTagProvider extends FabricTagProvider.ItemTagProvider {
private final UBlockTagProvider blockTagProvider;
public UItemTagProvider(FabricDataOutput output, CompletableFuture<RegistryWrapper.WrapperLookup> registriesFuture, UBlockTagProvider blockTagProvider) {
super(output, registriesFuture, blockTagProvider);
this.blockTagProvider = blockTagProvider;
}
@Override
public void copy(TagKey<Block> blockTag, TagKey<Item> itemTag) {
TagBuilder blockTagBuilder = Objects.requireNonNull(blockTagProvider, "Pass Block tag provider via constructor to use copy").getTagBuilder(blockTag);
TagBuilder itemTagBuilder = getTagBuilder(itemTag);
blockTagBuilder.build().forEach(entry -> {
if (entry.canAdd(Registries.ITEM::containsId, tagId -> getTagBuilder(TagKey.of(RegistryKeys.ITEM, tagId)) != null)) {
itemTagBuilder.add(entry);
} else {
Datagen.LOGGER.warn("Cannot copy missing entry {} to item tag {}", entry, itemTag.id());
}
});
}
@Override
protected void configure(WrapperLookup arg) {
copyBlockTags();
exportConventionalTags();
getOrCreateTagBuilder(ItemTags.BOOKSHELF_BOOKS).add(UItems.SPELLBOOK);
getOrCreateTagBuilder(ItemTags.BEDS).add(UItems.CLOTH_BED, UItems.CLOUD_BED);
getOrCreateTagBuilder(ItemTags.CHEST_BOATS).add(UItems.PALM_CHEST_BOAT);
getOrCreateTagBuilder(ItemTags.BOATS).add(UItems.PALM_BOAT);
getOrCreateTagBuilder(ItemTags.MUSIC_DISCS).add(ItemFamilies.MUSIC_DISCS);
getOrCreateTagBuilder(ItemTags.CREEPER_DROP_MUSIC_DISCS).add(UItems.MUSIC_DISC_CRUSADE, UItems.MUSIC_DISC_FUNK, UItems.MUSIC_DISC_PET, UItems.MUSIC_DISC_POPULAR);
getOrCreateTagBuilder(ItemTags.SIGNS).add(UBlocks.PALM_SIGN.asItem());
getOrCreateTagBuilder(ItemTags.HANGING_SIGNS).add(UBlocks.PALM_HANGING_SIGN.asItem());
getOrCreateTagBuilder(UTags.HORSE_SHOES).add(ItemFamilies.HORSE_SHOES);
getOrCreateTagBuilder(UTags.POLEARMS).add(ItemFamilies.POLEARMS);
getOrCreateTagBuilder(ItemTags.TOOLS).addTag(UTags.HORSE_SHOES).addTag(UTags.POLEARMS);
getOrCreateTagBuilder(UTags.BASKETS).add(ItemFamilies.BASKETS);
getOrCreateTagBuilder(UTags.BADGES).add(Race.REGISTRY.stream()
.map(race -> race.getId().withPath(p -> p + "_badge"))
.flatMap(id -> Registries.ITEM.getOrEmpty(id).stream())
.toArray(Item[]::new));
getOrCreateTagBuilder(UTags.WOOL_BED_SHEETS).add(BedsheetsItem.ITEMS.values().stream().filter(sheet -> sheet != UItems.KELP_BED_SHEETS).toArray(Item[]::new));
getOrCreateTagBuilder(UTags.BED_SHEETS).forceAddTag(UTags.WOOL_BED_SHEETS).add(UItems.KELP_BED_SHEETS);
getOrCreateTagBuilder(UTags.APPLE_SEEDS).add(UItems.GREEN_APPLE_SEEDS, UItems.SWEET_APPLE_SEEDS, UItems.SOUR_APPLE_SEEDS);
getOrCreateTagBuilder(UTags.MAGIC_FEATHERS).add(UItems.PEGASUS_FEATHER, UItems.GRYPHON_FEATHER);
getOrCreateTagBuilder(UTags.FRESH_APPLES).add(Items.APPLE, UItems.GREEN_APPLE, UItems.SWEET_APPLE, UItems.SOUR_APPLE);
getOrCreateTagBuilder(UTags.CLOUD_JARS).add(UItems.RAIN_CLOUD_JAR, UItems.STORM_CLOUD_JAR);
getOrCreateTagBuilder(UTags.PIES).add(UItems.APPLE_PIE, UItems.APPLE_PIE_HOOF);
// technical tags
getOrCreateTagBuilder(ItemTags.VILLAGER_PLANTABLE_SEEDS).addTag(UTags.APPLE_SEEDS);
getOrCreateTagBuilder(UTags.CAN_CUT_PIE).forceAddTag(ConventionalItemTags.SHEARS).addOptionalTag(UConventionalTags.TOOL_KNIVES);
getOrCreateTagBuilder(UTags.COOLS_OFF_KIRINS).add(Items.MELON_SLICE, UItems.JUICE).forceAddTag(ConventionalItemTags.WATER_BUCKETS);
getOrCreateTagBuilder(UTags.FALLS_SLOWLY).add(Items.FEATHER, UItems.CLOUD_LUMP).forceAddTag(UTags.MAGIC_FEATHERS);
getOrCreateTagBuilder(UTags.IS_DELIVERED_AGGRESSIVELY).forceAddTag(ItemTags.ANVIL);
getOrCreateTagBuilder(UTags.SPOOKED_MOB_DROPS).add(Items.BRICK);
getOrCreateTagBuilder(UTags.SHADES).add(
Items.CARVED_PUMPKIN, Items.SKELETON_SKULL, Items.WITHER_SKELETON_SKULL, Items.PLAYER_HEAD,
Items.ZOMBIE_HEAD, Items.CREEPER_HEAD, Items.DRAGON_HEAD, Items.PIGLIN_HEAD,
UItems.SUNGLASSES
);
getOrCreateTagBuilder(UTags.FLOATS_ON_CLOUDS)
.forceAddTag(UTags.Items.CLOUD_BEDS)
.forceAddTag(UTags.Items.CLOUD_SLABS)
.forceAddTag(UTags.Items.CLOUD_STAIRS)
.forceAddTag(UTags.Items.CLOUD_BLOCKS)
.add(UItems.CLOUD_LUMP);
getOrCreateTagBuilder(UTags.HAS_NO_TRAITS).add(
Items.AIR, Items.SPAWNER, Items.STRUCTURE_VOID, Items.STRUCTURE_BLOCK,
Items.COMMAND_BLOCK, Items.CHAIN_COMMAND_BLOCK, Items.REPEATING_COMMAND_BLOCK,
Items.LIGHT, Items.JIGSAW, Items.BARRIER, Items.BEDROCK, Items.END_PORTAL_FRAME,
Items.DEBUG_STICK, Items.COMMAND_BLOCK_MINECART,
UItems.PLUNDER_VINE
).forceAddTag(UTags.BADGES);
getOrCreateTagBuilder(UTags.LOOT_BUG_HIGH_VALUE_DROPS).add(
Items.DIAMOND, Items.GOLDEN_APPLE, Items.GOLDEN_CARROT,
Items.GOLDEN_HELMET, Items.GOLDEN_BOOTS, Items.GOLDEN_LEGGINGS, Items.GOLDEN_CHESTPLATE,
Items.GOLDEN_HORSE_ARMOR,
Items.GOLDEN_PICKAXE, Items.GOLDEN_SHOVEL, Items.GOLDEN_AXE, Items.GOLDEN_SWORD, Items.GOLDEN_HOE,
UItems.GOLDEN_HORSE_SHOE, UItems.GOLDEN_POLEARM, UItems.GOLDEN_FEATHER, UItems.GOLDEN_WING,
UItems.GOLDEN_OAK_SEEDS
).forceAddTag(ConventionalItemTags.NUGGETS)
.forceAddTag(ConventionalItemTags.GOLD_INGOTS).forceAddTag(ConventionalItemTags.RAW_GOLD_ORES).forceAddTag(ConventionalItemTags.RAW_GOLD_BLOCKS)
.addOptionalTag(new Identifier("farmersdelight:golden_knife"));
exportFarmersDelightItems();
}
private void copyBlockTags() {
copy(BlockTags.LEAVES, ItemTags.LEAVES);
copy(BlockTags.LOGS_THAT_BURN, ItemTags.LOGS_THAT_BURN);
copy(BlockTags.LOGS, ItemTags.LOGS);
copy(BlockTags.PLANKS, ItemTags.PLANKS);
copy(BlockTags.WOODEN_BUTTONS, ItemTags.WOODEN_BUTTONS);
copy(BlockTags.WOODEN_DOORS, ItemTags.WOODEN_DOORS);
copy(BlockTags.FENCE_GATES, ItemTags.FENCE_GATES);
copy(BlockTags.WOODEN_FENCES, ItemTags.WOODEN_FENCES);
copy(BlockTags.WOODEN_PRESSURE_PLATES, ItemTags.WOODEN_PRESSURE_PLATES);
copy(BlockTags.SLABS, ItemTags.SLABS);
copy(BlockTags.WOODEN_SLABS, ItemTags.WOODEN_SLABS);
copy(BlockTags.STAIRS, ItemTags.STAIRS);
copy(BlockTags.WOODEN_STAIRS, ItemTags.WOODEN_STAIRS);
copy(BlockTags.TRAPDOORS, ItemTags.TRAPDOORS);
copy(BlockTags.WOODEN_TRAPDOORS, ItemTags.WOODEN_TRAPDOORS);
copy(BlockTags.SAPLINGS, ItemTags.SAPLINGS);
copy(UTags.Blocks.ZAP_LOGS, UTags.Items.ZAP_LOGS);
copy(UTags.Blocks.WAXED_ZAP_LOGS, UTags.Items.WAXED_ZAP_LOGS);
copy(UTags.Blocks.PALM_LOGS, UTags.Items.PALM_LOGS);
copy(UTags.Blocks.CLOUD_BEDS, UTags.Items.CLOUD_BEDS);
copy(UTags.Blocks.CLOUD_SLABS, UTags.Items.CLOUD_SLABS);
copy(UTags.Blocks.CLOUD_STAIRS, UTags.Items.CLOUD_STAIRS);
copy(UTags.Blocks.CLOUD_BLOCKS, UTags.Items.CLOUD_BLOCKS);
copy(UTags.Blocks.CHITIN_BLOCKS, UTags.Items.CHITIN_BLOCKS);
}
private void exportConventionalTags() {
getOrCreateTagBuilder(UConventionalTags.ACORNS).add(UItems.ACORN);
getOrCreateTagBuilder(UConventionalTags.APPLES)
.add(Items.APPLE, Items.GOLDEN_APPLE, Items.ENCHANTED_GOLDEN_APPLE, UItems.ROTTEN_APPLE)
.forceAddTag(UTags.FRESH_APPLES)
.addOptionalTag(new Identifier("c", "pyrite_apples")) // no idea which mod add pyrite apples
;
getOrCreateTagBuilder(UConventionalTags.BANANAS).add(UItems.BANANA);
getOrCreateTagBuilder(UConventionalTags.COOKED_FISH).add(Items.COOKED_COD, Items.COOKED_SALMON);
getOrCreateTagBuilder(UConventionalTags.STICKS).add(Items.STICK);
getOrCreateTagBuilder(UConventionalTags.PINECONES).add(UItems.PINECONE);
getOrCreateTagBuilder(UConventionalTags.PINEAPPLES).add(UItems.PINEAPPLE);
getOrCreateTagBuilder(UConventionalTags.MANGOES).add(UItems.MANGO);
getOrCreateTagBuilder(UConventionalTags.MUSHROOMS).add(Items.RED_MUSHROOM, Items.BROWN_MUSHROOM);
getOrCreateTagBuilder(UConventionalTags.MUFFINS).add(UItems.MUFFIN);
getOrCreateTagBuilder(UConventionalTags.SEEDS).add(Items.BEETROOT_SEEDS, Items.MELON_SEEDS, Items.PUMPKIN_SEEDS, Items.TORCHFLOWER_SEEDS, Items.WHEAT_SEEDS)
.add(UItems.OAT_SEEDS)
.forceAddTag(UTags.APPLE_SEEDS);
getOrCreateTagBuilder(UConventionalTags.OATMEALS).add(UItems.OATMEAL);
getOrCreateTagBuilder(UConventionalTags.GRAIN).add(Items.WHEAT, UItems.OATS);
getOrCreateTagBuilder(UConventionalTags.NUTS).addOptionalTag(UConventionalTags.CROPS_PEANUTS);
getOrCreateTagBuilder(UConventionalTags.FRUITS)
.forceAddTag(UConventionalTags.MANGOES)
.forceAddTag(UConventionalTags.PINEAPPLES)
.forceAddTag(UConventionalTags.APPLES)
.forceAddTag(UConventionalTags.BANANAS);
}
private void exportFarmersDelightItems() {
getOrCreateTagBuilder(UTags.COOLS_OFF_KIRINS)
.addOptional(new Identifier("farmersdelight:melon_popsicle"))
.addOptional(new Identifier("farmersdelight:melon_juice"));
getOrCreateTagBuilder(TagKey.of(RegistryKeys.ITEM, new Identifier("farmersdelight:cabbage_roll_ingredients"))).add(UItems.OATS, UItems.ROCK, UItems.WHEAT_WORMS);
getOrCreateTagBuilder(TagKey.of(RegistryKeys.ITEM, new Identifier("farmersdelight:comfort_foods"))).add(UItems.OATMEAL, UItems.ROCK_STEW, UItems.MUFFIN);
}
}

View file

@ -59,12 +59,14 @@ public class UModelProvider extends FabricModelProvider {
ItemModels.register(itemModelGenerator,
UItems.ACORN, UItems.APPLE_PIE_HOOF, UItems.APPLE_PIE_SLICE, UItems.APPLE_PIE,
UItems.BANANA, UItems.BOTCHED_GEM, UItems.BOWL_OF_NUTS, UItems.BROKEN_SUNGLASSES, UItems.BURNED_JUICE, UItems.BURNED_TOAST,
UItems.CARAPACE, UItems.CLAM_SHELL, UItems.COOKED_ZAP_APPLE, UItems.CHOCOLATE_OATMEAL_COOKIE, UItems.CLOUD_LUMP, UItems.CRISPY_HAY_FRIES, UItems.CRYSTAL_HEART, UItems.CRYSTAL_SHARD,
UItems.CARAPACE, UItems.CLAM_SHELL, UItems.COOKED_ZAP_APPLE, UItems.CHOCOLATE_OATMEAL_COOKIE,
UItems.CLOUD_LUMP, UItems.CRISPY_HAY_FRIES, UItems.CRYSTAL_HEART, UItems.CRYSTAL_SHARD,
UItems.COOKED_TROPICAL_FISH, UItems.COOKED_PUFFERFISH, UItems.FRIED_AXOLOTL,
UItems.DAFFODIL_DAISY_SANDWICH, UItems.DRAGON_BREATH_SCROLL,
UItems.EMPTY_JAR,
UItems.FRIENDSHIP_BRACELET,
UItems.GIANT_BALLOON, UItems.GOLDEN_FEATHER, UItems.GOLDEN_OAK_SEEDS, UItems.GOLDEN_WING, UItems.GREEN_APPLE_SEEDS, UItems.GREEN_APPLE, UItems.GROGARS_BELL,
UItems.GRYPHON_FEATHER,
UItems.GRYPHON_FEATHER, UItems.GREEN_FRIED_EGG,
UItems.HAY_BURGER, UItems.HAY_FRIES, UItems.HORSE_SHOE_FRIES,
UItems.IMPORTED_OATS,
UItems.JAM_TOAST, UItems.JUICE,
@ -72,7 +74,8 @@ public class UModelProvider extends FabricModelProvider {
UItems.MANGO, UItems.MUFFIN,
UItems.OATMEAL, UItems.OATMEAL_COOKIE, UItems.SCONE,
UItems.PEBBLES, UItems.PEGASUS_FEATHER, UItems.PINECONE, UItems.PINECONE_COOKIE, UItems.PINEAPPLE_CROWN,
UItems.RAIN_CLOUD_JAR, UItems.ROCK_STEW, UItems.ROCK, UItems.ROTTEN_APPLE,
UItems.RAIN_CLOUD_JAR, UItems.ROCK_STEW, UItems.ROCK,
UItems.ROTTEN_APPLE, UItems.ROTTEN_COD, UItems.ROTTEN_TROPICAL_FISH, UItems.ROTTEN_SALMON, UItems.ROTTEN_PUFFERFISH,
UItems.SALT_CUBE, UItems.SCALLOP_SHELL, UItems.SHELLY, UItems.SOUR_APPLE_SEEDS, UItems.SOUR_APPLE, UItems.SPELLBOOK, UItems.STORM_CLOUD_JAR,
UItems.SWEET_APPLE_SEEDS, UItems.SWEET_APPLE,
UItems.TOAST, UItems.TOM, UItems.TURRET_SHELL,
@ -106,7 +109,10 @@ public class UModelProvider extends FabricModelProvider {
.put(TextureKey.LAYER1, ModelIds.getItemSubModelId(UItems.MAGIC_STAFF, "_magic")), itemModelGenerator.writer);
// polearms
List.of(UItems.DIAMOND_POLEARM, UItems.GOLDEN_POLEARM, UItems.NETHERITE_POLEARM, UItems.STONE_POLEARM, UItems.WOODEN_POLEARM, UItems.IRON_POLEARM).forEach(item -> ItemModels.registerPolearm(itemModelGenerator, item));
List.of(
UItems.DIAMOND_POLEARM, UItems.GOLDEN_POLEARM, UItems.NETHERITE_POLEARM,
UItems.STONE_POLEARM, UItems.WOODEN_POLEARM, UItems.IRON_POLEARM
).forEach(item -> ItemModels.registerPolearm(itemModelGenerator, item));
// sheets
ItemModels.register(itemModelGenerator, BedsheetsItem.ITEMS.values().stream().toArray(Item[]::new));
// badges

View file

@ -2,6 +2,7 @@ package com.minelittlepony.unicopia.datagen.providers.loot;
import java.util.function.Function;
import com.minelittlepony.unicopia.UTags;
import com.minelittlepony.unicopia.item.UItems;
import com.minelittlepony.unicopia.item.enchantment.UEnchantments;
@ -14,20 +15,24 @@ import net.minecraft.enchantment.Enchantments;
import net.minecraft.item.ItemConvertible;
import net.minecraft.loot.LootPool;
import net.minecraft.loot.LootTable;
import net.minecraft.loot.condition.LocationCheckLootCondition;
import net.minecraft.loot.condition.LootCondition;
import net.minecraft.loot.condition.MatchToolLootCondition;
import net.minecraft.loot.condition.RandomChanceLootCondition;
import net.minecraft.loot.condition.TableBonusLootCondition;
import net.minecraft.loot.entry.ItemEntry;
import net.minecraft.loot.entry.LootPoolEntry;
import net.minecraft.loot.entry.TagEntry;
import net.minecraft.loot.function.ApplyBonusLootFunction;
import net.minecraft.loot.function.SetCountLootFunction;
import net.minecraft.loot.provider.number.ConstantLootNumberProvider;
import net.minecraft.loot.provider.number.UniformLootNumberProvider;
import net.minecraft.predicate.NumberRange;
import net.minecraft.predicate.entity.LocationPredicate;
import net.minecraft.predicate.item.EnchantmentPredicate;
import net.minecraft.predicate.item.ItemPredicate;
import net.minecraft.util.Identifier;
import net.minecraft.world.biome.BiomeKeys;
public class UBlockAdditionsLootTableProvider extends FabricBlockLootTableProvider {
public static final LootCondition.Builder WITH_GEM_FINDER = MatchToolLootCondition.builder(ItemPredicate.Builder.create().enchantment(new EnchantmentPredicate(UEnchantments.GEM_FINDER, NumberRange.IntRange.atLeast(1))));
@ -35,6 +40,10 @@ public class UBlockAdditionsLootTableProvider extends FabricBlockLootTableProvid
public static final LootCondition.Builder WITHOUT_SILK_TOUCH_AND_GEM_FINDER = WITHOUT_SILK_TOUCH.and(WITH_GEM_FINDER);
public static final float[] GEMSTONES_FORTUNE_CHANCE = { 0.1F, 0.14285715F, 0.25F, 1F };
public static final LootCondition.Builder NEEDS_OCEAN_OR_BEACH_BIOME =
LocationCheckLootCondition.builder(LocationPredicate.Builder.create().biome(BiomeKeys.OCEAN))
.or(LocationCheckLootCondition.builder(LocationPredicate.Builder.create().biome(BiomeKeys.BEACH)));
public UBlockAdditionsLootTableProvider(FabricDataOutput dataOutput) {
super(dataOutput);
}
@ -57,12 +66,25 @@ public class UBlockAdditionsLootTableProvider extends FabricBlockLootTableProvid
addVanillaDrop(Blocks.DEEPSLATE_DIAMOND_ORE, this::crystalShardDrops);
addVanillaDrop(Blocks.OAK_LEAVES, block -> chanceDropWithShears(block, UItems.ACORN, GEMSTONES_FORTUNE_CHANCE));
addVanillaDrop(Blocks.SPRUCE_LEAVES, block -> chanceDropWithShears(block, UItems.PINECONE, GEMSTONES_FORTUNE_CHANCE));
addVanillaDrop(Blocks.GRAVEL, this::shellDrops);
addVanillaDrop(Blocks.SUSPICIOUS_GRAVEL, this::shellDrops);
}
private void addVanillaDrop(Block block, Function<Block, LootTable.Builder> lootTableFunction) {
lootTables.put(new Identifier("unicopiamc", block.getLootTableId().getPath()), lootTableFunction.apply(block));
}
public LootTable.Builder shellDrops(Block block) {
return LootTable.builder().pool(LootPool.builder()
.rolls(ConstantLootNumberProvider.create(1))
.conditionally(WITHOUT_SILK_TOUCH.and(NEEDS_OCEAN_OR_BEACH_BIOME))
.with(applyExplosionDecay(block, TagEntry.builder(UTags.Items.SHELLS)
.apply(SetCountLootFunction.builder(ConstantLootNumberProvider.create(1)))
)
.conditionally(TableBonusLootCondition.builder(Enchantments.FORTUNE, GEMSTONES_FORTUNE_CHANCE)))
);
}
public LootTable.Builder chanceDropWithShears(Block block, ItemConvertible drop, float...chance) {
return LootTable.builder()
.pool(LootPool.builder()

View file

@ -1,7 +1,17 @@
package com.minelittlepony.unicopia.datagen.providers.loot;
import java.util.List;
import com.minelittlepony.unicopia.Unicopia;
import com.minelittlepony.unicopia.block.EdibleBlock;
import com.minelittlepony.unicopia.block.EnchantedFruitBlock;
import com.minelittlepony.unicopia.block.PieBlock;
import com.minelittlepony.unicopia.block.PileBlock;
import com.minelittlepony.unicopia.block.SegmentedCropBlock;
import com.minelittlepony.unicopia.block.ShellsBlock;
import com.minelittlepony.unicopia.block.SlimePustuleBlock;
import com.minelittlepony.unicopia.block.UBlocks;
import com.minelittlepony.unicopia.datagen.Datagen;
import com.minelittlepony.unicopia.datagen.providers.UModelProvider;
import com.minelittlepony.unicopia.item.UItems;
import com.minelittlepony.unicopia.server.world.Tree;
@ -9,22 +19,44 @@ import com.minelittlepony.unicopia.server.world.UTreeGen;
import net.fabricmc.fabric.api.datagen.v1.FabricDataOutput;
import net.fabricmc.fabric.api.datagen.v1.provider.FabricBlockLootTableProvider;
import net.fabricmc.fabric.api.resource.conditions.v1.DefaultResourceConditions;
import net.minecraft.block.BedBlock;
import net.minecraft.block.Block;
import net.minecraft.block.Blocks;
import net.minecraft.block.CarrotsBlock;
import net.minecraft.block.SlabBlock;
import net.minecraft.block.enums.BedPart;
import net.minecraft.block.enums.BlockHalf;
import net.minecraft.block.enums.SlabType;
import net.minecraft.enchantment.Enchantments;
import net.minecraft.item.Item;
import net.minecraft.item.ItemConvertible;
import net.minecraft.item.Items;
import net.minecraft.loot.LootPool;
import net.minecraft.loot.LootTable;
import net.minecraft.loot.condition.BlockStatePropertyLootCondition;
import net.minecraft.loot.condition.LootConditionConsumingBuilder;
import net.minecraft.loot.condition.RandomChanceLootCondition;
import net.minecraft.loot.condition.TableBonusLootCondition;
import net.minecraft.loot.entry.ItemEntry;
import net.minecraft.loot.function.ApplyBonusLootFunction;
import net.minecraft.loot.function.ConditionalLootFunction;
import net.minecraft.loot.function.SetCountLootFunction;
import net.minecraft.loot.provider.number.ConstantLootNumberProvider;
import net.minecraft.loot.provider.number.LootNumberProvider;
import net.minecraft.loot.provider.number.UniformLootNumberProvider;
import net.minecraft.predicate.StatePredicate;
import net.minecraft.state.property.BooleanProperty;
import net.minecraft.state.property.IntProperty;
import net.minecraft.state.property.Properties;
import net.minecraft.state.property.Property;
import net.minecraft.util.Identifier;
import net.minecraft.util.StringIdentifiable;
public class UBlockLootTableProvider extends FabricBlockLootTableProvider {
private static final ConditionalLootFunction.Builder<?> FORTUNE_BONUS = ApplyBonusLootFunction.binomialWithBonusCount(Enchantments.FORTUNE, 0.5714286F, 3);
public UBlockLootTableProvider(FabricDataOutput output) {
super(output);
}
@ -63,13 +95,22 @@ public class UBlockLootTableProvider extends FabricBlockLootTableProvider {
UBlocks.CHISELLED_CHITIN_SLAB, UBlocks.CLOUD_BRICK_SLAB,
UBlocks.CLOUD_PLANK_SLAB, UBlocks.PALM_SLAB, UBlocks.ZAP_SLAB, UBlocks.WAXED_ZAP_SLAB
).forEach(slab -> addDrop(slab, this::slabDrops));
addDrop(UBlocks.CLOUD_SLAB, slab -> decomposingSlabDrops(slab, UItems.CLOUD_LUMP, 2));
addDrop(UBlocks.SOGGY_CLOUD_SLAB, slab -> decomposingSlabDrops(slab, UItems.CLOUD_LUMP, 2));
addDrop(UBlocks.DENSE_CLOUD_SLAB, slab -> decomposingSlabDrops(slab, UItems.CLOUD_LUMP, 4));
addDrop(UBlocks.ETCHED_CLOUD_SLAB, slab -> decomposingSlabDrops(slab, UItems.CLOUD_LUMP, 4));
// fruit
UModelProvider.FRUITS.forEach((block, drop) -> {
if (block != UBlocks.GOLDEN_APPLE) {
addDrop(block, drop);
addDrop(block, fortuneBonusDrops(drop));
}
});
addDrop(UBlocks.GOLDEN_APPLE, LootTable.builder().pool(LootPool.builder()
.rolls(exactly(1))
.with(applyStateCondition(UBlocks.GOLDEN_APPLE, EnchantedFruitBlock.ENCHANTED, false, applyExplosionDecay(UBlocks.GOLDEN_APPLE, ItemEntry.builder(Items.GOLDEN_APPLE))).apply(FORTUNE_BONUS))
.with(applyStateCondition(UBlocks.GOLDEN_APPLE, EnchantedFruitBlock.ENCHANTED, true, applyExplosionDecay(UBlocks.GOLDEN_APPLE, ItemEntry.builder(Items.ENCHANTED_GOLDEN_APPLE))).apply(FORTUNE_BONUS))
));
List.of(UBlocks.GREEN_APPLE_LEAVES, UBlocks.SOUR_APPLE_LEAVES, UBlocks.SWEET_APPLE_LEAVES, UBlocks.GOLDEN_OAK_LEAVES).forEach(block -> addDrop(block, this::fruitLeavesDrops));
addDrop(UBlocks.MANGO_LEAVES, block -> leavesDrops(block, UTreeGen.MANGO_TREE.sapling().get(), 0.025F, 0.027777778F, 0.03125F, 0.041666668F, 0.1F)); // same chance as jungle
addDrop(UBlocks.ZAP_LEAVES, block -> leavesDrops(block, UTreeGen.ZAP_APPLE_TREE.sapling().get(), SAPLING_DROP_CHANCE));
@ -97,43 +138,197 @@ public class UBlockLootTableProvider extends FabricBlockLootTableProvider {
UBlocks.CLOUD_BED, UBlocks.CLOTH_BED
).forEach(bed -> addDrop(bed, b -> dropsWithProperty(b, BedBlock.PART, BedPart.HEAD)));
addDrop(UBlocks.CHITIN_SPIKES, drops(UBlocks.CHITIN_SPIKES, UItems.CARAPACE, ConstantLootNumberProvider.create(6)));
addDrop(UBlocks.CHITIN, drops(UBlocks.CHITIN, UItems.CARAPACE, ConstantLootNumberProvider.create(9)));
addDrop(UBlocks.SURFACE_CHITIN, drops(UBlocks.SURFACE_CHITIN, UItems.CARAPACE, ConstantLootNumberProvider.create(9)));
addDrop(UBlocks.CHITIN_SPIKES, drops(UBlocks.CHITIN_SPIKES, UItems.CARAPACE, exactly(6)));
addDrop(UBlocks.CHITIN, drops(UBlocks.CHITIN, UItems.CARAPACE, exactly(9)));
addDrop(UBlocks.SURFACE_CHITIN, drops(UBlocks.SURFACE_CHITIN, UItems.CARAPACE, exactly(9)));
addDrop(UBlocks.CHISELLED_CHITIN_HULL, hullDrops(UBlocks.CHISELLED_CHITIN_HULL, UBlocks.CHITIN, UBlocks.CHISELLED_CHITIN));
addDrop(UBlocks.CLOUD, drops(UBlocks.CLOUD, UItems.CLOUD_LUMP, ConstantLootNumberProvider.create(4)));
addDrop(UBlocks.CLOUD_STAIRS, drops(UBlocks.CLOUD_STAIRS, UItems.CLOUD_LUMP, ConstantLootNumberProvider.create(6)));
addDrop(UBlocks.SLIME_PUSTULE, LootTable.builder()
.pool(applyStateCondition(UBlocks.SLIME_PUSTULE, SlimePustuleBlock.SHAPE, SlimePustuleBlock.Shape.POD,
addSurvivesExplosionCondition(UBlocks.SLIME_PUSTULE, LootPool.builder()
.rolls(exactly(1))
.with(ItemEntry.builder(UBlocks.SLIME_PUSTULE)).conditionally(WITH_SILK_TOUCH_OR_SHEARS))
)));
addDrop(UBlocks.MYSTERIOUS_EGG, LootTable.builder()
.pool(addSurvivesExplosionCondition(UBlocks.MYSTERIOUS_EGG, LootPool.builder()
.rolls(exactly(1))
.with(ItemEntry.builder(UBlocks.MYSTERIOUS_EGG))
.apply(PileBlock.COUNT.getValues(), count -> applyStateCondition(UBlocks.MYSTERIOUS_EGG, PileBlock.COUNT, count, SetCountLootFunction.builder(exactly(count)))))));
addDrop(UBlocks.SOGGY_CLOUD, drops(UBlocks.CLOUD, UItems.CLOUD_LUMP, ConstantLootNumberProvider.create(4)));
addDrop(UBlocks.SOGGY_CLOUD_STAIRS, drops(UBlocks.CLOUD_STAIRS, UItems.CLOUD_LUMP, ConstantLootNumberProvider.create(6)));
addDrop(UBlocks.CLOUD, drops(UBlocks.CLOUD, UItems.CLOUD_LUMP, exactly(4)));
addDrop(UBlocks.CLOUD_STAIRS, drops(UBlocks.CLOUD_STAIRS, UItems.CLOUD_LUMP, exactly(6)));
addDrop(UBlocks.DENSE_CLOUD, drops(UBlocks.DENSE_CLOUD, UItems.CLOUD_LUMP, ConstantLootNumberProvider.create(9)));
addDrop(UBlocks.DENSE_CLOUD_STAIRS, drops(UBlocks.DENSE_CLOUD_STAIRS, UItems.CLOUD_LUMP, ConstantLootNumberProvider.create(13)));
addDrop(UBlocks.ETCHED_CLOUD, drops(UBlocks.ETCHED_CLOUD, UItems.CLOUD_LUMP, ConstantLootNumberProvider.create(9)));
addDrop(UBlocks.ETCHED_CLOUD_STAIRS, drops(UBlocks.ETCHED_CLOUD_STAIRS, UItems.CLOUD_LUMP, ConstantLootNumberProvider.create(13)));
addDrop(UBlocks.SOGGY_CLOUD, drops(UBlocks.CLOUD, UItems.CLOUD_LUMP, exactly(4)));
addDrop(UBlocks.SOGGY_CLOUD_STAIRS, drops(UBlocks.CLOUD_STAIRS, UItems.CLOUD_LUMP, exactly(6)));
addDrop(UBlocks.DENSE_CLOUD, drops(UBlocks.DENSE_CLOUD, UItems.CLOUD_LUMP, exactly(9)));
addDrop(UBlocks.DENSE_CLOUD_STAIRS, drops(UBlocks.DENSE_CLOUD_STAIRS, UItems.CLOUD_LUMP, exactly(13)));
addDrop(UBlocks.ETCHED_CLOUD, drops(UBlocks.ETCHED_CLOUD, UItems.CLOUD_LUMP, exactly(9)));
addDrop(UBlocks.ETCHED_CLOUD_STAIRS, drops(UBlocks.ETCHED_CLOUD_STAIRS, UItems.CLOUD_LUMP, exactly(13)));
// recipe produces: 6 blocks -> 3 pillars means: 6/3 = 2
addDrop(UBlocks.CLOUD_PILLAR, drops(UBlocks.CLOUD_PILLAR, UBlocks.CLOUD, ConstantLootNumberProvider.create(2)));
addDrop(UBlocks.CLOUD_PILLAR, drops(UBlocks.CLOUD_PILLAR, UBlocks.CLOUD, exactly(2)));
addDrop(UBlocks.FROSTED_OBSIDIAN, Blocks.OBSIDIAN);
addDrop(UBlocks.APPLE_PIE, pieDrops(UBlocks.APPLE_PIE, UItems.APPLE_PIE, UItems.APPLE_PIE_HOOF));
// crops
addTallCropDrops(UBlocks.OATS, UItems.OATS);
addDrop(UBlocks.BANANAS, LootTable.builder()
.pool(addSurvivesExplosionCondition(UBlocks.BANANAS, LootPool.builder()
.rolls(exactly(1))
.with(item(UItems.BANANA, between(6, 12F)).apply(FORTUNE_BONUS))
)));
addDrop(UBlocks.PINEAPPLE, LootTable.builder()
.pool(addSurvivesExplosionCondition(UBlocks.PINEAPPLE, LootPool.builder()
.rolls(exactly(1))
.with(item(UItems.PINEAPPLE, between(6, 12F))
.apply(FORTUNE_BONUS)
.conditionally(BlockStatePropertyLootCondition.builder(UBlocks.PINEAPPLE).properties(StatePredicate.Builder.create()
.exactMatch(Properties.BLOCK_HALF, BlockHalf.TOP)
.exactMatch(Properties.AGE_7, Properties.AGE_7_MAX))))
)));
addDrop(UBlocks.ROCKS, applyExplosionDecay(UBlocks.ROCKS, LootTable.builder()
.pool(applyStateCondition(UBlocks.ROCKS, Properties.AGE_7, Properties.AGE_7_MAX, LootPool.builder()
.rolls(exactly(1))
.with(ItemEntry.builder(UItems.WEIRD_ROCK).conditionally(RandomChanceLootCondition.builder(0.25F)).apply(FORTUNE_BONUS))
.with(ItemEntry.builder(UItems.ROCK).apply(FORTUNE_BONUS))))
.pool(LootPool.builder()
.rolls(exactly(1))
.with(ItemEntry.builder(UItems.PEBBLES)))
));
addDrop(UBlocks.GOLD_ROOT, applyExplosionDecay(UBlocks.GOLD_ROOT, LootTable.builder()
.pool(LootPool.builder().with(ItemEntry.builder(Items.GOLDEN_CARROT)))
.pool(applyStateCondition(UBlocks.GOLD_ROOT, CarrotsBlock.AGE, 7, LootPool.builder())
.with(ItemEntry.builder(Items.GOLDEN_CARROT).apply(FORTUNE_BONUS)))));
addDrop(UBlocks.PLUNDER_VINE, applyExplosionDecay(UBlocks.PLUNDER_VINE, LootTable.builder()
.pool(LootPool.builder().rolls(exactly(4))
.with(ItemEntry.builder(Items.STICK))
.with(ItemEntry.builder(Items.DEAD_BUSH)))
.pool(LootPool.builder().rolls(exactly(1))
.with(ItemEntry.builder(Items.STICK))
.with(ItemEntry.builder(Items.DEAD_BUSH))
.with(ItemEntry.builder(UItems.GRYPHON_FEATHER)))
));
// hay
addDrop(UBlocks.HAY_BLOCK, b -> edibleBlockDrops(b, Items.WHEAT));
// shells
addDrop(UBlocks.CLAM_SHELL, shellDrops(UBlocks.CLAM_SHELL, UItems.CLAM_SHELL));
addDrop(UBlocks.SCALLOP_SHELL, shellDrops(UBlocks.SCALLOP_SHELL, UItems.SCALLOP_SHELL));
addDrop(UBlocks.TURRET_SHELL, shellDrops(UBlocks.TURRET_SHELL, UItems.TURRET_SHELL));
var farmersDelightGenerator = withConditions(DefaultResourceConditions.allModsLoaded("farmersdelight"));
farmersDelightGenerator.addDrop(Datagen.getOrCreateBaleBlock(Unicopia.id("rice_block")), b -> edibleBlockDrops(b, Datagen.getOrCreateItem(new Identifier("farmersdelight", "rice_panicle"))));
farmersDelightGenerator.addDrop(Datagen.getOrCreateBaleBlock(Unicopia.id("straw_block")), b -> edibleBlockDrops(b, Datagen.getOrCreateItem(new Identifier("farmersdelight", "straw"))));
}
private void addTallCropDrops(SegmentedCropBlock baseCrop, ItemConvertible crop) {
addDrop(baseCrop, applyExplosionDecay(baseCrop, LootTable.builder()
.pool(LootPool.builder()
.rolls(exactly(1))
.with(ItemEntry.builder(baseCrop.getSeedsItem()))))
.pool(applyStateCondition(baseCrop, baseCrop.getAgeProperty(), baseCrop.getMaxAge(), LootPool.builder()
.rolls(exactly(1))
.with(ItemEntry.builder(baseCrop.getSeedsItem()).apply(FORTUNE_BONUS)))));
SegmentedCropBlock stage = baseCrop;
while ((stage = stage.getNext()) != null) {
addDrop(stage, applyExplosionDecay(stage, LootTable.builder()
.pool(LootPool.builder()
.rolls(exactly(1))
.with(applyStateCondition(stage, stage.getAgeProperty(), stage.getMaxAge(), ItemEntry.builder(crop))))));
}
}
private LootTable.Builder decomposingSlabDrops(Block slab, ItemConvertible drop, int count) {
return LootTable.builder()
.pool(applyExplosionDecay(slab, LootPool.builder()
.rolls(exactly(1))
.with(item(drop, exactly(count))
.apply(applyStateCondition(slab, SlabBlock.TYPE, SlabType.DOUBLE, SetCountLootFunction.builder(exactly(count * 2)))))));
}
private LootTable.Builder fruitLeavesDrops(Block leaves) {
return LootTable.builder()
.pool(LootPool.builder()
.rolls(ConstantLootNumberProvider.create(1))
.with(ItemEntry.builder(leaves).conditionally(WITH_SILK_TOUCH_OR_SHEARS))
)
.pool(LootPool.builder()
.rolls(ConstantLootNumberProvider.create(1))
.conditionally(WITHOUT_SILK_TOUCH_NOR_SHEARS)
.with(
applyExplosionDecay(leaves, ItemEntry.builder(Items.STICK)
.apply(SetCountLootFunction.builder(UniformLootNumberProvider.create(1, 2)))
)
.conditionally(TableBonusLootCondition.builder(Enchantments.FORTUNE, LEAVES_STICK_DROP_CHANCE))
)
);
.rolls(exactly(1))
.with(ItemEntry.builder(leaves).conditionally(WITH_SILK_TOUCH_OR_SHEARS)))
.pool(applyExplosionDecay(leaves, LootPool.builder()
.rolls(exactly(1))
.conditionally(WITHOUT_SILK_TOUCH_NOR_SHEARS)
.with(item(Items.STICK, between(1, 2)).conditionally(TableBonusLootCondition.builder(Enchantments.FORTUNE, LEAVES_STICK_DROP_CHANCE)))));
}
private LootTable.Builder hullDrops(Block hull, ItemConvertible inner, ItemConvertible outer) {
return LootTable.builder()
.pool(addSurvivesExplosionCondition(hull, LootPool.builder()
.rolls(exactly(1))
.with(item(hull, exactly(2)).conditionally(WITHOUT_SILK_TOUCH))
.with(item(inner, exactly(2)).conditionally(WITHOUT_SILK_TOUCH))
.with(item(outer, exactly(2)).conditionally(WITH_SILK_TOUCH))));
}
private LootTable.Builder edibleBlockDrops(Block block, ItemConvertible drop) {
LootTable.Builder builder = LootTable.builder();
for (BooleanProperty segment : EdibleBlock.SEGMENTS) {
builder
.pool(addSurvivesExplosionCondition(block, LootPool.builder()
.rolls(exactly(1))
.with(applyStateCondition(block, segment, true, ItemEntry.builder(drop)))));
}
return builder;
}
private LootTable.Builder pieDrops(Block block, Item drop, Item stomped) {
return LootTable.builder()
.pool(applyExplosionDecay(block, LootPool.builder()
.rolls(exactly(1)).conditionally(WITH_SILK_TOUCH)
.with(applyStateCondition(block, PieBlock.STOMPED, false, ItemEntry.builder(drop)))
.with(applyStateCondition(block, PieBlock.STOMPED, true, ItemEntry.builder(stomped)))));
}
private LootTable.Builder shellDrops(Block block, Item shell) {
return LootTable.builder()
.pool(applyExplosionDecay(block, LootPool.builder()
.rolls(exactly(1))
.with(ItemEntry.builder(shell))
.apply(ShellsBlock.COUNT.getValues(), count -> applyStateCondition(block, ShellsBlock.COUNT, count, SetCountLootFunction.builder(exactly(count))))
.apply(FORTUNE_BONUS)));
}
public LootTable.Builder fortuneBonusDrops(ItemConvertible drop) {
return LootTable.builder().pool(addSurvivesExplosionCondition(drop, LootPool.builder()
.rolls(exactly(1))
.with(ItemEntry.builder(drop).apply(FORTUNE_BONUS))));
}
public static ConstantLootNumberProvider exactly(float n) {
return ConstantLootNumberProvider.create(n);
}
public static UniformLootNumberProvider between(float from, float to) {
return UniformLootNumberProvider.create(from, to);
}
public static ItemEntry.Builder<?> item(ItemConvertible item, LootNumberProvider count) {
return ItemEntry.builder(item).apply(SetCountLootFunction.builder(count));
}
public static <T extends LootConditionConsumingBuilder<T>, P extends Comparable<P> & StringIdentifiable> T applyStateCondition(Block block,
Property<P> property, P value, LootConditionConsumingBuilder<T> builder) {
return builder.conditionally(BlockStatePropertyLootCondition.builder(block).properties(StatePredicate.Builder.create().exactMatch(property, value)));
}
public static <T extends LootConditionConsumingBuilder<T>> T applyStateCondition(Block block,
BooleanProperty property, boolean value, LootConditionConsumingBuilder<T> builder) {
return builder.conditionally(BlockStatePropertyLootCondition.builder(block).properties(StatePredicate.Builder.create().exactMatch(property, value)));
}
public static <T extends LootConditionConsumingBuilder<T>> T applyStateCondition(Block block,
IntProperty property, int value, LootConditionConsumingBuilder<T> builder) {
return builder.conditionally(BlockStatePropertyLootCondition.builder(block).properties(StatePredicate.Builder.create().exactMatch(property, value)));
}
}

View file

@ -2,6 +2,7 @@ package com.minelittlepony.unicopia.datagen.providers.loot;
import java.util.function.BiConsumer;
import com.minelittlepony.unicopia.UConventionalTags;
import com.minelittlepony.unicopia.UTags;
import com.minelittlepony.unicopia.item.UItems;
@ -24,6 +25,10 @@ public class UChestAdditionsLootTableProvider extends SimpleFabricLootTableProvi
super(dataOutput, LootContextTypes.CHEST);
}
@Override
public String getName() {
return super.getName() + " Additions";
}
@Override
public void accept(BiConsumer<Identifier, Builder> exporter) {
@ -39,7 +44,7 @@ public class UChestAdditionsLootTableProvider extends SimpleFabricLootTableProvi
.rolls(UniformLootNumberProvider.create(2, 4))
.with(ItemEntry.builder(UItems.GRYPHON_FEATHER).weight(10).apply(SetCountLootFunction.builder(UniformLootNumberProvider.create(1, 7))))
.with(ItemEntry.builder(UItems.GOLDEN_WING).weight(1).apply(SetCountLootFunction.builder(UniformLootNumberProvider.create(1, 2))))
.with(TagEntry.expandBuilder(UTags.FRESH_APPLES).weight(1).apply(SetCountLootFunction.builder(UniformLootNumberProvider.create(2, 5))))
.with(TagEntry.expandBuilder(UTags.Items.FRESH_APPLES).weight(1).apply(SetCountLootFunction.builder(UniformLootNumberProvider.create(2, 5))))
));
exporter.accept(LootTables.VILLAGE_FLETCHER_CHEST, LootTable.builder().pool(LootPool.builder()
.rolls(UniformLootNumberProvider.create(2, 4))
@ -48,37 +53,42 @@ public class UChestAdditionsLootTableProvider extends SimpleFabricLootTableProvi
));
exporter.accept(LootTables.VILLAGE_PLAINS_CHEST, LootTable.builder().pool(LootPool.builder()
.rolls(UniformLootNumberProvider.create(3, 4))
.with(TagEntry.expandBuilder(UTags.FRESH_APPLES).weight(1))
.with(TagEntry.expandBuilder(UTags.APPLE_SEEDS).weight(1))
.with(TagEntry.expandBuilder(UTags.Items.FRESH_APPLES).weight(1))
.with(TagEntry.expandBuilder(UTags.Items.APPLE_SEEDS).weight(1))
));
exporter.accept(LootTables.ANCIENT_CITY_CHEST, LootTable.builder().pool(LootPool.builder()
.rolls(UniformLootNumberProvider.create(0, 1))
.with(ItemEntry.builder(UItems.GROGARS_BELL).weight(1))
));
exporter.accept(LootTables.BURIED_TREASURE_CHEST, LootTable.builder().pool(LootPool.builder()
.rolls(UniformLootNumberProvider.create(1, 4))
.with(ItemEntry.builder(UItems.PEARL_NECKLACE).weight(1))
.with(TagEntry.expandBuilder(UTags.item("food_types/shells")).weight(3))
.with(TagEntry.expandBuilder(UTags.Items.SHELLS).weight(3))
));
exporter.accept(LootTables.SHIPWRECK_SUPPLY_CHEST, LootTable.builder().pool(LootPool.builder()
.rolls(UniformLootNumberProvider.create(1, 6))
.with(TagEntry.expandBuilder(UTags.SHELLS).weight(3))
.with(TagEntry.expandBuilder(UTags.Items.SHELLS).weight(3))
.with(TagEntry.expandBuilder(UConventionalTags.Items.ROTTEN_FISH).weight(1))
));
exporter.accept(LootTables.SHIPWRECK_TREASURE_CHEST, LootTable.builder().pool(LootPool.builder()
.rolls(UniformLootNumberProvider.create(1, 4))
.with(ItemEntry.builder(UItems.PEARL_NECKLACE).weight(1))
.with(TagEntry.expandBuilder(UTags.SHELLS).weight(3))
.with(TagEntry.expandBuilder(UTags.Items.SHELLS).weight(3))
.with(TagEntry.expandBuilder(UConventionalTags.Items.ROTTEN_FISH).weight(1))
));
exporter.accept(LootTables.UNDERWATER_RUIN_BIG_CHEST, LootTable.builder().pool(LootPool.builder()
.rolls(UniformLootNumberProvider.create(1, 2))
.with(ItemEntry.builder(UItems.PEARL_NECKLACE).weight(1))
.with(ItemEntry.builder(UItems.SHELLY).weight(4))
.with(TagEntry.expandBuilder(UTags.SHELLS).weight(8))
.with(TagEntry.expandBuilder(UTags.Items.SHELLS).weight(8))
.with(TagEntry.expandBuilder(UConventionalTags.Items.ROTTEN_FISH).weight(1))
));
exporter.accept(LootTables.UNDERWATER_RUIN_SMALL_CHEST, LootTable.builder().pool(LootPool.builder()
.rolls(UniformLootNumberProvider.create(1, 4))
.with(TagEntry.expandBuilder(UTags.SHELLS).weight(1))
.with(TagEntry.expandBuilder(UTags.Items.SHELLS).weight(1))
.with(TagEntry.expandBuilder(UConventionalTags.Items.ROTTEN_FISH).weight(1))
));
exporter.accept(LootTables.DESERT_WELL_ARCHAEOLOGY, LootTable.builder().pool(LootPool.builder()
@ -89,7 +99,7 @@ public class UChestAdditionsLootTableProvider extends SimpleFabricLootTableProvi
.with(ItemEntry.builder(UItems.ROCK_STEW).weight(1))
.with(ItemEntry.builder(UItems.PEBBLES).weight(1))
.with(ItemEntry.builder(UItems.SHELLY).weight(1))
.with(TagEntry.expandBuilder(UTags.SHELLS).weight(1))
.with(TagEntry.expandBuilder(UTags.Items.SHELLS).weight(1))
.with(ItemEntry.builder(UItems.PEARL_NECKLACE).weight(1))
));
exporter.accept(LootTables.TRAIL_RUINS_COMMON_ARCHAEOLOGY, LootTable.builder().pool(LootPool.builder()
@ -106,19 +116,22 @@ public class UChestAdditionsLootTableProvider extends SimpleFabricLootTableProvi
));
exporter.accept(LootTables.OCEAN_RUIN_WARM_ARCHAEOLOGY, LootTable.builder().pool(LootPool.builder()
.rolls(UniformLootNumberProvider.create(1, 4))
.with(TagEntry.expandBuilder(UTags.SHELLS).weight(1))
.with(TagEntry.expandBuilder(UTags.Items.SHELLS).weight(1))
.with(ItemEntry.builder(UItems.PEARL_NECKLACE).weight(1))
.with(TagEntry.expandBuilder(UConventionalTags.Items.ROTTEN_FISH).weight(1))
));
exporter.accept(LootTables.FISHING_GAMEPLAY, LootTable.builder().pool(LootPool.builder()
.rolls(UniformLootNumberProvider.create(1, 4))
.with(TagEntry.expandBuilder(UTags.SHELLS).weight(2))
.with(TagEntry.expandBuilder(UTags.Items.SHELLS).weight(2))
.with(TagEntry.expandBuilder(UConventionalTags.Items.ROTTEN_FISH).weight(1))
));
exporter.accept(LootTables.FISHING_JUNK_GAMEPLAY, LootTable.builder().pool(LootPool.builder()
.rolls(UniformLootNumberProvider.create(1, 4))
.with(ItemEntry.builder(UItems.BROKEN_SUNGLASSES).weight(2))
.with(ItemEntry.builder(UItems.WHEAT_WORMS).weight(2))
.with(TagEntry.expandBuilder(UConventionalTags.Items.ROTTEN_FISH).weight(1))
.with(ItemEntry.builder(UItems.BOTCHED_GEM).weight(4))
));

View file

@ -0,0 +1,56 @@
package com.minelittlepony.unicopia.datagen.providers.loot;
import java.util.function.BiConsumer;
import com.minelittlepony.unicopia.Unicopia;
import com.minelittlepony.unicopia.entity.effect.UPotions;
import net.fabricmc.fabric.api.datagen.v1.FabricDataOutput;
import net.fabricmc.fabric.api.datagen.v1.provider.SimpleFabricLootTableProvider;
import net.minecraft.item.Items;
import net.minecraft.loot.LootPool;
import net.minecraft.loot.LootTable;
import net.minecraft.loot.LootTable.Builder;
import net.minecraft.loot.context.LootContextTypes;
import net.minecraft.loot.entry.ItemEntry;
import net.minecraft.loot.function.SetCountLootFunction;
import net.minecraft.loot.function.SetPotionLootFunction;
import net.minecraft.loot.provider.number.ConstantLootNumberProvider;
import net.minecraft.loot.provider.number.UniformLootNumberProvider;
import net.minecraft.potion.Potion;
import net.minecraft.util.Identifier;
public class UChestLootTableProvider extends SimpleFabricLootTableProvider {
public UChestLootTableProvider(FabricDataOutput output) {
super(output, LootContextTypes.CHEST);
}
@Override
public void accept(BiConsumer<Identifier, Builder> exporter) {
exporter.accept(Unicopia.id("chests/changeling_hive_trap"), LootTable.builder()
.pool(LootPool.builder()
.rolls(ConstantLootNumberProvider.create(6))
.with(createTippedArrowEntry(UPotions.MORPH_EARTH_PONY.shortEffect(), 3))
.with(createTippedArrowEntry(UPotions.MORPH_UNICORN.shortEffect(), 1))
.with(createTippedArrowEntry(UPotions.MORPH_PEGASUS.shortEffect(), 1))
.with(createTippedArrowEntry(UPotions.MORPH_BAT.shortEffect(), 1))
.with(createTippedArrowEntry(UPotions.MORPH_KIRIN.shortEffect(), 1))
.with(createTippedArrowEntry(UPotions.MORPH_HIPPOGRIFF.shortEffect(), 1))
.with(createTippedArrowEntry(UPotions.MORPH_EARTH_PONY.longEffect(), 5))
.with(createTippedArrowEntry(UPotions.MORPH_UNICORN.longEffect(), 2))
.with(createTippedArrowEntry(UPotions.MORPH_PEGASUS.longEffect(), 2))
.with(createTippedArrowEntry(UPotions.MORPH_BAT.longEffect(), 2))
.with(createTippedArrowEntry(UPotions.MORPH_KIRIN.longEffect(), 2))
.with(createTippedArrowEntry(UPotions.MORPH_HIPPOGRIFF.longEffect(), 2))
));
}
private static ItemEntry.Builder<?> createTippedArrowEntry(Potion potion, int weight) {
return ItemEntry.builder(Items.TIPPED_ARROW)
.weight(weight)
.apply(SetPotionLootFunction.builder(potion))
.apply(SetCountLootFunction.builder(UniformLootNumberProvider.create(3, 9)));
}
}

View file

@ -0,0 +1,63 @@
package com.minelittlepony.unicopia.datagen.providers.loot;
import java.util.function.BiConsumer;
import com.minelittlepony.unicopia.UTags;
import com.minelittlepony.unicopia.entity.mob.UEntities;
import com.minelittlepony.unicopia.item.UItems;
import net.fabricmc.fabric.api.datagen.v1.FabricDataOutput;
import net.fabricmc.fabric.api.datagen.v1.provider.SimpleFabricLootTableProvider;
import net.minecraft.entity.EntityType;
import net.minecraft.loot.LootPool;
import net.minecraft.loot.LootTable;
import net.minecraft.loot.LootTable.Builder;
import net.minecraft.loot.condition.RandomChanceLootCondition;
import net.minecraft.loot.context.LootContextTypes;
import net.minecraft.loot.entry.ItemEntry;
import net.minecraft.loot.entry.TagEntry;
import net.minecraft.loot.function.LootingEnchantLootFunction;
import net.minecraft.loot.function.SetCountLootFunction;
import net.minecraft.loot.provider.number.ConstantLootNumberProvider;
import net.minecraft.loot.provider.number.UniformLootNumberProvider;
import net.minecraft.util.Identifier;
public class UEntityLootTableProvider extends SimpleFabricLootTableProvider {
public UEntityLootTableProvider(FabricDataOutput output) {
super(output, LootContextTypes.ENTITY);
}
@Override
public void accept(BiConsumer<Identifier, Builder> exporter) {
generate((type, builder) -> exporter.accept(EntityType.getId(type).withPrefixedPath("entities/"), builder));
}
protected void generate(BiConsumer<EntityType<?>, Builder> exporter) {
exporter.accept(UEntities.BUTTERFLY, LootTable.builder()
.pool(LootPool.builder()
.rolls(ConstantLootNumberProvider.create(1))
.with(ItemEntry.builder(UItems.BUTTERFLY)
.apply(LootingEnchantLootFunction.builder(UniformLootNumberProvider.create(0, 1))))));
exporter.accept(UEntities.STORM_CLOUD, LootTable.builder()
.pool(LootPool.builder()
.rolls(ConstantLootNumberProvider.create(1))
.with(ItemEntry.builder(UItems.CLOUD_LUMP)
.apply(SetCountLootFunction.builder(UniformLootNumberProvider.create(6, 12)))
.apply(LootingEnchantLootFunction.builder(UniformLootNumberProvider.create(0, 1))))));
exporter.accept(UEntities.LOOT_BUG, LootTable.builder()
.pool(LootPool.builder()
.rolls(ConstantLootNumberProvider.create(1))
.with(TagEntry.builder(UTags.Items.LOOT_BUG_COMMON_DROPS)
.apply(SetCountLootFunction.builder(UniformLootNumberProvider.create(6, 12)))
.apply(LootingEnchantLootFunction.builder(UniformLootNumberProvider.create(0, 3))))
.with(TagEntry.builder(UTags.Items.LOOT_BUG_RARE_DROPS)
.conditionally(RandomChanceLootCondition.builder(0.25F))
.apply(SetCountLootFunction.builder(UniformLootNumberProvider.create(1, 3)))
.apply(LootingEnchantLootFunction.builder(UniformLootNumberProvider.create(0, 6))))
.with(TagEntry.builder(UTags.Items.LOOT_BUG_EPIC_DROPS)
.conditionally(RandomChanceLootCondition.builder(0.1F))
.apply(SetCountLootFunction.builder(ConstantLootNumberProvider.create(1)))
.apply(LootingEnchantLootFunction.builder(UniformLootNumberProvider.create(0, 2))))
));
}
}

View file

@ -73,7 +73,7 @@ public class BedSheetPatternRecipeBuilder {
private static void offerBedSheetConversionRecipe(Consumer<RecipeJsonProvider> exporter, ItemConvertible output, Stream<ItemConvertible> wools) {
var builder = ShapelessRecipeJsonBuilder.create(RecipeCategory.DECORATIONS, output)
.input(UTags.WOOL_BED_SHEETS).criterion("has_bed_sheet", RecipeProvider.conditionsFromTag(UTags.WOOL_BED_SHEETS));
.input(UTags.Items.WOOL_BED_SHEETS).criterion("has_bed_sheet", RecipeProvider.conditionsFromTag(UTags.Items.WOOL_BED_SHEETS));
wools.forEach(builder::input);
builder
.group("bed_sheet")

View file

@ -4,7 +4,7 @@ import java.util.Map;
import java.util.NoSuchElementException;
import com.minelittlepony.unicopia.ability.magic.spell.effect.SpellType;
import com.minelittlepony.unicopia.item.URecipes;
import com.minelittlepony.unicopia.recipe.URecipes;
import com.mojang.datafixers.util.Either;
import net.fabricmc.fabric.api.tag.convention.v1.ConventionalItemTags;

View file

@ -7,7 +7,7 @@ import org.jetbrains.annotations.Nullable;
import org.spongepowered.include.com.google.common.base.Preconditions;
import com.google.gson.JsonObject;
import com.minelittlepony.unicopia.item.URecipes;
import com.minelittlepony.unicopia.recipe.URecipes;
import com.mojang.serialization.JsonOps;
import net.minecraft.advancement.Advancement;

View file

@ -15,7 +15,8 @@ import com.minelittlepony.unicopia.ability.magic.spell.effect.SpellType;
import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits;
import com.minelittlepony.unicopia.advancement.TraitDiscoveredCriterion;
import com.minelittlepony.unicopia.item.UItems;
import com.minelittlepony.unicopia.item.URecipes;
import com.minelittlepony.unicopia.recipe.URecipes;
import net.minecraft.advancement.Advancement;
import net.minecraft.advancement.AdvancementRewards;
import net.minecraft.advancement.CriterionMerger;

View file

@ -8,7 +8,7 @@ import org.spongepowered.include.com.google.common.base.Preconditions;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.minelittlepony.unicopia.item.URecipes;
import com.minelittlepony.unicopia.recipe.URecipes;
import net.minecraft.advancement.Advancement;
import net.minecraft.advancement.AdvancementRewards;

View file

@ -17,7 +17,7 @@ import com.minelittlepony.unicopia.datagen.ItemFamilies;
import com.minelittlepony.unicopia.datagen.UBlockFamilies;
import com.minelittlepony.unicopia.datagen.providers.recipe.BedSheetPatternRecipeBuilder.PatternTemplate;
import com.minelittlepony.unicopia.item.UItems;
import com.minelittlepony.unicopia.item.URecipes;
import com.minelittlepony.unicopia.recipe.URecipes;
import com.minelittlepony.unicopia.server.world.UTreeGen;
import com.mojang.datafixers.util.Either;
@ -80,8 +80,19 @@ public class URecipeProvider extends FabricRecipeProvider {
}
private void generateVanillaRecipeExtensions(Consumer<RecipeJsonProvider> exporter) {
ShapelessRecipeJsonBuilder.create(RecipeCategory.MISC, Items.WRITABLE_BOOK).input(Items.BOOK).input(Items.INK_SAC).input(UTags.MAGIC_FEATHERS).criterion("has_book", conditionsFromItem(Items.BOOK)).offerTo(exporter);
ShapedRecipeJsonBuilder.create(RecipeCategory.COMBAT, Items.ARROW, 4).input('#', UConventionalTags.STICKS).input('X', Items.FLINT).input('Y', UTags.MAGIC_FEATHERS).pattern("X").pattern("#").pattern("Y").criterion("has_feather", conditionsFromTag(UTags.MAGIC_FEATHERS)).criterion("has_flint", conditionsFromItem(Items.FLINT)).offerTo(exporter);
ShapelessRecipeJsonBuilder.create(RecipeCategory.MISC, Items.WRITABLE_BOOK)
.input(Items.BOOK).criterion("has_book", conditionsFromItem(Items.BOOK))
.input(Items.INK_SAC)
.input(UTags.Items.MAGIC_FEATHERS)
.offerTo(exporter);
ShapedRecipeJsonBuilder.create(RecipeCategory.COMBAT, Items.ARROW, 4)
.input('#', UConventionalTags.Items.STICKS)
.input('X', Items.FLINT).criterion("has_flint", conditionsFromItem(Items.FLINT))
.input('Y', UTags.Items.MAGIC_FEATHERS).criterion("has_feather", conditionsFromTag(UTags.Items.MAGIC_FEATHERS))
.pattern("X")
.pattern("#")
.pattern("Y")
.offerTo(exporter);
}
private void offerJarRecipes(Consumer<RecipeJsonProvider> exporter) {
@ -97,7 +108,7 @@ public class URecipeProvider extends FabricRecipeProvider {
}
private void offerCloudRecipes(Consumer<RecipeJsonProvider> exporter) {
offerShapelessRecipe(exporter, UItems.CLOUD_LUMP, UTags.CLOUD_JARS, "cloud", 4);
offerShapelessRecipe(exporter, UItems.CLOUD_LUMP, UTags.Items.CLOUD_JARS, "cloud", 4);
generateFamily(exporter, UBlockFamilies.CLOUD);
offer2x3Recipe(exporter, UBlocks.CLOUD_PILLAR, UBlocks.CLOUD, "pillar");
offer2x2CompactingRecipe(exporter, RecipeCategory.BUILDING_BLOCKS, UBlocks.CLOUD, UItems.CLOUD_LUMP);
@ -200,7 +211,7 @@ public class URecipeProvider extends FabricRecipeProvider {
// magic staff
ShapedRecipeJsonBuilder.create(RecipeCategory.TOOLS, UItems.MAGIC_STAFF)
.input('*', UItems.GEMSTONE).criterion("has_gemstone", conditionsFromItem(UItems.GEMSTONE))
.input('#', UConventionalTags.STICKS).criterion("has_stick", conditionsFromTag(UConventionalTags.STICKS))
.input('#', UConventionalTags.Items.STICKS).criterion("has_stick", conditionsFromTag(UConventionalTags.Items.STICKS))
.pattern(" *")
.pattern(" # ")
.pattern("# ")
@ -217,7 +228,7 @@ public class URecipeProvider extends FabricRecipeProvider {
// pegasus amulet
ShapedRecipeJsonBuilder.create(RecipeCategory.MISC, UItems.GOLDEN_FEATHER)
.input('*', Items.GOLD_NUGGET).criterion("has_nugget", conditionsFromItem(Items.GOLD_NUGGET))
.input('#', UTags.MAGIC_FEATHERS).criterion("has_feather", conditionsFromTag(UTags.MAGIC_FEATHERS))
.input('#', UTags.Items.MAGIC_FEATHERS).criterion("has_feather", conditionsFromTag(UTags.Items.MAGIC_FEATHERS))
.pattern("***")
.pattern("*#*")
.pattern("***")
@ -232,7 +243,7 @@ public class URecipeProvider extends FabricRecipeProvider {
// friendship bracelet
ShapedRecipeJsonBuilder.create(RecipeCategory.TOOLS, UItems.FRIENDSHIP_BRACELET)
.input('*', Items.STRING)
.input('#', Items.LEATHER).criterion(hasItem(Items.LEATHER), conditionsFromTag(UTags.MAGIC_FEATHERS))
.input('#', Items.LEATHER).criterion(hasItem(Items.LEATHER), conditionsFromItem(Items.LEATHER))
.pattern("*#*")
.pattern("# #")
.pattern("*#*")
@ -242,7 +253,7 @@ public class URecipeProvider extends FabricRecipeProvider {
// meadowbrook's staff
ShapedRecipeJsonBuilder.create(RecipeCategory.TOOLS, UItems.MEADOWBROOKS_STAFF)
.input('*', UItems.GEMSTONE).criterion(hasItem(UItems.GEMSTONE), conditionsFromItem(UItems.GEMSTONE))
.input('/', UConventionalTags.STICKS).criterion(hasItem(Items.STICK), conditionsFromTag(UConventionalTags.STICKS))
.input('/', UConventionalTags.Items.STICKS).criterion(hasItem(Items.STICK), conditionsFromTag(UConventionalTags.Items.STICKS))
.pattern(" *")
.pattern(" / ")
.pattern("/ ")
@ -310,7 +321,7 @@ public class URecipeProvider extends FabricRecipeProvider {
offerShapelessRecipe(exporter, UItems.SOUR_APPLE_SEEDS, UItems.SOUR_APPLE, "seeds", 3);
offerShapelessRecipe(exporter, UItems.GREEN_APPLE_SEEDS, UItems.GREEN_APPLE, "seeds", 3);
offerShapelessRecipe(exporter, UItems.GOLDEN_OAK_SEEDS, Items.GOLDEN_APPLE, "seeds", 1);
offerPieRecipe(exporter, UItems.APPLE_PIE, UItems.APPLE_PIE_SLICE, Items.WHEAT, UTags.FRESH_APPLES);
offerPieRecipe(exporter, UItems.APPLE_PIE, UItems.APPLE_PIE_SLICE, Items.WHEAT, UTags.Items.FRESH_APPLES);
ShapelessRecipeJsonBuilder.create(RecipeCategory.FOOD, UItems.ROCK_STEW)
.input(UItems.ROCK, 3).criterion(hasItem(UItems.ROCK), conditionsFromItem(UItems.ROCK))
@ -344,20 +355,20 @@ public class URecipeProvider extends FabricRecipeProvider {
.pattern("###")
.offerTo(exporter, convertBetween(UItems.OATS, Items.WHEAT));
ShapelessRecipeJsonBuilder.create(RecipeCategory.FOOD, UItems.JUICE)
.input(Ingredient.fromTag(UTags.FRESH_APPLES), 6).criterion(hasItem(Items.APPLE), conditionsFromTag(UTags.FRESH_APPLES))
.input(Ingredient.fromTag(UTags.Items.FRESH_APPLES), 6).criterion(hasItem(Items.APPLE), conditionsFromTag(UTags.Items.FRESH_APPLES))
.input(Items.GLASS_BOTTLE)
.group("juice")
.offerTo(exporter);
appendIngredients(ShapelessRecipeJsonBuilder.create(RecipeCategory.FOOD, UItems.MUFFIN), Items.SUGAR, Items.EGG, Items.POTATO, UItems.JUICE, UItems.WHEAT_WORMS).offerTo(exporter);
ShapedRecipeJsonBuilder.create(RecipeCategory.MISC, UItems.MUG)
.input('*', Items.IRON_NUGGET).criterion(hasItem(Items.IRON_NUGGET), conditionsFromItem(Items.IRON_NUGGET))
.input('#', UConventionalTags.STICKS).criterion(hasItem(Items.STICK), conditionsFromTag(UConventionalTags.STICKS))
.input('#', UConventionalTags.Items.STICKS).criterion(hasItem(Items.STICK), conditionsFromTag(UConventionalTags.Items.STICKS))
.pattern("# #")
.pattern("* *")
.pattern(" # ")
.offerTo(exporter);
appendIngredients(ShapelessRecipeJsonBuilder.create(RecipeCategory.FOOD, UItems.CIDER), UItems.BURNED_JUICE, UItems.MUG)
.input(Ingredient.fromTag(UTags.FRESH_APPLES)).criterion(hasItem(Items.APPLE), conditionsFromTag(UTags.FRESH_APPLES))
.input(Ingredient.fromTag(UTags.Items.FRESH_APPLES)).criterion(hasItem(Items.APPLE), conditionsFromTag(UTags.Items.FRESH_APPLES))
.offerTo(exporter);
ShapedRecipeJsonBuilder.create(RecipeCategory.FOOD, UItems.HAY_FRIES)
@ -400,6 +411,10 @@ public class URecipeProvider extends FabricRecipeProvider {
offerSmelting(exporter, List.of(UItems.BURNED_JUICE, UItems.BURNED_TOAST), RecipeCategory.FOOD, Items.CHARCOAL, 1, 20, "coal");
offerSmelting(exporter, List.of(UItems.HAY_FRIES), RecipeCategory.FOOD, UItems.CRISPY_HAY_FRIES, 1F, 25, "hay_fries");
offerSmelting(exporter, List.of(UItems.ZAP_APPLE), RecipeCategory.FOOD, UItems.COOKED_ZAP_APPLE, 1.2F, 430, "zap_apple");
offerSmelting(exporter, List.of(Items.TROPICAL_FISH), RecipeCategory.FOOD, UItems.COOKED_TROPICAL_FISH, 1.2F, 230, "fish");
offerSmelting(exporter, List.of(Items.PUFFERFISH), RecipeCategory.FOOD, UItems.COOKED_PUFFERFISH, 1.2F, 230, "fish");
offerSmelting(exporter, List.of(Items.AXOLOTL_BUCKET), RecipeCategory.FOOD, UItems.FRIED_AXOLOTL, 2.2F, 230, "fried_axolotl");
offerSmelting(exporter, List.of(UBlocks.MYSTERIOUS_EGG.asItem()), RecipeCategory.FOOD, UItems.GREEN_FRIED_EGG, 3.8F, 630, "fried_egg");
ShapelessRecipeJsonBuilder.create(RecipeCategory.FOOD, UItems.ZAP_APPLE_JAM_JAR)
.input(UItems.COOKED_ZAP_APPLE, 6).criterion(hasItem(UItems.COOKED_ZAP_APPLE), conditionsFromItem(UItems.COOKED_ZAP_APPLE))
@ -410,8 +425,8 @@ public class URecipeProvider extends FabricRecipeProvider {
.input(UItems.TOAST, 8)
.offerTo(exporter);
ShapelessRecipeJsonBuilder.create(RecipeCategory.FOOD, UItems.CANDIED_APPLE)
.input(UConventionalTags.STICKS)
.input(UTags.FRESH_APPLES).criterion(hasItem(UItems.ZAP_APPLE_JAM_JAR), conditionsFromItem(UItems.ZAP_APPLE_JAM_JAR))
.input(UConventionalTags.Items.STICKS)
.input(UTags.Items.FRESH_APPLES).criterion(hasItem(Items.APPLE), conditionsFromTag(UTags.Items.FRESH_APPLES))
.input(Items.SUGAR, 4)
.offerTo(exporter);
@ -445,7 +460,7 @@ public class URecipeProvider extends FabricRecipeProvider {
.pattern(" C ")
.offerTo(exporter);
ShapedRecipeJsonBuilder.create(RecipeCategory.COMBAT, UItems.PEARL_NECKLACE)
.input('#', UTags.SHELLS).criterion("has_shell", conditionsFromTag(UTags.SHELLS))
.input('#', UTags.Items.SHELLS).criterion("has_shell", conditionsFromTag(UTags.Items.SHELLS))
.input('~', Items.STRING)
.pattern("# #")
.pattern("# #")
@ -492,7 +507,7 @@ public class URecipeProvider extends FabricRecipeProvider {
.pattern("#*")
.offerTo(exporter, convertBetween(Items.DIRT, UItems.WHEAT_WORMS));
offerShapelessRecipe(exporter, Items.BONE_MEAL, UTags.SHELLS, "bonemeal", 3);
offerShapelessRecipe(exporter, Items.BONE_MEAL, UTags.Items.SHELLS, "bonemeal", 3);
// pegasus feathers for non pegasi
ShapedRecipeJsonBuilder.create(RecipeCategory.MISC, UItems.PEGASUS_FEATHER)
@ -578,7 +593,7 @@ public class URecipeProvider extends FabricRecipeProvider {
public static void offerPolearmRecipe(Consumer<RecipeJsonProvider> exporter, ItemConvertible output, Either<ItemConvertible, TagKey<Item>> input) {
CraftingMaterialHelper
.input(ShapedRecipeJsonBuilder.create(RecipeCategory.TOOLS, output), 'o', input).criterion(CraftingMaterialHelper.hasEither(input), CraftingMaterialHelper.conditionsFromEither(input))
.input('#', UConventionalTags.STICKS)
.input('#', UConventionalTags.Items.STICKS)
.pattern(" o")
.pattern(" # ")
.pattern("# ")

View file

@ -1,7 +1,9 @@
package com.minelittlepony.unicopia.datagen.providers;
package com.minelittlepony.unicopia.datagen.providers.tag;
import java.util.Arrays;
import java.util.concurrent.CompletableFuture;
import com.minelittlepony.unicopia.UConventionalTags;
import com.minelittlepony.unicopia.UTags;
import com.minelittlepony.unicopia.Unicopia;
import com.minelittlepony.unicopia.block.UBlocks;
@ -12,12 +14,14 @@ import net.fabricmc.fabric.api.datagen.v1.provider.FabricTagProvider;
import net.fabricmc.fabric.api.tag.convention.v1.ConventionalBlockTags;
import net.minecraft.block.Block;
import net.minecraft.block.Blocks;
import net.minecraft.registry.Registries;
import net.minecraft.registry.RegistryKeys;
import net.minecraft.registry.RegistryWrapper;
import net.minecraft.registry.RegistryWrapper.WrapperLookup;
import net.minecraft.registry.tag.BlockTags;
import net.minecraft.registry.tag.TagBuilder;
import net.minecraft.registry.tag.TagKey;
import net.minecraft.util.DyeColor;
import net.minecraft.util.Identifier;
public class UBlockTagProvider extends FabricTagProvider.BlockTagProvider {
@ -32,6 +36,7 @@ public class UBlockTagProvider extends FabricTagProvider.BlockTagProvider {
@Override
protected void configure(WrapperLookup registries) {
populateConventionalTags();
Block[] crops = {
UBlocks.OATS, UBlocks.OATS_STEM, UBlocks.OATS_CROWN,
UBlocks.ROCKS, UBlocks.PINEAPPLE,
@ -39,13 +44,14 @@ public class UBlockTagProvider extends FabricTagProvider.BlockTagProvider {
UBlocks.GOLDEN_OAK_SPROUT
};
getOrCreateTagBuilder(UTags.CATAPULT_IMMUNE).add(Blocks.BEDROCK).forceAddTag(BlockTags.DOORS).forceAddTag(BlockTags.TRAPDOORS);
getOrCreateTagBuilder(UTags.JARS).add(UBlocks.JAR, UBlocks.CLOUD_JAR, UBlocks.STORM_JAR, UBlocks.LIGHTNING_JAR, UBlocks.ZAP_JAR);
getOrCreateTagBuilder(UTags.Blocks.CATAPULT_IMMUNE).add(Blocks.BEDROCK).forceAddTag(BlockTags.DOORS).forceAddTag(BlockTags.TRAPDOORS);
getOrCreateTagBuilder(UTags.Blocks.BUTTERFLIES_SPAWNABLE_ON).forceAddTag(BlockTags.ANIMALS_SPAWNABLE_ON).forceAddTag(BlockTags.LEAVES).forceAddTag(BlockTags.FLOWERS).forceAddTag(BlockTags.FLOWER_POTS);
getOrCreateTagBuilder(UTags.Blocks.JARS).add(UBlocks.JAR, UBlocks.CLOUD_JAR, UBlocks.STORM_JAR, UBlocks.LIGHTNING_JAR, UBlocks.ZAP_JAR);
getOrCreateTagBuilder(BlockTags.CROPS).add(crops);
getOrCreateTagBuilder(BlockTags.BEE_GROWABLES).add(crops);
getOrCreateTagBuilder(BlockTags.MAINTAINS_FARMLAND).add(crops);
getOrCreateTagBuilder(BlockTags.NEEDS_DIAMOND_TOOL).add(UBlocks.FROSTED_OBSIDIAN);
getOrCreateTagBuilder(BlockTags.PICKAXE_MINEABLE).add(UBlocks.ROCKS, UBlocks.FROSTED_OBSIDIAN, UBlocks.WEATHER_VANE).forceAddTag(UTags.JARS);
getOrCreateTagBuilder(BlockTags.PICKAXE_MINEABLE).add(UBlocks.ROCKS, UBlocks.FROSTED_OBSIDIAN, UBlocks.WEATHER_VANE).forceAddTag(UTags.Blocks.JARS);
getOrCreateTagBuilder(BlockTags.DRAGON_IMMUNE).add(UBlocks.FROSTED_OBSIDIAN, UBlocks.GOLDEN_OAK_LOG, UBlocks.GOLDEN_OAK_LEAVES);
getOrCreateTagBuilder(BlockTags.FIRE).add(UBlocks.SPECTRAL_FIRE);
getOrCreateTagBuilder(BlockTags.HOE_MINEABLE).add(UBlocks.HAY_BLOCK).addOptional(Unicopia.id("rice_block")).addOptional(Unicopia.id("straw_block"));
@ -57,31 +63,31 @@ public class UBlockTagProvider extends FabricTagProvider.BlockTagProvider {
addChitinBlocksets();
addFruitTrees();
getOrCreateTagBuilder(UTags.CRYSTAL_HEART_BASE).add(
getOrCreateTagBuilder(UTags.Blocks.CRYSTAL_HEART_BASE).add(
Blocks.DIAMOND_BLOCK,
Blocks.QUARTZ_BLOCK, Blocks.QUARTZ_BRICKS, Blocks.QUARTZ_SLAB, Blocks.QUARTZ_STAIRS, Blocks.QUARTZ_PILLAR,
Blocks.SMOOTH_QUARTZ, Blocks.SMOOTH_QUARTZ_SLAB, Blocks.SMOOTH_QUARTZ_STAIRS, Blocks.CHISELED_QUARTZ_BLOCK,
Blocks.AMETHYST_BLOCK, Blocks.NETHERITE_BLOCK, Blocks.EMERALD_BLOCK
);
getOrCreateTagBuilder(UTags.CRYSTAL_HEART_ORNAMENT).add(Blocks.END_ROD);
getOrCreateTagBuilder(UTags.Blocks.CRYSTAL_HEART_ORNAMENT).add(Blocks.END_ROD);
getOrCreateTagBuilder(UTags.FRAGILE)
getOrCreateTagBuilder(UTags.Blocks.FRAGILE)
.forceAddTag(ConventionalBlockTags.GLASS_BLOCKS)
.forceAddTag(ConventionalBlockTags.GLASS_PANES)
.forceAddTag(UTags.JARS)
.forceAddTag(UTags.Blocks.JARS)
.add(Blocks.VINE, Blocks.LILY_PAD);
getOrCreateTagBuilder(UTags.INTERESTING).add(
getOrCreateTagBuilder(UTags.Blocks.INTERESTING).add(
Blocks.SEA_LANTERN, Blocks.ENDER_CHEST, Blocks.END_PORTAL_FRAME,
Blocks.JUKEBOX, Blocks.SPAWNER
).forceAddTag(ConventionalBlockTags.ORES);
getOrCreateTagBuilder(UTags.KICKS_UP_DUST).forceAddTag(BlockTags.SAND).add(
getOrCreateTagBuilder(UTags.Blocks.KICKS_UP_DUST).forceAddTag(BlockTags.SAND).add(
Blocks.SUSPICIOUS_SAND,
Blocks.GRAVEL, Blocks.SUSPICIOUS_GRAVEL
).forceAddTag(TagKey.of(RegistryKeys.BLOCK, new Identifier("c", "concrete_powders")));
getOrCreateTagBuilder(UTags.UNAFFECTED_BY_GROW_ABILITY).add(Blocks.GRASS_BLOCK);
getOrCreateTagBuilder(UTags.Blocks.UNAFFECTED_BY_GROW_ABILITY).add(Blocks.GRASS_BLOCK);
}
private void addFruitTrees() {
@ -106,7 +112,7 @@ public class UBlockTagProvider extends FabricTagProvider.BlockTagProvider {
private void addZapWoodset() {
getOrCreateTagBuilder(BlockTags.LEAVES).add(UBlocks.ZAP_LEAVES, UBlocks.FLOWERING_ZAP_LEAVES);
getOrCreateTagBuilder(UTags.POLEARM_MINEABLE).add(
getOrCreateTagBuilder(UTags.Blocks.POLEARM_MINEABLE).add(
UBlocks.ZAP_LEAVES, UBlocks.FLOWERING_ZAP_LEAVES,
UBlocks.ZAP_PLANKS,
UBlocks.ZAP_LOG, UBlocks.ZAP_WOOD, UBlocks.STRIPPED_ZAP_LOG, UBlocks.STRIPPED_ZAP_WOOD,
@ -204,4 +210,13 @@ public class UBlockTagProvider extends FabricTagProvider.BlockTagProvider {
getOrCreateTagBuilder(BlockTags.CEILING_HANGING_SIGNS).add(hanging);
getOrCreateTagBuilder(BlockTags.WALL_HANGING_SIGNS).add(wallHanging);
}
private void populateConventionalTags() {
getOrCreateTagBuilder(UConventionalTags.Blocks.CONCRETES).add(Arrays.stream(DyeColor.values()).map(i -> Registries.BLOCK.get(new Identifier(i.getName() + "_concrete"))).toArray(Block[]::new));
getOrCreateTagBuilder(UConventionalTags.Blocks.CONCRETE_POWDERS).add(Arrays.stream(DyeColor.values()).map(i -> Registries.BLOCK.get(new Identifier(i.getName() + "_concrete_powder"))).toArray(Block[]::new));
getOrCreateTagBuilder(UConventionalTags.Blocks.GLAZED_TERRACOTTAS).add(Arrays.stream(DyeColor.values()).map(i -> Registries.BLOCK.get(new Identifier(i.getName() + "_glazed_terracotta"))).toArray(Block[]::new));
getOrCreateTagBuilder(UConventionalTags.Blocks.CORAL_BLOCKS).add(Blocks.TUBE_CORAL_BLOCK, Blocks.BRAIN_CORAL_BLOCK, Blocks.BUBBLE_CORAL_BLOCK, Blocks.FIRE_CORAL_BLOCK, Blocks.HORN_CORAL_BLOCK);
getOrCreateTagBuilder(UConventionalTags.Blocks.CORAL_FANS).add(Blocks.TUBE_CORAL_FAN, Blocks.BRAIN_CORAL_FAN, Blocks.BUBBLE_CORAL_FAN, Blocks.FIRE_CORAL_FAN, Blocks.HORN_CORAL_FAN);
getOrCreateTagBuilder(UConventionalTags.Blocks.CORALS).add(Blocks.TUBE_CORAL, Blocks.BRAIN_CORAL, Blocks.BUBBLE_CORAL, Blocks.FIRE_CORAL, Blocks.HORN_CORAL);
}
}

View file

@ -0,0 +1,30 @@
package com.minelittlepony.unicopia.datagen.providers.tag;
import java.util.concurrent.CompletableFuture;
import com.minelittlepony.unicopia.UTags;
import com.minelittlepony.unicopia.entity.damage.UDamageTypes;
import net.fabricmc.fabric.api.datagen.v1.FabricDataOutput;
import net.fabricmc.fabric.api.datagen.v1.provider.FabricTagProvider;
import net.minecraft.entity.damage.DamageType;
import net.minecraft.registry.RegistryKeys;
import net.minecraft.registry.RegistryWrapper.WrapperLookup;
import net.minecraft.registry.tag.DamageTypeTags;
public class UDamageTypeProvider extends FabricTagProvider<DamageType> {
public UDamageTypeProvider(FabricDataOutput output, CompletableFuture<WrapperLookup> registriesFuture) {
super(output, RegistryKeys.DAMAGE_TYPE, registriesFuture);
}
@Override
protected void configure(WrapperLookup lookup) {
getOrCreateTagBuilder(UTags.DamageTypes.SPELLBOOK_IMMUNE_TO).add(
UDamageTypes.ZAP_APPLE, UDamageTypes.LOVE_DRAINING, UDamageTypes.LIFE_DRAINING,
UDamageTypes.RAINBOOM, UDamageTypes.SUN, UDamageTypes.SUNLIGHT, UDamageTypes.SMASH
).forceAddTag(DamageTypeTags.IS_FALL).forceAddTag(DamageTypeTags.IS_FREEZING).forceAddTag(DamageTypeTags.IS_LIGHTNING).forceAddTag(DamageTypeTags.IS_PROJECTILE);
getOrCreateTagBuilder(UTags.DamageTypes.FROM_ROCKS).add(UDamageTypes.ROCK);
getOrCreateTagBuilder(UTags.DamageTypes.FROM_HORSESHOES).add(UDamageTypes.HORSESHOE);
getOrCreateTagBuilder(UTags.DamageTypes.BREAKS_SUNGLASSES).add(UDamageTypes.BAT_SCREECH, UDamageTypes.RAINBOOM);
}
}

View file

@ -0,0 +1,348 @@
package com.minelittlepony.unicopia.datagen.providers.tag;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import com.minelittlepony.unicopia.Race;
import com.minelittlepony.unicopia.UConventionalTags;
import com.minelittlepony.unicopia.UTags;
import com.minelittlepony.unicopia.block.UBlocks;
import com.minelittlepony.unicopia.datagen.Datagen;
import com.minelittlepony.unicopia.datagen.ItemFamilies;
import com.minelittlepony.unicopia.item.BedsheetsItem;
import com.minelittlepony.unicopia.item.UItems;
import net.fabricmc.fabric.api.datagen.v1.FabricDataOutput;
import net.fabricmc.fabric.api.datagen.v1.provider.FabricTagProvider;
import net.fabricmc.fabric.api.tag.convention.v1.ConventionalItemTags;
import net.minecraft.block.Block;
import net.minecraft.item.Item;
import net.minecraft.item.Items;
import net.minecraft.registry.Registries;
import net.minecraft.registry.RegistryKeys;
import net.minecraft.registry.RegistryWrapper;
import net.minecraft.registry.RegistryWrapper.WrapperLookup;
import net.minecraft.registry.tag.BlockTags;
import net.minecraft.registry.tag.ItemTags;
import net.minecraft.registry.tag.TagBuilder;
import net.minecraft.registry.tag.TagKey;
import net.minecraft.util.Identifier;
public class UItemTagProvider extends FabricTagProvider.ItemTagProvider {
private final UBlockTagProvider blockTagProvider;
public UItemTagProvider(FabricDataOutput output, CompletableFuture<RegistryWrapper.WrapperLookup> registriesFuture, UBlockTagProvider blockTagProvider) {
super(output, registriesFuture, blockTagProvider);
this.blockTagProvider = blockTagProvider;
}
@Override
public void copy(TagKey<Block> blockTag, TagKey<Item> itemTag) {
TagBuilder blockTagBuilder = Objects.requireNonNull(blockTagProvider, "Pass Block tag provider via constructor to use copy").getTagBuilder(blockTag);
TagBuilder itemTagBuilder = getTagBuilder(itemTag);
blockTagBuilder.build().forEach(entry -> {
if (entry.canAdd(Registries.ITEM::containsId, tagId -> getTagBuilder(TagKey.of(RegistryKeys.ITEM, tagId)) != null)) {
itemTagBuilder.add(entry);
} else {
Datagen.LOGGER.warn("Cannot copy missing entry {} to item tag {}", entry, itemTag.id());
}
});
}
@Override
protected void configure(WrapperLookup arg) {
copyBlockTags();
exportConventionalTags();
getOrCreateTagBuilder(ItemTags.BOOKSHELF_BOOKS).add(UItems.SPELLBOOK);
getOrCreateTagBuilder(ItemTags.BEDS).add(UItems.CLOTH_BED, UItems.CLOUD_BED);
getOrCreateTagBuilder(ItemTags.CHEST_BOATS).add(UItems.PALM_CHEST_BOAT);
getOrCreateTagBuilder(ItemTags.BOATS).add(UItems.PALM_BOAT);
getOrCreateTagBuilder(ItemTags.MUSIC_DISCS).add(ItemFamilies.MUSIC_DISCS);
getOrCreateTagBuilder(ItemTags.CREEPER_DROP_MUSIC_DISCS).add(UItems.MUSIC_DISC_CRUSADE, UItems.MUSIC_DISC_FUNK, UItems.MUSIC_DISC_PET, UItems.MUSIC_DISC_POPULAR);
getOrCreateTagBuilder(ItemTags.SIGNS).add(UBlocks.PALM_SIGN.asItem());
getOrCreateTagBuilder(ItemTags.HANGING_SIGNS).add(UBlocks.PALM_HANGING_SIGN.asItem());
getOrCreateTagBuilder(UTags.Items.HORSE_SHOES).add(ItemFamilies.HORSE_SHOES);
getOrCreateTagBuilder(UTags.Items.POLEARMS).add(ItemFamilies.POLEARMS);
getOrCreateTagBuilder(ItemTags.TOOLS).addTag(UTags.Items.HORSE_SHOES).addTag(UTags.Items.POLEARMS);
getOrCreateTagBuilder(UTags.Items.BASKETS).add(ItemFamilies.BASKETS);
getOrCreateTagBuilder(UTags.Items.BADGES).add(Race.REGISTRY.stream()
.map(race -> race.getId().withPath(p -> p + "_badge"))
.flatMap(id -> Registries.ITEM.getOrEmpty(id).stream())
.toArray(Item[]::new));
getOrCreateTagBuilder(UTags.Items.WOOL_BED_SHEETS).add(BedsheetsItem.ITEMS.values().stream().filter(sheet -> sheet != UItems.KELP_BED_SHEETS).toArray(Item[]::new));
getOrCreateTagBuilder(UTags.Items.BED_SHEETS).forceAddTag(UTags.Items.WOOL_BED_SHEETS).add(UItems.KELP_BED_SHEETS);
getOrCreateTagBuilder(UTags.Items.APPLE_SEEDS).add(UItems.GREEN_APPLE_SEEDS, UItems.SWEET_APPLE_SEEDS, UItems.SOUR_APPLE_SEEDS);
getOrCreateTagBuilder(UTags.Items.MAGIC_FEATHERS).add(UItems.PEGASUS_FEATHER, UItems.GRYPHON_FEATHER);
getOrCreateTagBuilder(UTags.Items.FRESH_APPLES).add(Items.APPLE, UItems.GREEN_APPLE, UItems.SWEET_APPLE, UItems.SOUR_APPLE);
getOrCreateTagBuilder(UTags.Items.CLOUD_JARS).add(UItems.RAIN_CLOUD_JAR, UItems.STORM_CLOUD_JAR);
getOrCreateTagBuilder(UTags.Items.PIES).add(UItems.APPLE_PIE, UItems.APPLE_PIE_HOOF);
// technical tags
getOrCreateTagBuilder(ItemTags.VILLAGER_PLANTABLE_SEEDS).addTag(UTags.Items.APPLE_SEEDS);
getOrCreateTagBuilder(UTags.Items.CAN_CUT_PIE).forceAddTag(ConventionalItemTags.SHEARS).addOptionalTag(UConventionalTags.Items.TOOL_KNIVES);
getOrCreateTagBuilder(UTags.Items.COOLS_OFF_KIRINS).add(Items.MELON_SLICE, UItems.JUICE).forceAddTag(ConventionalItemTags.WATER_BUCKETS);
getOrCreateTagBuilder(UTags.Items.FALLS_SLOWLY).add(Items.FEATHER, UItems.CLOUD_LUMP).forceAddTag(UTags.Items.MAGIC_FEATHERS);
getOrCreateTagBuilder(UTags.Items.IS_DELIVERED_AGGRESSIVELY).forceAddTag(ItemTags.ANVIL);
getOrCreateTagBuilder(UTags.Items.SPOOKED_MOB_DROPS).add(Items.BRICK);
getOrCreateTagBuilder(UTags.Items.SHADES).add(
Items.CARVED_PUMPKIN, Items.SKELETON_SKULL, Items.WITHER_SKELETON_SKULL, Items.PLAYER_HEAD,
Items.ZOMBIE_HEAD, Items.CREEPER_HEAD, Items.DRAGON_HEAD, Items.PIGLIN_HEAD,
UItems.SUNGLASSES
);
getOrCreateTagBuilder(UTags.Items.FLOATS_ON_CLOUDS)
.forceAddTag(UTags.Items.CLOUD_BEDS)
.forceAddTag(UTags.Items.CLOUD_SLABS)
.forceAddTag(UTags.Items.CLOUD_STAIRS)
.forceAddTag(UTags.Items.CLOUD_BLOCKS)
.add(UItems.CLOUD_LUMP);
getOrCreateTagBuilder(UTags.Items.CONTAINER_WITH_LOVE).add(UItems.LOVE_BOTTLE, UItems.LOVE_BUCKET, UItems.LOVE_MUG);
getOrCreateTagBuilder(UTags.Items.HAS_NO_TRAITS).add(
Items.AIR, Items.SPAWNER, Items.STRUCTURE_VOID, Items.STRUCTURE_BLOCK,
Items.COMMAND_BLOCK, Items.CHAIN_COMMAND_BLOCK, Items.REPEATING_COMMAND_BLOCK,
Items.LIGHT, Items.JIGSAW, Items.BARRIER, Items.BEDROCK, Items.END_PORTAL_FRAME,
Items.DEBUG_STICK, Items.COMMAND_BLOCK_MINECART,
UItems.PLUNDER_VINE
).forceAddTag(UTags.Items.BADGES);
getOrCreateTagBuilder(UTags.Items.LOOT_BUG_COMMON_DROPS).forceAddTag(ConventionalItemTags.NUGGETS);
getOrCreateTagBuilder(UTags.Items.LOOT_BUG_RARE_DROPS).add(
Items.DIAMOND, Items.GOLDEN_APPLE, Items.GOLDEN_CARROT,
Items.GOLDEN_HELMET, Items.GOLDEN_BOOTS, Items.GOLDEN_LEGGINGS, Items.GOLDEN_CHESTPLATE,
Items.GOLDEN_HORSE_ARMOR,
Items.GOLDEN_PICKAXE, Items.GOLDEN_SHOVEL, Items.GOLDEN_AXE, Items.GOLDEN_SWORD, Items.GOLDEN_HOE,
UItems.GOLDEN_HORSE_SHOE, UItems.GOLDEN_POLEARM, UItems.GOLDEN_FEATHER, UItems.GOLDEN_WING,
UItems.GOLDEN_OAK_SEEDS
).forceAddTag(ConventionalItemTags.GOLD_INGOTS).forceAddTag(ConventionalItemTags.RAW_GOLD_ORES).forceAddTag(ConventionalItemTags.RAW_GOLD_BLOCKS)
.addOptionalTag(new Identifier("farmersdelight:golden_knife"));
getOrCreateTagBuilder(UTags.Items.LOOT_BUG_EPIC_DROPS).add(
Items.DIAMOND_BLOCK,
Items.DIAMOND_HELMET, Items.DIAMOND_BOOTS, Items.DIAMOND_LEGGINGS, Items.DIAMOND_CHESTPLATE,
Items.DIAMOND_HORSE_ARMOR,
Items.DIAMOND_PICKAXE, Items.DIAMOND_SHOVEL, Items.DIAMOND_AXE, Items.DIAMOND_SWORD, Items.DIAMOND_HOE,
UItems.DIAMOND_POLEARM
).forceAddTag(UTags.Items.BADGES).forceAddTag(ConventionalItemTags.GOLD_INGOTS);
getOrCreateTagBuilder(UTags.Items.SHELLS).add(Items.NAUTILUS_SHELL, UItems.CLAM_SHELL, UItems.SCALLOP_SHELL, UItems.TURRET_SHELL);
getOrCreateTagBuilder(UTags.Items.SPECIAL_SHELLS).add(UItems.SHELLY);
getOrCreateTagBuilder(UTags.Items.ROCK_STEWS).add(UItems.ROCK_STEW);
getOrCreateTagBuilder(UTags.Items.HIGH_QUALITY_SEA_VEGETABLES)
.add(Items.DRIED_KELP_BLOCK, Items.GLOW_LICHEN)
.forceAddTag(UConventionalTags.Items.CORAL_BLOCKS);
getOrCreateTagBuilder(UTags.Items.LOW_QUALITY_SEA_VEGETABLES)
.add(Items.KELP, Items.DRIED_KELP, Items.SEAGRASS, Items.SEA_PICKLE)
.forceAddTag(UConventionalTags.Items.CORALS).forceAddTag(UConventionalTags.Items.CORAL_FANS);
exportForagingTags();
exportFarmersDelightItems();
}
private void copyBlockTags() {
copy(BlockTags.LEAVES, ItemTags.LEAVES);
copy(BlockTags.LOGS_THAT_BURN, ItemTags.LOGS_THAT_BURN);
copy(BlockTags.LOGS, ItemTags.LOGS);
copy(BlockTags.PLANKS, ItemTags.PLANKS);
copy(BlockTags.WOODEN_BUTTONS, ItemTags.WOODEN_BUTTONS);
copy(BlockTags.WOODEN_DOORS, ItemTags.WOODEN_DOORS);
copy(BlockTags.FENCE_GATES, ItemTags.FENCE_GATES);
copy(BlockTags.WOODEN_FENCES, ItemTags.WOODEN_FENCES);
copy(BlockTags.WOODEN_PRESSURE_PLATES, ItemTags.WOODEN_PRESSURE_PLATES);
copy(BlockTags.SLABS, ItemTags.SLABS);
copy(BlockTags.WOODEN_SLABS, ItemTags.WOODEN_SLABS);
copy(BlockTags.STAIRS, ItemTags.STAIRS);
copy(BlockTags.WOODEN_STAIRS, ItemTags.WOODEN_STAIRS);
copy(BlockTags.TRAPDOORS, ItemTags.TRAPDOORS);
copy(BlockTags.WOODEN_TRAPDOORS, ItemTags.WOODEN_TRAPDOORS);
copy(BlockTags.SAPLINGS, ItemTags.SAPLINGS);
copy(UTags.Blocks.ZAP_LOGS, UTags.Items.ZAP_LOGS);
copy(UTags.Blocks.WAXED_ZAP_LOGS, UTags.Items.WAXED_ZAP_LOGS);
copy(UTags.Blocks.PALM_LOGS, UTags.Items.PALM_LOGS);
copy(UTags.Blocks.CLOUD_BEDS, UTags.Items.CLOUD_BEDS);
copy(UTags.Blocks.CLOUD_SLABS, UTags.Items.CLOUD_SLABS);
copy(UTags.Blocks.CLOUD_STAIRS, UTags.Items.CLOUD_STAIRS);
copy(UTags.Blocks.CLOUD_BLOCKS, UTags.Items.CLOUD_BLOCKS);
copy(UTags.Blocks.CHITIN_BLOCKS, UTags.Items.CHITIN_BLOCKS);
}
private void exportForagingTags() {
getOrCreateTagBuilder(UTags.Items.FORAGE_BLINDING).add(Items.OXEYE_DAISY);
getOrCreateTagBuilder(UTags.Items.FORAGE_DANGEROUS).add(Items.POPPY, Items.LILY_OF_THE_VALLEY);
getOrCreateTagBuilder(UTags.Items.FORAGE_FILLING).add(Items.HAY_BLOCK);
getOrCreateTagBuilder(UTags.Items.FORAGE_SAFE).add(Items.BLUE_ORCHID, Items.RED_TULIP, Items.ORANGE_TULIP,
Items.PINK_TULIP, Items.CORNFLOWER, Items.PEONY, Items.SUNFLOWER, Items.DANDELION, Items.LILAC, Items.TALL_GRASS,
Items.DEAD_BUSH, Items.PINK_PETALS
).forceAddTag(UConventionalTags.Items.MUSHROOMS).forceAddTag(ItemTags.SAPLINGS);
getOrCreateTagBuilder(UTags.Items.FORAGE_NAUSEATING).add(Items.GRASS, UItems.CIDER);
getOrCreateTagBuilder(UTags.Items.FORAGE_PRICKLY).add(Items.ROSE_BUSH).forceAddTag(ItemTags.SAPLINGS);
getOrCreateTagBuilder(UTags.Items.FORAGE_GLOWING).add(Items.AZURE_BLUET, Items.TORCHFLOWER);
getOrCreateTagBuilder(UTags.Items.FORAGE_RISKY).add(Items.ALLIUM, Items.WHITE_TULIP, UItems.BURNED_JUICE);
getOrCreateTagBuilder(UTags.Items.FORAGE_STRENGHENING).add(Items.FERN);
getOrCreateTagBuilder(UTags.Items.FORAGE_SEVERE_NAUSEATING).add(Items.PITCHER_PLANT);
getOrCreateTagBuilder(UTags.Items.FORAGE_SEVERE_PRICKLY).add(Items.LARGE_FERN);
}
private void exportConventionalTags() {
copy(UConventionalTags.Blocks.CONCRETES, UConventionalTags.Items.CONCRETES);
copy(UConventionalTags.Blocks.CONCRETE_POWDERS, UConventionalTags.Items.CONCRETE_POWDERS);
copy(UConventionalTags.Blocks.GLAZED_TERRACOTTAS, UConventionalTags.Items.GLAZED_TERRACOTTAS);
copy(UConventionalTags.Blocks.CORAL_BLOCKS, UConventionalTags.Items.CORAL_BLOCKS);
copy(UConventionalTags.Blocks.CORAL_FANS, UConventionalTags.Items.CORAL_FANS);
copy(UConventionalTags.Blocks.CORALS, UConventionalTags.Items.CORALS);
getOrCreateTagBuilder(UConventionalTags.Items.ACORNS).add(UItems.ACORN);
getOrCreateTagBuilder(UConventionalTags.Items.APPLES)
.add(Items.APPLE, Items.GOLDEN_APPLE, Items.ENCHANTED_GOLDEN_APPLE, UItems.ROTTEN_APPLE)
.forceAddTag(UTags.Items.FRESH_APPLES)
.addOptionalTag(new Identifier("c", "pyrite_apples")) // no idea which mod add pyrite apples
;
getOrCreateTagBuilder(UConventionalTags.Items.BANANAS).add(UItems.BANANA);
getOrCreateTagBuilder(UConventionalTags.Items.RAW_FISH).add(Items.COD, Items.SALMON, Items.PUFFERFISH, Items.TROPICAL_FISH).addOptionalTag(new Identifier("c", "mollusks"));
getOrCreateTagBuilder(UConventionalTags.Items.COOKED_FISH).add(Items.COOKED_COD, Items.COOKED_SALMON, UItems.COOKED_TROPICAL_FISH, UItems.COOKED_PUFFERFISH, UItems.FRIED_AXOLOTL);
getOrCreateTagBuilder(UConventionalTags.Items.ROTTEN_FISH).add(UItems.ROTTEN_COD, UItems.ROTTEN_TROPICAL_FISH, UItems.ROTTEN_SALMON, UItems.ROTTEN_PUFFERFISH);
getOrCreateTagBuilder(ItemTags.FISHES).add(
UItems.COOKED_TROPICAL_FISH, UItems.COOKED_PUFFERFISH, UItems.FRIED_AXOLOTL,
UItems.ROTTEN_COD, UItems.ROTTEN_TROPICAL_FISH, UItems.ROTTEN_SALMON, UItems.ROTTEN_PUFFERFISH
);
getOrCreateTagBuilder(UConventionalTags.Items.COOKED_MEAT)
.add(Items.COOKED_PORKCHOP, Items.COOKED_BEEF, Items.COOKED_MUTTON, Items.COOKED_RABBIT, Items.COOKED_CHICKEN, Items.RABBIT_STEW)
.addOptionalTag(new Identifier("c", "cooked_bacon"))
.addOptionalTag(new Identifier("c", "cooked_beef"))
.addOptionalTag(new Identifier("c", "cooked_chicken"))
.addOptionalTag(new Identifier("c", "cooked_mutton"))
.addOptionalTag(new Identifier("c", "cooked_pork"))
.addOptionalTag(new Identifier("c", "fried_chickens"))
.addOptionalTag(new Identifier("c", "hamburgers"))
.addOptionalTag(new Identifier("c", "pork_and_beans"))
.addOptionalTag(new Identifier("c", "pork_jerkies"))
.addOptionalTag(new Identifier("c", "protien"));
getOrCreateTagBuilder(UConventionalTags.Items.RAW_MEAT)
.add(Items.PORKCHOP, Items.BEEF, Items.MUTTON, Items.RABBIT, Items.CHICKEN)
.addOptionalTag(new Identifier("c", "raw_bacon"))
.addOptionalTag(new Identifier("c", "raw_beef"))
.addOptionalTag(new Identifier("c", "raw_chicken"))
.addOptionalTag(new Identifier("c", "raw_mutton"))
.addOptionalTag(new Identifier("c", "raw_pork"))
.addOptionalTag(new Identifier("c", "lemon_chickens"));
getOrCreateTagBuilder(UConventionalTags.Items.ROTTEN_MEAT).add(Items.ROTTEN_FLESH);
getOrCreateTagBuilder(UConventionalTags.Items.ROTTEN_INSECT).add(Items.FERMENTED_SPIDER_EYE);
getOrCreateTagBuilder(UConventionalTags.Items.COOKED_INSECT);//.add(Items.FERMENTED_SPIDER_EYE); TODO
getOrCreateTagBuilder(UConventionalTags.Items.RAW_INSECT).add(Items.SPIDER_EYE, UItems.BUTTERFLY, UItems.WHEAT_WORMS, UBlocks.WORM_BLOCK.asItem());
getOrCreateTagBuilder(UConventionalTags.Items.WORMS).add(UItems.WHEAT_WORMS);
getOrCreateTagBuilder(UConventionalTags.Items.STICKS).add(Items.STICK);
getOrCreateTagBuilder(UConventionalTags.Items.ROCKS).add(UItems.ROCK);
getOrCreateTagBuilder(UConventionalTags.Items.PINECONES).add(UItems.PINECONE);
getOrCreateTagBuilder(UConventionalTags.Items.PINEAPPLES).add(UItems.PINEAPPLE);
getOrCreateTagBuilder(UConventionalTags.Items.MANGOES).add(UItems.MANGO);
getOrCreateTagBuilder(UConventionalTags.Items.MUSHROOMS).add(Items.RED_MUSHROOM, Items.BROWN_MUSHROOM);
getOrCreateTagBuilder(UConventionalTags.Items.MUFFINS).add(UItems.MUFFIN);
getOrCreateTagBuilder(UConventionalTags.Items.SEEDS).add(Items.BEETROOT_SEEDS, Items.MELON_SEEDS, Items.PUMPKIN_SEEDS, Items.TORCHFLOWER_SEEDS, Items.WHEAT_SEEDS)
.add(UItems.OAT_SEEDS)
.forceAddTag(UTags.Items.APPLE_SEEDS);
getOrCreateTagBuilder(UConventionalTags.Items.COOKIES).add(Items.COOKIE, UItems.OATMEAL_COOKIE, UItems.CHOCOLATE_OATMEAL_COOKIE, UItems.PINECONE_COOKIE);
getOrCreateTagBuilder(UConventionalTags.Items.OATMEALS).add(UItems.OATMEAL);
getOrCreateTagBuilder(UConventionalTags.Items.GRAIN).add(Items.WHEAT, UItems.OATS);
getOrCreateTagBuilder(UConventionalTags.Items.NUTS).add(UItems.BOWL_OF_NUTS)
.addOptionalTag(UConventionalTags.Items.CROPS_PEANUTS)
.forceAddTag(UConventionalTags.Items.ACORNS)
.addOptional(new Identifier("garnished", "nuts"))
.addOptional(new Identifier("garnished", "nut_mix"))
.addOptional(new Identifier("garnished", "neverable_delecacies"));
getOrCreateTagBuilder(UConventionalTags.Items.FRUITS)
.add(Items.MELON_SLICE, Items.SWEET_BERRIES, Items.GLOW_BERRIES, Items.CHORUS_FRUIT)
.add(UItems.JUICE, UItems.ZAP_APPLE, UItems.ZAP_BULB)
.forceAddTag(UConventionalTags.Items.MANGOES)
.forceAddTag(UConventionalTags.Items.PINEAPPLES)
.forceAddTag(UConventionalTags.Items.APPLES)
.forceAddTag(UConventionalTags.Items.BANANAS)
.addOptionalTag(new Identifier("garnished", "berries"));
getOrCreateTagBuilder(UConventionalTags.Items.DESSERTS).add(Items.CAKE, UItems.APPLE_PIE_SLICE).forceAddTag(UTags.Items.PIES);
getOrCreateTagBuilder(UConventionalTags.Items.CANDY).add(Items.SUGAR, UItems.ROCK_CANDY, UItems.CANDIED_APPLE);
getOrCreateTagBuilder(UTags.Items.BAKED_GOODS).add(
Items.BREAD, Items.COOKIE, Items.PUMPKIN_PIE,
UItems.MUFFIN, UItems.SCONE, UItems.COOKED_ZAP_APPLE, UItems.TOAST, UItems.BURNED_TOAST, UItems.JAM_TOAST, UItems.IMPORTED_OATS,
UItems.HAY_FRIES, UItems.CRISPY_HAY_FRIES, UItems.HORSE_SHOE_FRIES)
.forceAddTag(UConventionalTags.Items.OATMEALS)
.forceAddTag(UConventionalTags.Items.COOKIES);
}
private void exportFarmersDelightItems() {
getOrCreateTagBuilder(UTags.Items.COOLS_OFF_KIRINS)
.addOptional(new Identifier("farmersdelight", "melon_popsicle"))
.addOptional(new Identifier("farmersdelight", "melon_juice"));
getOrCreateTagBuilder(TagKey.of(RegistryKeys.ITEM, new Identifier("farmersdelight", "cabbage_roll_ingredients"))).add(UItems.OATS, UItems.ROCK, UItems.WHEAT_WORMS);
getOrCreateTagBuilder(TagKey.of(RegistryKeys.ITEM, new Identifier("farmersdelight", "comfort_foods"))).add(UItems.OATMEAL, UItems.ROCK_STEW, UItems.MUFFIN);
getOrCreateTagBuilder(UConventionalTags.Items.RAW_FISH)
.addOptional(new Identifier("farmersdelight", "cod_roll"))
.addOptional(new Identifier("farmersdelight", "salmon_roll"))
.addOptional(new Identifier("farmersdelight", "cod_slice"))
.addOptional(new Identifier("farmersdelight", "salmon_slice"));
getOrCreateTagBuilder(UConventionalTags.Items.COOKED_FISH)
.addOptional(new Identifier("farmersdelight", "fish_stew"))
.addOptional(new Identifier("farmersdelight", "baked_cod_stew"))
.addOptional(new Identifier("farmersdelight", "grilled_salmon"));
getOrCreateTagBuilder(UConventionalTags.Items.RAW_MEAT)
.addOptional(new Identifier("farmersdelight", "ham"));
getOrCreateTagBuilder(UConventionalTags.Items.COOKED_MEAT)
.addOptional(new Identifier("farmersdelight", "chicken_soup"))
.addOptional(new Identifier("farmersdelight", "bacon_and_eggs"))
.addOptional(new Identifier("farmersdelight", "pasta_with_meatballs"))
.addOptional(new Identifier("farmersdelight", "beef_stew"))
.addOptional(new Identifier("farmersdelight", "bone_broth"))
.addOptional(new Identifier("farmersdelight", "mutton_wrap"))
.addOptional(new Identifier("farmersdelight", "bacon_sandwich"))
.addOptional(new Identifier("farmersdelight", "hamburger"))
.addOptional(new Identifier("farmersdelight", "chicken_sandwich"))
.addOptional(new Identifier("farmersdelight", "barbecue_stick"))
.addOptional(new Identifier("farmersdelight", "smoked_ham"))
.addOptional(new Identifier("farmersdelight", "honey_glazed_ham"))
.addOptional(new Identifier("farmersdelight", "honey_glazed_ham_block"))
.addOptional(new Identifier("farmersdelight", "roast_chicken"))
.addOptional(new Identifier("farmersdelight", "roast_chicken_block"))
.addOptional(new Identifier("farmersdelight", "steak_and_potatoes"))
.addOptional(new Identifier("farmersdelight", "roasted_mutton_chops"))
.addOptional(new Identifier("farmersdelight", "pasta_with_mutton_chop"));
getOrCreateTagBuilder(UConventionalTags.Items.FRUITS)
.addOptional(new Identifier("farmersdelight", "pumpkin_slice"))
.addOptional(new Identifier("farmersdelight", "tomato"))
.addOptional(new Identifier("farmersdelight", "melon_juice"))
.addOptional(new Identifier("farmersdelight", "fruit_salad"));
getOrCreateTagBuilder(UConventionalTags.Items.DESSERTS)
.addOptional(new Identifier("farmersdelight", "sweet_berry_cheesecake"))
.addOptional(new Identifier("farmersdelight", "sweet_berry_cheesecake_slice"))
.addOptional(new Identifier("farmersdelight", "chocolate_pie_slice"))
.addOptional(new Identifier("farmersdelight", "cake_slice"))
.addOptional(new Identifier("farmersdelight", "apple_pie_slice"))
.addOptional(new Identifier("farmersdelight", "glow_berry_custard"));
getOrCreateTagBuilder(UConventionalTags.Items.COOKIES)
.addOptional(new Identifier("farmersdelight", "sweet_berry_cookie"))
.addOptional(new Identifier("farmersdelight", "honey_cookie"));
getOrCreateTagBuilder(UTags.Items.BAKED_GOODS)
.addOptional(new Identifier("farmersdelight", "wheat_dough"))
.addOptional(new Identifier("farmersdelight", "raw_pasta"))
.addOptional(new Identifier("farmersdelight", "pie_crust"))
.addOptional(new Identifier("farmersdelight", "egg_sandwich"));
getOrCreateTagBuilder(UTags.Items.HIGH_QUALITY_SEA_VEGETABLES)
.addOptional(new Identifier("farmersdelight", "kelp_roll"));
getOrCreateTagBuilder(UTags.Items.LOW_QUALITY_SEA_VEGETABLES)
.addOptional(new Identifier("farmersdelight", "kelp_roll_slice"));
getOrCreateTagBuilder(UTags.Items.FORAGE_FILLING)
.addOptional(new Identifier("farmersdelight", "horse_feed"))
.addOptional(new Identifier("farmersdelight", "rice_bale"))
.addOptional(new Identifier("farmersdelight", "straw_bale"));
getOrCreateTagBuilder(UTags.Items.FORAGE_SAFE)
.addOptional(new Identifier("farmersdelight", "sandy_shrub"))
.addOptional(new Identifier("farmersdelight", "wild_cabbages"))
.addOptional(new Identifier("farmersdelight", "wild_onions"))
.addOptional(new Identifier("farmersdelight", "wild_carrots"))
.addOptional(new Identifier("farmersdelight", "wild_beetroots"))
.addOptional(new Identifier("farmersdelight", "wild_rice"));
getOrCreateTagBuilder(UTags.Items.FORAGE_RISKY)
.addOptional(new Identifier("farmersdelight", "wild_tomatoes"))
.addOptional(new Identifier("farmersdelight", "wild_potatoes"))
.addOptionalTag(new Identifier("c", "meads"));
}
}

View file

@ -5,11 +5,11 @@ import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import org.jetbrains.annotations.Nullable;
import com.minelittlepony.unicopia.entity.player.Pony;
import com.minelittlepony.unicopia.item.ItemDuck;
import com.mojang.datafixers.util.Pair;
@ -19,33 +19,53 @@ import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.client.item.TooltipContext;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.FoodComponent;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.network.PacketByteBuf;
import net.minecraft.registry.RegistryKeys;
import net.minecraft.registry.tag.TagKey;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
import net.minecraft.util.Identifier;
import net.minecraft.util.UseAction;
public record DietProfile(
float defaultMultiplier,
float foragingMultiplier,
List<Multiplier> multipliers,
List<Effect> effects,
Optional<Effect> defaultEffect
List<FoodGroupEffects> effects,
Optional<FoodGroupEffects> defaultEffect
) {
public static final DietProfile EMPTY = new DietProfile(1, 1, List.of(), List.of(), Optional.empty());
public static final Codec<DietProfile> CODEC = RecordCodecBuilder.create(instance -> instance.group(
Codec.FLOAT.fieldOf("default_multiplier").forGetter(DietProfile::defaultMultiplier),
Codec.FLOAT.fieldOf("foraging_multiplier").forGetter(DietProfile::foragingMultiplier),
Codec.list(Multiplier.CODEC).fieldOf("multipliers").forGetter(DietProfile::multipliers),
Codec.list(Effect.CODEC).fieldOf("effects").forGetter(DietProfile::effects),
Effect.CODEC.optionalFieldOf("default_effect").forGetter(DietProfile::defaultEffect)
Codec.list(FoodGroupEffects.CODEC).fieldOf("effects").forGetter(DietProfile::effects),
FoodGroupEffects.CODEC.optionalFieldOf("default_effect").forGetter(DietProfile::defaultEffect)
).apply(instance, DietProfile::new));
public DietProfile(PacketByteBuf buffer) {
this(buffer.readFloat(), buffer.readFloat(), buffer.readList(Multiplier::new), buffer.readList(Effect::new), buffer.readOptional(Effect::new));
this(buffer.readFloat(), buffer.readFloat(),
buffer.readList(Multiplier::new),
buffer.readList(b -> new FoodGroupEffects(b, FoodGroupKey.LOOKUP)),
buffer.readOptional(b -> new FoodGroupEffects(b, FoodGroupKey.LOOKUP))
);
}
public void validate(Consumer<String> issues, Predicate<Identifier> foodGroupExists) {
multipliers.stream().flatMap(i -> i.tags().stream()).forEach(key -> {
if (!foodGroupExists.test(key.id())) {
issues.accept("Multiplier referenced unknown food group: " + key.id());
}
});
effects.stream().flatMap(i -> i.tags().stream()).forEach(key -> {
if (!foodGroupExists.test(key.id())) {
issues.accept("Override defined for unknown food group: " + key.id());
}
});
defaultEffect.stream().flatMap(i -> i.tags().stream()).forEach(key -> {
if (!foodGroupExists.test(key.id())) {
issues.accept("Default override defined for unknown food group: " + key.id());
}
});
}
public void toBuffer(PacketByteBuf buffer) {
@ -61,7 +81,7 @@ public record DietProfile(
}
public Optional<Effect> findEffect(ItemStack stack) {
return effects.stream().filter(m -> m.test(stack)).findFirst().or(this::defaultEffect);
return effects.stream().filter(m -> m.test(stack)).findFirst().or(this::defaultEffect).map(Effect.class::cast);
}
static boolean isForaged(ItemStack stack) {
@ -145,11 +165,11 @@ public record DietProfile(
}
public record Multiplier(
Set<TagKey<Item>> tags,
Set<FoodGroupKey> tags,
float hunger,
float saturation
) implements Predicate<ItemStack> {
public static final Codec<Set<TagKey<Item>>> TAGS_CODEC = Codec.list(TagKey.unprefixedCodec(RegistryKeys.ITEM)).xmap(
public static final Codec<Set<FoodGroupKey>> TAGS_CODEC = FoodGroupKey.CODEC.listOf().xmap(
l -> l.stream().distinct().collect(Collectors.toSet()),
set -> new ArrayList<>(set)
);
@ -160,12 +180,12 @@ public record DietProfile(
).apply(instance, Multiplier::new));
public Multiplier(PacketByteBuf buffer) {
this(buffer.readCollection(HashSet::new, p -> TagKey.of(RegistryKeys.ITEM, p.readIdentifier())), buffer.readFloat(), buffer.readFloat());
this(buffer.readCollection(HashSet::new, p -> FoodGroupKey.LOOKUP.apply(p.readIdentifier())), buffer.readFloat(), buffer.readFloat());
}
@Override
public boolean test(ItemStack stack) {
return tags.stream().anyMatch(tag -> stack.isIn(tag));
return tags.stream().anyMatch(tag -> tag.contains(stack));
}
public void toBuffer(PacketByteBuf buffer) {
@ -173,5 +193,30 @@ public record DietProfile(
buffer.writeFloat(hunger);
buffer.writeFloat(saturation);
}
public static final class Builder {
private Set<FoodGroupKey> tags = new HashSet<>();
private float hunger = 1;
private float saturation = 1;
public Builder tag(Identifier tag) {
tags.add(FoodGroupKey.LOOKUP.apply(tag));
return this;
}
public Builder hunger(float hunger) {
this.hunger = hunger;
return this;
}
public Builder saturation(float saturation) {
this.saturation = saturation;
return this;
}
public Multiplier build() {
return new Multiplier(tags, hunger, saturation);
}
}
}
}

View file

@ -1,12 +1,9 @@
package com.minelittlepony.unicopia.diet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import org.slf4j.Logger;
import com.google.gson.JsonElement;
@ -36,9 +33,24 @@ public class DietsLoader implements IdentifiableResourceReloadListener {
Profiler prepareProfiler, Profiler applyProfiler,
Executor prepareExecutor, Executor applyExecutor) {
var dietsLoadTask = loadData(manager, prepareExecutor, "diets/races").thenApplyAsync(data -> {
CompletableFuture<Map<Identifier, Effect>> foodGroupsFuture = CompletableFuture.supplyAsync(() -> {
Map<Identifier, Effect> foodGroups = new HashMap<>();
for (var group : loadData(manager, prepareExecutor, "diet/food_groups").entrySet()) {
try {
FoodGroup.CODEC.parse(JsonOps.INSTANCE, group.getValue())
.resultOrPartial(error -> LOGGER.error("Could not load food group {}: {}", group.getKey(), error))
.ifPresent(value -> {
foodGroups.put(group.getKey(), new FoodGroup(group.getKey(), value));
});
} catch (Throwable t) {
LOGGER.error("Could not load food effects {}", group.getKey(), t);
}
}
return foodGroups;
}, prepareExecutor);
CompletableFuture<Map<Race, DietProfile>> profilesFuture = CompletableFuture.supplyAsync(() -> {
Map<Race, DietProfile> profiles = new HashMap<>();
for (var entry : data.entrySet()) {
for (var entry : loadData(manager, prepareExecutor, "diet/races").entrySet()) {
Identifier id = entry.getKey();
try {
Race.REGISTRY.getOrEmpty(id).ifPresentOrElse(race -> {
@ -53,33 +65,26 @@ public class DietsLoader implements IdentifiableResourceReloadListener {
return profiles;
}, prepareExecutor);
var effectsLoadTask = loadData(manager, prepareExecutor, "diets/food_effects").thenApplyAsync(data -> data.entrySet().stream()
.map(entry -> {
try {
return Effect.CODEC.parse(JsonOps.INSTANCE, entry.getValue())
.resultOrPartial(error -> LOGGER.error("Could not load food effect {}: {}", entry.getKey(), error));
} catch (Throwable t) {
LOGGER.error("Could not load food effects {}", entry.getKey(), t);
}
return Optional.<Effect>empty();
})
.filter(Optional::isPresent)
.map(Optional::get)
.toList(), prepareExecutor);
return CompletableFuture.allOf(dietsLoadTask, effectsLoadTask).thenCompose(sync::whenPrepared).thenRunAsync(() -> {
PonyDiets.load(new PonyDiets(
dietsLoadTask.getNow(Map.of()),
effectsLoadTask.getNow(List.of())
));
return CompletableFuture.allOf(foodGroupsFuture, profilesFuture).thenCompose(sync::whenPrepared).thenAcceptAsync(v -> {
var profiles = profilesFuture.getNow(Map.of());
var foodGroups = foodGroupsFuture.getNow(Map.of());
profiles.entrySet().removeIf(entry -> {
StringBuilder issueList = new StringBuilder();
entry.getValue().validate(issue -> {
issueList.append(System.lineSeparator()).append(issue);
}, foodGroups::containsKey);
if (!issueList.isEmpty()) {
LOGGER.error("Could not load diet profile {}. Caused by {}", entry.getKey(), issueList.toString());
}
return issueList.isEmpty();
});
PonyDiets.load(new PonyDiets(profiles, foodGroups));
}, applyExecutor);
}
private static CompletableFuture<Map<Identifier, JsonElement>> loadData(ResourceManager manager, Executor prepareExecutor, String path) {
return CompletableFuture.supplyAsync(() -> {
Map<Identifier, JsonElement> results = new HashMap<>();
JsonDataLoader.load(manager, path, Resources.GSON, results);
return results;
});
private static Map<Identifier, JsonElement> loadData(ResourceManager manager, Executor prepareExecutor, String path) {
Map<Identifier, JsonElement> results = new HashMap<>();
JsonDataLoader.load(manager, path, Resources.GSON, results);
return results;
}
}

View file

@ -4,54 +4,29 @@ import java.util.List;
import java.util.Optional;
import java.util.function.Predicate;
import com.minelittlepony.unicopia.entity.player.Pony;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.client.item.TooltipContext;
import net.minecraft.item.FoodComponent;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.network.PacketByteBuf;
import net.minecraft.registry.RegistryKeys;
import net.minecraft.registry.tag.TagKey;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
import net.minecraft.util.UseAction;
import net.minecraft.util.Util;
public record Effect(
List<TagKey<Item>> tags,
Optional<FoodComponent> foodComponent,
Ailment ailment
) implements Predicate<ItemStack> {
public static final Effect EMPTY = new Effect(List.of(), Optional.empty(), Ailment.EMPTY);
public static final Codec<Effect> CODEC = RecordCodecBuilder.create(instance -> instance.group(
TagKey.unprefixedCodec(RegistryKeys.ITEM).listOf().fieldOf("tags").forGetter(Effect::tags),
FoodAttributes.CODEC.optionalFieldOf("food_component").forGetter(Effect::foodComponent),
Ailment.CODEC.fieldOf("ailment").forGetter(Effect::ailment)
).apply(instance, Effect::new));
public interface Effect extends Predicate<ItemStack> {
Effect EMPTY = new FoodGroupEffects(List.of(), Optional.empty(), Ailment.EMPTY);
public Effect(PacketByteBuf buffer) {
this(buffer.readList(b -> TagKey.of(RegistryKeys.ITEM, b.readIdentifier())), buffer.readOptional(FoodAttributes::read), new Ailment(buffer));
}
List<FoodGroupKey> tags();
public void afflict(Pony pony, ItemStack stack) {
ailment().effects().afflict(pony.asEntity(), stack);
}
Optional<FoodComponent> foodComponent();
public void appendTooltip(ItemStack stack, List<Text> tooltip, TooltipContext context) {
int size = tooltip.size();
tags.forEach(tag -> {
if (stack.isIn(tag)) {
tooltip.add(Text.literal(" ").append(Text.translatable(Util.createTranslationKey("tag", tag.id()))).formatted(Formatting.GRAY));
}
});
if (tooltip.size() == size) {
Ailment ailment();
default void appendTooltip(ItemStack stack, List<Text> tooltip, TooltipContext context) {
if (!test(stack)) {
if (stack.isFood()) {
tooltip.add(Text.literal(" ").append(Text.translatable("tag.unicopia.food_types.misc")).formatted(Formatting.GRAY));
tooltip.add(Text.literal(" ").append(Text.translatable("food_group.unicopia.misc")).formatted(Formatting.GRAY));
} else if (stack.getUseAction() == UseAction.DRINK) {
tooltip.add(Text.literal(" ").append(Text.translatable("tag.unicopia.food_types.drinks")).formatted(Formatting.GRAY));
tooltip.add(Text.literal(" ").append(Text.translatable("food_group.unicopia.drinks")).formatted(Formatting.GRAY));
}
}
@ -63,14 +38,14 @@ public record Effect(
}
}
public void toBuffer(PacketByteBuf buffer) {
buffer.writeCollection(tags, (b, t) -> b.writeIdentifier(t.id()));
buffer.writeOptional(foodComponent, FoodAttributes::write);
ailment.toBuffer(buffer);
default void toBuffer(PacketByteBuf buffer) {
buffer.writeCollection(tags(), (b, t) -> b.writeIdentifier(t.id()));
buffer.writeOptional(foodComponent(), FoodAttributes::write);
ailment().toBuffer(buffer);
}
@Override
public boolean test(ItemStack stack) {
return tags.stream().anyMatch(stack::isIn);
default boolean test(ItemStack stack) {
return tags().stream().anyMatch(tag -> tag.contains(stack));
}
}
}

View file

@ -0,0 +1,56 @@
package com.minelittlepony.unicopia.diet;
import java.util.List;
import java.util.Optional;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.client.item.TooltipContext;
import net.minecraft.item.FoodComponent;
import net.minecraft.item.ItemStack;
import net.minecraft.network.PacketByteBuf;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
import net.minecraft.util.Identifier;
import net.minecraft.util.Util;
public record FoodGroup(
Identifier id,
FoodGroupEffects attributes) implements Effect {
public static final Codec<FoodGroupEffects> CODEC = RecordCodecBuilder.create(instance -> instance.group(
FoodGroupKey.TAG_CODEC.listOf().fieldOf("tags").forGetter(FoodGroupEffects::tags),
FoodAttributes.CODEC.optionalFieldOf("food_component").forGetter(FoodGroupEffects::foodComponent),
Ailment.CODEC.fieldOf("ailment").forGetter(FoodGroupEffects::ailment)
).apply(instance, FoodGroupEffects::new));
public FoodGroup(PacketByteBuf buffer) {
this(buffer.readIdentifier(), new FoodGroupEffects(buffer, FoodGroupKey.TAG_ID_LOOKUP));
}
@Override
public List<FoodGroupKey> tags() {
return attributes.tags();
}
@Override
public Optional<FoodComponent> foodComponent() {
return attributes.foodComponent();
}
@Override
public Ailment ailment() {
return attributes.ailment();
}
@Override
public void appendTooltip(ItemStack stack, List<Text> tooltip, TooltipContext context) {
tooltip.add(Text.literal(" ").append(Text.translatable(Util.createTranslationKey("food_group", id()))).formatted(Formatting.GRAY));
Effect.super.appendTooltip(stack, tooltip, context);
}
@Override
public void toBuffer(PacketByteBuf buffer) {
buffer.writeIdentifier(id());
Effect.super.toBuffer(buffer);
}
}

View file

@ -0,0 +1,86 @@
package com.minelittlepony.unicopia.diet;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.function.Function;
import com.minelittlepony.unicopia.diet.affliction.Affliction;
import com.minelittlepony.unicopia.item.UFoodComponents;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.client.item.TooltipContext;
import net.minecraft.item.FoodComponent;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.network.PacketByteBuf;
import net.minecraft.registry.RegistryKeys;
import net.minecraft.registry.tag.TagKey;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
import net.minecraft.util.Identifier;
import net.minecraft.util.Util;
public record FoodGroupEffects(
List<FoodGroupKey> tags,
Optional<FoodComponent> foodComponent,
Ailment ailment
) implements Effect {
public static final Codec<FoodGroupEffects> CODEC = RecordCodecBuilder.create(instance -> instance.group(
FoodGroupKey.CODEC.listOf().fieldOf("tags").forGetter(FoodGroupEffects::tags),
FoodAttributes.CODEC.optionalFieldOf("food_component").forGetter(FoodGroupEffects::foodComponent),
Ailment.CODEC.fieldOf("ailment").forGetter(FoodGroupEffects::ailment)
).apply(instance, FoodGroupEffects::new));
public FoodGroupEffects(PacketByteBuf buffer, Function<Identifier, FoodGroupKey> lookup) {
this(buffer.readList(b -> lookup.apply(b.readIdentifier())), buffer.readOptional(FoodAttributes::read), new Ailment(buffer));
}
@Override
public void appendTooltip(ItemStack stack, List<Text> tooltip, TooltipContext context) {
tags.forEach(tag -> {
if (tag.contains(stack)) {
tooltip.add(Text.literal(" ").append(Text.translatable(Util.createTranslationKey("tag", tag.id()))).formatted(Formatting.GRAY));
}
});
Effect.super.appendTooltip(stack, tooltip, context);
}
public static final class Builder {
private final List<FoodGroupKey> tags = new ArrayList<>();
private Optional<FoodComponent> foodComponent = Optional.empty();
private Ailment ailment = new Ailment(Affliction.EMPTY);
public Builder tag(Identifier tag) {
return tag(TagKey.of(RegistryKeys.ITEM, tag));
}
public Builder tag(TagKey<Item> tag) {
tags.add(FoodGroupKey.TAG_LOOKUP.apply(tag));
return this;
}
public Builder ailment(Affliction affliction) {
ailment = new Ailment(affliction);
return this;
}
public Builder food(int hunger, float saturation) {
return food(UFoodComponents.builder(hunger, saturation));
}
public Builder food(FoodComponent.Builder food) {
return food(food.build());
}
public Builder food(FoodComponent food) {
foodComponent = Optional.of(food);
return this;
}
public FoodGroupEffects build() {
return new FoodGroupEffects(tags, foodComponent, ailment);
}
}
}

View file

@ -0,0 +1,80 @@
package com.minelittlepony.unicopia.diet;
import java.util.function.Function;
import com.minelittlepony.unicopia.Debug;
import com.minelittlepony.unicopia.Unicopia;
import com.mojang.serialization.Codec;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.registry.Registries;
import net.minecraft.registry.RegistryKeys;
import net.minecraft.registry.tag.TagKey;
import net.minecraft.util.Identifier;
import net.minecraft.util.Util;
public interface FoodGroupKey {
Function<Identifier, FoodGroupKey> LOOKUP = Util.memoize(id -> {
return new FoodGroupKey() {
@Override
public Identifier id() {
return id;
}
@Override
public boolean contains(ItemStack stack) {
var group = PonyDiets.getEffect(id);
return group != null && group.test(stack);
}
@Override
public boolean equals(Object o) {
return o == this && (o instanceof FoodGroupKey k && k.id().equals(id()));
}
@Override
public int hashCode() {
return id().hashCode();
}
};
});
Function<TagKey<Item>, FoodGroupKey> TAG_LOOKUP = Util.memoize(tag -> {
return new FoodGroupKey() {
private boolean check;
@Override
public Identifier id() {
return tag.id();
}
@Override
public boolean contains(ItemStack stack) {
if (Debug.CHECK_GAME_VALUES && !check) {
check = true;
if (Registries.ITEM.getEntryList(tag).isEmpty()) {
Unicopia.LOGGER.info("Tag is empty: " + tag.id());
}
}
return stack.isIn(tag);
}
@Override
public boolean equals(Object o) {
return o == this && (o instanceof FoodGroupKey k && k.id().equals(id()));
}
@Override
public int hashCode() {
return id().hashCode();
}
};
});
Function<Identifier, FoodGroupKey> TAG_ID_LOOKUP = id -> TAG_LOOKUP.apply(TagKey.of(RegistryKeys.ITEM, id));
Codec<FoodGroupKey> CODEC = Identifier.CODEC.xmap(LOOKUP, FoodGroupKey::id);
Codec<FoodGroupKey> TAG_CODEC = TagKey.unprefixedCodec(RegistryKeys.ITEM).xmap(TAG_LOOKUP, k -> TagKey.of(RegistryKeys.ITEM, k.id()));
Identifier id();
boolean contains(ItemStack stack);
}

View file

@ -1,8 +1,11 @@
package com.minelittlepony.unicopia.diet;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Collectors;
import org.jetbrains.annotations.Nullable;
@ -18,35 +21,44 @@ import net.minecraft.network.PacketByteBuf;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
import net.minecraft.util.Hand;
import net.minecraft.util.Identifier;
import net.minecraft.util.TypedActionResult;
import net.minecraft.world.World;
public class PonyDiets implements DietView {
private final Map<Race, DietProfile> diets;
private final List<Effect> effects;
private final Map<Identifier, Effect> effects;
private static PonyDiets INSTANCE = new PonyDiets(Map.of(), List.of());
private static PonyDiets INSTANCE = new PonyDiets(Map.of(), Map.of());
public static PonyDiets getInstance() {
return INSTANCE;
}
@Nullable
static Effect getEffect(Identifier id) {
return INSTANCE.effects.get(id);
}
public static void load(PonyDiets diets) {
INSTANCE = diets;
}
PonyDiets(Map<Race, DietProfile> diets, List<Effect> effects) {
PonyDiets(Map<Race, DietProfile> diets, Map<Identifier, Effect> effects) {
this.diets = diets;
this.effects = effects;
}
public PonyDiets(PacketByteBuf buffer) {
this(buffer.readMap(b -> b.readRegistryValue(Race.REGISTRY), DietProfile::new), buffer.readList(Effect::new));
this(
buffer.readMap(b -> b.readRegistryValue(Race.REGISTRY), DietProfile::new),
buffer.readCollection(ArrayList::new, FoodGroup::new).stream().collect(Collectors.toMap(FoodGroup::id, Function.identity()))
);
}
public void toBuffer(PacketByteBuf buffer) {
buffer.writeMap(diets, (b, r) -> b.writeRegistryValue(Race.REGISTRY, r), (b, e) -> e.toBuffer(b));
buffer.writeCollection(effects, (b, e) -> e.toBuffer(b));
buffer.writeCollection(effects.values(), (b, e) -> e.toBuffer(b));
}
private DietProfile getDiet(Pony pony) {
@ -54,7 +66,7 @@ public class PonyDiets implements DietView {
}
Effect getEffects(ItemStack stack) {
return effects.stream().filter(effect -> effect.test(stack)).findFirst().orElse(Effect.EMPTY);
return effects.values().stream().filter(effect -> effect.test(stack)).findFirst().orElse(Effect.EMPTY);
}
private Effect getEffects(ItemStack stack, Pony pony) {
@ -71,7 +83,7 @@ public class PonyDiets implements DietView {
@Override
public void finishUsing(ItemStack stack, World world, LivingEntity entity) {
if (initEdibility(stack, entity)) {
Pony.of(entity).ifPresent(pony -> getEffects(stack, pony).afflict(pony, stack));
Pony.of(entity).ifPresent(pony -> getEffects(stack, pony).ailment().effects().afflict(pony.asEntity(), stack));
}
}

View file

@ -37,7 +37,7 @@ public interface Affliction {
affliction -> ((CompoundAffliction)affliction).afflictions
)).xmap(
either -> either.left().or(either::right).get(),
affliction -> affliction instanceof CompoundAffliction ? Either.left(affliction) : Either.right(affliction)
affliction -> affliction instanceof CompoundAffliction ? Either.right(affliction) : Either.left(affliction)
);
void afflict(PlayerEntity player, ItemStack stack);

View file

@ -7,7 +7,7 @@ import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.network.PacketByteBuf;
final class ClearLoveSicknessAffliction implements Affliction {
public final class ClearLoveSicknessAffliction implements Affliction {
public static final ClearLoveSicknessAffliction INSTANCE = new ClearLoveSicknessAffliction();
public static final Codec<ClearLoveSicknessAffliction> CODEC = Codec.unit(INSTANCE);
@ -21,6 +21,7 @@ final class ClearLoveSicknessAffliction implements Affliction {
player.heal(stack.isFood() ? stack.getItem().getFoodComponent().getHunger() : 1);
player.removeStatusEffect(StatusEffects.NAUSEA);
player.removeStatusEffect(UEffects.FOOD_POISONING);
player.removeStatusEffect(StatusEffects.WEAKNESS);
}
@Override

View file

@ -7,7 +7,7 @@ import net.minecraft.item.ItemStack;
import net.minecraft.network.PacketByteBuf;
import net.minecraft.text.Text;
class CompoundAffliction implements Affliction {
public class CompoundAffliction implements Affliction {
public final List<Affliction> afflictions;
private final Text name;
@ -18,6 +18,10 @@ class CompoundAffliction implements Affliction {
});
}
public static CompoundAffliction of(Affliction...afflictions) {
return new CompoundAffliction(List.of(afflictions));
}
public CompoundAffliction(PacketByteBuf buffer) {
this(buffer.readList(Affliction::read));
}

View file

@ -8,7 +8,7 @@ import net.minecraft.item.ItemStack;
import net.minecraft.network.PacketByteBuf;
import net.minecraft.text.Text;
record HealingAffliction(float health) implements Affliction {
public record HealingAffliction(float health) implements Affliction {
public static final Codec<HealingAffliction> CODEC = RecordCodecBuilder.create(instance -> instance.group(
Codec.FLOAT.fieldOf("health").forGetter(HealingAffliction::health)
).apply(instance, HealingAffliction::new));

View file

@ -7,7 +7,7 @@ import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.network.PacketByteBuf;
import net.minecraft.util.dynamic.Codecs;
record Range(int min, int max) {
public record Range(int min, int max) {
public static final Codec<Range> CODEC = Codecs.xor(
Codec.INT.xmap(value -> Range.of(value, -1), range -> range.min()),
RecordCodecBuilder.<Range>create(instance -> instance.group(
@ -20,6 +20,10 @@ record Range(int min, int max) {
return new Range(min, max);
}
public static Range of(int exact) {
return of(exact, exact);
}
public static Range of(PacketByteBuf buffer) {
return of(buffer.readInt(), buffer.readInt());
}

View file

@ -4,6 +4,7 @@ import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.entity.attribute.EntityAttributes;
import net.minecraft.entity.effect.StatusEffect;
import net.minecraft.entity.effect.StatusEffectInstance;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
@ -11,25 +12,24 @@ import net.minecraft.network.PacketByteBuf;
import net.minecraft.registry.Registries;
import net.minecraft.text.MutableText;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;
import net.minecraft.util.StringHelper;
import net.minecraft.util.math.MathHelper;
record StatusEffectAffliction(Identifier effect, Range seconds, Range amplifier, int chance) implements Affliction {
public record StatusEffectAffliction(StatusEffect effect, Range seconds, Range amplifier, int chance) implements Affliction {
public static final Codec<StatusEffectAffliction> CODEC = RecordCodecBuilder.create(instance -> instance.group(
Identifier.CODEC.fieldOf("effect").forGetter(StatusEffectAffliction::effect),
Registries.STATUS_EFFECT.getCodec().fieldOf("effect").forGetter(StatusEffectAffliction::effect),
Range.CODEC.fieldOf("seconds").forGetter(StatusEffectAffliction::seconds),
Range.CODEC.optionalFieldOf("amplifier", Range.of(0, -1)).forGetter(StatusEffectAffliction::amplifier),
Codec.INT.optionalFieldOf("chance", 0).forGetter(StatusEffectAffliction::chance)
).apply(instance, StatusEffectAffliction::new));
public StatusEffectAffliction(PacketByteBuf buffer) {
this(buffer.readIdentifier(), Range.of(buffer), Range.of(buffer), buffer.readInt());
this(Registries.STATUS_EFFECT.get(buffer.readIdentifier()), Range.of(buffer), Range.of(buffer), buffer.readInt());
}
@Override
public void toBuffer(PacketByteBuf buffer) {
buffer.writeIdentifier(effect);
buffer.writeIdentifier(Registries.STATUS_EFFECT.getId(effect));
seconds.toBuffer(buffer);
amplifier.toBuffer(buffer);
buffer.writeInt(chance);
@ -45,35 +45,31 @@ record StatusEffectAffliction(Identifier effect, Range seconds, Range amplifier,
if (chance > 0 && player.getWorld().random.nextInt(chance) > 0) {
return;
}
Registries.STATUS_EFFECT.getOrEmpty(effect).ifPresent(effect -> {
float health = player.getHealth();
StatusEffectInstance current = player.getStatusEffect(effect);
player.addStatusEffect(new StatusEffectInstance(effect,
seconds.getClamped(current == null ? 0 : current.getDuration(), 20),
amplifier.getClamped(current == null ? 0 : current.getAmplifier(), 1)
));
// keep original health
if (effect.getAttributeModifiers().containsKey(EntityAttributes.GENERIC_MAX_HEALTH)) {
player.setHealth(MathHelper.clamp(health, 0, player.getMaxHealth()));
}
});
float health = player.getHealth();
StatusEffectInstance current = player.getStatusEffect(effect);
player.addStatusEffect(new StatusEffectInstance(effect,
seconds.getClamped(current == null ? 0 : current.getDuration(), 20),
amplifier.getClamped(current == null ? 0 : current.getAmplifier(), 1)
));
// keep original health
if (effect.getAttributeModifiers().containsKey(EntityAttributes.GENERIC_MAX_HEALTH)) {
player.setHealth(MathHelper.clamp(health, 0, player.getMaxHealth()));
}
}
@Override
public Text getName() {
return Registries.STATUS_EFFECT.getOrEmpty(effect).map(effect -> {
MutableText text = effect.getName().copy();
MutableText text = effect.getName().copy();
if (amplifier.min() > 0) {
text = Text.translatable("potion.withAmplifier", text, Text.translatable("potion.potency." + (amplifier.min())));
}
if (amplifier.min() > 0) {
text = Text.translatable("potion.withAmplifier", text, Text.translatable("potion.potency." + (amplifier.min())));
}
text = Text.translatable("potion.withDuration", text, StringHelper.formatTicks(seconds.min() * 20));
text = Text.translatable("potion.withDuration", text, StringHelper.formatTicks(seconds.min() * 20));
if (chance > 0) {
text = Text.translatable("potion.withChance", chance, text);
}
return (Text)text;
}).orElse(EMPTY.getName());
if (chance > 0) {
text = Text.translatable("potion.withChance", chance, text);
}
return text;
}
}

View file

@ -111,7 +111,7 @@ public class ItemImpl implements Equine<ItemEntity> {
});
}
if (stack.isIn(UTags.FALLS_SLOWLY)) {
if (stack.isIn(UTags.Items.FALLS_SLOWLY)) {
if (!entity.isOnGround() && Math.signum(entity.getVelocity().y) != getPhysics().getGravitySignum()) {
double ticks = ((Entity)entity).age;
double shift = Math.sin(ticks / 9D) / 9D;
@ -160,7 +160,7 @@ public class ItemImpl implements Equine<ItemEntity> {
@Override
public boolean collidesWithClouds() {
return entity.getStack().isIn(UTags.FLOATS_ON_CLOUDS) || getSpecies().hasPersistentWeatherMagic();
return entity.getStack().isIn(UTags.Items.FLOATS_ON_CLOUDS) || getSpecies().hasPersistentWeatherMagic();
}
@Override

View file

@ -310,7 +310,7 @@ public abstract class Living<T extends LivingEntity> implements Equine<T>, Caste
ItemStack payload = stack.payload();
Item item = payload.getItem();
boolean deliverAggressively = payload.isIn(UTags.IS_DELIVERED_AGGRESSIVELY);
boolean deliverAggressively = payload.isIn(UTags.Items.IS_DELIVERED_AGGRESSIVELY);
Vec3d randomPos = deliverAggressively ? targetPos.add(0, 2, 0) : targetPos.add(VecHelper.supply(() -> entity.getRandom().nextTriangular(0.1, 0.5)));
@ -400,7 +400,7 @@ public abstract class Living<T extends LivingEntity> implements Equine<T>, Caste
this.attacker = attacker;
}
if (magical.isIn(UTags.BREAKS_SUNGLASSES)) {
if (magical.isIn(UTags.DamageTypes.BREAKS_SUNGLASSES)) {
ItemStack glasses = GlassesItem.getForEntity(entity);
if (glasses.getItem() == UItems.SUNGLASSES) {
ItemStack broken = UItems.BROKEN_SUNGLASSES.getDefaultStack();

View file

@ -1,18 +1,14 @@
package com.minelittlepony.unicopia.entity.damage;
import java.util.ArrayList;
import java.util.List;
import com.minelittlepony.unicopia.Unicopia;
import com.minelittlepony.unicopia.util.registry.DynamicRegistry;
import net.fabricmc.fabric.api.event.registry.DynamicRegistrySetupCallback;
import net.minecraft.entity.damage.DamageType;
import net.minecraft.registry.Registry;
import net.minecraft.registry.RegistryKey;
import net.minecraft.registry.RegistryKeys;
public interface UDamageTypes {
List<RegistryKey<DamageType>> REGISTRY = new ArrayList<>();
DynamicRegistry<DamageType> REGISTRY = new DynamicRegistry<>(RegistryKeys.DAMAGE_TYPE, key -> new DamageType(key.getValue().getNamespace() + "." + key.getValue().getPath(), 0));
RegistryKey<DamageType> EXHAUSTION = register("magical_exhaustion");
RegistryKey<DamageType> ALICORN_AMULET = register("alicorn_amulet");
@ -34,18 +30,8 @@ public interface UDamageTypes {
RegistryKey<DamageType> SPIKES = register("spikes");
private static RegistryKey<DamageType> register(String name) {
var key = RegistryKey.of(RegistryKeys.DAMAGE_TYPE, Unicopia.id(name));
REGISTRY.add(key);
return key;
return REGISTRY.register(Unicopia.id(name));
}
static void bootstrap() {
DynamicRegistrySetupCallback.EVENT.register(registries -> {
registries.getOptional(RegistryKeys.DAMAGE_TYPE).ifPresent(registry -> {
REGISTRY.forEach(key -> {
Registry.register(registry, key.getValue(), new DamageType(key.getValue().getNamespace() + "." + key.getValue().getPath(), 0));
});
});
});
}
static void bootstrap() {}
}

View file

@ -72,8 +72,8 @@ public class SunBlindnessStatusEffect extends StatusEffect {
return true;
}
if (entity.getEquippedStack(EquipmentSlot.HEAD).isIn(UTags.SHADES)
|| TrinketsDelegate.getInstance(entity).getEquipped(entity, TrinketsDelegate.FACE).anyMatch(i -> i.isIn(UTags.SHADES))
if (entity.getEquippedStack(EquipmentSlot.HEAD).isIn(UTags.Items.SHADES)
|| TrinketsDelegate.getInstance(entity).getEquipped(entity, TrinketsDelegate.FACE).anyMatch(i -> i.isIn(UTags.Items.SHADES))
|| entity.isSubmergedInWater()) {
return false;
}

View file

@ -11,6 +11,7 @@ import java.util.stream.Collectors;
import org.jetbrains.annotations.Nullable;
import com.minelittlepony.unicopia.USounds;
import com.minelittlepony.unicopia.UTags;
import com.minelittlepony.unicopia.Unicopia;
import com.minelittlepony.unicopia.item.ButterflyItem;
import com.minelittlepony.unicopia.util.NbtSerialisable;
@ -73,7 +74,7 @@ public class ButterflyEntity extends AmbientEntity {
}
public static boolean canSpawn(EntityType<? extends ButterflyEntity> type, WorldAccess world, SpawnReason spawnReason, BlockPos pos, Random random) {
return world.getBlockState(pos.down()).isIn(BlockTags.ANIMALS_SPAWNABLE_ON);
return world.getBlockState(pos.down()).isIn(UTags.Blocks.BUTTERFLIES_SPAWNABLE_ON);
}
@Override

View file

@ -373,7 +373,7 @@ public class SpellbookEntity extends MobEntity implements MagicImmune {
@Override
public boolean isInvulnerableTo(DamageSource damageSource) {
return super.isInvulnerableTo(damageSource) || damageSource.isIn(UTags.SPELLBOOK_IMMUNE_TO);
return super.isInvulnerableTo(damageSource) || damageSource.isIn(UTags.DamageTypes.SPELLBOOK_IMMUNE_TO);
}
@Override

View file

@ -35,7 +35,7 @@ public interface UTradeOffers {
factories.add(buyForEmeralds(UItems.GEMSTONE, 3, 1, 20, 1, 0.05F));
});
TradeOfferHelper.registerVillagerOffers(VillagerProfession.FARMER, 2, factories -> {
factories.add(buy(Items.EMERALD, 4, UTags.APPLE_SEEDS, 2, 20, 1, 0.05F));
factories.add(buy(Items.EMERALD, 4, UTags.Items.APPLE_SEEDS, 2, 20, 1, 0.05F));
factories.add(buy(Items.EMERALD, 8, UItems.MANGO, 1, 15, 1, 0.025F));
});
@ -47,7 +47,7 @@ public interface UTradeOffers {
factories.add(buy(ItemTags.SMALL_FLOWERS, 2, UItems.DAFFODIL_DAISY_SANDWICH, 1, 10, 6, 0.08F));
factories.add(buy(UItems.ZAP_APPLE, 45, UItems.ZAP_APPLE_JAM_JAR, 5, 50, 3, 0.07F));
factories.add(buy(UItems.CIDER, 1, UItems.FRIENDSHIP_BRACELET, 1, 6, 1, 0.05F));
factories.add(buy(UItems.GEMSTONE, 5, UTags.FRESH_APPLES, 2, 12, 3, 0.05F));
factories.add(buy(UItems.GEMSTONE, 5, UTags.Items.FRESH_APPLES, 2, 12, 3, 0.05F));
factories.add(buy(Items.EMERALD, 4, UItems.MANGO, 1, 35, 1, 0.025F));
factories.add(new JarredItemTradeOfferFactory());
});

View file

@ -194,7 +194,7 @@ public class PlayerPhysics extends EntityPhysics<PlayerEntity> implements Tickab
private FlightType recalculateFlightType() {
DimensionType dimension = entity.getWorld().getDimension();
if ((RegistryUtils.isIn(entity.getWorld(), dimension, RegistryKeys.DIMENSION_TYPE, UTags.HAS_NO_ATMOSPHERE)
if ((RegistryUtils.isIn(entity.getWorld(), dimension, RegistryKeys.DIMENSION_TYPE, UTags.DimensionTypes.HAS_NO_ATMOSPHERE)
|| Unicopia.getConfig().dimensionsWithoutAtmosphere.get().contains(RegistryUtils.getId(entity.getWorld(), dimension, RegistryKeys.DIMENSION_TYPE).toString()))
&& !OxygenUtils.API.hasOxygen(entity)) {
return FlightType.NONE;
@ -582,7 +582,7 @@ public class PlayerPhysics extends EntityPhysics<PlayerEntity> implements Tickab
if (entity.isOnGround() || !force) {
BlockState steppingState = pony.asEntity().getSteppingBlockState();
if (steppingState.isIn(UTags.KICKS_UP_DUST)) {
if (steppingState.isIn(UTags.Blocks.KICKS_UP_DUST)) {
pony.addParticle(new BlockStateParticleEffect(UParticles.DUST_CLOUD, steppingState), pony.getOrigin().toCenterPos(), Vec3d.ZERO);
} else {
Supplier<Vec3d> pos = VecHelper.sphere(pony.asWorld().getRandom(), 0.5D);

View file

@ -551,7 +551,7 @@ public class Pony extends Living<PlayerEntity> implements Copyable<Pony>, Update
}
if (getObservedSpecies() == Race.BAT && !entity.hasPortalCooldown()) {
boolean hasShades = TrinketsDelegate.getInstance(entity).getEquipped(entity, TrinketsDelegate.FACE).anyMatch(s -> s.isIn(UTags.SHADES));
boolean hasShades = TrinketsDelegate.getInstance(entity).getEquipped(entity, TrinketsDelegate.FACE).anyMatch(s -> s.isIn(UTags.Items.SHADES));
if (!this.hasShades && hasShades && getObservedSpecies() == Race.BAT) {
UCriteria.WEAR_SHADES.trigger(entity);
}
@ -754,7 +754,7 @@ public class Pony extends Living<PlayerEntity> implements Copyable<Pony>, Update
}
if (getObservedSpecies() == Race.KIRIN
&& (stack.isIn(UTags.COOLS_OFF_KIRINS) || PotionUtil.getPotion(stack) == Potions.WATER)) {
&& (stack.isIn(UTags.Items.COOLS_OFF_KIRINS) || PotionUtil.getPotion(stack) == Potions.WATER)) {
getMagicalReserves().getCharge().multiply(0.5F);
getSpellSlot().get(SpellType.RAGE, false).ifPresent(RageAbilitySpell::setExtenguishing);
}

View file

@ -4,16 +4,22 @@ import java.util.Optional;
import net.minecraft.advancement.criterion.Criteria;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemUsage;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.stat.Stats;
import net.minecraft.util.UseAction;
import net.minecraft.world.World;
public class DrinkableItem extends Item {
public DrinkableItem(Item.Settings settings) {
public class ConsumableItem extends Item {
private final UseAction action;
public ConsumableItem(Item.Settings settings, UseAction action) {
super(settings);
this.action = action;
}
@Override
@ -25,11 +31,20 @@ public class DrinkableItem extends Item {
serverPlayerEntity.incrementStat(Stats.USED.getOrCreateStat(this));
}
return stack.isEmpty() ? Optional.ofNullable(getRecipeRemainder()).map(Item::getDefaultStack).orElse(ItemStack.EMPTY) : stack;
if (stack.isEmpty()) {
return stack.isEmpty() ? Optional.ofNullable(getRecipeRemainder()).map(Item::getDefaultStack).orElse(ItemStack.EMPTY) : stack;
}
if (user instanceof PlayerEntity player) {
return Optional.ofNullable(getRecipeRemainder()).map(Item::getDefaultStack).map(remainder -> {
return ItemUsage.exchangeStack(stack, player, remainder);
}).orElse(stack);
}
return stack;
}
@Override
public UseAction getUseAction(ItemStack stack) {
return UseAction.DRINK;
return action;
}
}

View file

@ -188,7 +188,7 @@ public class CrystalHeartItem extends Item implements FloatingArtefactEntity.Art
BlockPos tip = entity.getBlockPos().offset(direction);
BlockState tipState = entity.getWorld().getBlockState(tip);
if (!tipState.isIn(UTags.CRYSTAL_HEART_ORNAMENT) || (!tipState.contains(EndRodBlock.FACING)|| tipState.get(EndRodBlock.FACING) != direction.getOpposite())) {
if (!tipState.isIn(UTags.Blocks.CRYSTAL_HEART_ORNAMENT) || (!tipState.contains(EndRodBlock.FACING)|| tipState.get(EndRodBlock.FACING) != direction.getOpposite())) {
return false;
}
@ -207,6 +207,6 @@ public class CrystalHeartItem extends Item implements FloatingArtefactEntity.Art
}
private boolean isDiamond(BlockState state) {
return state.isIn(UTags.CRYSTAL_HEART_BASE);
return state.isIn(UTags.Blocks.CRYSTAL_HEART_BASE);
}
}

View file

@ -29,7 +29,7 @@ public class PineappleItem extends Item {
});
if (world.random.nextInt(20) == 0) {
RegistryUtils.pickRandom(world, UTags.PINEAPPLE_EFFECTS, e -> !user.hasStatusEffect(e)).ifPresent(effect -> {
RegistryUtils.pickRandom(world, UTags.StatusEffects.PINEAPPLE_EFFECTS, e -> !user.hasStatusEffect(e)).ifPresent(effect -> {
user.addStatusEffect(new StatusEffectInstance(effect, 10, 1));
});
}

View file

@ -41,7 +41,7 @@ public class PolearmItem extends SwordItem {
@Override
public boolean isSuitableFor(BlockState state) {
return state.isIn(UTags.POLEARM_MINEABLE);
return state.isIn(UTags.Blocks.POLEARM_MINEABLE);
}
@Override

View file

@ -29,11 +29,8 @@ public interface UFoodComponents {
FoodComponent OATMEAL_COOKIE = FoodComponents.COOKIE; //builder(2, 0.1F).build();
FoodComponent CHOCOLATE_OATMEAL_COOKIE = builder(3, 0.4F).build();
FoodComponent SCONE = builder(2, 0.2F).build();
FoodComponent FRIED_EGG = builder(4, 0.4F).build();
@Deprecated
FoodComponent RANDOM_FOLIAGE = builder(2, 1).build();
@Deprecated
FoodComponent RANDOM_FOLIAGE_FILLING = builder(18, 1).build();
FoodComponent WORMS = builder(1, 1.5F).alwaysEdible().meat().build();
FoodComponent INSECTS = builder(1, 0).alwaysEdible().build();
@ -62,9 +59,7 @@ public interface UFoodComponents {
FoodComponent POISON_JOKE = builder(0, 0F).alwaysEdible().snack().build();
@Deprecated
FoodComponent SHELL = builder(3, 5).build();
@Deprecated
FoodComponent SHELLY = builder(6, 7).build();
static FoodComponent.Builder builder(int hunger, float saturation) {

View file

@ -12,6 +12,7 @@ import com.minelittlepony.unicopia.item.cloud.CloudBedItem;
import com.minelittlepony.unicopia.item.enchantment.UEnchantments;
import com.minelittlepony.unicopia.item.group.ItemGroupRegistry;
import com.minelittlepony.unicopia.item.group.UItemGroups;
import com.minelittlepony.unicopia.recipe.URecipes;
import com.terraformersmc.terraform.boat.api.TerraformBoatType;
import com.terraformersmc.terraform.boat.api.TerraformBoatTypeRegistry;
import com.terraformersmc.terraform.boat.api.item.TerraformBoatItemHelper;
@ -27,6 +28,7 @@ import net.fabricmc.fabric.api.registry.CompostingChanceRegistry;
import net.fabricmc.fabric.api.registry.FuelRegistry;
import net.minecraft.sound.SoundEvent;
import net.minecraft.util.Rarity;
import net.minecraft.util.UseAction;
import net.minecraft.registry.Registry;
import net.minecraft.registry.RegistryKey;
import net.minecraft.registry.Registries;
@ -109,7 +111,7 @@ public interface UItems {
Item TOM = register("tom", new BluntWeaponItem(new Item.Settings(), ImmutableMultimap.of(
EntityAttributes.GENERIC_KNOCKBACK_RESISTANCE, new EntityAttributeModifier(BluntWeaponItem.KNOCKBACK_MODIFIER_ID, "Weapon modifier", 0.9, EntityAttributeModifier.Operation.ADDITION)
)), ItemGroups.NATURAL);
Item ROCK_STEW = register("rock_stew", new StewItem(new Item.Settings().food(FoodComponents.MUSHROOM_STEW).recipeRemainder(Items.BOWL)), ItemGroups.FOOD_AND_DRINK);
Item ROCK_STEW = register("rock_stew", new StewItem(new Item.Settings().food(FoodComponents.MUSHROOM_STEW).maxCount(1).recipeRemainder(Items.BOWL)), ItemGroups.FOOD_AND_DRINK);
Item ROCK_CANDY = register("rock_candy", new Item(new Item.Settings().food(UFoodComponents.CANDY).maxCount(16)), ItemGroups.FOOD_AND_DRINK);
Item SALT_CUBE = register("salt_cube", new Item(new Item.Settings().food(UFoodComponents.SALT_CUBE)), ItemGroups.FOOD_AND_DRINK);
@ -119,17 +121,17 @@ public interface UItems {
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()), ItemGroups.TOOLS);
Item CIDER = register("cider", new DrinkableItem(new Item.Settings().food(UFoodComponents.CIDER).maxCount(16).recipeRemainder(MUG)), ItemGroups.FOOD_AND_DRINK);
Item JUICE = register("juice", new DrinkableItem(new Item.Settings().recipeRemainder(Items.GLASS_BOTTLE).maxCount(16).food(UFoodComponents.JUICE)), ItemGroups.FOOD_AND_DRINK);
Item BURNED_JUICE = register("burned_juice", new DrinkableItem(new Item.Settings().recipeRemainder(Items.GLASS_BOTTLE).maxCount(16).food(UFoodComponents.BURNED_JUICE)), ItemGroups.FOOD_AND_DRINK);
Item CIDER = register("cider", new ConsumableItem(new Item.Settings().food(UFoodComponents.CIDER).maxCount(16).recipeRemainder(MUG), UseAction.DRINK), ItemGroups.FOOD_AND_DRINK);
Item JUICE = register("juice", new ConsumableItem(new Item.Settings().recipeRemainder(Items.GLASS_BOTTLE).maxCount(16).food(UFoodComponents.JUICE), UseAction.DRINK), ItemGroups.FOOD_AND_DRINK);
Item BURNED_JUICE = register("burned_juice", new ConsumableItem(new Item.Settings().recipeRemainder(Items.GLASS_BOTTLE).maxCount(16).food(UFoodComponents.BURNED_JUICE), UseAction.DRINK), ItemGroups.FOOD_AND_DRINK);
Item APPLE_PIE = register("apple_pie", new BlockItem(UBlocks.APPLE_PIE, new Item.Settings().maxCount(1)), ItemGroups.FOOD_AND_DRINK);
Item APPLE_PIE_HOOF = register("apple_pie_hoof", new AliasedBlockItem(UBlocks.APPLE_PIE, new Item.Settings().maxCount(1)), ItemGroups.FOOD_AND_DRINK);
Item APPLE_PIE_SLICE = register("apple_pie_slice", new Item(new Item.Settings().maxCount(16).food(UFoodComponents.PIE)), ItemGroups.FOOD_AND_DRINK);
Item CANDIED_APPLE = register("candied_apple", new StagedFoodItem(new Item.Settings().food(UFoodComponents.CANDY).maxDamage(3), () -> Items.STICK), ItemGroups.FOOD_AND_DRINK);
Item LOVE_BOTTLE = register("love_bottle", new DrinkableItem(new Item.Settings().food(UFoodComponents.LOVE_BOTTLE).maxCount(1).recipeRemainder(Items.GLASS_BOTTLE)), ItemGroups.FOOD_AND_DRINK);
Item LOVE_BUCKET = register("love_bucket", new DrinkableItem(new Item.Settings().food(UFoodComponents.LOVE_BUCKET).recipeRemainder(Items.BUCKET)), ItemGroups.FOOD_AND_DRINK);
Item LOVE_MUG = register("love_mug", new DrinkableItem(new Item.Settings().food(UFoodComponents.LOVE_MUG).recipeRemainder(MUG)), ItemGroups.FOOD_AND_DRINK);
Item LOVE_BOTTLE = register("love_bottle", new ConsumableItem(new Item.Settings().food(UFoodComponents.LOVE_BOTTLE).maxCount(1).recipeRemainder(Items.GLASS_BOTTLE), UseAction.DRINK), ItemGroups.FOOD_AND_DRINK);
Item LOVE_BUCKET = register("love_bucket", new ConsumableItem(new Item.Settings().food(UFoodComponents.LOVE_BUCKET).recipeRemainder(Items.BUCKET), UseAction.DRINK), ItemGroups.FOOD_AND_DRINK);
Item LOVE_MUG = register("love_mug", new ConsumableItem(new Item.Settings().food(UFoodComponents.LOVE_MUG).recipeRemainder(MUG), UseAction.DRINK), ItemGroups.FOOD_AND_DRINK);
Item GOLDEN_FEATHER = register("golden_feather", new Item(new Item.Settings().rarity(Rarity.UNCOMMON)), ItemGroups.NATURAL);
Item GOLDEN_WING = register("golden_wing", new Item(new Item.Settings().rarity(Rarity.UNCOMMON)), ItemGroups.NATURAL);
@ -226,6 +228,16 @@ public interface UItems {
Item TURRET_SHELL = register("turret_shell", new Item(new Item.Settings()), ItemGroups.INGREDIENTS);
Item SHELLY = register("shelly", new Item(new Item.Settings()), ItemGroups.INGREDIENTS);
Item ROTTEN_COD = register("rotten_cod", new Item(new Item.Settings().food(FoodComponents.ROTTEN_FLESH)), ItemGroups.FOOD_AND_DRINK);
Item ROTTEN_SALMON = register("rotten_salmon", new Item(new Item.Settings().food(FoodComponents.ROTTEN_FLESH)), ItemGroups.FOOD_AND_DRINK);
Item ROTTEN_TROPICAL_FISH = register("rotten_tropical_fish", new Item(new Item.Settings().food(FoodComponents.ROTTEN_FLESH)), ItemGroups.FOOD_AND_DRINK);
Item ROTTEN_PUFFERFISH = register("rotten_pufferfish", new Item(new Item.Settings().food(FoodComponents.ROTTEN_FLESH)), ItemGroups.FOOD_AND_DRINK);
Item COOKED_TROPICAL_FISH = register("cooked_tropical_fish", new Item(new Item.Settings().food(FoodComponents.COOKED_COD)), ItemGroups.FOOD_AND_DRINK);
Item COOKED_PUFFERFISH = register("cooked_pufferfish", new Item(new Item.Settings().food(FoodComponents.COOKED_COD)), ItemGroups.FOOD_AND_DRINK);
Item FRIED_AXOLOTL = register("fried_axolotl", new ConsumableItem(new Item.Settings().food(FoodComponents.COOKED_CHICKEN).maxCount(1).recipeRemainder(Items.BUCKET), UseAction.EAT), ItemGroups.FOOD_AND_DRINK);
Item GREEN_FRIED_EGG = register("green_fried_egg", new Item(new Item.Settings().food(UFoodComponents.FRIED_EGG)), ItemGroups.FOOD_AND_DRINK);
Item CARAPACE = register("carapace", new Item(new Item.Settings()), ItemGroups.INGREDIENTS);
Item CLOTH_BED = register("cloth_bed", new FancyBedItem(UBlocks.CLOTH_BED, new Item.Settings().maxCount(1)), ItemGroups.FUNCTIONAL);
Item CLOUD_BED = register("cloud_bed", new CloudBedItem(UBlocks.CLOUD_BED, new Item.Settings().maxCount(1)), ItemGroups.FUNCTIONAL);
@ -272,7 +284,7 @@ public interface UItems {
FuelRegistry.INSTANCE.add(SPELLBOOK, 9000);
FuelRegistry.INSTANCE.add(MEADOWBROOKS_STAFF, 800);
FuelRegistry.INSTANCE.add(BURNED_TOAST, 1600);
FuelRegistry.INSTANCE.add(UTags.BASKETS, 1700);
FuelRegistry.INSTANCE.add(UTags.Items.BASKETS, 1700);
CompostingChanceRegistry.INSTANCE.add(GREEN_APPLE, 0.65F);
CompostingChanceRegistry.INSTANCE.add(SWEET_APPLE, 0.65F);

View file

@ -103,7 +103,7 @@ public class ZapAppleItem extends Item implements ChameleonItem, MultiItem {
public List<ItemStack> getDefaultStacks() {
return Unicopia.SIDE.getPony().map(Pony::asWorld)
.stream()
.flatMap(world -> RegistryUtils.valuesForTag(world, UConventionalTags.APPLES))
.flatMap(world -> RegistryUtils.valuesForTag(world, UConventionalTags.Items.APPLES))
.filter(a -> a != this).map(item -> {
ItemStack stack = new ItemStack(this);
stack.getOrCreateNbt().putString("appearance", Registries.ITEM.getId(item).toString());

View file

@ -21,7 +21,7 @@ public class GemFindingEnchantment extends SimpleEnchantment {
BlockPos origin = user.getOrigin();
double volume = BlockPos.findClosest(origin, radius, radius, pos -> user.asWorld().getBlockState(pos).isIn(UTags.INTERESTING))
double volume = BlockPos.findClosest(origin, radius, radius, pos -> user.asWorld().getBlockState(pos).isIn(UTags.Blocks.INTERESTING))
.map(p -> user.getOriginVector().squaredDistanceTo(p.getX(), p.getY(), p.getZ()))
.map(find -> (1 - (Math.sqrt(find) / radius)))
.orElse(-1D);

View file

@ -4,7 +4,6 @@ import java.util.*;
import java.util.function.Supplier;
import java.util.stream.Stream;
import com.minelittlepony.unicopia.UTags;
import com.minelittlepony.unicopia.Unicopia;
import net.fabricmc.fabric.api.itemgroup.v1.FabricItemGroup;
@ -57,10 +56,9 @@ public interface ItemGroupRegistry {
return key;
}
static RegistryKey<ItemGroup> createGroupFromTag(String name, Supplier<ItemStack> icon) {
TagKey<Item> key = UTags.item("groups/" + name);
static RegistryKey<ItemGroup> createGroupFromTag(String name, TagKey<Item> tag, Supplier<ItemStack> icon) {
return createDynamic(name, icon, () -> {
return Registries.ITEM.getEntryList(key)
return Registries.ITEM.getEntryList(tag)
.stream()
.flatMap(named -> named.stream())
.map(entry -> entry.value());

View file

@ -2,6 +2,7 @@ package com.minelittlepony.unicopia.item.group;
import java.util.stream.Stream;
import com.minelittlepony.unicopia.UTags;
import com.minelittlepony.unicopia.item.ChameleonItem;
import com.minelittlepony.unicopia.item.UItems;
import net.minecraft.item.*;
@ -12,13 +13,13 @@ public interface UItemGroups {
return Stream.concat(Stream.of(Items.APPLE), ItemGroupRegistry.ITEMS.stream()
.filter(item -> !(item instanceof ChameleonItem) || ((ChameleonItem)item).isFullyDisguised()));
});
RegistryKey<ItemGroup> FORAGING_ITEMS = ItemGroupRegistry.createGroupFromTag("foraging", Items.HAY_BLOCK::getDefaultStack);
RegistryKey<ItemGroup> EARTH_PONY_ITEMS = ItemGroupRegistry.createGroupFromTag("earth_pony", UItems.EARTH_BADGE::getDefaultStack);
RegistryKey<ItemGroup> UNICORN_ITEMS = ItemGroupRegistry.createGroupFromTag("unicorn", UItems.UNICORN_BADGE::getDefaultStack);
RegistryKey<ItemGroup> PEGASUS_ITEMS = ItemGroupRegistry.createGroupFromTag("pegasus", UItems.PEGASUS_BADGE::getDefaultStack);
RegistryKey<ItemGroup> BAT_PONY_ITEMS = ItemGroupRegistry.createGroupFromTag("bat_pony", UItems.BAT_BADGE::getDefaultStack);
RegistryKey<ItemGroup> SEA_PON_ITEMS = ItemGroupRegistry.createGroupFromTag("sea_pony", UItems.PEARL_NECKLACE::getDefaultStack);
RegistryKey<ItemGroup> CHANGELING_ITEMS = ItemGroupRegistry.createGroupFromTag("changeling", UItems.CHANGELING_BADGE::getDefaultStack);
RegistryKey<ItemGroup> FORAGING_ITEMS = ItemGroupRegistry.createGroupFromTag("foraging", UTags.Items.GROUP_FORAGING, Items.HAY_BLOCK::getDefaultStack);
RegistryKey<ItemGroup> EARTH_PONY_ITEMS = ItemGroupRegistry.createGroupFromTag("earth_pony", UTags.Items.GROUP_EARTH_PONY, UItems.EARTH_BADGE::getDefaultStack);
RegistryKey<ItemGroup> UNICORN_ITEMS = ItemGroupRegistry.createGroupFromTag("unicorn", UTags.Items.GROUP_UNICORN, UItems.UNICORN_BADGE::getDefaultStack);
RegistryKey<ItemGroup> PEGASUS_ITEMS = ItemGroupRegistry.createGroupFromTag("pegasus", UTags.Items.GROUP_PEGASUS, UItems.PEGASUS_BADGE::getDefaultStack);
RegistryKey<ItemGroup> BAT_PONY_ITEMS = ItemGroupRegistry.createGroupFromTag("bat_pony", UTags.Items.GROUP_BAT_PONY, UItems.BAT_BADGE::getDefaultStack);
RegistryKey<ItemGroup> SEA_PON_ITEMS = ItemGroupRegistry.createGroupFromTag("sea_pony", UTags.Items.GROUP_SEA_PONY, UItems.PEARL_NECKLACE::getDefaultStack);
RegistryKey<ItemGroup> CHANGELING_ITEMS = ItemGroupRegistry.createGroupFromTag("changeling", UTags.Items.GROUP_CHANGELING, UItems.CHANGELING_BADGE::getDefaultStack);
static void bootstrap() {
ItemGroupRegistry.bootstrap();

View file

@ -0,0 +1,16 @@
package com.minelittlepony.unicopia.mixin;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
import net.minecraft.entity.EntityType;
import net.minecraft.item.EntityBucketItem;
import net.minecraft.sound.SoundEvent;
@Mixin(EntityBucketItem.class)
public interface MixinEntityBucketItem {
@Accessor
EntityType<?> getEntityType();
@Accessor
SoundEvent getEmptyingSound();
}

View file

@ -145,7 +145,7 @@ public class PhysicsBodyProjectileEntity extends PersistentProjectileEntity impl
return;
} else {
ItemStack stack = asItemStack();
if (stack.isIn(UTags.HORSE_SHOES)) {
if (stack.isIn(UTags.Items.HORSE_SHOES)) {
if (stack.damage(1 + random.nextInt(10), random, null)) {
playSound(USounds.Vanilla.ENTITY_ITEM_BREAK, 1, 1);
} else {
@ -205,7 +205,7 @@ public class PhysicsBodyProjectileEntity extends PersistentProjectileEntity impl
boolean ownerCanModify = !getWorld().isClient && Caster.of(getOwner()).filter(pony -> pony.canModifyAt(hit.getBlockPos())).isPresent();
if (ownerCanModify && getWorld().getGameRules().getBoolean(GameRules.DO_MOB_GRIEFING)) {
if ((!isBouncy() || getWorld().random.nextInt(200) == 0) && state.isIn(UTags.FRAGILE)) {
if ((!isBouncy() || getWorld().random.nextInt(200) == 0) && state.isIn(UTags.Blocks.FRAGILE)) {
getWorld().breakBlock(hit.getBlockPos(), true);
}
}
@ -246,7 +246,7 @@ public class PhysicsBodyProjectileEntity extends PersistentProjectileEntity impl
emitGameEvent(GameEvent.STEP);
if (!isBouncy()) {
if (stack.isIn(UTags.HORSE_SHOES)) {
if (stack.isIn(UTags.Items.HORSE_SHOES)) {
if (stack.damage(1 + random.nextInt(10), random, null)) {
playSound(USounds.Vanilla.ENTITY_ITEM_BREAK, 1, 1);
discard();
@ -262,7 +262,7 @@ public class PhysicsBodyProjectileEntity extends PersistentProjectileEntity impl
@Override
protected SoundEvent getHitSound() {
if (getStack().isIn(UTags.HORSE_SHOES)) {
if (getStack().isIn(UTags.Items.HORSE_SHOES)) {
return USounds.Vanilla.ITEM_TRIDENT_HIT_GROUND;
}
return isBouncy() ? USounds.ITEM_MUFFIN_BOUNCE.value() : USounds.ITEM_ROCK_LAND;

View file

@ -1,7 +1,6 @@
package com.minelittlepony.unicopia.item.cloud;
package com.minelittlepony.unicopia.recipe;
import com.minelittlepony.unicopia.block.UBlocks;
import com.minelittlepony.unicopia.item.URecipes;
import net.minecraft.item.ItemStack;
import net.minecraft.recipe.Ingredient;

View file

@ -1,4 +1,6 @@
package com.minelittlepony.unicopia.item;
package com.minelittlepony.unicopia.recipe;
import com.minelittlepony.unicopia.item.GlowableItem;
import net.minecraft.inventory.RecipeInputInventory;
import net.minecraft.item.ItemStack;

View file

@ -1,4 +1,4 @@
package com.minelittlepony.unicopia.item;
package com.minelittlepony.unicopia.recipe;
import net.minecraft.inventory.RecipeInputInventory;
import net.minecraft.item.ItemStack;

View file

@ -1,7 +1,9 @@
package com.minelittlepony.unicopia.item;
package com.minelittlepony.unicopia.recipe;
import org.jetbrains.annotations.Nullable;
import com.minelittlepony.unicopia.item.UItems;
import net.minecraft.inventory.RecipeInputInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.recipe.RecipeSerializer;

View file

@ -1,4 +1,7 @@
package com.minelittlepony.unicopia.item;
package com.minelittlepony.unicopia.recipe;
import com.minelittlepony.unicopia.item.EmptyJarItem;
import com.minelittlepony.unicopia.item.UItems;
import net.minecraft.inventory.RecipeInputInventory;
import net.minecraft.item.ItemStack;

View file

@ -1,4 +1,4 @@
package com.minelittlepony.unicopia.item;
package com.minelittlepony.unicopia.recipe;
import java.util.HashSet;
import java.util.Set;

View file

@ -1,10 +1,9 @@
package com.minelittlepony.unicopia.item;
package com.minelittlepony.unicopia.recipe;
import java.util.List;
import com.google.gson.JsonArray;
import com.minelittlepony.unicopia.ability.magic.spell.crafting.*;
import com.minelittlepony.unicopia.item.cloud.CloudShapingRecipe;
import net.fabricmc.fabric.api.loot.v2.LootTableEvents;
import net.minecraft.loot.LootTable;

Some files were not shown because too many files have changed in this diff Show more