Added buckets, bottles, and mugs full of love + Changelings can now collect love from the crystal heart

This commit is contained in:
Sollace 2022-09-30 18:48:34 +02:00
parent 02eaf365c8
commit 3ca28335bd
17 changed files with 106 additions and 26 deletions

View file

@ -1,12 +1,11 @@
package com.minelittlepony.unicopia.item; package com.minelittlepony.unicopia.item;
import java.util.ArrayList; import java.util.*;
import java.util.List; import java.util.function.Supplier;
import com.minelittlepony.unicopia.USounds; import com.google.common.base.Suppliers;
import com.minelittlepony.unicopia.UTags; import com.minelittlepony.unicopia.*;
import com.minelittlepony.unicopia.entity.FloatingArtefactEntity; import com.minelittlepony.unicopia.entity.*;
import com.minelittlepony.unicopia.entity.UEntities;
import com.minelittlepony.unicopia.entity.FloatingArtefactEntity.State; import com.minelittlepony.unicopia.entity.FloatingArtefactEntity.State;
import com.minelittlepony.unicopia.particle.FollowingParticleEffect; import com.minelittlepony.unicopia.particle.FollowingParticleEffect;
import com.minelittlepony.unicopia.particle.ParticleUtils; import com.minelittlepony.unicopia.particle.ParticleUtils;
@ -16,17 +15,11 @@ import com.minelittlepony.unicopia.util.VecHelper;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.EndRodBlock; import net.minecraft.block.EndRodBlock;
import net.minecraft.entity.LivingEntity; import net.minecraft.entity.*;
import net.minecraft.entity.Saddleable;
import net.minecraft.entity.SpawnGroup;
import net.minecraft.entity.SpawnReason;
import net.minecraft.entity.mob.MobEntity; import net.minecraft.entity.mob.MobEntity;
import net.minecraft.entity.passive.TameableEntity; import net.minecraft.entity.passive.TameableEntity;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.Item; import net.minecraft.item.*;
import net.minecraft.item.ItemPlacementContext;
import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemUsageContext;
import net.minecraft.particle.ParticleTypes; import net.minecraft.particle.ParticleTypes;
import net.minecraft.predicate.entity.EntityPredicates; import net.minecraft.predicate.entity.EntityPredicates;
import net.minecraft.server.world.ServerWorld; import net.minecraft.server.world.ServerWorld;
@ -38,6 +31,28 @@ import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World; import net.minecraft.world.World;
public class CrystalHeartItem extends Item implements FloatingArtefactEntity.Artifact { public class CrystalHeartItem extends Item implements FloatingArtefactEntity.Artifact {
private static final Supplier<Map<Item, Item>> ITEM_MAP = Suppliers.memoize(() -> {
return Map.of(
Items.BUCKET, UItems.LOVE_BUCKET,
Items.GLASS_BOTTLE, UItems.LOVE_BOTTLE,
UItems.MUG, UItems.LOVE_MUG
);
});
private static boolean isFillable(ItemStack stack) {
return ITEM_MAP.get().containsKey(stack.getItem());
}
private static ItemStack fill(ItemStack stack) {
Item item = ITEM_MAP.get().getOrDefault(stack.getItem(), stack.getItem());
if (item == stack.getItem()) {
return stack;
}
ItemStack newStack = item.getDefaultStack();
newStack.setNbt(stack.getNbt());
newStack.setCount(stack.getCount());
return newStack;
}
public CrystalHeartItem(Settings settings) { public CrystalHeartItem(Settings settings) {
super(settings); super(settings);
@ -55,16 +70,16 @@ public class CrystalHeartItem extends Item implements FloatingArtefactEntity.Art
return ActionResult.FAIL; return ActionResult.FAIL;
} }
if (world instanceof ServerWorld) { if (world instanceof ServerWorld serverWorld) {
FloatingArtefactEntity entity = UEntities.FLOATING_ARTEFACT.create((ServerWorld)world, context.getStack().getNbt(), null, context.getPlayer(), blockPos, SpawnReason.SPAWN_EGG, false, true); FloatingArtefactEntity entity = UEntities.FLOATING_ARTEFACT.create(serverWorld, context.getStack().getNbt(), null, context.getPlayer(), blockPos, SpawnReason.SPAWN_EGG, false, true);
if (entity == null) { if (entity == null) {
return ActionResult.FAIL; return ActionResult.FAIL;
} }
entity.setStack(context.getStack().split(1)); entity.setStack(context.getStack().split(1));
((ServerWorld)world).spawnEntityAndPassengers(entity); serverWorld.spawnEntityAndPassengers(entity);
entity.playSound(USounds.ENTITY_CRYSTAL_HEART_ACTIVATE, 0.75F, 0.8F); entity.playSound(USounds.ENTITY_CRYSTAL_HEART_ACTIVATE, 0.75F, 0.8F);
} else { } else {
@ -98,6 +113,7 @@ public class CrystalHeartItem extends Item implements FloatingArtefactEntity.Art
if (entity.world.getTime() % 80 == 0 && !entity.world.isClient) { if (entity.world.getTime() % 80 == 0 && !entity.world.isClient) {
List<LivingEntity> inputs = new ArrayList<>(); List<LivingEntity> inputs = new ArrayList<>();
List<LivingEntity> outputs = new ArrayList<>(); List<LivingEntity> outputs = new ArrayList<>();
List<ItemEntity> containers = new ArrayList<>();
VecHelper.findInRange(entity, entity.world, entity.getPos(), 20, EntityPredicates.EXCEPT_CREATIVE_OR_SPECTATOR.and(e -> !e.isRemoved() && (e instanceof PlayerEntity || e instanceof MobEntity))).forEach(e -> { VecHelper.findInRange(entity, entity.world, entity.getPos(), 20, EntityPredicates.EXCEPT_CREATIVE_OR_SPECTATOR.and(e -> !e.isRemoved() && (e instanceof PlayerEntity || e instanceof MobEntity))).forEach(e -> {
LivingEntity living = (LivingEntity)e; LivingEntity living = (LivingEntity)e;
@ -112,8 +128,11 @@ public class CrystalHeartItem extends Item implements FloatingArtefactEntity.Art
inputs.add(living); inputs.add(living);
} }
}); });
VecHelper.findInRange(entity, entity.world, entity.getPos(), 20, i -> {
return i instanceof ItemEntity ie && isFillable(ie.getStack()) && PonyContainer.of(i).filter(p -> p.get().getSpecies() == Race.CHANGELING).isPresent();
}).forEach(i -> containers.add((ItemEntity)i));
int demand = outputs.size(); int demand = outputs.size() + containers.stream().mapToInt(i -> i.getStack().getCount()).sum();
int supply = inputs.size(); int supply = inputs.size();
if (demand == 0 || supply == 0) { if (demand == 0 || supply == 0) {
@ -142,6 +161,10 @@ public class CrystalHeartItem extends Item implements FloatingArtefactEntity.Art
ParticleUtils.spawnParticles(new FollowingParticleEffect(UParticles.HEALTH_DRAIN, output, 0.2F), entity, 1); ParticleUtils.spawnParticles(new FollowingParticleEffect(UParticles.HEALTH_DRAIN, output, 0.2F), entity, 1);
output.heal(gives); output.heal(gives);
}); });
containers.forEach(container -> {
ParticleUtils.spawnParticles(new FollowingParticleEffect(UParticles.HEALTH_DRAIN, container, 0.2F), entity, 1);
container.setStack(fill(container.getStack()));
});
entity.addSpin(gives > 0 ? 20 : 10, 30); entity.addSpin(gives > 0 ? 20 : 10, 30);
} }

View file

@ -25,12 +25,12 @@ public class DrinkableItem extends Item {
serverPlayerEntity.incrementStat(Stats.USED.getOrCreateStat(this)); serverPlayerEntity.incrementStat(Stats.USED.getOrCreateStat(this));
} }
((ToxicHolder)this).getToxic(stack).finishUsing(stack, world, user);
if (user instanceof PlayerEntity && !((PlayerEntity)user).getAbilities().creativeMode) { if (user instanceof PlayerEntity && !((PlayerEntity)user).getAbilities().creativeMode) {
stack.decrement(1); stack.decrement(1);
} }
((ToxicHolder)this).getToxic(stack).finishUsing(stack, world, user);
return stack.isEmpty() ? new ItemStack(getRecipeRemainder()) : stack; return stack.isEmpty() ? new ItemStack(getRecipeRemainder()) : stack;
} }

View file

@ -36,7 +36,7 @@ public interface UItemGroups {
ItemGroup UNICORN_ITEMS = forTag("unicorn", UItems.SPELLBOOK::getDefaultStack); ItemGroup UNICORN_ITEMS = forTag("unicorn", UItems.SPELLBOOK::getDefaultStack);
ItemGroup PEGASUS_ITEMS = forTag("pegasus", UItems.PEGASUS_FEATHER::getDefaultStack); ItemGroup PEGASUS_ITEMS = forTag("pegasus", UItems.PEGASUS_FEATHER::getDefaultStack);
ItemGroup BAT_PONY_ITEMS = forTag("bat_pony", UItems.SUNGLASSES::getDefaultStack); ItemGroup BAT_PONY_ITEMS = forTag("bat_pony", UItems.SUNGLASSES::getDefaultStack);
ItemGroup CHANGELING_ITEMS = forTag("changeling", Items.SCULK_SHRIEKER::getDefaultStack); ItemGroup CHANGELING_ITEMS = forTag("changeling", UItems.LOVE_BOTTLE::getDefaultStack);
static ItemGroup forTag(String name, Supplier<ItemStack> icon) { static ItemGroup forTag(String name, Supplier<ItemStack> icon) {
TagKey<Item> key = UTags.item("groups/" + name); TagKey<Item> key = UTags.item("groups/" + name);

View file

@ -86,6 +86,10 @@ public interface UItems {
Item APPLE_PIE = register("apple_pie", new BlockItem(UBlocks.APPLE_PIE, new Item.Settings().group(ItemGroup.FOOD).maxCount(1))); Item APPLE_PIE = register("apple_pie", new BlockItem(UBlocks.APPLE_PIE, new Item.Settings().group(ItemGroup.FOOD).maxCount(1)));
Item APPLE_PIE_SLICE = register("apple_pie_slice", new Item(new Item.Settings().group(ItemGroup.FOOD).maxCount(16).food(UFoodComponents.PIE))); Item APPLE_PIE_SLICE = register("apple_pie_slice", new Item(new Item.Settings().group(ItemGroup.FOOD).maxCount(16).food(UFoodComponents.PIE)));
Item LOVE_BOTTLE = register("love_bottle", new DrinkableItem(new Item.Settings().group(ItemGroup.FOOD).food(UFoodComponents.LOVE_BOTTLE).maxCount(1).recipeRemainder(Items.GLASS_BOTTLE)));
Item LOVE_BUCKET = register("love_bucket", new DrinkableItem(new Item.Settings().group(ItemGroup.FOOD).food(UFoodComponents.LOVE_BUCKET).recipeRemainder(Items.BUCKET)));
Item LOVE_MUG = register("love_mug", new DrinkableItem(new Item.Settings().group(ItemGroup.FOOD).food(UFoodComponents.LOVE_MUG).recipeRemainder(MUG)));
Item GOLDEN_FEATHER = register("golden_feather", new Item(new Item.Settings().rarity(Rarity.UNCOMMON).group(ItemGroup.MATERIALS))); Item GOLDEN_FEATHER = register("golden_feather", new Item(new Item.Settings().rarity(Rarity.UNCOMMON).group(ItemGroup.MATERIALS)));
Item GOLDEN_WING = register("golden_wing", new Item(new Item.Settings().rarity(Rarity.UNCOMMON).group(ItemGroup.MATERIALS))); Item GOLDEN_WING = register("golden_wing", new Item(new Item.Settings().rarity(Rarity.UNCOMMON).group(ItemGroup.MATERIALS)));

View file

@ -100,7 +100,9 @@ public interface Toxics {
.with(Race.BAT, Ailment.INNERT) .with(Race.BAT, Ailment.INNERT)
); );
Toxic LOVE = register("love", new Toxic.Builder(Ailment.INNERT)); Toxic LOVE = register("love", new Toxic.Builder(Ailment.INNERT)
.with(Race.CHANGELING, of(Toxicity.SAFE, Toxin.LOVE_CONSUMPTION))
);
static void bootstrap() {} static void bootstrap() {}

View file

@ -40,6 +40,14 @@ public interface Toxin extends Affliction {
player.getHungerManager().add(-food.getHunger()/2, -food.getSaturationModifier()/2); player.getHungerManager().add(-food.getHunger()/2, -food.getSaturationModifier()/2);
}).and(STRONG_NAUSEA).and(IF_NOT_PEACEFUL.then(WEAK_FOOD_POISONING.withChance(20))).and(WEAKNESS); }).and(STRONG_NAUSEA).and(IF_NOT_PEACEFUL.then(WEAK_FOOD_POISONING.withChance(20))).and(WEAKNESS);
Toxin LOVE_CONSUMPTION = of(Text.literal("love"), (player, stack) -> {
player.heal(stack.isFood() ? stack.getItem().getFoodComponent().getHunger() : 1);
player.removeStatusEffect(StatusEffects.NAUSEA);
if (player.world.random.nextInt(10) == 0) {
player.removeStatusEffect(UEffects.FOOD_POISONING);
}
});
default void appendTooltip(List<Text> tooltip) { default void appendTooltip(List<Text> tooltip) {
tooltip.add(getName()); tooltip.add(getName());
} }

View file

@ -35,6 +35,10 @@ public interface UFoodComponents {
.statusEffect(new StatusEffectInstance(StatusEffects.BAD_OMEN, 100, 0), 0.6F) .statusEffect(new StatusEffectInstance(StatusEffects.BAD_OMEN, 100, 0), 0.6F)
.build(); .build();
FoodComponent LOVE_BOTTLE = builder(2, 0.125F).alwaysEdible().snack().build();
FoodComponent LOVE_MUG = builder(4, 0.125F).snack().build();
FoodComponent LOVE_BUCKET = builder(8, 0.125F).build();
static FoodComponent.Builder builder(int hunger, float saturation) { static FoodComponent.Builder builder(int hunger, float saturation) {
return new FoodComponent.Builder() return new FoodComponent.Builder()
.hunger(hunger) .hunger(hunger)

View file

@ -33,6 +33,10 @@
"item.unicopia.zap_apple": "Zap Apple", "item.unicopia.zap_apple": "Zap Apple",
"item.unicopia.zap_bulb": "Unripened Zap Apple", "item.unicopia.zap_bulb": "Unripened Zap Apple",
"item.unicopia.love_bottle": "Bottle o' Love",
"item.unicopia.love_bucket": "Love Bucket",
"item.unicopia.love_mug": "Mug o' Love",
"item.unicopia.empty_jar": "Glass Jar", "item.unicopia.empty_jar": "Glass Jar",
"item.unicopia.filled_jar": "%s in a Jar", "item.unicopia.filled_jar": "%s in a Jar",
"item.unicopia.rain_cloud_jar": "Rain in a Jar", "item.unicopia.rain_cloud_jar": "Rain in a Jar",

View file

@ -0,0 +1,6 @@
{
"parent": "unicopia:item/mug",
"textures": {
"layer0": "unicopia:item/love_bottle"
}
}

View file

@ -0,0 +1,6 @@
{
"parent": "unicopia:item/mug",
"textures": {
"layer0": "unicopia:item/love_bucket"
}
}

View file

@ -0,0 +1,6 @@
{
"parent": "unicopia:item/mug",
"textures": {
"layer0": "unicopia:item/love_mug"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

View file

@ -0,0 +1,8 @@
{
"replace": false,
"values": [
"unicopia:love_bottle",
"unicopia:love_bucket",
"unicopia:love_mug"
]
}

View file

@ -4,6 +4,7 @@
"#unicopia:food_types/cooked_meat", "#unicopia:food_types/cooked_meat",
"#unicopia:food_types/raw_meat", "#unicopia:food_types/raw_meat",
"#unicopia:food_types/raw_insect", "#unicopia:food_types/raw_insect",
"#unicopia:food_types/rotten_meat" "#unicopia:food_types/rotten_meat",
"#unicopia:food_types/love"
] ]
} }

View file

@ -1,6 +1,14 @@
{ {
"replace": false, "replace": false,
"values": [ "values": [
"unicopia:green_apple_leaves",
"unicopia:sweet_apple_leaves",
"unicopia:sour_apple_leaves",
"unicopia:zap_leaves",
"unicopia:zap_log",
"unicopia:zap_wood",
"unicopia:stripped_zap_log",
"unicopia:stripped_zap_wood",
"minecraft:apple", "minecraft:apple",
"unicopia:green_apple", "unicopia:green_apple",
"unicopia:sweet_apple", "unicopia:sweet_apple",
@ -8,6 +16,9 @@
"unicopia:zap_apple", "unicopia:zap_apple",
"unicopia:zap_bulb", "unicopia:zap_bulb",
"unicopia:rotten_apple", "unicopia:rotten_apple",
"unicopia:green_apple_seeds",
"unicopia:sweet_apple_seeds",
"unicopia:sour_apple_seeds",
"unicopia:empty_jar", "unicopia:empty_jar",
"unicopia:cooked_zap_apple", "unicopia:cooked_zap_apple",
"unicopia:zap_apple_jam_jar", "unicopia:zap_apple_jam_jar",
@ -24,9 +35,6 @@
"unicopia:rock", "unicopia:rock",
"unicopia:weird_rock", "unicopia:weird_rock",
"unicopia:rock_stew", "unicopia:rock_stew",
"unicopia:green_apple_seeds",
"unicopia:sweet_apple_seeds",
"unicopia:sour_apple_seeds",
"unicopia:mug", "unicopia:mug",
"unicopia:cider", "unicopia:cider",
"unicopia:juice", "unicopia:juice",